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 "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/krb5pac.h"
29 #include "auth/auth.h"
30 #include "lib/ldb/include/ldb.h"
31 #include "auth/auth_sam.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/credentials/credentials.h"
34 #include "auth/credentials/credentials_krb5.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/gensec/gensec_proto.h"
37 #include "param/param.h"
38 #include "auth/session_proto.h"
39 #include <gssapi/gssapi.h>
40 #include <gssapi/gssapi_krb5.h>
41 #include <gssapi/gssapi_spnego.h>
42 #include "auth/gensec/gensec_gssapi.h"
44 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
45 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
47 static char *gssapi_error_string(TALLOC_CTX *mem_ctx,
48 OM_uint32 maj_stat, OM_uint32 min_stat,
51 OM_uint32 disp_min_stat, disp_maj_stat;
52 gss_buffer_desc maj_error_message;
53 gss_buffer_desc min_error_message;
54 char *maj_error_string, *min_error_string;
55 OM_uint32 msg_ctx = 0;
59 maj_error_message.value = NULL;
60 min_error_message.value = NULL;
61 maj_error_message.length = 0;
62 min_error_message.length = 0;
64 disp_maj_stat = gss_display_status(&disp_min_stat, maj_stat, GSS_C_GSS_CODE,
65 mech, &msg_ctx, &maj_error_message);
66 disp_maj_stat = gss_display_status(&disp_min_stat, min_stat, GSS_C_MECH_CODE,
67 mech, &msg_ctx, &min_error_message);
69 maj_error_string = talloc_strndup(mem_ctx, (char *)maj_error_message.value, maj_error_message.length);
71 min_error_string = talloc_strndup(mem_ctx, (char *)min_error_message.value, min_error_message.length);
73 ret = talloc_asprintf(mem_ctx, "%s: %s", maj_error_string, min_error_string);
75 talloc_free(maj_error_string);
76 talloc_free(min_error_string);
78 gss_release_buffer(&disp_min_stat, &maj_error_message);
79 gss_release_buffer(&disp_min_stat, &min_error_message);
85 static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
87 OM_uint32 maj_stat, min_stat;
89 if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
90 maj_stat = gss_release_cred(&min_stat,
91 &gensec_gssapi_state->delegated_cred_handle);
94 if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
95 maj_stat = gss_delete_sec_context (&min_stat,
96 &gensec_gssapi_state->gssapi_context,
100 if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
101 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->server_name);
103 if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
104 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
107 if (gensec_gssapi_state->lucid) {
108 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
114 static NTSTATUS gensec_gssapi_init_lucid(struct gensec_gssapi_state *gensec_gssapi_state)
116 OM_uint32 maj_stat, min_stat;
118 if (gensec_gssapi_state->lucid) {
122 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
123 &gensec_gssapi_state->gssapi_context,
125 (void **)&gensec_gssapi_state->lucid);
126 if (maj_stat != GSS_S_COMPLETE) {
127 DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
128 gssapi_error_string(gensec_gssapi_state,
130 gensec_gssapi_state->gss_oid)));
131 return NT_STATUS_INTERNAL_ERROR;
134 if (gensec_gssapi_state->lucid->version != 1) {
135 DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
136 gensec_gssapi_state->lucid->version));
137 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
138 gensec_gssapi_state->lucid = NULL;
139 return NT_STATUS_INTERNAL_ERROR;
145 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
147 struct gensec_gssapi_state *gensec_gssapi_state;
149 struct gsskrb5_send_to_kdc send_to_kdc;
152 gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
153 if (!gensec_gssapi_state) {
154 return NT_STATUS_NO_MEMORY;
157 gensec_gssapi_state->gss_exchange_count = 0;
158 gensec_gssapi_state->max_wrap_buf_size
159 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
161 gensec_gssapi_state->sasl = false;
162 gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
164 gensec_security->private_data = gensec_gssapi_state;
166 gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
167 gensec_gssapi_state->server_name = GSS_C_NO_NAME;
168 gensec_gssapi_state->client_name = GSS_C_NO_NAME;
169 gensec_gssapi_state->lucid = NULL;
171 /* TODO: Fill in channel bindings */
172 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
174 gensec_gssapi_state->want_flags = 0;
175 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
176 gensec_gssapi_state->want_flags |= GSS_C_DELEG_POLICY_FLAG;
178 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
179 gensec_gssapi_state->want_flags |= GSS_C_MUTUAL_FLAG;
181 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", true)) {
182 gensec_gssapi_state->want_flags |= GSS_C_DELEG_FLAG;
184 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
185 gensec_gssapi_state->want_flags |= GSS_C_REPLAY_FLAG;
187 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
188 gensec_gssapi_state->want_flags |= GSS_C_SEQUENCE_FLAG;
191 gensec_gssapi_state->got_flags = 0;
193 gensec_gssapi_state->session_key = data_blob(NULL, 0);
194 gensec_gssapi_state->pac = data_blob(NULL, 0);
196 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
197 gensec_gssapi_state->sig_size = 0;
199 talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
201 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
202 gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
204 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
205 gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
207 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
208 gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
211 switch (gensec_security->ops->auth_type) {
212 case DCERPC_AUTH_TYPE_SPNEGO:
213 gensec_gssapi_state->gss_oid = gss_mech_spnego;
215 case DCERPC_AUTH_TYPE_KRB5:
217 gensec_gssapi_state->gss_oid = gss_mech_krb5;
221 send_to_kdc.func = smb_krb5_send_and_recv_func;
222 send_to_kdc.ptr = gensec_security->event_ctx;
224 ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
226 DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
227 talloc_free(gensec_gssapi_state);
228 return NT_STATUS_INTERNAL_ERROR;
231 realm = lp_realm(gensec_security->settings->lp_ctx);
233 ret = gsskrb5_set_default_realm(realm);
235 DEBUG(1,("gensec_krb5_start: gsskrb5_set_default_realm failed\n"));
236 talloc_free(gensec_gssapi_state);
237 return NT_STATUS_INTERNAL_ERROR;
241 /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
242 ret = gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security->settings, "krb5", "set_dns_canonicalize", false));
244 DEBUG(1,("gensec_krb5_start: gsskrb5_set_dns_canonicalize failed\n"));
245 talloc_free(gensec_gssapi_state);
246 return NT_STATUS_INTERNAL_ERROR;
249 ret = smb_krb5_init_context(gensec_gssapi_state,
250 gensec_security->event_ctx,
251 gensec_security->settings->lp_ctx,
252 &gensec_gssapi_state->smb_krb5_context);
254 DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
255 error_message(ret)));
256 talloc_free(gensec_gssapi_state);
257 return NT_STATUS_INTERNAL_ERROR;
262 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
266 struct gensec_gssapi_state *gensec_gssapi_state;
267 struct cli_credentials *machine_account;
268 struct gssapi_creds_container *gcc;
270 nt_status = gensec_gssapi_start(gensec_security);
271 if (!NT_STATUS_IS_OK(nt_status)) {
275 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
277 machine_account = gensec_get_credentials(gensec_security);
279 if (!machine_account) {
280 DEBUG(3, ("No machine account credentials specified\n"));
281 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
283 ret = cli_credentials_get_server_gss_creds(machine_account,
284 gensec_security->event_ctx,
285 gensec_security->settings->lp_ctx, &gcc);
287 DEBUG(1, ("Aquiring acceptor credentials failed: %s\n",
288 error_message(ret)));
289 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
293 gensec_gssapi_state->server_cred = gcc;
298 static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
301 struct gensec_gssapi_state *gensec_gssapi_state;
302 nt_status = gensec_gssapi_server_start(gensec_security);
304 if (NT_STATUS_IS_OK(nt_status)) {
305 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
306 gensec_gssapi_state->sasl = true;
311 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
313 struct gensec_gssapi_state *gensec_gssapi_state;
314 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
317 gss_buffer_desc name_token;
319 OM_uint32 maj_stat, min_stat;
320 const char *hostname = gensec_get_target_hostname(gensec_security);
321 const char *principal;
322 struct gssapi_creds_container *gcc;
325 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
326 return NT_STATUS_INVALID_PARAMETER;
328 if (is_ipaddress(hostname)) {
329 DEBUG(2, ("Cannot do GSSAPI to an IP address\n"));
330 return NT_STATUS_INVALID_PARAMETER;
332 if (strcmp(hostname, "localhost") == 0) {
333 DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n"));
334 return NT_STATUS_INVALID_PARAMETER;
337 nt_status = gensec_gssapi_start(gensec_security);
338 if (!NT_STATUS_IS_OK(nt_status)) {
342 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
344 principal = gensec_get_target_principal(gensec_security);
345 if (principal && lp_client_use_spnego_principal(gensec_security->settings->lp_ctx)) {
346 name_type = GSS_C_NULL_OID;
348 principal = talloc_asprintf(gensec_gssapi_state, "%s@%s",
349 gensec_get_target_service(gensec_security),
352 name_type = GSS_C_NT_HOSTBASED_SERVICE;
354 name_token.value = discard_const_p(uint8_t, principal);
355 name_token.length = strlen(principal);
358 maj_stat = gss_import_name (&min_stat,
361 &gensec_gssapi_state->server_name);
363 DEBUG(2, ("GSS Import name of %s failed: %s\n",
364 (char *)name_token.value,
365 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
366 return NT_STATUS_INVALID_PARAMETER;
369 ret = cli_credentials_get_client_gss_creds(creds,
370 gensec_security->event_ctx,
371 gensec_security->settings->lp_ctx, &gcc);
375 case KRB5KDC_ERR_PREAUTH_FAILED:
376 return NT_STATUS_LOGON_FAILURE;
377 case KRB5_KDC_UNREACH:
378 DEBUG(3, ("Cannot reach a KDC we require to contact %s\n", principal));
379 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
381 DEBUG(1, ("Aquiring initiator credentials failed\n"));
382 return NT_STATUS_UNSUCCESSFUL;
385 gensec_gssapi_state->client_cred = gcc;
386 if (!talloc_reference(gensec_gssapi_state, gcc)) {
387 return NT_STATUS_NO_MEMORY;
393 static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
396 struct gensec_gssapi_state *gensec_gssapi_state;
397 nt_status = gensec_gssapi_client_start(gensec_security);
399 if (NT_STATUS_IS_OK(nt_status)) {
400 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
401 gensec_gssapi_state->sasl = true;
408 * Check if the packet is one for this mechansim
410 * @param gensec_security GENSEC state
411 * @param in The request, as a DATA_BLOB
412 * @return Error, INVALID_PARAMETER if it's not a packet for us
413 * or NT_STATUS_OK if the packet is ok.
416 static NTSTATUS gensec_gssapi_magic(struct gensec_security *gensec_security,
419 if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
422 return NT_STATUS_INVALID_PARAMETER;
428 * Next state function for the GSSAPI GENSEC mechanism
430 * @param gensec_gssapi_state GSSAPI State
431 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
432 * @param in The request, as a DATA_BLOB
433 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
434 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
435 * or NT_STATUS_OK if the user is authenticated.
438 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
439 TALLOC_CTX *out_mem_ctx,
440 const DATA_BLOB in, DATA_BLOB *out)
442 struct gensec_gssapi_state *gensec_gssapi_state
443 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
444 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
445 OM_uint32 maj_stat, min_stat;
447 gss_buffer_desc input_token, output_token;
448 gss_OID gss_oid_p = NULL;
449 input_token.length = in.length;
450 input_token.value = in.data;
452 switch (gensec_gssapi_state->sasl_state) {
455 switch (gensec_security->gensec_role) {
458 maj_stat = gss_init_sec_context(&min_stat,
459 gensec_gssapi_state->client_cred->creds,
460 &gensec_gssapi_state->gssapi_context,
461 gensec_gssapi_state->server_name,
462 gensec_gssapi_state->gss_oid,
463 gensec_gssapi_state->want_flags,
465 gensec_gssapi_state->input_chan_bindings,
469 &gensec_gssapi_state->got_flags, /* ret flags */
472 gensec_gssapi_state->gss_oid = gss_oid_p;
478 maj_stat = gss_accept_sec_context(&min_stat,
479 &gensec_gssapi_state->gssapi_context,
480 gensec_gssapi_state->server_cred->creds,
482 gensec_gssapi_state->input_chan_bindings,
483 &gensec_gssapi_state->client_name,
486 &gensec_gssapi_state->got_flags,
488 &gensec_gssapi_state->delegated_cred_handle);
490 gensec_gssapi_state->gss_oid = gss_oid_p;
495 return NT_STATUS_INVALID_PARAMETER;
499 gensec_gssapi_state->gss_exchange_count++;
501 if (maj_stat == GSS_S_COMPLETE) {
502 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
503 gss_release_buffer(&min_stat2, &output_token);
505 if (gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG) {
506 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
508 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
511 /* We may have been invoked as SASL, so there
512 * is more work to do */
513 if (gensec_gssapi_state->sasl) {
514 /* Due to a very subtle interaction
515 * with SASL and the LDAP libs, we
516 * must ensure the data pointer is
517 * != NULL, but the length is 0.
519 * This ensures we send a 'zero
520 * length' (rather than NULL) response
524 out->data = (uint8_t *)talloc_strdup(out_mem_ctx, "\0");
527 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
528 return NT_STATUS_MORE_PROCESSING_REQUIRED;
530 gensec_gssapi_state->sasl_state = STAGE_DONE;
532 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
533 DEBUG(5, ("GSSAPI Connection will be cryptographicly sealed\n"));
534 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
535 DEBUG(5, ("GSSAPI Connection will be cryptographicly signed\n"));
537 DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
542 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
543 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
544 gss_release_buffer(&min_stat2, &output_token);
546 return NT_STATUS_MORE_PROCESSING_REQUIRED;
547 } else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
549 case KRB5_KDC_UNREACH:
550 DEBUG(3, ("Cannot reach a KDC we require: %s\n",
551 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
552 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
553 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
554 DEBUG(3, ("Server is not registered with our KDC: %s\n",
555 gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
556 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
557 case KRB5KRB_AP_ERR_MSG_TYPE:
558 /* garbage input, possibly from the auto-mech detection */
559 return NT_STATUS_INVALID_PARAMETER;
561 DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n",
562 gensec_gssapi_state->gss_exchange_count,
563 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
567 DEBUG(1, ("GSS Update(%d) failed: %s\n",
568 gensec_gssapi_state->gss_exchange_count,
569 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
575 /* These last two stages are only done if we were invoked as SASL */
576 case STAGE_SASL_SSF_NEG:
578 switch (gensec_security->gensec_role) {
581 uint8_t maxlength_proposed[4];
582 uint8_t maxlength_accepted[4];
583 uint8_t security_supported;
586 input_token.length = in.length;
587 input_token.value = in.data;
589 /* As a client, we have just send a
590 * zero-length blob to the server (after the
591 * normal GSSAPI exchange), and it has replied
592 * with it's SASL negotiation */
594 maj_stat = gss_unwrap(&min_stat,
595 gensec_gssapi_state->gssapi_context,
600 if (GSS_ERROR(maj_stat)) {
601 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
602 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
603 return NT_STATUS_ACCESS_DENIED;
606 if (output_token.length < 4) {
607 return NT_STATUS_INVALID_PARAMETER;
610 memcpy(maxlength_proposed, output_token.value, 4);
611 gss_release_buffer(&min_stat, &output_token);
613 /* first byte is the proposed security */
614 security_supported = maxlength_proposed[0];
615 maxlength_proposed[0] = '\0';
617 /* Rest is the proposed max wrap length */
618 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0),
619 gensec_gssapi_state->max_wrap_buf_size);
620 gensec_gssapi_state->sasl_protection = 0;
621 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
622 if (security_supported & NEG_SEAL) {
623 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
625 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
626 if (security_supported & NEG_SIGN) {
627 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
629 } else if (security_supported & NEG_NONE) {
630 gensec_gssapi_state->sasl_protection |= NEG_NONE;
632 DEBUG(1, ("Remote server does not support unprotected connections"));
633 return NT_STATUS_ACCESS_DENIED;
636 /* Send back the negotiated max length */
638 RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
640 maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
642 input_token.value = maxlength_accepted;
643 input_token.length = sizeof(maxlength_accepted);
645 maj_stat = gss_wrap(&min_stat,
646 gensec_gssapi_state->gssapi_context,
652 if (GSS_ERROR(maj_stat)) {
653 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
654 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
655 return NT_STATUS_ACCESS_DENIED;
658 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
659 gss_release_buffer(&min_stat, &output_token);
661 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
662 gensec_gssapi_state->sasl_state = STAGE_DONE;
664 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
665 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly sealed\n"));
666 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
667 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly signed\n"));
669 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographicly protection\n"));
676 uint8_t maxlength_proposed[4];
677 uint8_t security_supported = 0x0;
680 /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
681 if (in.length != 0) {
682 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
685 /* Give the client some idea what we will support */
687 RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
688 /* first byte is the proposed security */
689 maxlength_proposed[0] = '\0';
691 gensec_gssapi_state->sasl_protection = 0;
692 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
693 security_supported |= NEG_SEAL;
695 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
696 security_supported |= NEG_SIGN;
698 if (security_supported == 0) {
699 /* If we don't support anything, this must be 0 */
700 RSIVAL(maxlength_proposed, 0, 0x0);
703 /* TODO: We may not wish to support this */
704 security_supported |= NEG_NONE;
705 maxlength_proposed[0] = security_supported;
707 input_token.value = maxlength_proposed;
708 input_token.length = sizeof(maxlength_proposed);
710 maj_stat = gss_wrap(&min_stat,
711 gensec_gssapi_state->gssapi_context,
717 if (GSS_ERROR(maj_stat)) {
718 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
719 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
720 return NT_STATUS_ACCESS_DENIED;
723 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
724 gss_release_buffer(&min_stat, &output_token);
726 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
727 return NT_STATUS_MORE_PROCESSING_REQUIRED;
730 return NT_STATUS_INVALID_PARAMETER;
734 /* This is s server-only stage */
735 case STAGE_SASL_SSF_ACCEPT:
737 uint8_t maxlength_accepted[4];
738 uint8_t security_accepted;
741 input_token.length = in.length;
742 input_token.value = in.data;
744 maj_stat = gss_unwrap(&min_stat,
745 gensec_gssapi_state->gssapi_context,
750 if (GSS_ERROR(maj_stat)) {
751 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
752 gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
753 return NT_STATUS_ACCESS_DENIED;
756 if (output_token.length < 4) {
757 return NT_STATUS_INVALID_PARAMETER;
760 memcpy(maxlength_accepted, output_token.value, 4);
761 gss_release_buffer(&min_stat, &output_token);
763 /* first byte is the proposed security */
764 security_accepted = maxlength_accepted[0];
765 maxlength_accepted[0] = '\0';
767 /* Rest is the proposed max wrap length */
768 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0),
769 gensec_gssapi_state->max_wrap_buf_size);
771 gensec_gssapi_state->sasl_protection = 0;
772 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
773 if (security_accepted & NEG_SEAL) {
774 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
776 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
777 if (security_accepted & NEG_SIGN) {
778 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
780 } else if (security_accepted & NEG_NONE) {
781 gensec_gssapi_state->sasl_protection |= NEG_NONE;
783 DEBUG(1, ("Remote client does not support unprotected connections, but we failed to negotiate anything better"));
784 return NT_STATUS_ACCESS_DENIED;
787 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
788 gensec_gssapi_state->sasl_state = STAGE_DONE;
789 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
790 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly sealed\n"));
791 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
792 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly signed\n"));
794 DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
797 *out = data_blob(NULL, 0);
801 return NT_STATUS_INVALID_PARAMETER;
805 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
810 struct gensec_gssapi_state *gensec_gssapi_state
811 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
812 OM_uint32 maj_stat, min_stat;
813 gss_buffer_desc input_token, output_token;
815 input_token.length = in->length;
816 input_token.value = in->data;
818 maj_stat = gss_wrap(&min_stat,
819 gensec_gssapi_state->gssapi_context,
820 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
825 if (GSS_ERROR(maj_stat)) {
826 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
827 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
828 return NT_STATUS_ACCESS_DENIED;
831 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
832 gss_release_buffer(&min_stat, &output_token);
834 if (gensec_gssapi_state->sasl) {
835 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
836 if (max_wrapped_size < out->length) {
837 DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
838 (unsigned)in->length,
839 (unsigned)out->length,
840 (unsigned int)max_wrapped_size));
841 return NT_STATUS_INVALID_PARAMETER;
845 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
847 return NT_STATUS_ACCESS_DENIED;
852 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
857 struct gensec_gssapi_state *gensec_gssapi_state
858 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
859 OM_uint32 maj_stat, min_stat;
860 gss_buffer_desc input_token, output_token;
863 input_token.length = in->length;
864 input_token.value = in->data;
866 if (gensec_gssapi_state->sasl) {
867 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
868 if (max_wrapped_size < in->length) {
869 DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
870 return NT_STATUS_INVALID_PARAMETER;
874 maj_stat = gss_unwrap(&min_stat,
875 gensec_gssapi_state->gssapi_context,
880 if (GSS_ERROR(maj_stat)) {
881 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n",
882 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
883 return NT_STATUS_ACCESS_DENIED;
886 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
887 gss_release_buffer(&min_stat, &output_token);
889 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
891 return NT_STATUS_ACCESS_DENIED;
896 /* Find out the maximum input size negotiated on this connection */
898 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security)
900 struct gensec_gssapi_state *gensec_gssapi_state
901 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
902 OM_uint32 maj_stat, min_stat;
903 OM_uint32 max_input_size;
905 maj_stat = gss_wrap_size_limit(&min_stat,
906 gensec_gssapi_state->gssapi_context,
907 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
909 gensec_gssapi_state->max_wrap_buf_size,
911 if (GSS_ERROR(maj_stat)) {
912 TALLOC_CTX *mem_ctx = talloc_new(NULL);
913 DEBUG(1, ("gensec_gssapi_max_input_size: determinaing signature size with gss_wrap_size_limit failed: %s\n",
914 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
915 talloc_free(mem_ctx);
919 return max_input_size;
922 /* Find out the maximum output size negotiated on this connection */
923 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security)
925 struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
926 return gensec_gssapi_state->max_wrap_buf_size;
929 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
931 uint8_t *data, size_t length,
932 const uint8_t *whole_pdu, size_t pdu_length,
935 struct gensec_gssapi_state *gensec_gssapi_state
936 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
937 OM_uint32 maj_stat, min_stat;
938 gss_buffer_desc input_token, output_token;
942 input_token.length = length;
943 input_token.value = data;
945 maj_stat = gss_wrap(&min_stat,
946 gensec_gssapi_state->gssapi_context,
947 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
952 if (GSS_ERROR(maj_stat)) {
953 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap failed: %s\n",
954 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
955 return NT_STATUS_ACCESS_DENIED;
958 if (output_token.length < input_token.length) {
959 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n",
960 (long)output_token.length, (long)length));
961 return NT_STATUS_INTERNAL_ERROR;
963 sig_length = output_token.length - input_token.length;
965 memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
966 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
968 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
969 dump_data_pw("gensec_gssapi_seal_packet: clear\n", data, length);
970 dump_data_pw("gensec_gssapi_seal_packet: sealed\n", ((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
972 gss_release_buffer(&min_stat, &output_token);
974 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
976 return NT_STATUS_ACCESS_DENIED;
981 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
983 uint8_t *data, size_t length,
984 const uint8_t *whole_pdu, size_t pdu_length,
985 const DATA_BLOB *sig)
987 struct gensec_gssapi_state *gensec_gssapi_state
988 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
989 OM_uint32 maj_stat, min_stat;
990 gss_buffer_desc input_token, output_token;
995 dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length);
997 in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
999 memcpy(in.data, sig->data, sig->length);
1000 memcpy(in.data + sig->length, data, length);
1002 input_token.length = in.length;
1003 input_token.value = in.data;
1005 maj_stat = gss_unwrap(&min_stat,
1006 gensec_gssapi_state->gssapi_context,
1011 if (GSS_ERROR(maj_stat)) {
1012 DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n",
1013 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1014 return NT_STATUS_ACCESS_DENIED;
1017 if (output_token.length != length) {
1018 return NT_STATUS_INTERNAL_ERROR;
1021 memcpy(data, output_token.value, length);
1023 gss_release_buffer(&min_stat, &output_token);
1025 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1027 return NT_STATUS_ACCESS_DENIED;
1029 return NT_STATUS_OK;
1032 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
1033 TALLOC_CTX *mem_ctx,
1034 const uint8_t *data, size_t length,
1035 const uint8_t *whole_pdu, size_t pdu_length,
1038 struct gensec_gssapi_state *gensec_gssapi_state
1039 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1040 OM_uint32 maj_stat, min_stat;
1041 gss_buffer_desc input_token, output_token;
1043 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1044 input_token.length = pdu_length;
1045 input_token.value = discard_const_p(uint8_t *, whole_pdu);
1047 input_token.length = length;
1048 input_token.value = discard_const_p(uint8_t *, data);
1051 maj_stat = gss_get_mic(&min_stat,
1052 gensec_gssapi_state->gssapi_context,
1056 if (GSS_ERROR(maj_stat)) {
1057 DEBUG(1, ("GSS GetMic 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 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
1064 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
1066 gss_release_buffer(&min_stat, &output_token);
1068 return NT_STATUS_OK;
1071 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
1072 TALLOC_CTX *mem_ctx,
1073 const uint8_t *data, size_t length,
1074 const uint8_t *whole_pdu, size_t pdu_length,
1075 const DATA_BLOB *sig)
1077 struct gensec_gssapi_state *gensec_gssapi_state
1078 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1079 OM_uint32 maj_stat, min_stat;
1080 gss_buffer_desc input_token;
1081 gss_buffer_desc input_message;
1082 gss_qop_t qop_state;
1084 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
1086 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1087 input_message.length = pdu_length;
1088 input_message.value = discard_const(whole_pdu);
1090 input_message.length = length;
1091 input_message.value = discard_const(data);
1094 input_token.length = sig->length;
1095 input_token.value = sig->data;
1097 maj_stat = gss_verify_mic(&min_stat,
1098 gensec_gssapi_state->gssapi_context,
1102 if (GSS_ERROR(maj_stat)) {
1103 DEBUG(1, ("GSS VerifyMic failed: %s\n",
1104 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1105 return NT_STATUS_ACCESS_DENIED;
1108 return NT_STATUS_OK;
1111 /* Try to figure out what features we actually got on the connection */
1112 static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
1115 struct gensec_gssapi_state *gensec_gssapi_state
1116 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1117 if (feature & GENSEC_FEATURE_SIGN) {
1118 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1119 if (gensec_gssapi_state->sasl
1120 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1121 return ((gensec_gssapi_state->sasl_protection & NEG_SIGN)
1122 && (gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG));
1124 return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
1126 if (feature & GENSEC_FEATURE_SEAL) {
1127 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1128 if (gensec_gssapi_state->sasl
1129 && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1130 return ((gensec_gssapi_state->sasl_protection & NEG_SEAL)
1131 && (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG));
1133 return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
1135 if (feature & GENSEC_FEATURE_SESSION_KEY) {
1136 /* Only for GSSAPI/Krb5 */
1137 if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
1141 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1142 return gensec_gssapi_state->got_flags & GSS_C_DCE_STYLE;
1144 if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1147 if (!(gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG)) {
1151 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1154 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1158 status = gensec_gssapi_init_lucid(gensec_gssapi_state);
1159 if (!NT_STATUS_IS_OK(status)) {
1163 if (gensec_gssapi_state->lucid->protocol == 1) {
1169 /* We can always do async (rather than strict request/reply) packets. */
1170 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1177 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1178 * (for encrypting some passwords).
1180 * This breaks all the abstractions, but what do you expect...
1182 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
1183 DATA_BLOB *session_key)
1185 struct gensec_gssapi_state *gensec_gssapi_state
1186 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1187 OM_uint32 maj_stat, min_stat;
1188 krb5_keyblock *subkey;
1190 if (gensec_gssapi_state->sasl_state != STAGE_DONE) {
1191 return NT_STATUS_NO_USER_SESSION_KEY;
1194 if (gensec_gssapi_state->session_key.data) {
1195 *session_key = gensec_gssapi_state->session_key;
1196 return NT_STATUS_OK;
1199 maj_stat = gsskrb5_get_subkey(&min_stat,
1200 gensec_gssapi_state->gssapi_context,
1202 if (maj_stat != 0) {
1203 DEBUG(1, ("NO session key for this mech\n"));
1204 return NT_STATUS_NO_USER_SESSION_KEY;
1207 DEBUG(10, ("Got KRB5 session key of length %d%s\n",
1208 (int)KRB5_KEY_LENGTH(subkey),
1209 (gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":""));
1210 *session_key = data_blob_talloc(gensec_gssapi_state,
1211 KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
1212 krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);
1213 gensec_gssapi_state->session_key = *session_key;
1214 dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
1216 return NT_STATUS_OK;
1219 /* Get some basic (and authorization) information about the user on
1220 * this session. This uses either the PAC (if present) or a local
1221 * database lookup */
1222 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
1223 struct auth_session_info **_session_info)
1226 TALLOC_CTX *mem_ctx;
1227 struct gensec_gssapi_state *gensec_gssapi_state
1228 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1229 struct auth_serversupplied_info *server_info = NULL;
1230 struct auth_session_info *session_info = NULL;
1231 OM_uint32 maj_stat, min_stat;
1232 gss_buffer_desc pac;
1235 if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
1236 || (memcmp(gensec_gssapi_state->gss_oid->elements, gss_mech_krb5->elements,
1237 gensec_gssapi_state->gss_oid->length) != 0)) {
1238 DEBUG(1, ("NO session info available for this mech\n"));
1239 return NT_STATUS_INVALID_PARAMETER;
1242 mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context");
1243 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
1245 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
1246 gensec_gssapi_state->gssapi_context,
1247 KRB5_AUTHDATA_WIN2K_PAC,
1251 if (maj_stat == 0) {
1252 pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);
1253 gss_release_buffer(&min_stat, &pac);
1256 pac_blob = data_blob(NULL, 0);
1259 /* IF we have the PAC - otherwise we need to get this
1260 * data from elsewere - local ldb, or (TODO) lookup of some
1263 if (pac_blob.length) {
1264 nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
1265 gensec_security->settings->iconv_convenience,
1267 gensec_gssapi_state->smb_krb5_context->krb5_context,
1269 if (!NT_STATUS_IS_OK(nt_status)) {
1270 talloc_free(mem_ctx);
1274 gss_buffer_desc name_token;
1275 char *principal_string;
1277 maj_stat = gss_display_name (&min_stat,
1278 gensec_gssapi_state->client_name,
1281 if (GSS_ERROR(maj_stat)) {
1282 DEBUG(1, ("GSS display_name failed: %s\n",
1283 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1284 talloc_free(mem_ctx);
1285 return NT_STATUS_FOOBAR;
1288 principal_string = talloc_strndup(mem_ctx,
1289 (const char *)name_token.value,
1292 gss_release_buffer(&min_stat, &name_token);
1294 if (!principal_string) {
1295 talloc_free(mem_ctx);
1296 return NT_STATUS_NO_MEMORY;
1299 if (gensec_security->auth_context &&
1300 !gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
1301 DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
1302 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1303 nt_status = gensec_security->auth_context->get_server_info_principal(mem_ctx,
1304 gensec_security->auth_context,
1308 if (!NT_STATUS_IS_OK(nt_status)) {
1309 talloc_free(mem_ctx);
1313 DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
1315 gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1316 return NT_STATUS_ACCESS_DENIED;
1320 /* references the server_info into the session_info */
1321 nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx,
1322 gensec_security->settings->lp_ctx, server_info, &session_info);
1323 if (!NT_STATUS_IS_OK(nt_status)) {
1324 talloc_free(mem_ctx);
1328 nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
1329 if (!NT_STATUS_IS_OK(nt_status)) {
1330 talloc_free(mem_ctx);
1334 if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) {
1335 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1337 krb5_error_code ret;
1338 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1339 session_info->credentials = cli_credentials_init(session_info);
1340 if (!session_info->credentials) {
1341 talloc_free(mem_ctx);
1342 return NT_STATUS_NO_MEMORY;
1345 cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx);
1346 /* Just so we don't segfault trying to get at a username */
1347 cli_credentials_set_anonymous(session_info->credentials);
1349 ret = cli_credentials_set_client_gss_creds(session_info->credentials,
1350 gensec_security->event_ctx,
1351 gensec_security->settings->lp_ctx,
1352 gensec_gssapi_state->delegated_cred_handle,
1355 talloc_free(mem_ctx);
1356 return NT_STATUS_NO_MEMORY;
1359 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1360 cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);
1362 /* It has been taken from this place... */
1363 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1365 talloc_steal(gensec_gssapi_state, session_info);
1366 talloc_free(mem_ctx);
1367 *_session_info = session_info;
1369 return NT_STATUS_OK;
1372 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
1374 struct gensec_gssapi_state *gensec_gssapi_state
1375 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1378 if (gensec_gssapi_state->sig_size) {
1379 return gensec_gssapi_state->sig_size;
1382 if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1383 gensec_gssapi_state->sig_size = 45;
1385 gensec_gssapi_state->sig_size = 37;
1388 status = gensec_gssapi_init_lucid(gensec_gssapi_state);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 return gensec_gssapi_state->sig_size;
1393 if (gensec_gssapi_state->lucid->protocol == 1) {
1394 if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1396 * TODO: windows uses 76 here, but we don't know
1397 * gss_wrap works with aes keys yet
1399 gensec_gssapi_state->sig_size = 76;
1401 gensec_gssapi_state->sig_size = 28;
1403 } else if (gensec_gssapi_state->lucid->protocol == 0) {
1404 switch (gensec_gssapi_state->lucid->rfc1964_kd.ctx_key.type) {
1406 case KEYTYPE_ARCFOUR:
1407 case KEYTYPE_ARCFOUR_56:
1408 if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1409 gensec_gssapi_state->sig_size = 45;
1411 gensec_gssapi_state->sig_size = 37;
1415 if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1416 gensec_gssapi_state->sig_size = 57;
1418 gensec_gssapi_state->sig_size = 49;
1424 return gensec_gssapi_state->sig_size;
1427 static const char *gensec_gssapi_krb5_oids[] = {
1428 GENSEC_OID_KERBEROS5_OLD,
1429 GENSEC_OID_KERBEROS5,
1433 static const char *gensec_gssapi_spnego_oids[] = {
1438 /* As a server, this could in theory accept any GSSAPI mech */
1439 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1440 .name = "gssapi_spnego",
1441 .sasl_name = "GSS-SPNEGO",
1442 .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
1443 .oid = gensec_gssapi_spnego_oids,
1444 .client_start = gensec_gssapi_client_start,
1445 .server_start = gensec_gssapi_server_start,
1446 .magic = gensec_gssapi_magic,
1447 .update = gensec_gssapi_update,
1448 .session_key = gensec_gssapi_session_key,
1449 .session_info = gensec_gssapi_session_info,
1450 .sign_packet = gensec_gssapi_sign_packet,
1451 .check_packet = gensec_gssapi_check_packet,
1452 .seal_packet = gensec_gssapi_seal_packet,
1453 .unseal_packet = gensec_gssapi_unseal_packet,
1454 .wrap = gensec_gssapi_wrap,
1455 .unwrap = gensec_gssapi_unwrap,
1456 .have_feature = gensec_gssapi_have_feature,
1459 .priority = GENSEC_GSSAPI
1462 /* As a server, this could in theory accept any GSSAPI mech */
1463 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1464 .name = "gssapi_krb5",
1465 .auth_type = DCERPC_AUTH_TYPE_KRB5,
1466 .oid = gensec_gssapi_krb5_oids,
1467 .client_start = gensec_gssapi_client_start,
1468 .server_start = gensec_gssapi_server_start,
1469 .magic = gensec_gssapi_magic,
1470 .update = gensec_gssapi_update,
1471 .session_key = gensec_gssapi_session_key,
1472 .session_info = gensec_gssapi_session_info,
1473 .sig_size = gensec_gssapi_sig_size,
1474 .sign_packet = gensec_gssapi_sign_packet,
1475 .check_packet = gensec_gssapi_check_packet,
1476 .seal_packet = gensec_gssapi_seal_packet,
1477 .unseal_packet = gensec_gssapi_unseal_packet,
1478 .wrap = gensec_gssapi_wrap,
1479 .unwrap = gensec_gssapi_unwrap,
1480 .have_feature = gensec_gssapi_have_feature,
1483 .priority = GENSEC_GSSAPI
1486 /* As a server, this could in theory accept any GSSAPI mech */
1487 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1488 .name = "gssapi_krb5_sasl",
1489 .sasl_name = "GSSAPI",
1490 .client_start = gensec_gssapi_sasl_client_start,
1491 .server_start = gensec_gssapi_sasl_server_start,
1492 .update = gensec_gssapi_update,
1493 .session_key = gensec_gssapi_session_key,
1494 .session_info = gensec_gssapi_session_info,
1495 .max_input_size = gensec_gssapi_max_input_size,
1496 .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1497 .wrap = gensec_gssapi_wrap,
1498 .unwrap = gensec_gssapi_unwrap,
1499 .have_feature = gensec_gssapi_have_feature,
1502 .priority = GENSEC_GSSAPI
1505 _PUBLIC_ NTSTATUS gensec_gssapi_init(void)
1509 ret = gensec_register(&gensec_gssapi_spnego_security_ops);
1510 if (!NT_STATUS_IS_OK(ret)) {
1511 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1512 gensec_gssapi_spnego_security_ops.name));
1516 ret = gensec_register(&gensec_gssapi_krb5_security_ops);
1517 if (!NT_STATUS_IS_OK(ret)) {
1518 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1519 gensec_gssapi_krb5_security_ops.name));
1523 ret = gensec_register(&gensec_gssapi_sasl_krb5_security_ops);
1524 if (!NT_STATUS_IS_OK(ret)) {
1525 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1526 gensec_gssapi_sasl_krb5_security_ops.name));