2 * GSSAPI Security Extensions
3 * RPC Pipe client and server routines
4 * Copyright (C) Simo Sorce 2010.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 /* We support only GSSAPI/KRB5 here */
25 #if defined(HAVE_KRB5) && defined(HAVE_GSSAPI_GSSAPI_EXT_H) && defined(HAVE_GSS_WRAP_IOV)
30 #include <gssapi/gssapi.h>
31 #include <gssapi/gssapi_krb5.h>
32 #include <gssapi/gssapi_ext.h>
34 #ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
35 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
36 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
39 gss_OID_desc gse_sesskey_inq_oid
= {
40 GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH
,
41 (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
44 #ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
45 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
46 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
49 gss_OID_desc gse_sesskeytype_oid
= {
50 GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH
,
51 (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
54 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH 12
55 /* EXTRACTION OID AUTHZ ID */
56 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" "\x01"
58 gss_OID_desc gse_authz_data_oid
= {
59 GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH
,
60 (void *)GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID
63 #ifndef GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID
64 #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 11
65 #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c"
68 gss_OID_desc gse_authtime_oid
= {
69 GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH
,
70 (void *)GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID
73 static char *gse_errstr(TALLOC_CTX
*mem_ctx
, OM_uint32 maj
, OM_uint32 min
);
82 gss_OID_desc gss_mech
;
83 OM_uint32 gss_c_flags
;
85 gss_name_t server_name
;
89 gss_cred_id_t delegated_creds
;
90 gss_name_t client_name
;
97 /* free non talloc dependent contexts */
98 static int gse_context_destructor(void *ptr
)
100 struct gse_context
*gse_ctx
;
101 OM_uint32 gss_min
, gss_maj
;
103 gse_ctx
= talloc_get_type_abort(ptr
, struct gse_context
);
104 if (gse_ctx
->k5ctx
) {
105 if (gse_ctx
->ccache
) {
106 krb5_cc_close(gse_ctx
->k5ctx
, gse_ctx
->ccache
);
107 gse_ctx
->ccache
= NULL
;
109 if (gse_ctx
->keytab
) {
110 krb5_kt_close(gse_ctx
->k5ctx
, gse_ctx
->keytab
);
111 gse_ctx
->keytab
= NULL
;
113 krb5_free_context(gse_ctx
->k5ctx
);
114 gse_ctx
->k5ctx
= NULL
;
116 if (gse_ctx
->gss_ctx
!= GSS_C_NO_CONTEXT
) {
117 gss_maj
= gss_delete_sec_context(&gss_min
,
121 if (gse_ctx
->server_name
) {
122 gss_maj
= gss_release_name(&gss_min
,
123 &gse_ctx
->server_name
);
125 if (gse_ctx
->client_name
) {
126 gss_maj
= gss_release_name(&gss_min
,
127 &gse_ctx
->client_name
);
129 if (gse_ctx
->creds
) {
130 gss_maj
= gss_release_cred(&gss_min
,
133 if (gse_ctx
->delegated_creds
) {
134 gss_maj
= gss_release_cred(&gss_min
,
135 &gse_ctx
->delegated_creds
);
137 if (gse_ctx
->ret_mech
) {
138 gss_maj
= gss_release_oid(&gss_min
,
144 static NTSTATUS
gse_context_init(TALLOC_CTX
*mem_ctx
,
145 enum dcerpc_AuthType auth_type
,
146 enum dcerpc_AuthLevel auth_level
,
147 const char *ccache_name
,
148 uint32_t add_gss_c_flags
,
149 struct gse_context
**_gse_ctx
)
151 struct gse_context
*gse_ctx
;
152 krb5_error_code k5ret
;
155 gse_ctx
= talloc_zero(mem_ctx
, struct gse_context
);
157 return NT_STATUS_NO_MEMORY
;
159 talloc_set_destructor((TALLOC_CTX
*)gse_ctx
, gse_context_destructor
);
161 memcpy(&gse_ctx
->gss_mech
, gss_mech_krb5
, sizeof(gss_OID_desc
));
164 case DCERPC_AUTH_TYPE_SPNEGO
:
165 gse_ctx
->spnego_wrap
= true;
167 case DCERPC_AUTH_TYPE_KRB5
:
168 gse_ctx
->spnego_wrap
= false;
171 status
= NT_STATUS_INVALID_PARAMETER
;
175 gse_ctx
->gss_c_flags
= GSS_C_MUTUAL_FLAG
|
177 GSS_C_DELEG_POLICY_FLAG
|
180 switch (auth_level
) {
181 case DCERPC_AUTH_LEVEL_INTEGRITY
:
182 gse_ctx
->gss_c_flags
|= GSS_C_INTEG_FLAG
;
184 case DCERPC_AUTH_LEVEL_PRIVACY
:
185 gse_ctx
->gss_c_flags
|= GSS_C_CONF_FLAG
;
191 gse_ctx
->gss_c_flags
|= add_gss_c_flags
;
193 /* Initialize Kerberos Context */
194 initialize_krb5_error_table();
196 k5ret
= krb5_init_context(&gse_ctx
->k5ctx
);
198 DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
199 error_message(k5ret
)));
200 status
= NT_STATUS_INTERNAL_ERROR
;
205 ccache_name
= krb5_cc_default_name(gse_ctx
->k5ctx
);
207 k5ret
= krb5_cc_resolve(gse_ctx
->k5ctx
, ccache_name
,
210 DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
211 error_message(k5ret
)));
212 status
= NT_STATUS_INTERNAL_ERROR
;
216 /* TODO: Should we enforce a enc_types list ?
217 ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
224 TALLOC_FREE(gse_ctx
);
228 NTSTATUS
gse_init_client(TALLOC_CTX
*mem_ctx
,
229 enum dcerpc_AuthType auth_type
,
230 enum dcerpc_AuthLevel auth_level
,
231 const char *ccache_name
,
234 const char *username
,
235 const char *password
,
236 uint32_t add_gss_c_flags
,
237 struct gse_context
**_gse_ctx
)
239 struct gse_context
*gse_ctx
;
240 OM_uint32 gss_maj
, gss_min
;
241 gss_buffer_desc name_buffer
= {0, NULL
};
242 gss_OID_set_desc mech_set
;
245 if (!server
|| !service
) {
246 return NT_STATUS_INVALID_PARAMETER
;
249 status
= gse_context_init(mem_ctx
, auth_type
, auth_level
,
250 ccache_name
, add_gss_c_flags
,
252 if (!NT_STATUS_IS_OK(status
)) {
253 return NT_STATUS_NO_MEMORY
;
256 name_buffer
.value
= talloc_asprintf(gse_ctx
,
257 "%s@%s", service
, server
);
258 if (!name_buffer
.value
) {
259 status
= NT_STATUS_NO_MEMORY
;
262 name_buffer
.length
= strlen((char *)name_buffer
.value
);
263 gss_maj
= gss_import_name(&gss_min
, &name_buffer
,
264 GSS_C_NT_HOSTBASED_SERVICE
,
265 &gse_ctx
->server_name
);
267 DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
268 (char *)name_buffer
.value
,
269 gse_errstr(gse_ctx
, gss_maj
, gss_min
)));
270 status
= NT_STATUS_INTERNAL_ERROR
;
274 /* TODO: get krb5 ticket using username/password, if no valid
275 * one already available in ccache */
278 mech_set
.elements
= &gse_ctx
->gss_mech
;
280 gss_maj
= gss_acquire_cred(&gss_min
,
288 DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
289 (char *)name_buffer
.value
,
290 gse_errstr(gse_ctx
, gss_maj
, gss_min
)));
291 status
= NT_STATUS_INTERNAL_ERROR
;
296 TALLOC_FREE(name_buffer
.value
);
300 TALLOC_FREE(name_buffer
.value
);
301 TALLOC_FREE(gse_ctx
);
305 NTSTATUS
gse_get_client_auth_token(TALLOC_CTX
*mem_ctx
,
306 struct gse_context
*gse_ctx
,
308 DATA_BLOB
*token_out
)
310 OM_uint32 gss_maj
, gss_min
;
311 gss_buffer_desc in_data
;
312 gss_buffer_desc out_data
;
313 DATA_BLOB blob
= data_blob_null
;
316 in_data
.value
= token_in
->data
;
317 in_data
.length
= token_in
->length
;
319 gss_maj
= gss_init_sec_context(&gss_min
,
322 gse_ctx
->server_name
,
324 gse_ctx
->gss_c_flags
,
325 0, GSS_C_NO_CHANNEL_BINDINGS
,
326 &in_data
, NULL
, &out_data
,
330 /* we are done with it */
331 gse_ctx
->more_processing
= false;
332 status
= NT_STATUS_OK
;
334 case GSS_S_CONTINUE_NEEDED
:
335 /* we will need a third leg */
336 gse_ctx
->more_processing
= true;
337 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
338 status
= NT_STATUS_OK
;
341 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
342 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
343 status
= NT_STATUS_INTERNAL_ERROR
;
347 blob
= data_blob_talloc(mem_ctx
, out_data
.value
, out_data
.length
);
349 status
= NT_STATUS_NO_MEMORY
;
352 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
359 NTSTATUS
gse_init_server(TALLOC_CTX
*mem_ctx
,
360 enum dcerpc_AuthType auth_type
,
361 enum dcerpc_AuthLevel auth_level
,
362 uint32_t add_gss_c_flags
,
364 const char *keytab_name
,
365 struct gse_context
**_gse_ctx
)
367 struct gse_context
*gse_ctx
;
368 OM_uint32 gss_maj
, gss_min
;
369 gss_OID_set_desc mech_set
;
374 status
= gse_context_init(mem_ctx
, auth_type
, auth_level
,
375 NULL
, add_gss_c_flags
, &gse_ctx
);
376 if (!NT_STATUS_IS_OK(status
)) {
377 return NT_STATUS_NO_MEMORY
;
381 ret
= gse_krb5_get_server_keytab(gse_ctx
->k5ctx
,
384 status
= NT_STATUS_INTERNAL_ERROR
;
387 ret
= smb_krb5_keytab_name(gse_ctx
, gse_ctx
->k5ctx
,
388 gse_ctx
->keytab
, &ktname
);
390 status
= NT_STATUS_INTERNAL_ERROR
;
394 ktname
= keytab_name
;
398 * This call sets the default keytab for the whole server, not
399 * just for this context. Need to find a way that does not alter
400 * the state of the whole server ... */
401 ret
= gsskrb5_register_acceptor_identity(ktname
);
403 status
= NT_STATUS_INTERNAL_ERROR
;
408 mech_set
.elements
= &gse_ctx
->gss_mech
;
410 gss_maj
= gss_acquire_cred(&gss_min
,
418 DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
419 gse_errstr(gse_ctx
, gss_maj
, gss_min
)));
420 status
= NT_STATUS_INTERNAL_ERROR
;
424 status
= NT_STATUS_OK
;
427 if (!NT_STATUS_IS_OK(status
)) {
428 TALLOC_FREE(gse_ctx
);
435 NTSTATUS
gse_get_server_auth_token(TALLOC_CTX
*mem_ctx
,
436 struct gse_context
*gse_ctx
,
438 DATA_BLOB
*token_out
)
440 OM_uint32 gss_maj
, gss_min
;
441 gss_buffer_desc in_data
;
442 gss_buffer_desc out_data
;
443 DATA_BLOB blob
= data_blob_null
;
446 in_data
.value
= token_in
->data
;
447 in_data
.length
= token_in
->length
;
449 gss_maj
= gss_accept_sec_context(&gss_min
,
453 GSS_C_NO_CHANNEL_BINDINGS
,
454 &gse_ctx
->client_name
,
457 &gse_ctx
->ret_flags
, NULL
,
458 &gse_ctx
->delegated_creds
);
461 /* we are done with it */
462 gse_ctx
->more_processing
= false;
463 gse_ctx
->authenticated
= true;
464 status
= NT_STATUS_OK
;
466 case GSS_S_CONTINUE_NEEDED
:
467 /* we will need a third leg */
468 gse_ctx
->more_processing
= true;
469 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
470 status
= NT_STATUS_OK
;
473 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
474 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
476 if (gse_ctx
->gss_ctx
) {
477 gss_delete_sec_context(&gss_min
,
482 status
= NT_STATUS_INTERNAL_ERROR
;
486 /* we may be told to return nothing */
487 if (out_data
.length
) {
488 blob
= data_blob_talloc(mem_ctx
, out_data
.value
, out_data
.length
);
490 status
= NT_STATUS_NO_MEMORY
;
492 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
501 NTSTATUS
gse_verify_server_auth_flags(struct gse_context
*gse_ctx
)
503 if (!gse_ctx
->authenticated
) {
504 return NT_STATUS_INVALID_HANDLE
;
507 if (memcmp(gse_ctx
->ret_mech
,
508 gss_mech_krb5
, sizeof(gss_OID_desc
)) != 0) {
509 return NT_STATUS_ACCESS_DENIED
;
512 /* GSS_C_MUTUAL_FLAG */
513 if (gse_ctx
->gss_c_flags
& GSS_C_MUTUAL_FLAG
) {
514 if (!(gse_ctx
->ret_flags
& GSS_C_MUTUAL_FLAG
)) {
515 return NT_STATUS_ACCESS_DENIED
;
519 /* GSS_C_DELEG_FLAG */
520 /* GSS_C_DELEG_POLICY_FLAG */
521 /* GSS_C_REPLAY_FLAG */
522 /* GSS_C_SEQUENCE_FLAG */
524 /* GSS_C_INTEG_FLAG */
525 if (gse_ctx
->gss_c_flags
& GSS_C_INTEG_FLAG
) {
526 if (!(gse_ctx
->ret_flags
& GSS_C_INTEG_FLAG
)) {
527 return NT_STATUS_ACCESS_DENIED
;
531 /* GSS_C_CONF_FLAG */
532 if (gse_ctx
->gss_c_flags
& GSS_C_CONF_FLAG
) {
533 if (!(gse_ctx
->ret_flags
& GSS_C_CONF_FLAG
)) {
534 return NT_STATUS_ACCESS_DENIED
;
541 static char *gse_errstr(TALLOC_CTX
*mem_ctx
, OM_uint32 maj
, OM_uint32 min
)
543 OM_uint32 gss_min
, gss_maj
;
544 gss_buffer_desc msg_min
;
545 gss_buffer_desc msg_maj
;
546 OM_uint32 msg_ctx
= 0;
550 ZERO_STRUCT(msg_min
);
551 ZERO_STRUCT(msg_maj
);
553 gss_maj
= gss_display_status(&gss_min
, maj
, GSS_C_GSS_CODE
,
554 GSS_C_NO_OID
, &msg_ctx
, &msg_maj
);
558 gss_maj
= gss_display_status(&gss_min
, min
, GSS_C_MECH_CODE
,
559 (gss_OID
)discard_const(gss_mech_krb5
),
565 errstr
= talloc_strndup(mem_ctx
,
566 (char *)msg_maj
.value
,
571 errstr
= talloc_strdup_append_buffer(errstr
, ": ");
575 errstr
= talloc_strndup_append_buffer(errstr
,
576 (char *)msg_min
.value
,
584 gss_maj
= gss_release_buffer(&gss_min
, &msg_min
);
587 gss_maj
= gss_release_buffer(&gss_min
, &msg_maj
);
592 bool gse_require_more_processing(struct gse_context
*gse_ctx
)
594 return gse_ctx
->more_processing
;
597 DATA_BLOB
gse_get_session_key(TALLOC_CTX
*mem_ctx
,
598 struct gse_context
*gse_ctx
)
600 OM_uint32 gss_min
, gss_maj
;
601 gss_buffer_set_t set
= GSS_C_NO_BUFFER_SET
;
604 gss_maj
= gss_inquire_sec_context_by_oid(
605 &gss_min
, gse_ctx
->gss_ctx
,
606 &gse_sesskey_inq_oid
, &set
);
608 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
609 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
610 return data_blob_null
;
613 if ((set
== GSS_C_NO_BUFFER_SET
) ||
615 (memcmp(set
->elements
[1].value
,
616 gse_sesskeytype_oid
.elements
,
617 gse_sesskeytype_oid
.length
) != 0)) {
618 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
619 "OID for data in results:\n"));
620 dump_data(1, (uint8_t *)set
->elements
[1].value
,
621 set
->elements
[1].length
);
622 return data_blob_null
;
625 ret
= data_blob_talloc(mem_ctx
, set
->elements
[0].value
,
626 set
->elements
[0].length
);
628 gss_maj
= gss_release_buffer_set(&gss_min
, &set
);
632 NTSTATUS
gse_get_client_name(struct gse_context
*gse_ctx
,
633 TALLOC_CTX
*mem_ctx
, char **cli_name
)
635 OM_uint32 gss_min
, gss_maj
;
636 gss_buffer_desc name_buffer
;
638 if (!gse_ctx
->authenticated
) {
639 return NT_STATUS_ACCESS_DENIED
;
642 if (!gse_ctx
->client_name
) {
643 return NT_STATUS_NOT_FOUND
;
646 /* TODO: check OID matches KRB5 Principal Name OID ? */
648 gss_maj
= gss_display_name(&gss_min
,
649 gse_ctx
->client_name
,
652 DEBUG(0, ("gss_display_name failed [%s]\n",
653 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
654 return NT_STATUS_INTERNAL_ERROR
;
657 *cli_name
= talloc_strndup(talloc_tos(),
658 (char *)name_buffer
.value
,
661 gss_maj
= gss_release_buffer(&gss_min
, &name_buffer
);
664 return NT_STATUS_NO_MEMORY
;
670 NTSTATUS
gse_get_authz_data(struct gse_context
*gse_ctx
,
671 TALLOC_CTX
*mem_ctx
, DATA_BLOB
*pac
)
673 OM_uint32 gss_min
, gss_maj
;
674 gss_buffer_set_t set
= GSS_C_NO_BUFFER_SET
;
676 if (!gse_ctx
->authenticated
) {
677 return NT_STATUS_ACCESS_DENIED
;
680 gss_maj
= gss_inquire_sec_context_by_oid(
681 &gss_min
, gse_ctx
->gss_ctx
,
682 &gse_authz_data_oid
, &set
);
684 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
685 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
686 return NT_STATUS_NOT_FOUND
;
689 if (set
== GSS_C_NO_BUFFER_SET
) {
690 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
691 "data in results.\n"));
692 return NT_STATUS_INTERNAL_ERROR
;
695 /* for now we just hope it is the first value */
696 *pac
= data_blob_talloc(mem_ctx
,
697 set
->elements
[0].value
,
698 set
->elements
[0].length
);
700 gss_maj
= gss_release_buffer_set(&gss_min
, &set
);
705 NTSTATUS
gse_get_authtime(struct gse_context
*gse_ctx
, time_t *authtime
)
707 OM_uint32 gss_min
, gss_maj
;
708 gss_buffer_set_t set
= GSS_C_NO_BUFFER_SET
;
711 if (!gse_ctx
->authenticated
) {
712 return NT_STATUS_ACCESS_DENIED
;
715 gss_maj
= gss_inquire_sec_context_by_oid(
716 &gss_min
, gse_ctx
->gss_ctx
,
717 &gse_authtime_oid
, &set
);
719 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
720 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
721 return NT_STATUS_NOT_FOUND
;
724 if ((set
== GSS_C_NO_BUFFER_SET
) || (set
->count
!= 1) != 0) {
725 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
726 "data in results.\n"));
727 return NT_STATUS_INTERNAL_ERROR
;
730 if (set
->elements
[0].length
!= sizeof(int32_t)) {
731 DEBUG(0, ("Invalid authtime size!\n"));
732 return NT_STATUS_INTERNAL_ERROR
;
735 tkttime
= *((int32_t *)set
->elements
[0].value
);
737 gss_maj
= gss_release_buffer_set(&gss_min
, &set
);
739 *authtime
= (time_t)tkttime
;
743 size_t gse_get_signature_length(struct gse_context
*gse_ctx
,
744 int seal
, size_t payload_size
)
746 OM_uint32 gss_min
, gss_maj
;
747 gss_iov_buffer_desc iov
[2];
748 uint8_t fakebuf
[payload_size
];
751 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
;
752 iov
[0].buffer
.value
= NULL
;
753 iov
[0].buffer
.length
= 0;
754 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
755 iov
[1].buffer
.value
= fakebuf
;
756 iov
[1].buffer
.length
= payload_size
;
758 gss_maj
= gss_wrap_iov_length(&gss_min
, gse_ctx
->gss_ctx
,
759 seal
, GSS_C_QOP_DEFAULT
,
762 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
763 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
767 return iov
[0].buffer
.length
;
770 NTSTATUS
gse_seal(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
771 DATA_BLOB
*data
, DATA_BLOB
*signature
)
773 OM_uint32 gss_min
, gss_maj
;
774 gss_iov_buffer_desc iov
[2];
775 int req_seal
= 1; /* setting to 1 means we request sign+seal */
779 /* allocate the memory ourselves so we do not need to talloc_memdup */
780 signature
->length
= gse_get_signature_length(gse_ctx
, 1, data
->length
);
781 if (!signature
->length
) {
782 return NT_STATUS_INTERNAL_ERROR
;
784 signature
->data
= (uint8_t *)talloc_size(mem_ctx
, signature
->length
);
785 if (!signature
->data
) {
786 return NT_STATUS_NO_MEMORY
;
788 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
;
789 iov
[0].buffer
.value
= signature
->data
;
790 iov
[0].buffer
.length
= signature
->length
;
792 /* data is encrypted in place, which is ok */
793 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
794 iov
[1].buffer
.value
= data
->data
;
795 iov
[1].buffer
.length
= data
->length
;
797 gss_maj
= gss_wrap_iov(&gss_min
, gse_ctx
->gss_ctx
,
798 req_seal
, GSS_C_QOP_DEFAULT
,
801 DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
802 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
803 status
= NT_STATUS_ACCESS_DENIED
;
808 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
809 status
= NT_STATUS_ACCESS_DENIED
;
813 status
= NT_STATUS_OK
;
815 DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
816 (int)iov
[1].buffer
.length
, (int)iov
[0].buffer
.length
));
822 NTSTATUS
gse_unseal(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
823 DATA_BLOB
*data
, DATA_BLOB
*signature
)
825 OM_uint32 gss_min
, gss_maj
;
826 gss_iov_buffer_desc iov
[2];
830 iov
[0].type
= GSS_IOV_BUFFER_TYPE_HEADER
;
831 iov
[0].buffer
.value
= signature
->data
;
832 iov
[0].buffer
.length
= signature
->length
;
834 /* data is decrypted in place, which is ok */
835 iov
[1].type
= GSS_IOV_BUFFER_TYPE_DATA
;
836 iov
[1].buffer
.value
= data
->data
;
837 iov
[1].buffer
.length
= data
->length
;
839 gss_maj
= gss_unwrap_iov(&gss_min
, gse_ctx
->gss_ctx
,
840 &sealed
, NULL
, iov
, 2);
842 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
843 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
844 status
= NT_STATUS_ACCESS_DENIED
;
849 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
850 status
= NT_STATUS_ACCESS_DENIED
;
854 status
= NT_STATUS_OK
;
856 DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
857 (int)iov
[1].buffer
.length
, (int)iov
[0].buffer
.length
));
863 NTSTATUS
gse_sign(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
864 DATA_BLOB
*data
, DATA_BLOB
*signature
)
866 OM_uint32 gss_min
, gss_maj
;
867 gss_buffer_desc in_data
= { 0, NULL
};
868 gss_buffer_desc out_data
= { 0, NULL
};
871 in_data
.value
= data
->data
;
872 in_data
.length
= data
->length
;
874 gss_maj
= gss_get_mic(&gss_min
, gse_ctx
->gss_ctx
,
876 &in_data
, &out_data
);
878 DEBUG(0, ("gss_get_mic failed with [%s]\n",
879 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
880 status
= NT_STATUS_ACCESS_DENIED
;
884 *signature
= data_blob_talloc(mem_ctx
,
885 out_data
.value
, out_data
.length
);
886 if (!signature
->data
) {
887 status
= NT_STATUS_NO_MEMORY
;
891 status
= NT_STATUS_OK
;
894 if (out_data
.value
) {
895 gss_maj
= gss_release_buffer(&gss_min
, &out_data
);
900 NTSTATUS
gse_sigcheck(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
901 DATA_BLOB
*data
, DATA_BLOB
*signature
)
903 OM_uint32 gss_min
, gss_maj
;
904 gss_buffer_desc in_data
= { 0, NULL
};
905 gss_buffer_desc in_token
= { 0, NULL
};
908 in_data
.value
= data
->data
;
909 in_data
.length
= data
->length
;
910 in_token
.value
= signature
->data
;
911 in_token
.length
= signature
->length
;
913 gss_maj
= gss_verify_mic(&gss_min
, gse_ctx
->gss_ctx
,
914 &in_data
, &in_token
, NULL
);
916 DEBUG(0, ("gss_verify_mic failed with [%s]\n",
917 gse_errstr(talloc_tos(), gss_maj
, gss_min
)));
918 status
= NT_STATUS_ACCESS_DENIED
;
922 status
= NT_STATUS_OK
;
930 NTSTATUS
gse_init_client(TALLOC_CTX
*mem_ctx
,
931 enum dcerpc_AuthType auth_type
,
932 enum dcerpc_AuthLevel auth_level
,
933 const char *ccache_name
,
936 const char *username
,
937 const char *password
,
938 uint32_t add_gss_c_flags
,
939 struct gse_context
**_gse_ctx
)
941 return NT_STATUS_NOT_IMPLEMENTED
;
944 NTSTATUS
gse_get_client_auth_token(TALLOC_CTX
*mem_ctx
,
945 struct gse_context
*gse_ctx
,
947 DATA_BLOB
*token_out
)
949 return NT_STATUS_NOT_IMPLEMENTED
;
952 NTSTATUS
gse_init_server(TALLOC_CTX
*mem_ctx
,
953 enum dcerpc_AuthType auth_type
,
954 enum dcerpc_AuthLevel auth_level
,
955 uint32_t add_gss_c_flags
,
958 struct gse_context
**_gse_ctx
)
960 return NT_STATUS_NOT_IMPLEMENTED
;
963 NTSTATUS
gse_get_server_auth_token(TALLOC_CTX
*mem_ctx
,
964 struct gse_context
*gse_ctx
,
966 DATA_BLOB
*token_out
)
968 return NT_STATUS_NOT_IMPLEMENTED
;
971 NTSTATUS
gse_verify_server_auth_flags(struct gse_context
*gse_ctx
)
973 return NT_STATUS_NOT_IMPLEMENTED
;
976 bool gse_require_more_processing(struct gse_context
*gse_ctx
)
981 DATA_BLOB
gse_get_session_key(TALLOC_CTX
*mem_ctx
,
982 struct gse_context
*gse_ctx
)
984 return data_blob_null
;
987 NTSTATUS
gse_get_client_name(struct gse_context
*gse_ctx
,
988 TALLOC_CTX
*mem_ctx
, char **cli_name
)
990 return NT_STATUS_NOT_IMPLEMENTED
;
993 NTSTATUS
gse_get_authz_data(struct gse_context
*gse_ctx
,
994 TALLOC_CTX
*mem_ctx
, DATA_BLOB
*pac
)
996 return NT_STATUS_NOT_IMPLEMENTED
;
999 NTSTATUS
gse_get_authtime(struct gse_context
*gse_ctx
, time_t *authtime
)
1001 return NT_STATUS_NOT_IMPLEMENTED
;
1004 size_t gse_get_signature_length(struct gse_context
*gse_ctx
,
1005 int seal
, size_t payload_size
)
1010 NTSTATUS
gse_seal(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
1011 DATA_BLOB
*data
, DATA_BLOB
*signature
)
1013 return NT_STATUS_NOT_IMPLEMENTED
;
1016 NTSTATUS
gse_unseal(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
1017 DATA_BLOB
*data
, DATA_BLOB
*signature
)
1019 return NT_STATUS_NOT_IMPLEMENTED
;
1022 NTSTATUS
gse_sign(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
1023 DATA_BLOB
*data
, DATA_BLOB
*signature
)
1025 return NT_STATUS_NOT_IMPLEMENTED
;
1028 NTSTATUS
gse_sigcheck(TALLOC_CTX
*mem_ctx
, struct gse_context
*gse_ctx
,
1029 DATA_BLOB
*data
, DATA_BLOB
*signature
)
1031 return NT_STATUS_NOT_IMPLEMENTED
;
1034 #endif /* HAVE_KRB5 && HAVE_GSSAPI_EXT_H && HAVE_GSS_WRAP_IOV */