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_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"
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"
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
);
75 gss_OID_desc gss_mech
;
76 OM_uint32 gss_c_flags
;
78 gss_name_t server_name
;
82 gss_cred_id_t delegated_creds
;
83 gss_name_t client_name
;
89 #ifndef HAVE_GSS_OID_EQUAL
91 static bool gss_oid_equal(const gss_OID o1
, const gss_OID o2
)
96 if ((o1
== NULL
&& o2
!= NULL
) || (o1
!= NULL
&& o2
== NULL
)) {
99 if (o1
->length
!= o2
->length
) {
102 return memcmp(o1
->elements
, o2
->elements
, o1
->length
) == false;
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
,
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
,
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
158 SMB_ASSERT(gss_oid_equal(&gse_ctx
->gss_mech
, GSS_C_NO_OID
) || gss_oid_equal(&gse_ctx
->gss_mech
, gss_mech_krb5
));
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
;
173 gse_ctx
= talloc_zero(mem_ctx
, struct gse_context
);
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
|
183 GSS_C_DELEG_POLICY_FLAG
|
187 gse_ctx
->gss_c_flags
|= GSS_C_INTEG_FLAG
;
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
);
200 DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
201 error_message(k5ret
)));
202 status
= NT_STATUS_INTERNAL_ERROR
;
207 ccache_name
= krb5_cc_default_name(gse_ctx
->k5ctx
);
209 k5ret
= krb5_cc_resolve(gse_ctx
->k5ctx
, ccache_name
,
212 DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
213 error_message(k5ret
)));
214 status
= NT_STATUS_INTERNAL_ERROR
;
218 /* TODO: Should we enforce a enc_types list ?
219 ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
226 TALLOC_FREE(gse_ctx
);
230 NTSTATUS
gse_init_client(TALLOC_CTX
*mem_ctx
,
231 bool do_sign
, bool do_seal
,
232 const char *ccache_name
,
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
;
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
,
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
,
266 if (!name_buffer
.value
) {
267 status
= NT_STATUS_NO_MEMORY
;
270 name_buffer
.length
= strlen((char *)name_buffer
.value
);
271 gss_maj
= gss_import_name(&gss_min
, &name_buffer
,
273 &gse_ctx
->server_name
);
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
;
282 /* TODO: get krb5 ticket using username/password, if no valid
283 * one already available in ccache */
286 mech_set
.elements
= &gse_ctx
->gss_mech
;
288 gss_maj
= gss_acquire_cred(&gss_min
,
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
;
304 TALLOC_FREE(name_buffer
.value
);
308 TALLOC_FREE(name_buffer
.value
);
309 TALLOC_FREE(gse_ctx
);
313 NTSTATUS
gse_get_client_auth_token(TALLOC_CTX
*mem_ctx
,
314 struct gse_context
*gse_ctx
,
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
;
324 in_data
.value
= token_in
->data
;
325 in_data
.length
= token_in
->length
;
327 gss_maj
= gss_init_sec_context(&gss_min
,
330 gse_ctx
->server_name
,
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
);
338 /* we are done with it */
339 gse_ctx
->more_processing
= false;
340 status
= NT_STATUS_OK
;
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
;
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
;
355 blob
= data_blob_talloc(mem_ctx
, out_data
.value
, out_data
.length
);
357 status
= NT_STATUS_NO_MEMORY
;
360 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
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
;
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
,
386 status
= NT_STATUS_INTERNAL_ERROR
;
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
,
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
;
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
))
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 ... */
417 gss_OID_set_desc mech_set
;
419 ret
= smb_krb5_keytab_name(gse_ctx
, gse_ctx
->k5ctx
,
420 gse_ctx
->keytab
, &ktname
);
422 status
= NT_STATUS_INTERNAL_ERROR
;
426 ret
= gsskrb5_register_acceptor_identity(ktname
);
428 status
= NT_STATUS_INTERNAL_ERROR
;
433 mech_set
.elements
= &gse_ctx
->gss_mech
;
435 gss_maj
= gss_acquire_cred(&gss_min
,
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
;
451 status
= NT_STATUS_OK
;
454 if (!NT_STATUS_IS_OK(status
)) {
455 TALLOC_FREE(gse_ctx
);
462 NTSTATUS
gse_get_server_auth_token(TALLOC_CTX
*mem_ctx
,
463 struct gse_context
*gse_ctx
,
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
;
473 in_data
.value
= token_in
->data
;
474 in_data
.length
= token_in
->length
;
476 gss_maj
= gss_accept_sec_context(&gss_min
,
480 GSS_C_NO_CHANNEL_BINDINGS
,
481 &gse_ctx
->client_name
,
484 &gse_ctx
->ret_flags
, NULL
,
485 &gse_ctx
->delegated_creds
);
488 /* we are done with it */
489 gse_ctx
->more_processing
= false;
490 gse_ctx
->authenticated
= true;
491 status
= NT_STATUS_OK
;
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
;
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
,
509 status
= NT_STATUS_INTERNAL_ERROR
;
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
);
517 status
= NT_STATUS_NO_MEMORY
;
519 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
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
;
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;
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
);
585 errstr
= talloc_strndup(mem_ctx
,
586 (char *)msg_maj
.value
,
591 gss_maj
= gss_display_status(&gss_min
, min
, GSS_C_MECH_CODE
,
592 (gss_OID
)discard_const(gss_mech_krb5
),
598 errstr
= talloc_strdup_append_buffer(errstr
, ": ");
602 errstr
= talloc_strndup_append_buffer(errstr
,
603 (char *)msg_min
.value
,
611 gss_maj
= gss_release_buffer(&gss_min
, &msg_min
);
614 gss_maj
= gss_release_buffer(&gss_min
, &msg_maj
);
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
;
631 gss_maj
= gss_inquire_sec_context_by_oid(
632 &gss_min
, gse_ctx
->gss_ctx
,
633 &gse_sesskey_inq_oid
, &set
);
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
) ||
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
,
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
);
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
;
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
);
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
,
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
,
703 gss_maj
= gss_release_buffer(&gss_min
, &name_buffer
);
706 return NT_STATUS_NO_MEMORY
;
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
);
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
);
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
];
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
,
777 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
778 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
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 */
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
,
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
;
823 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
824 status
= NT_STATUS_ACCESS_DENIED
;
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
));
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];
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);
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
;
864 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
865 status
= NT_STATUS_ACCESS_DENIED
;
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
));
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
};
886 in_data
.value
= data
->data
;
887 in_data
.length
= data
->length
;
889 gss_maj
= gss_get_mic(&gss_min
, gse_ctx
->gss_ctx
,
891 &in_data
, &out_data
);
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
;
899 *signature
= data_blob_talloc(mem_ctx
,
900 out_data
.value
, out_data
.length
);
901 if (!signature
->data
) {
902 status
= NT_STATUS_NO_MEMORY
;
906 status
= NT_STATUS_OK
;
909 if (out_data
.value
) {
910 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
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
};
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
);
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
;
937 status
= NT_STATUS_OK
;
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
);
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
);
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
) {
971 if (gensec_security
->want_features
& GENSEC_FEATURE_SEAL
) {
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
,
980 username
, password
, want_flags
,
982 if (!NT_STATUS_IS_OK(nt_status
)) {
985 gensec_security
->private_data
= gse_ctx
;
989 static NTSTATUS
gensec_gse_server_start(struct gensec_security
*gensec_security
)
991 struct gse_context
*gse_ctx
;
993 OM_uint32 want_flags
= 0;
994 bool do_sign
= false, do_seal
= false;
996 if (gensec_security
->want_features
& GENSEC_FEATURE_SIGN
) {
999 if (gensec_security
->want_features
& GENSEC_FEATURE_SEAL
) {
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
,
1008 if (!NT_STATUS_IS_OK(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
;
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
)
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
) {
1058 status
= gse_get_client_auth_token(mem_ctx
, gse_ctx
,
1062 status
= gse_get_server_auth_token(mem_ctx
, gse_ctx
,
1066 if (!NT_STATUS_IS_OK(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
,
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
;
1091 input_token
.length
= in
->length
;
1092 input_token
.value
= in
->data
;
1094 maj_stat
= gss_wrap(&min_stat
,
1096 gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
),
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
)
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
,
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
;
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
,
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
)
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
,
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
,
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
,
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
)) {
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
) {
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
);
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
,
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
,
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
,
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
,
1315 pac_blob_ptr
, principal_string
,
1316 gensec_get_remote_address(gensec_security
),
1318 if (!NT_STATUS_IS_OK(nt_status
)) {
1319 talloc_free(tmp_ctx
);
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
);
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
,
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
,
1348 static const char *gensec_gse_krb5_oids
[] = {
1349 GENSEC_OID_KERBEROS5_OLD
,
1350 GENSEC_OID_KERBEROS5
,
1354 const struct gensec_security_ops gensec_gse_krb5_security_ops
= {
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
,
1374 .priority
= GENSEC_GSSAPI
1379 NTSTATUS
gse_init_client(TALLOC_CTX
*mem_ctx
,
1380 bool do_sign
, bool do_seal
,
1381 const char *ccache_name
,
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
)
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
)
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 */