Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/gssapi/krb5/accept_sec_context.c
34923 views
1
/*
2
* Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
20
*
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
* SUCH DAMAGE.
32
*/
33
34
#include "gsskrb5_locl.h"
35
36
HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
37
krb5_keytab _gsskrb5_keytab;
38
39
static krb5_error_code
40
validate_keytab(krb5_context context, const char *name, krb5_keytab *id)
41
{
42
krb5_error_code ret;
43
44
ret = krb5_kt_resolve(context, name, id);
45
if (ret)
46
return ret;
47
48
ret = krb5_kt_have_content(context, *id);
49
if (ret) {
50
krb5_kt_close(context, *id);
51
*id = NULL;
52
}
53
54
return ret;
55
}
56
57
OM_uint32
58
_gsskrb5_register_acceptor_identity(OM_uint32 *min_stat, const char *identity)
59
{
60
krb5_context context;
61
krb5_error_code ret;
62
63
*min_stat = 0;
64
65
ret = _gsskrb5_init(&context);
66
if(ret)
67
return GSS_S_FAILURE;
68
69
HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
70
71
if(_gsskrb5_keytab != NULL) {
72
krb5_kt_close(context, _gsskrb5_keytab);
73
_gsskrb5_keytab = NULL;
74
}
75
if (identity == NULL) {
76
ret = krb5_kt_default(context, &_gsskrb5_keytab);
77
} else {
78
/*
79
* First check if we can the keytab as is and if it has content...
80
*/
81
ret = validate_keytab(context, identity, &_gsskrb5_keytab);
82
/*
83
* if it doesn't, lets prepend FILE: and try again
84
*/
85
if (ret) {
86
char *p = NULL;
87
ret = asprintf(&p, "FILE:%s", identity);
88
if(ret < 0 || p == NULL) {
89
HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
90
return GSS_S_FAILURE;
91
}
92
ret = validate_keytab(context, p, &_gsskrb5_keytab);
93
free(p);
94
}
95
}
96
HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
97
if(ret) {
98
*min_stat = ret;
99
return GSS_S_FAILURE;
100
}
101
return GSS_S_COMPLETE;
102
}
103
104
void
105
_gsskrb5i_is_cfx(krb5_context context, gsskrb5_ctx ctx, int acceptor)
106
{
107
krb5_error_code ret;
108
krb5_keyblock *key;
109
110
if (acceptor) {
111
if (ctx->auth_context->local_subkey)
112
key = ctx->auth_context->local_subkey;
113
else
114
key = ctx->auth_context->remote_subkey;
115
} else {
116
if (ctx->auth_context->remote_subkey)
117
key = ctx->auth_context->remote_subkey;
118
else
119
key = ctx->auth_context->local_subkey;
120
}
121
if (key == NULL)
122
key = ctx->auth_context->keyblock;
123
124
if (key == NULL)
125
return;
126
127
switch (key->keytype) {
128
case ETYPE_DES_CBC_CRC:
129
case ETYPE_DES_CBC_MD4:
130
case ETYPE_DES_CBC_MD5:
131
case ETYPE_DES3_CBC_MD5:
132
case ETYPE_OLD_DES3_CBC_SHA1:
133
case ETYPE_DES3_CBC_SHA1:
134
case ETYPE_ARCFOUR_HMAC_MD5:
135
case ETYPE_ARCFOUR_HMAC_MD5_56:
136
break;
137
default :
138
ctx->more_flags |= IS_CFX;
139
140
if ((acceptor && ctx->auth_context->local_subkey) ||
141
(!acceptor && ctx->auth_context->remote_subkey))
142
ctx->more_flags |= ACCEPTOR_SUBKEY;
143
break;
144
}
145
if (ctx->crypto)
146
krb5_crypto_destroy(context, ctx->crypto);
147
ret = krb5_crypto_init(context, key, 0, &ctx->crypto);
148
}
149
150
151
static OM_uint32
152
gsskrb5_accept_delegated_token
153
(OM_uint32 * minor_status,
154
gsskrb5_ctx ctx,
155
krb5_context context,
156
gss_cred_id_t * delegated_cred_handle
157
)
158
{
159
krb5_ccache ccache = NULL;
160
krb5_error_code kret;
161
int32_t ac_flags, ret = GSS_S_COMPLETE;
162
163
*minor_status = 0;
164
165
/* XXX Create a new delegated_cred_handle? */
166
if (delegated_cred_handle == NULL) {
167
kret = krb5_cc_default (context, &ccache);
168
} else {
169
*delegated_cred_handle = NULL;
170
kret = krb5_cc_new_unique (context, krb5_cc_type_memory,
171
NULL, &ccache);
172
}
173
if (kret) {
174
ctx->flags &= ~GSS_C_DELEG_FLAG;
175
goto out;
176
}
177
178
kret = krb5_cc_initialize(context, ccache, ctx->source);
179
if (kret) {
180
ctx->flags &= ~GSS_C_DELEG_FLAG;
181
goto out;
182
}
183
184
krb5_auth_con_removeflags(context,
185
ctx->auth_context,
186
KRB5_AUTH_CONTEXT_DO_TIME,
187
&ac_flags);
188
kret = krb5_rd_cred2(context,
189
ctx->auth_context,
190
ccache,
191
&ctx->fwd_data);
192
krb5_auth_con_setflags(context,
193
ctx->auth_context,
194
ac_flags);
195
if (kret) {
196
ctx->flags &= ~GSS_C_DELEG_FLAG;
197
ret = GSS_S_FAILURE;
198
*minor_status = kret;
199
goto out;
200
}
201
202
if (delegated_cred_handle) {
203
gsskrb5_cred handle;
204
205
ret = _gsskrb5_krb5_import_cred(minor_status,
206
ccache,
207
NULL,
208
NULL,
209
delegated_cred_handle);
210
if (ret != GSS_S_COMPLETE)
211
goto out;
212
213
handle = (gsskrb5_cred) *delegated_cred_handle;
214
215
handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
216
krb5_cc_close(context, ccache);
217
ccache = NULL;
218
}
219
220
out:
221
if (ccache) {
222
/* Don't destroy the default cred cache */
223
if (delegated_cred_handle == NULL)
224
krb5_cc_close(context, ccache);
225
else
226
krb5_cc_destroy(context, ccache);
227
}
228
return ret;
229
}
230
231
static OM_uint32
232
gsskrb5_acceptor_ready(OM_uint32 * minor_status,
233
gsskrb5_ctx ctx,
234
krb5_context context,
235
gss_cred_id_t *delegated_cred_handle)
236
{
237
OM_uint32 ret;
238
int32_t seq_number;
239
int is_cfx = 0;
240
241
krb5_auth_con_getremoteseqnumber (context,
242
ctx->auth_context,
243
&seq_number);
244
245
_gsskrb5i_is_cfx(context, ctx, 1);
246
is_cfx = (ctx->more_flags & IS_CFX);
247
248
ret = _gssapi_msg_order_create(minor_status,
249
&ctx->order,
250
_gssapi_msg_order_f(ctx->flags),
251
seq_number, 0, is_cfx);
252
if (ret)
253
return ret;
254
255
/*
256
* If requested, set local sequence num to remote sequence if this
257
* isn't a mutual authentication context
258
*/
259
if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) {
260
krb5_auth_con_setlocalseqnumber(context,
261
ctx->auth_context,
262
seq_number);
263
}
264
265
/*
266
* We should handle the delegation ticket, in case it's there
267
*/
268
if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) {
269
ret = gsskrb5_accept_delegated_token(minor_status,
270
ctx,
271
context,
272
delegated_cred_handle);
273
if (ret)
274
return ret;
275
} else {
276
/* Well, looks like it wasn't there after all */
277
ctx->flags &= ~GSS_C_DELEG_FLAG;
278
}
279
280
ctx->state = ACCEPTOR_READY;
281
ctx->more_flags |= OPEN;
282
283
return GSS_S_COMPLETE;
284
}
285
286
static OM_uint32
287
send_error_token(OM_uint32 *minor_status,
288
krb5_context context,
289
krb5_error_code kret,
290
krb5_principal server,
291
krb5_data *indata,
292
gss_buffer_t output_token)
293
{
294
krb5_principal ap_req_server = NULL;
295
krb5_error_code ret;
296
krb5_data outbuf;
297
/* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which
298
tells windows to try again with the corrected timestamp. See
299
[MS-KILE] 2.2.1 KERB-ERROR-DATA */
300
krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") };
301
302
/* build server from request if the acceptor had not selected one */
303
if (server == NULL) {
304
AP_REQ ap_req;
305
306
ret = krb5_decode_ap_req(context, indata, &ap_req);
307
if (ret) {
308
*minor_status = ret;
309
return GSS_S_FAILURE;
310
}
311
ret = _krb5_principalname2krb5_principal(context,
312
&ap_req_server,
313
ap_req.ticket.sname,
314
ap_req.ticket.realm);
315
free_AP_REQ(&ap_req);
316
if (ret) {
317
*minor_status = ret;
318
return GSS_S_FAILURE;
319
}
320
server = ap_req_server;
321
}
322
323
ret = krb5_mk_error(context, kret, NULL, &e_data, NULL,
324
server, NULL, NULL, &outbuf);
325
if (ap_req_server)
326
krb5_free_principal(context, ap_req_server);
327
if (ret) {
328
*minor_status = ret;
329
return GSS_S_FAILURE;
330
}
331
332
ret = _gsskrb5_encapsulate(minor_status,
333
&outbuf,
334
output_token,
335
"\x03\x00",
336
GSS_KRB5_MECHANISM);
337
krb5_data_free (&outbuf);
338
if (ret)
339
return ret;
340
341
*minor_status = 0;
342
return GSS_S_CONTINUE_NEEDED;
343
}
344
345
346
static OM_uint32
347
gsskrb5_acceptor_start(OM_uint32 * minor_status,
348
gsskrb5_ctx ctx,
349
krb5_context context,
350
const gss_cred_id_t acceptor_cred_handle,
351
const gss_buffer_t input_token_buffer,
352
const gss_channel_bindings_t input_chan_bindings,
353
gss_name_t * src_name,
354
gss_OID * mech_type,
355
gss_buffer_t output_token,
356
OM_uint32 * ret_flags,
357
OM_uint32 * time_rec,
358
gss_cred_id_t * delegated_cred_handle)
359
{
360
krb5_error_code kret;
361
OM_uint32 ret = GSS_S_COMPLETE;
362
krb5_data indata;
363
krb5_flags ap_options;
364
krb5_keytab keytab = NULL;
365
int is_cfx = 0;
366
const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle;
367
368
/*
369
* We may, or may not, have an escapsulation.
370
*/
371
ret = _gsskrb5_decapsulate (minor_status,
372
input_token_buffer,
373
&indata,
374
"\x01\x00",
375
GSS_KRB5_MECHANISM);
376
377
if (ret) {
378
/* Assume that there is no OID wrapping. */
379
indata.length = input_token_buffer->length;
380
indata.data = input_token_buffer->value;
381
}
382
383
/*
384
* We need to get our keytab
385
*/
386
if (acceptor_cred == NULL) {
387
if (_gsskrb5_keytab != NULL)
388
keytab = _gsskrb5_keytab;
389
} else if (acceptor_cred->keytab != NULL) {
390
keytab = acceptor_cred->keytab;
391
}
392
393
/*
394
* We need to check the ticket and create the AP-REP packet
395
*/
396
397
{
398
krb5_rd_req_in_ctx in = NULL;
399
krb5_rd_req_out_ctx out = NULL;
400
krb5_principal server = NULL;
401
402
if (acceptor_cred)
403
server = acceptor_cred->principal;
404
405
kret = krb5_rd_req_in_ctx_alloc(context, &in);
406
if (kret == 0)
407
kret = krb5_rd_req_in_set_keytab(context, in, keytab);
408
if (kret) {
409
if (in)
410
krb5_rd_req_in_ctx_free(context, in);
411
*minor_status = kret;
412
return GSS_S_FAILURE;
413
}
414
415
kret = krb5_rd_req_ctx(context,
416
&ctx->auth_context,
417
&indata,
418
server,
419
in, &out);
420
krb5_rd_req_in_ctx_free(context, in);
421
if (kret == KRB5KRB_AP_ERR_SKEW || kret == KRB5KRB_AP_ERR_TKT_NYV) {
422
/*
423
* No reply in non-MUTUAL mode, but we don't know that its
424
* non-MUTUAL mode yet, thats inside the 8003 checksum, so
425
* lets only send the error token on clock skew, that
426
* limit when send error token for non-MUTUAL.
427
*/
428
free_Authenticator(ctx->auth_context->authenticator);
429
return send_error_token(minor_status, context, kret,
430
server, &indata, output_token);
431
} else if (kret) {
432
*minor_status = kret;
433
return GSS_S_FAILURE;
434
}
435
436
/*
437
* we need to remember some data on the context_handle.
438
*/
439
kret = krb5_rd_req_out_get_ap_req_options(context, out,
440
&ap_options);
441
if (kret == 0)
442
kret = krb5_rd_req_out_get_ticket(context, out,
443
&ctx->ticket);
444
if (kret == 0)
445
kret = krb5_rd_req_out_get_keyblock(context, out,
446
&ctx->service_keyblock);
447
ctx->lifetime = ctx->ticket->ticket.endtime;
448
449
krb5_rd_req_out_ctx_free(context, out);
450
if (kret) {
451
ret = GSS_S_FAILURE;
452
*minor_status = kret;
453
return ret;
454
}
455
}
456
457
458
/*
459
* We need to copy the principal names to the context and the
460
* calling layer.
461
*/
462
kret = krb5_copy_principal(context,
463
ctx->ticket->client,
464
&ctx->source);
465
if (kret) {
466
ret = GSS_S_FAILURE;
467
*minor_status = kret;
468
}
469
470
kret = krb5_copy_principal(context,
471
ctx->ticket->server,
472
&ctx->target);
473
if (kret) {
474
ret = GSS_S_FAILURE;
475
*minor_status = kret;
476
return ret;
477
}
478
479
/*
480
* We need to setup some compat stuff, this assumes that
481
* context_handle->target is already set.
482
*/
483
ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
484
if (ret)
485
return ret;
486
487
if (src_name != NULL) {
488
kret = krb5_copy_principal (context,
489
ctx->ticket->client,
490
(gsskrb5_name*)src_name);
491
if (kret) {
492
ret = GSS_S_FAILURE;
493
*minor_status = kret;
494
return ret;
495
}
496
}
497
498
/*
499
* We need to get the flags out of the 8003 checksum.
500
*/
501
502
{
503
krb5_authenticator authenticator;
504
505
kret = krb5_auth_con_getauthenticator(context,
506
ctx->auth_context,
507
&authenticator);
508
if(kret) {
509
ret = GSS_S_FAILURE;
510
*minor_status = kret;
511
return ret;
512
}
513
514
if (authenticator->cksum == NULL) {
515
krb5_free_authenticator(context, &authenticator);
516
*minor_status = 0;
517
return GSS_S_BAD_BINDINGS;
518
}
519
520
if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {
521
ret = _gsskrb5_verify_8003_checksum(minor_status,
522
input_chan_bindings,
523
authenticator->cksum,
524
&ctx->flags,
525
&ctx->fwd_data);
526
527
krb5_free_authenticator(context, &authenticator);
528
if (ret) {
529
return ret;
530
}
531
} else {
532
krb5_crypto crypto;
533
534
kret = krb5_crypto_init(context,
535
ctx->auth_context->keyblock,
536
0, &crypto);
537
if(kret) {
538
krb5_free_authenticator(context, &authenticator);
539
540
ret = GSS_S_FAILURE;
541
*minor_status = kret;
542
return ret;
543
}
544
545
/*
546
* Windows accepts Samba3's use of a kerberos, rather than
547
* GSSAPI checksum here
548
*/
549
550
kret = krb5_verify_checksum(context,
551
crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0,
552
authenticator->cksum);
553
krb5_free_authenticator(context, &authenticator);
554
krb5_crypto_destroy(context, crypto);
555
556
if(kret) {
557
ret = GSS_S_BAD_SIG;
558
*minor_status = kret;
559
return ret;
560
}
561
562
/*
563
* Samba style get some flags (but not DCE-STYLE), use
564
* ap_options to guess the mutual flag.
565
*/
566
ctx->flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
567
if (ap_options & AP_OPTS_MUTUAL_REQUIRED)
568
ctx->flags |= GSS_C_MUTUAL_FLAG;
569
}
570
}
571
572
if(ctx->flags & GSS_C_MUTUAL_FLAG) {
573
krb5_data outbuf;
574
int use_subkey = 0;
575
576
_gsskrb5i_is_cfx(context, ctx, 1);
577
is_cfx = (ctx->more_flags & IS_CFX);
578
579
if (is_cfx || (ap_options & AP_OPTS_USE_SUBKEY)) {
580
use_subkey = 1;
581
} else {
582
krb5_keyblock *rkey;
583
584
/*
585
* If there is a initiator subkey, copy that to acceptor
586
* subkey to match Windows behavior
587
*/
588
kret = krb5_auth_con_getremotesubkey(context,
589
ctx->auth_context,
590
&rkey);
591
if (kret == 0) {
592
kret = krb5_auth_con_setlocalsubkey(context,
593
ctx->auth_context,
594
rkey);
595
if (kret == 0)
596
use_subkey = 1;
597
krb5_free_keyblock(context, rkey);
598
}
599
}
600
if (use_subkey) {
601
ctx->more_flags |= ACCEPTOR_SUBKEY;
602
krb5_auth_con_addflags(context, ctx->auth_context,
603
KRB5_AUTH_CONTEXT_USE_SUBKEY,
604
NULL);
605
}
606
607
kret = krb5_mk_rep(context,
608
ctx->auth_context,
609
&outbuf);
610
if (kret) {
611
*minor_status = kret;
612
return GSS_S_FAILURE;
613
}
614
615
if (IS_DCE_STYLE(ctx)) {
616
output_token->length = outbuf.length;
617
output_token->value = outbuf.data;
618
} else {
619
ret = _gsskrb5_encapsulate(minor_status,
620
&outbuf,
621
output_token,
622
"\x02\x00",
623
GSS_KRB5_MECHANISM);
624
krb5_data_free (&outbuf);
625
if (ret)
626
return ret;
627
}
628
}
629
630
ctx->flags |= GSS_C_TRANS_FLAG;
631
632
/* Remember the flags */
633
634
ctx->lifetime = ctx->ticket->ticket.endtime;
635
ctx->more_flags |= OPEN;
636
637
if (mech_type)
638
*mech_type = GSS_KRB5_MECHANISM;
639
640
if (time_rec) {
641
ret = _gsskrb5_lifetime_left(minor_status,
642
context,
643
ctx->lifetime,
644
time_rec);
645
if (ret) {
646
return ret;
647
}
648
}
649
650
/*
651
* When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from
652
* the client.
653
*/
654
if (IS_DCE_STYLE(ctx)) {
655
/*
656
* Return flags to caller, but we haven't processed
657
* delgations yet
658
*/
659
if (ret_flags)
660
*ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG);
661
662
ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE;
663
return GSS_S_CONTINUE_NEEDED;
664
}
665
666
ret = gsskrb5_acceptor_ready(minor_status, ctx, context,
667
delegated_cred_handle);
668
669
if (ret_flags)
670
*ret_flags = ctx->flags;
671
672
return ret;
673
}
674
675
static OM_uint32
676
acceptor_wait_for_dcestyle(OM_uint32 * minor_status,
677
gsskrb5_ctx ctx,
678
krb5_context context,
679
const gss_cred_id_t acceptor_cred_handle,
680
const gss_buffer_t input_token_buffer,
681
const gss_channel_bindings_t input_chan_bindings,
682
gss_name_t * src_name,
683
gss_OID * mech_type,
684
gss_buffer_t output_token,
685
OM_uint32 * ret_flags,
686
OM_uint32 * time_rec,
687
gss_cred_id_t * delegated_cred_handle)
688
{
689
OM_uint32 ret;
690
krb5_error_code kret;
691
krb5_data inbuf;
692
int32_t r_seq_number, l_seq_number;
693
694
/*
695
* We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP
696
*/
697
698
inbuf.length = input_token_buffer->length;
699
inbuf.data = input_token_buffer->value;
700
701
/*
702
* We need to remeber the old remote seq_number, then check if the
703
* client has replied with our local seq_number, and then reset
704
* the remote seq_number to the old value
705
*/
706
{
707
kret = krb5_auth_con_getlocalseqnumber(context,
708
ctx->auth_context,
709
&l_seq_number);
710
if (kret) {
711
*minor_status = kret;
712
return GSS_S_FAILURE;
713
}
714
715
kret = krb5_auth_con_getremoteseqnumber(context,
716
ctx->auth_context,
717
&r_seq_number);
718
if (kret) {
719
*minor_status = kret;
720
return GSS_S_FAILURE;
721
}
722
723
kret = krb5_auth_con_setremoteseqnumber(context,
724
ctx->auth_context,
725
l_seq_number);
726
if (kret) {
727
*minor_status = kret;
728
return GSS_S_FAILURE;
729
}
730
}
731
732
/*
733
* We need to verify the AP_REP, but we need to flag that this is
734
* DCE_STYLE, so don't check the timestamps this time, but put the
735
* flag DO_TIME back afterward.
736
*/
737
{
738
krb5_ap_rep_enc_part *repl;
739
int32_t auth_flags;
740
741
krb5_auth_con_removeflags(context,
742
ctx->auth_context,
743
KRB5_AUTH_CONTEXT_DO_TIME,
744
&auth_flags);
745
746
kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl);
747
if (kret) {
748
*minor_status = kret;
749
return GSS_S_FAILURE;
750
}
751
krb5_free_ap_rep_enc_part(context, repl);
752
krb5_auth_con_setflags(context, ctx->auth_context, auth_flags);
753
}
754
755
/* We need to check the liftime */
756
{
757
OM_uint32 lifetime_rec;
758
759
ret = _gsskrb5_lifetime_left(minor_status,
760
context,
761
ctx->lifetime,
762
&lifetime_rec);
763
if (ret) {
764
return ret;
765
}
766
if (lifetime_rec == 0) {
767
return GSS_S_CONTEXT_EXPIRED;
768
}
769
770
if (time_rec) *time_rec = lifetime_rec;
771
}
772
773
/* We need to give the caller the flags which are in use */
774
if (ret_flags) *ret_flags = ctx->flags;
775
776
if (src_name) {
777
kret = krb5_copy_principal(context,
778
ctx->source,
779
(gsskrb5_name*)src_name);
780
if (kret) {
781
*minor_status = kret;
782
return GSS_S_FAILURE;
783
}
784
}
785
786
/*
787
* After the krb5_rd_rep() the remote and local seq_number should
788
* be the same, because the client just replies the seq_number
789
* from our AP-REP in its AP-REP, but then the client uses the
790
* seq_number from its AP-REQ for GSS_wrap()
791
*/
792
{
793
int32_t tmp_r_seq_number, tmp_l_seq_number;
794
795
kret = krb5_auth_con_getremoteseqnumber(context,
796
ctx->auth_context,
797
&tmp_r_seq_number);
798
if (kret) {
799
*minor_status = kret;
800
return GSS_S_FAILURE;
801
}
802
803
kret = krb5_auth_con_getlocalseqnumber(context,
804
ctx->auth_context,
805
&tmp_l_seq_number);
806
if (kret) {
807
808
*minor_status = kret;
809
return GSS_S_FAILURE;
810
}
811
812
/*
813
* Here we check if the client has responsed with our local seq_number,
814
*/
815
if (tmp_r_seq_number != tmp_l_seq_number) {
816
return GSS_S_UNSEQ_TOKEN;
817
}
818
}
819
820
/*
821
* We need to reset the remote seq_number, because the client will use,
822
* the old one for the GSS_wrap() calls
823
*/
824
{
825
kret = krb5_auth_con_setremoteseqnumber(context,
826
ctx->auth_context,
827
r_seq_number);
828
if (kret) {
829
*minor_status = kret;
830
return GSS_S_FAILURE;
831
}
832
}
833
834
return gsskrb5_acceptor_ready(minor_status, ctx, context,
835
delegated_cred_handle);
836
}
837
838
839
OM_uint32 GSSAPI_CALLCONV
840
_gsskrb5_accept_sec_context(OM_uint32 * minor_status,
841
gss_ctx_id_t * context_handle,
842
const gss_cred_id_t acceptor_cred_handle,
843
const gss_buffer_t input_token_buffer,
844
const gss_channel_bindings_t input_chan_bindings,
845
gss_name_t * src_name,
846
gss_OID * mech_type,
847
gss_buffer_t output_token,
848
OM_uint32 * ret_flags,
849
OM_uint32 * time_rec,
850
gss_cred_id_t * delegated_cred_handle)
851
{
852
krb5_context context;
853
OM_uint32 ret;
854
gsskrb5_ctx ctx;
855
856
GSSAPI_KRB5_INIT(&context);
857
858
output_token->length = 0;
859
output_token->value = NULL;
860
861
if (src_name != NULL)
862
*src_name = NULL;
863
if (mech_type)
864
*mech_type = GSS_KRB5_MECHANISM;
865
866
if (*context_handle == GSS_C_NO_CONTEXT) {
867
ret = _gsskrb5_create_ctx(minor_status,
868
context_handle,
869
context,
870
input_chan_bindings,
871
ACCEPTOR_START);
872
if (ret)
873
return ret;
874
}
875
876
ctx = (gsskrb5_ctx)*context_handle;
877
878
879
/*
880
* TODO: check the channel_bindings
881
* (above just sets them to krb5 layer)
882
*/
883
884
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
885
886
switch (ctx->state) {
887
case ACCEPTOR_START:
888
ret = gsskrb5_acceptor_start(minor_status,
889
ctx,
890
context,
891
acceptor_cred_handle,
892
input_token_buffer,
893
input_chan_bindings,
894
src_name,
895
mech_type,
896
output_token,
897
ret_flags,
898
time_rec,
899
delegated_cred_handle);
900
break;
901
case ACCEPTOR_WAIT_FOR_DCESTYLE:
902
ret = acceptor_wait_for_dcestyle(minor_status,
903
ctx,
904
context,
905
acceptor_cred_handle,
906
input_token_buffer,
907
input_chan_bindings,
908
src_name,
909
mech_type,
910
output_token,
911
ret_flags,
912
time_rec,
913
delegated_cred_handle);
914
break;
915
case ACCEPTOR_READY:
916
/*
917
* If we get there, the caller have called
918
* gss_accept_sec_context() one time too many.
919
*/
920
ret = GSS_S_BAD_STATUS;
921
break;
922
default:
923
/* TODO: is this correct here? --metze */
924
ret = GSS_S_BAD_STATUS;
925
break;
926
}
927
928
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
929
930
if (GSS_ERROR(ret)) {
931
OM_uint32 min2;
932
_gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER);
933
}
934
935
return ret;
936
}
937
938