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

Generated by: LCOV version 1.13