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