1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
4 * Portions Copyright (C) 2007 Apple Inc.
5 * Copyright 1990, 1991, 2007, 2008, 2009, 2013, 2014 by the
6 * Massachusetts Institute of Technology. All Rights Reserved.
8 * Export of this software from the United States of America may
9 * require a specific license from the United States Government.
10 * It is the responsibility of any person or organization contemplating
11 * export to obtain such a license before exporting.
13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14 * distribute this software and its documentation for any purpose and
15 * without fee is hereby granted, provided that the above copyright
16 * notice appear in all copies and that both that copyright notice and
17 * this permission notice appear in supporting documentation, and that
18 * the name of M.I.T. not be used in advertising or publicity pertaining
19 * to distribution of the software without specific, written prior
20 * permission. Furthermore if you modify this software you must label
21 * your software as modified software and not distribute it in such a
22 * fashion that it might be confused with the original M.I.T. software.
23 * M.I.T. makes no representations about the suitability of
24 * this software for any purpose. It is provided "as is" without express
25 * or implied warranty.
28 * KDC Routines to deal with AS_REQ's
31 * Copyright (c) 2006-2008, Novell, Inc.
32 * All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions are met:
37 * * Redistributions of source code must retain the above copyright notice,
38 * this list of conditions and the following disclaimer.
39 * * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * * The copyright holder's name is not used to endorse or promote products
43 * derived from this software without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
46 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
49 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55 * POSSIBILITY OF SUCH DAMAGE.
62 #ifdef HAVE_NETINET_IN_H
63 #include <sys/types.h>
64 #include <netinet/in.h>
66 #include <arpa/inet.h>
68 #endif /* HAVE_NETINET_IN_H */
71 #include "kdc_audit.h"
73 #include <kadm5/admin.h>
74 #include "adm_proto.h"
77 static krb5_error_code
78 prepare_error_as(struct kdc_request_state *, krb5_kdc_req *, krb5_db_entry *,
79 int, krb5_pa_data **, krb5_boolean, krb5_principal,
80 krb5_data **, const char *);
82 /* Determine the key-expiration value according to RFC 4120 section 5.4.2. */
84 get_key_exp(krb5_db_entry *entry)
86 if (entry->expiration == 0)
87 return entry->pw_expiration;
88 if (entry->pw_expiration == 0)
89 return entry->expiration;
90 return min(entry->expiration, entry->pw_expiration);
94 * Find the key in client for the most preferred enctype in req_enctypes. Fill
95 * in *kb_out with the decrypted keyblock (which the caller must free) and set
96 * *kd_out to an alias to that key data entry. Set *kd_out to NULL and leave
97 * *kb_out zeroed if no key is found for any of the requested enctypes.
98 * kb_out->enctype may differ from the enctype of *kd_out for DES enctypes; in
99 * this case, kb_out->enctype is the requested enctype used to match the key
102 static krb5_error_code
103 select_client_key(krb5_context context, krb5_db_entry *client,
104 krb5_enctype *req_enctypes, int n_req_enctypes,
105 krb5_keyblock *kb_out, krb5_key_data **kd_out)
112 memset(kb_out, 0, sizeof(*kb_out));
115 for (i = 0; i < n_req_enctypes; i++) {
116 etype = req_enctypes[i];
117 if (!krb5_c_valid_enctype(etype))
119 if (krb5_dbe_find_enctype(context, client, etype, -1, 0, &kd) == 0) {
120 /* Decrypt the client key data and set its enctype to the request
121 * enctype (which may differ from the key data enctype for DES). */
122 ret = krb5_dbe_decrypt_key_data(context, NULL, kd, kb_out, NULL);
125 kb_out->enctype = etype;
133 struct as_req_state {
134 loop_respond_fn respond;
137 krb5_principal_data client_princ;
138 krb5_enc_tkt_part enc_tkt_reply;
139 krb5_enc_kdc_rep_part reply_encpart;
140 krb5_ticket ticket_reply;
141 krb5_keyblock server_keyblock;
142 krb5_keyblock client_keyblock;
143 krb5_db_entry *client;
144 krb5_db_entry *server;
145 krb5_db_entry *local_tgt;
146 krb5_db_entry *local_tgt_storage;
147 krb5_key_data *client_key;
148 krb5_kdc_req *request;
149 struct krb5_kdcpreauth_rock_st rock;
151 krb5_pa_data **e_data;
152 krb5_boolean typed_e_data;
154 krb5_timestamp kdc_time;
155 krb5_timestamp authtime;
156 krb5_keyblock session_key;
157 unsigned int c_flags;
159 krb5_data *inner_body;
160 struct kdc_request_state *rstate;
163 const krb5_fulladdr *from;
164 krb5_data **auth_indicators;
166 krb5_error_code preauth_err;
168 kdc_realm_t *active_realm;
169 krb5_audit_state *au_state;
173 finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
175 krb5_key_data *server_key;
176 krb5_keyblock *as_encrypting_key = NULL;
177 krb5_data *response = NULL;
178 const char *emsg = 0;
180 loop_respond_fn oldrespond;
182 kdc_realm_t *kdc_active_realm = state->active_realm;
183 krb5_audit_state *au_state = state->au_state;
186 oldrespond = state->respond;
192 au_state->stage = ENCR_REP;
194 if ((errcode = validate_forwardable(state->request, *state->client,
195 *state->server, state->kdc_time,
197 errcode += ERROR_TABLE_BASE_krb5;
201 errcode = check_indicators(kdc_context, state->server,
202 state->auth_indicators);
204 state->status = "HIGHER_AUTHENTICATION_REQUIRED";
208 state->ticket_reply.enc_part2 = &state->enc_tkt_reply;
211 * Find the server key
213 if ((errcode = krb5_dbe_find_enctype(kdc_context, state->server,
214 -1, /* ignore keytype */
215 -1, /* Ignore salttype */
216 0, /* Get highest kvno */
218 state->status = "FINDING_SERVER_KEY";
223 * Convert server->key into a real key
224 * (it may be encrypted in the database)
226 * server_keyblock is later used to generate auth data signatures
228 if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
230 &state->server_keyblock,
232 state->status = "DECRYPT_SERVER_KEY";
236 /* Start assembling the response */
237 state->reply.msg_type = KRB5_AS_REP;
238 state->reply.client = state->enc_tkt_reply.client; /* post canonization */
239 state->reply.ticket = &state->ticket_reply;
240 state->reply_encpart.session = &state->session_key;
241 if ((errcode = fetch_last_req_info(state->client,
242 &state->reply_encpart.last_req))) {
243 state->status = "FETCH_LAST_REQ";
246 state->reply_encpart.nonce = state->request->nonce;
247 state->reply_encpart.key_exp = get_key_exp(state->client);
248 state->reply_encpart.flags = state->enc_tkt_reply.flags;
249 state->reply_encpart.server = state->ticket_reply.server;
251 /* copy the time fields EXCEPT for authtime; it's location
254 state->reply_encpart.times = state->enc_tkt_reply.times;
255 state->reply_encpart.times.authtime = state->authtime = state->kdc_time;
257 state->reply_encpart.caddrs = state->enc_tkt_reply.caddrs;
258 state->reply_encpart.enc_padata = NULL;
260 /* Fetch the padata info to be returned (do this before
261 * authdata to handle possible replacement of reply key
263 errcode = return_padata(kdc_context, &state->rock, state->req_pkt,
264 state->request, &state->reply,
265 &state->client_keyblock, &state->pa_context);
267 state->status = "KDC_RETURN_PADATA";
271 /* If we didn't find a client long-term key and no preauth mechanism
272 * replaced the reply key, error out now. */
273 if (state->client_keyblock.enctype == ENCTYPE_NULL) {
274 state->status = "CANT_FIND_CLIENT_KEY";
275 errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
279 errcode = handle_authdata(kdc_context,
285 &state->client_keyblock,
286 &state->server_keyblock,
290 NULL, /* for_user_princ */
291 NULL, /* enc_tkt_request */
292 state->auth_indicators,
293 &state->enc_tkt_reply);
295 krb5_klog_syslog(LOG_INFO, _("AS_REQ : handle_authdata (%d)"),
297 state->status = "HANDLE_AUTHDATA";
301 errcode = krb5_encrypt_tkt_part(kdc_context, &state->server_keyblock,
302 &state->ticket_reply);
304 state->status = "ENCRYPT_TICKET";
308 errcode = kau_make_tkt_id(kdc_context, &state->ticket_reply,
309 &au_state->tkt_out_id);
311 state->status = "GENERATE_TICKET_ID";
315 state->ticket_reply.enc_part.kvno = server_key->key_data_kvno;
316 errcode = kdc_fast_response_handle_padata(state->rstate,
319 state->client_keyblock.enctype);
321 state->status = "MAKE_FAST_RESPONSE";
325 /* now encode/encrypt the response */
327 state->reply.enc_part.enctype = state->client_keyblock.enctype;
329 errcode = kdc_fast_handle_reply_key(state->rstate, &state->client_keyblock,
332 state->status = "MAKE_FAST_REPLY_KEY";
335 errcode = return_enc_padata(kdc_context, state->req_pkt, state->request,
336 as_encrypting_key, state->server,
337 &state->reply_encpart, FALSE);
339 state->status = "KDC_RETURN_ENC_PADATA";
343 if (kdc_fast_hide_client(state->rstate))
344 state->reply.client = (krb5_principal)krb5_anonymous_principal();
345 errcode = krb5_encode_kdc_rep(kdc_context, KRB5_AS_REP,
346 &state->reply_encpart, 0,
348 &state->reply, &response);
349 if (state->client_key != NULL)
350 state->reply.enc_part.kvno = state->client_key->key_data_kvno;
352 state->status = "ENCODE_KDC_REP";
356 /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we
357 can use them in raw form if needed. But, we don't... */
358 memset(state->reply.enc_part.ciphertext.data, 0,
359 state->reply.enc_part.ciphertext.length);
360 free(state->reply.enc_part.ciphertext.data);
362 log_as_req(kdc_context, state->from, state->request, &state->reply,
363 state->client, state->cname, state->server,
364 state->sname, state->authtime, 0, 0, 0);
369 assert (state->status != 0);
371 au_state->status = state->status;
372 au_state->reply = &state->reply;
373 kau_as_req(kdc_context,
374 (errcode || state->preauth_err) ? FALSE : TRUE, au_state);
375 kau_free_kdc_req(au_state);
377 free_padata_context(kdc_context, state->pa_context);
378 if (as_encrypting_key)
379 krb5_free_keyblock(kdc_context, as_encrypting_key);
381 emsg = krb5_get_error_message(kdc_context, errcode);
384 log_as_req(kdc_context,
385 state->from, state->request, &state->reply, state->client,
386 state->cname, state->server, state->sname, state->authtime,
387 state->status, errcode, emsg);
391 if (state->status == 0) {
392 state->status = emsg;
394 if (errcode != KRB5KDC_ERR_DISCARD) {
395 errcode -= ERROR_TABLE_BASE_krb5;
396 if (errcode < 0 || errcode > KRB_ERR_MAX)
397 errcode = KRB_ERR_GENERIC;
399 errcode = prepare_error_as(state->rstate, state->request,
400 state->local_tgt, errcode,
401 state->e_data, state->typed_e_data,
402 ((state->client != NULL) ?
403 state->client->princ : NULL),
404 &response, state->status);
410 krb5_free_error_message(kdc_context, emsg);
411 if (state->enc_tkt_reply.authorization_data != NULL)
412 krb5_free_authdata(kdc_context,
413 state->enc_tkt_reply.authorization_data);
414 if (state->server_keyblock.contents != NULL)
415 krb5_free_keyblock_contents(kdc_context, &state->server_keyblock);
416 if (state->client_keyblock.contents != NULL)
417 krb5_free_keyblock_contents(kdc_context, &state->client_keyblock);
418 if (state->reply.padata != NULL)
419 krb5_free_pa_data(kdc_context, state->reply.padata);
420 if (state->reply_encpart.enc_padata)
421 krb5_free_pa_data(kdc_context, state->reply_encpart.enc_padata);
423 if (state->cname != NULL)
425 if (state->sname != NULL)
427 krb5_db_free_principal(kdc_context, state->client);
428 krb5_db_free_principal(kdc_context, state->server);
429 krb5_db_free_principal(kdc_context, state->local_tgt_storage);
430 if (state->session_key.contents != NULL)
431 krb5_free_keyblock_contents(kdc_context, &state->session_key);
432 if (state->ticket_reply.enc_part.ciphertext.data != NULL) {
433 memset(state->ticket_reply.enc_part.ciphertext.data , 0,
434 state->ticket_reply.enc_part.ciphertext.length);
435 free(state->ticket_reply.enc_part.ciphertext.data);
438 krb5_free_pa_data(kdc_context, state->e_data);
439 krb5_free_data(kdc_context, state->inner_body);
440 kdc_free_rstate(state->rstate);
441 krb5_free_kdc_req(kdc_context, state->request);
442 k5_free_data_ptr_list(state->auth_indicators);
443 assert(did_log != 0);
446 (*oldrespond)(oldarg, errcode, response);
450 finish_missing_required_preauth(void *arg)
452 struct as_req_state *state = (struct as_req_state *)arg;
454 finish_process_as_req(state, state->preauth_err);
458 finish_preauth(void *arg, krb5_error_code code)
460 struct as_req_state *state = arg;
461 krb5_error_code real_code = code;
465 code = KRB5KRB_ERR_GENERIC;
466 state->status = "PREAUTH_FAILED";
467 if (real_code == KRB5KDC_ERR_PREAUTH_FAILED) {
468 state->preauth_err = code;
469 get_preauth_hint_list(state->request, &state->rock, &state->e_data,
470 finish_missing_required_preauth, state);
475 * Final check before handing out ticket: If the client requires
476 * preauthentication, verify that the proper kind of
477 * preauthentication was carried out.
479 state->status = missing_required_preauth(state->client, state->server,
480 &state->enc_tkt_reply);
482 state->preauth_err = KRB5KDC_ERR_PREAUTH_REQUIRED;
483 get_preauth_hint_list(state->request, &state->rock, &state->e_data,
484 finish_missing_required_preauth, state);
489 finish_process_as_req(state, code);
494 process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
495 const krb5_fulladdr *from, kdc_realm_t *kdc_active_realm,
496 verto_ctx *vctx, loop_respond_fn respond, void *arg)
498 krb5_error_code errcode;
499 unsigned int s_flags = 0;
500 krb5_data encoded_req_body;
501 krb5_enctype useenctype;
502 struct as_req_state *state;
503 krb5_audit_state *au_state = NULL;
505 state = k5alloc(sizeof(*state), &errcode);
507 (*respond)(arg, errcode, NULL);
510 state->respond = respond;
512 state->request = request;
513 state->req_pkt = req_pkt;
515 state->active_realm = kdc_active_realm;
517 errcode = kdc_make_rstate(kdc_active_realm, &state->rstate);
519 (*respond)(arg, errcode, NULL);
524 /* Initialize audit state. */
525 errcode = kau_init_kdc_req(kdc_context, state->request, from, &au_state);
527 (*respond)(arg, errcode, NULL);
528 kdc_free_rstate(state->rstate);
532 state->au_state = au_state;
534 if (state->request->msg_type != KRB5_AS_REQ) {
535 state->status = "VALIDATE_MESSAGE_TYPE";
536 errcode = KRB5_BADMSGTYPE;
540 /* Seed the audit trail with the request ID and basic information. */
541 kau_as_req(kdc_context, TRUE, au_state);
543 if (fetch_asn1_field((unsigned char *) req_pkt->data,
544 1, 4, &encoded_req_body) != 0) {
545 errcode = ASN1_BAD_ID;
546 state->status = "FETCH_REQ_BODY";
549 errcode = kdc_find_fast(&state->request, &encoded_req_body, NULL, NULL,
550 state->rstate, &state->inner_body);
552 state->status = "FIND_FAST";
555 if (state->inner_body == NULL) {
556 /* Not a FAST request; copy the encoded request body. */
557 errcode = krb5_copy_data(kdc_context, &encoded_req_body,
560 state->status = "COPY_REQ_BODY";
564 au_state->request = state->request;
565 state->rock.request = state->request;
566 state->rock.inner_body = state->inner_body;
567 state->rock.rstate = state->rstate;
568 state->rock.vctx = vctx;
569 state->rock.auth_indicators = &state->auth_indicators;
570 if (!state->request->client) {
571 state->status = "NULL_CLIENT";
572 errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
575 if ((errcode = krb5_unparse_name(kdc_context,
576 state->request->client,
578 state->status = "UNPARSE_CLIENT";
581 limit_string(state->cname);
583 if (!state->request->server) {
584 state->status = "NULL_SERVER";
585 errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
588 if ((errcode = krb5_unparse_name(kdc_context,
589 state->request->server,
591 state->status = "UNPARSE_SERVER";
594 limit_string(state->sname);
597 * We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint
598 * to the backend to return naming information in lieu
599 * of cross realm TGS entries.
601 setflag(state->c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY);
603 * Note that according to the referrals draft we should
604 * always canonicalize enterprise principal names.
606 if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) ||
607 state->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
608 setflag(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE);
609 setflag(state->c_flags, KRB5_KDB_FLAG_ALIAS_OK);
611 if (include_pac_p(kdc_context, state->request)) {
612 setflag(state->c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
614 errcode = krb5_db_get_principal(kdc_context, state->request->client,
615 state->c_flags, &state->client);
616 if (errcode == KRB5_KDB_CANTLOCK_DB)
617 errcode = KRB5KDC_ERR_SVC_UNAVAILABLE;
618 if (errcode == KRB5_KDB_NOENTRY) {
619 state->status = "CLIENT_NOT_FOUND";
621 errcode = KRB5KRB_ERR_GENERIC;
623 errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
625 } else if (errcode) {
626 state->status = "LOOKING_UP_CLIENT";
629 state->rock.client = state->client;
632 * If the backend returned a principal that is not in the local
633 * realm, then we need to refer the client to that realm.
635 if (!is_local_principal(kdc_active_realm, state->client->princ)) {
636 /* Entry is a referral to another realm */
637 state->status = "REFERRAL";
638 au_state->cl_realm = &state->client->princ->realm;
639 errcode = KRB5KDC_ERR_WRONG_REALM;
643 au_state->stage = SRVC_PRINC;
646 setflag(s_flags, KRB5_KDB_FLAG_ALIAS_OK);
647 if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE)) {
648 setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE);
650 errcode = krb5_db_get_principal(kdc_context, state->request->server,
651 s_flags, &state->server);
652 if (errcode == KRB5_KDB_CANTLOCK_DB)
653 errcode = KRB5KDC_ERR_SVC_UNAVAILABLE;
654 if (errcode == KRB5_KDB_NOENTRY) {
655 state->status = "SERVER_NOT_FOUND";
656 errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
658 } else if (errcode) {
659 state->status = "LOOKING_UP_SERVER";
663 errcode = get_local_tgt(kdc_context, &state->request->server->realm,
664 state->server, &state->local_tgt,
665 &state->local_tgt_storage);
667 state->status = "GET_LOCAL_TGT";
671 au_state->stage = VALIDATE_POL;
673 if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) {
674 state->status = "TIMEOFDAY";
677 state->authtime = state->kdc_time; /* for audit_as_request() */
679 if ((errcode = validate_as_request(kdc_active_realm,
680 state->request, *state->client,
681 *state->server, state->kdc_time,
682 &state->status, &state->e_data))) {
684 state->status = "UNKNOWN_REASON";
685 errcode += ERROR_TABLE_BASE_krb5;
689 au_state->stage = ISSUE_TKT;
692 * Select the keytype for the ticket session key.
694 if ((useenctype = select_session_keytype(kdc_active_realm, state->server,
695 state->request->nktypes,
696 state->request->ktype)) == 0) {
697 /* unsupported ktype */
698 state->status = "BAD_ENCRYPTION_TYPE";
699 errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
703 if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
704 &state->session_key))) {
705 state->status = "MAKE_RANDOM_KEY";
710 * Canonicalization is only effective if we are issuing a TGT
711 * (the intention is to allow support for Windows "short" realm
712 * aliases, nothing more).
714 if (isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE) &&
715 krb5_is_tgs_principal(state->request->server) &&
716 krb5_is_tgs_principal(state->server->princ)) {
717 state->ticket_reply.server = state->server->princ;
719 state->ticket_reply.server = state->request->server;
722 /* Copy options that request the corresponding ticket flags. */
723 state->enc_tkt_reply.flags = OPTS2FLAGS(state->request->kdc_options);
724 state->enc_tkt_reply.times.authtime = state->authtime;
726 setflag(state->enc_tkt_reply.flags, TKT_FLG_INITIAL);
727 setflag(state->enc_tkt_reply.flags, TKT_FLG_ENC_PA_REP);
730 * It should be noted that local policy may affect the
731 * processing of any of these flags. For example, some
732 * realms may refuse to issue renewable tickets
735 state->enc_tkt_reply.session = &state->session_key;
736 if (isflagset(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
737 state->client_princ = *(state->client->princ);
739 state->client_princ = *(state->request->client);
740 /* The realm is always canonicalized */
741 state->client_princ.realm = state->client->princ->realm;
743 state->enc_tkt_reply.client = &state->client_princ;
744 state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
745 state->enc_tkt_reply.transited.tr_contents = empty_string;
747 if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) {
748 setflag(state->enc_tkt_reply.flags, TKT_FLG_INVALID);
749 state->enc_tkt_reply.times.starttime = state->request->from;
751 state->enc_tkt_reply.times.starttime = state->kdc_time;
753 kdc_get_ticket_endtime(kdc_active_realm,
754 state->enc_tkt_reply.times.starttime,
755 kdc_infinity, state->request->till, state->client,
756 state->server, &state->enc_tkt_reply.times.endtime);
758 kdc_get_ticket_renewtime(kdc_active_realm, state->request, NULL,
759 state->client, state->server,
760 &state->enc_tkt_reply);
763 * starttime is optional, and treated as authtime if not present.
764 * so we can nuke it if it matches
766 if (state->enc_tkt_reply.times.starttime ==
767 state->enc_tkt_reply.times.authtime)
768 state->enc_tkt_reply.times.starttime = 0;
770 state->enc_tkt_reply.caddrs = state->request->addresses;
771 state->enc_tkt_reply.authorization_data = 0;
773 /* If anonymous requests are being used, adjust the realm of the client
775 if (isflagset(state->request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) {
776 if (!krb5_principal_compare_any_realm(kdc_context,
777 state->request->client,
778 krb5_anonymous_principal())) {
779 errcode = KRB5KDC_ERR_BADOPTION;
780 /* Anonymous requested but anonymous principal not used.*/
781 state->status = "VALIDATE_ANONYMOUS_PRINCIPAL";
784 krb5_free_principal(kdc_context, state->request->client);
785 state->request->client = NULL;
786 errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
787 &state->request->client);
789 state->status = "COPY_ANONYMOUS_PRINCIPAL";
792 state->enc_tkt_reply.client = state->request->client;
793 setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH);
796 errcode = select_client_key(kdc_context, state->client,
797 state->request->ktype, state->request->nktypes,
798 &state->client_keyblock, &state->client_key);
800 state->status = "DECRYPT_CLIENT_KEY";
803 if (state->client_key != NULL) {
804 state->rock.client_key = state->client_key;
805 state->rock.client_keyblock = &state->client_keyblock;
808 errcode = kdc_fast_read_cookie(kdc_context, state->rstate, state->request,
811 state->status = "READ_COOKIE";
816 * Check the preauthentication if it is there.
818 if (state->request->padata) {
819 check_padata(kdc_context, &state->rock, state->req_pkt,
820 state->request, &state->enc_tkt_reply, &state->pa_context,
821 &state->e_data, &state->typed_e_data, finish_preauth,
824 finish_preauth(state, 0);
828 finish_process_as_req(state, errcode);
831 static krb5_error_code
832 prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request,
833 krb5_db_entry *local_tgt, int error, krb5_pa_data **e_data_in,
834 krb5_boolean typed_e_data, krb5_principal canon_client,
835 krb5_data **response, const char *status)
838 krb5_error_code retval;
839 krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
840 krb5_pa_data **e_data = NULL, *cookie = NULL;
841 kdc_realm_t *kdc_active_realm = rstate->realm_data;
844 if (e_data_in != NULL) {
845 /* Add a PA-FX-COOKIE to e_data_in. e_data is a shallow copy
846 * containing aliases. */
847 for (count = 0; e_data_in[count] != NULL; count++);
848 e_data = calloc(count + 2, sizeof(*e_data));
851 memcpy(e_data, e_data_in, count * sizeof(*e_data));
852 retval = kdc_fast_make_cookie(kdc_context, rstate, local_tgt,
853 request->client, &cookie);
854 e_data[count] = cookie;
857 errpkt.ctime = request->nonce;
860 retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
863 errpkt.error = error;
864 errpkt.server = request->server;
865 errpkt.client = (error == KDC_ERR_WRONG_REALM) ? canon_client :
867 errpkt.text = string2data((char *)status);
869 if (e_data != NULL) {
871 retval = encode_krb5_typed_data(e_data, &e_data_asn1);
873 retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
876 errpkt.e_data = *e_data_asn1;
878 errpkt.e_data = empty_data();
880 retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
881 &errpkt, &fast_edata);
884 if (fast_edata != NULL)
885 errpkt.e_data = *fast_edata;
887 scratch = k5alloc(sizeof(*scratch), &retval);
890 if (kdc_fast_hide_client(rstate) && errpkt.client != NULL)
891 errpkt.client = (krb5_principal)krb5_anonymous_principal();
892 retval = krb5_mk_error(kdc_context, &errpkt, scratch);
900 krb5_free_data(kdc_context, fast_edata);
901 krb5_free_data(kdc_context, e_data_asn1);
905 free(cookie->contents);