2 Unix SMB/CIFS implementation.
4 Kerberos backend for GENSEC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
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.
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.
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/>.
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"
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"
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)
56 _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *);
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);
62 static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
66 if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
67 gss_release_cred(&min_stat,
68 &gensec_gssapi_state->delegated_cred_handle);
71 if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
72 gss_delete_sec_context(&min_stat,
73 &gensec_gssapi_state->gssapi_context,
77 if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
78 gss_release_name(&min_stat,
79 &gensec_gssapi_state->server_name);
81 if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
82 gss_release_name(&min_stat,
83 &gensec_gssapi_state->client_name);
89 static NTSTATUS gensec_gssapi_setup_server_principal(TALLOC_CTX *mem_ctx,
90 const char *target_principal,
95 char **pserver_principal,
96 gss_name_t *pserver_name)
98 char *server_principal = NULL;
99 gss_buffer_desc name_token;
101 OM_uint32 maj_stat, min_stat = 0;
103 if (target_principal != NULL) {
104 server_principal = talloc_strdup(mem_ctx, target_principal);
105 name_type = GSS_C_NULL_OID;
107 server_principal = talloc_asprintf(mem_ctx,
109 service, hostname, realm);
110 name_type = GSS_C_NT_USER_NAME;
112 if (server_principal == NULL) {
113 return NT_STATUS_NO_MEMORY;
116 name_token.value = (uint8_t *)server_principal;
117 name_token.length = strlen(server_principal);
119 maj_stat = gss_import_name(&min_stat,
124 DBG_WARNING("GSS Import name of %s failed: %s\n",
126 gssapi_error_string(mem_ctx,
130 TALLOC_FREE(server_principal);
131 return NT_STATUS_INVALID_PARAMETER;
134 *pserver_principal = server_principal;
139 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
141 struct gensec_gssapi_state *gensec_gssapi_state;
143 #ifdef SAMBA4_USES_HEIMDAL
147 gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
148 if (!gensec_gssapi_state) {
149 return NT_STATUS_NO_MEMORY;
152 gensec_security->private_data = gensec_gssapi_state;
154 gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
156 if (gensec_security->channel_bindings != NULL) {
157 gensec_gssapi_state->_input_chan_bindings.initiator_addrtype =
158 gensec_security->channel_bindings->initiator_addrtype;
159 gensec_gssapi_state->_input_chan_bindings.initiator_address.value =
160 gensec_security->channel_bindings->initiator_address.data;
161 gensec_gssapi_state->_input_chan_bindings.initiator_address.length =
162 gensec_security->channel_bindings->initiator_address.length;
164 gensec_gssapi_state->_input_chan_bindings.acceptor_addrtype =
165 gensec_security->channel_bindings->acceptor_addrtype;
166 gensec_gssapi_state->_input_chan_bindings.acceptor_address.value =
167 gensec_security->channel_bindings->acceptor_address.data;
168 gensec_gssapi_state->_input_chan_bindings.acceptor_address.length =
169 gensec_security->channel_bindings->acceptor_address.length;
171 gensec_gssapi_state->_input_chan_bindings.application_data.value =
172 gensec_security->channel_bindings->application_data.data;
173 gensec_gssapi_state->_input_chan_bindings.application_data.length =
174 gensec_security->channel_bindings->application_data.length;
176 gensec_gssapi_state->input_chan_bindings =
177 &gensec_gssapi_state->_input_chan_bindings;
179 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
182 gensec_gssapi_state->server_name = GSS_C_NO_NAME;
183 gensec_gssapi_state->client_name = GSS_C_NO_NAME;
185 gensec_gssapi_state->gss_want_flags = 0;
186 gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
188 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
189 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG;
191 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
192 gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG;
194 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", false)) {
195 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG;
197 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
198 gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG;
200 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
201 gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
204 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
205 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
207 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
208 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
210 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
211 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
212 gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG;
214 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
215 gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE;
218 gensec_gssapi_state->gss_got_flags = 0;
220 switch (gensec_security->ops->auth_type) {
221 case DCERPC_AUTH_TYPE_SPNEGO:
222 gensec_gssapi_state->gss_oid = gss_mech_spnego;
224 case DCERPC_AUTH_TYPE_KRB5:
226 gensec_gssapi_state->gss_oid =
227 discard_const_p(void, gss_mech_krb5);
231 ret = smb_krb5_init_context(gensec_gssapi_state,
232 gensec_security->settings->lp_ctx,
233 &gensec_gssapi_state->smb_krb5_context);
235 DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n",
236 error_message(ret)));
237 talloc_free(gensec_gssapi_state);
238 return NT_STATUS_INTERNAL_ERROR;
241 gensec_gssapi_state->client_cred = NULL;
242 gensec_gssapi_state->server_cred = NULL;
244 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
246 gensec_gssapi_state->sasl = false;
247 gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
248 gensec_gssapi_state->sasl_protection = 0;
250 gensec_gssapi_state->max_wrap_buf_size
251 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
252 gensec_gssapi_state->gss_exchange_count = 0;
253 gensec_gssapi_state->sig_size = 0;
255 talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
257 #ifdef SAMBA4_USES_HEIMDAL
258 realm = lpcfg_realm(gensec_security->settings->lp_ctx);
260 ret = gsskrb5_set_default_realm(realm);
262 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n"));
263 talloc_free(gensec_gssapi_state);
264 return NT_STATUS_INTERNAL_ERROR;
268 /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
269 ret = gsskrb5_set_dns_canonicalize(false);
271 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n"));
272 talloc_free(gensec_gssapi_state);
273 return NT_STATUS_INTERNAL_ERROR;
279 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
283 struct gensec_gssapi_state *gensec_gssapi_state;
284 struct cli_credentials *machine_account;
285 struct gssapi_creds_container *gcc;
287 nt_status = gensec_gssapi_start(gensec_security);
288 if (!NT_STATUS_IS_OK(nt_status)) {
292 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
294 machine_account = gensec_get_credentials(gensec_security);
296 if (!machine_account) {
297 DEBUG(3, ("No machine account credentials specified\n"));
298 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
300 ret = cli_credentials_get_server_gss_creds(machine_account,
301 gensec_security->settings->lp_ctx, &gcc);
303 DEBUG(1, ("Acquiring acceptor credentials failed: %s\n",
304 error_message(ret)));
305 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
309 gensec_gssapi_state->server_cred = gcc;
314 static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
317 struct gensec_gssapi_state *gensec_gssapi_state;
318 nt_status = gensec_gssapi_server_start(gensec_security);
320 if (NT_STATUS_IS_OK(nt_status)) {
321 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
322 gensec_gssapi_state->sasl = true;
327 static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security,
328 struct tevent_context *ev)
330 struct gensec_gssapi_state *gensec_gssapi_state;
331 struct gssapi_creds_container *gcc;
332 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
333 const char *error_string;
336 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
338 /* Only run this the first time the update() call is made */
339 if (gensec_gssapi_state->client_cred) {
343 ret = cli_credentials_get_client_gss_creds(creds,
345 gensec_security->settings->lp_ctx, &gcc, &error_string);
350 DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
351 return NT_STATUS_INVALID_PARAMETER;
352 case KRB5KDC_ERR_PREAUTH_FAILED:
353 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
354 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
355 DEBUG(1, ("Wrong username or password: %s\n", error_string));
356 return NT_STATUS_LOGON_FAILURE;
357 case KRB5KDC_ERR_CLIENT_REVOKED:
358 DEBUG(1, ("Account locked out: %s\n", error_string));
359 return NT_STATUS_ACCOUNT_LOCKED_OUT;
360 case KRB5_REALM_UNKNOWN:
361 case KRB5_KDC_UNREACH:
362 DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
363 return NT_STATUS_NO_LOGON_SERVERS;
364 case KRB5_CC_NOTFOUND:
366 DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string));
367 return NT_STATUS_TIME_DIFFERENCE_AT_DC;
369 DEBUG(1, ("Acquiring initiator credentials failed: %s\n", error_string));
370 return NT_STATUS_UNSUCCESSFUL;
373 gensec_gssapi_state->client_cred = gcc;
374 if (!talloc_reference(gensec_gssapi_state, gcc)) {
375 return NT_STATUS_NO_MEMORY;
381 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
383 struct gensec_gssapi_state *gensec_gssapi_state;
384 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
387 nt_status = gensec_kerberos_possible(gensec_security);
388 if (!NT_STATUS_IS_OK(nt_status)) {
389 char *target_name = NULL;
390 char *cred_name = NULL;
392 target_name = gensec_get_unparsed_target_principal(gensec_security,
394 cred_name = cli_credentials_get_unparsed_name(creds,
397 DBG_NOTICE("Not using kerberos to %s as %s: %s\n",
398 target_name, cred_name, nt_errstr(nt_status));
400 TALLOC_FREE(target_name);
401 TALLOC_FREE(cred_name);
405 nt_status = gensec_gssapi_start(gensec_security);
406 if (!NT_STATUS_IS_OK(nt_status)) {
410 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
412 #ifdef HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG
414 * We can only use GSS_C_CHANNEL_BOUND_FLAG if the kerberos library
415 * supports that in order to add KERB_AP_OPTIONS_CBT.
418 * https://github.com/heimdal/heimdal/pull/1234
419 * https://github.com/krb5/krb5/pull/1329
421 if (!(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL)) {
422 gensec_gssapi_state->gss_want_flags |= GSS_C_CHANNEL_BOUND_FLAG;
426 if (cli_credentials_get_impersonate_principal(creds)) {
427 gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
433 static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
436 struct gensec_gssapi_state *gensec_gssapi_state;
437 nt_status = gensec_gssapi_client_start(gensec_security);
439 if (NT_STATUS_IS_OK(nt_status)) {
440 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
441 gensec_gssapi_state->sasl = true;
446 static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_security,
447 TALLOC_CTX *out_mem_ctx,
448 struct tevent_context *ev,
449 const DATA_BLOB in, DATA_BLOB *out)
451 struct gensec_gssapi_state *gensec_gssapi_state
452 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
454 OM_uint32 maj_stat, min_stat;
456 gss_buffer_desc input_token = { 0, NULL };
457 gss_buffer_desc output_token = { 0, NULL };
458 struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security);
459 const char *target_principal = gensec_get_target_principal(gensec_security);
460 const char *hostname = gensec_get_target_hostname(gensec_security);
461 const char *service = gensec_get_target_service(gensec_security);
462 gss_OID gss_oid_p = NULL;
463 OM_uint32 time_req = 0;
464 OM_uint32 time_rec = 0;
467 time_req = gensec_setting_int(gensec_security->settings,
468 "gensec_gssapi", "requested_life_time",
471 input_token.length = in.length;
472 input_token.value = in.data;
474 switch (gensec_gssapi_state->sasl_state) {
477 switch (gensec_security->gensec_role) {
480 const char *client_realm = NULL;
481 #ifdef SAMBA4_USES_HEIMDAL
482 struct gsskrb5_send_to_kdc send_to_kdc;
485 bool fallback = false;
488 nt_status = gensec_gssapi_client_creds(gensec_security, ev);
489 if (!NT_STATUS_IS_OK(nt_status)) {
493 #ifdef SAMBA4_USES_HEIMDAL
494 send_to_kdc.func = smb_krb5_send_and_recv_func;
495 send_to_kdc.ptr = ev;
497 min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
499 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
500 return NT_STATUS_INTERNAL_ERROR;
505 * With credentials for
506 * administrator@FOREST1.EXAMPLE.COM this patch changes
507 * the target_principal for the ldap service of host
508 * dc2.forest2.example.com from
510 * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
514 * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM
517 * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
518 * should be used in order to allow the KDC of
519 * FOREST1.EXAMPLE.COM to generate a referral ticket
520 * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM.
522 * The problem is that KDCs only return such referral
523 * tickets if there's a forest trust between
524 * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If
525 * there's only an external domain trust between
526 * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC
527 * of FOREST1.EXAMPLE.COM will respond with
528 * S_PRINCIPAL_UNKNOWN when being asked for
529 * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM.
531 * In the case of an external trust the client can
532 * still ask explicitly for
533 * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and
534 * the KDC of FOREST1.EXAMPLE.COM will generate it.
536 * From there the client can use the
537 * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM
538 * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a
540 * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM.
542 * With Heimdal we'll get the fallback on
543 * S_PRINCIPAL_UNKNOWN behavior when we pass
544 * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as
545 * target principal. As _krb5_get_cred_kdc_any() first
546 * calls get_cred_kdc_referral() (which always starts
547 * with the client realm) and falls back to
548 * get_cred_kdc_capath() (which starts with the given
551 * MIT krb5 only tries the given realm of the target
552 * principal, if we want to autodetect support for
553 * transitive forest trusts, would have to do the
556 client_realm = cli_credentials_get_realm(cli_creds);
557 #ifndef SAMBA4_USES_HEIMDAL
558 if (gensec_gssapi_state->server_name == NULL) {
559 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
564 gensec_gssapi_state->gss_oid,
565 &gensec_gssapi_state->target_principal,
566 &gensec_gssapi_state->server_name);
567 if (!NT_STATUS_IS_OK(nt_status)) {
571 maj_stat = gss_init_sec_context(&min_stat,
572 gensec_gssapi_state->client_cred->creds,
573 &gensec_gssapi_state->gssapi_context,
574 gensec_gssapi_state->server_name,
575 gensec_gssapi_state->gss_oid,
576 gensec_gssapi_state->gss_want_flags,
578 gensec_gssapi_state->input_chan_bindings,
582 &gensec_gssapi_state->gss_got_flags, /* ret flags */
584 if (maj_stat != GSS_S_FAILURE) {
585 goto init_sec_context_done;
587 if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
588 goto init_sec_context_done;
590 if (target_principal != NULL) {
591 goto init_sec_context_done;
595 TALLOC_FREE(gensec_gssapi_state->target_principal);
596 gss_release_name(&min_stat2, &gensec_gssapi_state->server_name);
598 #endif /* !SAMBA4_USES_HEIMDAL */
599 if (gensec_gssapi_state->server_name == NULL) {
600 const char *server_realm = NULL;
602 server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state,
605 if (server_realm == NULL) {
606 return NT_STATUS_NO_MEMORY;
609 #ifndef SAMBA4_USES_HEIMDAL
611 strequal(client_realm, server_realm)) {
612 goto init_sec_context_done;
614 #endif /* !SAMBA4_USES_HEIMDAL */
616 nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
621 gensec_gssapi_state->gss_oid,
622 &gensec_gssapi_state->target_principal,
623 &gensec_gssapi_state->server_name);
624 if (!NT_STATUS_IS_OK(nt_status)) {
629 maj_stat = gss_init_sec_context(&min_stat,
630 gensec_gssapi_state->client_cred->creds,
631 &gensec_gssapi_state->gssapi_context,
632 gensec_gssapi_state->server_name,
633 gensec_gssapi_state->gss_oid,
634 gensec_gssapi_state->gss_want_flags,
636 gensec_gssapi_state->input_chan_bindings,
640 &gensec_gssapi_state->gss_got_flags, /* ret flags */
642 goto init_sec_context_done;
644 init_sec_context_done:
646 gensec_gssapi_state->gss_oid = gss_oid_p;
649 #ifdef SAMBA4_USES_HEIMDAL
650 send_to_kdc.func = smb_krb5_send_and_recv_func;
651 send_to_kdc.ptr = NULL;
653 ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
655 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
656 return NT_STATUS_INTERNAL_ERROR;
663 maj_stat = gss_accept_sec_context(&min_stat,
664 &gensec_gssapi_state->gssapi_context,
665 gensec_gssapi_state->server_cred->creds,
667 gensec_gssapi_state->input_chan_bindings,
668 &gensec_gssapi_state->client_name,
671 &gensec_gssapi_state->gss_got_flags,
673 &gensec_gssapi_state->delegated_cred_handle);
675 gensec_gssapi_state->gss_oid = gss_oid_p;
677 #ifdef GSS_C_CHANNEL_BOUND_FLAG
678 if (maj_stat == GSS_S_COMPLETE &&
679 gensec_security->channel_bindings != NULL &&
680 !(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL) &&
681 !(gensec_gssapi_state->gss_got_flags & GSS_C_CHANNEL_BOUND_FLAG))
684 * If we require valid channel bindings
685 * we need to check the client provided
689 * GSS_C_CHANNEL_BOUND_FLAG is given.
691 * Recent heimdal and MIT releases support this
692 * with older releases (e.g. MIT > 1.19).
694 * It means client with zero channel bindings
695 * on a server with non-zero channel bindings
696 * won't generate GSS_S_BAD_BINDINGS directly
697 * unless KERB_AP_OPTIONS_CBT was also
698 * provides by the client.
700 * So we need to convert a missing
701 * GSS_C_CHANNEL_BOUND_FLAG into
702 * GSS_S_BAD_BINDINGS by default
703 * (unless GENSEC_FEATURE_CB_OPTIONAL is given).
705 maj_stat = GSS_S_BAD_BINDINGS;
708 #endif /* GSS_C_CHANNEL_BOUND_FLAG */
713 return NT_STATUS_INVALID_PARAMETER;
717 gensec_gssapi_state->gss_exchange_count++;
719 if (maj_stat == GSS_S_COMPLETE) {
720 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
721 gss_release_buffer(&min_stat2, &output_token);
723 if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
724 gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
725 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
727 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
730 tv = timeval_current_ofs(time_rec, 0);
731 gensec_gssapi_state->expire_time = timeval_to_nttime(&tv);
733 /* We may have been invoked as SASL, so there
734 * is more work to do */
735 if (gensec_gssapi_state->sasl) {
736 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
737 return NT_STATUS_MORE_PROCESSING_REQUIRED;
739 gensec_gssapi_state->sasl_state = STAGE_DONE;
741 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
742 DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
743 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
744 DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
746 DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
751 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
752 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
753 gss_release_buffer(&min_stat2, &output_token);
755 return NT_STATUS_MORE_PROCESSING_REQUIRED;
756 } else if (maj_stat == GSS_S_BAD_BINDINGS) {
757 DBG_WARNING("Got GSS_S_BAD_BINDINGS\n");
758 return NT_STATUS_BAD_BINDINGS;
759 } else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
760 gss_cred_id_t creds = NULL;
762 gss_buffer_desc buffer;
763 OM_uint32 lifetime = 0;
764 gss_cred_usage_t usage;
765 const char *role = NULL;
767 switch (gensec_security->gensec_role) {
769 creds = gensec_gssapi_state->client_cred->creds;
773 creds = gensec_gssapi_state->server_cred->creds;
778 DBG_ERR("GSS %s Update(krb5)(%d) failed, credentials "
779 "expired during GSSAPI handshake!\n",
781 gensec_gssapi_state->gss_exchange_count);
783 maj_stat = gss_inquire_cred(&min_stat,
785 &name, &lifetime, &usage, NULL);
787 if (maj_stat == GSS_S_COMPLETE) {
788 const char *usage_string = NULL;
791 usage_string = "GSS_C_BOTH";
794 usage_string = "GSS_C_ACCEPT";
797 usage_string = "GSS_C_INITIATE";
800 maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
806 DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n",
807 (int)buffer.length, (int)buffer.length, (char *)buffer.value,
808 lifetime, usage_string));
810 DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n",
811 (int)buffer.length, (int)buffer.length, (char *)buffer.value,
814 gss_release_buffer(&min_stat, &buffer);
815 gss_release_name(&min_stat, &name);
816 } else if (maj_stat != GSS_S_COMPLETE) {
817 DEBUG(0, ("inquiry of credential lifetime via GSSAPI gss_inquire_cred failed: %s\n",
818 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
820 return NT_STATUS_INVALID_PARAMETER;
821 } else if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
824 case (OM_uint32)KRB5KRB_AP_ERR_TKT_NYV:
825 DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
826 gensec_gssapi_state->target_principal,
827 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
828 return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
829 case (OM_uint32)KRB5KRB_AP_ERR_TKT_EXPIRED:
830 DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
831 gensec_gssapi_state->target_principal,
832 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
833 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
834 case (OM_uint32)KRB5_KDC_UNREACH:
835 DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticket to %s: %s\n",
836 gensec_gssapi_state->target_principal,
837 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
838 return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
839 case (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
840 DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
841 gensec_gssapi_state->target_principal,
842 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
843 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
844 case (OM_uint32)KRB5KRB_AP_ERR_MSG_TYPE:
845 /* garbage input, possibly from the auto-mech detection */
846 return NT_STATUS_INVALID_PARAMETER;
848 DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
849 gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
850 gensec_gssapi_state->gss_exchange_count,
851 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
852 return NT_STATUS_LOGON_FAILURE;
855 DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
856 gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
857 gensec_gssapi_state->gss_exchange_count,
858 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
859 return NT_STATUS_LOGON_FAILURE;
864 /* These last two stages are only done if we were invoked as SASL */
865 case STAGE_SASL_SSF_NEG:
867 switch (gensec_security->gensec_role) {
870 uint8_t maxlength_proposed[4];
871 uint8_t maxlength_accepted[4];
872 uint8_t security_supported;
875 input_token.length = in.length;
876 input_token.value = in.data;
878 /* As a client, we have just send a
879 * zero-length blob to the server (after the
880 * normal GSSAPI exchange), and it has replied
881 * with it's SASL negotiation */
883 maj_stat = gss_unwrap(&min_stat,
884 gensec_gssapi_state->gssapi_context,
889 if (GSS_ERROR(maj_stat)) {
890 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
891 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
892 return NT_STATUS_ACCESS_DENIED;
895 if (output_token.length < 4) {
896 gss_release_buffer(&min_stat, &output_token);
897 return NT_STATUS_INVALID_PARAMETER;
900 memcpy(maxlength_proposed, output_token.value, 4);
901 gss_release_buffer(&min_stat, &output_token);
903 /* first byte is the proposed security */
904 security_supported = maxlength_proposed[0];
905 maxlength_proposed[0] = '\0';
907 /* Rest is the proposed max wrap length */
908 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0),
909 gensec_gssapi_state->max_wrap_buf_size);
910 gensec_gssapi_state->sasl_protection = 0;
911 if (security_supported & NEG_SEAL) {
912 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
913 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
916 if (security_supported & NEG_SIGN) {
917 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
918 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
921 if (security_supported & NEG_NONE) {
922 gensec_gssapi_state->sasl_protection |= NEG_NONE;
924 if (gensec_gssapi_state->sasl_protection == 0) {
925 DEBUG(1, ("Remote server does not support unprotected connections\n"));
926 return NT_STATUS_ACCESS_DENIED;
929 /* Send back the negotiated max length */
931 RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
933 maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
935 input_token.value = maxlength_accepted;
936 input_token.length = sizeof(maxlength_accepted);
938 maj_stat = gss_wrap(&min_stat,
939 gensec_gssapi_state->gssapi_context,
945 if (GSS_ERROR(maj_stat)) {
946 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
947 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
948 return NT_STATUS_ACCESS_DENIED;
951 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
952 gss_release_buffer(&min_stat, &output_token);
954 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
955 gensec_gssapi_state->sasl_state = STAGE_DONE;
957 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
958 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
959 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
960 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
962 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographic protection\n"));
969 uint8_t maxlength_proposed[4];
970 uint8_t security_supported = 0x0;
973 /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
974 if (in.length != 0) {
975 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
978 /* Give the client some idea what we will support */
980 RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
981 /* first byte is the proposed security */
982 maxlength_proposed[0] = '\0';
984 gensec_gssapi_state->sasl_protection = 0;
985 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
986 security_supported |= NEG_SEAL;
988 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
989 security_supported |= NEG_SIGN;
991 if (security_supported == 0) {
992 /* If we don't support anything, this must be 0 */
993 RSIVAL(maxlength_proposed, 0, 0x0);
996 /* TODO: We may not wish to support this */
997 security_supported |= NEG_NONE;
998 maxlength_proposed[0] = security_supported;
1000 input_token.value = maxlength_proposed;
1001 input_token.length = sizeof(maxlength_proposed);
1003 maj_stat = gss_wrap(&min_stat,
1004 gensec_gssapi_state->gssapi_context,
1010 if (GSS_ERROR(maj_stat)) {
1011 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
1012 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1013 return NT_STATUS_ACCESS_DENIED;
1016 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
1017 gss_release_buffer(&min_stat, &output_token);
1019 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
1020 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1023 return NT_STATUS_INVALID_PARAMETER;
1027 /* This is s server-only stage */
1028 case STAGE_SASL_SSF_ACCEPT:
1030 uint8_t maxlength_accepted[4];
1031 uint8_t security_accepted;
1033 gss_qop_t qop_state;
1034 input_token.length = in.length;
1035 input_token.value = in.data;
1037 maj_stat = gss_unwrap(&min_stat,
1038 gensec_gssapi_state->gssapi_context,
1043 if (GSS_ERROR(maj_stat)) {
1044 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
1045 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1046 return NT_STATUS_ACCESS_DENIED;
1049 if (output_token.length < 4) {
1050 gss_release_buffer(&min_stat, &output_token);
1051 return NT_STATUS_INVALID_PARAMETER;
1054 memcpy(maxlength_accepted, output_token.value, 4);
1055 gss_release_buffer(&min_stat, &output_token);
1057 /* first byte is the proposed security */
1058 security_accepted = maxlength_accepted[0];
1059 maxlength_accepted[0] = '\0';
1061 /* Rest is the proposed max wrap length */
1062 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0),
1063 gensec_gssapi_state->max_wrap_buf_size);
1065 gensec_gssapi_state->sasl_protection = 0;
1066 if (security_accepted & NEG_SEAL) {
1067 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1068 DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
1069 return NT_STATUS_ACCESS_DENIED;
1071 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
1073 if (security_accepted & NEG_SIGN) {
1074 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1075 DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
1076 return NT_STATUS_ACCESS_DENIED;
1078 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
1080 if (security_accepted & NEG_NONE) {
1081 gensec_gssapi_state->sasl_protection |= NEG_NONE;
1084 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
1085 gensec_gssapi_state->sasl_state = STAGE_DONE;
1086 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1087 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
1088 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1089 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
1091 DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
1094 *out = data_blob(NULL, 0);
1095 return NT_STATUS_OK;
1098 return NT_STATUS_INVALID_PARAMETER;
1102 struct gensec_gssapi_update_state {
1107 static struct tevent_req *gensec_gssapi_update_send(TALLOC_CTX *mem_ctx,
1108 struct tevent_context *ev,
1109 struct gensec_security *gensec_security,
1112 struct tevent_req *req = NULL;
1113 struct gensec_gssapi_update_state *state = NULL;
1116 req = tevent_req_create(mem_ctx, &state,
1117 struct gensec_gssapi_update_state);
1122 status = gensec_gssapi_update_internal(gensec_security,
1125 state->status = status;
1126 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1127 tevent_req_done(req);
1128 return tevent_req_post(req, ev);
1130 if (tevent_req_nterror(req, status)) {
1131 return tevent_req_post(req, ev);
1134 tevent_req_done(req);
1135 return tevent_req_post(req, ev);
1138 static NTSTATUS gensec_gssapi_update_recv(struct tevent_req *req,
1139 TALLOC_CTX *out_mem_ctx,
1142 struct gensec_gssapi_update_state *state =
1143 tevent_req_data(req,
1144 struct gensec_gssapi_update_state);
1147 *out = data_blob_null;
1149 if (tevent_req_is_nterror(req, &status)) {
1150 tevent_req_received(req);
1155 talloc_steal(out_mem_ctx, state->out.data);
1156 status = state->status;
1157 tevent_req_received(req);
1161 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
1162 TALLOC_CTX *mem_ctx,
1163 const DATA_BLOB *in,
1166 struct gensec_gssapi_state *gensec_gssapi_state
1167 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1168 OM_uint32 maj_stat, min_stat;
1169 gss_buffer_desc input_token, output_token;
1171 input_token.length = in->length;
1172 input_token.value = in->data;
1174 maj_stat = gss_wrap(&min_stat,
1175 gensec_gssapi_state->gssapi_context,
1176 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1181 if (GSS_ERROR(maj_stat)) {
1182 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
1183 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1184 return NT_STATUS_ACCESS_DENIED;
1187 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1188 gss_release_buffer(&min_stat, &output_token);
1190 if (gensec_gssapi_state->sasl) {
1191 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1192 if (max_wrapped_size < out->length) {
1193 DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
1194 (unsigned)in->length,
1195 (unsigned)out->length,
1196 (unsigned int)max_wrapped_size));
1197 return NT_STATUS_INVALID_PARAMETER;
1201 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1203 return NT_STATUS_ACCESS_DENIED;
1205 return NT_STATUS_OK;
1208 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
1209 TALLOC_CTX *mem_ctx,
1210 const DATA_BLOB *in,
1213 struct gensec_gssapi_state *gensec_gssapi_state
1214 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1215 OM_uint32 maj_stat, min_stat;
1216 gss_buffer_desc input_token, output_token;
1218 gss_qop_t qop_state;
1219 input_token.length = in->length;
1220 input_token.value = in->data;
1222 if (gensec_gssapi_state->sasl) {
1223 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1224 if (max_wrapped_size < in->length) {
1225 DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
1226 return NT_STATUS_INVALID_PARAMETER;
1231 * FIXME: input_message_buffer is marked const, but gss_unwrap() may
1232 * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()).
1234 maj_stat = gss_unwrap(&min_stat,
1235 gensec_gssapi_state->gssapi_context,
1240 if (GSS_ERROR(maj_stat)) {
1241 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n",
1242 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1243 return NT_STATUS_ACCESS_DENIED;
1246 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1247 gss_release_buffer(&min_stat, &output_token);
1249 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1251 return NT_STATUS_ACCESS_DENIED;
1253 return NT_STATUS_OK;
1256 /* Find out the maximum input size negotiated on this connection */
1258 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security)
1260 struct gensec_gssapi_state *gensec_gssapi_state
1261 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1262 OM_uint32 maj_stat, min_stat;
1263 OM_uint32 max_input_size;
1265 maj_stat = gss_wrap_size_limit(&min_stat,
1266 gensec_gssapi_state->gssapi_context,
1267 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1269 gensec_gssapi_state->max_wrap_buf_size,
1271 if (GSS_ERROR(maj_stat)) {
1272 TALLOC_CTX *mem_ctx = talloc_new(NULL);
1273 DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
1274 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1275 talloc_free(mem_ctx);
1279 return max_input_size;
1282 /* Find out the maximum output size negotiated on this connection */
1283 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security)
1285 struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
1286 return gensec_gssapi_state->max_wrap_buf_size;
1289 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
1290 TALLOC_CTX *mem_ctx,
1291 uint8_t *data, size_t length,
1292 const uint8_t *whole_pdu, size_t pdu_length,
1295 struct gensec_gssapi_state *gensec_gssapi_state
1296 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1297 bool hdr_signing = false;
1298 size_t sig_size = 0;
1301 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1305 sig_size = gensec_gssapi_sig_size(gensec_security, length);
1307 status = gssapi_seal_packet(gensec_gssapi_state->gssapi_context,
1308 gensec_gssapi_state->gss_oid,
1309 hdr_signing, sig_size,
1311 whole_pdu, pdu_length,
1313 if (!NT_STATUS_IS_OK(status)) {
1314 DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu,"
1315 "data=%zu,pdu=%zu) failed: %s\n",
1316 hdr_signing, sig_size, length, pdu_length,
1317 nt_errstr(status)));
1321 return NT_STATUS_OK;
1324 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
1325 uint8_t *data, size_t length,
1326 const uint8_t *whole_pdu, size_t pdu_length,
1327 const DATA_BLOB *sig)
1329 struct gensec_gssapi_state *gensec_gssapi_state
1330 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1331 bool hdr_signing = false;
1334 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1338 status = gssapi_unseal_packet(gensec_gssapi_state->gssapi_context,
1339 gensec_gssapi_state->gss_oid,
1342 whole_pdu, pdu_length,
1344 if (!NT_STATUS_IS_OK(status)) {
1345 DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu,"
1346 "data=%zu,pdu=%zu) failed: %s\n",
1347 hdr_signing, sig->length, length, pdu_length,
1348 nt_errstr(status)));
1352 return NT_STATUS_OK;
1355 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
1356 TALLOC_CTX *mem_ctx,
1357 const uint8_t *data, size_t length,
1358 const uint8_t *whole_pdu, size_t pdu_length,
1361 struct gensec_gssapi_state *gensec_gssapi_state
1362 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1363 bool hdr_signing = false;
1366 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1370 status = gssapi_sign_packet(gensec_gssapi_state->gssapi_context,
1371 gensec_gssapi_state->gss_oid,
1374 whole_pdu, pdu_length,
1376 if (!NT_STATUS_IS_OK(status)) {
1377 DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
1378 "data=%zu,pdu=%zu) failed: %s\n",
1379 hdr_signing, length, pdu_length,
1380 nt_errstr(status)));
1384 return NT_STATUS_OK;
1387 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
1388 const uint8_t *data, size_t length,
1389 const uint8_t *whole_pdu, size_t pdu_length,
1390 const DATA_BLOB *sig)
1392 struct gensec_gssapi_state *gensec_gssapi_state
1393 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1394 bool hdr_signing = false;
1397 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1401 status = gssapi_check_packet(gensec_gssapi_state->gssapi_context,
1402 gensec_gssapi_state->gss_oid,
1405 whole_pdu, pdu_length,
1407 if (!NT_STATUS_IS_OK(status)) {
1408 DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu,"
1409 "data=%zu,pdu=%zu) failed: %s\n",
1410 hdr_signing, sig->length, length, pdu_length,
1411 nt_errstr(status)));
1415 return NT_STATUS_OK;
1418 /* Try to figure out what features we actually got on the connection */
1419 static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
1422 struct gensec_gssapi_state *gensec_gssapi_state
1423 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1424 if (feature & GENSEC_FEATURE_SIGN) {
1425 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1426 if (gensec_gssapi_state->sasl
1427 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1428 return ((gensec_gssapi_state->sasl_protection & NEG_SIGN)
1429 && (gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG));
1431 return gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG;
1433 if (feature & GENSEC_FEATURE_SEAL) {
1434 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1435 if (gensec_gssapi_state->sasl
1436 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1437 return ((gensec_gssapi_state->sasl_protection & NEG_SEAL)
1438 && (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG));
1440 return gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG;
1442 if (feature & GENSEC_FEATURE_SESSION_KEY) {
1443 /* Only for GSSAPI/Krb5 */
1444 if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1449 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1450 return gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE;
1452 if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1456 if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
1460 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1463 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1467 status = gssapi_get_session_key(gensec_gssapi_state,
1468 gensec_gssapi_state->gssapi_context, NULL, &keytype);
1470 * We should do a proper sig on the mechListMic unless
1471 * we know we have to be backwards compatible with
1472 * earlier windows versions.
1474 * Negotiating a non-krb5
1475 * mech for example should be regarded as having
1478 if (NT_STATUS_IS_OK(status)) {
1480 case ENCTYPE_DES_CBC_CRC:
1481 case ENCTYPE_DES_CBC_MD5:
1482 case ENCTYPE_ARCFOUR_HMAC:
1483 case ENCTYPE_DES3_CBC_SHA1:
1489 /* We can always do async (rather than strict request/reply) packets. */
1490 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1493 if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1499 static NTTIME gensec_gssapi_expire_time(struct gensec_security *gensec_security)
1501 struct gensec_gssapi_state *gensec_gssapi_state =
1502 talloc_get_type_abort(gensec_security->private_data,
1503 struct gensec_gssapi_state);
1505 return gensec_gssapi_state->expire_time;
1509 * Extract the 'session key' needed by SMB signing and ncacn_np
1510 * (for encrypting some passwords).
1512 * This breaks all the abstractions, but what do you expect...
1514 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
1515 TALLOC_CTX *mem_ctx,
1516 DATA_BLOB *session_key)
1518 struct gensec_gssapi_state *gensec_gssapi_state
1519 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1520 return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
1523 /* Get some basic (and authorization) information about the user on
1524 * this session. This uses either the PAC (if present) or a local
1525 * database lookup */
1526 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
1527 TALLOC_CTX *mem_ctx,
1528 struct auth_session_info **_session_info)
1531 TALLOC_CTX *tmp_ctx;
1532 struct gensec_gssapi_state *gensec_gssapi_state
1533 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1534 struct auth_session_info *session_info = NULL;
1535 OM_uint32 maj_stat, min_stat;
1536 DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1538 gss_buffer_desc name_token;
1539 char *principal_string;
1541 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
1542 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1544 maj_stat = gss_display_name (&min_stat,
1545 gensec_gssapi_state->client_name,
1548 if (GSS_ERROR(maj_stat)) {
1549 DEBUG(1, ("GSS display_name failed: %s\n",
1550 gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1551 talloc_free(tmp_ctx);
1552 return NT_STATUS_FOOBAR;
1555 principal_string = talloc_strndup(tmp_ctx,
1556 (const char *)name_token.value,
1559 gss_release_buffer(&min_stat, &name_token);
1561 if (!principal_string) {
1562 talloc_free(tmp_ctx);
1563 return NT_STATUS_NO_MEMORY;
1566 nt_status = gssapi_obtain_pac_blob(tmp_ctx, gensec_gssapi_state->gssapi_context,
1567 gensec_gssapi_state->client_name,
1570 /* IF we have the PAC - otherwise we need to get this
1571 * data from elsewhere - local ldb, or (TODO) lookup of some
1574 if (NT_STATUS_IS_OK(nt_status)) {
1575 pac_blob_ptr = &pac_blob;
1577 nt_status = gensec_generate_session_info_pac(tmp_ctx,
1579 gensec_gssapi_state->smb_krb5_context,
1580 pac_blob_ptr, principal_string,
1581 gensec_get_remote_address(gensec_security),
1583 if (!NT_STATUS_IS_OK(nt_status)) {
1584 talloc_free(tmp_ctx);
1588 nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
1589 if (!NT_STATUS_IS_OK(nt_status)) {
1590 talloc_free(tmp_ctx);
1594 if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
1595 gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
1596 krb5_error_code ret;
1597 const char *error_string;
1599 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1602 * Create anonymous credentials for now.
1604 * We will update them with the provided client gss creds.
1606 session_info->credentials = cli_credentials_init_anon(session_info);
1607 if (session_info->credentials == NULL) {
1608 talloc_free(tmp_ctx);
1609 return NT_STATUS_NO_MEMORY;
1612 ret = cli_credentials_set_client_gss_creds(session_info->credentials,
1613 gensec_security->settings->lp_ctx,
1614 gensec_gssapi_state->delegated_cred_handle,
1615 CRED_SPECIFIED, &error_string);
1617 talloc_free(tmp_ctx);
1618 DEBUG(2,("Failed to get gss creds: %s\n", error_string));
1619 return NT_STATUS_NO_MEMORY;
1622 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1623 cli_credentials_set_kerberos_state(session_info->credentials,
1624 CRED_USE_KERBEROS_REQUIRED,
1627 /* It has been taken from this place... */
1628 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1630 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1633 *_session_info = talloc_steal(mem_ctx, session_info);
1634 talloc_free(tmp_ctx);
1636 return NT_STATUS_OK;
1639 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
1641 struct gensec_gssapi_state *gensec_gssapi_state
1642 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1645 if (gensec_gssapi_state->sig_size > 0) {
1646 return gensec_gssapi_state->sig_size;
1649 sig_size = gssapi_get_sig_size(gensec_gssapi_state->gssapi_context,
1650 gensec_gssapi_state->gss_oid,
1651 gensec_gssapi_state->gss_got_flags,
1654 gensec_gssapi_state->sig_size = sig_size;
1655 return gensec_gssapi_state->sig_size;
1658 static const char *gensec_gssapi_final_auth_type(struct gensec_security *gensec_security)
1660 struct gensec_gssapi_state *gensec_gssapi_state
1661 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1662 /* Only return the string for GSSAPI/Krb5 */
1663 if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1665 return GENSEC_FINAL_AUTH_TYPE_KRB5;
1667 return "gensec_gssapi: UNKNOWN MECH";
1671 static const char *gensec_gssapi_krb5_oids[] = {
1672 GENSEC_OID_KERBEROS5_OLD,
1673 GENSEC_OID_KERBEROS5,
1677 static const char *gensec_gssapi_spnego_oids[] = {
1682 /* As a server, this could in theory accept any GSSAPI mech */
1683 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1684 .name = "gssapi_spnego",
1685 .sasl_name = "GSS-SPNEGO",
1686 .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
1687 .oid = gensec_gssapi_spnego_oids,
1688 .client_start = gensec_gssapi_client_start,
1689 .server_start = gensec_gssapi_server_start,
1690 .magic = gensec_magic_check_krb5_oid,
1691 .update_send = gensec_gssapi_update_send,
1692 .update_recv = gensec_gssapi_update_recv,
1693 .session_key = gensec_gssapi_session_key,
1694 .session_info = gensec_gssapi_session_info,
1695 .sign_packet = gensec_gssapi_sign_packet,
1696 .check_packet = gensec_gssapi_check_packet,
1697 .seal_packet = gensec_gssapi_seal_packet,
1698 .unseal_packet = gensec_gssapi_unseal_packet,
1699 .max_input_size = gensec_gssapi_max_input_size,
1700 .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1701 .wrap = gensec_gssapi_wrap,
1702 .unwrap = gensec_gssapi_unwrap,
1703 .have_feature = gensec_gssapi_have_feature,
1704 .expire_time = gensec_gssapi_expire_time,
1705 .final_auth_type = gensec_gssapi_final_auth_type,
1708 .priority = GENSEC_GSSAPI
1711 /* As a server, this could in theory accept any GSSAPI mech */
1712 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1713 .name = "gssapi_krb5",
1714 .auth_type = DCERPC_AUTH_TYPE_KRB5,
1715 .oid = gensec_gssapi_krb5_oids,
1716 .client_start = gensec_gssapi_client_start,
1717 .server_start = gensec_gssapi_server_start,
1718 .magic = gensec_magic_check_krb5_oid,
1719 .update_send = gensec_gssapi_update_send,
1720 .update_recv = gensec_gssapi_update_recv,
1721 .session_key = gensec_gssapi_session_key,
1722 .session_info = gensec_gssapi_session_info,
1723 .sig_size = gensec_gssapi_sig_size,
1724 .sign_packet = gensec_gssapi_sign_packet,
1725 .check_packet = gensec_gssapi_check_packet,
1726 .seal_packet = gensec_gssapi_seal_packet,
1727 .unseal_packet = gensec_gssapi_unseal_packet,
1728 .max_input_size = gensec_gssapi_max_input_size,
1729 .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1730 .wrap = gensec_gssapi_wrap,
1731 .unwrap = gensec_gssapi_unwrap,
1732 .have_feature = gensec_gssapi_have_feature,
1733 .expire_time = gensec_gssapi_expire_time,
1734 .final_auth_type = gensec_gssapi_final_auth_type,
1737 .priority = GENSEC_GSSAPI
1740 /* As a server, this could in theory accept any GSSAPI mech */
1741 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1742 .name = "gssapi_krb5_sasl",
1743 .sasl_name = "GSSAPI",
1744 .client_start = gensec_gssapi_sasl_client_start,
1745 .server_start = gensec_gssapi_sasl_server_start,
1746 .update_send = gensec_gssapi_update_send,
1747 .update_recv = gensec_gssapi_update_recv,
1748 .session_key = gensec_gssapi_session_key,
1749 .session_info = gensec_gssapi_session_info,
1750 .max_input_size = gensec_gssapi_max_input_size,
1751 .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1752 .wrap = gensec_gssapi_wrap,
1753 .unwrap = gensec_gssapi_unwrap,
1754 .have_feature = gensec_gssapi_have_feature,
1755 .expire_time = gensec_gssapi_expire_time,
1756 .final_auth_type = gensec_gssapi_final_auth_type,
1759 .priority = GENSEC_GSSAPI
1762 _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *ctx)
1766 ret = gensec_register(ctx, &gensec_gssapi_spnego_security_ops);
1767 if (!NT_STATUS_IS_OK(ret)) {
1768 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1769 gensec_gssapi_spnego_security_ops.name));
1773 ret = gensec_register(ctx, &gensec_gssapi_krb5_security_ops);
1774 if (!NT_STATUS_IS_OK(ret)) {
1775 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1776 gensec_gssapi_krb5_security_ops.name));
1780 ret = gensec_register(ctx, &gensec_gssapi_sasl_krb5_security_ops);
1781 if (!NT_STATUS_IS_OK(ret)) {
1782 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1783 gensec_gssapi_sasl_krb5_security_ops.name));