s3-gse Make gse available as a gensec client module
[Samba/gebeck_regimport.git] / source3 / librpc / crypto / gse.c
blobbd7146c1c87a31e98a4503fd7200d37b3d3e2037
1 /*
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 */
24 #include "includes.h"
25 #include "gse.h"
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)
34 #include "smb_krb5.h"
35 #include "gse_krb5.h"
37 #ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
38 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
39 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
40 #endif
42 gss_OID_desc gse_sesskey_inq_oid = {
43 GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
44 (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
47 #ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
48 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
49 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
50 #endif
52 gss_OID_desc gse_sesskeytype_oid = {
53 GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
54 (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
57 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH 12
58 /* EXTRACTION OID AUTHZ ID */
59 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" "\x01"
61 gss_OID_desc gse_authz_data_oid = {
62 GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH,
63 (void *)GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID
66 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
68 struct gse_context {
69 krb5_context k5ctx;
70 krb5_ccache ccache;
71 krb5_keytab keytab;
73 gss_ctx_id_t gss_ctx;
75 gss_OID_desc gss_mech;
76 OM_uint32 gss_c_flags;
77 gss_cred_id_t creds;
78 gss_name_t server_name;
80 gss_OID ret_mech;
81 OM_uint32 ret_flags;
82 gss_cred_id_t delegated_creds;
83 gss_name_t client_name;
85 bool more_processing;
86 bool authenticated;
89 #ifndef HAVE_GSS_OID_EQUAL
91 static bool gss_oid_equal(const gss_OID o1, const gss_OID o2)
93 if (o1 == o2) {
94 return true;
96 if ((o1 == NULL && o2 != NULL) || (o1 != NULL && o2 == NULL)) {
97 return false;
99 if (o1->length != o2->length) {
100 return false;
102 return memcmp(o1->elements, o2->elements, o1->length) == false;
105 #endif
107 /* free non talloc dependent contexts */
108 static int gse_context_destructor(void *ptr)
110 struct gse_context *gse_ctx;
111 OM_uint32 gss_min, gss_maj;
113 gse_ctx = talloc_get_type_abort(ptr, struct gse_context);
114 if (gse_ctx->k5ctx) {
115 if (gse_ctx->ccache) {
116 krb5_cc_close(gse_ctx->k5ctx, gse_ctx->ccache);
117 gse_ctx->ccache = NULL;
119 if (gse_ctx->keytab) {
120 krb5_kt_close(gse_ctx->k5ctx, gse_ctx->keytab);
121 gse_ctx->keytab = NULL;
123 krb5_free_context(gse_ctx->k5ctx);
124 gse_ctx->k5ctx = NULL;
126 if (gse_ctx->gss_ctx != GSS_C_NO_CONTEXT) {
127 gss_maj = gss_delete_sec_context(&gss_min,
128 &gse_ctx->gss_ctx,
129 GSS_C_NO_BUFFER);
131 if (gse_ctx->server_name) {
132 gss_maj = gss_release_name(&gss_min,
133 &gse_ctx->server_name);
135 if (gse_ctx->client_name) {
136 gss_maj = gss_release_name(&gss_min,
137 &gse_ctx->client_name);
139 if (gse_ctx->creds) {
140 gss_maj = gss_release_cred(&gss_min,
141 &gse_ctx->creds);
143 if (gse_ctx->delegated_creds) {
144 gss_maj = gss_release_cred(&gss_min,
145 &gse_ctx->delegated_creds);
148 /* MIT and Heimdal differ as to if you can call
149 * gss_release_oid() on this OID, generated by
150 * gss_{accept,init}_sec_context(). However, as long as the
151 * oid is gss_mech_krb5 (which it always is at the moment),
152 * then this is a moot point, as both declare this particular
153 * OID static, and so no memory is lost. This assert is in
154 * place to ensure that the programmer who wishes to extend
155 * this code to EAP or other GSS mechanisms determines an
156 * implementation-dependent way of releasing any dynamically
157 * allocated OID */
158 SMB_ASSERT(gss_oid_equal(&gse_ctx->gss_mech, GSS_C_NO_OID) || gss_oid_equal(&gse_ctx->gss_mech, gss_mech_krb5));
160 return 0;
163 static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
164 bool do_sign, bool do_seal,
165 const char *ccache_name,
166 uint32_t add_gss_c_flags,
167 struct gse_context **_gse_ctx)
169 struct gse_context *gse_ctx;
170 krb5_error_code k5ret;
171 NTSTATUS status;
173 gse_ctx = talloc_zero(mem_ctx, struct gse_context);
174 if (!gse_ctx) {
175 return NT_STATUS_NO_MEMORY;
177 talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
179 memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
181 gse_ctx->gss_c_flags = GSS_C_MUTUAL_FLAG |
182 GSS_C_DELEG_FLAG |
183 GSS_C_DELEG_POLICY_FLAG |
184 GSS_C_REPLAY_FLAG |
185 GSS_C_SEQUENCE_FLAG;
186 if (do_sign) {
187 gse_ctx->gss_c_flags |= GSS_C_INTEG_FLAG;
189 if (do_seal) {
190 gse_ctx->gss_c_flags |= GSS_C_CONF_FLAG;
193 gse_ctx->gss_c_flags |= add_gss_c_flags;
195 /* Initialize Kerberos Context */
196 initialize_krb5_error_table();
198 k5ret = krb5_init_context(&gse_ctx->k5ctx);
199 if (k5ret) {
200 DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
201 error_message(k5ret)));
202 status = NT_STATUS_INTERNAL_ERROR;
203 goto err_out;
206 if (!ccache_name) {
207 ccache_name = krb5_cc_default_name(gse_ctx->k5ctx);
209 k5ret = krb5_cc_resolve(gse_ctx->k5ctx, ccache_name,
210 &gse_ctx->ccache);
211 if (k5ret) {
212 DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
213 error_message(k5ret)));
214 status = NT_STATUS_INTERNAL_ERROR;
215 goto err_out;
218 /* TODO: Should we enforce a enc_types list ?
219 ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
222 *_gse_ctx = gse_ctx;
223 return NT_STATUS_OK;
225 err_out:
226 TALLOC_FREE(gse_ctx);
227 return status;
230 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
231 bool do_sign, bool do_seal,
232 const char *ccache_name,
233 const char *server,
234 const char *service,
235 const char *username,
236 const char *password,
237 uint32_t add_gss_c_flags,
238 struct gse_context **_gse_ctx)
240 struct gse_context *gse_ctx;
241 OM_uint32 gss_maj, gss_min;
242 gss_buffer_desc name_buffer = {0, NULL};
243 gss_OID_set_desc mech_set;
244 NTSTATUS status;
246 if (!server || !service) {
247 return NT_STATUS_INVALID_PARAMETER;
250 status = gse_context_init(mem_ctx, do_sign, do_seal,
251 ccache_name, add_gss_c_flags,
252 &gse_ctx);
253 if (!NT_STATUS_IS_OK(status)) {
254 return NT_STATUS_NO_MEMORY;
257 /* Guess the realm based on the supplied service, and avoid the GSS libs
258 doing DNS lookups which may fail.
260 TODO: Loop with the KDC on some more combinations (local
261 realm in particular), possibly falling back to
262 GSS_C_NT_HOSTBASED_SERVICE
264 name_buffer.value = kerberos_get_principal_from_service_hostname(gse_ctx,
265 service, server);
266 if (!name_buffer.value) {
267 status = NT_STATUS_NO_MEMORY;
268 goto err_out;
270 name_buffer.length = strlen((char *)name_buffer.value);
271 gss_maj = gss_import_name(&gss_min, &name_buffer,
272 GSS_C_NT_USER_NAME,
273 &gse_ctx->server_name);
274 if (gss_maj) {
275 DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
276 (char *)name_buffer.value,
277 gse_errstr(gse_ctx, gss_maj, gss_min)));
278 status = NT_STATUS_INTERNAL_ERROR;
279 goto err_out;
282 /* TODO: get krb5 ticket using username/password, if no valid
283 * one already available in ccache */
285 mech_set.count = 1;
286 mech_set.elements = &gse_ctx->gss_mech;
288 gss_maj = gss_acquire_cred(&gss_min,
289 GSS_C_NO_NAME,
290 GSS_C_INDEFINITE,
291 &mech_set,
292 GSS_C_INITIATE,
293 &gse_ctx->creds,
294 NULL, NULL);
295 if (gss_maj) {
296 DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
297 (char *)name_buffer.value,
298 gse_errstr(gse_ctx, gss_maj, gss_min)));
299 status = NT_STATUS_INTERNAL_ERROR;
300 goto err_out;
303 *_gse_ctx = gse_ctx;
304 TALLOC_FREE(name_buffer.value);
305 return NT_STATUS_OK;
307 err_out:
308 TALLOC_FREE(name_buffer.value);
309 TALLOC_FREE(gse_ctx);
310 return status;
313 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
314 struct gse_context *gse_ctx,
315 DATA_BLOB *token_in,
316 DATA_BLOB *token_out)
318 OM_uint32 gss_maj, gss_min;
319 gss_buffer_desc in_data;
320 gss_buffer_desc out_data;
321 DATA_BLOB blob = data_blob_null;
322 NTSTATUS status;
324 in_data.value = token_in->data;
325 in_data.length = token_in->length;
327 gss_maj = gss_init_sec_context(&gss_min,
328 gse_ctx->creds,
329 &gse_ctx->gss_ctx,
330 gse_ctx->server_name,
331 &gse_ctx->gss_mech,
332 gse_ctx->gss_c_flags,
333 0, GSS_C_NO_CHANNEL_BINDINGS,
334 &in_data, NULL, &out_data,
335 &gse_ctx->ret_flags, NULL);
336 switch (gss_maj) {
337 case GSS_S_COMPLETE:
338 /* we are done with it */
339 gse_ctx->more_processing = false;
340 status = NT_STATUS_OK;
341 break;
342 case GSS_S_CONTINUE_NEEDED:
343 /* we will need a third leg */
344 gse_ctx->more_processing = true;
345 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
346 status = NT_STATUS_OK;
347 break;
348 default:
349 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
350 gse_errstr(talloc_tos(), gss_maj, gss_min)));
351 status = NT_STATUS_INTERNAL_ERROR;
352 goto done;
355 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
356 if (!blob.data) {
357 status = NT_STATUS_NO_MEMORY;
360 gss_maj = gss_release_buffer(&gss_min, &out_data);
362 done:
363 *token_out = blob;
364 return status;
367 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
368 bool do_sign, bool do_seal,
369 uint32_t add_gss_c_flags,
370 struct gse_context **_gse_ctx)
372 struct gse_context *gse_ctx;
373 OM_uint32 gss_maj, gss_min;
374 krb5_error_code ret;
375 NTSTATUS status;
377 status = gse_context_init(mem_ctx, do_sign, do_seal,
378 NULL, add_gss_c_flags, &gse_ctx);
379 if (!NT_STATUS_IS_OK(status)) {
380 return NT_STATUS_NO_MEMORY;
383 ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx,
384 &gse_ctx->keytab);
385 if (ret) {
386 status = NT_STATUS_INTERNAL_ERROR;
387 goto done;
390 #ifdef HAVE_GSS_KRB5_IMPORT_CRED
392 /* This creates a GSSAPI cred_id_t with the keytab set */
393 gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab,
394 &gse_ctx->creds);
396 if (gss_maj != 0
397 && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) {
398 DEBUG(0, ("gss_krb5_import_cred failed with [%s]\n",
399 gse_errstr(gse_ctx, gss_maj, gss_min)));
400 status = NT_STATUS_INTERNAL_ERROR;
401 goto done;
403 /* This is the error the MIT krb5 1.9 gives when it
404 * implements the function, but we do not specify the
405 * principal. However, when we specify the principal
406 * as host$@REALM the GSS acceptor fails with 'wrong
407 * principal in request'. Work around the issue by
408 * falling back to the alternate approach below. */
409 } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME))
410 #endif
411 /* FIXME!!!
412 * This call sets the default keytab for the whole server, not
413 * just for this context. Need to find a way that does not alter
414 * the state of the whole server ... */
416 const char *ktname;
417 gss_OID_set_desc mech_set;
419 ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx,
420 gse_ctx->keytab, &ktname);
421 if (ret) {
422 status = NT_STATUS_INTERNAL_ERROR;
423 goto done;
426 ret = gsskrb5_register_acceptor_identity(ktname);
427 if (ret) {
428 status = NT_STATUS_INTERNAL_ERROR;
429 goto done;
432 mech_set.count = 1;
433 mech_set.elements = &gse_ctx->gss_mech;
435 gss_maj = gss_acquire_cred(&gss_min,
436 GSS_C_NO_NAME,
437 GSS_C_INDEFINITE,
438 &mech_set,
439 GSS_C_ACCEPT,
440 &gse_ctx->creds,
441 NULL, NULL);
443 if (gss_maj) {
444 DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
445 gse_errstr(gse_ctx, gss_maj, gss_min)));
446 status = NT_STATUS_INTERNAL_ERROR;
447 goto done;
451 status = NT_STATUS_OK;
453 done:
454 if (!NT_STATUS_IS_OK(status)) {
455 TALLOC_FREE(gse_ctx);
458 *_gse_ctx = gse_ctx;
459 return status;
462 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
463 struct gse_context *gse_ctx,
464 DATA_BLOB *token_in,
465 DATA_BLOB *token_out)
467 OM_uint32 gss_maj, gss_min;
468 gss_buffer_desc in_data;
469 gss_buffer_desc out_data;
470 DATA_BLOB blob = data_blob_null;
471 NTSTATUS status;
473 in_data.value = token_in->data;
474 in_data.length = token_in->length;
476 gss_maj = gss_accept_sec_context(&gss_min,
477 &gse_ctx->gss_ctx,
478 gse_ctx->creds,
479 &in_data,
480 GSS_C_NO_CHANNEL_BINDINGS,
481 &gse_ctx->client_name,
482 &gse_ctx->ret_mech,
483 &out_data,
484 &gse_ctx->ret_flags, NULL,
485 &gse_ctx->delegated_creds);
486 switch (gss_maj) {
487 case GSS_S_COMPLETE:
488 /* we are done with it */
489 gse_ctx->more_processing = false;
490 gse_ctx->authenticated = true;
491 status = NT_STATUS_OK;
492 break;
493 case GSS_S_CONTINUE_NEEDED:
494 /* we will need a third leg */
495 gse_ctx->more_processing = true;
496 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
497 status = NT_STATUS_OK;
498 break;
499 default:
500 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
501 gse_errstr(talloc_tos(), gss_maj, gss_min)));
503 if (gse_ctx->gss_ctx) {
504 gss_delete_sec_context(&gss_min,
505 &gse_ctx->gss_ctx,
506 GSS_C_NO_BUFFER);
509 status = NT_STATUS_INTERNAL_ERROR;
510 goto done;
513 /* we may be told to return nothing */
514 if (out_data.length) {
515 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
516 if (!blob.data) {
517 status = NT_STATUS_NO_MEMORY;
519 gss_maj = gss_release_buffer(&gss_min, &out_data);
523 done:
524 *token_out = blob;
525 return status;
528 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
530 if (!gse_ctx->authenticated) {
531 return NT_STATUS_INVALID_HANDLE;
534 if (memcmp(gse_ctx->ret_mech,
535 gss_mech_krb5, sizeof(gss_OID_desc)) != 0) {
536 return NT_STATUS_ACCESS_DENIED;
539 /* GSS_C_MUTUAL_FLAG */
540 if (gse_ctx->gss_c_flags & GSS_C_MUTUAL_FLAG) {
541 if (!(gse_ctx->ret_flags & GSS_C_MUTUAL_FLAG)) {
542 return NT_STATUS_ACCESS_DENIED;
546 /* GSS_C_DELEG_FLAG */
547 /* GSS_C_DELEG_POLICY_FLAG */
548 /* GSS_C_REPLAY_FLAG */
549 /* GSS_C_SEQUENCE_FLAG */
551 /* GSS_C_INTEG_FLAG */
552 if (gse_ctx->gss_c_flags & GSS_C_INTEG_FLAG) {
553 if (!(gse_ctx->ret_flags & GSS_C_INTEG_FLAG)) {
554 return NT_STATUS_ACCESS_DENIED;
558 /* GSS_C_CONF_FLAG */
559 if (gse_ctx->gss_c_flags & GSS_C_CONF_FLAG) {
560 if (!(gse_ctx->ret_flags & GSS_C_CONF_FLAG)) {
561 return NT_STATUS_ACCESS_DENIED;
565 return NT_STATUS_OK;
568 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min)
570 OM_uint32 gss_min, gss_maj;
571 gss_buffer_desc msg_min;
572 gss_buffer_desc msg_maj;
573 OM_uint32 msg_ctx = 0;
575 char *errstr = NULL;
577 ZERO_STRUCT(msg_min);
578 ZERO_STRUCT(msg_maj);
580 gss_maj = gss_display_status(&gss_min, maj, GSS_C_GSS_CODE,
581 GSS_C_NO_OID, &msg_ctx, &msg_maj);
582 if (gss_maj) {
583 goto done;
585 errstr = talloc_strndup(mem_ctx,
586 (char *)msg_maj.value,
587 msg_maj.length);
588 if (!errstr) {
589 goto done;
591 gss_maj = gss_display_status(&gss_min, min, GSS_C_MECH_CODE,
592 (gss_OID)discard_const(gss_mech_krb5),
593 &msg_ctx, &msg_min);
594 if (gss_maj) {
595 goto done;
598 errstr = talloc_strdup_append_buffer(errstr, ": ");
599 if (!errstr) {
600 goto done;
602 errstr = talloc_strndup_append_buffer(errstr,
603 (char *)msg_min.value,
604 msg_min.length);
605 if (!errstr) {
606 goto done;
609 done:
610 if (msg_min.value) {
611 gss_maj = gss_release_buffer(&gss_min, &msg_min);
613 if (msg_maj.value) {
614 gss_maj = gss_release_buffer(&gss_min, &msg_maj);
616 return errstr;
619 bool gse_require_more_processing(struct gse_context *gse_ctx)
621 return gse_ctx->more_processing;
624 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
625 struct gse_context *gse_ctx)
627 OM_uint32 gss_min, gss_maj;
628 gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
629 DATA_BLOB ret;
631 gss_maj = gss_inquire_sec_context_by_oid(
632 &gss_min, gse_ctx->gss_ctx,
633 &gse_sesskey_inq_oid, &set);
634 if (gss_maj) {
635 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
636 gse_errstr(talloc_tos(), gss_maj, gss_min)));
637 return data_blob_null;
640 if ((set == GSS_C_NO_BUFFER_SET) ||
641 (set->count != 2) ||
642 (memcmp(set->elements[1].value,
643 gse_sesskeytype_oid.elements,
644 gse_sesskeytype_oid.length) != 0)) {
645 #ifdef HAVE_GSSKRB5_GET_SUBKEY
646 krb5_keyblock *subkey;
647 gss_maj = gsskrb5_get_subkey(&gss_min,
648 gse_ctx->gss_ctx,
649 &subkey);
650 if (gss_maj != 0) {
651 DEBUG(1, ("NO session key for this mech\n"));
652 return data_blob_null;
654 ret = data_blob_talloc(mem_ctx,
655 KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
656 krb5_free_keyblock(NULL /* should be krb5_context */, subkey);
657 return ret;
658 #else
659 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
660 "OID for data in results:\n"));
661 dump_data(1, (uint8_t *)set->elements[1].value,
662 set->elements[1].length);
663 return data_blob_null;
664 #endif
667 ret = data_blob_talloc(mem_ctx, set->elements[0].value,
668 set->elements[0].length);
670 gss_maj = gss_release_buffer_set(&gss_min, &set);
671 return ret;
674 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
675 TALLOC_CTX *mem_ctx, char **cli_name)
677 OM_uint32 gss_min, gss_maj;
678 gss_buffer_desc name_buffer;
680 if (!gse_ctx->authenticated) {
681 return NT_STATUS_ACCESS_DENIED;
684 if (!gse_ctx->client_name) {
685 return NT_STATUS_NOT_FOUND;
688 /* TODO: check OID matches KRB5 Principal Name OID ? */
690 gss_maj = gss_display_name(&gss_min,
691 gse_ctx->client_name,
692 &name_buffer, NULL);
693 if (gss_maj) {
694 DEBUG(0, ("gss_display_name failed [%s]\n",
695 gse_errstr(talloc_tos(), gss_maj, gss_min)));
696 return NT_STATUS_INTERNAL_ERROR;
699 *cli_name = talloc_strndup(mem_ctx,
700 (char *)name_buffer.value,
701 name_buffer.length);
703 gss_maj = gss_release_buffer(&gss_min, &name_buffer);
705 if (!*cli_name) {
706 return NT_STATUS_NO_MEMORY;
709 return NT_STATUS_OK;
712 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
713 TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
715 OM_uint32 gss_min, gss_maj;
716 gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
718 if (!gse_ctx->authenticated) {
719 return NT_STATUS_ACCESS_DENIED;
722 gss_maj = gss_inquire_sec_context_by_oid(
723 &gss_min, gse_ctx->gss_ctx,
724 &gse_authz_data_oid, &set);
725 if (gss_maj) {
726 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
727 gse_errstr(talloc_tos(), gss_maj, gss_min)));
728 return NT_STATUS_NOT_FOUND;
731 if (set == GSS_C_NO_BUFFER_SET) {
732 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
733 "data in results.\n"));
734 return NT_STATUS_INTERNAL_ERROR;
737 /* for now we just hope it is the first value */
738 *pac = data_blob_talloc(mem_ctx,
739 set->elements[0].value,
740 set->elements[0].length);
742 gss_maj = gss_release_buffer_set(&gss_min, &set);
744 return NT_STATUS_OK;
747 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
748 TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob)
750 if (!gse_ctx->authenticated) {
751 return NT_STATUS_ACCESS_DENIED;
754 return gssapi_obtain_pac_blob(mem_ctx, gse_ctx->gss_ctx,
755 gse_ctx->client_name, pac_blob);
758 size_t gse_get_signature_length(struct gse_context *gse_ctx,
759 int seal, size_t payload_size)
761 OM_uint32 gss_min, gss_maj;
762 gss_iov_buffer_desc iov[2];
763 uint8_t fakebuf[payload_size];
764 int sealed;
766 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
767 iov[0].buffer.value = NULL;
768 iov[0].buffer.length = 0;
769 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
770 iov[1].buffer.value = fakebuf;
771 iov[1].buffer.length = payload_size;
773 gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gss_ctx,
774 seal, GSS_C_QOP_DEFAULT,
775 &sealed, iov, 2);
776 if (gss_maj) {
777 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
778 gse_errstr(talloc_tos(), gss_maj, gss_min)));
779 return 0;
782 return iov[0].buffer.length;
785 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
786 DATA_BLOB *data, DATA_BLOB *signature)
788 OM_uint32 gss_min, gss_maj;
789 gss_iov_buffer_desc iov[2];
790 int req_seal = 1; /* setting to 1 means we request sign+seal */
791 int sealed = 1;
792 NTSTATUS status;
794 /* allocate the memory ourselves so we do not need to talloc_memdup */
795 signature->length = gse_get_signature_length(gse_ctx, 1, data->length);
796 if (!signature->length) {
797 return NT_STATUS_INTERNAL_ERROR;
799 signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
800 if (!signature->data) {
801 return NT_STATUS_NO_MEMORY;
803 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
804 iov[0].buffer.value = signature->data;
805 iov[0].buffer.length = signature->length;
807 /* data is encrypted in place, which is ok */
808 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
809 iov[1].buffer.value = data->data;
810 iov[1].buffer.length = data->length;
812 gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gss_ctx,
813 req_seal, GSS_C_QOP_DEFAULT,
814 &sealed, iov, 2);
815 if (gss_maj) {
816 DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
817 gse_errstr(talloc_tos(), gss_maj, gss_min)));
818 status = NT_STATUS_ACCESS_DENIED;
819 goto done;
822 if (!sealed) {
823 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
824 status = NT_STATUS_ACCESS_DENIED;
825 goto done;
828 status = NT_STATUS_OK;
830 DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
831 (int)iov[1].buffer.length, (int)iov[0].buffer.length));
833 done:
834 return status;
837 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
838 DATA_BLOB *data, DATA_BLOB *signature)
840 OM_uint32 gss_min, gss_maj;
841 gss_iov_buffer_desc iov[2];
842 int sealed;
843 NTSTATUS status;
845 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
846 iov[0].buffer.value = signature->data;
847 iov[0].buffer.length = signature->length;
849 /* data is decrypted in place, which is ok */
850 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
851 iov[1].buffer.value = data->data;
852 iov[1].buffer.length = data->length;
854 gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gss_ctx,
855 &sealed, NULL, iov, 2);
856 if (gss_maj) {
857 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
858 gse_errstr(talloc_tos(), gss_maj, gss_min)));
859 status = NT_STATUS_ACCESS_DENIED;
860 goto done;
863 if (!sealed) {
864 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
865 status = NT_STATUS_ACCESS_DENIED;
866 goto done;
869 status = NT_STATUS_OK;
871 DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
872 (int)iov[1].buffer.length, (int)iov[0].buffer.length));
874 done:
875 return status;
878 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
879 DATA_BLOB *data, DATA_BLOB *signature)
881 OM_uint32 gss_min, gss_maj;
882 gss_buffer_desc in_data = { 0, NULL };
883 gss_buffer_desc out_data = { 0, NULL};
884 NTSTATUS status;
886 in_data.value = data->data;
887 in_data.length = data->length;
889 gss_maj = gss_get_mic(&gss_min, gse_ctx->gss_ctx,
890 GSS_C_QOP_DEFAULT,
891 &in_data, &out_data);
892 if (gss_maj) {
893 DEBUG(0, ("gss_get_mic failed with [%s]\n",
894 gse_errstr(talloc_tos(), gss_maj, gss_min)));
895 status = NT_STATUS_ACCESS_DENIED;
896 goto done;
899 *signature = data_blob_talloc(mem_ctx,
900 out_data.value, out_data.length);
901 if (!signature->data) {
902 status = NT_STATUS_NO_MEMORY;
903 goto done;
906 status = NT_STATUS_OK;
908 done:
909 if (out_data.value) {
910 gss_maj = gss_release_buffer(&gss_min, &out_data);
912 return status;
915 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
916 DATA_BLOB *data, DATA_BLOB *signature)
918 OM_uint32 gss_min, gss_maj;
919 gss_buffer_desc in_data = { 0, NULL };
920 gss_buffer_desc in_token = { 0, NULL};
921 NTSTATUS status;
923 in_data.value = data->data;
924 in_data.length = data->length;
925 in_token.value = signature->data;
926 in_token.length = signature->length;
928 gss_maj = gss_verify_mic(&gss_min, gse_ctx->gss_ctx,
929 &in_data, &in_token, NULL);
930 if (gss_maj) {
931 DEBUG(0, ("gss_verify_mic failed with [%s]\n",
932 gse_errstr(talloc_tos(), gss_maj, gss_min)));
933 status = NT_STATUS_ACCESS_DENIED;
934 goto done;
937 status = NT_STATUS_OK;
939 done:
940 return status;
943 static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
945 struct gse_context *gse_ctx;
946 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
947 NTSTATUS nt_status;
948 OM_uint32 want_flags = 0;
949 bool do_sign = false, do_seal = false;
950 const char *hostname = gensec_get_target_hostname(gensec_security);
951 const char *service = gensec_get_target_service(gensec_security);
952 const char *username = cli_credentials_get_username(creds);
953 const char *password = cli_credentials_get_password(creds);
955 if (!hostname) {
956 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
957 return NT_STATUS_INVALID_PARAMETER;
959 if (is_ipaddress(hostname)) {
960 DEBUG(2, ("Cannot do GSE to an IP address\n"));
961 return NT_STATUS_INVALID_PARAMETER;
963 if (strcmp(hostname, "localhost") == 0) {
964 DEBUG(2, ("GSE to 'localhost' does not make sense\n"));
965 return NT_STATUS_INVALID_PARAMETER;
968 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
969 do_sign = true;
971 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
972 do_seal = true;
974 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
975 want_flags |= GSS_C_DCE_STYLE;
978 nt_status = gse_init_client(gensec_security, do_sign, do_seal, NULL,
979 hostname, service,
980 username, password, want_flags,
981 &gse_ctx);
982 if (!NT_STATUS_IS_OK(nt_status)) {
983 return nt_status;
985 gensec_security->private_data = gse_ctx;
986 return NT_STATUS_OK;
989 static NTSTATUS gensec_gse_server_start(struct gensec_security *gensec_security)
991 struct gse_context *gse_ctx;
992 NTSTATUS nt_status;
993 OM_uint32 want_flags = 0;
994 bool do_sign = false, do_seal = false;
996 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
997 do_sign = true;
999 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
1000 do_seal = true;
1002 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
1003 want_flags |= GSS_C_DCE_STYLE;
1006 nt_status = gse_init_server(gensec_security, do_sign, do_seal, want_flags,
1007 &gse_ctx);
1008 if (!NT_STATUS_IS_OK(nt_status)) {
1009 return nt_status;
1011 gensec_security->private_data = gse_ctx;
1012 return NT_STATUS_OK;
1016 * Check if the packet is one for this mechansim
1018 * @param gensec_security GENSEC state
1019 * @param in The request, as a DATA_BLOB
1020 * @return Error, INVALID_PARAMETER if it's not a packet for us
1021 * or NT_STATUS_OK if the packet is ok.
1024 static NTSTATUS gensec_gse_magic(struct gensec_security *gensec_security,
1025 const DATA_BLOB *in)
1027 if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
1028 return NT_STATUS_OK;
1029 } else {
1030 return NT_STATUS_INVALID_PARAMETER;
1036 * Next state function for the GSE GENSEC mechanism
1038 * @param gensec_gse_state GSE State
1039 * @param mem_ctx The TALLOC_CTX for *out to be allocated on
1040 * @param in The request, as a DATA_BLOB
1041 * @param out The reply, as an talloc()ed DATA_BLOB, on *mem_ctx
1042 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
1043 * or NT_STATUS_OK if the user is authenticated.
1046 static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security,
1047 TALLOC_CTX *mem_ctx,
1048 struct tevent_context *ev,
1049 const DATA_BLOB in, DATA_BLOB *out)
1051 NTSTATUS status;
1052 struct gse_context *gse_ctx =
1053 talloc_get_type_abort(gensec_security->private_data,
1054 struct gse_context);
1056 switch (gensec_security->gensec_role) {
1057 case GENSEC_CLIENT:
1058 status = gse_get_client_auth_token(mem_ctx, gse_ctx,
1059 &in, out);
1060 break;
1061 case GENSEC_SERVER:
1062 status = gse_get_server_auth_token(mem_ctx, gse_ctx,
1063 &in, out);
1064 break;
1066 if (!NT_STATUS_IS_OK(status)) {
1067 return status;
1069 if (gse_ctx->more_processing) {
1070 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1073 if (gensec_security->gensec_role == GENSEC_SERVER) {
1074 return gse_verify_server_auth_flags(gse_ctx);
1077 return NT_STATUS_OK;
1080 static NTSTATUS gensec_gse_wrap(struct gensec_security *gensec_security,
1081 TALLOC_CTX *mem_ctx,
1082 const DATA_BLOB *in,
1083 DATA_BLOB *out)
1085 struct gse_context *gse_ctx =
1086 talloc_get_type_abort(gensec_security->private_data,
1087 struct gse_context);
1088 OM_uint32 maj_stat, min_stat;
1089 gss_buffer_desc input_token, output_token;
1090 int conf_state;
1091 input_token.length = in->length;
1092 input_token.value = in->data;
1094 maj_stat = gss_wrap(&min_stat,
1095 gse_ctx->gss_ctx,
1096 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1097 GSS_C_QOP_DEFAULT,
1098 &input_token,
1099 &conf_state,
1100 &output_token);
1101 if (GSS_ERROR(maj_stat)) {
1102 DEBUG(0, ("gensec_gse_wrap: GSS Wrap failed: %s\n",
1103 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1104 return NT_STATUS_ACCESS_DENIED;
1107 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1108 gss_release_buffer(&min_stat, &output_token);
1110 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1111 && !conf_state) {
1112 return NT_STATUS_ACCESS_DENIED;
1114 return NT_STATUS_OK;
1117 static NTSTATUS gensec_gse_unwrap(struct gensec_security *gensec_security,
1118 TALLOC_CTX *mem_ctx,
1119 const DATA_BLOB *in,
1120 DATA_BLOB *out)
1122 struct gse_context *gse_ctx =
1123 talloc_get_type_abort(gensec_security->private_data,
1124 struct gse_context);
1125 OM_uint32 maj_stat, min_stat;
1126 gss_buffer_desc input_token, output_token;
1127 int conf_state;
1128 gss_qop_t qop_state;
1129 input_token.length = in->length;
1130 input_token.value = in->data;
1132 maj_stat = gss_unwrap(&min_stat,
1133 gse_ctx->gss_ctx,
1134 &input_token,
1135 &output_token,
1136 &conf_state,
1137 &qop_state);
1138 if (GSS_ERROR(maj_stat)) {
1139 DEBUG(0, ("gensec_gse_unwrap: GSS UnWrap failed: %s\n",
1140 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1141 return NT_STATUS_ACCESS_DENIED;
1144 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1145 gss_release_buffer(&min_stat, &output_token);
1147 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1148 && !conf_state) {
1149 return NT_STATUS_ACCESS_DENIED;
1151 return NT_STATUS_OK;
1154 static NTSTATUS gensec_gse_seal_packet(struct gensec_security *gensec_security,
1155 TALLOC_CTX *mem_ctx,
1156 uint8_t *data, size_t length,
1157 const uint8_t *whole_pdu, size_t pdu_length,
1158 DATA_BLOB *sig)
1160 struct gse_context *gse_ctx =
1161 talloc_get_type_abort(gensec_security->private_data,
1162 struct gse_context);
1163 DATA_BLOB payload = data_blob_const(data, length);
1164 return gse_seal(mem_ctx, gse_ctx, &payload, sig);
1167 static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security,
1168 uint8_t *data, size_t length,
1169 const uint8_t *whole_pdu, size_t pdu_length,
1170 const DATA_BLOB *sig)
1172 struct gse_context *gse_ctx =
1173 talloc_get_type_abort(gensec_security->private_data,
1174 struct gse_context);
1175 DATA_BLOB payload = data_blob_const(data, length);
1176 return gse_unseal(talloc_tos() /* unused */, gse_ctx, &payload, sig);
1179 static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security,
1180 TALLOC_CTX *mem_ctx,
1181 const uint8_t *data, size_t length,
1182 const uint8_t *whole_pdu, size_t pdu_length,
1183 DATA_BLOB *sig)
1185 struct gse_context *gse_ctx =
1186 talloc_get_type_abort(gensec_security->private_data,
1187 struct gse_context);
1188 DATA_BLOB payload = data_blob_const(data, length);
1189 return gse_sign(mem_ctx, gse_ctx, &payload, sig);
1192 static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security,
1193 const uint8_t *data, size_t length,
1194 const uint8_t *whole_pdu, size_t pdu_length,
1195 const DATA_BLOB *sig)
1197 struct gse_context *gse_ctx =
1198 talloc_get_type_abort(gensec_security->private_data,
1199 struct gse_context);
1200 DATA_BLOB payload = data_blob_const(data, length);
1201 return gse_sigcheck(NULL, gse_ctx, &payload, sig);
1204 /* Try to figure out what features we actually got on the connection */
1205 static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
1206 uint32_t feature)
1208 struct gse_context *gse_ctx =
1209 talloc_get_type_abort(gensec_security->private_data,
1210 struct gse_context);
1212 if (feature & GENSEC_FEATURE_SIGN) {
1213 return gse_ctx->ret_flags & GSS_C_INTEG_FLAG;
1215 if (feature & GENSEC_FEATURE_SEAL) {
1216 return gse_ctx->ret_flags & GSS_C_CONF_FLAG;
1218 if (feature & GENSEC_FEATURE_SESSION_KEY) {
1219 /* Only for GSE/Krb5 */
1220 if (gss_oid_equal(gse_ctx->ret_mech, gss_mech_krb5)) {
1221 return true;
1224 if (feature & GENSEC_FEATURE_DCE_STYLE) {
1225 return gse_ctx->ret_flags & GSS_C_DCE_STYLE;
1227 /* We can always do async (rather than strict request/reply) packets. */
1228 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1229 return true;
1231 return false;
1235 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1236 * (for encrypting some passwords).
1238 * This breaks all the abstractions, but what do you expect...
1240 static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security,
1241 TALLOC_CTX *mem_ctx,
1242 DATA_BLOB *session_key_out)
1244 struct gse_context *gse_ctx =
1245 talloc_get_type_abort(gensec_security->private_data,
1246 struct gse_context);
1248 DATA_BLOB session_key = gse_get_session_key(mem_ctx, gse_ctx);
1249 if (session_key.data == NULL) {
1250 return NT_STATUS_NO_USER_SESSION_KEY;
1253 *session_key_out = session_key;
1255 return NT_STATUS_OK;
1258 /* Get some basic (and authorization) information about the user on
1259 * this session. This uses either the PAC (if present) or a local
1260 * database lookup */
1261 static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security,
1262 TALLOC_CTX *mem_ctx,
1263 struct auth_session_info **_session_info)
1265 struct gse_context *gse_ctx =
1266 talloc_get_type_abort(gensec_security->private_data,
1267 struct gse_context);
1268 NTSTATUS nt_status;
1269 TALLOC_CTX *tmp_ctx;
1270 struct auth_session_info *session_info = NULL;
1271 OM_uint32 maj_stat, min_stat;
1272 DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1274 gss_buffer_desc name_token;
1275 char *principal_string;
1277 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gse_session_info context");
1278 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1280 maj_stat = gss_display_name(&min_stat,
1281 gse_ctx->client_name,
1282 &name_token,
1283 NULL);
1284 if (GSS_ERROR(maj_stat)) {
1285 DEBUG(1, ("GSS display_name failed: %s\n",
1286 gse_errstr(talloc_tos(), maj_stat, min_stat)));
1287 talloc_free(tmp_ctx);
1288 return NT_STATUS_FOOBAR;
1291 principal_string = talloc_strndup(tmp_ctx,
1292 (const char *)name_token.value,
1293 name_token.length);
1295 gss_release_buffer(&min_stat, &name_token);
1297 if (!principal_string) {
1298 talloc_free(tmp_ctx);
1299 return NT_STATUS_NO_MEMORY;
1302 nt_status = gssapi_obtain_pac_blob(tmp_ctx, gse_ctx->gss_ctx,
1303 gse_ctx->client_name,
1304 &pac_blob);
1306 /* IF we have the PAC - otherwise we need to get this
1307 * data from elsewere
1309 if (NT_STATUS_IS_OK(nt_status)) {
1310 pac_blob_ptr = &pac_blob;
1312 nt_status = gensec_generate_session_info_pac(tmp_ctx,
1313 gensec_security,
1314 NULL,
1315 pac_blob_ptr, principal_string,
1316 gensec_get_remote_address(gensec_security),
1317 &session_info);
1318 if (!NT_STATUS_IS_OK(nt_status)) {
1319 talloc_free(tmp_ctx);
1320 return nt_status;
1323 nt_status = gensec_gse_session_key(gensec_security, session_info,
1324 &session_info->session_key);
1325 if (!NT_STATUS_IS_OK(nt_status)) {
1326 talloc_free(tmp_ctx);
1327 return nt_status;
1330 *_session_info = talloc_move(mem_ctx, &session_info);
1331 talloc_free(tmp_ctx);
1333 return NT_STATUS_OK;
1336 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
1337 size_t data_size)
1339 struct gse_context *gse_ctx =
1340 talloc_get_type_abort(gensec_security->private_data,
1341 struct gse_context);
1343 return gse_get_signature_length(gse_ctx,
1344 gensec_security->want_features & GENSEC_FEATURE_SEAL,
1345 data_size);
1348 static const char *gensec_gse_krb5_oids[] = {
1349 GENSEC_OID_KERBEROS5_OLD,
1350 GENSEC_OID_KERBEROS5,
1351 NULL
1354 const struct gensec_security_ops gensec_gse_krb5_security_ops = {
1355 .name = "gse_krb5",
1356 .auth_type = DCERPC_AUTH_TYPE_KRB5,
1357 .oid = gensec_gse_krb5_oids,
1358 .client_start = gensec_gse_client_start,
1359 .server_start = gensec_gse_server_start,
1360 .magic = gensec_gse_magic,
1361 .update = gensec_gse_update,
1362 .session_key = gensec_gse_session_key,
1363 .session_info = gensec_gse_session_info,
1364 .sig_size = gensec_gse_sig_size,
1365 .sign_packet = gensec_gse_sign_packet,
1366 .check_packet = gensec_gse_check_packet,
1367 .seal_packet = gensec_gse_seal_packet,
1368 .unseal_packet = gensec_gse_unseal_packet,
1369 .wrap = gensec_gse_wrap,
1370 .unwrap = gensec_gse_unwrap,
1371 .have_feature = gensec_gse_have_feature,
1372 .enabled = true,
1373 .kerberos = true,
1374 .priority = GENSEC_GSSAPI
1377 #else
1379 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
1380 bool do_sign, bool do_seal,
1381 const char *ccache_name,
1382 const char *server,
1383 const char *service,
1384 const char *username,
1385 const char *password,
1386 uint32_t add_gss_c_flags,
1387 struct gse_context **_gse_ctx)
1389 return NT_STATUS_NOT_IMPLEMENTED;
1392 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
1393 struct gse_context *gse_ctx,
1394 DATA_BLOB *token_in,
1395 DATA_BLOB *token_out)
1397 return NT_STATUS_NOT_IMPLEMENTED;
1400 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
1401 bool do_sign, bool do_seal,
1402 uint32_t add_gss_c_flags,
1403 struct gse_context **_gse_ctx)
1405 return NT_STATUS_NOT_IMPLEMENTED;
1408 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
1409 struct gse_context *gse_ctx,
1410 DATA_BLOB *token_in,
1411 DATA_BLOB *token_out)
1413 return NT_STATUS_NOT_IMPLEMENTED;
1416 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
1418 return NT_STATUS_NOT_IMPLEMENTED;
1421 bool gse_require_more_processing(struct gse_context *gse_ctx)
1423 return false;
1426 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
1427 struct gse_context *gse_ctx)
1429 return data_blob_null;
1432 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
1433 TALLOC_CTX *mem_ctx, char **cli_name)
1435 return NT_STATUS_NOT_IMPLEMENTED;
1438 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
1439 TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
1441 return NT_STATUS_NOT_IMPLEMENTED;
1444 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
1445 TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob)
1447 return NT_STATUS_NOT_IMPLEMENTED;
1450 size_t gse_get_signature_length(struct gse_context *gse_ctx,
1451 int seal, size_t payload_size)
1453 return 0;
1456 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
1457 DATA_BLOB *data, DATA_BLOB *signature)
1459 return NT_STATUS_NOT_IMPLEMENTED;
1462 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
1463 DATA_BLOB *data, DATA_BLOB *signature)
1465 return NT_STATUS_NOT_IMPLEMENTED;
1468 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
1469 DATA_BLOB *data, DATA_BLOB *signature)
1471 return NT_STATUS_NOT_IMPLEMENTED;
1474 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
1475 DATA_BLOB *data, DATA_BLOB *signature)
1477 return NT_STATUS_NOT_IMPLEMENTED;
1480 #endif /* HAVE_KRB5 && HAVE_GSS_WRAP_IOV */