2 * GSSAPI Security Extensions
3 * RPC Pipe client and server routines
4 * Copyright (C) Simo Sorce 2010.
5 * Copyright (C) Andrew Bartlett 2004-2011.
6 * Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 /* We support only GSSAPI/KRB5 here */
26 #include "libads/kerberos_proto.h"
27 #include "auth/common_auth.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/credentials/credentials.h"
30 #include "../librpc/gen_ndr/dcerpc.h"
32 #if defined(HAVE_KRB5) && defined(HAVE_GSS_WRAP_IOV)
37 #ifndef GSS_C_DCE_STYLE
38 #define GSS_C_DCE_STYLE 0x1000
41 #ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
42 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
43 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
46 gss_OID_desc gse_sesskey_inq_oid = {
47 GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
48 (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
51 #ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
52 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
53 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
56 gss_OID_desc gse_sesskeytype_oid = {
57 GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
58 (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
61 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH 12
62 /* EXTRACTION OID AUTHZ ID */
63 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" "\x01"
65 gss_OID_desc gse_authz_data_oid = {
66 GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH,
67 (void *)GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID
70 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
73 gss_ctx_id_t gssapi_context;
74 gss_name_t server_name;
75 gss_name_t client_name;
76 OM_uint32 gss_want_flags, gss_got_flags;
78 gss_cred_id_t delegated_cred_handle;
80 gss_krb5_lucid_context_v1_t *lucid;
87 gss_OID_desc gss_mech;
93 #ifndef HAVE_GSS_OID_EQUAL
95 static bool gss_oid_equal(const gss_OID o1, const gss_OID o2)
100 if ((o1 == NULL && o2 != NULL) || (o1 != NULL && o2 == NULL)) {
103 if (o1->length != o2->length) {
106 return memcmp(o1->elements, o2->elements, o1->length) == false;
111 /* free non talloc dependent contexts */
112 static int gse_context_destructor(void *ptr)
114 struct gse_context *gse_ctx;
115 OM_uint32 gss_min, gss_maj;
117 gse_ctx = talloc_get_type_abort(ptr, struct gse_context);
118 if (gse_ctx->k5ctx) {
119 if (gse_ctx->ccache) {
120 krb5_cc_close(gse_ctx->k5ctx, gse_ctx->ccache);
121 gse_ctx->ccache = NULL;
123 if (gse_ctx->keytab) {
124 krb5_kt_close(gse_ctx->k5ctx, gse_ctx->keytab);
125 gse_ctx->keytab = NULL;
127 krb5_free_context(gse_ctx->k5ctx);
128 gse_ctx->k5ctx = NULL;
130 if (gse_ctx->gssapi_context != GSS_C_NO_CONTEXT) {
131 gss_maj = gss_delete_sec_context(&gss_min,
132 &gse_ctx->gssapi_context,
135 if (gse_ctx->server_name) {
136 gss_maj = gss_release_name(&gss_min,
137 &gse_ctx->server_name);
139 if (gse_ctx->client_name) {
140 gss_maj = gss_release_name(&gss_min,
141 &gse_ctx->client_name);
143 if (gse_ctx->creds) {
144 gss_maj = gss_release_cred(&gss_min,
147 if (gse_ctx->delegated_cred_handle) {
148 gss_maj = gss_release_cred(&gss_min,
149 &gse_ctx->delegated_cred_handle);
152 /* MIT and Heimdal differ as to if you can call
153 * gss_release_oid() on this OID, generated by
154 * gss_{accept,init}_sec_context(). However, as long as the
155 * oid is gss_mech_krb5 (which it always is at the moment),
156 * then this is a moot point, as both declare this particular
157 * OID static, and so no memory is lost. This assert is in
158 * place to ensure that the programmer who wishes to extend
159 * this code to EAP or other GSS mechanisms determines an
160 * implementation-dependent way of releasing any dynamically
162 SMB_ASSERT(gss_oid_equal(&gse_ctx->gss_mech, GSS_C_NO_OID) || gss_oid_equal(&gse_ctx->gss_mech, gss_mech_krb5));
167 static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
168 bool do_sign, bool do_seal,
169 const char *ccache_name,
170 uint32_t add_gss_c_flags,
171 struct gse_context **_gse_ctx)
173 struct gse_context *gse_ctx;
174 krb5_error_code k5ret;
177 gse_ctx = talloc_zero(mem_ctx, struct gse_context);
179 return NT_STATUS_NO_MEMORY;
181 talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
183 memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
185 gse_ctx->gss_want_flags = GSS_C_MUTUAL_FLAG |
187 GSS_C_DELEG_POLICY_FLAG |
191 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
194 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
195 gse_ctx->gss_want_flags |= GSS_C_CONF_FLAG;
198 gse_ctx->gss_want_flags |= add_gss_c_flags;
200 /* Initialize Kerberos Context */
201 initialize_krb5_error_table();
203 k5ret = krb5_init_context(&gse_ctx->k5ctx);
205 DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
206 error_message(k5ret)));
207 status = NT_STATUS_INTERNAL_ERROR;
212 ccache_name = krb5_cc_default_name(gse_ctx->k5ctx);
214 k5ret = krb5_cc_resolve(gse_ctx->k5ctx, ccache_name,
217 DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
218 error_message(k5ret)));
219 status = NT_STATUS_INTERNAL_ERROR;
223 /* TODO: Should we enforce a enc_types list ?
224 ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
231 TALLOC_FREE(gse_ctx);
235 static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
236 bool do_sign, bool do_seal,
237 const char *ccache_name,
240 const char *username,
241 const char *password,
242 uint32_t add_gss_c_flags,
243 struct gse_context **_gse_ctx)
245 struct gse_context *gse_ctx;
246 OM_uint32 gss_maj, gss_min;
247 gss_buffer_desc name_buffer = {0, NULL};
248 gss_OID_set_desc mech_set;
251 if (!server || !service) {
252 return NT_STATUS_INVALID_PARAMETER;
255 status = gse_context_init(mem_ctx, do_sign, do_seal,
256 ccache_name, add_gss_c_flags,
258 if (!NT_STATUS_IS_OK(status)) {
259 return NT_STATUS_NO_MEMORY;
262 /* Guess the realm based on the supplied service, and avoid the GSS libs
263 doing DNS lookups which may fail.
265 TODO: Loop with the KDC on some more combinations (local
266 realm in particular), possibly falling back to
267 GSS_C_NT_HOSTBASED_SERVICE
269 name_buffer.value = kerberos_get_principal_from_service_hostname(gse_ctx,
271 if (!name_buffer.value) {
272 status = NT_STATUS_NO_MEMORY;
275 name_buffer.length = strlen((char *)name_buffer.value);
276 gss_maj = gss_import_name(&gss_min, &name_buffer,
278 &gse_ctx->server_name);
280 DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
281 (char *)name_buffer.value,
282 gse_errstr(gse_ctx, gss_maj, gss_min)));
283 status = NT_STATUS_INTERNAL_ERROR;
287 /* TODO: get krb5 ticket using username/password, if no valid
288 * one already available in ccache */
291 mech_set.elements = &gse_ctx->gss_mech;
293 gss_maj = gss_acquire_cred(&gss_min,
301 DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
302 (char *)name_buffer.value,
303 gse_errstr(gse_ctx, gss_maj, gss_min)));
304 status = NT_STATUS_INTERNAL_ERROR;
309 TALLOC_FREE(name_buffer.value);
313 TALLOC_FREE(name_buffer.value);
314 TALLOC_FREE(gse_ctx);
318 static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
319 struct gse_context *gse_ctx,
320 const DATA_BLOB *token_in,
321 DATA_BLOB *token_out)
323 OM_uint32 gss_maj, gss_min;
324 gss_buffer_desc in_data;
325 gss_buffer_desc out_data;
326 DATA_BLOB blob = data_blob_null;
329 in_data.value = token_in->data;
330 in_data.length = token_in->length;
332 gss_maj = gss_init_sec_context(&gss_min,
334 &gse_ctx->gssapi_context,
335 gse_ctx->server_name,
337 gse_ctx->gss_want_flags,
338 0, GSS_C_NO_CHANNEL_BINDINGS,
339 &in_data, NULL, &out_data,
340 &gse_ctx->gss_got_flags, NULL);
343 /* we are done with it */
344 status = NT_STATUS_OK;
346 case GSS_S_CONTINUE_NEEDED:
347 /* we will need a third leg */
348 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
351 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
352 gse_errstr(talloc_tos(), gss_maj, gss_min)));
353 status = NT_STATUS_INTERNAL_ERROR;
357 /* we may be told to return nothing */
358 if (out_data.length) {
359 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
361 status = NT_STATUS_NO_MEMORY;
364 gss_maj = gss_release_buffer(&gss_min, &out_data);
372 static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
373 bool do_sign, bool do_seal,
374 uint32_t add_gss_c_flags,
375 struct gse_context **_gse_ctx)
377 struct gse_context *gse_ctx;
378 OM_uint32 gss_maj, gss_min;
382 status = gse_context_init(mem_ctx, do_sign, do_seal,
383 NULL, add_gss_c_flags, &gse_ctx);
384 if (!NT_STATUS_IS_OK(status)) {
385 return NT_STATUS_NO_MEMORY;
388 ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx,
391 status = NT_STATUS_INTERNAL_ERROR;
395 #ifdef HAVE_GSS_KRB5_IMPORT_CRED
397 /* This creates a GSSAPI cred_id_t with the keytab set */
398 gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab,
402 && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) {
403 DEBUG(0, ("gss_krb5_import_cred failed with [%s]\n",
404 gse_errstr(gse_ctx, gss_maj, gss_min)));
405 status = NT_STATUS_INTERNAL_ERROR;
408 /* This is the error the MIT krb5 1.9 gives when it
409 * implements the function, but we do not specify the
410 * principal. However, when we specify the principal
411 * as host$@REALM the GSS acceptor fails with 'wrong
412 * principal in request'. Work around the issue by
413 * falling back to the alternate approach below. */
414 } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME))
417 * This call sets the default keytab for the whole server, not
418 * just for this context. Need to find a way that does not alter
419 * the state of the whole server ... */
422 gss_OID_set_desc mech_set;
424 ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx,
425 gse_ctx->keytab, &ktname);
427 status = NT_STATUS_INTERNAL_ERROR;
431 ret = gsskrb5_register_acceptor_identity(ktname);
433 status = NT_STATUS_INTERNAL_ERROR;
438 mech_set.elements = &gse_ctx->gss_mech;
440 gss_maj = gss_acquire_cred(&gss_min,
449 DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
450 gse_errstr(gse_ctx, gss_maj, gss_min)));
451 status = NT_STATUS_INTERNAL_ERROR;
456 status = NT_STATUS_OK;
459 if (!NT_STATUS_IS_OK(status)) {
460 TALLOC_FREE(gse_ctx);
467 static NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
468 struct gse_context *gse_ctx,
469 const DATA_BLOB *token_in,
470 DATA_BLOB *token_out)
472 OM_uint32 gss_maj, gss_min;
473 gss_buffer_desc in_data;
474 gss_buffer_desc out_data;
475 DATA_BLOB blob = data_blob_null;
478 in_data.value = token_in->data;
479 in_data.length = token_in->length;
481 gss_maj = gss_accept_sec_context(&gss_min,
482 &gse_ctx->gssapi_context,
485 GSS_C_NO_CHANNEL_BINDINGS,
486 &gse_ctx->client_name,
489 &gse_ctx->gss_got_flags, NULL,
490 &gse_ctx->delegated_cred_handle);
493 /* we are done with it */
494 status = NT_STATUS_OK;
496 case GSS_S_CONTINUE_NEEDED:
497 /* we will need a third leg */
498 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
501 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
502 gse_errstr(talloc_tos(), gss_maj, gss_min)));
504 if (gse_ctx->gssapi_context) {
505 gss_delete_sec_context(&gss_min,
506 &gse_ctx->gssapi_context,
510 status = NT_STATUS_INTERNAL_ERROR;
514 /* we may be told to return nothing */
515 if (out_data.length) {
516 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
518 status = NT_STATUS_NO_MEMORY;
520 gss_maj = gss_release_buffer(&gss_min, &out_data);
529 static NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
531 if (memcmp(gse_ctx->ret_mech,
532 gss_mech_krb5, sizeof(gss_OID_desc)) != 0) {
533 return NT_STATUS_ACCESS_DENIED;
536 /* GSS_C_MUTUAL_FLAG */
537 /* GSS_C_DELEG_FLAG */
538 /* GSS_C_DELEG_POLICY_FLAG */
539 /* GSS_C_REPLAY_FLAG */
540 /* GSS_C_SEQUENCE_FLAG */
542 /* GSS_C_INTEG_FLAG */
543 if (gse_ctx->gss_want_flags & GSS_C_INTEG_FLAG) {
544 if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) {
545 return NT_STATUS_ACCESS_DENIED;
549 /* GSS_C_CONF_FLAG */
550 if (gse_ctx->gss_want_flags & GSS_C_CONF_FLAG) {
551 if (!(gse_ctx->gss_got_flags & GSS_C_CONF_FLAG)) {
552 return NT_STATUS_ACCESS_DENIED;
555 /* GSS_C_CONF_FLAG implies GSS_C_INTEG_FLAG */
556 if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) {
557 return NT_STATUS_ACCESS_DENIED;
561 /* GSS_C_DCE_STYLE */
562 if (gse_ctx->gss_want_flags & GSS_C_DCE_STYLE) {
563 if (!(gse_ctx->gss_got_flags & GSS_C_DCE_STYLE)) {
564 return NT_STATUS_ACCESS_DENIED;
566 /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */
567 if (!(gse_ctx->gss_got_flags & GSS_C_MUTUAL_FLAG)) {
568 return NT_STATUS_ACCESS_DENIED;
575 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min)
577 OM_uint32 gss_min, gss_maj;
578 gss_buffer_desc msg_min;
579 gss_buffer_desc msg_maj;
580 OM_uint32 msg_ctx = 0;
584 ZERO_STRUCT(msg_min);
585 ZERO_STRUCT(msg_maj);
587 gss_maj = gss_display_status(&gss_min, maj, GSS_C_GSS_CODE,
588 GSS_C_NO_OID, &msg_ctx, &msg_maj);
592 errstr = talloc_strndup(mem_ctx,
593 (char *)msg_maj.value,
598 gss_maj = gss_display_status(&gss_min, min, GSS_C_MECH_CODE,
599 (gss_OID)discard_const(gss_mech_krb5),
605 errstr = talloc_strdup_append_buffer(errstr, ": ");
609 errstr = talloc_strndup_append_buffer(errstr,
610 (char *)msg_min.value,
618 gss_maj = gss_release_buffer(&gss_min, &msg_min);
621 gss_maj = gss_release_buffer(&gss_min, &msg_maj);
626 static NTSTATUS gse_init_lucid(struct gse_context *gse_ctx)
628 OM_uint32 maj_stat, min_stat;
631 if (gse_ctx->lucid) {
635 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
636 &gse_ctx->gssapi_context,
638 if (maj_stat != GSS_S_COMPLETE) {
639 DEBUG(0,("gse_init_lucid: %s\n",
640 gse_errstr(talloc_tos(), maj_stat, min_stat)));
641 return NT_STATUS_INTERNAL_ERROR;
643 gse_ctx->lucid = (gss_krb5_lucid_context_v1_t *)ptr;
645 if (gse_ctx->lucid->version != 1) {
646 DEBUG(0,("gse_init_lucid: lucid version[%d] != 1\n",
647 gse_ctx->lucid->version));
648 gss_krb5_free_lucid_sec_context(&min_stat, gse_ctx->lucid);
649 gse_ctx->lucid = NULL;
650 return NT_STATUS_INTERNAL_ERROR;
656 static DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
657 struct gse_context *gse_ctx)
659 OM_uint32 gss_min, gss_maj;
660 gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
663 gss_maj = gss_inquire_sec_context_by_oid(
664 &gss_min, gse_ctx->gssapi_context,
665 &gse_sesskey_inq_oid, &set);
667 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
668 gse_errstr(talloc_tos(), gss_maj, gss_min)));
669 return data_blob_null;
672 if ((set == GSS_C_NO_BUFFER_SET) ||
674 (memcmp(set->elements[1].value,
675 gse_sesskeytype_oid.elements,
676 gse_sesskeytype_oid.length) != 0)) {
677 #ifdef HAVE_GSSKRB5_GET_SUBKEY
678 krb5_keyblock *subkey;
679 gss_maj = gsskrb5_get_subkey(&gss_min,
680 gse_ctx->gssapi_context,
683 DEBUG(1, ("NO session key for this mech\n"));
684 return data_blob_null;
686 ret = data_blob_talloc(mem_ctx,
687 KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
688 krb5_free_keyblock(NULL /* should be krb5_context */, subkey);
691 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
692 "OID for data in results:\n"));
693 dump_data(1, (uint8_t *)set->elements[1].value,
694 set->elements[1].length);
695 return data_blob_null;
699 ret = data_blob_talloc(mem_ctx, set->elements[0].value,
700 set->elements[0].length);
702 gss_maj = gss_release_buffer_set(&gss_min, &set);
706 static size_t gse_get_signature_length(struct gse_context *gse_ctx,
707 bool seal, size_t payload_size)
709 OM_uint32 gss_min, gss_maj;
710 gss_iov_buffer_desc iov[2];
714 * gss_wrap_iov_length() only needs the type and length
716 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
717 iov[0].buffer.value = NULL;
718 iov[0].buffer.length = 0;
719 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
720 iov[1].buffer.value = NULL;
721 iov[1].buffer.length = payload_size;
723 gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gssapi_context,
724 seal, GSS_C_QOP_DEFAULT,
727 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
728 gse_errstr(talloc_tos(), gss_maj, gss_min)));
732 return iov[0].buffer.length;
735 static NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
736 DATA_BLOB *data, DATA_BLOB *signature)
738 OM_uint32 gss_min, gss_maj;
739 gss_iov_buffer_desc iov[2];
740 int req_seal = 1; /* setting to 1 means we request sign+seal */
744 /* allocate the memory ourselves so we do not need to talloc_memdup */
745 signature->length = gse_get_signature_length(gse_ctx, true, data->length);
746 if (!signature->length) {
747 return NT_STATUS_INTERNAL_ERROR;
749 signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
750 if (!signature->data) {
751 return NT_STATUS_NO_MEMORY;
753 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
754 iov[0].buffer.value = signature->data;
755 iov[0].buffer.length = signature->length;
757 /* data is encrypted in place, which is ok */
758 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
759 iov[1].buffer.value = data->data;
760 iov[1].buffer.length = data->length;
762 gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gssapi_context,
763 req_seal, GSS_C_QOP_DEFAULT,
766 DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
767 gse_errstr(talloc_tos(), gss_maj, gss_min)));
768 status = NT_STATUS_ACCESS_DENIED;
773 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
774 status = NT_STATUS_ACCESS_DENIED;
778 status = NT_STATUS_OK;
780 DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
781 (int)iov[1].buffer.length, (int)iov[0].buffer.length));
787 static NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
788 DATA_BLOB *data, const DATA_BLOB *signature)
790 OM_uint32 gss_min, gss_maj;
791 gss_iov_buffer_desc iov[2];
795 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
796 iov[0].buffer.value = signature->data;
797 iov[0].buffer.length = signature->length;
799 /* data is decrypted in place, which is ok */
800 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
801 iov[1].buffer.value = data->data;
802 iov[1].buffer.length = data->length;
804 gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gssapi_context,
805 &sealed, NULL, iov, 2);
807 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
808 gse_errstr(talloc_tos(), gss_maj, gss_min)));
809 status = NT_STATUS_ACCESS_DENIED;
814 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
815 status = NT_STATUS_ACCESS_DENIED;
819 status = NT_STATUS_OK;
821 DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
822 (int)iov[1].buffer.length, (int)iov[0].buffer.length));
828 static NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
829 DATA_BLOB *data, DATA_BLOB *signature)
831 OM_uint32 gss_min, gss_maj;
832 gss_buffer_desc in_data = { 0, NULL };
833 gss_buffer_desc out_data = { 0, NULL};
836 in_data.value = data->data;
837 in_data.length = data->length;
839 gss_maj = gss_get_mic(&gss_min, gse_ctx->gssapi_context,
841 &in_data, &out_data);
843 DEBUG(0, ("gss_get_mic failed with [%s]\n",
844 gse_errstr(talloc_tos(), gss_maj, gss_min)));
845 status = NT_STATUS_ACCESS_DENIED;
849 *signature = data_blob_talloc(mem_ctx,
850 out_data.value, out_data.length);
851 if (!signature->data) {
852 status = NT_STATUS_NO_MEMORY;
856 status = NT_STATUS_OK;
859 if (out_data.value) {
860 gss_maj = gss_release_buffer(&gss_min, &out_data);
865 static NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
866 const DATA_BLOB *data, const DATA_BLOB *signature)
868 OM_uint32 gss_min, gss_maj;
869 gss_buffer_desc in_data = { 0, NULL };
870 gss_buffer_desc in_token = { 0, NULL};
873 in_data.value = data->data;
874 in_data.length = data->length;
875 in_token.value = signature->data;
876 in_token.length = signature->length;
878 gss_maj = gss_verify_mic(&gss_min, gse_ctx->gssapi_context,
879 &in_data, &in_token, NULL);
881 DEBUG(0, ("gss_verify_mic failed with [%s]\n",
882 gse_errstr(talloc_tos(), gss_maj, gss_min)));
883 status = NT_STATUS_ACCESS_DENIED;
887 status = NT_STATUS_OK;
893 static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
895 struct gse_context *gse_ctx;
896 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
898 OM_uint32 want_flags = 0;
899 bool do_sign = false, do_seal = false;
900 const char *hostname = gensec_get_target_hostname(gensec_security);
901 const char *service = gensec_get_target_service(gensec_security);
902 const char *username = cli_credentials_get_username(creds);
903 const char *password = cli_credentials_get_password(creds);
906 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
907 return NT_STATUS_INVALID_PARAMETER;
909 if (is_ipaddress(hostname)) {
910 DEBUG(2, ("Cannot do GSE to an IP address\n"));
911 return NT_STATUS_INVALID_PARAMETER;
913 if (strcmp(hostname, "localhost") == 0) {
914 DEBUG(2, ("GSE to 'localhost' does not make sense\n"));
915 return NT_STATUS_INVALID_PARAMETER;
918 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
921 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
924 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
925 want_flags |= GSS_C_DCE_STYLE;
928 nt_status = gse_init_client(gensec_security, do_sign, do_seal, NULL,
930 username, password, want_flags,
932 if (!NT_STATUS_IS_OK(nt_status)) {
935 gensec_security->private_data = gse_ctx;
939 static NTSTATUS gensec_gse_server_start(struct gensec_security *gensec_security)
941 struct gse_context *gse_ctx;
943 OM_uint32 want_flags = 0;
944 bool do_sign = false, do_seal = false;
946 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
949 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
952 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
953 want_flags |= GSS_C_DCE_STYLE;
956 nt_status = gse_init_server(gensec_security, do_sign, do_seal, want_flags,
958 if (!NT_STATUS_IS_OK(nt_status)) {
961 gensec_security->private_data = gse_ctx;
966 * Check if the packet is one for this mechansim
968 * @param gensec_security GENSEC state
969 * @param in The request, as a DATA_BLOB
970 * @return Error, INVALID_PARAMETER if it's not a packet for us
971 * or NT_STATUS_OK if the packet is ok.
974 static NTSTATUS gensec_gse_magic(struct gensec_security *gensec_security,
977 if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
980 return NT_STATUS_INVALID_PARAMETER;
986 * Next state function for the GSE GENSEC mechanism
988 * @param gensec_gse_state GSE State
989 * @param mem_ctx The TALLOC_CTX for *out to be allocated on
990 * @param in The request, as a DATA_BLOB
991 * @param out The reply, as an talloc()ed DATA_BLOB, on *mem_ctx
992 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
993 * or NT_STATUS_OK if the user is authenticated.
996 static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security,
998 struct tevent_context *ev,
999 const DATA_BLOB in, DATA_BLOB *out)
1002 struct gse_context *gse_ctx =
1003 talloc_get_type_abort(gensec_security->private_data,
1004 struct gse_context);
1006 switch (gensec_security->gensec_role) {
1008 status = gse_get_client_auth_token(mem_ctx, gse_ctx,
1012 status = gse_get_server_auth_token(mem_ctx, gse_ctx,
1016 if (!NT_STATUS_IS_OK(status)) {
1020 if (gensec_security->gensec_role == GENSEC_SERVER) {
1021 return gse_verify_server_auth_flags(gse_ctx);
1024 return NT_STATUS_OK;
1027 static NTSTATUS gensec_gse_wrap(struct gensec_security *gensec_security,
1028 TALLOC_CTX *mem_ctx,
1029 const DATA_BLOB *in,
1032 struct gse_context *gse_ctx =
1033 talloc_get_type_abort(gensec_security->private_data,
1034 struct gse_context);
1035 OM_uint32 maj_stat, min_stat;
1036 gss_buffer_desc input_token, output_token;
1038 input_token.length = in->length;
1039 input_token.value = in->data;
1041 maj_stat = gss_wrap(&min_stat,
1042 gse_ctx->gssapi_context,
1043 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1048 if (GSS_ERROR(maj_stat)) {
1049 DEBUG(0, ("gensec_gse_wrap: GSS Wrap failed: %s\n",
1050 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1051 return NT_STATUS_ACCESS_DENIED;
1054 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1055 gss_release_buffer(&min_stat, &output_token);
1057 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1059 return NT_STATUS_ACCESS_DENIED;
1061 return NT_STATUS_OK;
1064 static NTSTATUS gensec_gse_unwrap(struct gensec_security *gensec_security,
1065 TALLOC_CTX *mem_ctx,
1066 const DATA_BLOB *in,
1069 struct gse_context *gse_ctx =
1070 talloc_get_type_abort(gensec_security->private_data,
1071 struct gse_context);
1072 OM_uint32 maj_stat, min_stat;
1073 gss_buffer_desc input_token, output_token;
1075 gss_qop_t qop_state;
1076 input_token.length = in->length;
1077 input_token.value = in->data;
1079 maj_stat = gss_unwrap(&min_stat,
1080 gse_ctx->gssapi_context,
1085 if (GSS_ERROR(maj_stat)) {
1086 DEBUG(0, ("gensec_gse_unwrap: GSS UnWrap failed: %s\n",
1087 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1088 return NT_STATUS_ACCESS_DENIED;
1091 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1092 gss_release_buffer(&min_stat, &output_token);
1094 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1096 return NT_STATUS_ACCESS_DENIED;
1098 return NT_STATUS_OK;
1101 static NTSTATUS gensec_gse_seal_packet(struct gensec_security *gensec_security,
1102 TALLOC_CTX *mem_ctx,
1103 uint8_t *data, size_t length,
1104 const uint8_t *whole_pdu, size_t pdu_length,
1107 struct gse_context *gse_ctx =
1108 talloc_get_type_abort(gensec_security->private_data,
1109 struct gse_context);
1110 DATA_BLOB payload = data_blob_const(data, length);
1111 return gse_seal(mem_ctx, gse_ctx, &payload, sig);
1114 static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security,
1115 uint8_t *data, size_t length,
1116 const uint8_t *whole_pdu, size_t pdu_length,
1117 const DATA_BLOB *sig)
1119 struct gse_context *gse_ctx =
1120 talloc_get_type_abort(gensec_security->private_data,
1121 struct gse_context);
1122 DATA_BLOB payload = data_blob_const(data, length);
1123 return gse_unseal(talloc_tos() /* unused */, gse_ctx, &payload, sig);
1126 static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security,
1127 TALLOC_CTX *mem_ctx,
1128 const uint8_t *data, size_t length,
1129 const uint8_t *whole_pdu, size_t pdu_length,
1132 struct gse_context *gse_ctx =
1133 talloc_get_type_abort(gensec_security->private_data,
1134 struct gse_context);
1135 DATA_BLOB payload = data_blob_const(data, length);
1136 return gse_sign(mem_ctx, gse_ctx, &payload, sig);
1139 static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security,
1140 const uint8_t *data, size_t length,
1141 const uint8_t *whole_pdu, size_t pdu_length,
1142 const DATA_BLOB *sig)
1144 struct gse_context *gse_ctx =
1145 talloc_get_type_abort(gensec_security->private_data,
1146 struct gse_context);
1147 DATA_BLOB payload = data_blob_const(data, length);
1148 return gse_sigcheck(NULL, gse_ctx, &payload, sig);
1151 /* Try to figure out what features we actually got on the connection */
1152 static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
1155 struct gse_context *gse_ctx =
1156 talloc_get_type_abort(gensec_security->private_data,
1157 struct gse_context);
1159 if (feature & GENSEC_FEATURE_SIGN) {
1160 return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
1162 if (feature & GENSEC_FEATURE_SEAL) {
1163 return gse_ctx->gss_got_flags & GSS_C_CONF_FLAG;
1165 if (feature & GENSEC_FEATURE_SESSION_KEY) {
1166 /* Only for GSE/Krb5 */
1167 if (gss_oid_equal(gse_ctx->ret_mech, gss_mech_krb5)) {
1171 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1172 return gse_ctx->gss_got_flags & GSS_C_DCE_STYLE;
1174 if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1177 if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) {
1181 status = gse_init_lucid(gse_ctx);
1182 if (!NT_STATUS_IS_OK(status)) {
1186 if (gse_ctx->lucid->protocol == 1) {
1192 /* We can always do async (rather than strict request/reply) packets. */
1193 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1200 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1201 * (for encrypting some passwords).
1203 * This breaks all the abstractions, but what do you expect...
1205 static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security,
1206 TALLOC_CTX *mem_ctx,
1207 DATA_BLOB *session_key_out)
1209 struct gse_context *gse_ctx =
1210 talloc_get_type_abort(gensec_security->private_data,
1211 struct gse_context);
1213 DATA_BLOB session_key = gse_get_session_key(mem_ctx, gse_ctx);
1214 if (session_key.data == NULL) {
1215 return NT_STATUS_NO_USER_SESSION_KEY;
1218 *session_key_out = session_key;
1220 return NT_STATUS_OK;
1223 /* Get some basic (and authorization) information about the user on
1224 * this session. This uses either the PAC (if present) or a local
1225 * database lookup */
1226 static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security,
1227 TALLOC_CTX *mem_ctx,
1228 struct auth_session_info **_session_info)
1230 struct gse_context *gse_ctx =
1231 talloc_get_type_abort(gensec_security->private_data,
1232 struct gse_context);
1234 TALLOC_CTX *tmp_ctx;
1235 struct auth_session_info *session_info = NULL;
1236 OM_uint32 maj_stat, min_stat;
1237 DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1239 gss_buffer_desc name_token;
1240 char *principal_string;
1242 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gse_session_info context");
1243 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1245 maj_stat = gss_display_name(&min_stat,
1246 gse_ctx->client_name,
1249 if (GSS_ERROR(maj_stat)) {
1250 DEBUG(1, ("GSS display_name failed: %s\n",
1251 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1252 talloc_free(tmp_ctx);
1253 return NT_STATUS_FOOBAR;
1256 principal_string = talloc_strndup(tmp_ctx,
1257 (const char *)name_token.value,
1260 gss_release_buffer(&min_stat, &name_token);
1262 if (!principal_string) {
1263 talloc_free(tmp_ctx);
1264 return NT_STATUS_NO_MEMORY;
1267 nt_status = gssapi_obtain_pac_blob(tmp_ctx, gse_ctx->gssapi_context,
1268 gse_ctx->client_name,
1271 /* IF we have the PAC - otherwise we need to get this
1272 * data from elsewere
1274 if (NT_STATUS_IS_OK(nt_status)) {
1275 pac_blob_ptr = &pac_blob;
1277 nt_status = gensec_generate_session_info_pac(tmp_ctx,
1280 pac_blob_ptr, principal_string,
1281 gensec_get_remote_address(gensec_security),
1283 if (!NT_STATUS_IS_OK(nt_status)) {
1284 talloc_free(tmp_ctx);
1288 nt_status = gensec_gse_session_key(gensec_security, session_info,
1289 &session_info->session_key);
1290 if (!NT_STATUS_IS_OK(nt_status)) {
1291 talloc_free(tmp_ctx);
1295 *_session_info = talloc_move(mem_ctx, &session_info);
1296 talloc_free(tmp_ctx);
1298 return NT_STATUS_OK;
1301 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
1304 struct gse_context *gse_ctx =
1305 talloc_get_type_abort(gensec_security->private_data,
1306 struct gse_context);
1308 return gse_get_signature_length(gse_ctx,
1309 gensec_security->want_features & GENSEC_FEATURE_SEAL,
1313 static const char *gensec_gse_krb5_oids[] = {
1314 GENSEC_OID_KERBEROS5_OLD,
1315 GENSEC_OID_KERBEROS5,
1319 const struct gensec_security_ops gensec_gse_krb5_security_ops = {
1321 .auth_type = DCERPC_AUTH_TYPE_KRB5,
1322 .oid = gensec_gse_krb5_oids,
1323 .client_start = gensec_gse_client_start,
1324 .server_start = gensec_gse_server_start,
1325 .magic = gensec_gse_magic,
1326 .update = gensec_gse_update,
1327 .session_key = gensec_gse_session_key,
1328 .session_info = gensec_gse_session_info,
1329 .sig_size = gensec_gse_sig_size,
1330 .sign_packet = gensec_gse_sign_packet,
1331 .check_packet = gensec_gse_check_packet,
1332 .seal_packet = gensec_gse_seal_packet,
1333 .unseal_packet = gensec_gse_unseal_packet,
1334 .wrap = gensec_gse_wrap,
1335 .unwrap = gensec_gse_unwrap,
1336 .have_feature = gensec_gse_have_feature,
1339 .priority = GENSEC_GSSAPI
1342 #endif /* HAVE_KRB5 && HAVE_GSS_WRAP_IOV */