2 * Copyright (c) 2005 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
29 #include "mech_locl.h"
35 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
36 gss_krb5_copy_ccache(OM_uint32
*minor_status
,
40 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
47 ret
= gss_inquire_cred_by_oid(minor_status
,
49 GSS_KRB5_COPY_CCACHE_X
,
54 if (data_set
== GSS_C_NO_BUFFER_SET
|| data_set
->count
< 1) {
55 gss_release_buffer_set(minor_status
, &data_set
);
56 *minor_status
= EINVAL
;
60 kret
= krb5_init_context(&context
);
63 gss_release_buffer_set(minor_status
, &data_set
);
67 kret
= asprintf(&str
, "%.*s", (int)data_set
->elements
[0].length
,
68 (char *)data_set
->elements
[0].value
);
69 gss_release_buffer_set(minor_status
, &data_set
);
70 if (kret
< 0 || str
== NULL
) {
71 *minor_status
= ENOMEM
;
75 kret
= krb5_cc_resolve(context
, str
, &id
);
82 kret
= krb5_cc_copy_cache(context
, id
, out
);
83 krb5_cc_close(context
, id
);
84 krb5_free_context(context
);
93 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
94 gss_krb5_import_cred(OM_uint32
*minor_status
,
96 krb5_principal keytab_principal
,
100 gss_buffer_desc buffer
;
101 OM_uint32 major_status
;
102 krb5_context context
;
108 *cred
= GSS_C_NO_CREDENTIAL
;
110 ret
= krb5_init_context(&context
);
113 return GSS_S_FAILURE
;
116 sp
= krb5_storage_emem();
118 *minor_status
= ENOMEM
;
119 major_status
= GSS_S_FAILURE
;
124 ret
= krb5_cc_get_full_name(context
, id
, &str
);
126 ret
= krb5_store_string(sp
, str
);
130 ret
= krb5_store_string(sp
, "");
133 major_status
= GSS_S_FAILURE
;
137 if (keytab_principal
) {
138 ret
= krb5_unparse_name(context
, keytab_principal
, &str
);
140 ret
= krb5_store_string(sp
, str
);
144 krb5_store_string(sp
, "");
147 major_status
= GSS_S_FAILURE
;
153 ret
= krb5_kt_get_full_name(context
, keytab
, &str
);
155 ret
= krb5_store_string(sp
, str
);
159 krb5_store_string(sp
, "");
162 major_status
= GSS_S_FAILURE
;
166 ret
= krb5_storage_to_data(sp
, &data
);
169 major_status
= GSS_S_FAILURE
;
173 buffer
.value
= data
.data
;
174 buffer
.length
= data
.length
;
176 major_status
= gss_set_cred_option(minor_status
,
178 GSS_KRB5_IMPORT_CRED_X
,
180 krb5_data_free(&data
);
183 krb5_storage_free(sp
);
184 krb5_free_context(context
);
188 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
189 gsskrb5_register_acceptor_identity(const char *identity
)
191 gssapi_mech_interface m
;
192 gss_buffer_desc buffer
;
197 buffer
.value
= rk_UNCONST(identity
);
198 buffer
.length
= strlen(identity
);
200 m
= __gss_get_mechanism(GSS_KRB5_MECHANISM
);
201 if (m
== NULL
|| m
->gm_set_sec_context_option
== NULL
)
202 return GSS_S_FAILURE
;
204 return m
->gm_set_sec_context_option(&junk
, NULL
,
205 GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X
, &buffer
);
208 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
209 krb5_gss_register_acceptor_identity(const char *identity
)
211 return gsskrb5_register_acceptor_identity(identity
);
215 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
216 gsskrb5_set_dns_canonicalize(int flag
)
218 struct _gss_mech_switch
*m
;
219 gss_buffer_desc buffer
;
221 char b
= (flag
!= 0);
226 buffer
.length
= sizeof(b
);
228 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
229 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
231 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
232 GSS_KRB5_SET_DNS_CANONICALIZE_X
, &buffer
);
235 return (GSS_S_COMPLETE
);
240 static krb5_error_code
241 set_key(krb5_keyblock
*keyblock
, gss_krb5_lucid_key_t
*key
)
243 key
->type
= keyblock
->keytype
;
244 key
->length
= keyblock
->keyvalue
.length
;
245 key
->data
= malloc(key
->length
);
246 if (key
->data
== NULL
&& key
->length
!= 0)
248 memcpy(key
->data
, keyblock
->keyvalue
.data
, key
->length
);
253 free_key(gss_krb5_lucid_key_t
*key
)
255 memset(key
->data
, 0, key
->length
);
257 memset(key
, 0, sizeof(*key
));
260 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
261 gss_krb5_export_lucid_sec_context(OM_uint32
*minor_status
,
262 gss_ctx_id_t
*context_handle
,
266 krb5_context context
= NULL
;
268 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
269 OM_uint32 major_status
;
270 gss_krb5_lucid_context_v1_t
*ctx
= NULL
;
271 krb5_storage
*sp
= NULL
;
274 if (context_handle
== NULL
275 || *context_handle
== GSS_C_NO_CONTEXT
278 *minor_status
= EINVAL
;
279 return GSS_S_FAILURE
;
283 gss_inquire_sec_context_by_oid (minor_status
,
285 GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X
,
290 if (data_set
== GSS_C_NO_BUFFER_SET
|| data_set
->count
!= 1) {
291 gss_release_buffer_set(minor_status
, &data_set
);
292 *minor_status
= EINVAL
;
293 return GSS_S_FAILURE
;
296 ret
= krb5_init_context(&context
);
300 ctx
= calloc(1, sizeof(*ctx
));
306 sp
= krb5_storage_from_mem(data_set
->elements
[0].value
,
307 data_set
->elements
[0].length
);
313 ret
= krb5_ret_uint32(sp
, &num
);
321 ret
= krb5_ret_uint32(sp
, &ctx
->initiate
);
324 ret
= krb5_ret_uint32(sp
, &ctx
->endtime
);
327 ret
= krb5_ret_uint32(sp
, &num
);
329 ctx
->send_seq
= ((uint64_t)num
) << 32;
330 ret
= krb5_ret_uint32(sp
, &num
);
332 ctx
->send_seq
|= num
;
334 ret
= krb5_ret_uint32(sp
, &num
);
336 ctx
->recv_seq
= ((uint64_t)num
) << 32;
337 ret
= krb5_ret_uint32(sp
, &num
);
339 ctx
->recv_seq
|= num
;
341 ret
= krb5_ret_uint32(sp
, &ctx
->protocol
);
343 if (ctx
->protocol
== 0) {
347 ret
= krb5_ret_uint32(sp
, &ctx
->rfc1964_kd
.sign_alg
);
350 ret
= krb5_ret_uint32(sp
, &ctx
->rfc1964_kd
.seal_alg
);
353 ret
= krb5_ret_keyblock(sp
, &key
);
355 ret
= set_key(&key
, &ctx
->rfc1964_kd
.ctx_key
);
356 krb5_free_keyblock_contents(context
, &key
);
358 } else if (ctx
->protocol
== 1) {
361 /* acceptor_subkey */
362 ret
= krb5_ret_uint32(sp
, &ctx
->cfx_kd
.have_acceptor_subkey
);
365 ret
= krb5_ret_keyblock(sp
, &key
);
367 ret
= set_key(&key
, &ctx
->cfx_kd
.ctx_key
);
368 krb5_free_keyblock_contents(context
, &key
);
370 /* acceptor_subkey */
371 if (ctx
->cfx_kd
.have_acceptor_subkey
) {
372 ret
= krb5_ret_keyblock(sp
, &key
);
374 ret
= set_key(&key
, &ctx
->cfx_kd
.acceptor_subkey
);
375 krb5_free_keyblock_contents(context
, &key
);
386 gss_release_buffer_set(minor_status
, &data_set
);
388 krb5_storage_free(sp
);
390 krb5_free_context(context
);
394 gss_krb5_free_lucid_sec_context(NULL
, ctx
);
397 return GSS_S_FAILURE
;
400 return GSS_S_COMPLETE
;
403 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
404 gss_krb5_free_lucid_sec_context(OM_uint32
*minor_status
, void *c
)
406 gss_krb5_lucid_context_v1_t
*ctx
= c
;
408 if (ctx
->version
!= 1) {
411 return GSS_S_FAILURE
;
414 if (ctx
->protocol
== 0) {
415 free_key(&ctx
->rfc1964_kd
.ctx_key
);
416 } else if (ctx
->protocol
== 1) {
417 free_key(&ctx
->cfx_kd
.ctx_key
);
418 if (ctx
->cfx_kd
.have_acceptor_subkey
)
419 free_key(&ctx
->cfx_kd
.acceptor_subkey
);
424 return GSS_S_COMPLETE
;
431 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
432 gss_krb5_set_allowable_enctypes(OM_uint32
*minor_status
,
434 OM_uint32 num_enctypes
,
435 krb5_enctype
*enctypes
)
438 OM_uint32 maj_status
;
439 gss_buffer_desc buffer
;
444 sp
= krb5_storage_emem();
446 *minor_status
= ENOMEM
;
447 maj_status
= GSS_S_FAILURE
;
451 for (i
= 0; i
< num_enctypes
; i
++) {
452 ret
= krb5_store_int32(sp
, enctypes
[i
]);
455 maj_status
= GSS_S_FAILURE
;
460 ret
= krb5_storage_to_data(sp
, &data
);
463 maj_status
= GSS_S_FAILURE
;
467 buffer
.value
= data
.data
;
468 buffer
.length
= data
.length
;
470 maj_status
= gss_set_cred_option(minor_status
,
472 GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X
,
474 krb5_data_free(&data
);
477 krb5_storage_free(sp
);
485 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
486 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc
*c
)
488 struct _gss_mech_switch
*m
;
489 gss_buffer_desc buffer
;
496 buffer
.length
= sizeof(*c
);
502 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
503 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
505 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
506 GSS_KRB5_SEND_TO_KDC_X
, &buffer
);
509 return (GSS_S_COMPLETE
);
516 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
517 gss_krb5_ccache_name(OM_uint32
*minor_status
,
519 const char **out_name
)
521 struct _gss_mech_switch
*m
;
522 gss_buffer_desc buffer
;
530 buffer
.value
= rk_UNCONST(name
);
531 buffer
.length
= strlen(name
);
533 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
534 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
536 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
537 GSS_KRB5_CCACHE_NAME_X
, &buffer
);
540 return (GSS_S_COMPLETE
);
548 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
549 gsskrb5_extract_authtime_from_sec_context(OM_uint32
*minor_status
,
550 gss_ctx_id_t context_handle
,
553 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
556 if (context_handle
== GSS_C_NO_CONTEXT
) {
557 *minor_status
= EINVAL
;
558 return GSS_S_FAILURE
;
562 gss_inquire_sec_context_by_oid (minor_status
,
564 GSS_KRB5_GET_AUTHTIME_X
,
569 if (data_set
== GSS_C_NO_BUFFER_SET
) {
570 gss_release_buffer_set(minor_status
, &data_set
);
571 *minor_status
= EINVAL
;
572 return GSS_S_FAILURE
;
575 if (data_set
->count
!= 1) {
576 gss_release_buffer_set(minor_status
, &data_set
);
577 *minor_status
= EINVAL
;
578 return GSS_S_FAILURE
;
581 if (data_set
->elements
[0].length
!= 4) {
582 gss_release_buffer_set(minor_status
, &data_set
);
583 *minor_status
= EINVAL
;
584 return GSS_S_FAILURE
;
588 unsigned char *buf
= data_set
->elements
[0].value
;
589 *authtime
= (buf
[3] <<24) | (buf
[2] << 16) |
590 (buf
[1] << 8) | (buf
[0] << 0);
593 gss_release_buffer_set(minor_status
, &data_set
);
596 return GSS_S_COMPLETE
;
603 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
604 gsskrb5_extract_authz_data_from_sec_context(OM_uint32
*minor_status
,
605 gss_ctx_id_t context_handle
,
607 gss_buffer_t ad_data
)
609 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
610 OM_uint32 maj_stat
, tmp
;
611 gss_OID_desc oid_flat
;
612 heim_oid baseoid
, oid
;
615 if (context_handle
== GSS_C_NO_CONTEXT
) {
616 *minor_status
= EINVAL
;
617 return GSS_S_FAILURE
;
620 /* All this to append an integer to an oid... */
622 if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X
->elements
,
623 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X
->length
,
624 &baseoid
, NULL
) != 0) {
625 *minor_status
= EINVAL
;
626 return GSS_S_FAILURE
;
629 oid
.length
= baseoid
.length
+ 1;
630 oid
.components
= calloc(oid
.length
, sizeof(*oid
.components
));
631 if (oid
.components
== NULL
) {
632 der_free_oid(&baseoid
);
634 *minor_status
= ENOMEM
;
635 return GSS_S_FAILURE
;
638 memcpy(oid
.components
, baseoid
.components
,
639 baseoid
.length
* sizeof(*baseoid
.components
));
641 der_free_oid(&baseoid
);
643 oid
.components
[oid
.length
- 1] = ad_type
;
645 oid_flat
.length
= der_length_oid(&oid
);
646 oid_flat
.elements
= malloc(oid_flat
.length
);
647 if (oid_flat
.elements
== NULL
) {
648 free(oid
.components
);
649 *minor_status
= ENOMEM
;
650 return GSS_S_FAILURE
;
653 if (der_put_oid((unsigned char *)oid_flat
.elements
+ oid_flat
.length
- 1,
654 oid_flat
.length
, &oid
, &size
) != 0) {
655 free(oid
.components
);
656 _gss_free_oid(&tmp
, &oid_flat
);
657 *minor_status
= EINVAL
;
658 return GSS_S_FAILURE
;
660 if (oid_flat
.length
!= size
)
663 free(oid
.components
);
665 /* FINALLY, we have the OID */
667 maj_stat
= gss_inquire_sec_context_by_oid (minor_status
,
672 _gss_free_oid(&tmp
, &oid_flat
);
677 if (data_set
== GSS_C_NO_BUFFER_SET
|| data_set
->count
!= 1) {
678 gss_release_buffer_set(minor_status
, &data_set
);
679 *minor_status
= EINVAL
;
680 return GSS_S_FAILURE
;
683 ad_data
->value
= malloc(data_set
->elements
[0].length
);
684 if (ad_data
->value
== NULL
) {
685 gss_release_buffer_set(minor_status
, &data_set
);
686 *minor_status
= ENOMEM
;
687 return GSS_S_FAILURE
;
690 ad_data
->length
= data_set
->elements
[0].length
;
691 memcpy(ad_data
->value
, data_set
->elements
[0].value
, ad_data
->length
);
692 gss_release_buffer_set(minor_status
, &data_set
);
695 return GSS_S_COMPLETE
;
703 gsskrb5_extract_key(OM_uint32
*minor_status
,
704 gss_ctx_id_t context_handle
,
706 krb5_keyblock
**keyblock
)
709 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
710 OM_uint32 major_status
;
711 krb5_context context
= NULL
;
712 krb5_storage
*sp
= NULL
;
714 if (context_handle
== GSS_C_NO_CONTEXT
) {
715 *minor_status
= EINVAL
;
716 return GSS_S_FAILURE
;
719 ret
= krb5_init_context(&context
);
722 return GSS_S_FAILURE
;
726 gss_inquire_sec_context_by_oid (minor_status
,
733 if (data_set
== GSS_C_NO_BUFFER_SET
|| data_set
->count
!= 1) {
734 gss_release_buffer_set(minor_status
, &data_set
);
735 *minor_status
= EINVAL
;
736 return GSS_S_FAILURE
;
739 sp
= krb5_storage_from_mem(data_set
->elements
[0].value
,
740 data_set
->elements
[0].length
);
746 *keyblock
= calloc(1, sizeof(**keyblock
));
747 if (keyblock
== NULL
) {
752 ret
= krb5_ret_keyblock(sp
, *keyblock
);
755 gss_release_buffer_set(minor_status
, &data_set
);
757 krb5_storage_free(sp
);
758 if (ret
&& keyblock
) {
759 krb5_free_keyblock(context
, *keyblock
);
763 krb5_free_context(context
);
767 return GSS_S_FAILURE
;
769 return GSS_S_COMPLETE
;
776 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
777 gsskrb5_extract_service_keyblock(OM_uint32
*minor_status
,
778 gss_ctx_id_t context_handle
,
779 krb5_keyblock
**keyblock
)
781 return gsskrb5_extract_key(minor_status
,
783 GSS_KRB5_GET_SERVICE_KEYBLOCK_X
,
787 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
788 gsskrb5_get_initiator_subkey(OM_uint32
*minor_status
,
789 gss_ctx_id_t context_handle
,
790 krb5_keyblock
**keyblock
)
792 return gsskrb5_extract_key(minor_status
,
794 GSS_KRB5_GET_INITIATOR_SUBKEY_X
,
798 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
799 gsskrb5_get_subkey(OM_uint32
*minor_status
,
800 gss_ctx_id_t context_handle
,
801 krb5_keyblock
**keyblock
)
803 return gsskrb5_extract_key(minor_status
,
805 GSS_KRB5_GET_SUBKEY_X
,
809 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
810 gsskrb5_set_default_realm(const char *realm
)
812 struct _gss_mech_switch
*m
;
813 gss_buffer_desc buffer
;
818 buffer
.value
= rk_UNCONST(realm
);
819 buffer
.length
= strlen(realm
);
821 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
822 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
824 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
825 GSS_KRB5_SET_DEFAULT_REALM_X
, &buffer
);
828 return (GSS_S_COMPLETE
);
831 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
832 gss_krb5_get_tkt_flags(OM_uint32
*minor_status
,
833 gss_ctx_id_t context_handle
,
834 OM_uint32
*tkt_flags
)
837 OM_uint32 major_status
;
838 gss_buffer_set_t data_set
= GSS_C_NO_BUFFER_SET
;
840 if (context_handle
== GSS_C_NO_CONTEXT
) {
841 *minor_status
= EINVAL
;
842 return GSS_S_FAILURE
;
846 gss_inquire_sec_context_by_oid (minor_status
,
848 GSS_KRB5_GET_TKT_FLAGS_X
,
853 if (data_set
== GSS_C_NO_BUFFER_SET
||
854 data_set
->count
!= 1 ||
855 data_set
->elements
[0].length
< 4) {
856 gss_release_buffer_set(minor_status
, &data_set
);
857 *minor_status
= EINVAL
;
858 return GSS_S_FAILURE
;
862 const u_char
*p
= data_set
->elements
[0].value
;
863 *tkt_flags
= (p
[0] << 0) | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
866 gss_release_buffer_set(minor_status
, &data_set
);
867 return GSS_S_COMPLETE
;
870 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
871 gsskrb5_set_time_offset(int offset
)
873 struct _gss_mech_switch
*m
;
874 gss_buffer_desc buffer
;
881 buffer
.length
= sizeof(o
);
883 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
884 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
886 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
887 GSS_KRB5_SET_TIME_OFFSET_X
, &buffer
);
890 return (GSS_S_COMPLETE
);
893 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
894 gsskrb5_get_time_offset(int *offset
)
896 struct _gss_mech_switch
*m
;
897 gss_buffer_desc buffer
;
898 OM_uint32 maj_stat
, junk
;
904 buffer
.length
= sizeof(o
);
906 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
907 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
909 maj_stat
= m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
910 GSS_KRB5_GET_TIME_OFFSET_X
, &buffer
);
912 if (maj_stat
== GSS_S_COMPLETE
) {
918 return (GSS_S_UNAVAILABLE
);
921 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
922 gsskrb5_plugin_register(struct gsskrb5_krb5_plugin
*c
)
924 struct _gss_mech_switch
*m
;
925 gss_buffer_desc buffer
;
931 buffer
.length
= sizeof(*c
);
933 HEIM_SLIST_FOREACH(m
, &_gss_mechs
, gm_link
) {
934 if (m
->gm_mech
.gm_set_sec_context_option
== NULL
)
936 m
->gm_mech
.gm_set_sec_context_option(&junk
, NULL
,
937 GSS_KRB5_PLUGIN_REGISTER_X
, &buffer
);
940 return (GSS_S_COMPLETE
);