Fix VC warning about enctypes
[heimdal.git] / lib / gssapi / mech / gss_krb5.c
blobf81df431d8337ce2b895d97eb32c5c2467dae37c
1 /*-
2 * Copyright (c) 2005 Doug Rabson
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
24 * SUCH DAMAGE.
26 * $FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
29 #include "mech_locl.h"
31 #include <krb5.h>
32 #include <roken.h>
35 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
36 gss_krb5_copy_ccache(OM_uint32 *minor_status,
37 gss_cred_id_t cred,
38 krb5_ccache out)
40 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
41 krb5_context context;
42 krb5_error_code kret;
43 krb5_ccache id;
44 OM_uint32 ret;
45 char *str = NULL;
47 ret = gss_inquire_cred_by_oid(minor_status,
48 cred,
49 GSS_KRB5_COPY_CCACHE_X,
50 &data_set);
51 if (ret)
52 return ret;
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;
57 return GSS_S_FAILURE;
60 kret = krb5_init_context(&context);
61 if (kret) {
62 *minor_status = kret;
63 gss_release_buffer_set(minor_status, &data_set);
64 return GSS_S_FAILURE;
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;
72 return GSS_S_FAILURE;
75 kret = krb5_cc_resolve(context, str, &id);
76 free(str);
77 if (kret) {
78 *minor_status = kret;
79 return GSS_S_FAILURE;
82 kret = krb5_cc_copy_cache(context, id, out);
83 krb5_cc_close(context, id);
84 krb5_free_context(context);
85 if (kret) {
86 *minor_status = kret;
87 return GSS_S_FAILURE;
90 return ret;
93 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
94 gss_krb5_import_cred(OM_uint32 *minor_status,
95 krb5_ccache id,
96 krb5_principal keytab_principal,
97 krb5_keytab keytab,
98 gss_cred_id_t *cred)
100 gss_buffer_desc buffer;
101 OM_uint32 major_status;
102 krb5_context context;
103 krb5_error_code ret;
104 krb5_storage *sp;
105 krb5_data data;
106 char *str;
108 *cred = GSS_C_NO_CREDENTIAL;
110 ret = krb5_init_context(&context);
111 if (ret) {
112 *minor_status = ret;
113 return GSS_S_FAILURE;
116 sp = krb5_storage_emem();
117 if (sp == NULL) {
118 *minor_status = ENOMEM;
119 major_status = GSS_S_FAILURE;
120 goto out;
123 if (id) {
124 ret = krb5_cc_get_full_name(context, id, &str);
125 if (ret == 0) {
126 ret = krb5_store_string(sp, str);
127 free(str);
129 } else
130 ret = krb5_store_string(sp, "");
131 if (ret) {
132 *minor_status = ret;
133 major_status = GSS_S_FAILURE;
134 goto out;
137 if (keytab_principal) {
138 ret = krb5_unparse_name(context, keytab_principal, &str);
139 if (ret == 0) {
140 ret = krb5_store_string(sp, str);
141 free(str);
143 } else
144 krb5_store_string(sp, "");
145 if (ret) {
146 *minor_status = ret;
147 major_status = GSS_S_FAILURE;
148 goto out;
152 if (keytab) {
153 ret = krb5_kt_get_full_name(context, keytab, &str);
154 if (ret == 0) {
155 ret = krb5_store_string(sp, str);
156 free(str);
158 } else
159 krb5_store_string(sp, "");
160 if (ret) {
161 *minor_status = ret;
162 major_status = GSS_S_FAILURE;
163 goto out;
166 ret = krb5_storage_to_data(sp, &data);
167 if (ret) {
168 *minor_status = ret;
169 major_status = GSS_S_FAILURE;
170 goto out;
173 buffer.value = data.data;
174 buffer.length = data.length;
176 major_status = gss_set_cred_option(minor_status,
177 cred,
178 GSS_KRB5_IMPORT_CRED_X,
179 &buffer);
180 krb5_data_free(&data);
181 out:
182 if (sp)
183 krb5_storage_free(sp);
184 krb5_free_context(context);
185 return major_status;
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;
193 OM_uint32 junk;
195 _gss_load_mech();
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;
220 OM_uint32 junk;
221 char b = (flag != 0);
223 _gss_load_mech();
225 buffer.value = &b;
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)
230 continue;
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)
247 return ENOMEM;
248 memcpy(key->data, keyblock->keyvalue.data, key->length);
249 return 0;
252 static void
253 free_key(gss_krb5_lucid_key_t *key)
255 memset(key->data, 0, key->length);
256 free(key->data);
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,
263 OM_uint32 version,
264 void **rctx)
266 krb5_context context = NULL;
267 krb5_error_code ret;
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;
272 uint32_t num;
274 if (context_handle == NULL
275 || *context_handle == GSS_C_NO_CONTEXT
276 || version != 1)
278 *minor_status = EINVAL;
279 return GSS_S_FAILURE;
282 major_status =
283 gss_inquire_sec_context_by_oid (minor_status,
284 *context_handle,
285 GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X,
286 &data_set);
287 if (major_status)
288 return major_status;
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);
297 if (ret)
298 goto out;
300 ctx = calloc(1, sizeof(*ctx));
301 if (ctx == NULL) {
302 ret = ENOMEM;
303 goto out;
306 sp = krb5_storage_from_mem(data_set->elements[0].value,
307 data_set->elements[0].length);
308 if (sp == NULL) {
309 ret = ENOMEM;
310 goto out;
313 ret = krb5_ret_uint32(sp, &num);
314 if (ret) goto out;
315 if (num != 1) {
316 ret = EINVAL;
317 goto out;
319 ctx->version = 1;
320 /* initiator */
321 ret = krb5_ret_uint32(sp, &ctx->initiate);
322 if (ret) goto out;
323 /* endtime */
324 ret = krb5_ret_uint32(sp, &ctx->endtime);
325 if (ret) goto out;
326 /* send_seq */
327 ret = krb5_ret_uint32(sp, &num);
328 if (ret) goto out;
329 ctx->send_seq = ((uint64_t)num) << 32;
330 ret = krb5_ret_uint32(sp, &num);
331 if (ret) goto out;
332 ctx->send_seq |= num;
333 /* recv_seq */
334 ret = krb5_ret_uint32(sp, &num);
335 if (ret) goto out;
336 ctx->recv_seq = ((uint64_t)num) << 32;
337 ret = krb5_ret_uint32(sp, &num);
338 if (ret) goto out;
339 ctx->recv_seq |= num;
340 /* protocol */
341 ret = krb5_ret_uint32(sp, &ctx->protocol);
342 if (ret) goto out;
343 if (ctx->protocol == 0) {
344 krb5_keyblock key;
346 /* sign_alg */
347 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg);
348 if (ret) goto out;
349 /* seal_alg */
350 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg);
351 if (ret) goto out;
352 /* ctx_key */
353 ret = krb5_ret_keyblock(sp, &key);
354 if (ret) goto out;
355 ret = set_key(&key, &ctx->rfc1964_kd.ctx_key);
356 krb5_free_keyblock_contents(context, &key);
357 if (ret) goto out;
358 } else if (ctx->protocol == 1) {
359 krb5_keyblock key;
361 /* acceptor_subkey */
362 ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey);
363 if (ret) goto out;
364 /* ctx_key */
365 ret = krb5_ret_keyblock(sp, &key);
366 if (ret) goto out;
367 ret = set_key(&key, &ctx->cfx_kd.ctx_key);
368 krb5_free_keyblock_contents(context, &key);
369 if (ret) goto out;
370 /* acceptor_subkey */
371 if (ctx->cfx_kd.have_acceptor_subkey) {
372 ret = krb5_ret_keyblock(sp, &key);
373 if (ret) goto out;
374 ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey);
375 krb5_free_keyblock_contents(context, &key);
376 if (ret) goto out;
378 } else {
379 ret = EINVAL;
380 goto out;
383 *rctx = ctx;
385 out:
386 gss_release_buffer_set(minor_status, &data_set);
387 if (sp)
388 krb5_storage_free(sp);
389 if (context)
390 krb5_free_context(context);
392 if (ret) {
393 if (ctx)
394 gss_krb5_free_lucid_sec_context(NULL, ctx);
396 *minor_status = ret;
397 return GSS_S_FAILURE;
399 *minor_status = 0;
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) {
409 if (minor_status)
410 *minor_status = 0;
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);
421 free(ctx);
422 if (minor_status)
423 *minor_status = 0;
424 return GSS_S_COMPLETE;
431 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
432 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
433 gss_cred_id_t cred,
434 OM_uint32 num_enctypes,
435 krb5_enctype *enctypes)
437 krb5_error_code ret;
438 OM_uint32 maj_status;
439 gss_buffer_desc buffer;
440 krb5_storage *sp;
441 krb5_data data;
442 size_t i;
444 sp = krb5_storage_emem();
445 if (sp == NULL) {
446 *minor_status = ENOMEM;
447 maj_status = GSS_S_FAILURE;
448 goto out;
451 for (i = 0; i < num_enctypes; i++) {
452 ret = krb5_store_int32(sp, enctypes[i]);
453 if (ret) {
454 *minor_status = ret;
455 maj_status = GSS_S_FAILURE;
456 goto out;
460 ret = krb5_storage_to_data(sp, &data);
461 if (ret) {
462 *minor_status = ret;
463 maj_status = GSS_S_FAILURE;
464 goto out;
467 buffer.value = data.data;
468 buffer.length = data.length;
470 maj_status = gss_set_cred_option(minor_status,
471 &cred,
472 GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
473 &buffer);
474 krb5_data_free(&data);
475 out:
476 if (sp)
477 krb5_storage_free(sp);
478 return maj_status;
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;
490 OM_uint32 junk;
492 _gss_load_mech();
494 if (c) {
495 buffer.value = c;
496 buffer.length = sizeof(*c);
497 } else {
498 buffer.value = NULL;
499 buffer.length = 0;
502 HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
503 if (m->gm_mech.gm_set_sec_context_option == NULL)
504 continue;
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,
518 const char *name,
519 const char **out_name)
521 struct _gss_mech_switch *m;
522 gss_buffer_desc buffer;
523 OM_uint32 junk;
525 _gss_load_mech();
527 if (out_name)
528 *out_name = NULL;
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)
535 continue;
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,
551 time_t *authtime)
553 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
554 OM_uint32 maj_stat;
556 if (context_handle == GSS_C_NO_CONTEXT) {
557 *minor_status = EINVAL;
558 return GSS_S_FAILURE;
561 maj_stat =
562 gss_inquire_sec_context_by_oid (minor_status,
563 context_handle,
564 GSS_KRB5_GET_AUTHTIME_X,
565 &data_set);
566 if (maj_stat)
567 return maj_stat;
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);
595 *minor_status = 0;
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,
606 int ad_type,
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;
613 size_t size;
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)
661 abort();
663 free(oid.components);
665 /* FINALLY, we have the OID */
667 maj_stat = gss_inquire_sec_context_by_oid (minor_status,
668 context_handle,
669 &oid_flat,
670 &data_set);
672 _gss_free_oid(&tmp, &oid_flat);
674 if (maj_stat)
675 return maj_stat;
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);
694 *minor_status = 0;
695 return GSS_S_COMPLETE;
702 static OM_uint32
703 gsskrb5_extract_key(OM_uint32 *minor_status,
704 gss_ctx_id_t context_handle,
705 const gss_OID oid,
706 krb5_keyblock **keyblock)
708 krb5_error_code ret;
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);
720 if(ret) {
721 *minor_status = ret;
722 return GSS_S_FAILURE;
725 major_status =
726 gss_inquire_sec_context_by_oid (minor_status,
727 context_handle,
728 oid,
729 &data_set);
730 if (major_status)
731 return major_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);
741 if (sp == NULL) {
742 ret = ENOMEM;
743 goto out;
746 *keyblock = calloc(1, sizeof(**keyblock));
747 if (keyblock == NULL) {
748 ret = ENOMEM;
749 goto out;
752 ret = krb5_ret_keyblock(sp, *keyblock);
754 out:
755 gss_release_buffer_set(minor_status, &data_set);
756 if (sp)
757 krb5_storage_free(sp);
758 if (ret && keyblock) {
759 krb5_free_keyblock(context, *keyblock);
760 *keyblock = NULL;
762 if (context)
763 krb5_free_context(context);
765 *minor_status = ret;
766 if (ret)
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,
782 context_handle,
783 GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
784 keyblock);
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,
793 context_handle,
794 GSS_KRB5_GET_INITIATOR_SUBKEY_X,
795 keyblock);
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,
804 context_handle,
805 GSS_KRB5_GET_SUBKEY_X,
806 keyblock);
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;
814 OM_uint32 junk;
816 _gss_load_mech();
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)
823 continue;
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;
845 major_status =
846 gss_inquire_sec_context_by_oid (minor_status,
847 context_handle,
848 GSS_KRB5_GET_TKT_FLAGS_X,
849 &data_set);
850 if (major_status)
851 return major_status;
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;
875 OM_uint32 junk;
876 int32_t o = offset;
878 _gss_load_mech();
880 buffer.value = &o;
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)
885 continue;
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;
899 int32_t o;
901 _gss_load_mech();
903 buffer.value = &o;
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)
908 continue;
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) {
913 *offset = o;
914 return maj_stat;
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;
926 OM_uint32 junk;
928 _gss_load_mech();
930 buffer.value = c;
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)
935 continue;
936 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
937 GSS_KRB5_PLUGIN_REGISTER_X, &buffer);
940 return (GSS_S_COMPLETE);