1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2005 Doug Rabson
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <gssapi/gssapi.h>
30 #include <gssapi/gssapi_krb5.h>
31
32 /* RCSID("$Id: gss_krb5.c 21889 2007-08-09 07:43:24Z lha $"); */
33
34 #include <krb5.h>
35 #include <roken.h>
36 #include <der.h>
37
38 OM_uint32
gss_krb5_copy_ccache(OM_uint32 * minor_status,gss_cred_id_t cred,krb5_ccache out)39 gss_krb5_copy_ccache(OM_uint32 *minor_status,
40 gss_cred_id_t cred,
41 krb5_ccache out)
42 {
43 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
44 krb5_context context;
45 krb5_error_code kret;
46 krb5_ccache id;
47 OM_uint32 ret;
48 char *str;
49
50 ret = gss_inquire_cred_by_oid(minor_status,
51 cred,
52 GSS_KRB5_COPY_CCACHE_X,
53 &data_set);
54 if (ret)
55 return ret;
56
57 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
58 gss_release_buffer_set(minor_status, &data_set);
59 *minor_status = EINVAL;
60 return GSS_S_FAILURE;
61 }
62
63 kret = krb5_init_context(&context);
64 if (kret) {
65 *minor_status = kret;
66 gss_release_buffer_set(minor_status, &data_set);
67 return GSS_S_FAILURE;
68 }
69
70 kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
71 (char *)data_set->elements[0].value);
72 gss_release_buffer_set(minor_status, &data_set);
73 if (kret == -1) {
74 *minor_status = ENOMEM;
75 return GSS_S_FAILURE;
76 }
77
78 kret = krb5_cc_resolve(context, str, &id);
79 free(str);
80 if (kret) {
81 *minor_status = kret;
82 return GSS_S_FAILURE;
83 }
84
85 kret = krb5_cc_copy_cache(context, id, out);
86 krb5_cc_close(context, id);
87 krb5_free_context(context);
88 if (kret) {
89 *minor_status = kret;
90 return GSS_S_FAILURE;
91 }
92
93 return ret;
94 }
95
96 OM_uint32
gss_krb5_import_cred(OM_uint32 * minor_status,krb5_ccache id,krb5_principal keytab_principal,krb5_keytab keytab,gss_cred_id_t * cred)97 gss_krb5_import_cred(OM_uint32 *minor_status,
98 krb5_ccache id,
99 krb5_principal keytab_principal,
100 krb5_keytab keytab,
101 gss_cred_id_t *cred)
102 {
103 gss_buffer_desc buffer;
104 OM_uint32 major_status;
105 krb5_context context;
106 krb5_error_code ret;
107 krb5_storage *sp;
108 krb5_data data;
109 char *str;
110
111 *cred = GSS_C_NO_CREDENTIAL;
112
113 ret = krb5_init_context(&context);
114 if (ret) {
115 *minor_status = ret;
116 return GSS_S_FAILURE;
117 }
118
119 sp = krb5_storage_emem();
120 if (sp == NULL) {
121 *minor_status = ENOMEM;
122 major_status = GSS_S_FAILURE;
123 goto out;
124 }
125
126 if (id) {
127 ret = krb5_cc_get_full_name(context, id, &str);
128 if (ret == 0) {
129 ret = krb5_store_string(sp, str);
130 free(str);
131 }
132 } else
133 ret = krb5_store_string(sp, "");
134 if (ret) {
135 *minor_status = ret;
136 major_status = GSS_S_FAILURE;
137 goto out;
138 }
139
140 if (keytab_principal) {
141 ret = krb5_unparse_name(context, keytab_principal, &str);
142 if (ret == 0) {
143 ret = krb5_store_string(sp, str);
144 free(str);
145 }
146 } else
147 krb5_store_string(sp, "");
148 if (ret) {
149 *minor_status = ret;
150 major_status = GSS_S_FAILURE;
151 goto out;
152 }
153
154
155 if (keytab) {
156 ret = krb5_kt_get_full_name(context, keytab, &str);
157 if (ret == 0) {
158 ret = krb5_store_string(sp, str);
159 free(str);
160 }
161 } else
162 krb5_store_string(sp, "");
163 if (ret) {
164 *minor_status = ret;
165 major_status = GSS_S_FAILURE;
166 goto out;
167 }
168
169 ret = krb5_storage_to_data(sp, &data);
170 if (ret) {
171 *minor_status = ret;
172 major_status = GSS_S_FAILURE;
173 goto out;
174 }
175
176 buffer.value = data.data;
177 buffer.length = data.length;
178
179 major_status = gss_set_cred_option(minor_status,
180 cred,
181 GSS_KRB5_IMPORT_CRED_X,
182 &buffer);
183 krb5_data_free(&data);
184 out:
185 if (sp)
186 krb5_storage_free(sp);
187 krb5_free_context(context);
188 return major_status;
189 }
190
191 OM_uint32
gsskrb5_register_acceptor_identity(const char * identity)192 gsskrb5_register_acceptor_identity(const char *identity)
193 {
194 gss_buffer_desc buffer;
195 OM_uint32 junk;
196
197 buffer.value = rk_UNCONST(identity);
198 buffer.length = strlen(identity);
199
200 gss_set_sec_context_option(&junk, NULL,
201 GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer);
202
203 return (GSS_S_COMPLETE);
204 }
205
206 OM_uint32
gsskrb5_set_dns_canonicalize(int flag)207 gsskrb5_set_dns_canonicalize(int flag)
208 {
209 gss_buffer_desc buffer;
210 OM_uint32 junk;
211 char b = (flag != 0);
212
213 buffer.value = &b;
214 buffer.length = sizeof(b);
215
216 gss_set_sec_context_option(&junk, NULL,
217 GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer);
218
219 return (GSS_S_COMPLETE);
220 }
221
222
223
224 static krb5_error_code
set_key(krb5_keyblock * keyblock,gss_krb5_lucid_key_t * key)225 set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key)
226 {
227 key->type = keyblock->keytype;
228 key->length = keyblock->keyvalue.length;
229 key->data = malloc(key->length);
230 if (key->data == NULL && key->length != 0)
231 return ENOMEM;
232 memcpy(key->data, keyblock->keyvalue.data, key->length);
233 return 0;
234 }
235
236 static void
free_key(gss_krb5_lucid_key_t * key)237 free_key(gss_krb5_lucid_key_t *key)
238 {
239 memset(key->data, 0, key->length);
240 free(key->data);
241 memset(key, 0, sizeof(*key));
242 }
243
244 OM_uint32
gss_krb5_export_lucid_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,OM_uint32 version,void ** rctx)245 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
246 gss_ctx_id_t *context_handle,
247 OM_uint32 version,
248 void **rctx)
249 {
250 krb5_context context = NULL;
251 krb5_error_code ret;
252 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
253 OM_uint32 major_status;
254 gss_krb5_lucid_context_v1_t *ctx = NULL;
255 krb5_storage *sp = NULL;
256 uint32_t num;
257
258 if (context_handle == NULL
259 || *context_handle == GSS_C_NO_CONTEXT
260 || version != 1)
261 {
262 ret = EINVAL;
263 return GSS_S_FAILURE;
264 }
265
266 major_status =
267 gss_inquire_sec_context_by_oid (minor_status,
268 *context_handle,
269 GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X,
270 &data_set);
271 if (major_status)
272 return major_status;
273
274 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
275 gss_release_buffer_set(minor_status, &data_set);
276 *minor_status = EINVAL;
277 return GSS_S_FAILURE;
278 }
279
280 ret = krb5_init_context(&context);
281 if (ret)
282 goto out;
283
284 ctx = calloc(1, sizeof(*ctx));
285 if (ctx == NULL) {
286 ret = ENOMEM;
287 goto out;
288 }
289
290 sp = krb5_storage_from_mem(data_set->elements[0].value,
291 data_set->elements[0].length);
292 if (sp == NULL) {
293 ret = ENOMEM;
294 goto out;
295 }
296
297 ret = krb5_ret_uint32(sp, &num);
298 if (ret) goto out;
299 if (num != 1) {
300 ret = EINVAL;
301 goto out;
302 }
303 ctx->version = 1;
304 /* initiator */
305 ret = krb5_ret_uint32(sp, &ctx->initiate);
306 if (ret) goto out;
307 /* endtime */
308 ret = krb5_ret_uint32(sp, &ctx->endtime);
309 if (ret) goto out;
310 /* send_seq */
311 ret = krb5_ret_uint32(sp, &num);
312 if (ret) goto out;
313 ctx->send_seq = ((uint64_t)num) << 32;
314 ret = krb5_ret_uint32(sp, &num);
315 if (ret) goto out;
316 ctx->send_seq |= num;
317 /* recv_seq */
318 ret = krb5_ret_uint32(sp, &num);
319 if (ret) goto out;
320 ctx->recv_seq = ((uint64_t)num) << 32;
321 ret = krb5_ret_uint32(sp, &num);
322 if (ret) goto out;
323 ctx->recv_seq |= num;
324 /* protocol */
325 ret = krb5_ret_uint32(sp, &ctx->protocol);
326 if (ret) goto out;
327 if (ctx->protocol == 0) {
328 krb5_keyblock key;
329
330 /* sign_alg */
331 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg);
332 if (ret) goto out;
333 /* seal_alg */
334 ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg);
335 if (ret) goto out;
336 /* ctx_key */
337 ret = krb5_ret_keyblock(sp, &key);
338 if (ret) goto out;
339 ret = set_key(&key, &ctx->rfc1964_kd.ctx_key);
340 krb5_free_keyblock_contents(context, &key);
341 if (ret) goto out;
342 } else if (ctx->protocol == 1) {
343 krb5_keyblock key;
344
345 /* acceptor_subkey */
346 ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey);
347 if (ret) goto out;
348 /* ctx_key */
349 ret = krb5_ret_keyblock(sp, &key);
350 if (ret) goto out;
351 ret = set_key(&key, &ctx->cfx_kd.ctx_key);
352 krb5_free_keyblock_contents(context, &key);
353 if (ret) goto out;
354 /* acceptor_subkey */
355 if (ctx->cfx_kd.have_acceptor_subkey) {
356 ret = krb5_ret_keyblock(sp, &key);
357 if (ret) goto out;
358 ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey);
359 krb5_free_keyblock_contents(context, &key);
360 if (ret) goto out;
361 }
362 } else {
363 ret = EINVAL;
364 goto out;
365 }
366
367 *rctx = ctx;
368
369 out:
370 gss_release_buffer_set(minor_status, &data_set);
371 if (sp)
372 krb5_storage_free(sp);
373 if (context)
374 krb5_free_context(context);
375
376 if (ret) {
377 if (ctx)
378 gss_krb5_free_lucid_sec_context(NULL, ctx);
379
380 *minor_status = ret;
381 return GSS_S_FAILURE;
382 }
383 *minor_status = 0;
384 return GSS_S_COMPLETE;
385 }
386
387 OM_uint32
gss_krb5_free_lucid_sec_context(OM_uint32 * minor_status,void * c)388 gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
389 {
390 gss_krb5_lucid_context_v1_t *ctx = c;
391
392 if (ctx->version != 1) {
393 if (minor_status)
394 *minor_status = 0;
395 return GSS_S_FAILURE;
396 }
397
398 if (ctx->protocol == 0) {
399 free_key(&ctx->rfc1964_kd.ctx_key);
400 } else if (ctx->protocol == 1) {
401 free_key(&ctx->cfx_kd.ctx_key);
402 if (ctx->cfx_kd.have_acceptor_subkey)
403 free_key(&ctx->cfx_kd.acceptor_subkey);
404 }
405 free(ctx);
406 if (minor_status)
407 *minor_status = 0;
408 return GSS_S_COMPLETE;
409 }
410
411 /*
412 *
413 */
414
415 OM_uint32
gss_krb5_set_allowable_enctypes(OM_uint32 * minor_status,gss_cred_id_t cred,OM_uint32 num_enctypes,int32_t * enctypes)416 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
417 gss_cred_id_t cred,
418 OM_uint32 num_enctypes,
419 int32_t *enctypes)
420 {
421 krb5_error_code ret;
422 OM_uint32 maj_status;
423 gss_buffer_desc buffer;
424 krb5_storage *sp;
425 krb5_data data;
426 int i;
427
428 sp = krb5_storage_emem();
429 if (sp == NULL) {
430 *minor_status = ENOMEM;
431 maj_status = GSS_S_FAILURE;
432 goto out;
433 }
434
435 for (i = 0; i < num_enctypes; i++) {
436 ret = krb5_store_int32(sp, enctypes[i]);
437 if (ret) {
438 *minor_status = ret;
439 maj_status = GSS_S_FAILURE;
440 goto out;
441 }
442 }
443
444 ret = krb5_storage_to_data(sp, &data);
445 if (ret) {
446 *minor_status = ret;
447 maj_status = GSS_S_FAILURE;
448 goto out;
449 }
450
451 buffer.value = data.data;
452 buffer.length = data.length;
453
454 maj_status = gss_set_cred_option(minor_status,
455 &cred,
456 GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
457 &buffer);
458 krb5_data_free(&data);
459 out:
460 if (sp)
461 krb5_storage_free(sp);
462 return maj_status;
463 }
464
465 /*
466 *
467 */
468
469 OM_uint32
gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc * c)470 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
471 {
472 gss_buffer_desc buffer;
473 OM_uint32 junk;
474
475 if (c) {
476 buffer.value = c;
477 buffer.length = sizeof(*c);
478 } else {
479 buffer.value = NULL;
480 buffer.length = 0;
481 }
482
483 gss_set_sec_context_option(&junk, NULL,
484 GSS_KRB5_SEND_TO_KDC_X, &buffer);
485
486 return (GSS_S_COMPLETE);
487 }
488
489 /*
490 *
491 */
492
493 OM_uint32
gss_krb5_ccache_name(OM_uint32 * minor_status,const char * name,const char ** out_name)494 gss_krb5_ccache_name(OM_uint32 *minor_status,
495 const char *name,
496 const char **out_name)
497 {
498 gss_buffer_desc buffer;
499 OM_uint32 junk;
500
501 if (out_name)
502 *out_name = NULL;
503
504 buffer.value = rk_UNCONST(name);
505 buffer.length = strlen(name);
506
507 gss_set_sec_context_option(&junk, NULL,
508 GSS_KRB5_CCACHE_NAME_X, &buffer);
509
510 return (GSS_S_COMPLETE);
511 }
512
513
514 /*
515 *
516 */
517
518 OM_uint32
gsskrb5_extract_authtime_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,time_t * authtime)519 gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
520 gss_ctx_id_t context_handle,
521 time_t *authtime)
522 {
523 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
524 OM_uint32 maj_stat;
525
526 if (context_handle == GSS_C_NO_CONTEXT) {
527 *minor_status = EINVAL;
528 return GSS_S_FAILURE;
529 }
530
531 maj_stat =
532 gss_inquire_sec_context_by_oid (minor_status,
533 context_handle,
534 GSS_KRB5_GET_AUTHTIME_X,
535 &data_set);
536 if (maj_stat)
537 return maj_stat;
538
539 if (data_set == GSS_C_NO_BUFFER_SET) {
540 gss_release_buffer_set(minor_status, &data_set);
541 *minor_status = EINVAL;
542 return GSS_S_FAILURE;
543 }
544
545 if (data_set->count != 1) {
546 gss_release_buffer_set(minor_status, &data_set);
547 *minor_status = EINVAL;
548 return GSS_S_FAILURE;
549 }
550
551 if (data_set->elements[0].length != 4) {
552 gss_release_buffer_set(minor_status, &data_set);
553 *minor_status = EINVAL;
554 return GSS_S_FAILURE;
555 }
556
557 {
558 unsigned char *buf = data_set->elements[0].value;
559 *authtime = (buf[3] <<24) | (buf[2] << 16) |
560 (buf[1] << 8) | (buf[0] << 0);
561 }
562
563 gss_release_buffer_set(minor_status, &data_set);
564
565 *minor_status = 0;
566 return GSS_S_COMPLETE;
567 }
568
569 /*
570 *
571 */
572
573 OM_uint32
gsskrb5_extract_authz_data_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int ad_type,gss_buffer_t ad_data)574 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
575 gss_ctx_id_t context_handle,
576 int ad_type,
577 gss_buffer_t ad_data)
578 {
579 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
580 OM_uint32 maj_stat;
581 gss_OID_desc oid_flat;
582 heim_oid baseoid, oid;
583 size_t size;
584
585 if (context_handle == GSS_C_NO_CONTEXT) {
586 *minor_status = EINVAL;
587 return GSS_S_FAILURE;
588 }
589
590 /* All this to append an integer to an oid... */
591
592 if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
593 GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
594 &baseoid, NULL) != 0) {
595 *minor_status = EINVAL;
596 return GSS_S_FAILURE;
597 }
598
599 oid.length = baseoid.length + 1;
600 oid.components = calloc(oid.length, sizeof(*oid.components));
601 if (oid.components == NULL) {
602 der_free_oid(&baseoid);
603
604 *minor_status = ENOMEM;
605 return GSS_S_FAILURE;
606 }
607
608 memcpy(oid.components, baseoid.components,
609 baseoid.length * sizeof(*baseoid.components));
610
611 der_free_oid(&baseoid);
612
613 oid.components[oid.length - 1] = ad_type;
614
615 oid_flat.length = der_length_oid(&oid);
616 oid_flat.elements = malloc(oid_flat.length);
617 if (oid_flat.elements == NULL) {
618 free(oid.components);
619 *minor_status = ENOMEM;
620 return GSS_S_FAILURE;
621 }
622
623 if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
624 oid_flat.length, &oid, &size) != 0) {
625 free(oid.components);
626 free(oid_flat.elements);
627 *minor_status = EINVAL;
628 return GSS_S_FAILURE;
629 }
630 if (oid_flat.length != size)
631 abort();
632
633 free(oid.components);
634
635 /* FINALLY, we have the OID */
636
637 maj_stat = gss_inquire_sec_context_by_oid (minor_status,
638 context_handle,
639 &oid_flat,
640 &data_set);
641
642 free(oid_flat.elements);
643
644 if (maj_stat)
645 return maj_stat;
646
647 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
648 gss_release_buffer_set(minor_status, &data_set);
649 *minor_status = EINVAL;
650 return GSS_S_FAILURE;
651 }
652
653 ad_data->value = malloc(data_set->elements[0].length);
654 if (ad_data->value == NULL) {
655 gss_release_buffer_set(minor_status, &data_set);
656 *minor_status = ENOMEM;
657 return GSS_S_FAILURE;
658 }
659
660 ad_data->length = data_set->elements[0].length;
661 memcpy(ad_data->value, data_set->elements[0].value, ad_data->length);
662 gss_release_buffer_set(minor_status, &data_set);
663
664 *minor_status = 0;
665 return GSS_S_COMPLETE;
666 }
667
668 /*
669 *
670 */
671
672 static OM_uint32
gsskrb5_extract_key(OM_uint32 * minor_status,gss_ctx_id_t context_handle,const gss_OID oid,krb5_keyblock ** keyblock)673 gsskrb5_extract_key(OM_uint32 *minor_status,
674 gss_ctx_id_t context_handle,
675 const gss_OID oid,
676 krb5_keyblock **keyblock)
677 {
678 krb5_error_code ret;
679 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
680 OM_uint32 major_status;
681 krb5_context context = NULL;
682 krb5_storage *sp = NULL;
683
684 if (context_handle == GSS_C_NO_CONTEXT) {
685 ret = EINVAL;
686 return GSS_S_FAILURE;
687 }
688
689 ret = krb5_init_context(&context);
690 if(ret) {
691 *minor_status = ret;
692 return GSS_S_FAILURE;
693 }
694
695 major_status =
696 gss_inquire_sec_context_by_oid (minor_status,
697 context_handle,
698 oid,
699 &data_set);
700 if (major_status)
701 return major_status;
702
703 if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
704 gss_release_buffer_set(minor_status, &data_set);
705 *minor_status = EINVAL;
706 return GSS_S_FAILURE;
707 }
708
709 sp = krb5_storage_from_mem(data_set->elements[0].value,
710 data_set->elements[0].length);
711 if (sp == NULL) {
712 ret = ENOMEM;
713 goto out;
714 }
715
716 *keyblock = calloc(1, sizeof(**keyblock));
717 if (keyblock == NULL) {
718 ret = ENOMEM;
719 goto out;
720 }
721
722 ret = krb5_ret_keyblock(sp, *keyblock);
723
724 out:
725 gss_release_buffer_set(minor_status, &data_set);
726 if (sp)
727 krb5_storage_free(sp);
728 if (ret && keyblock) {
729 krb5_free_keyblock(context, *keyblock);
730 *keyblock = NULL;
731 }
732 if (context)
733 krb5_free_context(context);
734
735 *minor_status = ret;
736 if (ret)
737 return GSS_S_FAILURE;
738
739 return GSS_S_COMPLETE;
740 }
741
742 /*
743 *
744 */
745
746 OM_uint32
gsskrb5_extract_service_keyblock(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)747 gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
748 gss_ctx_id_t context_handle,
749 krb5_keyblock **keyblock)
750 {
751 return gsskrb5_extract_key(minor_status,
752 context_handle,
753 GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
754 keyblock);
755 }
756
757 OM_uint32
gsskrb5_get_initiator_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)758 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
759 gss_ctx_id_t context_handle,
760 krb5_keyblock **keyblock)
761 {
762 return gsskrb5_extract_key(minor_status,
763 context_handle,
764 GSS_KRB5_GET_INITIATOR_SUBKEY_X,
765 keyblock);
766 }
767
768 OM_uint32
gsskrb5_get_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)769 gsskrb5_get_subkey(OM_uint32 *minor_status,
770 gss_ctx_id_t context_handle,
771 krb5_keyblock **keyblock)
772 {
773 return gsskrb5_extract_key(minor_status,
774 context_handle,
775 GSS_KRB5_GET_SUBKEY_X,
776 keyblock);
777 }
778
779 OM_uint32
gsskrb5_set_default_realm(const char * realm)780 gsskrb5_set_default_realm(const char *realm)
781 {
782 gss_buffer_desc buffer;
783 OM_uint32 junk;
784
785 buffer.value = rk_UNCONST(realm);
786 buffer.length = strlen(realm);
787
788 gss_set_sec_context_option(&junk, NULL,
789 GSS_KRB5_SET_DEFAULT_REALM_X, &buffer);
790
791 return (GSS_S_COMPLETE);
792 }
793
794 OM_uint32
gss_krb5_get_tkt_flags(OM_uint32 * minor_status,gss_ctx_id_t context_handle,OM_uint32 * tkt_flags)795 gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
796 gss_ctx_id_t context_handle,
797 OM_uint32 *tkt_flags)
798 {
799
800 OM_uint32 major_status;
801 gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
802
803 if (context_handle == GSS_C_NO_CONTEXT) {
804 *minor_status = EINVAL;
805 return GSS_S_FAILURE;
806 }
807
808 major_status =
809 gss_inquire_sec_context_by_oid (minor_status,
810 context_handle,
811 GSS_KRB5_GET_TKT_FLAGS_X,
812 &data_set);
813 if (major_status)
814 return major_status;
815
816 if (data_set == GSS_C_NO_BUFFER_SET ||
817 data_set->count != 1 ||
818 data_set->elements[0].length < 4) {
819 gss_release_buffer_set(minor_status, &data_set);
820 *minor_status = EINVAL;
821 return GSS_S_FAILURE;
822 }
823
824 {
825 const u_char *p = data_set->elements[0].value;
826 *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
827 }
828
829 gss_release_buffer_set(minor_status, &data_set);
830 return GSS_S_COMPLETE;
831 }
832
833