LCOV - code coverage report
Current view: top level - source4/auth/gensec - gensec_gssapi.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 629 808 77.8 %
Date: 2024-05-31 13:13:24 Functions: 26 26 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Kerberos backend for GENSEC
       5             :    
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
       7             :    Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include <tevent.h>
      26             : #include "lib/util/tevent_ntstatus.h"
      27             : #include "lib/events/events.h"
      28             : #include "system/kerberos.h"
      29             : #include "system/gssapi.h"
      30             : #include "auth/kerberos/kerberos.h"
      31             : #include "librpc/gen_ndr/krb5pac.h"
      32             : #include "auth/auth.h"
      33             : #include <ldb.h>
      34             : #include "auth/auth_sam.h"
      35             : #include "librpc/gen_ndr/dcerpc.h"
      36             : #include "auth/credentials/credentials.h"
      37             : #include "auth/credentials/credentials_krb5.h"
      38             : #include "auth/gensec/gensec.h"
      39             : #include "auth/gensec/gensec_internal.h"
      40             : #include "auth/gensec/gensec_proto.h"
      41             : #include "auth/gensec/gensec_toplevel_proto.h"
      42             : #include "param/param.h"
      43             : #include "auth/session_proto.h"
      44             : #include "gensec_gssapi.h"
      45             : #include "lib/util/util_net.h"
      46             : #include "auth/kerberos/pac_utils.h"
      47             : #include "auth/kerberos/gssapi_helper.h"
      48             : #include "lib/util/smb_strtox.h"
      49             : 
      50             : #ifndef gss_mech_spnego
      51             : gss_OID_desc spnego_mech_oid_desc =
      52             :                 { 6, discard_const_p(void, "\x2b\x06\x01\x05\x05\x02") };
      53             : #define gss_mech_spnego (&spnego_mech_oid_desc)
      54             : #endif
      55             : 
      56             : _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *);
      57             : 
      58             : static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
      59             : static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
      60             : static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size);
      61             : 
      62       79400 : static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
      63             : {
      64        3221 :         OM_uint32 min_stat;
      65             : 
      66       79400 :         if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
      67          96 :                 gss_release_cred(&min_stat,
      68             :                                  &gensec_gssapi_state->delegated_cred_handle);
      69             :         }
      70             : 
      71       79400 :         if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
      72       61247 :                 gss_delete_sec_context(&min_stat,
      73             :                                        &gensec_gssapi_state->gssapi_context,
      74             :                                        GSS_C_NO_BUFFER);
      75             :         }
      76             : 
      77       79400 :         if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
      78       29938 :                 gss_release_name(&min_stat,
      79             :                                  &gensec_gssapi_state->server_name);
      80             :         }
      81       79400 :         if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
      82       31334 :                 gss_release_name(&min_stat,
      83             :                                  &gensec_gssapi_state->client_name);
      84             :         }
      85             : 
      86       79400 :         return 0;
      87             : }
      88             : 
      89       29996 : static NTSTATUS gensec_gssapi_setup_server_principal(TALLOC_CTX *mem_ctx,
      90             :                                                      const char *target_principal,
      91             :                                                      const char *service,
      92             :                                                      const char *hostname,
      93             :                                                      const char *realm,
      94             :                                                      const gss_OID mech,
      95             :                                                      char **pserver_principal,
      96             :                                                      gss_name_t *pserver_name)
      97             : {
      98       29996 :         char *server_principal = NULL;
      99        1042 :         gss_buffer_desc name_token;
     100        1042 :         gss_OID name_type;
     101       29996 :         OM_uint32 maj_stat, min_stat = 0;
     102             : 
     103       29996 :         if (target_principal != NULL) {
     104         219 :                 server_principal = talloc_strdup(mem_ctx, target_principal);
     105         219 :                 name_type = GSS_C_NULL_OID;
     106             :         } else {
     107       29777 :                 server_principal = talloc_asprintf(mem_ctx,
     108             :                                                    "%s/%s@%s",
     109             :                                                    service, hostname, realm);
     110       29777 :                 name_type = GSS_C_NT_USER_NAME;
     111             :         }
     112       29996 :         if (server_principal == NULL) {
     113           0 :                 return NT_STATUS_NO_MEMORY;
     114             :         }
     115             : 
     116       29996 :         name_token.value = (uint8_t *)server_principal;
     117       29996 :         name_token.length = strlen(server_principal);
     118             : 
     119       29996 :         maj_stat = gss_import_name(&min_stat,
     120             :                                    &name_token,
     121             :                                    name_type,
     122             :                                    pserver_name);
     123       29996 :         if (maj_stat) {
     124           0 :                 DBG_WARNING("GSS Import name of %s failed: %s\n",
     125             :                             server_principal,
     126             :                             gssapi_error_string(mem_ctx,
     127             :                                                 maj_stat,
     128             :                                                 min_stat,
     129             :                                                 mech));
     130           0 :                 TALLOC_FREE(server_principal);
     131           0 :                 return NT_STATUS_INVALID_PARAMETER;
     132             :         }
     133             : 
     134       29996 :         *pserver_principal = server_principal;
     135             : 
     136       29996 :         return NT_STATUS_OK;
     137             : }
     138             : 
     139       79420 : static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
     140             : {
     141        3226 :         struct gensec_gssapi_state *gensec_gssapi_state;
     142        3226 :         krb5_error_code ret;
     143             : #ifdef SAMBA4_USES_HEIMDAL
     144        3226 :         const char *realm;
     145             : #endif
     146             : 
     147       79420 :         gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
     148       79420 :         if (!gensec_gssapi_state) {
     149           0 :                 return NT_STATUS_NO_MEMORY;
     150             :         }
     151             : 
     152       79420 :         gensec_security->private_data = gensec_gssapi_state;
     153             : 
     154       79420 :         gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
     155             : 
     156       79420 :         if (gensec_security->channel_bindings != NULL) {
     157         196 :                 gensec_gssapi_state->_input_chan_bindings.initiator_addrtype =
     158         196 :                         gensec_security->channel_bindings->initiator_addrtype;
     159         196 :                 gensec_gssapi_state->_input_chan_bindings.initiator_address.value =
     160         196 :                         gensec_security->channel_bindings->initiator_address.data;
     161         196 :                 gensec_gssapi_state->_input_chan_bindings.initiator_address.length =
     162         196 :                         gensec_security->channel_bindings->initiator_address.length;
     163             : 
     164         196 :                 gensec_gssapi_state->_input_chan_bindings.acceptor_addrtype =
     165         196 :                         gensec_security->channel_bindings->acceptor_addrtype;
     166         196 :                 gensec_gssapi_state->_input_chan_bindings.acceptor_address.value =
     167         196 :                         gensec_security->channel_bindings->acceptor_address.data;
     168         196 :                 gensec_gssapi_state->_input_chan_bindings.acceptor_address.length =
     169         196 :                         gensec_security->channel_bindings->acceptor_address.length;
     170             : 
     171         196 :                 gensec_gssapi_state->_input_chan_bindings.application_data.value =
     172         196 :                         gensec_security->channel_bindings->application_data.data;
     173         196 :                 gensec_gssapi_state->_input_chan_bindings.application_data.length =
     174         196 :                         gensec_security->channel_bindings->application_data.length;
     175             : 
     176         196 :                 gensec_gssapi_state->input_chan_bindings =
     177         196 :                         &gensec_gssapi_state->_input_chan_bindings;
     178             :         } else {
     179       79224 :                 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
     180             :         }
     181             : 
     182       79420 :         gensec_gssapi_state->server_name = GSS_C_NO_NAME;
     183       79420 :         gensec_gssapi_state->client_name = GSS_C_NO_NAME;
     184             :         
     185       79420 :         gensec_gssapi_state->gss_want_flags = 0;
     186       79420 :         gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
     187             : 
     188       79420 :         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
     189       79420 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG;
     190             :         }
     191       79420 :         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
     192       79420 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG;
     193             :         }
     194       79420 :         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", false)) {
     195           0 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG;
     196             :         }
     197       79420 :         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
     198       79420 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG;
     199             :         }
     200       79420 :         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
     201       79420 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
     202             :         }
     203             : 
     204       79420 :         if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
     205       33413 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
     206             :         }
     207       79420 :         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
     208       24190 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
     209             :         }
     210       79420 :         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
     211       22770 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
     212       22770 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG;
     213             :         }
     214       79420 :         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
     215        8343 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE;
     216             :         }
     217             : 
     218       79420 :         gensec_gssapi_state->gss_got_flags = 0;
     219             : 
     220       79420 :         switch (gensec_security->ops->auth_type) {
     221           0 :         case DCERPC_AUTH_TYPE_SPNEGO:
     222           0 :                 gensec_gssapi_state->gss_oid = gss_mech_spnego;
     223           0 :                 break;
     224       79420 :         case DCERPC_AUTH_TYPE_KRB5:
     225             :         default:
     226       79420 :                 gensec_gssapi_state->gss_oid =
     227             :                         discard_const_p(void, gss_mech_krb5);
     228       79420 :                 break;
     229             :         }
     230             : 
     231       82646 :         ret = smb_krb5_init_context(gensec_gssapi_state,
     232       79420 :                                     gensec_security->settings->lp_ctx,
     233             :                                     &gensec_gssapi_state->smb_krb5_context);
     234       79420 :         if (ret) {
     235           0 :                 DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n",
     236             :                          error_message(ret)));
     237           0 :                 talloc_free(gensec_gssapi_state);
     238           0 :                 return NT_STATUS_INTERNAL_ERROR;
     239             :         }
     240             : 
     241       79420 :         gensec_gssapi_state->client_cred = NULL;
     242       79420 :         gensec_gssapi_state->server_cred = NULL;
     243             : 
     244       79420 :         gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
     245             : 
     246       79420 :         gensec_gssapi_state->sasl = false;
     247       79420 :         gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
     248       79420 :         gensec_gssapi_state->sasl_protection = 0;
     249             : 
     250        3226 :         gensec_gssapi_state->max_wrap_buf_size
     251       79420 :                 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
     252       79420 :         gensec_gssapi_state->gss_exchange_count = 0;
     253       79420 :         gensec_gssapi_state->sig_size = 0;
     254             : 
     255       79420 :         talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
     256             : 
     257             : #ifdef SAMBA4_USES_HEIMDAL
     258       58886 :         realm = lpcfg_realm(gensec_security->settings->lp_ctx);
     259       58886 :         if (realm != NULL) {
     260       58886 :                 ret = gsskrb5_set_default_realm(realm);
     261       58886 :                 if (ret) {
     262           0 :                         DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n"));
     263           0 :                         talloc_free(gensec_gssapi_state);
     264           0 :                         return NT_STATUS_INTERNAL_ERROR;
     265             :                 }
     266             :         }
     267             : 
     268             :         /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
     269       58886 :         ret = gsskrb5_set_dns_canonicalize(false);
     270       58886 :         if (ret) {
     271           0 :                 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n"));
     272           0 :                 talloc_free(gensec_gssapi_state);
     273           0 :                 return NT_STATUS_INTERNAL_ERROR;
     274             :         }
     275             : #endif
     276       79420 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279       48017 : static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
     280             : {
     281        2184 :         NTSTATUS nt_status;
     282        2184 :         int ret;
     283        2184 :         struct gensec_gssapi_state *gensec_gssapi_state;
     284        2184 :         struct cli_credentials *machine_account;
     285        2184 :         struct gssapi_creds_container *gcc;
     286             : 
     287       48017 :         nt_status = gensec_gssapi_start(gensec_security);
     288       48017 :         if (!NT_STATUS_IS_OK(nt_status)) {
     289           0 :                 return nt_status;
     290             :         }
     291             : 
     292       48017 :         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     293             : 
     294       48017 :         machine_account = gensec_get_credentials(gensec_security);
     295             :         
     296       48017 :         if (!machine_account) {
     297           0 :                 DEBUG(3, ("No machine account credentials specified\n"));
     298           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     299             :         } else {
     300       50201 :                 ret = cli_credentials_get_server_gss_creds(machine_account, 
     301       48017 :                                                            gensec_security->settings->lp_ctx, &gcc);
     302       48017 :                 if (ret) {
     303           0 :                         DEBUG(1, ("Acquiring acceptor credentials failed: %s\n",
     304             :                                   error_message(ret)));
     305           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     306             :                 }
     307             :         }
     308             : 
     309       48017 :         gensec_gssapi_state->server_cred = gcc;
     310       48017 :         return NT_STATUS_OK;
     311             : 
     312             : }
     313             : 
     314         121 : static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
     315             : {
     316           0 :         NTSTATUS nt_status;
     317           0 :         struct gensec_gssapi_state *gensec_gssapi_state;
     318         121 :         nt_status = gensec_gssapi_server_start(gensec_security);
     319             : 
     320         121 :         if (NT_STATUS_IS_OK(nt_status)) {
     321         121 :                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     322         121 :                 gensec_gssapi_state->sasl = true;
     323             :         }
     324         121 :         return nt_status;
     325             : }
     326             : 
     327       60393 : static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security,
     328             :                                            struct tevent_context *ev)
     329             : {
     330        1929 :         struct gensec_gssapi_state *gensec_gssapi_state;
     331        1929 :         struct gssapi_creds_container *gcc;
     332       60393 :         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
     333        1929 :         const char *error_string;
     334        1929 :         int ret;
     335             : 
     336       60393 :         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     337             : 
     338             :         /* Only run this the first time the update() call is made */
     339       60393 :         if (gensec_gssapi_state->client_cred) {
     340       28990 :                 return NT_STATUS_OK;
     341             :         }
     342             : 
     343       32445 :         ret = cli_credentials_get_client_gss_creds(creds,
     344             :                                                    ev,
     345       31403 :                                                    gensec_security->settings->lp_ctx, &gcc, &error_string);
     346       31403 :         switch (ret) {
     347       28948 :         case 0:
     348       29990 :                 break;
     349           0 :         case EINVAL:
     350           0 :                 DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
     351        1413 :                 return NT_STATUS_INVALID_PARAMETER;
     352         173 :         case KRB5KDC_ERR_PREAUTH_FAILED:
     353             :         case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
     354             :         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
     355         173 :                 DEBUG(1, ("Wrong username or password: %s\n", error_string));
     356         173 :                 return NT_STATUS_LOGON_FAILURE;
     357          23 :         case KRB5KDC_ERR_CLIENT_REVOKED:
     358          23 :                 DEBUG(1, ("Account locked out: %s\n", error_string));
     359          23 :                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
     360        1214 :         case KRB5_REALM_UNKNOWN:
     361             :         case KRB5_KDC_UNREACH:
     362        1214 :                 DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
     363        1214 :                 return NT_STATUS_NO_LOGON_SERVERS;
     364           0 :         case KRB5_CC_NOTFOUND:
     365             :         case KRB5_CC_END:
     366           0 :                 DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string));
     367           0 :                 return NT_STATUS_TIME_DIFFERENCE_AT_DC;
     368           3 :         default:
     369           3 :                 DEBUG(1, ("Acquiring initiator credentials failed: %s\n", error_string));
     370           3 :                 return NT_STATUS_UNSUCCESSFUL;
     371             :         }
     372             : 
     373       29990 :         gensec_gssapi_state->client_cred = gcc;
     374       29990 :         if (!talloc_reference(gensec_gssapi_state, gcc)) {
     375           0 :                 return NT_STATUS_NO_MEMORY;
     376             :         }
     377             : 
     378       29990 :         return NT_STATUS_OK;
     379             : }
     380             : 
     381       41089 : static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
     382             : {
     383        1048 :         struct gensec_gssapi_state *gensec_gssapi_state;
     384       41089 :         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
     385        1048 :         NTSTATUS nt_status;
     386             : 
     387       41089 :         nt_status = gensec_kerberos_possible(gensec_security);
     388       41089 :         if (!NT_STATUS_IS_OK(nt_status)) {
     389        9686 :                 char *target_name = NULL;
     390        9686 :                 char *cred_name = NULL;
     391             : 
     392        9686 :                 target_name = gensec_get_unparsed_target_principal(gensec_security,
     393             :                                                                    gensec_security);
     394        9686 :                 cred_name = cli_credentials_get_unparsed_name(creds,
     395             :                                                               gensec_security);
     396             : 
     397        9686 :                 DBG_NOTICE("Not using kerberos to %s as %s: %s\n",
     398             :                            target_name, cred_name, nt_errstr(nt_status));
     399             : 
     400        9686 :                 TALLOC_FREE(target_name);
     401        9686 :                 TALLOC_FREE(cred_name);
     402        9686 :                 return nt_status;
     403             :         }
     404             : 
     405       31403 :         nt_status = gensec_gssapi_start(gensec_security);
     406       31403 :         if (!NT_STATUS_IS_OK(nt_status)) {
     407           0 :                 return nt_status;
     408             :         }
     409             : 
     410       31403 :         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     411             : 
     412             : #ifdef HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG
     413             :         /*
     414             :          * We can only use GSS_C_CHANNEL_BOUND_FLAG if the kerberos library
     415             :          * supports that in order to add KERB_AP_OPTIONS_CBT.
     416             :          *
     417             :          * See:
     418             :          * https://github.com/heimdal/heimdal/pull/1234
     419             :          * https://github.com/krb5/krb5/pull/1329
     420             :          */
     421       23639 :         if (!(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL)) {
     422       23607 :                 gensec_gssapi_state->gss_want_flags |= GSS_C_CHANNEL_BOUND_FLAG;
     423             :         }
     424             : #endif
     425             : 
     426       31403 :         if (cli_credentials_get_impersonate_principal(creds)) {
     427          45 :                 gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
     428             :         }
     429             : 
     430       31403 :         return NT_STATUS_OK;
     431             : }
     432             : 
     433         139 : static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
     434             : {
     435           0 :         NTSTATUS nt_status;
     436           0 :         struct gensec_gssapi_state *gensec_gssapi_state;
     437         139 :         nt_status = gensec_gssapi_client_start(gensec_security);
     438             : 
     439         139 :         if (NT_STATUS_IS_OK(nt_status)) {
     440         139 :                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     441         139 :                 gensec_gssapi_state->sasl = true;
     442             :         }
     443         139 :         return nt_status;
     444             : }
     445             : 
     446       96216 : static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_security,
     447             :                                               TALLOC_CTX *out_mem_ctx,
     448             :                                               struct tevent_context *ev,
     449             :                                               const DATA_BLOB in, DATA_BLOB *out)
     450             : {
     451        2913 :         struct gensec_gssapi_state *gensec_gssapi_state
     452       96216 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
     453        2913 :         NTSTATUS nt_status;
     454        2913 :         OM_uint32 maj_stat, min_stat;
     455        2913 :         OM_uint32 min_stat2;
     456       96216 :         gss_buffer_desc input_token = { 0, NULL };
     457       96216 :         gss_buffer_desc output_token = { 0, NULL };
     458       96216 :         struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security);
     459       96216 :         const char *target_principal = gensec_get_target_principal(gensec_security);
     460       96216 :         const char *hostname = gensec_get_target_hostname(gensec_security);
     461       96216 :         const char *service = gensec_get_target_service(gensec_security);
     462       96216 :         gss_OID gss_oid_p = NULL;
     463       96216 :         OM_uint32 time_req = 0;
     464       96216 :         OM_uint32 time_rec = 0;
     465        2913 :         struct timeval tv;
     466             : 
     467       96216 :         time_req = gensec_setting_int(gensec_security->settings,
     468             :                                       "gensec_gssapi", "requested_life_time",
     469             :                                       time_req);
     470             : 
     471       96216 :         input_token.length = in.length;
     472       96216 :         input_token.value = in.data;
     473             : 
     474       96216 :         switch (gensec_gssapi_state->sasl_state) {
     475       95871 :         case STAGE_GSS_NEG:
     476             :         {
     477       95871 :                 switch (gensec_security->gensec_role) {
     478       60393 :                 case GENSEC_CLIENT:
     479             :                 {
     480       60393 :                         const char *client_realm = NULL;
     481             : #ifdef SAMBA4_USES_HEIMDAL
     482        1929 :                         struct gsskrb5_send_to_kdc send_to_kdc;
     483        1929 :                         krb5_error_code ret;
     484             : #else
     485       14898 :                         bool fallback = false;
     486             : #endif
     487             : 
     488       60393 :                         nt_status = gensec_gssapi_client_creds(gensec_security, ev);
     489       60393 :                         if (!NT_STATUS_IS_OK(nt_status)) {
     490        1413 :                                 return nt_status;
     491             :                         }
     492             : 
     493             : #ifdef SAMBA4_USES_HEIMDAL
     494       44331 :                         send_to_kdc.func = smb_krb5_send_and_recv_func;
     495       44331 :                         send_to_kdc.ptr = ev;
     496             : 
     497       44331 :                         min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
     498       44331 :                         if (min_stat) {
     499           0 :                                 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
     500           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     501             :                         }
     502             : #endif
     503             : 
     504             :                         /*
     505             :                          * With credentials for
     506             :                          * administrator@FOREST1.EXAMPLE.COM this patch changes
     507             :                          * the target_principal for the ldap service of host
     508             :                          * dc2.forest2.example.com from
     509             :                          *
     510             :                          *   ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
     511             :                          *
     512             :                          * to
     513             :                          *
     514             :                          *   ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM
     515             :                          *
     516             :                          * Typically
     517             :                          * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
     518             :                          * should be used in order to allow the KDC of
     519             :                          * FOREST1.EXAMPLE.COM to generate a referral ticket
     520             :                          * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM.
     521             :                          *
     522             :                          * The problem is that KDCs only return such referral
     523             :                          * tickets if there's a forest trust between
     524             :                          * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If
     525             :                          * there's only an external domain trust between
     526             :                          * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC
     527             :                          * of FOREST1.EXAMPLE.COM will respond with
     528             :                          * S_PRINCIPAL_UNKNOWN when being asked for
     529             :                          * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM.
     530             :                          *
     531             :                          * In the case of an external trust the client can
     532             :                          * still ask explicitly for
     533             :                          * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and
     534             :                          * the KDC of FOREST1.EXAMPLE.COM will generate it.
     535             :                          *
     536             :                          * From there the client can use the
     537             :                          * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM
     538             :                          * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a
     539             :                          * service ticket for
     540             :                          * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM.
     541             :                          *
     542             :                          * With Heimdal we'll get the fallback on
     543             :                          * S_PRINCIPAL_UNKNOWN behavior when we pass
     544             :                          * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as
     545             :                          * target principal. As _krb5_get_cred_kdc_any() first
     546             :                          * calls get_cred_kdc_referral() (which always starts
     547             :                          * with the client realm) and falls back to
     548             :                          * get_cred_kdc_capath() (which starts with the given
     549             :                          * realm).
     550             :                          *
     551             :                          * MIT krb5 only tries the given realm of the target
     552             :                          * principal, if we want to autodetect support for
     553             :                          * transitive forest trusts, would have to do the
     554             :                          * fallback ourself.
     555             :                          */
     556       58980 :                         client_realm = cli_credentials_get_realm(cli_creds);
     557             : #ifndef SAMBA4_USES_HEIMDAL
     558       14649 :                         if (gensec_gssapi_state->server_name == NULL) {
     559        7499 :                                 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
     560             :                                                                                  target_principal,
     561             :                                                                                  service,
     562             :                                                                                  hostname,
     563             :                                                                                  client_realm,
     564             :                                                                                  gensec_gssapi_state->gss_oid,
     565             :                                                                                  &gensec_gssapi_state->target_principal,
     566             :                                                                                  &gensec_gssapi_state->server_name);
     567        7499 :                                 if (!NT_STATUS_IS_OK(nt_status)) {
     568           0 :                                         return nt_status;
     569             :                                 }
     570             : 
     571        7499 :                                 maj_stat = gss_init_sec_context(&min_stat,
     572        7499 :                                                                 gensec_gssapi_state->client_cred->creds,
     573             :                                                                 &gensec_gssapi_state->gssapi_context,
     574             :                                                                 gensec_gssapi_state->server_name,
     575             :                                                                 gensec_gssapi_state->gss_oid,
     576             :                                                                 gensec_gssapi_state->gss_want_flags,
     577             :                                                                 time_req,
     578             :                                                                 gensec_gssapi_state->input_chan_bindings,
     579             :                                                                 &input_token,
     580             :                                                                 &gss_oid_p,
     581             :                                                                 &output_token,
     582             :                                                                 &gensec_gssapi_state->gss_got_flags, /* ret flags */
     583             :                                                                 &time_rec);
     584        7499 :                                 if (maj_stat != GSS_S_FAILURE) {
     585        7492 :                                         goto init_sec_context_done;
     586             :                                 }
     587           7 :                                 if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
     588           0 :                                         goto init_sec_context_done;
     589             :                                 }
     590           7 :                                 if (target_principal != NULL) {
     591           0 :                                         goto init_sec_context_done;
     592             :                                 }
     593             : 
     594           7 :                                 fallback = true;
     595           7 :                                 TALLOC_FREE(gensec_gssapi_state->target_principal);
     596           7 :                                 gss_release_name(&min_stat2, &gensec_gssapi_state->server_name);
     597             :                         }
     598             : #endif /* !SAMBA4_USES_HEIMDAL */
     599       51488 :                         if (gensec_gssapi_state->server_name == NULL) {
     600       22498 :                                 const char *server_realm = NULL;
     601             : 
     602       22498 :                                 server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state,
     603             :                                                                                 hostname,
     604             :                                                                                 client_realm);
     605       22498 :                                 if (server_realm == NULL) {
     606           0 :                                         return NT_STATUS_NO_MEMORY;
     607             :                                 }
     608             : 
     609             : #ifndef SAMBA4_USES_HEIMDAL
     610          14 :                                 if (fallback &&
     611           7 :                                     strequal(client_realm, server_realm)) {
     612           1 :                                         goto init_sec_context_done;
     613             :                                 }
     614             : #endif /* !SAMBA4_USES_HEIMDAL */
     615             : 
     616       22497 :                                 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
     617             :                                                                                  target_principal,
     618             :                                                                                  service,
     619             :                                                                                  hostname,
     620             :                                                                                  server_realm,
     621             :                                                                                  gensec_gssapi_state->gss_oid,
     622             :                                                                                  &gensec_gssapi_state->target_principal,
     623             :                                                                                  &gensec_gssapi_state->server_name);
     624       22497 :                                 if (!NT_STATUS_IS_OK(nt_status)) {
     625           0 :                                         return nt_status;
     626             :                                 }
     627             :                         }
     628             : 
     629       53416 :                         maj_stat = gss_init_sec_context(&min_stat, 
     630       51487 :                                                         gensec_gssapi_state->client_cred->creds,
     631             :                                                         &gensec_gssapi_state->gssapi_context, 
     632       44331 :                                                         gensec_gssapi_state->server_name, 
     633             :                                                         gensec_gssapi_state->gss_oid,
     634             :                                                         gensec_gssapi_state->gss_want_flags, 
     635             :                                                         time_req,
     636             :                                                         gensec_gssapi_state->input_chan_bindings,
     637             :                                                         &input_token, 
     638             :                                                         &gss_oid_p,
     639             :                                                         &output_token, 
     640             :                                                         &gensec_gssapi_state->gss_got_flags, /* ret flags */
     641             :                                                         &time_rec);
     642       51487 :                         goto init_sec_context_done;
     643             :                         /* JUMP! */
     644       58980 : init_sec_context_done:
     645       58980 :                         if (gss_oid_p) {
     646       58977 :                                 gensec_gssapi_state->gss_oid = gss_oid_p;
     647             :                         }
     648             : 
     649             : #ifdef SAMBA4_USES_HEIMDAL
     650       44331 :                         send_to_kdc.func = smb_krb5_send_and_recv_func;
     651       44331 :                         send_to_kdc.ptr = NULL;
     652             : 
     653       44331 :                         ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
     654       44331 :                         if (ret) {
     655           0 :                                 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
     656           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     657             :                         }
     658             : #endif
     659       58980 :                         break;
     660             :                 }
     661       35478 :                 case GENSEC_SERVER:
     662             :                 {
     663       36462 :                         maj_stat = gss_accept_sec_context(&min_stat, 
     664             :                                                           &gensec_gssapi_state->gssapi_context, 
     665       35478 :                                                           gensec_gssapi_state->server_cred->creds,
     666             :                                                           &input_token, 
     667             :                                                           gensec_gssapi_state->input_chan_bindings,
     668             :                                                           &gensec_gssapi_state->client_name, 
     669             :                                                           &gss_oid_p,
     670             :                                                           &output_token, 
     671             :                                                           &gensec_gssapi_state->gss_got_flags, 
     672             :                                                           &time_rec,
     673             :                                                           &gensec_gssapi_state->delegated_cred_handle);
     674       35478 :                         if (gss_oid_p) {
     675       34885 :                                 gensec_gssapi_state->gss_oid = gss_oid_p;
     676             :                         }
     677             : #ifdef GSS_C_CHANNEL_BOUND_FLAG
     678       35478 :                         if (maj_stat == GSS_S_COMPLETE &&
     679       31303 :                             gensec_security->channel_bindings != NULL &&
     680          69 :                             !(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL) &&
     681          36 :                             !(gensec_gssapi_state->gss_got_flags & GSS_C_CHANNEL_BOUND_FLAG))
     682             :                         {
     683             :                                 /*
     684             :                                  * If we require valid channel bindings
     685             :                                  * we need to check the client provided
     686             :                                  * them.
     687             :                                  *
     688             :                                  * We detect this if
     689             :                                  * GSS_C_CHANNEL_BOUND_FLAG is given.
     690             :                                  *
     691             :                                  * Recent heimdal and MIT releases support this
     692             :                                  * with older releases (e.g. MIT > 1.19).
     693             :                                  *
     694             :                                  * It means client with zero channel bindings
     695             :                                  * on a server with non-zero channel bindings
     696             :                                  * won't generate GSS_S_BAD_BINDINGS directly
     697             :                                  * unless KERB_AP_OPTIONS_CBT was also
     698             :                                  * provides by the client.
     699             :                                  *
     700             :                                  * So we need to convert a missing
     701             :                                  * GSS_C_CHANNEL_BOUND_FLAG into
     702             :                                  * GSS_S_BAD_BINDINGS by default
     703             :                                  * (unless GENSEC_FEATURE_CB_OPTIONAL is given).
     704             :                                  */
     705          12 :                                 maj_stat = GSS_S_BAD_BINDINGS;
     706          12 :                                 min_stat = 0;
     707             :                         }
     708             : #endif /* GSS_C_CHANNEL_BOUND_FLAG */
     709             : 
     710       34494 :                         break;
     711             :                 }
     712           0 :                 default:
     713           0 :                         return NT_STATUS_INVALID_PARAMETER;
     714             :                         
     715             :                 }
     716             : 
     717       94458 :                 gensec_gssapi_state->gss_exchange_count++;
     718             : 
     719       94458 :                 if (maj_stat == GSS_S_COMPLETE) {
     720       60281 :                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
     721       60281 :                         gss_release_buffer(&min_stat2, &output_token);
     722             :                         
     723       60281 :                         if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
     724       58089 :                             gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
     725       29945 :                                 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
     726             :                         } else {
     727       30336 :                                 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
     728             :                         }
     729             : 
     730       60281 :                         tv = timeval_current_ofs(time_rec, 0);
     731       60281 :                         gensec_gssapi_state->expire_time = timeval_to_nttime(&tv);
     732             : 
     733             :                         /* We may have been invoked as SASL, so there
     734             :                          * is more work to do */
     735       60281 :                         if (gensec_gssapi_state->sasl) {
     736         230 :                                 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
     737         230 :                                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
     738             :                         } else {
     739       60051 :                                 gensec_gssapi_state->sasl_state = STAGE_DONE;
     740             : 
     741       60051 :                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
     742       40183 :                                         DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
     743       19868 :                                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
     744       19514 :                                         DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
     745             :                                 } else {
     746         354 :                                         DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
     747             :                                 }
     748             : 
     749       60051 :                                 return NT_STATUS_OK;
     750             :                         }
     751       34177 :                 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
     752       34084 :                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
     753       34084 :                         gss_release_buffer(&min_stat2, &output_token);
     754             :                         
     755       34084 :                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
     756          93 :                 } else if (maj_stat == GSS_S_BAD_BINDINGS) {
     757          64 :                         DBG_WARNING("Got GSS_S_BAD_BINDINGS\n");
     758          64 :                         return NT_STATUS_BAD_BINDINGS;
     759          29 :                 } else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
     760           0 :                         gss_cred_id_t creds = NULL;
     761           0 :                         gss_name_t name;
     762           0 :                         gss_buffer_desc buffer;
     763           0 :                         OM_uint32 lifetime = 0;
     764           0 :                         gss_cred_usage_t usage;
     765           0 :                         const char *role = NULL;
     766             : 
     767           0 :                         switch (gensec_security->gensec_role) {
     768           0 :                         case GENSEC_CLIENT:
     769           0 :                                 creds = gensec_gssapi_state->client_cred->creds;
     770           0 :                                 role = "client";
     771           0 :                                 break;
     772           0 :                         case GENSEC_SERVER:
     773           0 :                                 creds = gensec_gssapi_state->server_cred->creds;
     774           0 :                                 role = "server";
     775           0 :                                 break;
     776             :                         }
     777             : 
     778           0 :                         DBG_ERR("GSS %s Update(krb5)(%d) failed, credentials "
     779             :                                 "expired during GSSAPI handshake!\n",
     780             :                                 role,
     781             :                                 gensec_gssapi_state->gss_exchange_count);
     782             : 
     783           0 :                         maj_stat = gss_inquire_cred(&min_stat, 
     784             :                                                     creds,
     785             :                                                     &name, &lifetime, &usage, NULL);
     786             : 
     787           0 :                         if (maj_stat == GSS_S_COMPLETE) {
     788           0 :                                 const char *usage_string = NULL;
     789           0 :                                 switch (usage) {
     790           0 :                                 case GSS_C_BOTH:
     791           0 :                                         usage_string = "GSS_C_BOTH";
     792           0 :                                         break;
     793           0 :                                 case GSS_C_ACCEPT:
     794           0 :                                         usage_string = "GSS_C_ACCEPT";
     795           0 :                                         break;
     796           0 :                                 case GSS_C_INITIATE:
     797           0 :                                         usage_string = "GSS_C_INITIATE";
     798           0 :                                         break;
     799             :                                 }
     800           0 :                                 maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
     801           0 :                                 if (maj_stat) {
     802           0 :                                         buffer.value = NULL;
     803           0 :                                         buffer.length = 0;
     804             :                                 }
     805           0 :                                 if (lifetime > 0) {
     806           0 :                                         DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n", 
     807             :                                                   (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
     808             :                                                   lifetime, usage_string));
     809             :                                 } else {
     810           0 :                                         DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n", 
     811             :                                                   (int)buffer.length, (int)buffer.length, (char *)buffer.value, 
     812             :                                                   usage_string));
     813             :                                 }
     814           0 :                                 gss_release_buffer(&min_stat, &buffer);
     815           0 :                                 gss_release_name(&min_stat, &name);
     816           0 :                         } else if (maj_stat != GSS_S_COMPLETE) {
     817           0 :                                 DEBUG(0, ("inquiry of credential lifetime via GSSAPI gss_inquire_cred failed: %s\n",
     818             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     819             :                         }
     820           0 :                         return NT_STATUS_INVALID_PARAMETER;
     821          29 :                 } else if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
     822             :                                              gss_mech_krb5)) {
     823          29 :                         switch (min_stat) {
     824           0 :                         case (OM_uint32)KRB5KRB_AP_ERR_TKT_NYV:
     825           0 :                                 DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
     826             :                                           gensec_gssapi_state->target_principal,
     827             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     828           0 :                                 return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
     829           0 :                         case (OM_uint32)KRB5KRB_AP_ERR_TKT_EXPIRED:
     830           0 :                                 DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
     831             :                                           gensec_gssapi_state->target_principal,
     832             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     833           0 :                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
     834           0 :                         case (OM_uint32)KRB5_KDC_UNREACH:
     835           0 :                                 DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticket to %s: %s\n",
     836             :                                           gensec_gssapi_state->target_principal,
     837             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     838           0 :                                 return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
     839          12 :                         case (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
     840          12 :                                 DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
     841             :                                           gensec_gssapi_state->target_principal,
     842             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     843          12 :                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
     844           0 :                         case (OM_uint32)KRB5KRB_AP_ERR_MSG_TYPE:
     845             :                                 /* garbage input, possibly from the auto-mech detection */
     846           0 :                                 return NT_STATUS_INVALID_PARAMETER;
     847          17 :                         default:
     848          17 :                                 DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
     849             :                                           gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
     850             :                                           gensec_gssapi_state->gss_exchange_count,
     851             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     852          17 :                                 return NT_STATUS_LOGON_FAILURE;
     853             :                         }
     854             :                 } else {
     855           0 :                         DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
     856             :                                   gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
     857             :                                   gensec_gssapi_state->gss_exchange_count,
     858             :                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     859           0 :                         return NT_STATUS_LOGON_FAILURE;
     860             :                 }
     861           0 :                 break;
     862             :         }
     863             : 
     864             :         /* These last two stages are only done if we were invoked as SASL */
     865         230 :         case STAGE_SASL_SSF_NEG:
     866             :         {
     867         230 :                 switch (gensec_security->gensec_role) {
     868         115 :                 case GENSEC_CLIENT:
     869             :                 {
     870           0 :                         uint8_t maxlength_proposed[4]; 
     871           0 :                         uint8_t maxlength_accepted[4]; 
     872           0 :                         uint8_t security_supported;
     873           0 :                         int conf_state;
     874           0 :                         gss_qop_t qop_state;
     875         115 :                         input_token.length = in.length;
     876         115 :                         input_token.value = in.data;
     877             : 
     878             :                         /* As a client, we have just send a
     879             :                          * zero-length blob to the server (after the
     880             :                          * normal GSSAPI exchange), and it has replied
     881             :                          * with it's SASL negotiation */
     882             :                         
     883         115 :                         maj_stat = gss_unwrap(&min_stat, 
     884          90 :                                               gensec_gssapi_state->gssapi_context, 
     885             :                                               &input_token,
     886             :                                               &output_token, 
     887             :                                               &conf_state,
     888             :                                               &qop_state);
     889         115 :                         if (GSS_ERROR(maj_stat)) {
     890           0 :                                 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
     891             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     892           0 :                                 return NT_STATUS_ACCESS_DENIED;
     893             :                         }
     894             :                         
     895         115 :                         if (output_token.length < 4) {
     896           0 :                                 gss_release_buffer(&min_stat, &output_token);
     897           0 :                                 return NT_STATUS_INVALID_PARAMETER;
     898             :                         }
     899             : 
     900         115 :                         memcpy(maxlength_proposed, output_token.value, 4);
     901         115 :                         gss_release_buffer(&min_stat, &output_token);
     902             : 
     903             :                         /* first byte is the proposed security */
     904         115 :                         security_supported = maxlength_proposed[0];
     905         115 :                         maxlength_proposed[0] = '\0';
     906             :                         
     907             :                         /* Rest is the proposed max wrap length */
     908         115 :                         gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0), 
     909             :                                                                      gensec_gssapi_state->max_wrap_buf_size);
     910         115 :                         gensec_gssapi_state->sasl_protection = 0;
     911         115 :                         if (security_supported & NEG_SEAL) {
     912          21 :                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
     913          21 :                                         gensec_gssapi_state->sasl_protection |= NEG_SEAL;
     914             :                                 }
     915             :                         }
     916         115 :                         if (security_supported & NEG_SIGN) {
     917          21 :                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
     918          21 :                                         gensec_gssapi_state->sasl_protection |= NEG_SIGN;
     919             :                                 }
     920             :                         }
     921         115 :                         if (security_supported & NEG_NONE) {
     922         115 :                                 gensec_gssapi_state->sasl_protection |= NEG_NONE;
     923             :                         }
     924         115 :                         if (gensec_gssapi_state->sasl_protection == 0) {
     925           0 :                                 DEBUG(1, ("Remote server does not support unprotected connections\n"));
     926           0 :                                 return NT_STATUS_ACCESS_DENIED;
     927             :                         }
     928             : 
     929             :                         /* Send back the negotiated max length */
     930             : 
     931         115 :                         RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
     932             : 
     933         115 :                         maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
     934             :                         
     935         115 :                         input_token.value = maxlength_accepted;
     936         115 :                         input_token.length = sizeof(maxlength_accepted);
     937             : 
     938         115 :                         maj_stat = gss_wrap(&min_stat, 
     939          90 :                                             gensec_gssapi_state->gssapi_context, 
     940             :                                             false,
     941             :                                             GSS_C_QOP_DEFAULT,
     942             :                                             &input_token,
     943             :                                             &conf_state,
     944             :                                             &output_token);
     945         115 :                         if (GSS_ERROR(maj_stat)) {
     946           0 :                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
     947             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
     948           0 :                                 return NT_STATUS_ACCESS_DENIED;
     949             :                         }
     950             :                         
     951         115 :                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
     952         115 :                         gss_release_buffer(&min_stat, &output_token);
     953             : 
     954             :                         /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
     955         115 :                         gensec_gssapi_state->sasl_state = STAGE_DONE;
     956             : 
     957         115 :                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
     958          21 :                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
     959          94 :                         } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
     960           0 :                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
     961             :                         } else {
     962          94 :                                 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographic protection\n"));
     963             :                         }
     964             : 
     965         115 :                         return NT_STATUS_OK;
     966             :                 }
     967         115 :                 case GENSEC_SERVER:
     968             :                 {
     969           0 :                         uint8_t maxlength_proposed[4]; 
     970         115 :                         uint8_t security_supported = 0x0;
     971           0 :                         int conf_state;
     972             : 
     973             :                         /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
     974         115 :                         if (in.length != 0) {
     975           0 :                                 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
     976             :                         }
     977             :                         
     978             :                         /* Give the client some idea what we will support */
     979             :                           
     980         115 :                         RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
     981             :                         /* first byte is the proposed security */
     982         115 :                         maxlength_proposed[0] = '\0';
     983             :                         
     984         115 :                         gensec_gssapi_state->sasl_protection = 0;
     985         115 :                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
     986          21 :                                 security_supported |= NEG_SEAL;
     987             :                         } 
     988         115 :                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
     989          21 :                                 security_supported |= NEG_SIGN;
     990             :                         }
     991         115 :                         if (security_supported == 0) {
     992             :                                 /* If we don't support anything, this must be 0 */
     993          94 :                                 RSIVAL(maxlength_proposed, 0, 0x0);
     994             :                         }
     995             : 
     996             :                         /* TODO:  We may not wish to support this */
     997         115 :                         security_supported |= NEG_NONE;
     998         115 :                         maxlength_proposed[0] = security_supported;
     999             :                         
    1000         115 :                         input_token.value = maxlength_proposed;
    1001         115 :                         input_token.length = sizeof(maxlength_proposed);
    1002             : 
    1003         115 :                         maj_stat = gss_wrap(&min_stat, 
    1004          90 :                                             gensec_gssapi_state->gssapi_context, 
    1005             :                                             false,
    1006             :                                             GSS_C_QOP_DEFAULT,
    1007             :                                             &input_token,
    1008             :                                             &conf_state,
    1009             :                                             &output_token);
    1010         115 :                         if (GSS_ERROR(maj_stat)) {
    1011           0 :                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
    1012             :                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1013           0 :                                 return NT_STATUS_ACCESS_DENIED;
    1014             :                         }
    1015             :                         
    1016         115 :                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
    1017         115 :                         gss_release_buffer(&min_stat, &output_token);
    1018             : 
    1019         115 :                         gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
    1020         115 :                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
    1021             :                 }
    1022           0 :                 default:
    1023           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1024             :                         
    1025             :                 }
    1026             :         }
    1027             :         /* This is s server-only stage */
    1028         115 :         case STAGE_SASL_SSF_ACCEPT:
    1029             :         {
    1030           0 :                 uint8_t maxlength_accepted[4]; 
    1031           0 :                 uint8_t security_accepted;
    1032           0 :                 int conf_state;
    1033           0 :                 gss_qop_t qop_state;
    1034         115 :                 input_token.length = in.length;
    1035         115 :                 input_token.value = in.data;
    1036             :                         
    1037         115 :                 maj_stat = gss_unwrap(&min_stat, 
    1038          90 :                                       gensec_gssapi_state->gssapi_context, 
    1039             :                                       &input_token,
    1040             :                                       &output_token, 
    1041             :                                       &conf_state,
    1042             :                                       &qop_state);
    1043         115 :                 if (GSS_ERROR(maj_stat)) {
    1044           0 :                         DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
    1045             :                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1046           0 :                         return NT_STATUS_ACCESS_DENIED;
    1047             :                 }
    1048             :                         
    1049         115 :                 if (output_token.length < 4) {
    1050           0 :                         gss_release_buffer(&min_stat, &output_token);
    1051           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1052             :                 }
    1053             : 
    1054         115 :                 memcpy(maxlength_accepted, output_token.value, 4);
    1055         115 :                 gss_release_buffer(&min_stat, &output_token);
    1056             :                 
    1057             :                 /* first byte is the proposed security */
    1058         115 :                 security_accepted = maxlength_accepted[0];
    1059         115 :                 maxlength_accepted[0] = '\0';
    1060             : 
    1061             :                 /* Rest is the proposed max wrap length */
    1062         115 :                 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0), 
    1063             :                                                              gensec_gssapi_state->max_wrap_buf_size);
    1064             : 
    1065         115 :                 gensec_gssapi_state->sasl_protection = 0;
    1066         115 :                 if (security_accepted & NEG_SEAL) {
    1067          21 :                         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
    1068           0 :                                 DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
    1069           0 :                                 return NT_STATUS_ACCESS_DENIED;
    1070             :                         }
    1071          21 :                         gensec_gssapi_state->sasl_protection |= NEG_SEAL;
    1072             :                 }
    1073         115 :                 if (security_accepted & NEG_SIGN) {
    1074          21 :                         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
    1075           0 :                                 DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
    1076           0 :                                 return NT_STATUS_ACCESS_DENIED;
    1077             :                         }
    1078          21 :                         gensec_gssapi_state->sasl_protection |= NEG_SIGN;
    1079             :                 }
    1080         115 :                 if (security_accepted & NEG_NONE) {
    1081         115 :                         gensec_gssapi_state->sasl_protection |= NEG_NONE;
    1082             :                 }
    1083             : 
    1084             :                 /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
    1085         115 :                 gensec_gssapi_state->sasl_state = STAGE_DONE;
    1086         115 :                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
    1087          21 :                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
    1088          94 :                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
    1089           0 :                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
    1090             :                 } else {
    1091          94 :                         DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
    1092             :                 }
    1093             : 
    1094         115 :                 *out = data_blob(NULL, 0);
    1095         115 :                 return NT_STATUS_OK;    
    1096             :         }
    1097           0 :         default:
    1098           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1099             :         }
    1100             : }
    1101             : 
    1102             : struct gensec_gssapi_update_state {
    1103             :         NTSTATUS status;
    1104             :         DATA_BLOB out;
    1105             : };
    1106             : 
    1107       96216 : static struct tevent_req *gensec_gssapi_update_send(TALLOC_CTX *mem_ctx,
    1108             :                                                     struct tevent_context *ev,
    1109             :                                                     struct gensec_security *gensec_security,
    1110             :                                                     const DATA_BLOB in)
    1111             : {
    1112       96216 :         struct tevent_req *req = NULL;
    1113       96216 :         struct gensec_gssapi_update_state *state = NULL;
    1114        2913 :         NTSTATUS status;
    1115             : 
    1116       96216 :         req = tevent_req_create(mem_ctx, &state,
    1117             :                                 struct gensec_gssapi_update_state);
    1118       96216 :         if (req == NULL) {
    1119           0 :                 return NULL;
    1120             :         }
    1121             : 
    1122       96216 :         status = gensec_gssapi_update_internal(gensec_security,
    1123             :                                                state, ev, in,
    1124       96216 :                                                &state->out);
    1125       96216 :         state->status = status;
    1126       96216 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1127       34429 :                 tevent_req_done(req);
    1128       34429 :                 return tevent_req_post(req, ev);
    1129             :         }
    1130       61787 :         if (tevent_req_nterror(req, status)) {
    1131        1506 :                 return tevent_req_post(req, ev);
    1132             :         }
    1133             : 
    1134       60281 :         tevent_req_done(req);
    1135       60281 :         return tevent_req_post(req, ev);
    1136             : }
    1137             : 
    1138       96216 : static NTSTATUS gensec_gssapi_update_recv(struct tevent_req *req,
    1139             :                                           TALLOC_CTX *out_mem_ctx,
    1140             :                                           DATA_BLOB *out)
    1141             : {
    1142        2913 :         struct gensec_gssapi_update_state *state =
    1143       96216 :                 tevent_req_data(req,
    1144             :                 struct gensec_gssapi_update_state);
    1145        2913 :         NTSTATUS status;
    1146             : 
    1147       96216 :         *out = data_blob_null;
    1148             : 
    1149       96216 :         if (tevent_req_is_nterror(req, &status)) {
    1150        1506 :                 tevent_req_received(req);
    1151        1506 :                 return status;
    1152             :         }
    1153             : 
    1154       94710 :         *out = state->out;
    1155       94710 :         talloc_steal(out_mem_ctx, state->out.data);
    1156       94710 :         status = state->status;
    1157       94710 :         tevent_req_received(req);
    1158       94710 :         return status;
    1159             : }
    1160             : 
    1161     1017584 : static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security, 
    1162             :                                    TALLOC_CTX *mem_ctx, 
    1163             :                                    const DATA_BLOB *in, 
    1164             :                                    DATA_BLOB *out)
    1165             : {
    1166         930 :         struct gensec_gssapi_state *gensec_gssapi_state
    1167     1017584 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1168         930 :         OM_uint32 maj_stat, min_stat;
    1169         930 :         gss_buffer_desc input_token, output_token;
    1170         930 :         int conf_state;
    1171     1017584 :         input_token.length = in->length;
    1172     1017584 :         input_token.value = in->data;
    1173             : 
    1174     1019444 :         maj_stat = gss_wrap(&min_stat, 
    1175      744051 :                             gensec_gssapi_state->gssapi_context, 
    1176     1017584 :                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
    1177             :                             GSS_C_QOP_DEFAULT,
    1178             :                             &input_token,
    1179             :                             &conf_state,
    1180             :                             &output_token);
    1181     1017584 :         if (GSS_ERROR(maj_stat)) {
    1182           0 :                 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", 
    1183             :                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1184           0 :                 return NT_STATUS_ACCESS_DENIED;
    1185             :         }
    1186             : 
    1187     1017584 :         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
    1188     1017584 :         gss_release_buffer(&min_stat, &output_token);
    1189             : 
    1190     1017584 :         if (gensec_gssapi_state->sasl) {
    1191          12 :                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
    1192          12 :                 if (max_wrapped_size < out->length) {
    1193           0 :                         DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
    1194             :                                   (unsigned)in->length, 
    1195             :                                   (unsigned)out->length, 
    1196             :                                   (unsigned int)max_wrapped_size));
    1197           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1198             :                 }
    1199             :         }
    1200             :         
    1201     1017584 :         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
    1202     1017048 :             && !conf_state) {
    1203           0 :                 return NT_STATUS_ACCESS_DENIED;
    1204             :         }
    1205     1017584 :         return NT_STATUS_OK;
    1206             : }
    1207             : 
    1208     1017603 : static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, 
    1209             :                                      TALLOC_CTX *mem_ctx, 
    1210             :                                      const DATA_BLOB *in, 
    1211             :                                      DATA_BLOB *out)
    1212             : {
    1213         930 :         struct gensec_gssapi_state *gensec_gssapi_state
    1214     1017603 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1215         930 :         OM_uint32 maj_stat, min_stat;
    1216         930 :         gss_buffer_desc input_token, output_token;
    1217         930 :         int conf_state;
    1218         930 :         gss_qop_t qop_state;
    1219     1017603 :         input_token.length = in->length;
    1220     1017603 :         input_token.value = in->data;
    1221             :         
    1222     1017603 :         if (gensec_gssapi_state->sasl) {
    1223          12 :                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
    1224          12 :                 if (max_wrapped_size < in->length) {
    1225           0 :                         DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
    1226           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1227             :                 }
    1228             :         }
    1229             :         
    1230             :         /*
    1231             :          * FIXME: input_message_buffer is marked const, but gss_unwrap() may
    1232             :          * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()).
    1233             :          */
    1234     1018533 :         maj_stat = gss_unwrap(&min_stat, 
    1235      744064 :                               gensec_gssapi_state->gssapi_context, 
    1236             :                               &input_token,
    1237             :                               &output_token, 
    1238             :                               &conf_state,
    1239             :                               &qop_state);
    1240     1017603 :         if (GSS_ERROR(maj_stat)) {
    1241           0 :                 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n", 
    1242             :                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1243           0 :                 return NT_STATUS_ACCESS_DENIED;
    1244             :         }
    1245             : 
    1246     1017603 :         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
    1247     1017603 :         gss_release_buffer(&min_stat, &output_token);
    1248             :         
    1249     1017603 :         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
    1250     1017067 :             && !conf_state) {
    1251           0 :                 return NT_STATUS_ACCESS_DENIED;
    1252             :         }
    1253     1017603 :         return NT_STATUS_OK;
    1254             : }
    1255             : 
    1256             : /* Find out the maximum input size negotiated on this connection */
    1257             : 
    1258       34191 : static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security) 
    1259             : {
    1260         244 :         struct gensec_gssapi_state *gensec_gssapi_state
    1261       34191 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1262         244 :         OM_uint32 maj_stat, min_stat;
    1263         244 :         OM_uint32 max_input_size;
    1264             : 
    1265       60009 :         maj_stat = gss_wrap_size_limit(&min_stat, 
    1266       25574 :                                        gensec_gssapi_state->gssapi_context,
    1267       34191 :                                        gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
    1268             :                                        GSS_C_QOP_DEFAULT,
    1269       34191 :                                        gensec_gssapi_state->max_wrap_buf_size,
    1270             :                                        &max_input_size);
    1271       34191 :         if (GSS_ERROR(maj_stat)) {
    1272           0 :                 TALLOC_CTX *mem_ctx = talloc_new(NULL); 
    1273           0 :                 DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
    1274             :                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1275           0 :                 talloc_free(mem_ctx);
    1276           0 :                 return 0;
    1277             :         }
    1278             : 
    1279       34191 :         return max_input_size;
    1280             : }
    1281             : 
    1282             : /* Find out the maximum output size negotiated on this connection */
    1283       34215 : static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security) 
    1284             : {
    1285       34215 :         struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
    1286       33971 :         return gensec_gssapi_state->max_wrap_buf_size;
    1287             : }
    1288             : 
    1289      339018 : static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, 
    1290             :                                           TALLOC_CTX *mem_ctx, 
    1291             :                                           uint8_t *data, size_t length, 
    1292             :                                           const uint8_t *whole_pdu, size_t pdu_length, 
    1293             :                                           DATA_BLOB *sig)
    1294             : {
    1295        1313 :         struct gensec_gssapi_state *gensec_gssapi_state
    1296      339018 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1297      339018 :         bool hdr_signing = false;
    1298      339018 :         size_t sig_size = 0;
    1299        1313 :         NTSTATUS status;
    1300             : 
    1301      339018 :         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1302      333527 :                 hdr_signing = true;
    1303             :         }
    1304             : 
    1305      339018 :         sig_size = gensec_gssapi_sig_size(gensec_security, length);
    1306             : 
    1307      339018 :         status = gssapi_seal_packet(gensec_gssapi_state->gssapi_context,
    1308             :                                     gensec_gssapi_state->gss_oid,
    1309             :                                     hdr_signing, sig_size,
    1310             :                                     data, length,
    1311             :                                     whole_pdu, pdu_length,
    1312             :                                     mem_ctx, sig);
    1313      339018 :         if (!NT_STATUS_IS_OK(status)) {
    1314           0 :                 DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu,"
    1315             :                           "data=%zu,pdu=%zu) failed: %s\n",
    1316             :                           hdr_signing, sig_size, length, pdu_length,
    1317             :                           nt_errstr(status)));
    1318           0 :                 return status;
    1319             :         }
    1320             : 
    1321      339018 :         return NT_STATUS_OK;
    1322             : }
    1323             : 
    1324      338982 : static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, 
    1325             :                                             uint8_t *data, size_t length, 
    1326             :                                             const uint8_t *whole_pdu, size_t pdu_length,
    1327             :                                             const DATA_BLOB *sig)
    1328             : {
    1329        1312 :         struct gensec_gssapi_state *gensec_gssapi_state
    1330      338982 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1331      338982 :         bool hdr_signing = false;
    1332        1312 :         NTSTATUS status;
    1333             : 
    1334      338982 :         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1335      333491 :                 hdr_signing = true;
    1336             :         }
    1337             : 
    1338      338982 :         status = gssapi_unseal_packet(gensec_gssapi_state->gssapi_context,
    1339             :                                       gensec_gssapi_state->gss_oid,
    1340             :                                       hdr_signing,
    1341             :                                       data, length,
    1342             :                                       whole_pdu, pdu_length,
    1343             :                                       sig);
    1344      338982 :         if (!NT_STATUS_IS_OK(status)) {
    1345           0 :                 DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu,"
    1346             :                           "data=%zu,pdu=%zu) failed: %s\n",
    1347             :                           hdr_signing, sig->length, length, pdu_length,
    1348             :                           nt_errstr(status)));
    1349           0 :                 return status;
    1350             :         }
    1351             : 
    1352      338982 :         return NT_STATUS_OK;
    1353             : }
    1354             : 
    1355       67460 : static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security, 
    1356             :                                           TALLOC_CTX *mem_ctx, 
    1357             :                                           const uint8_t *data, size_t length, 
    1358             :                                           const uint8_t *whole_pdu, size_t pdu_length, 
    1359             :                                           DATA_BLOB *sig)
    1360             : {
    1361         316 :         struct gensec_gssapi_state *gensec_gssapi_state
    1362       67460 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1363       67460 :         bool hdr_signing = false;
    1364         316 :         NTSTATUS status;
    1365             : 
    1366       67460 :         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1367       53032 :                 hdr_signing = true;
    1368             :         }
    1369             : 
    1370       67460 :         status = gssapi_sign_packet(gensec_gssapi_state->gssapi_context,
    1371             :                                     gensec_gssapi_state->gss_oid,
    1372             :                                     hdr_signing,
    1373             :                                     data, length,
    1374             :                                     whole_pdu, pdu_length,
    1375             :                                     mem_ctx, sig);
    1376       67460 :         if (!NT_STATUS_IS_OK(status)) {
    1377           0 :                 DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
    1378             :                           "data=%zu,pdu=%zu) failed: %s\n",
    1379             :                           hdr_signing, length, pdu_length,
    1380             :                           nt_errstr(status)));
    1381           0 :                 return status;
    1382             :         }
    1383             : 
    1384       67460 :         return NT_STATUS_OK;
    1385             : }
    1386             : 
    1387       67365 : static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, 
    1388             :                                            const uint8_t *data, size_t length, 
    1389             :                                            const uint8_t *whole_pdu, size_t pdu_length, 
    1390             :                                            const DATA_BLOB *sig)
    1391             : {
    1392         316 :         struct gensec_gssapi_state *gensec_gssapi_state
    1393       67365 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1394       67365 :         bool hdr_signing = false;
    1395         316 :         NTSTATUS status;
    1396             : 
    1397       67365 :         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1398       53024 :                 hdr_signing = true;
    1399             :         }
    1400             : 
    1401       67365 :         status = gssapi_check_packet(gensec_gssapi_state->gssapi_context,
    1402             :                                      gensec_gssapi_state->gss_oid,
    1403             :                                      hdr_signing,
    1404             :                                      data, length,
    1405             :                                      whole_pdu, pdu_length,
    1406             :                                      sig);
    1407       67365 :         if (!NT_STATUS_IS_OK(status)) {
    1408           6 :                 DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu,"
    1409             :                           "data=%zu,pdu=%zu) failed: %s\n",
    1410             :                           hdr_signing, sig->length, length, pdu_length,
    1411             :                           nt_errstr(status)));
    1412           6 :                 return status;
    1413             :         }
    1414             : 
    1415       67359 :         return NT_STATUS_OK;
    1416             : }
    1417             : 
    1418             : /* Try to figure out what features we actually got on the connection */
    1419     8093053 : static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, 
    1420             :                                        uint32_t feature) 
    1421             : {
    1422       38690 :         struct gensec_gssapi_state *gensec_gssapi_state
    1423     8093053 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1424     8093053 :         if (feature & GENSEC_FEATURE_SIGN) {
    1425             :                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
    1426     1885789 :                 if (gensec_gssapi_state->sasl 
    1427         468 :                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
    1428         311 :                         return ((gensec_gssapi_state->sasl_protection & NEG_SIGN) 
    1429         311 :                                 && (gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG));
    1430             :                 }
    1431     1885478 :                 return gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG;
    1432             :         }
    1433     6207264 :         if (feature & GENSEC_FEATURE_SEAL) {
    1434             :                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
    1435     4677684 :                 if (gensec_gssapi_state->sasl 
    1436         556 :                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
    1437         399 :                         return ((gensec_gssapi_state->sasl_protection & NEG_SEAL) 
    1438         399 :                                  && (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG));
    1439             :                 }
    1440     4677285 :                 return gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG;
    1441             :         }
    1442     1529580 :         if (feature & GENSEC_FEATURE_SESSION_KEY) {
    1443             :                 /* Only for GSSAPI/Krb5 */
    1444       28747 :                 if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
    1445             :                                       gss_mech_krb5)) {
    1446       27431 :                         return true;
    1447             :                 }
    1448             :         }
    1449     1500833 :         if (feature & GENSEC_FEATURE_DCE_STYLE) {
    1450     1338372 :                 return gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE;
    1451             :         }
    1452      162461 :         if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
    1453         983 :                 NTSTATUS status;
    1454         983 :                 uint32_t keytype;
    1455             : 
    1456       32953 :                 if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
    1457          72 :                         return false;
    1458             :                 }
    1459             : 
    1460       32881 :                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
    1461           0 :                         return true;
    1462             :                 }
    1463       32881 :                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
    1464           0 :                         return false;
    1465             :                 }
    1466             : 
    1467       32881 :                 status = gssapi_get_session_key(gensec_gssapi_state,
    1468             :                                                 gensec_gssapi_state->gssapi_context, NULL, &keytype);
    1469             :                 /* 
    1470             :                  * We should do a proper sig on the mechListMic unless
    1471             :                  * we know we have to be backwards compatible with
    1472             :                  * earlier windows versions.  
    1473             :                  * 
    1474             :                  * Negotiating a non-krb5
    1475             :                  * mech for example should be regarded as having
    1476             :                  * NEW_SPNEGO
    1477             :                  */
    1478       32881 :                 if (NT_STATUS_IS_OK(status)) {
    1479       32881 :                         switch (keytype) {
    1480        2263 :                         case ENCTYPE_DES_CBC_CRC:
    1481             :                         case ENCTYPE_DES_CBC_MD5:
    1482             :                         case ENCTYPE_ARCFOUR_HMAC:
    1483             :                         case ENCTYPE_DES3_CBC_SHA1:
    1484        2263 :                                 return false;
    1485             :                         }
    1486             :                 }
    1487       30618 :                 return true;
    1488             :         }
    1489             :         /* We can always do async (rather than strict request/reply) packets.  */
    1490      129508 :         if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
    1491      119775 :                 return true;
    1492             :         }
    1493        8346 :         if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
    1494        8346 :                 return true;
    1495             :         }
    1496           0 :         return false;
    1497             : }
    1498             : 
    1499       23530 : static NTTIME gensec_gssapi_expire_time(struct gensec_security *gensec_security)
    1500             : {
    1501         649 :         struct gensec_gssapi_state *gensec_gssapi_state =
    1502       23530 :                 talloc_get_type_abort(gensec_security->private_data,
    1503             :                 struct gensec_gssapi_state);
    1504             : 
    1505       23530 :         return gensec_gssapi_state->expire_time;
    1506             : }
    1507             : 
    1508             : /*
    1509             :  * Extract the 'session key' needed by SMB signing and ncacn_np
    1510             :  * (for encrypting some passwords).
    1511             :  * 
    1512             :  * This breaks all the abstractions, but what do you expect...
    1513             :  */
    1514       45587 : static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 
    1515             :                                           TALLOC_CTX *mem_ctx,
    1516             :                                           DATA_BLOB *session_key) 
    1517             : {
    1518        1546 :         struct gensec_gssapi_state *gensec_gssapi_state
    1519       45587 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1520       45587 :         return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
    1521             : }
    1522             : 
    1523             : /* Get some basic (and authorization) information about the user on
    1524             :  * this session.  This uses either the PAC (if present) or a local
    1525             :  * database lookup */
    1526       31197 : static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
    1527             :                                            TALLOC_CTX *mem_ctx,
    1528             :                                            struct auth_session_info **_session_info) 
    1529             : {
    1530         888 :         NTSTATUS nt_status;
    1531         888 :         TALLOC_CTX *tmp_ctx;
    1532         888 :         struct gensec_gssapi_state *gensec_gssapi_state
    1533       31197 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1534       31197 :         struct auth_session_info *session_info = NULL;
    1535         888 :         OM_uint32 maj_stat, min_stat;
    1536       31197 :         DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
    1537             : 
    1538         888 :         gss_buffer_desc name_token;
    1539         888 :         char *principal_string;
    1540             :         
    1541       31197 :         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
    1542       31197 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
    1543             : 
    1544       32085 :         maj_stat = gss_display_name (&min_stat,
    1545       23353 :                                      gensec_gssapi_state->client_name,
    1546             :                                      &name_token,
    1547             :                                      NULL);
    1548       31197 :         if (GSS_ERROR(maj_stat)) {
    1549           0 :                 DEBUG(1, ("GSS display_name failed: %s\n",
    1550             :                           gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
    1551           0 :                 talloc_free(tmp_ctx);
    1552           0 :                 return NT_STATUS_FOOBAR;
    1553             :         }
    1554             : 
    1555       32085 :         principal_string = talloc_strndup(tmp_ctx,
    1556       31197 :                                           (const char *)name_token.value,
    1557             :                                           name_token.length);
    1558             : 
    1559       31197 :         gss_release_buffer(&min_stat, &name_token);
    1560             : 
    1561       31197 :         if (!principal_string) {
    1562           0 :                 talloc_free(tmp_ctx);
    1563           0 :                 return NT_STATUS_NO_MEMORY;
    1564             :         }
    1565             : 
    1566       31197 :         nt_status = gssapi_obtain_pac_blob(tmp_ctx,  gensec_gssapi_state->gssapi_context,
    1567             :                                            gensec_gssapi_state->client_name,
    1568             :                                            &pac_blob);
    1569             :         
    1570             :         /* IF we have the PAC - otherwise we need to get this
    1571             :          * data from elsewhere - local ldb, or (TODO) lookup of some
    1572             :          * kind... 
    1573             :          */
    1574       31197 :         if (NT_STATUS_IS_OK(nt_status)) {
    1575       31192 :                 pac_blob_ptr = &pac_blob;
    1576             :         }
    1577       31197 :         nt_status = gensec_generate_session_info_pac(tmp_ctx,
    1578             :                                                      gensec_security,
    1579             :                                                      gensec_gssapi_state->smb_krb5_context,
    1580             :                                                      pac_blob_ptr, principal_string,
    1581             :                                                      gensec_get_remote_address(gensec_security),
    1582             :                                                      &session_info);
    1583       31197 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1584           5 :                 talloc_free(tmp_ctx);
    1585           5 :                 return nt_status;
    1586             :         }
    1587             : 
    1588       31192 :         nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
    1589       31192 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1590           0 :                 talloc_free(tmp_ctx);
    1591           0 :                 return nt_status;
    1592             :         }
    1593             : 
    1594       31192 :         if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
    1595       29925 :             gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
    1596         888 :                 krb5_error_code ret;
    1597         888 :                 const char *error_string;
    1598             : 
    1599       29861 :                 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
    1600             : 
    1601             :                 /*
    1602             :                  * Create anonymous credentials for now.
    1603             :                  *
    1604             :                  * We will update them with the provided client gss creds.
    1605             :                  */
    1606       29861 :                 session_info->credentials = cli_credentials_init_anon(session_info);
    1607       29861 :                 if (session_info->credentials == NULL) {
    1608           0 :                         talloc_free(tmp_ctx);
    1609           0 :                         return NT_STATUS_NO_MEMORY;
    1610             :                 }
    1611             : 
    1612       30749 :                 ret = cli_credentials_set_client_gss_creds(session_info->credentials, 
    1613       29861 :                                                            gensec_security->settings->lp_ctx,
    1614             :                                                            gensec_gssapi_state->delegated_cred_handle,
    1615             :                                                            CRED_SPECIFIED, &error_string);
    1616       29861 :                 if (ret) {
    1617           0 :                         talloc_free(tmp_ctx);
    1618           0 :                         DEBUG(2,("Failed to get gss creds: %s\n", error_string));
    1619           0 :                         return NT_STATUS_NO_MEMORY;
    1620             :                 }
    1621             :                 
    1622             :                 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
    1623       29861 :                 cli_credentials_set_kerberos_state(session_info->credentials,
    1624             :                                                    CRED_USE_KERBEROS_REQUIRED,
    1625             :                                                    CRED_SPECIFIED);
    1626             : 
    1627             :                 /* It has been taken from this place... */
    1628       29861 :                 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
    1629             :         } else {
    1630        1331 :                 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
    1631             :         }
    1632             : 
    1633       31192 :         *_session_info = talloc_steal(mem_ctx, session_info);
    1634       31192 :         talloc_free(tmp_ctx);
    1635             : 
    1636       31192 :         return NT_STATUS_OK;
    1637             : }
    1638             : 
    1639      459937 : static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
    1640             : {
    1641        2682 :         struct gensec_gssapi_state *gensec_gssapi_state
    1642      459937 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1643        2682 :         size_t sig_size;
    1644             : 
    1645      459937 :         if (gensec_gssapi_state->sig_size > 0) {
    1646      449371 :                 return gensec_gssapi_state->sig_size;
    1647             :         }
    1648             : 
    1649        8070 :         sig_size = gssapi_get_sig_size(gensec_gssapi_state->gssapi_context,
    1650             :                                        gensec_gssapi_state->gss_oid,
    1651             :                                        gensec_gssapi_state->gss_got_flags,
    1652             :                                        data_size);
    1653             : 
    1654        8070 :         gensec_gssapi_state->sig_size = sig_size;
    1655        8070 :         return gensec_gssapi_state->sig_size;
    1656             : }
    1657             : 
    1658       31192 : static const char *gensec_gssapi_final_auth_type(struct gensec_security *gensec_security)
    1659             : {
    1660         888 :         struct gensec_gssapi_state *gensec_gssapi_state
    1661       31192 :                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
    1662             :         /* Only return the string for GSSAPI/Krb5 */
    1663       31192 :         if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
    1664             :                               gss_mech_krb5)) {
    1665       30304 :                 return GENSEC_FINAL_AUTH_TYPE_KRB5;
    1666             :         } else {
    1667           0 :                 return "gensec_gssapi: UNKNOWN MECH";
    1668             :         }
    1669             : }
    1670             : 
    1671             : static const char *gensec_gssapi_krb5_oids[] = { 
    1672             :         GENSEC_OID_KERBEROS5_OLD,
    1673             :         GENSEC_OID_KERBEROS5,
    1674             :         NULL 
    1675             : };
    1676             : 
    1677             : static const char *gensec_gssapi_spnego_oids[] = { 
    1678             :         GENSEC_OID_SPNEGO,
    1679             :         NULL 
    1680             : };
    1681             : 
    1682             : /* As a server, this could in theory accept any GSSAPI mech */
    1683             : static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
    1684             :         .name           = "gssapi_spnego",
    1685             :         .sasl_name      = "GSS-SPNEGO",
    1686             :         .auth_type      = DCERPC_AUTH_TYPE_SPNEGO,
    1687             :         .oid            = gensec_gssapi_spnego_oids,
    1688             :         .client_start   = gensec_gssapi_client_start,
    1689             :         .server_start   = gensec_gssapi_server_start,
    1690             :         .magic          = gensec_magic_check_krb5_oid,
    1691             :         .update_send    = gensec_gssapi_update_send,
    1692             :         .update_recv    = gensec_gssapi_update_recv,
    1693             :         .session_key    = gensec_gssapi_session_key,
    1694             :         .session_info   = gensec_gssapi_session_info,
    1695             :         .sign_packet    = gensec_gssapi_sign_packet,
    1696             :         .check_packet   = gensec_gssapi_check_packet,
    1697             :         .seal_packet    = gensec_gssapi_seal_packet,
    1698             :         .unseal_packet  = gensec_gssapi_unseal_packet,
    1699             :         .max_input_size   = gensec_gssapi_max_input_size,
    1700             :         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
    1701             :         .wrap           = gensec_gssapi_wrap,
    1702             :         .unwrap         = gensec_gssapi_unwrap,
    1703             :         .have_feature   = gensec_gssapi_have_feature,
    1704             :         .expire_time    = gensec_gssapi_expire_time,
    1705             :         .final_auth_type = gensec_gssapi_final_auth_type,
    1706             :         .enabled        = false,
    1707             :         .kerberos       = true,
    1708             :         .priority       = GENSEC_GSSAPI
    1709             : };
    1710             : 
    1711             : /* As a server, this could in theory accept any GSSAPI mech */
    1712             : static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
    1713             :         .name           = "gssapi_krb5",
    1714             :         .auth_type      = DCERPC_AUTH_TYPE_KRB5,
    1715             :         .oid            = gensec_gssapi_krb5_oids,
    1716             :         .client_start   = gensec_gssapi_client_start,
    1717             :         .server_start   = gensec_gssapi_server_start,
    1718             :         .magic          = gensec_magic_check_krb5_oid,
    1719             :         .update_send    = gensec_gssapi_update_send,
    1720             :         .update_recv    = gensec_gssapi_update_recv,
    1721             :         .session_key    = gensec_gssapi_session_key,
    1722             :         .session_info   = gensec_gssapi_session_info,
    1723             :         .sig_size       = gensec_gssapi_sig_size,
    1724             :         .sign_packet    = gensec_gssapi_sign_packet,
    1725             :         .check_packet   = gensec_gssapi_check_packet,
    1726             :         .seal_packet    = gensec_gssapi_seal_packet,
    1727             :         .unseal_packet  = gensec_gssapi_unseal_packet,
    1728             :         .max_input_size   = gensec_gssapi_max_input_size,
    1729             :         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
    1730             :         .wrap           = gensec_gssapi_wrap,
    1731             :         .unwrap         = gensec_gssapi_unwrap,
    1732             :         .have_feature   = gensec_gssapi_have_feature,
    1733             :         .expire_time    = gensec_gssapi_expire_time,
    1734             :         .final_auth_type = gensec_gssapi_final_auth_type,
    1735             :         .enabled        = true,
    1736             :         .kerberos       = true,
    1737             :         .priority       = GENSEC_GSSAPI
    1738             : };
    1739             : 
    1740             : /* As a server, this could in theory accept any GSSAPI mech */
    1741             : static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
    1742             :         .name             = "gssapi_krb5_sasl",
    1743             :         .sasl_name        = "GSSAPI",
    1744             :         .client_start     = gensec_gssapi_sasl_client_start,
    1745             :         .server_start     = gensec_gssapi_sasl_server_start,
    1746             :         .update_send      = gensec_gssapi_update_send,
    1747             :         .update_recv      = gensec_gssapi_update_recv,
    1748             :         .session_key      = gensec_gssapi_session_key,
    1749             :         .session_info     = gensec_gssapi_session_info,
    1750             :         .max_input_size   = gensec_gssapi_max_input_size,
    1751             :         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
    1752             :         .wrap             = gensec_gssapi_wrap,
    1753             :         .unwrap           = gensec_gssapi_unwrap,
    1754             :         .have_feature     = gensec_gssapi_have_feature,
    1755             :         .expire_time      = gensec_gssapi_expire_time,
    1756             :         .final_auth_type = gensec_gssapi_final_auth_type,
    1757             :         .enabled          = true,
    1758             :         .kerberos         = true,
    1759             :         .priority         = GENSEC_GSSAPI
    1760             : };
    1761             : 
    1762       53162 : _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *ctx)
    1763             : {
    1764        1228 :         NTSTATUS ret;
    1765             : 
    1766       53162 :         ret = gensec_register(ctx, &gensec_gssapi_spnego_security_ops);
    1767       53162 :         if (!NT_STATUS_IS_OK(ret)) {
    1768           0 :                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
    1769             :                         gensec_gssapi_spnego_security_ops.name));
    1770           0 :                 return ret;
    1771             :         }
    1772             : 
    1773       53162 :         ret = gensec_register(ctx, &gensec_gssapi_krb5_security_ops);
    1774       53162 :         if (!NT_STATUS_IS_OK(ret)) {
    1775           0 :                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
    1776             :                         gensec_gssapi_krb5_security_ops.name));
    1777           0 :                 return ret;
    1778             :         }
    1779             : 
    1780       53162 :         ret = gensec_register(ctx, &gensec_gssapi_sasl_krb5_security_ops);
    1781       53162 :         if (!NT_STATUS_IS_OK(ret)) {
    1782           0 :                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
    1783             :                         gensec_gssapi_sasl_krb5_security_ops.name));
    1784           0 :                 return ret;
    1785             :         }
    1786             : 
    1787       53162 :         return ret;
    1788             : }

Generated by: LCOV version 1.14