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/>.
25 #include "lib/events/events.h"
26 #include "system/kerberos.h"
27 #include "system/gssapi.h"
28 #include "auth/kerberos/kerberos.h"
29 #include "librpc/gen_ndr/krb5pac.h"
30 #include "auth/auth.h"
32 #include "auth/auth_sam.h"
33 #include "librpc/gen_ndr/dcerpc.h"
34 #include "auth/credentials/credentials.h"
35 #include "auth/credentials/credentials_krb5.h"
36 #include "auth/gensec/gensec.h"
37 #include "auth/gensec/gensec_internal.h"
38 #include "auth/gensec/gensec_proto.h"
39 #include "auth/gensec/gensec_toplevel_proto.h"
40 #include "param/param.h"
41 #include "auth/session_proto.h"
42 #include "gensec_gssapi.h"
43 #include "lib/util/util_net.h"
44 #include "auth/kerberos/pac_utils.h"
46 #ifndef gss_mech_spnego
47 gss_OID_desc spnego_mech_oid_desc =
48 { 6, discard_const_p(void, "\x2b\x06\x01\x05\x05\x02") };
49 #define gss_mech_spnego (&spnego_mech_oid_desc)
52 _PUBLIC_ NTSTATUS gensec_gssapi_init(void);
54 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
55 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
57 static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
61 if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
62 gss_release_cred(&min_stat,
63 &gensec_gssapi_state->delegated_cred_handle);
66 if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
67 gss_delete_sec_context(&min_stat,
68 &gensec_gssapi_state->gssapi_context,
72 if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
73 gss_release_name(&min_stat,
74 &gensec_gssapi_state->server_name);
76 if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
77 gss_release_name(&min_stat,
78 &gensec_gssapi_state->client_name);
81 if (gensec_gssapi_state->lucid) {
82 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
88 static NTSTATUS gensec_gssapi_init_lucid(struct gensec_gssapi_state *gensec_gssapi_state)
90 OM_uint32 maj_stat, min_stat;
92 if (gensec_gssapi_state->lucid) {
96 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
97 &gensec_gssapi_state->gssapi_context,
99 (void **)&gensec_gssapi_state->lucid);
100 if (maj_stat != GSS_S_COMPLETE) {
101 DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
102 gssapi_error_string(gensec_gssapi_state,
104 gensec_gssapi_state->gss_oid)));
105 return NT_STATUS_INTERNAL_ERROR;
108 if (gensec_gssapi_state->lucid->version != 1) {
109 DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
110 gensec_gssapi_state->lucid->version));
111 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
112 gensec_gssapi_state->lucid = NULL;
113 return NT_STATUS_INTERNAL_ERROR;
119 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
121 struct gensec_gssapi_state *gensec_gssapi_state;
125 gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
126 if (!gensec_gssapi_state) {
127 return NT_STATUS_NO_MEMORY;
130 gensec_security->private_data = gensec_gssapi_state;
132 gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
134 /* TODO: Fill in channel bindings */
135 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
137 gensec_gssapi_state->server_name = GSS_C_NO_NAME;
138 gensec_gssapi_state->client_name = GSS_C_NO_NAME;
140 gensec_gssapi_state->gss_want_flags = 0;
141 gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
143 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
144 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG;
146 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
147 gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG;
149 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", true)) {
150 gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG;
152 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
153 gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG;
155 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
156 gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
159 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
160 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
162 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
163 gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
164 gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG;
166 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
167 gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE;
170 gensec_gssapi_state->gss_got_flags = 0;
172 switch (gensec_security->ops->auth_type) {
173 case DCERPC_AUTH_TYPE_SPNEGO:
174 gensec_gssapi_state->gss_oid = gss_mech_spnego;
176 case DCERPC_AUTH_TYPE_KRB5:
178 gensec_gssapi_state->gss_oid =
179 discard_const_p(void, gss_mech_krb5);
183 ret = smb_krb5_init_context(gensec_gssapi_state,
184 gensec_security->settings->lp_ctx,
185 &gensec_gssapi_state->smb_krb5_context);
187 DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n",
188 error_message(ret)));
189 talloc_free(gensec_gssapi_state);
190 return NT_STATUS_INTERNAL_ERROR;
193 gensec_gssapi_state->client_cred = NULL;
194 gensec_gssapi_state->server_cred = NULL;
196 gensec_gssapi_state->lucid = NULL;
198 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
200 gensec_gssapi_state->sasl = false;
201 gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
202 gensec_gssapi_state->sasl_protection = 0;
204 gensec_gssapi_state->max_wrap_buf_size
205 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
206 gensec_gssapi_state->gss_exchange_count = 0;
207 gensec_gssapi_state->sig_size = 0;
209 talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
211 #ifdef SAMBA4_USES_HEIMDAL
212 realm = lpcfg_realm(gensec_security->settings->lp_ctx);
214 ret = gsskrb5_set_default_realm(realm);
216 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n"));
217 talloc_free(gensec_gssapi_state);
218 return NT_STATUS_INTERNAL_ERROR;
222 /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
223 ret = gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security->settings, "krb5", "set_dns_canonicalize", false));
225 DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n"));
226 talloc_free(gensec_gssapi_state);
227 return NT_STATUS_INTERNAL_ERROR;
233 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
237 struct gensec_gssapi_state *gensec_gssapi_state;
238 struct cli_credentials *machine_account;
239 struct gssapi_creds_container *gcc;
241 nt_status = gensec_gssapi_start(gensec_security);
242 if (!NT_STATUS_IS_OK(nt_status)) {
246 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
248 machine_account = gensec_get_credentials(gensec_security);
250 if (!machine_account) {
251 DEBUG(3, ("No machine account credentials specified\n"));
252 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
254 ret = cli_credentials_get_server_gss_creds(machine_account,
255 gensec_security->settings->lp_ctx, &gcc);
257 DEBUG(1, ("Aquiring acceptor credentials failed: %s\n",
258 error_message(ret)));
259 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
263 gensec_gssapi_state->server_cred = gcc;
268 static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
271 struct gensec_gssapi_state *gensec_gssapi_state;
272 nt_status = gensec_gssapi_server_start(gensec_security);
274 if (NT_STATUS_IS_OK(nt_status)) {
275 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
276 gensec_gssapi_state->sasl = true;
281 static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security,
282 struct tevent_context *ev)
284 struct gensec_gssapi_state *gensec_gssapi_state;
285 struct gssapi_creds_container *gcc;
286 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
287 const char *error_string;
290 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
292 /* Only run this the first time the update() call is made */
293 if (gensec_gssapi_state->client_cred) {
297 ret = cli_credentials_get_client_gss_creds(creds,
299 gensec_security->settings->lp_ctx, &gcc, &error_string);
304 DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
305 return NT_STATUS_INVALID_PARAMETER;
306 case KRB5KDC_ERR_PREAUTH_FAILED:
307 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
308 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
309 DEBUG(1, ("Wrong username or password: %s\n", error_string));
310 return NT_STATUS_LOGON_FAILURE;
311 case KRB5KDC_ERR_CLIENT_REVOKED:
312 DEBUG(1, ("Account locked out: %s\n", error_string));
313 return NT_STATUS_ACCOUNT_LOCKED_OUT;
314 case KRB5_KDC_UNREACH:
315 DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
316 return NT_STATUS_NO_LOGON_SERVERS;
317 case KRB5_CC_NOTFOUND:
319 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));
320 return NT_STATUS_TIME_DIFFERENCE_AT_DC;
322 DEBUG(1, ("Aquiring initiator credentials failed: %s\n", error_string));
323 return NT_STATUS_UNSUCCESSFUL;
326 gensec_gssapi_state->client_cred = gcc;
327 if (!talloc_reference(gensec_gssapi_state, gcc)) {
328 return NT_STATUS_NO_MEMORY;
334 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
336 struct gensec_gssapi_state *gensec_gssapi_state;
337 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
339 gss_buffer_desc name_token;
341 OM_uint32 maj_stat, min_stat;
342 const char *hostname = gensec_get_target_hostname(gensec_security);
345 DEBUG(3, ("No hostname for target computer passed in, cannot use kerberos for this connection\n"));
346 return NT_STATUS_INVALID_PARAMETER;
348 if (is_ipaddress(hostname)) {
349 DEBUG(2, ("Cannot do GSSAPI to an IP address\n"));
350 return NT_STATUS_INVALID_PARAMETER;
352 if (strcmp(hostname, "localhost") == 0) {
353 DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n"));
354 return NT_STATUS_INVALID_PARAMETER;
357 nt_status = gensec_gssapi_start(gensec_security);
358 if (!NT_STATUS_IS_OK(nt_status)) {
362 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
364 if (cli_credentials_get_impersonate_principal(creds)) {
365 gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
368 gensec_gssapi_state->target_principal = gensec_get_target_principal(gensec_security);
369 if (gensec_gssapi_state->target_principal) {
370 name_type = GSS_C_NULL_OID;
372 gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%s@%s",
373 gensec_get_target_service(gensec_security),
374 hostname, lpcfg_realm(gensec_security->settings->lp_ctx));
376 name_type = GSS_C_NT_USER_NAME;
378 name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal);
379 name_token.length = strlen(gensec_gssapi_state->target_principal);
382 maj_stat = gss_import_name (&min_stat,
385 &gensec_gssapi_state->server_name);
387 DEBUG(2, ("GSS Import name of %s failed: %s\n",
388 (char *)name_token.value,
389 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
390 return NT_STATUS_INVALID_PARAMETER;
396 static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
399 struct gensec_gssapi_state *gensec_gssapi_state;
400 nt_status = gensec_gssapi_client_start(gensec_security);
402 if (NT_STATUS_IS_OK(nt_status)) {
403 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
404 gensec_gssapi_state->sasl = true;
411 * Next state function for the GSSAPI GENSEC mechanism
413 * @param gensec_gssapi_state GSSAPI State
414 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
415 * @param in The request, as a DATA_BLOB
416 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
417 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
418 * or NT_STATUS_OK if the user is authenticated.
421 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
422 TALLOC_CTX *out_mem_ctx,
423 struct tevent_context *ev,
424 const DATA_BLOB in, DATA_BLOB *out)
426 struct gensec_gssapi_state *gensec_gssapi_state
427 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
428 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
429 OM_uint32 maj_stat, min_stat;
431 gss_buffer_desc input_token = { 0, NULL };
432 gss_buffer_desc output_token = { 0, NULL };
434 gss_OID gss_oid_p = NULL;
435 OM_uint32 time_req = 0;
436 OM_uint32 time_rec = 0;
439 time_req = gensec_setting_int(gensec_security->settings,
440 "gensec_gssapi", "requested_life_time",
443 input_token.length = in.length;
444 input_token.value = in.data;
446 switch (gensec_gssapi_state->sasl_state) {
449 switch (gensec_security->gensec_role) {
452 #ifdef SAMBA4_USES_HEIMDAL
453 struct gsskrb5_send_to_kdc send_to_kdc;
457 nt_status = gensec_gssapi_client_creds(gensec_security, ev);
458 if (!NT_STATUS_IS_OK(nt_status)) {
462 #ifdef SAMBA4_USES_HEIMDAL
463 send_to_kdc.func = smb_krb5_send_and_recv_func;
464 send_to_kdc.ptr = ev;
466 min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
468 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
469 return NT_STATUS_INTERNAL_ERROR;
472 maj_stat = gss_init_sec_context(&min_stat,
473 gensec_gssapi_state->client_cred->creds,
474 &gensec_gssapi_state->gssapi_context,
475 gensec_gssapi_state->server_name,
476 gensec_gssapi_state->gss_oid,
477 gensec_gssapi_state->gss_want_flags,
479 gensec_gssapi_state->input_chan_bindings,
483 &gensec_gssapi_state->gss_got_flags, /* ret flags */
486 gensec_gssapi_state->gss_oid = gss_oid_p;
489 #ifdef SAMBA4_USES_HEIMDAL
490 send_to_kdc.func = smb_krb5_send_and_recv_func;
491 send_to_kdc.ptr = NULL;
493 ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
495 DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
496 return NT_STATUS_INTERNAL_ERROR;
503 maj_stat = gss_accept_sec_context(&min_stat,
504 &gensec_gssapi_state->gssapi_context,
505 gensec_gssapi_state->server_cred->creds,
507 gensec_gssapi_state->input_chan_bindings,
508 &gensec_gssapi_state->client_name,
511 &gensec_gssapi_state->gss_got_flags,
513 &gensec_gssapi_state->delegated_cred_handle);
515 gensec_gssapi_state->gss_oid = gss_oid_p;
520 return NT_STATUS_INVALID_PARAMETER;
524 gensec_gssapi_state->gss_exchange_count++;
526 if (maj_stat == GSS_S_COMPLETE) {
527 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
528 gss_release_buffer(&min_stat2, &output_token);
530 if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
531 gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
532 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
534 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
537 tv = timeval_current_ofs(time_rec, 0);
538 gensec_gssapi_state->expire_time = timeval_to_nttime(&tv);
540 /* We may have been invoked as SASL, so there
541 * is more work to do */
542 if (gensec_gssapi_state->sasl) {
543 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
544 return NT_STATUS_MORE_PROCESSING_REQUIRED;
546 gensec_gssapi_state->sasl_state = STAGE_DONE;
548 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
549 DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
550 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
551 DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
553 DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
558 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
559 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
560 gss_release_buffer(&min_stat2, &output_token);
562 return NT_STATUS_MORE_PROCESSING_REQUIRED;
563 } else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
564 gss_cred_id_t creds = NULL;
566 gss_buffer_desc buffer;
567 OM_uint32 lifetime = 0;
568 gss_cred_usage_t usage;
569 const char *role = NULL;
570 DEBUG(0, ("GSS %s Update(krb5)(%d) Update failed, credentials expired during GSSAPI handshake!\n",
572 gensec_gssapi_state->gss_exchange_count));
575 switch (gensec_security->gensec_role) {
577 creds = gensec_gssapi_state->client_cred->creds;
581 creds = gensec_gssapi_state->server_cred->creds;
586 maj_stat = gss_inquire_cred(&min_stat,
588 &name, &lifetime, &usage, NULL);
590 if (maj_stat == GSS_S_COMPLETE) {
591 const char *usage_string = NULL;
594 usage_string = "GSS_C_BOTH";
597 usage_string = "GSS_C_ACCEPT";
600 usage_string = "GSS_C_INITIATE";
603 maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
609 DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n",
610 (int)buffer.length, (int)buffer.length, (char *)buffer.value,
611 lifetime, usage_string));
613 DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n",
614 (int)buffer.length, (int)buffer.length, (char *)buffer.value,
617 gss_release_buffer(&min_stat, &buffer);
618 gss_release_name(&min_stat, &name);
619 } else if (maj_stat != GSS_S_COMPLETE) {
620 DEBUG(0, ("inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
621 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
623 return NT_STATUS_INVALID_PARAMETER;
624 } else if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
627 case KRB5KRB_AP_ERR_TKT_NYV:
628 DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
629 gensec_gssapi_state->target_principal,
630 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
631 return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
632 case KRB5KRB_AP_ERR_TKT_EXPIRED:
633 DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
634 gensec_gssapi_state->target_principal,
635 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
636 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
637 case KRB5_KDC_UNREACH:
638 DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticket to %s: %s\n",
639 gensec_gssapi_state->target_principal,
640 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
641 return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
642 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
643 DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
644 gensec_gssapi_state->target_principal,
645 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
646 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
647 case KRB5KRB_AP_ERR_MSG_TYPE:
648 /* garbage input, possibly from the auto-mech detection */
649 return NT_STATUS_INVALID_PARAMETER;
651 DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
652 gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
653 gensec_gssapi_state->gss_exchange_count,
654 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
655 return NT_STATUS_LOGON_FAILURE;
658 DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
659 gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
660 gensec_gssapi_state->gss_exchange_count,
661 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
662 return NT_STATUS_LOGON_FAILURE;
667 /* These last two stages are only done if we were invoked as SASL */
668 case STAGE_SASL_SSF_NEG:
670 switch (gensec_security->gensec_role) {
673 uint8_t maxlength_proposed[4];
674 uint8_t maxlength_accepted[4];
675 uint8_t security_supported;
678 input_token.length = in.length;
679 input_token.value = in.data;
681 /* As a client, we have just send a
682 * zero-length blob to the server (after the
683 * normal GSSAPI exchange), and it has replied
684 * with it's SASL negotiation */
686 maj_stat = gss_unwrap(&min_stat,
687 gensec_gssapi_state->gssapi_context,
692 if (GSS_ERROR(maj_stat)) {
693 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
694 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
695 return NT_STATUS_ACCESS_DENIED;
698 if (output_token.length < 4) {
699 return NT_STATUS_INVALID_PARAMETER;
702 memcpy(maxlength_proposed, output_token.value, 4);
703 gss_release_buffer(&min_stat, &output_token);
705 /* first byte is the proposed security */
706 security_supported = maxlength_proposed[0];
707 maxlength_proposed[0] = '\0';
709 /* Rest is the proposed max wrap length */
710 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0),
711 gensec_gssapi_state->max_wrap_buf_size);
712 gensec_gssapi_state->sasl_protection = 0;
713 if (security_supported & NEG_SEAL) {
714 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
715 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
718 if (security_supported & NEG_SIGN) {
719 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
720 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
723 if (security_supported & NEG_NONE) {
724 gensec_gssapi_state->sasl_protection |= NEG_NONE;
726 if (gensec_gssapi_state->sasl_protection == 0) {
727 DEBUG(1, ("Remote server does not support unprotected connections\n"));
728 return NT_STATUS_ACCESS_DENIED;
731 /* Send back the negotiated max length */
733 RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
735 maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
737 input_token.value = maxlength_accepted;
738 input_token.length = sizeof(maxlength_accepted);
740 maj_stat = gss_wrap(&min_stat,
741 gensec_gssapi_state->gssapi_context,
747 if (GSS_ERROR(maj_stat)) {
748 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
749 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
750 return NT_STATUS_ACCESS_DENIED;
753 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
754 gss_release_buffer(&min_stat, &output_token);
756 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
757 gensec_gssapi_state->sasl_state = STAGE_DONE;
759 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
760 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
761 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
762 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
764 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographically protection\n"));
771 uint8_t maxlength_proposed[4];
772 uint8_t security_supported = 0x0;
775 /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
776 if (in.length != 0) {
777 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
780 /* Give the client some idea what we will support */
782 RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
783 /* first byte is the proposed security */
784 maxlength_proposed[0] = '\0';
786 gensec_gssapi_state->sasl_protection = 0;
787 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
788 security_supported |= NEG_SEAL;
790 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
791 security_supported |= NEG_SIGN;
793 if (security_supported == 0) {
794 /* If we don't support anything, this must be 0 */
795 RSIVAL(maxlength_proposed, 0, 0x0);
798 /* TODO: We may not wish to support this */
799 security_supported |= NEG_NONE;
800 maxlength_proposed[0] = security_supported;
802 input_token.value = maxlength_proposed;
803 input_token.length = sizeof(maxlength_proposed);
805 maj_stat = gss_wrap(&min_stat,
806 gensec_gssapi_state->gssapi_context,
812 if (GSS_ERROR(maj_stat)) {
813 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
814 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
815 return NT_STATUS_ACCESS_DENIED;
818 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
819 gss_release_buffer(&min_stat, &output_token);
821 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
822 return NT_STATUS_MORE_PROCESSING_REQUIRED;
825 return NT_STATUS_INVALID_PARAMETER;
829 /* This is s server-only stage */
830 case STAGE_SASL_SSF_ACCEPT:
832 uint8_t maxlength_accepted[4];
833 uint8_t security_accepted;
836 input_token.length = in.length;
837 input_token.value = in.data;
839 maj_stat = gss_unwrap(&min_stat,
840 gensec_gssapi_state->gssapi_context,
845 if (GSS_ERROR(maj_stat)) {
846 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
847 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
848 return NT_STATUS_ACCESS_DENIED;
851 if (output_token.length < 4) {
852 return NT_STATUS_INVALID_PARAMETER;
855 memcpy(maxlength_accepted, output_token.value, 4);
856 gss_release_buffer(&min_stat, &output_token);
858 /* first byte is the proposed security */
859 security_accepted = maxlength_accepted[0];
860 maxlength_accepted[0] = '\0';
862 /* Rest is the proposed max wrap length */
863 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0),
864 gensec_gssapi_state->max_wrap_buf_size);
866 gensec_gssapi_state->sasl_protection = 0;
867 if (security_accepted & NEG_SEAL) {
868 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
869 DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
870 return NT_STATUS_ACCESS_DENIED;
872 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
874 if (security_accepted & NEG_SIGN) {
875 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
876 DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
877 return NT_STATUS_ACCESS_DENIED;
879 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
881 if (security_accepted & NEG_NONE) {
882 gensec_gssapi_state->sasl_protection |= NEG_NONE;
885 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
886 gensec_gssapi_state->sasl_state = STAGE_DONE;
887 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
888 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
889 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
890 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
892 DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
895 *out = data_blob(NULL, 0);
899 return NT_STATUS_INVALID_PARAMETER;
903 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
908 struct gensec_gssapi_state *gensec_gssapi_state
909 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
910 OM_uint32 maj_stat, min_stat;
911 gss_buffer_desc input_token, output_token;
913 input_token.length = in->length;
914 input_token.value = in->data;
916 maj_stat = gss_wrap(&min_stat,
917 gensec_gssapi_state->gssapi_context,
918 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
923 if (GSS_ERROR(maj_stat)) {
924 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
925 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
926 return NT_STATUS_ACCESS_DENIED;
929 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
930 gss_release_buffer(&min_stat, &output_token);
932 if (gensec_gssapi_state->sasl) {
933 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
934 if (max_wrapped_size < out->length) {
935 DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
936 (unsigned)in->length,
937 (unsigned)out->length,
938 (unsigned int)max_wrapped_size));
939 return NT_STATUS_INVALID_PARAMETER;
943 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
945 return NT_STATUS_ACCESS_DENIED;
950 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
955 struct gensec_gssapi_state *gensec_gssapi_state
956 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
957 OM_uint32 maj_stat, min_stat;
958 gss_buffer_desc input_token, output_token;
961 input_token.length = in->length;
962 input_token.value = in->data;
964 if (gensec_gssapi_state->sasl) {
965 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
966 if (max_wrapped_size < in->length) {
967 DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
968 return NT_STATUS_INVALID_PARAMETER;
972 maj_stat = gss_unwrap(&min_stat,
973 gensec_gssapi_state->gssapi_context,
978 if (GSS_ERROR(maj_stat)) {
979 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n",
980 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
981 return NT_STATUS_ACCESS_DENIED;
984 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
985 gss_release_buffer(&min_stat, &output_token);
987 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
989 return NT_STATUS_ACCESS_DENIED;
994 /* Find out the maximum input size negotiated on this connection */
996 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security)
998 struct gensec_gssapi_state *gensec_gssapi_state
999 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1000 OM_uint32 maj_stat, min_stat;
1001 OM_uint32 max_input_size;
1003 maj_stat = gss_wrap_size_limit(&min_stat,
1004 gensec_gssapi_state->gssapi_context,
1005 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1007 gensec_gssapi_state->max_wrap_buf_size,
1009 if (GSS_ERROR(maj_stat)) {
1010 TALLOC_CTX *mem_ctx = talloc_new(NULL);
1011 DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
1012 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1013 talloc_free(mem_ctx);
1017 return max_input_size;
1020 /* Find out the maximum output size negotiated on this connection */
1021 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security)
1023 struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
1024 return gensec_gssapi_state->max_wrap_buf_size;
1027 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
1028 TALLOC_CTX *mem_ctx,
1029 uint8_t *data, size_t length,
1030 const uint8_t *whole_pdu, size_t pdu_length,
1033 struct gensec_gssapi_state *gensec_gssapi_state
1034 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1035 OM_uint32 maj_stat, min_stat;
1036 gss_buffer_desc input_token, output_token;
1040 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1041 DEBUG(1, ("gensec_gssapi_seal_packet: "
1042 "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n"));
1043 return NT_STATUS_ACCESS_DENIED;
1046 input_token.length = length;
1047 input_token.value = data;
1049 maj_stat = gss_wrap(&min_stat,
1050 gensec_gssapi_state->gssapi_context,
1051 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1056 if (GSS_ERROR(maj_stat)) {
1057 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap failed: %s\n",
1058 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1059 return NT_STATUS_ACCESS_DENIED;
1062 if (output_token.length < input_token.length) {
1063 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n",
1064 (long)output_token.length, (long)length));
1065 return NT_STATUS_INTERNAL_ERROR;
1067 sig_length = output_token.length - input_token.length;
1069 memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
1070 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
1072 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
1073 dump_data_pw("gensec_gssapi_seal_packet: clear\n", data, length);
1074 dump_data_pw("gensec_gssapi_seal_packet: sealed\n", ((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
1076 gss_release_buffer(&min_stat, &output_token);
1078 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1080 return NT_STATUS_ACCESS_DENIED;
1082 return NT_STATUS_OK;
1085 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
1086 uint8_t *data, size_t length,
1087 const uint8_t *whole_pdu, size_t pdu_length,
1088 const DATA_BLOB *sig)
1090 struct gensec_gssapi_state *gensec_gssapi_state
1091 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1092 OM_uint32 maj_stat, min_stat;
1093 gss_buffer_desc input_token, output_token;
1095 gss_qop_t qop_state;
1098 dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length);
1100 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1101 DEBUG(1, ("gensec_gssapi_unseal_packet: "
1102 "GENSEC_FEATURE_SIGN_PKT_HEADER not supported\n"));
1103 return NT_STATUS_ACCESS_DENIED;
1106 in = data_blob_talloc(gensec_security, NULL, sig->length + length);
1108 memcpy(in.data, sig->data, sig->length);
1109 memcpy(in.data + sig->length, data, length);
1111 input_token.length = in.length;
1112 input_token.value = in.data;
1114 maj_stat = gss_unwrap(&min_stat,
1115 gensec_gssapi_state->gssapi_context,
1120 talloc_free(in.data);
1121 if (GSS_ERROR(maj_stat)) {
1122 char *error_string = gssapi_error_string(NULL, maj_stat, min_stat, gensec_gssapi_state->gss_oid);
1123 DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n",
1125 talloc_free(error_string);
1126 return NT_STATUS_ACCESS_DENIED;
1129 if (output_token.length != length) {
1130 return NT_STATUS_INTERNAL_ERROR;
1133 memcpy(data, output_token.value, length);
1135 gss_release_buffer(&min_stat, &output_token);
1137 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1139 return NT_STATUS_ACCESS_DENIED;
1141 return NT_STATUS_OK;
1144 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
1145 TALLOC_CTX *mem_ctx,
1146 const uint8_t *data, size_t length,
1147 const uint8_t *whole_pdu, size_t pdu_length,
1150 struct gensec_gssapi_state *gensec_gssapi_state
1151 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1152 OM_uint32 maj_stat, min_stat;
1153 gss_buffer_desc input_token, output_token;
1155 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1156 input_token.length = pdu_length;
1157 input_token.value = discard_const_p(uint8_t *, whole_pdu);
1159 input_token.length = length;
1160 input_token.value = discard_const_p(uint8_t *, data);
1163 maj_stat = gss_get_mic(&min_stat,
1164 gensec_gssapi_state->gssapi_context,
1168 if (GSS_ERROR(maj_stat)) {
1169 DEBUG(1, ("GSS GetMic failed: %s\n",
1170 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1171 return NT_STATUS_ACCESS_DENIED;
1174 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
1176 dump_data_pw("gensec_gssapi_sign_packet: sig\n", sig->data, sig->length);
1178 gss_release_buffer(&min_stat, &output_token);
1180 return NT_STATUS_OK;
1183 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
1184 const uint8_t *data, size_t length,
1185 const uint8_t *whole_pdu, size_t pdu_length,
1186 const DATA_BLOB *sig)
1188 struct gensec_gssapi_state *gensec_gssapi_state
1189 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1190 OM_uint32 maj_stat, min_stat;
1191 gss_buffer_desc input_token;
1192 gss_buffer_desc input_message;
1193 gss_qop_t qop_state;
1195 dump_data_pw("gensec_gssapi_check_packet: sig\n", sig->data, sig->length);
1197 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1198 input_message.length = pdu_length;
1199 input_message.value = discard_const(whole_pdu);
1201 input_message.length = length;
1202 input_message.value = discard_const(data);
1205 input_token.length = sig->length;
1206 input_token.value = sig->data;
1208 maj_stat = gss_verify_mic(&min_stat,
1209 gensec_gssapi_state->gssapi_context,
1213 if (GSS_ERROR(maj_stat)) {
1214 char *error_string = gssapi_error_string(NULL, maj_stat, min_stat, gensec_gssapi_state->gss_oid);
1215 DEBUG(1, ("GSS VerifyMic failed: %s\n", error_string));
1216 talloc_free(error_string);
1218 return NT_STATUS_ACCESS_DENIED;
1221 return NT_STATUS_OK;
1224 /* Try to figure out what features we actually got on the connection */
1225 static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
1228 struct gensec_gssapi_state *gensec_gssapi_state
1229 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1230 if (feature & GENSEC_FEATURE_SIGN) {
1231 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1232 if (gensec_gssapi_state->sasl
1233 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1234 return ((gensec_gssapi_state->sasl_protection & NEG_SIGN)
1235 && (gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG));
1237 return gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG;
1239 if (feature & GENSEC_FEATURE_SEAL) {
1240 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1241 if (gensec_gssapi_state->sasl
1242 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1243 return ((gensec_gssapi_state->sasl_protection & NEG_SEAL)
1244 && (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG));
1246 return gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG;
1248 if (feature & GENSEC_FEATURE_SESSION_KEY) {
1249 /* Only for GSSAPI/Krb5 */
1250 if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1255 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1256 return gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE;
1258 if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1262 if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
1266 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1269 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1273 status = gssapi_get_session_key(gensec_gssapi_state,
1274 gensec_gssapi_state->gssapi_context, NULL, &keytype);
1276 * We should do a proper sig on the mechListMic unless
1277 * we know we have to be backwards compatible with
1278 * earlier windows versions.
1280 * Negotiating a non-krb5
1281 * mech for example should be regarded as having
1284 if (NT_STATUS_IS_OK(status)) {
1286 case ENCTYPE_DES_CBC_CRC:
1287 case ENCTYPE_DES_CBC_MD5:
1288 case ENCTYPE_ARCFOUR_HMAC:
1289 case ENCTYPE_DES3_CBC_SHA1:
1295 /* We can always do async (rather than strict request/reply) packets. */
1296 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1299 if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1300 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
1301 /* TODO: implement this using gss_wrap_iov() */
1305 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
1314 static NTTIME gensec_gssapi_expire_time(struct gensec_security *gensec_security)
1316 struct gensec_gssapi_state *gensec_gssapi_state =
1317 talloc_get_type_abort(gensec_security->private_data,
1318 struct gensec_gssapi_state);
1320 return gensec_gssapi_state->expire_time;
1324 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1325 * (for encrypting some passwords).
1327 * This breaks all the abstractions, but what do you expect...
1329 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
1330 TALLOC_CTX *mem_ctx,
1331 DATA_BLOB *session_key)
1333 struct gensec_gssapi_state *gensec_gssapi_state
1334 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1335 return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
1338 /* Get some basic (and authorization) information about the user on
1339 * this session. This uses either the PAC (if present) or a local
1340 * database lookup */
1341 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
1342 TALLOC_CTX *mem_ctx,
1343 struct auth_session_info **_session_info)
1346 TALLOC_CTX *tmp_ctx;
1347 struct gensec_gssapi_state *gensec_gssapi_state
1348 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1349 struct auth_session_info *session_info = NULL;
1350 OM_uint32 maj_stat, min_stat;
1351 DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1353 gss_buffer_desc name_token;
1354 char *principal_string;
1356 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
1357 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1359 maj_stat = gss_display_name (&min_stat,
1360 gensec_gssapi_state->client_name,
1363 if (GSS_ERROR(maj_stat)) {
1364 DEBUG(1, ("GSS display_name failed: %s\n",
1365 gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1366 talloc_free(tmp_ctx);
1367 return NT_STATUS_FOOBAR;
1370 principal_string = talloc_strndup(tmp_ctx,
1371 (const char *)name_token.value,
1374 gss_release_buffer(&min_stat, &name_token);
1376 if (!principal_string) {
1377 talloc_free(tmp_ctx);
1378 return NT_STATUS_NO_MEMORY;
1381 nt_status = gssapi_obtain_pac_blob(tmp_ctx, gensec_gssapi_state->gssapi_context,
1382 gensec_gssapi_state->client_name,
1385 /* IF we have the PAC - otherwise we need to get this
1386 * data from elsewere - local ldb, or (TODO) lookup of some
1389 if (NT_STATUS_IS_OK(nt_status)) {
1390 pac_blob_ptr = &pac_blob;
1392 nt_status = gensec_generate_session_info_pac(tmp_ctx,
1394 gensec_gssapi_state->smb_krb5_context,
1395 pac_blob_ptr, principal_string,
1396 gensec_get_remote_address(gensec_security),
1398 if (!NT_STATUS_IS_OK(nt_status)) {
1399 talloc_free(tmp_ctx);
1403 nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
1404 if (!NT_STATUS_IS_OK(nt_status)) {
1405 talloc_free(tmp_ctx);
1409 if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
1410 gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
1411 krb5_error_code ret;
1412 const char *error_string;
1414 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1415 session_info->credentials = cli_credentials_init(session_info);
1416 if (!session_info->credentials) {
1417 talloc_free(tmp_ctx);
1418 return NT_STATUS_NO_MEMORY;
1421 cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx);
1422 /* Just so we don't segfault trying to get at a username */
1423 cli_credentials_set_anonymous(session_info->credentials);
1425 ret = cli_credentials_set_client_gss_creds(session_info->credentials,
1426 gensec_security->settings->lp_ctx,
1427 gensec_gssapi_state->delegated_cred_handle,
1428 CRED_SPECIFIED, &error_string);
1430 talloc_free(tmp_ctx);
1431 DEBUG(2,("Failed to get gss creds: %s\n", error_string));
1432 return NT_STATUS_NO_MEMORY;
1435 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1436 cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);
1438 /* It has been taken from this place... */
1439 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1441 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1444 *_session_info = talloc_steal(mem_ctx, session_info);
1445 talloc_free(tmp_ctx);
1447 return NT_STATUS_OK;
1450 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
1452 struct gensec_gssapi_state *gensec_gssapi_state
1453 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1456 if (gensec_gssapi_state->sig_size) {
1457 return gensec_gssapi_state->sig_size;
1460 if (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG) {
1461 gensec_gssapi_state->sig_size = 45;
1463 gensec_gssapi_state->sig_size = 37;
1466 status = gensec_gssapi_init_lucid(gensec_gssapi_state);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 return gensec_gssapi_state->sig_size;
1471 if (gensec_gssapi_state->lucid->protocol == 1) {
1472 if (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG) {
1474 * TODO: windows uses 76 here, but we don't know
1475 * gss_wrap works with aes keys yet
1477 gensec_gssapi_state->sig_size = 76;
1479 gensec_gssapi_state->sig_size = 28;
1481 } else if (gensec_gssapi_state->lucid->protocol == 0) {
1482 switch (gensec_gssapi_state->lucid->rfc1964_kd.ctx_key.type) {
1483 case ENCTYPE_DES_CBC_CRC:
1484 case ENCTYPE_ARCFOUR_HMAC:
1485 case ENCTYPE_ARCFOUR_HMAC_EXP:
1486 if (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG) {
1487 gensec_gssapi_state->sig_size = 45;
1489 gensec_gssapi_state->sig_size = 37;
1492 #ifdef SAMBA4_USES_HEIMDAL
1493 case ENCTYPE_OLD_DES3_CBC_SHA1:
1494 if (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG) {
1495 gensec_gssapi_state->sig_size = 57;
1497 gensec_gssapi_state->sig_size = 49;
1504 return gensec_gssapi_state->sig_size;
1507 static const char *gensec_gssapi_krb5_oids[] = {
1508 GENSEC_OID_KERBEROS5_OLD,
1509 GENSEC_OID_KERBEROS5,
1513 static const char *gensec_gssapi_spnego_oids[] = {
1518 /* As a server, this could in theory accept any GSSAPI mech */
1519 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1520 .name = "gssapi_spnego",
1521 .sasl_name = "GSS-SPNEGO",
1522 .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
1523 .oid = gensec_gssapi_spnego_oids,
1524 .client_start = gensec_gssapi_client_start,
1525 .server_start = gensec_gssapi_server_start,
1526 .magic = gensec_magic_check_krb5_oid,
1527 .update = gensec_gssapi_update,
1528 .session_key = gensec_gssapi_session_key,
1529 .session_info = gensec_gssapi_session_info,
1530 .sign_packet = gensec_gssapi_sign_packet,
1531 .check_packet = gensec_gssapi_check_packet,
1532 .seal_packet = gensec_gssapi_seal_packet,
1533 .unseal_packet = gensec_gssapi_unseal_packet,
1534 .wrap = gensec_gssapi_wrap,
1535 .unwrap = gensec_gssapi_unwrap,
1536 .have_feature = gensec_gssapi_have_feature,
1537 .expire_time = gensec_gssapi_expire_time,
1540 .priority = GENSEC_GSSAPI
1543 /* As a server, this could in theory accept any GSSAPI mech */
1544 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1545 .name = "gssapi_krb5",
1546 .auth_type = DCERPC_AUTH_TYPE_KRB5,
1547 .oid = gensec_gssapi_krb5_oids,
1548 .client_start = gensec_gssapi_client_start,
1549 .server_start = gensec_gssapi_server_start,
1550 .magic = gensec_magic_check_krb5_oid,
1551 .update = gensec_gssapi_update,
1552 .session_key = gensec_gssapi_session_key,
1553 .session_info = gensec_gssapi_session_info,
1554 .sig_size = gensec_gssapi_sig_size,
1555 .sign_packet = gensec_gssapi_sign_packet,
1556 .check_packet = gensec_gssapi_check_packet,
1557 .seal_packet = gensec_gssapi_seal_packet,
1558 .unseal_packet = gensec_gssapi_unseal_packet,
1559 .wrap = gensec_gssapi_wrap,
1560 .unwrap = gensec_gssapi_unwrap,
1561 .have_feature = gensec_gssapi_have_feature,
1562 .expire_time = gensec_gssapi_expire_time,
1565 .priority = GENSEC_GSSAPI
1568 /* As a server, this could in theory accept any GSSAPI mech */
1569 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1570 .name = "gssapi_krb5_sasl",
1571 .sasl_name = "GSSAPI",
1572 .client_start = gensec_gssapi_sasl_client_start,
1573 .server_start = gensec_gssapi_sasl_server_start,
1574 .update = gensec_gssapi_update,
1575 .session_key = gensec_gssapi_session_key,
1576 .session_info = gensec_gssapi_session_info,
1577 .max_input_size = gensec_gssapi_max_input_size,
1578 .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1579 .wrap = gensec_gssapi_wrap,
1580 .unwrap = gensec_gssapi_unwrap,
1581 .have_feature = gensec_gssapi_have_feature,
1582 .expire_time = gensec_gssapi_expire_time,
1585 .priority = GENSEC_GSSAPI
1588 _PUBLIC_ NTSTATUS gensec_gssapi_init(void)
1592 ret = gensec_register(&gensec_gssapi_spnego_security_ops);
1593 if (!NT_STATUS_IS_OK(ret)) {
1594 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1595 gensec_gssapi_spnego_security_ops.name));
1599 ret = gensec_register(&gensec_gssapi_krb5_security_ops);
1600 if (!NT_STATUS_IS_OK(ret)) {
1601 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1602 gensec_gssapi_krb5_security_ops.name));
1606 ret = gensec_register(&gensec_gssapi_sasl_krb5_security_ops);
1607 if (!NT_STATUS_IS_OK(ret)) {
1608 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1609 gensec_gssapi_sasl_krb5_security_ops.name));