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