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 65124 : gss_krb5_copy_ccache(OM_uint32 *minor_status,
34 : gss_cred_id_t cred,
35 : krb5_ccache out)
36 : {
37 : gss_key_value_element_desc cred_store_kvs[1];
38 : gss_key_value_set_desc cred_store;
39 : krb5_context context;
40 65124 : OM_uint32 major = GSS_S_FAILURE;
41 65124 : char *fullname = NULL;
42 :
43 65124 : GSSAPI_KRB5_INIT(&context);
44 65124 : *minor_status = krb5_cc_get_full_name(context, out, &fullname);
45 65124 : if (*minor_status == 0) {
46 65124 : cred_store_kvs[0].key = "ccache";
47 65124 : cred_store_kvs[0].value = fullname;
48 65124 : cred_store.count = 1;
49 65124 : cred_store.elements = cred_store_kvs;
50 65124 : 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 65124 : free(fullname);
55 : }
56 65124 : return major;
57 : }
58 :
59 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
60 60037 : 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 : gss_buffer_desc buffer;
67 : OM_uint32 major_status;
68 : krb5_context context;
69 : krb5_error_code ret;
70 : krb5_storage *sp;
71 : krb5_data data;
72 : char *str;
73 :
74 60037 : *cred = GSS_C_NO_CREDENTIAL;
75 :
76 60037 : ret = krb5_init_context(&context);
77 60037 : if (ret) {
78 0 : *minor_status = ret;
79 0 : return GSS_S_FAILURE;
80 : }
81 :
82 60037 : sp = krb5_storage_emem();
83 60037 : if (sp == NULL) {
84 0 : *minor_status = ENOMEM;
85 0 : major_status = GSS_S_FAILURE;
86 0 : goto out;
87 : }
88 :
89 60037 : if (id) {
90 9828 : ret = krb5_cc_get_full_name(context, id, &str);
91 9828 : if (ret == 0) {
92 9828 : ret = krb5_store_string(sp, str);
93 9828 : free(str);
94 : }
95 : } else
96 50209 : ret = krb5_store_string(sp, "");
97 60037 : if (ret) {
98 0 : *minor_status = ret;
99 0 : major_status = GSS_S_FAILURE;
100 0 : goto out;
101 : }
102 :
103 60037 : if (keytab_principal) {
104 48802 : ret = krb5_unparse_name(context, keytab_principal, &str);
105 48802 : if (ret == 0) {
106 48802 : ret = krb5_store_string(sp, str);
107 48802 : free(str);
108 : }
109 : } else
110 11235 : krb5_store_string(sp, "");
111 60037 : if (ret) {
112 0 : *minor_status = ret;
113 0 : major_status = GSS_S_FAILURE;
114 0 : goto out;
115 : }
116 :
117 :
118 60037 : if (keytab) {
119 50209 : ret = krb5_kt_get_full_name(context, keytab, &str);
120 50209 : if (ret == 0) {
121 50209 : ret = krb5_store_string(sp, str);
122 50209 : free(str);
123 : }
124 : } else
125 9828 : krb5_store_string(sp, "");
126 60037 : if (ret) {
127 0 : *minor_status = ret;
128 0 : major_status = GSS_S_FAILURE;
129 0 : goto out;
130 : }
131 :
132 60037 : ret = krb5_storage_to_data(sp, &data);
133 60037 : if (ret) {
134 0 : *minor_status = ret;
135 0 : major_status = GSS_S_FAILURE;
136 0 : goto out;
137 : }
138 :
139 60037 : buffer.value = data.data;
140 60037 : buffer.length = data.length;
141 :
142 60037 : major_status = gss_set_cred_option(minor_status,
143 : cred,
144 : GSS_KRB5_IMPORT_CRED_X,
145 : &buffer);
146 60037 : krb5_data_free(&data);
147 60037 : out:
148 60037 : if (sp)
149 60037 : krb5_storage_free(sp);
150 60037 : krb5_free_context(context);
151 60037 : 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 : gssapi_mech_interface m;
158 : gss_buffer_desc buffer;
159 : 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 72635 : gsskrb5_set_dns_canonicalize(int flag)
183 : {
184 : struct _gss_mech_switch *m;
185 : gss_buffer_desc buffer;
186 : OM_uint32 junk;
187 72635 : char b = (flag != 0);
188 :
189 72635 : _gss_load_mech();
190 :
191 72635 : buffer.value = &b;
192 72635 : buffer.length = sizeof(b);
193 :
194 217905 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
195 145270 : if (m->gm_mech.gm_set_sec_context_option == NULL)
196 0 : continue;
197 145270 : m->gm_mech.gm_set_sec_context_option(&junk, NULL,
198 : GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer);
199 : }
200 :
201 72635 : 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 : krb5_error_code ret;
234 0 : gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
235 : OM_uint32 major_status;
236 0 : gss_krb5_lucid_context_v1_t *ctx = NULL;
237 0 : krb5_storage *sp = NULL;
238 : 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 : 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 : 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 : 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 8588 : 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 : krb5_error_code ret;
405 : OM_uint32 maj_status;
406 : gss_buffer_desc buffer;
407 : krb5_storage *sp;
408 : krb5_data data;
409 : size_t i;
410 :
411 8588 : sp = krb5_storage_emem();
412 8588 : if (sp == NULL) {
413 0 : *minor_status = ENOMEM;
414 0 : maj_status = GSS_S_FAILURE;
415 0 : goto out;
416 : }
417 :
418 58746 : for (i = 0; i < num_enctypes; i++) {
419 50158 : ret = krb5_store_int32(sp, enctypes[i]);
420 50158 : if (ret) {
421 0 : *minor_status = ret;
422 0 : maj_status = GSS_S_FAILURE;
423 0 : goto out;
424 : }
425 : }
426 :
427 8588 : ret = krb5_storage_to_data(sp, &data);
428 8588 : if (ret) {
429 0 : *minor_status = ret;
430 0 : maj_status = GSS_S_FAILURE;
431 0 : goto out;
432 : }
433 :
434 8588 : buffer.value = data.data;
435 8588 : buffer.length = data.length;
436 :
437 8588 : maj_status = gss_set_cred_option(minor_status,
438 : &cred,
439 : GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
440 : &buffer);
441 8588 : krb5_data_free(&data);
442 8588 : out:
443 8588 : if (sp)
444 8588 : krb5_storage_free(sp);
445 8588 : return maj_status;
446 : }
447 :
448 : /*
449 : *
450 : */
451 :
452 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
453 68186 : gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
454 : {
455 : struct _gss_mech_switch *m;
456 : gss_buffer_desc buffer;
457 : OM_uint32 junk;
458 :
459 68186 : _gss_load_mech();
460 :
461 68186 : if (c) {
462 68186 : buffer.value = c;
463 68186 : buffer.length = sizeof(*c);
464 : } else {
465 0 : buffer.value = NULL;
466 0 : buffer.length = 0;
467 : }
468 :
469 204558 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
470 136372 : if (m->gm_mech.gm_set_sec_context_option == NULL)
471 0 : continue;
472 136372 : m->gm_mech.gm_set_sec_context_option(&junk, NULL,
473 : GSS_KRB5_SEND_TO_KDC_X, &buffer);
474 : }
475 :
476 68186 : 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 : struct _gss_mech_switch *m;
489 0 : gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
490 : OM_uint32 major_status;
491 : 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 : 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 : 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 : 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 != 4) {
568 0 : gss_release_buffer_set(minor_status, &data_set);
569 0 : *minor_status = EINVAL;
570 0 : return GSS_S_FAILURE;
571 : }
572 :
573 : {
574 0 : unsigned char *buf = data_set->elements[0].value;
575 0 : *authtime = ((unsigned long)buf[3] <<24) | (buf[2] << 16) |
576 0 : (buf[1] << 8) | (buf[0] << 0);
577 : }
578 :
579 0 : gss_release_buffer_set(minor_status, &data_set);
580 :
581 0 : *minor_status = 0;
582 0 : return GSS_S_COMPLETE;
583 : }
584 :
585 : /*
586 : *
587 : */
588 :
589 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
590 0 : gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
591 : gss_ctx_id_t context_handle,
592 : int ad_type,
593 : gss_buffer_t ad_data)
594 : {
595 0 : gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
596 : OM_uint32 maj_stat, tmp;
597 : gss_OID_desc oid_flat;
598 : heim_oid baseoid, oid;
599 : size_t size;
600 :
601 0 : if (context_handle == GSS_C_NO_CONTEXT) {
602 0 : *minor_status = EINVAL;
603 0 : return GSS_S_FAILURE;
604 : }
605 :
606 : /* All this to append an integer to an oid... */
607 :
608 0 : if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
609 0 : GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
610 : &baseoid, NULL) != 0) {
611 0 : *minor_status = EINVAL;
612 0 : return GSS_S_FAILURE;
613 : }
614 :
615 0 : oid.length = baseoid.length + 1;
616 0 : oid.components = calloc(oid.length, sizeof(*oid.components));
617 0 : if (oid.components == NULL) {
618 0 : der_free_oid(&baseoid);
619 :
620 0 : *minor_status = ENOMEM;
621 0 : return GSS_S_FAILURE;
622 : }
623 :
624 0 : memcpy(oid.components, baseoid.components,
625 0 : baseoid.length * sizeof(*baseoid.components));
626 :
627 0 : der_free_oid(&baseoid);
628 :
629 0 : oid.components[oid.length - 1] = ad_type;
630 :
631 0 : oid_flat.length = (OM_uint32)der_length_oid(&oid);
632 0 : oid_flat.elements = malloc(oid_flat.length);
633 0 : if (oid_flat.elements == NULL) {
634 0 : free(oid.components);
635 0 : *minor_status = ENOMEM;
636 0 : return GSS_S_FAILURE;
637 : }
638 :
639 0 : if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
640 0 : oid_flat.length, &oid, &size) != 0) {
641 0 : free(oid.components);
642 0 : _gss_free_oid(&tmp, &oid_flat);
643 0 : *minor_status = EINVAL;
644 0 : return GSS_S_FAILURE;
645 : }
646 0 : if (oid_flat.length != size)
647 0 : abort();
648 :
649 0 : free(oid.components);
650 :
651 : /* FINALLY, we have the OID */
652 :
653 0 : maj_stat = gss_inquire_sec_context_by_oid (minor_status,
654 : context_handle,
655 : &oid_flat,
656 : &data_set);
657 :
658 0 : _gss_free_oid(&tmp, &oid_flat);
659 :
660 0 : if (maj_stat)
661 0 : return maj_stat;
662 :
663 0 : if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
664 0 : gss_release_buffer_set(minor_status, &data_set);
665 0 : *minor_status = EINVAL;
666 0 : return GSS_S_FAILURE;
667 : }
668 :
669 0 : ad_data->value = malloc(data_set->elements[0].length);
670 0 : if (ad_data->value == NULL) {
671 0 : gss_release_buffer_set(minor_status, &data_set);
672 0 : *minor_status = ENOMEM;
673 0 : return GSS_S_FAILURE;
674 : }
675 :
676 0 : ad_data->length = data_set->elements[0].length;
677 0 : memcpy(ad_data->value, data_set->elements[0].value, ad_data->length);
678 0 : gss_release_buffer_set(minor_status, &data_set);
679 :
680 0 : *minor_status = 0;
681 0 : return GSS_S_COMPLETE;
682 : }
683 :
684 : /*
685 : *
686 : */
687 :
688 : static OM_uint32
689 64218 : gsskrb5_extract_key(OM_uint32 *minor_status,
690 : gss_ctx_id_t context_handle,
691 : const gss_OID oid,
692 : krb5_keyblock **keyblock)
693 : {
694 : krb5_error_code ret;
695 64218 : gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
696 : OM_uint32 major_status;
697 64218 : krb5_context context = NULL;
698 64218 : krb5_storage *sp = NULL;
699 :
700 64218 : if (context_handle == GSS_C_NO_CONTEXT) {
701 0 : *minor_status = EINVAL;
702 0 : return GSS_S_FAILURE;
703 : }
704 :
705 64218 : ret = krb5_init_context(&context);
706 64218 : if(ret) {
707 0 : *minor_status = ret;
708 0 : return GSS_S_FAILURE;
709 : }
710 :
711 64218 : major_status =
712 : gss_inquire_sec_context_by_oid (minor_status,
713 : context_handle,
714 : oid,
715 : &data_set);
716 64218 : if (major_status)
717 0 : return major_status;
718 :
719 64218 : if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
720 0 : _gss_secure_release_buffer_set(minor_status, &data_set);
721 0 : *minor_status = EINVAL;
722 0 : return GSS_S_FAILURE;
723 : }
724 :
725 64218 : sp = krb5_storage_from_mem(data_set->elements[0].value,
726 64218 : data_set->elements[0].length);
727 64218 : if (sp == NULL) {
728 0 : ret = ENOMEM;
729 0 : goto out;
730 : }
731 :
732 64218 : *keyblock = calloc(1, sizeof(**keyblock));
733 64218 : if (*keyblock == NULL) {
734 0 : ret = ENOMEM;
735 0 : goto out;
736 : }
737 :
738 64218 : ret = krb5_ret_keyblock(sp, *keyblock);
739 :
740 64218 : out:
741 64218 : _gss_secure_release_buffer_set(minor_status, &data_set);
742 64218 : if (sp)
743 64218 : krb5_storage_free(sp);
744 64218 : if (ret && keyblock) {
745 0 : krb5_free_keyblock(context, *keyblock);
746 0 : *keyblock = NULL;
747 : }
748 64218 : if (context)
749 64218 : krb5_free_context(context);
750 :
751 64218 : *minor_status = ret;
752 64218 : if (ret)
753 0 : return GSS_S_FAILURE;
754 :
755 64218 : return GSS_S_COMPLETE;
756 : }
757 :
758 : /*
759 : *
760 : */
761 :
762 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
763 0 : gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
764 : gss_ctx_id_t context_handle,
765 : krb5_keyblock **keyblock)
766 : {
767 0 : return gsskrb5_extract_key(minor_status,
768 : context_handle,
769 : GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
770 : keyblock);
771 : }
772 :
773 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
774 0 : gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
775 : gss_ctx_id_t context_handle,
776 : krb5_keyblock **keyblock)
777 : {
778 0 : return gsskrb5_extract_key(minor_status,
779 : context_handle,
780 : GSS_KRB5_GET_INITIATOR_SUBKEY_X,
781 : keyblock);
782 : }
783 :
784 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
785 64218 : gsskrb5_get_subkey(OM_uint32 *minor_status,
786 : gss_ctx_id_t context_handle,
787 : krb5_keyblock **keyblock)
788 : {
789 64218 : return gsskrb5_extract_key(minor_status,
790 : context_handle,
791 : GSS_KRB5_GET_SUBKEY_X,
792 : keyblock);
793 : }
794 :
795 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
796 70031 : gsskrb5_set_default_realm(const char *realm)
797 : {
798 : struct _gss_mech_switch *m;
799 : gss_buffer_desc buffer;
800 : OM_uint32 junk;
801 :
802 70031 : _gss_load_mech();
803 :
804 70031 : buffer.value = rk_UNCONST(realm);
805 70031 : buffer.length = strlen(realm);
806 :
807 210093 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
808 140062 : if (m->gm_mech.gm_set_sec_context_option == NULL)
809 0 : continue;
810 140062 : m->gm_mech.gm_set_sec_context_option(&junk, NULL,
811 : GSS_KRB5_SET_DEFAULT_REALM_X, &buffer);
812 : }
813 :
814 70031 : return (GSS_S_COMPLETE);
815 : }
816 :
817 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
818 0 : gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
819 : gss_ctx_id_t context_handle,
820 : OM_uint32 *tkt_flags)
821 : {
822 :
823 : OM_uint32 major_status;
824 0 : gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
825 :
826 0 : if (context_handle == GSS_C_NO_CONTEXT) {
827 0 : *minor_status = EINVAL;
828 0 : return GSS_S_FAILURE;
829 : }
830 :
831 0 : major_status =
832 : gss_inquire_sec_context_by_oid (minor_status,
833 : context_handle,
834 : GSS_KRB5_GET_TKT_FLAGS_X,
835 : &data_set);
836 0 : if (major_status)
837 0 : return major_status;
838 :
839 0 : if (data_set == GSS_C_NO_BUFFER_SET ||
840 0 : data_set->count != 1 ||
841 0 : data_set->elements[0].length < 4) {
842 0 : gss_release_buffer_set(minor_status, &data_set);
843 0 : *minor_status = EINVAL;
844 0 : return GSS_S_FAILURE;
845 : }
846 :
847 : {
848 0 : const u_char *p = data_set->elements[0].value;
849 0 : *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
850 : }
851 :
852 0 : gss_release_buffer_set(minor_status, &data_set);
853 0 : return GSS_S_COMPLETE;
854 : }
855 :
856 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
857 0 : gsskrb5_set_time_offset(int offset)
858 : {
859 : struct _gss_mech_switch *m;
860 : gss_buffer_desc buffer;
861 : OM_uint32 junk;
862 0 : int32_t o = offset;
863 :
864 0 : _gss_load_mech();
865 :
866 0 : buffer.value = &o;
867 0 : buffer.length = sizeof(o);
868 :
869 0 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
870 0 : if (m->gm_mech.gm_set_sec_context_option == NULL)
871 0 : continue;
872 0 : m->gm_mech.gm_set_sec_context_option(&junk, NULL,
873 : GSS_KRB5_SET_TIME_OFFSET_X, &buffer);
874 : }
875 :
876 0 : return (GSS_S_COMPLETE);
877 : }
878 :
879 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
880 0 : gsskrb5_get_time_offset(int *offset)
881 : {
882 : struct _gss_mech_switch *m;
883 : gss_buffer_desc buffer;
884 : OM_uint32 maj_stat, junk;
885 : int32_t o;
886 :
887 0 : _gss_load_mech();
888 :
889 0 : buffer.value = &o;
890 0 : buffer.length = sizeof(o);
891 :
892 0 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
893 0 : if (m->gm_mech.gm_set_sec_context_option == NULL)
894 0 : continue;
895 0 : maj_stat = m->gm_mech.gm_set_sec_context_option(&junk, NULL,
896 : GSS_KRB5_GET_TIME_OFFSET_X, &buffer);
897 :
898 0 : if (maj_stat == GSS_S_COMPLETE) {
899 0 : *offset = o;
900 0 : return maj_stat;
901 : }
902 : }
903 :
904 0 : return (GSS_S_UNAVAILABLE);
905 : }
906 :
907 : GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
908 0 : gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *c)
909 : {
910 : struct _gss_mech_switch *m;
911 : gss_buffer_desc buffer;
912 : OM_uint32 junk;
913 :
914 0 : _gss_load_mech();
915 :
916 0 : buffer.value = c;
917 0 : buffer.length = sizeof(*c);
918 :
919 0 : HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
920 0 : if (m->gm_mech.gm_set_sec_context_option == NULL)
921 0 : continue;
922 0 : m->gm_mech.gm_set_sec_context_option(&junk, NULL,
923 : GSS_KRB5_PLUGIN_REGISTER_X, &buffer);
924 : }
925 :
926 0 : return (GSS_S_COMPLETE);
927 : }
|