/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- gss_krb5_copy_ccache
- gss_krb5_import_cred
- gsskrb5_register_acceptor_identity
- krb5_gss_register_acceptor_identity
- gsskrb5_set_dns_canonicalize
- set_key
- free_key
- gss_krb5_export_lucid_sec_context
- gss_krb5_free_lucid_sec_context
- gss_krb5_set_allowable_enctypes
- gsskrb5_set_send_to_kdc
- gss_krb5_ccache_name
- gsskrb5_extract_authtime_from_sec_context
- gsskrb5_extract_authz_data_from_sec_context
- gsskrb5_extract_key
- gsskrb5_extract_service_keyblock
- gsskrb5_get_initiator_subkey
- gsskrb5_get_subkey
- gsskrb5_set_default_realm
- gss_krb5_get_tkt_flags
- gsskrb5_set_time_offset
- gsskrb5_get_time_offset
- gsskrb5_plugin_register
1 /*-
2 * Copyright (c) 2005 Doug Rabson
3 * All rights reserved.
4 *
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.
13 *
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.
25 *
26 * $FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
27 */
28
29 #include "mech_locl.h"
30 RCSID("$Id$");
31
32 #include <krb5.h>
33 #include <roken.h>
34
35
36 OM_uint32 GSSAPI_LIB_FUNCTION
37 gss_krb5_copy_ccache(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
38 gss_cred_id_t cred,
39 krb5_ccache out)
40 {
41 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
42 krb5_context context;
43 krb5_error_code kret;
44 krb5_ccache id;
45 OM_uint32 ret;
46 char *str;
47
48 ret = gss_inquire_cred_by_oid(minor_status,
49 cred,
50 GSS_KRB5_COPY_CCACHE_X,
51 &data_set);
52 if (ret)
53 return ret;
54
55 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count < 1) {
56 gss_release_buffer_set(minor_status, &data_set);
57 *minor_status = EINVAL;
58 return GSS_S_FAILURE;
59 }
60
61 kret = krb5_init_context(&context);
62 if (kret) {
63 *minor_status = kret;
64 gss_release_buffer_set(minor_status, &data_set);
65 return GSS_S_FAILURE;
66 }
67
68 kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
69 (char *)data_set->elements[0].value);
70 gss_release_buffer_set(minor_status, &data_set);
71 if (kret == -1) {
72 *minor_status = ENOMEM;
73 return GSS_S_FAILURE;
74 }
75
76 kret = krb5_cc_resolve(context, str, &id);
77 free(str);
78 if (kret) {
79 *minor_status = kret;
80 return GSS_S_FAILURE;
81 }
82
83 kret = krb5_cc_copy_cache(context, id, out);
84 krb5_cc_close(context, id);
85 krb5_free_context(context);
86 if (kret) {
87 *minor_status = kret;
88 return GSS_S_FAILURE;
89 }
90
91 return ret;
92 }
93
94 OM_uint32 GSSAPI_LIB_FUNCTION
95 gss_krb5_import_cred(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
96 krb5_ccache id,
97 krb5_principal keytab_principal,
98 krb5_keytab keytab,
99 gss_cred_id_t *cred)
100 {
101 gss_buffer_desc buffer;
102 OM_uint32 major_status;
103 krb5_context context;
104 krb5_error_code ret;
105 krb5_storage *sp;
106 krb5_data data;
107 char *str;
108
109 *cred = GSS_C_NO_CREDENTIAL;
110
111 ret = krb5_init_context(&context);
112 if (ret) {
113 *minor_status = ret;
114 return GSS_S_FAILURE;
115 }
116
117 sp = krb5_storage_emem();
118 if (sp == NULL) {
119 *minor_status = ENOMEM;
120 major_status = GSS_S_FAILURE;
121 goto out;
122 }
123
124 if (id) {
125 ret = krb5_cc_get_full_name(context, id, &str);
126 if (ret == 0) {
127 ret = krb5_store_string(sp, str);
128 free(str);
129 }
130 } else
131 ret = krb5_store_string(sp, "");
132 if (ret) {
133 *minor_status = ret;
134 major_status = GSS_S_FAILURE;
135 goto out;
136 }
137
138 if (keytab_principal) {
139 ret = krb5_unparse_name(context, keytab_principal, &str);
140 if (ret == 0) {
141 ret = krb5_store_string(sp, str);
142 free(str);
143 }
144 } else
145 krb5_store_string(sp, "");
146 if (ret) {
147 *minor_status = ret;
148 major_status = GSS_S_FAILURE;
149 goto out;
150 }
151
152
153 if (keytab) {
154 ret = krb5_kt_get_full_name(context, keytab, &str);
155 if (ret == 0) {
156 ret = krb5_store_string(sp, str);
157 free(str);
158 }
159 } else
160 krb5_store_string(sp, "");
161 if (ret) {
162 *minor_status = ret;
163 major_status = GSS_S_FAILURE;
164 goto out;
165 }
166
167 ret = krb5_storage_to_data(sp, &data);
168 if (ret) {
169 *minor_status = ret;
170 major_status = GSS_S_FAILURE;
171 goto out;
172 }
173
174 buffer.value = data.data;
175 buffer.length = data.length;
176
177 major_status = gss_set_cred_option(minor_status,
178 cred,
179 GSS_KRB5_IMPORT_CRED_X,
180 &buffer);
181 krb5_data_free(&data);
182 out:
183 if (sp)
184 krb5_storage_free(sp);
185 krb5_free_context(context);
186 return major_status;
187 }
188
189 OM_uint32 GSSAPI_LIB_FUNCTION
190 gsskrb5_register_acceptor_identity(const char *identity)
/* [<][>][^][v][top][bottom][index][help] */
191 {
192 struct _gss_mech_switch *m;
193 gss_buffer_desc buffer;
194 OM_uint32 junk;
195
196 _gss_load_mech();
197
198 buffer.value = rk_UNCONST(identity);
199 buffer.length = strlen(identity);
200
201 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
202 if (m->gm_mech.gm_set_sec_context_option == NULL)
203 continue;
204 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
205 GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer);
206 }
207
208 return (GSS_S_COMPLETE);
209 }
210
211 OM_uint32 GSSAPI_LIB_FUNCTION
212 krb5_gss_register_acceptor_identity(const char *identity)
/* [<][>][^][v][top][bottom][index][help] */
213 {
214 return gsskrb5_register_acceptor_identity(identity);
215 }
216
217
218 OM_uint32 GSSAPI_LIB_FUNCTION
219 gsskrb5_set_dns_canonicalize(int flag)
/* [<][>][^][v][top][bottom][index][help] */
220 {
221 struct _gss_mech_switch *m;
222 gss_buffer_desc buffer;
223 OM_uint32 junk;
224 char b = (flag != 0);
225
226 _gss_load_mech();
227
228 buffer.value = &b;
229 buffer.length = sizeof(b);
230
231 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
232 if (m->gm_mech.gm_set_sec_context_option == NULL)
233 continue;
234 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
235 GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer);
236 }
237
238 return (GSS_S_COMPLETE);
239 }
240
241
242
243 static krb5_error_code
244 set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key)
/* [<][>][^][v][top][bottom][index][help] */
245 {
246 key->type = keyblock->keytype;
247 key->length = keyblock->keyvalue.length;
248 key->data = malloc(key->length);
249 if (key->data == NULL && key->length != 0)
250 return ENOMEM;
251 memcpy(key->data, keyblock->keyvalue.data, key->length);
252 return 0;
253 }
254
255 static void
256 free_key(gss_krb5_lucid_key_t *key)
/* [<][>][^][v][top][bottom][index][help] */
257 {
258 memset(key->data, 0, key->length);
259 free(key->data);
260 memset(key, 0, sizeof(*key));
261 }
262
263 OM_uint32 GSSAPI_LIB_FUNCTION
264 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
265 gss_ctx_id_t *context_handle,
266 OM_uint32 version,
267 void **rctx)
268 {
269 krb5_context context = NULL;
270 krb5_error_code ret;
271 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
272 OM_uint32 major_status;
273 gss_krb5_lucid_context_v1_t *ctx = NULL;
274 krb5_storage *sp = NULL;
275 uint32_t num;
276
277 if (context_handle == NULL
278 || *context_handle == GSS_C_NO_CONTEXT
279 || version != 1)
280 {
281 ret = EINVAL;
282 return GSS_S_FAILURE;
283 }
284
285 major_status =
286 gss_inquire_sec_context_by_oid (minor_status,
287 *context_handle,
288 GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X,
289 &data_set);
290 if (major_status)
291 return major_status;
292
293 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
294 gss_release_buffer_set(minor_status, &data_set);
295 *minor_status = EINVAL;
296 return GSS_S_FAILURE;
297 }
298
299 ret = krb5_init_context(&context);
300 if (ret)
301 goto out;
302
303 ctx = calloc(1, sizeof(*ctx));
304 if (ctx == NULL) {
305 ret = ENOMEM;
306 goto out;
307 }
308
309 sp = krb5_storage_from_mem(data_set->elements[0].value,
310 data_set->elements[0].length);
311 if (sp == NULL) {
312 ret = ENOMEM;
313 goto out;
314 }
315
316 ret = krb5_ret_uint32(sp, &num);
317 if (ret) goto out;
318 if (num != 1) {
319 ret = EINVAL;
320 goto out;
321 }
322 ctx->version = 1;
323 /* initiator */
324 ret = krb5_ret_uint32(sp, &ctx->initiate);
325 if (ret) goto out;
326 /* endtime */
327 ret = krb5_ret_uint32(sp, &ctx->endtime);
328 if (ret) goto out;
329 /* send_seq */
330 ret = krb5_ret_uint32(sp, &num);
331 if (ret) goto out;
332 ctx->send_seq = ((uint64_t)num) << 32;
333 ret = krb5_ret_uint32(sp, &num);
334 if (ret) goto out;
335 ctx->send_seq |= num;
336 /* recv_seq */
337 ret = krb5_ret_uint32(sp, &num);
338 if (ret) goto out;
339 ctx->recv_seq = ((uint64_t)num) << 32;
340 ret = krb5_ret_uint32(sp, &num);
341 if (ret) goto out;
342 ctx->recv_seq |= num;
343 /* protocol */
344 ret = krb5_ret_uint32(sp, &ctx->protocol);
345 if (ret) goto out;
346 if (ctx->protocol == 0) {
347 krb5_keyblock key;
348
349 /* sign_alg */
350 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg);
351 if (ret) goto out;
352 /* seal_alg */
353 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg);
354 if (ret) goto out;
355 /* ctx_key */
356 ret = krb5_ret_keyblock(sp, &key);
357 if (ret) goto out;
358 ret = set_key(&key, &ctx->rfc1964_kd.ctx_key);
359 krb5_free_keyblock_contents(context, &key);
360 if (ret) goto out;
361 } else if (ctx->protocol == 1) {
362 krb5_keyblock key;
363
364 /* acceptor_subkey */
365 ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey);
366 if (ret) goto out;
367 /* ctx_key */
368 ret = krb5_ret_keyblock(sp, &key);
369 if (ret) goto out;
370 ret = set_key(&key, &ctx->cfx_kd.ctx_key);
371 krb5_free_keyblock_contents(context, &key);
372 if (ret) goto out;
373 /* acceptor_subkey */
374 if (ctx->cfx_kd.have_acceptor_subkey) {
375 ret = krb5_ret_keyblock(sp, &key);
376 if (ret) goto out;
377 ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey);
378 krb5_free_keyblock_contents(context, &key);
379 if (ret) goto out;
380 }
381 } else {
382 ret = EINVAL;
383 goto out;
384 }
385
386 *rctx = ctx;
387
388 out:
389 gss_release_buffer_set(minor_status, &data_set);
390 if (sp)
391 krb5_storage_free(sp);
392 if (context)
393 krb5_free_context(context);
394
395 if (ret) {
396 if (ctx)
397 gss_krb5_free_lucid_sec_context(NULL, ctx);
398
399 *minor_status = ret;
400 return GSS_S_FAILURE;
401 }
402 *minor_status = 0;
403 return GSS_S_COMPLETE;
404 }
405
406 OM_uint32 GSSAPI_LIB_FUNCTION
407 gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
/* [<][>][^][v][top][bottom][index][help] */
408 {
409 gss_krb5_lucid_context_v1_t *ctx = c;
410
411 if (ctx->version != 1) {
412 if (minor_status)
413 *minor_status = 0;
414 return GSS_S_FAILURE;
415 }
416
417 if (ctx->protocol == 0) {
418 free_key(&ctx->rfc1964_kd.ctx_key);
419 } else if (ctx->protocol == 1) {
420 free_key(&ctx->cfx_kd.ctx_key);
421 if (ctx->cfx_kd.have_acceptor_subkey)
422 free_key(&ctx->cfx_kd.acceptor_subkey);
423 }
424 free(ctx);
425 if (minor_status)
426 *minor_status = 0;
427 return GSS_S_COMPLETE;
428 }
429
430 /*
431 *
432 */
433
434 OM_uint32 GSSAPI_LIB_FUNCTION
435 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
436 gss_cred_id_t cred,
437 OM_uint32 num_enctypes,
438 int32_t *enctypes)
439 {
440 krb5_error_code ret;
441 OM_uint32 maj_status;
442 gss_buffer_desc buffer;
443 krb5_storage *sp;
444 krb5_data data;
445 int i;
446
447 sp = krb5_storage_emem();
448 if (sp == NULL) {
449 *minor_status = ENOMEM;
450 maj_status = GSS_S_FAILURE;
451 goto out;
452 }
453
454 for (i = 0; i < num_enctypes; i++) {
455 ret = krb5_store_int32(sp, enctypes[i]);
456 if (ret) {
457 *minor_status = ret;
458 maj_status = GSS_S_FAILURE;
459 goto out;
460 }
461 }
462
463 ret = krb5_storage_to_data(sp, &data);
464 if (ret) {
465 *minor_status = ret;
466 maj_status = GSS_S_FAILURE;
467 goto out;
468 }
469
470 buffer.value = data.data;
471 buffer.length = data.length;
472
473 maj_status = gss_set_cred_option(minor_status,
474 &cred,
475 GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
476 &buffer);
477 krb5_data_free(&data);
478 out:
479 if (sp)
480 krb5_storage_free(sp);
481 return maj_status;
482 }
483
484 /*
485 *
486 */
487
488 OM_uint32 GSSAPI_LIB_FUNCTION
489 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
/* [<][>][^][v][top][bottom][index][help] */
490 {
491 struct _gss_mech_switch *m;
492 gss_buffer_desc buffer;
493 OM_uint32 junk;
494
495 _gss_load_mech();
496
497 if (c) {
498 buffer.value = c;
499 buffer.length = sizeof(*c);
500 } else {
501 buffer.value = NULL;
502 buffer.length = 0;
503 }
504
505 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
506 if (m->gm_mech.gm_set_sec_context_option == NULL)
507 continue;
508 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
509 GSS_KRB5_SEND_TO_KDC_X, &buffer);
510 }
511
512 return (GSS_S_COMPLETE);
513 }
514
515 /*
516 *
517 */
518
519 OM_uint32 GSSAPI_LIB_FUNCTION
520 gss_krb5_ccache_name(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
521 const char *name,
522 const char **out_name)
523 {
524 struct _gss_mech_switch *m;
525 gss_buffer_desc buffer;
526 OM_uint32 junk;
527
528 _gss_load_mech();
529
530 if (out_name)
531 *out_name = NULL;
532
533 buffer.value = rk_UNCONST(name);
534 buffer.length = strlen(name);
535
536 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
537 if (m->gm_mech.gm_set_sec_context_option == NULL)
538 continue;
539 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
540 GSS_KRB5_CCACHE_NAME_X, &buffer);
541 }
542
543 return (GSS_S_COMPLETE);
544 }
545
546
547 /*
548 *
549 */
550
551 OM_uint32 GSSAPI_LIB_FUNCTION
552 gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
553 gss_ctx_id_t context_handle,
554 time_t *authtime)
555 {
556 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
557 OM_uint32 maj_stat;
558
559 if (context_handle == GSS_C_NO_CONTEXT) {
560 *minor_status = EINVAL;
561 return GSS_S_FAILURE;
562 }
563
564 maj_stat =
565 gss_inquire_sec_context_by_oid (minor_status,
566 context_handle,
567 GSS_KRB5_GET_AUTHTIME_X,
568 &data_set);
569 if (maj_stat)
570 return maj_stat;
571
572 if (data_set == GSS_C_NO_BUFFER_SET) {
573 gss_release_buffer_set(minor_status, &data_set);
574 *minor_status = EINVAL;
575 return GSS_S_FAILURE;
576 }
577
578 if (data_set->count != 1) {
579 gss_release_buffer_set(minor_status, &data_set);
580 *minor_status = EINVAL;
581 return GSS_S_FAILURE;
582 }
583
584 if (data_set->elements[0].length != 4) {
585 gss_release_buffer_set(minor_status, &data_set);
586 *minor_status = EINVAL;
587 return GSS_S_FAILURE;
588 }
589
590 {
591 unsigned char *buf = data_set->elements[0].value;
592 *authtime = (buf[3] <<24) | (buf[2] << 16) |
593 (buf[1] << 8) | (buf[0] << 0);
594 }
595
596 gss_release_buffer_set(minor_status, &data_set);
597
598 *minor_status = 0;
599 return GSS_S_COMPLETE;
600 }
601
602 /*
603 *
604 */
605
606 OM_uint32 GSSAPI_LIB_FUNCTION
607 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
608 gss_ctx_id_t context_handle,
609 int ad_type,
610 gss_buffer_t ad_data)
611 {
612 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
613 OM_uint32 maj_stat;
614 gss_OID_desc oid_flat;
615 heim_oid baseoid, oid;
616 size_t size;
617
618 if (context_handle == GSS_C_NO_CONTEXT) {
619 *minor_status = EINVAL;
620 return GSS_S_FAILURE;
621 }
622
623 /* All this to append an integer to an oid... */
624
625 if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
626 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
627 &baseoid, NULL) != 0) {
628 *minor_status = EINVAL;
629 return GSS_S_FAILURE;
630 }
631
632 oid.length = baseoid.length + 1;
633 oid.components = calloc(oid.length, sizeof(*oid.components));
634 if (oid.components == NULL) {
635 der_free_oid(&baseoid);
636
637 *minor_status = ENOMEM;
638 return GSS_S_FAILURE;
639 }
640
641 memcpy(oid.components, baseoid.components,
642 baseoid.length * sizeof(*baseoid.components));
643
644 der_free_oid(&baseoid);
645
646 oid.components[oid.length - 1] = ad_type;
647
648 oid_flat.length = der_length_oid(&oid);
649 oid_flat.elements = malloc(oid_flat.length);
650 if (oid_flat.elements == NULL) {
651 free(oid.components);
652 *minor_status = ENOMEM;
653 return GSS_S_FAILURE;
654 }
655
656 if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
657 oid_flat.length, &oid, &size) != 0) {
658 free(oid.components);
659 free(oid_flat.elements);
660 *minor_status = EINVAL;
661 return GSS_S_FAILURE;
662 }
663 if (oid_flat.length != size)
664 abort();
665
666 free(oid.components);
667
668 /* FINALLY, we have the OID */
669
670 maj_stat = gss_inquire_sec_context_by_oid (minor_status,
671 context_handle,
672 &oid_flat,
673 &data_set);
674
675 free(oid_flat.elements);
676
677 if (maj_stat)
678 return maj_stat;
679
680 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
681 gss_release_buffer_set(minor_status, &data_set);
682 *minor_status = EINVAL;
683 return GSS_S_FAILURE;
684 }
685
686 ad_data->value = malloc(data_set->elements[0].length);
687 if (ad_data->value == NULL) {
688 gss_release_buffer_set(minor_status, &data_set);
689 *minor_status = ENOMEM;
690 return GSS_S_FAILURE;
691 }
692
693 ad_data->length = data_set->elements[0].length;
694 memcpy(ad_data->value, data_set->elements[0].value, ad_data->length);
695 gss_release_buffer_set(minor_status, &data_set);
696
697 *minor_status = 0;
698 return GSS_S_COMPLETE;
699 }
700
701 /*
702 *
703 */
704
705 static OM_uint32
706 gsskrb5_extract_key(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
707 gss_ctx_id_t context_handle,
708 const gss_OID oid,
709 krb5_keyblock **keyblock)
710 {
711 krb5_error_code ret;
712 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
713 OM_uint32 major_status;
714 krb5_context context = NULL;
715 krb5_storage *sp = NULL;
716
717 if (context_handle == GSS_C_NO_CONTEXT) {
718 ret = EINVAL;
719 return GSS_S_FAILURE;
720 }
721
722 ret = krb5_init_context(&context);
723 if(ret) {
724 *minor_status = ret;
725 return GSS_S_FAILURE;
726 }
727
728 major_status =
729 gss_inquire_sec_context_by_oid (minor_status,
730 context_handle,
731 oid,
732 &data_set);
733 if (major_status)
734 return major_status;
735
736 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
737 gss_release_buffer_set(minor_status, &data_set);
738 *minor_status = EINVAL;
739 return GSS_S_FAILURE;
740 }
741
742 sp = krb5_storage_from_mem(data_set->elements[0].value,
743 data_set->elements[0].length);
744 if (sp == NULL) {
745 ret = ENOMEM;
746 goto out;
747 }
748
749 *keyblock = calloc(1, sizeof(**keyblock));
750 if (keyblock == NULL) {
751 ret = ENOMEM;
752 goto out;
753 }
754
755 ret = krb5_ret_keyblock(sp, *keyblock);
756
757 out:
758 gss_release_buffer_set(minor_status, &data_set);
759 if (sp)
760 krb5_storage_free(sp);
761 if (ret && keyblock) {
762 krb5_free_keyblock(context, *keyblock);
763 *keyblock = NULL;
764 }
765 if (context)
766 krb5_free_context(context);
767
768 *minor_status = ret;
769 if (ret)
770 return GSS_S_FAILURE;
771
772 return GSS_S_COMPLETE;
773 }
774
775 /*
776 *
777 */
778
779 OM_uint32 GSSAPI_LIB_FUNCTION
780 gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
781 gss_ctx_id_t context_handle,
782 krb5_keyblock **keyblock)
783 {
784 return gsskrb5_extract_key(minor_status,
785 context_handle,
786 GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
787 keyblock);
788 }
789
790 OM_uint32 GSSAPI_LIB_FUNCTION
791 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
792 gss_ctx_id_t context_handle,
793 krb5_keyblock **keyblock)
794 {
795 return gsskrb5_extract_key(minor_status,
796 context_handle,
797 GSS_KRB5_GET_INITIATOR_SUBKEY_X,
798 keyblock);
799 }
800
801 OM_uint32 GSSAPI_LIB_FUNCTION
802 gsskrb5_get_subkey(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
803 gss_ctx_id_t context_handle,
804 krb5_keyblock **keyblock)
805 {
806 return gsskrb5_extract_key(minor_status,
807 context_handle,
808 GSS_KRB5_GET_SUBKEY_X,
809 keyblock);
810 }
811
812 OM_uint32 GSSAPI_LIB_FUNCTION
813 gsskrb5_set_default_realm(const char *realm)
/* [<][>][^][v][top][bottom][index][help] */
814 {
815 struct _gss_mech_switch *m;
816 gss_buffer_desc buffer;
817 OM_uint32 junk;
818
819 _gss_load_mech();
820
821 buffer.value = rk_UNCONST(realm);
822 buffer.length = strlen(realm);
823
824 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
825 if (m->gm_mech.gm_set_sec_context_option == NULL)
826 continue;
827 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
828 GSS_KRB5_SET_DEFAULT_REALM_X, &buffer);
829 }
830
831 return (GSS_S_COMPLETE);
832 }
833
834 OM_uint32 GSSAPI_LIB_FUNCTION
835 gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
/* [<][>][^][v][top][bottom][index][help] */
836 gss_ctx_id_t context_handle,
837 OM_uint32 *tkt_flags)
838 {
839
840 OM_uint32 major_status;
841 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
842
843 if (context_handle == GSS_C_NO_CONTEXT) {
844 *minor_status = EINVAL;
845 return GSS_S_FAILURE;
846 }
847
848 major_status =
849 gss_inquire_sec_context_by_oid (minor_status,
850 context_handle,
851 GSS_KRB5_GET_TKT_FLAGS_X,
852 &data_set);
853 if (major_status)
854 return major_status;
855
856 if (data_set == GSS_C_NO_BUFFER_SET ||
857 data_set->count != 1 ||
858 data_set->elements[0].length < 4) {
859 gss_release_buffer_set(minor_status, &data_set);
860 *minor_status = EINVAL;
861 return GSS_S_FAILURE;
862 }
863
864 {
865 const u_char *p = data_set->elements[0].value;
866 *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
867 }
868
869 gss_release_buffer_set(minor_status, &data_set);
870 return GSS_S_COMPLETE;
871 }
872
873 OM_uint32 GSSAPI_LIB_FUNCTION
874 gsskrb5_set_time_offset(int offset)
/* [<][>][^][v][top][bottom][index][help] */
875 {
876 struct _gss_mech_switch *m;
877 gss_buffer_desc buffer;
878 OM_uint32 junk;
879 int32_t o = offset;
880
881 _gss_load_mech();
882
883 buffer.value = &o;
884 buffer.length = sizeof(o);
885
886 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
887 if (m->gm_mech.gm_set_sec_context_option == NULL)
888 continue;
889 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
890 GSS_KRB5_SET_TIME_OFFSET_X, &buffer);
891 }
892
893 return (GSS_S_COMPLETE);
894 }
895
896 OM_uint32 GSSAPI_LIB_FUNCTION
897 gsskrb5_get_time_offset(int *offset)
/* [<][>][^][v][top][bottom][index][help] */
898 {
899 struct _gss_mech_switch *m;
900 gss_buffer_desc buffer;
901 OM_uint32 maj_stat, junk;
902 int32_t o;
903
904 _gss_load_mech();
905
906 buffer.value = &o;
907 buffer.length = sizeof(o);
908
909 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
910 if (m->gm_mech.gm_set_sec_context_option == NULL)
911 continue;
912 maj_stat = m->gm_mech.gm_set_sec_context_option(&junk, NULL,
913 GSS_KRB5_GET_TIME_OFFSET_X, &buffer);
914
915 if (maj_stat == GSS_S_COMPLETE) {
916 *offset = o;
917 return maj_stat;
918 }
919 }
920
921 return (GSS_S_UNAVAILABLE);
922 }
923
924 OM_uint32 GSSAPI_LIB_FUNCTION
925 gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *c)
/* [<][>][^][v][top][bottom][index][help] */
926 {
927 struct _gss_mech_switch *m;
928 gss_buffer_desc buffer;
929 OM_uint32 junk;
930
931 _gss_load_mech();
932
933 buffer.value = c;
934 buffer.length = sizeof(*c);
935
936 SLIST_FOREACH(m, &_gss_mechs, gm_link) {
937 if (m->gm_mech.gm_set_sec_context_option == NULL)
938 continue;
939 m->gm_mech.gm_set_sec_context_option(&junk, NULL,
940 GSS_KRB5_PLUGIN_REGISTER_X, &buffer);
941 }
942
943 return (GSS_S_COMPLETE);
944 }