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