2 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 #define MAX_TIME ((time_t)((1U << 31) - 1))
39 #define __attribute__(X)
41 struct kdc_pa_auth_status {
43 const char *auth_details;
47 static krb5_error_code
48 _kdc_audit_auth_status(astgs_request_t r,
49 struct kdc_pa_auth_status *status,
53 krb5_error_code ret = 0;
58 hdb = r->config->db[0];
60 if (hdb && hdb->hdb_auth_status)
61 ret = hdb->hdb_auth_status(r->context,
75 _kdc_fix_time(time_t **t)
81 if(**t == 0) **t = MAX_TIME; /* fix for old clients */
85 realloc_method_data(METHOD_DATA *md)
88 pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
96 static krb5_error_code
97 get_pa_etype_info2(krb5_context context,
98 krb5_kdc_configuration *config,
99 METHOD_DATA *md, Key *ckey,
100 krb5_boolean include_salt);
102 static krb5_error_code
103 set_salt_padata(krb5_context context,
104 krb5_kdc_configuration *config,
105 METHOD_DATA *md, Key *key)
108 return get_pa_etype_info2(context, config, md, key, TRUE);
114 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
116 if (req->padata == NULL)
119 while((size_t)*start < req->padata->len){
121 if(req->padata->val[*start - 1].padata_type == (unsigned)type)
122 return &req->padata->val[*start - 1];
128 * This is a hack to allow predefined weak services, like afs to
129 * still use weak types
133 _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
135 if (principal->name.name_string.len > 0 &&
136 strcmp(principal->name.name_string.val[0], "afs") == 0 &&
137 (etype == (krb5_enctype)ETYPE_DES_CBC_CRC
138 || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
139 || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
146 * Detect if `key' is the using the the precomputed `default_salt'.
150 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
152 if (key->salt == NULL)
154 if (default_salt->salttype != key->salt->type)
156 if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
162 * Detect if `key' is the using the the precomputed `default_salt'
163 * (for des-cbc-crc) or any salt otherwise.
165 * This is for avoiding Kerberos v4 (yes really) keys in AS-REQ as
166 * that salt is strange, and a buggy client will try to use the
167 * principal as the salt and not the returned value.
171 is_good_salt_p(const krb5_salt *default_salt, const Key *key)
173 if (key->key.keytype != (krb5_enctype)ETYPE_DES_CBC_CRC)
175 return is_default_salt_p(default_salt, key);
180 _kdc_is_anon_request(const KDC_REQ *req)
182 const KDC_REQ_BODY *b = &req->req_body;
185 * Versions of Heimdal from 0.9rc1 through 1.50 use bit 14 instead
186 * of 16 for request_anonymous, as indicated in the anonymous draft
187 * prior to version 11. Bit 14 is assigned to S4U2Proxy, but S4U2Proxy
188 * requests are only sent to the TGS and, in any case, would have an
189 * additional ticket present.
191 return b->kdc_options.request_anonymous ||
192 (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
196 * return the first appropriate key of `princ' in `ret_key'. Look for
197 * all the etypes in (`etypes', `len'), stopping as soon as we find
198 * one, but preferring one that has default salt.
200 * XXX This function does way way too much. Split it up!
202 * XXX `etypes' and `len' are always `b->etype.val' and `b->etype.len' -- the
203 * etype list from the KDC-REQ-BODY, which is available here as
204 * `r->req->req_body', so we could just stop having it passed in.
206 * XXX Picking an enctype(s) for PA-ETYPE-INFO* is rather different than
207 * picking an enctype for a ticket's session key. The former is what we do
208 * here when `(flags & KFE_IS_PREAUTH)', the latter otherwise.
212 _kdc_find_etype(astgs_request_t r, uint32_t flags,
213 krb5_enctype *etypes, unsigned len,
214 krb5_enctype *ret_enctype, Key **ret_key,
215 krb5_boolean *ret_default_salt)
217 krb5_boolean use_strongest_session_key;
218 krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
219 krb5_boolean is_tgs = flags & KFE_IS_TGS;
221 krb5_principal request_princ;
224 krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
225 const krb5_enctype *p;
229 if (is_preauth && (flags & KFE_USE_CLIENT) &&
230 r->client->entry.flags.synthetic)
231 return KRB5KDC_ERR_ETYPE_NOSUPP;
233 if ((flags & KFE_USE_CLIENT) && !r->client->entry.flags.synthetic) {
235 request_princ = r->client_princ;
238 request_princ = r->server->entry.principal;
241 use_strongest_session_key =
242 is_preauth ? r->config->preauth_use_strongest_session_key
243 : (is_tgs ? r->config->tgt_use_strongest_session_key :
244 r->config->svc_use_strongest_session_key);
246 /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
247 ret = krb5_get_pw_salt(r->context, request_princ, &def_salt);
251 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
254 * Pick an enctype that is in the intersection of:
256 * - permitted_enctypes (local policy)
257 * - requested enctypes (KDC-REQ-BODY's etype list)
258 * - the client's long-term keys' enctypes
260 * the server's configured etype list
262 * There are two sub-cases:
264 * - use local enctype preference (local policy)
265 * - use the client's preference list
268 if (use_strongest_session_key) {
270 * Pick the strongest key that the KDC, target service, and
271 * client all support, using the local cryptosystem enctype
272 * list in strongest-to-weakest order to drive the search.
274 * This is not what RFC4120 says to do, but it encourages
275 * adoption of stronger enctypes. This doesn't play well with
276 * clients that have multiple Kerberos client implementations
277 * with different supported enctype lists sharing the same ccache.
280 /* drive the search with local supported enctypes list */
281 p = krb5_kerberos_enctypes(r->context);
283 p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
285 if (krb5_enctype_valid(r->context, p[i]) != 0 &&
286 !_kdc_is_weak_exception(princ->entry.principal, p[i]))
289 /* check that the client supports it too */
290 for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
292 if (p[i] != etypes[k])
295 if (!is_preauth && (flags & KFE_USE_CLIENT)) {
297 * It suffices that the client says it supports this
298 * enctype in its KDC-REQ-BODY's etype list, which is what
305 /* check target princ support */
307 if (!(flags & KFE_USE_CLIENT) && princ->entry.etypes) {
309 * Use the etypes list from the server's HDB entry instead
310 * of deriving it from its long-term keys. This allows an
311 * entry to have just one long-term key but record support
312 * for multiple enctypes.
314 for (m = 0; m < princ->entry.etypes->len; m++) {
315 if (p[i] == princ->entry.etypes->val[m]) {
322 * Use the entry's long-term keys as the source of its
323 * supported enctypes, either because we're making
324 * PA-ETYPE-INFO* or because we're selecting a session key
327 while (hdb_next_enctype2key(r->context, &princ->entry, NULL,
329 if (key->key.keyvalue.length == 0) {
330 ret = KRB5KDC_ERR_NULL_KEY;
335 if (is_preauth && ret_key != NULL &&
336 !is_good_salt_p(&def_salt, key))
344 * Pick the first key from the client's enctype list that is
345 * supported by the cryptosystem and by the given principal.
347 * RFC4120 says we SHOULD pick the first _strong_ key from the
348 * client's list... not the first key... If the admin disallows
349 * weak enctypes in krb5.conf and selects this key selection
350 * algorithm, then we get exactly what RFC4120 says.
352 for(i = 0; ret != 0 && i < len; i++) {
354 if (krb5_enctype_valid(r->context, etypes[i]) != 0 &&
355 !_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
360 hdb_next_enctype2key(r->context, &princ->entry, NULL,
361 etypes[i], &key) == 0) {
362 if (key->key.keyvalue.length == 0) {
363 ret = KRB5KDC_ERR_NULL_KEY;
368 if (is_preauth && ret_key != NULL &&
369 !is_good_salt_p(&def_salt, key))
375 if (enctype == (krb5_enctype)ETYPE_NULL) {
377 * if the service principal is one for which there is a known 1DES
378 * exception and no other enctype matches both the client request and
379 * the service key list, provide a DES-CBC-CRC key.
381 if (ret_key == NULL &&
382 _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
384 enctype = ETYPE_DES_CBC_CRC;
386 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
391 if (ret_enctype != NULL)
392 *ret_enctype = enctype;
395 if (ret_default_salt != NULL)
396 *ret_default_salt = is_default_salt_p(&def_salt, key);
399 krb5_free_salt (r->context, def_salt);
404 _kdc_make_anonymous_principalname (PrincipalName *pn)
406 pn->name_type = KRB5_NT_WELLKNOWN;
407 pn->name_string.len = 2;
408 pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
409 if (pn->name_string.val == NULL)
412 pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
413 if (pn->name_string.val[0] == NULL)
416 pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
417 if (pn->name_string.val[1] == NULL)
423 free_PrincipalName(pn);
425 pn->name_type = KRB5_NT_UNKNOWN;
426 pn->name_string.len = 0;
427 pn->name_string.val = NULL;
433 _kdc_r_log(astgs_request_t r, int level, const char *fmt, ...)
434 __attribute__ ((__format__ (__printf__, 3, 4)))
439 s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
445 _kdc_set_const_e_text(astgs_request_t r, const char *e_text)
447 /* We should never see this */
449 kdc_log(r->context, r->config, 1,
450 "trying to replace e-text \"%s\" with \"%s\"\n",
456 kdc_log(r->context, r->config, 4, "%s", e_text);
460 _kdc_set_e_text(astgs_request_t r, const char *fmt, ...)
461 __attribute__ ((__format__ (__printf__, 2, 3)))
468 vasprintf_ret = vasprintf(&e_text, fmt, ap);
471 if (vasprintf_ret < 0 || !e_text) {
472 /* not much else to do... */
473 kdc_log(r->context, r->config, 1,
474 "Could not set e_text: %s (out of memory)", fmt);
478 /* We should never see this */
480 kdc_log(r->context, r->config, 1, "trying to replace e-text: %s\n",
487 r->e_text_buf = e_text;
488 kdc_log(r->context, r->config, 4, "%s", e_text);
492 _kdc_log_timestamp(astgs_request_t r, const char *type,
493 KerberosTime authtime, KerberosTime *starttime,
494 KerberosTime endtime, KerberosTime *renew_till)
496 krb5_kdc_configuration *config = r->config;
497 char authtime_str[100], starttime_str[100],
498 endtime_str[100], renewtime_str[100];
501 _kdc_audit_addkv((kdc_request_t)r, 0, "auth", "%ld", (long)authtime);
502 if (starttime && *starttime)
503 _kdc_audit_addkv((kdc_request_t)r, 0, "start", "%ld",
506 _kdc_audit_addkv((kdc_request_t)r, 0, "end", "%ld", (long)endtime);
507 if (renew_till && *renew_till)
508 _kdc_audit_addkv((kdc_request_t)r, 0, "renew", "%ld",
511 krb5_format_time(r->context, authtime,
512 authtime_str, sizeof(authtime_str), TRUE);
514 krb5_format_time(r->context, *starttime,
515 starttime_str, sizeof(starttime_str), TRUE);
517 strlcpy(starttime_str, "unset", sizeof(starttime_str));
518 krb5_format_time(r->context, endtime,
519 endtime_str, sizeof(endtime_str), TRUE);
521 krb5_format_time(r->context, *renew_till,
522 renewtime_str, sizeof(renewtime_str), TRUE);
524 strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
526 kdc_log(r->context, config, 4,
527 "%s authtime: %s starttime: %s endtime: %s renew till: %s",
528 type, authtime_str, starttime_str, endtime_str, renewtime_str);
537 static krb5_error_code
538 pa_pkinit_validate(astgs_request_t r,
540 struct kdc_pa_auth_status *auth_status)
542 pk_client_params *pkp = NULL;
543 char *client_cert = NULL;
546 ret = _kdc_pk_rd_padata(r, pa, &pkp);
547 if (ret || pkp == NULL) {
548 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
549 _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
551 auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE;
555 ret = _kdc_pk_check_client(r, pkp, &client_cert);
557 _kdc_set_e_text(r, "PKINIT certificate not allowed to "
558 "impersonate principal");
559 auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE;
562 auth_status->auth_details = client_cert;
563 auth_status->free_ptr = client_cert;
565 r->pa_endtime = _kdc_pk_endtime(pkp);
566 if (!r->client->entry.flags.synthetic)
567 r->pa_max_life = _kdc_pk_max_life(pkp);
569 _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
570 r->cname, client_cert);
572 ret = _kdc_pk_mk_pa_reply(r, pkp);
574 _kdc_set_e_text(r, "Failed to build PK-INIT reply");
577 ret = _kdc_add_initial_verified_cas(r->context, r->config,
580 auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_SUCCESS;
583 _kdc_pk_free_client_param(r->context, pkp);
590 static krb5_error_code
591 pa_gss_validate(astgs_request_t r,
593 struct kdc_pa_auth_status *auth_status)
595 gss_client_params *gcp = NULL;
596 char *client_name = NULL;
600 ret = _kdc_gss_rd_padata(r, pa, &gcp, &open);
601 if (ret && gcp == NULL)
605 ret = _kdc_gss_check_client(r, gcp, &client_name);
607 _kdc_set_e_text(r, "GSS-API client not allowed to "
608 "impersonate principal");
609 auth_status->auth_status = HDB_AUTHSTATUS_GSS_FAILURE;
612 auth_status->auth_details = client_name;
613 auth_status->free_ptr = client_name;
615 r->pa_endtime = _kdc_gss_endtime(r, gcp);
617 _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s",
618 r->cname, client_name);
620 ret = _kdc_gss_mk_composite_name_ad(r, gcp);
622 _kdc_set_e_text(r, "Failed to build GSS authorization data");
627 ret = _kdc_gss_mk_pa_reply(r, gcp);
629 if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
630 _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply");
635 auth_status->auth_status = HDB_AUTHSTATUS_GSS_SUCCESS;
637 heim_assert(r->pa_state == NULL, "already have PA state, should be NULL");
638 r->pa_state = (struct as_request_pa_state *)gcp;
643 _kdc_gss_free_client_param(r, gcp);
648 static krb5_error_code
649 pa_gss_finalize_pac(astgs_request_t r)
651 gss_client_params *gcp = (gss_client_params *)r->pa_state;
653 heim_assert(gcp != NULL, "invalid GSS-API client params");
655 return _kdc_gss_finalize_pac(r, gcp);
659 pa_gss_cleanup(astgs_request_t r)
661 gss_client_params *gcp = (gss_client_params *)r->pa_state;
664 _kdc_gss_free_client_param(r, gcp);
669 static krb5_error_code
670 pa_enc_chal_validate(astgs_request_t r,
672 struct kdc_pa_auth_status *auth_status)
674 krb5_data pepper1, pepper2;
675 int invalidPassword = 0;
676 EncryptedData enc_data;
677 krb5_enctype aenctype;
683 heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
685 if (_kdc_is_anon_request(&r->req)) {
686 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
687 kdc_log(r->context, r->config, 4, "ENC-CHALL doesn't support anon");
691 if (r->client->entry.flags.locked_out) {
692 ret = KRB5KDC_ERR_CLIENT_REVOKED;
693 kdc_log(r->context, r->config, 0,
694 "Client (%s) is locked out", r->cname);
695 auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT;
699 ret = decode_EncryptedData(pa->padata_value.data,
700 pa->padata_value.length,
704 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
705 _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
710 pepper1.data = "clientchallengearmor";
711 pepper1.length = strlen(pepper1.data);
712 pepper2.data = "challengelongterm";
713 pepper2.length = strlen(pepper2.data);
715 krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
717 kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
719 for (i = 0; i < r->client->entry.keys.len; i++) {
720 krb5_crypto challengecrypto, longtermcrypto;
721 krb5_keyblock challengekey;
723 k = &r->client->entry.keys.val[i];
725 ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
729 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
730 &pepper1, &pepper2, aenctype,
733 krb5_crypto_destroy(r->context, longtermcrypto);
737 ret = krb5_crypto_init(r->context, &challengekey, 0,
739 krb5_free_keyblock_contents(r->context, &challengekey);
741 krb5_crypto_destroy(r->context, longtermcrypto);
745 ret = _krb5_validate_pa_enc_challenge(r->context,
747 KRB5_KU_ENC_CHALLENGE_CLIENT,
750 krb5_crypto_destroy(r->context, challengecrypto);
753 krb5_error_code ret2;
756 krb5_crypto_destroy(r->context, longtermcrypto);
758 invalidPassword = (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY);
759 if (!invalidPassword) {
763 ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
766 msg = krb5_get_error_message(r->context, ret);
767 _kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
768 "(enctype %s) error %s",
769 r->cname, str ? str : "unknown enctype", msg);
770 krb5_free_error_message(r->context, msg);
777 * Found a key that the client used, lets pick that as the reply key
780 krb5_free_keyblock_contents(r->context, &r->reply_key);
781 ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
783 krb5_crypto_destroy(r->context, longtermcrypto);
787 krb5_free_keyblock_contents(r->context, &challengekey);
790 * Provide KDC authentication to the client, uses a different
791 * challenge key (different pepper).
794 pepper1.data = "kdcchallengearmor";
795 pepper1.length = strlen(pepper1.data);
797 ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
798 &pepper1, &pepper2, aenctype,
800 krb5_crypto_destroy(r->context, longtermcrypto);
804 ret = krb5_crypto_init(r->context, &challengekey, 0, &challengecrypto);
805 krb5_free_keyblock_contents(r->context, &challengekey);
809 ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
810 KRB5_KU_ENC_CHALLENGE_KDC,
812 krb5_crypto_destroy(r->context, challengecrypto);
816 ret = set_salt_padata(r->context, r->config,
824 auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD;
828 if (invalidPassword) {
829 auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD;
830 ret = KRB5KDC_ERR_PREAUTH_FAILED;
832 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
835 free_EncryptedData(&enc_data);
840 static krb5_error_code
841 pa_enc_ts_validate(astgs_request_t r,
843 struct kdc_pa_auth_status *auth_status)
845 EncryptedData enc_data;
854 if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp) {
855 ret = KRB5KDC_ERR_POLICY;
856 kdc_log(r->context, r->config, 0,
857 "Armored encrypted timestamp pre-authentication is disabled");
859 } else if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp) {
860 ret = KRB5KDC_ERR_POLICY;
861 kdc_log(r->context, r->config, 0,
862 "Unarmored encrypted timestamp pre-authentication is disabled");
866 if (r->client->entry.flags.locked_out) {
867 ret = KRB5KDC_ERR_CLIENT_REVOKED;
868 kdc_log(r->context, r->config, 0,
869 "Client (%s) is locked out", r->cname);
870 auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT;
874 ret = decode_EncryptedData(pa->padata_value.data,
875 pa->padata_value.length,
879 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
880 _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
885 ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
886 enc_data.etype, &pa_key);
889 _kdc_set_e_text(r, "No key matching entype");
890 ret = KRB5KDC_ERR_ETYPE_NOSUPP;
891 if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
895 "No client key matching pa-data (%d) -- %s",
896 enc_data.etype, r->cname);
899 "No client key matching pa-data (%s) -- %s",
902 free_EncryptedData(&enc_data);
907 ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
909 const char *msg = krb5_get_error_message(r->context, ret);
910 _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
911 krb5_free_error_message(r->context, msg);
912 free_EncryptedData(&enc_data);
916 ret = krb5_decrypt_EncryptedData (r->context,
918 KRB5_KU_PA_ENC_TIMESTAMP,
921 krb5_crypto_destroy(r->context, crypto);
923 * Since the user might have several keys with the same
924 * enctype but with diffrent salting, we need to try all
925 * the keys with the same enctype.
928 krb5_error_code ret2;
929 const char *msg = krb5_get_error_message(r->context, ret);
931 ret2 = krb5_enctype_to_string(r->context,
932 pa_key->key.keytype, &str);
935 _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
936 "(enctype %s) error %s",
937 r->cname, str ? str : "unknown enctype", msg);
938 krb5_free_error_message(r->context, msg);
940 free(auth_status->free_ptr);
941 auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD;
942 auth_status->auth_details = str ? str : "unknown enctype";
943 auth_status->free_ptr = str;
945 if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
946 enc_data.etype, &pa_key) == 0)
949 free_EncryptedData(&enc_data);
951 ret = KRB5KDC_ERR_PREAUTH_FAILED;
954 free_EncryptedData(&enc_data);
955 free(auth_status->free_ptr);
956 auth_status->auth_status = HDB_AUTHSTATUS_INVALID;
957 auth_status->auth_details = NULL;
958 auth_status->free_ptr = NULL;
959 ret = decode_PA_ENC_TS_ENC(ts_data.data,
963 krb5_data_free(&ts_data);
965 ret = KRB5KDC_ERR_PREAUTH_FAILED;
966 _kdc_r_log(r, 4, "Failed to decode PA-ENC-TS_ENC -- %s",
970 if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
971 char client_time[100];
973 krb5_format_time(r->context, p.patimestamp,
974 client_time, sizeof(client_time), TRUE);
976 ret = KRB5KRB_AP_ERR_SKEW;
977 _kdc_r_log(r, 4, "Too large time skew, "
978 "client time %s is out by %u > %u seconds -- %s",
980 (unsigned)labs(kdc_time - p.patimestamp),
981 r->context->max_skew,
983 auth_status->auth_details = "AP_ERR_SKEW";
986 * The following is needed to make windows clients to
987 * retry using the timestamp in the error message, if
988 * there is a e_text, they become unhappy.
991 free_PA_ENC_TS_ENC(&p);
994 free_PA_ENC_TS_ENC(&p);
996 ret = set_salt_padata(r->context, r->config,
997 r->rep.padata, pa_key);
1001 ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
1005 ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
1008 _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
1009 r->cname, str ? str : "unknown enctype");
1010 _kdc_audit_addkv((kdc_request_t)r, 0, "pa-etype", "%d",
1011 (int)pa_key->key.keytype);
1012 auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD;
1013 auth_status->auth_details = str ? str : "unknown enctype";
1014 auth_status->free_ptr = str;
1023 struct kdc_patypes {
1027 #define PA_ANNOUNCE 1
1028 #define PA_REQ_FAST 2 /* only use inside fast */
1029 #define PA_SYNTHETIC_OK 4
1030 #define PA_REPLACE_REPLY_KEY 8 /* PA mech replaces reply key */
1031 #define PA_USES_LONG_TERM_KEY 16 /* PA mech uses client's long-term key */
1032 krb5_error_code (*validate)(astgs_request_t,
1034 struct kdc_pa_auth_status *auth_status);
1035 krb5_error_code (*finalize_pac)(astgs_request_t r);
1036 void (*cleanup)(astgs_request_t r);
1039 static const struct kdc_patypes pat[] = {
1042 KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)",
1043 PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1044 pa_pkinit_validate, NULL, NULL
1047 KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE | PA_REPLACE_REPLY_KEY,
1048 pa_pkinit_validate, NULL, NULL
1051 KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
1055 { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL , NULL, NULL },
1056 { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL, NULL, NULL },
1057 { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL, NULL, NULL },
1059 { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL, NULL, NULL },
1061 KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
1062 PA_ANNOUNCE | PA_USES_LONG_TERM_KEY,
1063 pa_enc_ts_validate, NULL, NULL
1066 KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
1067 PA_ANNOUNCE | PA_USES_LONG_TERM_KEY | PA_REQ_FAST,
1068 pa_enc_chal_validate, NULL, NULL
1070 { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL, NULL, NULL },
1071 { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL, NULL, NULL },
1072 { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL, NULL, NULL },
1073 { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL, NULL, NULL },
1075 KRB5_PADATA_GSS , "GSS",
1076 PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
1077 pa_gss_validate, pa_gss_finalize_pac, pa_gss_cleanup
1082 log_patypes(astgs_request_t r, METHOD_DATA *padata)
1084 krb5_kdc_configuration *config = r->config;
1085 struct rk_strpool *p = NULL;
1089 for (n = 0; n < padata->len; n++) {
1090 for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
1091 if (padata->val[n].padata_type == pat[m].type) {
1092 p = rk_strpoolprintf(p, "%s", pat[m].name);
1096 if (m == sizeof(pat) / sizeof(pat[0]))
1097 p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
1098 if (p && n + 1 < padata->len)
1099 p = rk_strpoolprintf(p, ", ");
1101 kdc_log(r->context, config, 1, "out of memory");
1106 p = rk_strpoolprintf(p, "none");
1108 str = rk_strpoolcollect(p);
1109 kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
1110 _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1111 "client-pa", "%s", str);
1116 pa_used_flag_isset(astgs_request_t r, unsigned int flag)
1118 if (r->pa_used == NULL)
1121 return (r->pa_used->flags & flag) == flag;
1129 _kdc_encode_reply(krb5_context context,
1130 krb5_kdc_configuration *config,
1131 astgs_request_t r, uint32_t nonce,
1133 int skvno, const EncryptionKey *skey,
1141 krb5_error_code ret;
1143 KDC_REP *rep = &r->rep;
1144 EncTicketPart *et = &r->et;
1145 EncKDCRepPart *ek = &r->ek;
1147 heim_assert(rep->padata != NULL, "reply padata uninitialized");
1149 ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
1151 const char *msg = krb5_get_error_message(context, ret);
1152 kdc_log(context, config, 4, "Failed to encode ticket: %s", msg);
1153 krb5_free_error_message(context, msg);
1157 krb5_abortx(context, "Internal error in ASN.1 encoder");
1159 ret = krb5_crypto_init(context, skey, etype, &crypto);
1161 const char *msg = krb5_get_error_message(context, ret);
1162 kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1163 krb5_free_error_message(context, msg);
1168 ret = krb5_encrypt_EncryptedData(context,
1174 &rep->ticket.enc_part);
1176 krb5_crypto_destroy(context, crypto);
1178 const char *msg = krb5_get_error_message(context, ret);
1179 kdc_log(context, config, 4, "Failed to encrypt data: %s", msg);
1180 krb5_free_error_message(context, msg);
1184 if (r && r->armor_crypto) {
1185 KrbFastFinished finished;
1188 kdc_log(context, config, 4, "FAST armor protection");
1190 memset(&finished, 0, sizeof(finished));
1191 krb5_data_zero(&data);
1193 finished.timestamp = kdc_time;
1195 finished.crealm = et->crealm;
1196 finished.cname = et->cname;
1198 ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
1199 &rep->ticket, &len, ret);
1202 if (data.length != len)
1203 krb5_abortx(context, "internal asn.1 error");
1205 ret = krb5_create_checksum(context, r->armor_crypto,
1206 KRB5_KU_FAST_FINISHED, 0,
1207 data.data, data.length,
1208 &finished.ticket_checksum);
1209 krb5_data_free(&data);
1213 ret = _kdc_fast_mk_response(context, r->armor_crypto,
1214 rep->padata, &r->strengthen_key, &finished,
1216 free_Checksum(&finished.ticket_checksum);
1220 free_METHOD_DATA(r->rep.padata);
1222 ret = krb5_padata_add(context, rep->padata,
1223 KRB5_PADATA_FX_FAST,
1224 data.data, data.length);
1229 * Hide client name for privacy reasons
1231 if (r->fast.flags.requested_hidden_names) {
1232 Realm anon_realm = KRB5_ANON_REALM;
1234 free_Realm(&rep->crealm);
1235 ret = copy_Realm(&anon_realm, &rep->crealm);
1237 free_PrincipalName(&rep->cname);
1238 ret = _kdc_make_anonymous_principalname(&rep->cname);
1245 if (rep->padata->len == 0) {
1246 free_METHOD_DATA(rep->padata);
1251 if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
1252 ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
1254 ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
1256 const char *msg = krb5_get_error_message(context, ret);
1257 kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1258 krb5_free_error_message(context, msg);
1261 if(buf_size != len) {
1263 kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1264 _kdc_set_e_text(r, "KDC internal error");
1265 return KRB5KRB_ERR_GENERIC;
1267 ret = krb5_crypto_init(context, &r->reply_key, 0, &crypto);
1269 const char *msg = krb5_get_error_message(context, ret);
1271 kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
1272 krb5_free_error_message(context, msg);
1275 if(rep->msg_type == krb_as_rep) {
1276 krb5_encrypt_EncryptedData(context,
1278 KRB5_KU_AS_REP_ENC_PART,
1284 ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1286 krb5_encrypt_EncryptedData(context,
1288 rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1294 ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1296 krb5_crypto_destroy(context, crypto);
1298 const char *msg = krb5_get_error_message(context, ret);
1299 kdc_log(context, config, 4, "Failed to encode KDC-REP: %s", msg);
1300 krb5_free_error_message(context, msg);
1303 if(buf_size != len) {
1305 kdc_log(context, config, 4, "Internal error in ASN.1 encoder");
1306 _kdc_set_e_text(r, "KDC internal error");
1307 return KRB5KRB_ERR_GENERIC;
1310 reply->length = buf_size;
1318 static krb5_error_code
1319 make_etype_info_entry(krb5_context context,
1320 ETYPE_INFO_ENTRY *ent,
1322 krb5_boolean include_salt)
1324 ent->etype = key->key.keytype;
1325 if (key->salt && include_salt){
1327 ALLOC(ent->salttype);
1329 if(key->salt->type == hdb_pw_salt)
1330 *ent->salttype = 0; /* or 1? or NULL? */
1331 else if(key->salt->type == hdb_afs3_salt)
1334 kdc_log(context, config, 4, "unknown salt-type: %d",
1336 return KRB5KRB_ERR_GENERIC;
1338 /* according to `the specs', we can't send a salt if
1339 we have AFS3 salted key, but that requires that you
1340 *know* what cell you are using (e.g by assuming
1341 that the cell is the same as the realm in lower
1344 ALLOC(ent->salttype);
1345 *ent->salttype = key->salt->type;
1348 * We shouldn't sent salttype since it is incompatible with the
1349 * specification and it breaks windows clients. The afs
1350 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
1351 * implemented in Heimdal 0.7 and later.
1353 ent->salttype = NULL;
1355 krb5_copy_data(context, &key->salt->salt,
1358 /* we return no salt type at all, as that should indicate
1359 * the default salt type and make everybody happy. some
1360 * systems (like w2k) dislike being told the salt type
1363 ent->salttype = NULL;
1369 static krb5_error_code
1370 get_pa_etype_info(krb5_context context,
1371 krb5_kdc_configuration *config,
1372 METHOD_DATA *md, Key *ckey,
1373 krb5_boolean include_salt)
1375 krb5_error_code ret = 0;
1382 pa.val = calloc(1, sizeof(pa.val[0]));
1386 ret = make_etype_info_entry(context, &pa.val[0], ckey, include_salt);
1388 free_ETYPE_INFO(&pa);
1392 ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
1393 free_ETYPE_INFO(&pa);
1396 ret = realloc_method_data(md);
1401 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
1402 md->val[md->len - 1].padata_value.length = len;
1403 md->val[md->len - 1].padata_value.data = buf;
1411 extern int _krb5_AES_SHA1_string_to_default_iterator;
1412 extern int _krb5_AES_SHA2_string_to_default_iterator;
1414 static krb5_error_code
1415 make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1417 krb5_data *s2kparams;
1418 krb5_error_code ret;
1421 if (s2kparams == NULL)
1423 ret = krb5_data_alloc(s2kparams, len);
1428 _krb5_put_int(s2kparams->data, value, len);
1429 *ps2kparams = s2kparams;
1433 static krb5_error_code
1434 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent,
1436 krb5_boolean include_salt)
1438 krb5_error_code ret;
1440 ent->etype = key->key.keytype;
1441 if (key->salt && include_salt) {
1443 if (ent->salt == NULL)
1445 *ent->salt = malloc(key->salt->salt.length + 1);
1446 if (*ent->salt == NULL) {
1451 memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1452 (*ent->salt)[key->salt->salt.length] = '\0';
1456 ent->s2kparams = NULL;
1458 switch (key->key.keytype) {
1459 case ETYPE_AES128_CTS_HMAC_SHA1_96:
1460 case ETYPE_AES256_CTS_HMAC_SHA1_96:
1461 ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1462 4, &ent->s2kparams);
1464 case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1465 case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1466 ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1467 4, &ent->s2kparams);
1469 case ETYPE_DES_CBC_CRC:
1470 case ETYPE_DES_CBC_MD4:
1471 case ETYPE_DES_CBC_MD5:
1472 /* Check if this was a AFS3 salted key */
1473 if(key->salt && key->salt->type == hdb_afs3_salt)
1474 ret = make_s2kparams(1, 1, &ent->s2kparams);
1486 * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1487 * database (client supported enctypes first, then the unsupported
1491 static krb5_error_code
1492 get_pa_etype_info2(krb5_context context,
1493 krb5_kdc_configuration *config,
1494 METHOD_DATA *md, Key *ckey,
1495 krb5_boolean include_salt)
1497 krb5_error_code ret = 0;
1503 pa.val = calloc(1, sizeof(pa.val[0]));
1507 ret = make_etype_info2_entry(&pa.val[0], ckey, include_salt);
1509 free_ETYPE_INFO2(&pa);
1513 ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1514 free_ETYPE_INFO2(&pa);
1517 ret = realloc_method_data(md);
1522 md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1523 md->val[md->len - 1].padata_value.length = len;
1524 md->val[md->len - 1].padata_value.data = buf;
1529 * Return 0 if the client have only older enctypes, this is for
1530 * determining if the server should send ETYPE_INFO2 or not.
1534 newer_enctype_present(krb5_context context,
1535 struct KDC_REQ_BODY_etype *etype_list)
1539 for (i = 0; i < etype_list->len; i++) {
1540 if (!krb5_is_enctype_old(context, etype_list->val[i]))
1546 static krb5_error_code
1547 get_pa_etype_info_both(krb5_context context,
1548 krb5_kdc_configuration *config,
1549 struct KDC_REQ_BODY_etype *etype_list,
1550 METHOD_DATA *md, Key *ckey,
1551 krb5_boolean include_salt)
1553 krb5_error_code ret;
1556 * Windows 2019 (and earlier versions) always sends the salt
1557 * and Samba has testsuites that check this behaviour, so a
1558 * Samba AD DC will set this flag to match the AS-REP packet
1561 if (config->force_include_pa_etype_salt)
1562 include_salt = TRUE;
1566 * When the AS server is to include pre-authentication data in a
1567 * KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not
1568 * PA-ETYPE-INFO, if the etype field of the client's AS-REQ lists
1569 * at least one "newer" encryption type. Otherwise (when the etype
1570 * field of the client's AS-REQ does not list any "newer" encryption
1571 * types), it MUST send both PA-ETYPE-INFO2 and PA-ETYPE-INFO (both
1572 * with an entry for each enctype). A "newer" enctype is any enctype
1573 * first officially specified concurrently with or subsequent to the
1574 * issue of this RFC. The enctypes DES, 3DES, or RC4 and any defined
1575 * in [RFC1510] are not "newer" enctypes.
1577 * It goes on to state:
1578 * The preferred ordering of the "hint" pre-authentication data that
1579 * affect client key selection is: ETYPE-INFO2, followed by ETYPE-INFO,
1580 * followed by PW-SALT. As noted in Section 3.1.3, a KDC MUST NOT send
1581 * ETYPE-INFO or PW-SALT when the client's AS-REQ includes at least one
1585 ret = get_pa_etype_info2(context, config, md, ckey, include_salt);
1589 if (!newer_enctype_present(context, etype_list))
1590 ret = get_pa_etype_info(context, config, md, ckey, include_salt);
1600 _log_astgs_req(astgs_request_t r, krb5_enctype setype)
1602 const KDC_REQ_BODY *b = &r->req.req_body;
1603 krb5_enctype cetype = r->reply_key.keytype;
1604 krb5_error_code ret;
1605 struct rk_strpool *p;
1606 struct rk_strpool *s = NULL;
1613 * we are collecting ``p'' and ``s''. The former is a textual
1614 * representation of the enctypes as strings which will be used
1615 * for debugging. The latter is a terse comma separated list of
1616 * the %d's of the enctypes to emit into our audit trail to
1617 * conserve space in the logs.
1620 p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1622 for (i = 0; i < b->etype.len; i++) {
1623 ret = krb5_enctype_to_string(r->context, b->etype.val[i], &str);
1625 p = rk_strpoolprintf(p, "%s", str);
1628 p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1631 _kdc_r_log(r, 4, "out of memory");
1634 s = rk_strpoolprintf(s, "%d", b->etype.val[i]);
1635 if (i + 1 < b->etype.len) {
1636 p = rk_strpoolprintf(p, ", ");
1637 s = rk_strpoolprintf(s, ",");
1641 p = rk_strpoolprintf(p, "no encryption types");
1643 str = rk_strpoolcollect(s);
1645 _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
1649 ret = krb5_enctype_to_string(r->context, cetype, &cet);
1651 ret = krb5_enctype_to_string(r->context, setype, &set);
1653 p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1659 p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1662 str = rk_strpoolcollect(p);
1664 _kdc_r_log(r, 4, "%s", str);
1667 _kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
1673 result = unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1674 fixedstr, sizeof(fixedstr));
1676 _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
1677 _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
1678 "flags", "%s", fixedstr);
1684 * verify the flags on `client' and `server', returning 0
1685 * if they are OK and generating an error messages and returning
1686 * and error code otherwise.
1690 kdc_check_flags(astgs_request_t r,
1691 krb5_boolean is_as_req,
1692 hdb_entry_ex *client_ex,
1693 hdb_entry_ex *server_ex)
1695 if (client_ex != NULL) {
1696 hdb_entry *client = &client_ex->entry;
1699 if (client->flags.locked_out) {
1700 _kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
1701 return KRB5KDC_ERR_CLIENT_REVOKED;
1704 if (client->flags.invalid) {
1705 _kdc_audit_addreason((kdc_request_t)r,
1706 "Client has invalid bit set");
1707 return KRB5KDC_ERR_POLICY;
1710 if (!client->flags.client) {
1711 _kdc_audit_addreason((kdc_request_t)r,
1712 "Principal may not act as client");
1713 return KRB5KDC_ERR_POLICY;
1716 if (client->valid_start && *client->valid_start > kdc_time) {
1717 char starttime_str[100];
1718 krb5_format_time(r->context, *client->valid_start,
1719 starttime_str, sizeof(starttime_str), TRUE);
1720 _kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
1721 "until %s", starttime_str);
1722 return KRB5KDC_ERR_CLIENT_NOTYET;
1725 if (client->valid_end && *client->valid_end < kdc_time) {
1726 char endtime_str[100];
1727 krb5_format_time(r->context, *client->valid_end,
1728 endtime_str, sizeof(endtime_str), TRUE);
1729 _kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
1731 return KRB5KDC_ERR_NAME_EXP;
1734 if (client->flags.require_pwchange &&
1735 (server_ex == NULL || !server_ex->entry.flags.change_pw))
1736 return KRB5KDC_ERR_KEY_EXPIRED;
1738 if (client->pw_end && *client->pw_end < kdc_time
1739 && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1740 char pwend_str[100];
1741 krb5_format_time(r->context, *client->pw_end,
1742 pwend_str, sizeof(pwend_str), TRUE);
1743 _kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
1744 "at %s", pwend_str);
1745 return KRB5KDC_ERR_KEY_EXPIRED;
1751 if (server_ex != NULL) {
1752 hdb_entry *server = &server_ex->entry;
1754 if (server->flags.locked_out) {
1755 _kdc_audit_addreason((kdc_request_t)r, "Server locked out");
1756 return KRB5KDC_ERR_SERVICE_REVOKED;
1758 if (server->flags.invalid) {
1759 _kdc_audit_addreason((kdc_request_t)r,
1760 "Server has invalid flag set");
1761 return KRB5KDC_ERR_POLICY;
1763 if (!server->flags.server) {
1764 _kdc_audit_addreason((kdc_request_t)r,
1765 "Principal may not act as server");
1766 return KRB5KDC_ERR_POLICY;
1769 if (!is_as_req && server->flags.initial) {
1770 _kdc_audit_addreason((kdc_request_t)r,
1771 "AS-REQ is required for server");
1772 return KRB5KDC_ERR_POLICY;
1775 if (server->valid_start && *server->valid_start > kdc_time) {
1776 char starttime_str[100];
1777 krb5_format_time(r->context, *server->valid_start,
1778 starttime_str, sizeof(starttime_str), TRUE);
1779 _kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
1780 "until %s", starttime_str);
1781 return KRB5KDC_ERR_SERVICE_NOTYET;
1784 if (server->valid_end && *server->valid_end < kdc_time) {
1785 char endtime_str[100];
1786 krb5_format_time(r->context, *server->valid_end,
1787 endtime_str, sizeof(endtime_str), TRUE);
1788 _kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
1790 return KRB5KDC_ERR_SERVICE_EXP;
1793 if (server->pw_end && *server->pw_end < kdc_time) {
1794 char pwend_str[100];
1795 krb5_format_time(r->context, *server->pw_end,
1796 pwend_str, sizeof(pwend_str), TRUE);
1797 _kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
1798 "at %s", pwend_str);
1799 return KRB5KDC_ERR_KEY_EXPIRED;
1806 * Return TRUE if `from' is part of `addresses' taking into consideration
1807 * the configuration variables that tells us how strict we should be about
1812 _kdc_check_addresses(astgs_request_t r, HostAddresses *addresses,
1813 const struct sockaddr *from)
1815 krb5_kdc_configuration *config = r->config;
1816 krb5_error_code ret;
1818 krb5_boolean result;
1819 krb5_boolean only_netbios = TRUE;
1822 if (!config->check_ticket_addresses && !config->warn_ticket_addresses)
1826 * Fields of HostAddresses type are always OPTIONAL and should be non-
1827 * empty, but we check for empty just in case as our compiler doesn't
1828 * support size constraints on SEQUENCE OF.
1830 if (addresses == NULL || addresses->len == 0)
1831 return config->allow_null_ticket_addresses;
1833 for (i = 0; i < addresses->len; ++i) {
1834 if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
1835 only_netbios = FALSE;
1839 /* Windows sends it's netbios name, which I can only assume is
1840 * used for the 'allowed workstations' check. This is painful,
1841 * but we still want to check IP addresses if they happen to be
1846 return config->allow_null_ticket_addresses;
1848 ret = krb5_sockaddr2address (r->context, from, &addr);
1852 result = krb5_address_search(r->context, &addr, addresses);
1853 krb5_free_address (r->context, &addr);
1861 _kdc_check_anon_policy(astgs_request_t r)
1863 if (!r->config->allow_anonymous) {
1864 _kdc_audit_addreason((kdc_request_t)r,
1865 "Anonymous tickets denied by local policy");
1866 return KRB5KDC_ERR_POLICY;
1873 * Determine whether the client requested a PAC be included
1874 * or excluded explictly, or whether it doesn't care.
1878 get_pac_attributes(krb5_context context, KDC_REQ *req)
1880 krb5_error_code ret;
1881 PA_PAC_REQUEST pacreq;
1884 uint32_t pac_attributes;
1886 pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
1888 return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
1890 ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
1891 pa->padata_value.length,
1895 return KRB5_PAC_WAS_GIVEN_IMPLICITLY;
1897 pac_attributes = pacreq.include_pac ? KRB5_PAC_WAS_REQUESTED : 0;
1898 free_PA_PAC_REQUEST(&pacreq);
1899 return pac_attributes;
1906 static krb5_error_code
1907 generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
1908 krb5_boolean is_tgs)
1910 krb5_error_code ret;
1913 krb5_principal client;
1914 krb5_const_principal canon_princ = NULL;
1916 r->pac_attributes = get_pac_attributes(r->context, &r->req);
1917 _kdc_audit_addkv((kdc_request_t)r, 0, "pac_attributes", "%lx",
1918 (long)r->pac_attributes);
1920 if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
1924 * When a PA mech does not use the client's long-term key, the PAC
1925 * may include the client's long-term key (encrypted in the reply key)
1926 * for use by other shared secret authentication protocols, e.g. NTLM.
1927 * Validate a PA mech was actually used before doing this.
1930 ret = _kdc_pac_generate(r->context,
1933 r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY)
1934 ? &r->reply_key : NULL,
1938 _kdc_r_log(r, 4, "PAC generation failed for -- %s",
1945 rodc_id = r->server->entry.kvno >> 16;
1947 /* libkrb5 expects ticket and PAC client names to match */
1948 ret = _krb5_principalname2krb5_principal(r->context, &client,
1949 r->et.cname, r->et.crealm);
1954 * Include the canonical name of the principal in the authorization
1955 * data, if the realms match (if they don't, then the KDC could
1956 * impersonate any realm. Windows always canonicalizes the realm,
1957 * but Heimdal permits aliases between realms.)
1959 if (krb5_realm_compare(r->context, client, r->client->entry.principal)) {
1962 canon_princ = r->client->entry.principal;
1964 krb5_unparse_name(r->context, canon_princ, &cpn);
1965 _kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
1966 cpn ? cpn : "<unknown>");
1970 if (r->pa_used && r->pa_used->finalize_pac) {
1971 ret = r->pa_used->finalize_pac(r);
1976 ret = _krb5_pac_sign(r->context,
1980 &skey->key, /* Server key */
1981 &tkey->key, /* TGS key */
1985 is_tgs ? &r->pac_attributes : NULL,
1987 krb5_free_principal(r->context, client);
1988 krb5_pac_free(r->context, r->pac);
1991 _kdc_r_log(r, 4, "PAC signing failed for -- %s",
1996 ret = _kdc_tkt_insert_pac(r->context, &r->et, &data);
1997 krb5_data_free(&data);
2007 _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
2009 return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
2013 * Returns TRUE if principal is the unauthenticated anonymous identity,
2014 * i.e. WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Unfortunately due to
2015 * backwards compatibility logic in krb5_principal_is_anonymous() we
2016 * have to use our own implementation.
2020 _kdc_is_anonymous_pkinit(krb5_context context, krb5_const_principal principal)
2022 return _kdc_is_anonymous(context, principal) &&
2023 strcmp(principal->realm, KRB5_ANON_REALM) == 0;
2027 require_preauth_p(astgs_request_t r)
2029 return r->config->require_preauth
2030 || r->client->entry.flags.require_preauth
2031 || r->server->entry.flags.require_preauth;
2039 static krb5_error_code
2040 add_enc_pa_rep(astgs_request_t r)
2042 krb5_error_code ret;
2048 ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
2052 ret = krb5_create_checksum(r->context, crypto,
2054 r->request.data, r->request.length,
2056 krb5_crypto_destroy(r->context, crypto);
2060 ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
2061 &checksum, &len, ret);
2062 free_Checksum(&checksum);
2065 heim_assert(cdata.length == len, "ASN.1 internal error");
2067 if (r->ek.encrypted_pa_data == NULL) {
2068 ALLOC(r->ek.encrypted_pa_data);
2069 if (r->ek.encrypted_pa_data == NULL)
2072 ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2073 KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
2077 return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
2078 KRB5_PADATA_FX_FAST, NULL, 0);
2082 * Add an authorization data element indicating that a synthetic
2083 * principal was used, so that the TGS does not accidentally
2084 * synthesize a non-synthetic principal that has since been deleted.
2086 static krb5_error_code
2087 add_synthetic_princ_ad(astgs_request_t r)
2091 krb5_data_zero(&data);
2093 return _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
2094 KRB5_AUTHDATA_SYNTHETIC_PRINC_USED,
2098 static krb5_error_code
2099 get_local_tgs(krb5_context context,
2100 krb5_kdc_configuration *config,
2101 krb5_const_realm realm,
2102 hdb_entry_ex **krbtgt)
2104 krb5_error_code ret;
2105 krb5_principal tgs_name;
2109 ret = krb5_make_principal(context,
2118 ret = _kdc_db_fetch(context, config, tgs_name,
2119 HDB_F_GET_KRBTGT, NULL, NULL, krbtgt);
2120 krb5_free_principal(context, tgs_name);
2130 _kdc_as_rep(astgs_request_t r)
2132 krb5_kdc_configuration *config = r->config;
2133 KDC_REQ *req = &r->req;
2134 const char *from = r->from;
2135 KDC_REQ_BODY *b = NULL;
2136 KDC_REP *rep = &r->rep;
2138 krb5_enctype setype;
2139 krb5_error_code ret = 0;
2142 int i, flags = HDB_F_FOR_AS_REQ;
2144 krb5_boolean is_tgs;
2146 hdb_entry_ex *krbtgt = NULL;
2149 memset(rep, 0, sizeof(*rep));
2152 if (rep->padata == NULL) {
2154 krb5_set_error_message(r->context, ret, N_("malloc: out of memory", ""));
2159 * Look for FAST armor and unwrap
2161 ret = _kdc_fast_unwrap_request(r, NULL, NULL);
2163 _kdc_r_log(r, 1, "FAST unwrap request from %s failed: %d", from, ret);
2171 flags |= HDB_F_CANON;
2173 if (b->sname == NULL) {
2174 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2175 _kdc_set_e_text(r, "No server in request");
2179 ret = _krb5_principalname2krb5_principal(r->context, &r->server_princ,
2180 *(b->sname), b->realm);
2182 ret = krb5_unparse_name(r->context, r->server_princ, &r->sname);
2184 kdc_log(r->context, config, 2,
2185 "AS_REQ malformed server name from %s", from);
2189 if (b->cname == NULL) {
2190 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2191 _kdc_set_e_text(r, "No client in request");
2195 ret = _krb5_principalname2krb5_principal(r->context, &r->client_princ,
2196 *(b->cname), b->realm);
2198 ret = krb5_unparse_name(r->context, r->client_princ, &r->cname);
2200 kdc_log(r->context, config, 2,
2201 "AS-REQ malformed client name from %s", from);
2205 kdc_log(r->context, config, 4, "AS-REQ %s from %s for %s",
2206 r->cname, r->from, r->sname);
2208 is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
2210 if (_kdc_is_anonymous(r->context, r->client_princ) &&
2211 !_kdc_is_anon_request(req)) {
2212 kdc_log(r->context, config, 2, "Anonymous client w/o anonymous flag");
2213 ret = KRB5KDC_ERR_BADOPTION;
2217 ret = _kdc_db_fetch(r->context, config, r->client_princ,
2218 HDB_F_GET_CLIENT | HDB_F_SYNTHETIC_OK | flags, NULL,
2219 &r->clientdb, &r->client);
2221 case 0: /* Success */
2223 case HDB_ERR_NOT_FOUND_HERE:
2224 kdc_log(r->context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
2227 case HDB_ERR_WRONG_REALM: {
2228 char *fixed_client_name = NULL;
2230 ret = krb5_unparse_name(r->context, r->client->entry.principal,
2231 &fixed_client_name);
2236 kdc_log(r->context, config, 4, "WRONG_REALM - %s -> %s",
2237 r->cname, fixed_client_name);
2238 free(fixed_client_name);
2241 ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
2243 r->ret = KRB5_KDC_ERR_WRONG_REALM,
2244 r->client->entry.principal, r->server_princ,
2245 NULL, NULL, r->reply);
2250 struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_CLIENT_UNKNOWN, NULL, NULL};
2251 msg = krb5_get_error_message(r->context, ret);
2252 kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
2253 krb5_free_error_message(r->context, msg);
2254 ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
2255 _kdc_audit_auth_status(r, &auth_status, NULL);
2259 ret = _kdc_db_fetch(r->context, config, r->server_princ,
2260 HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
2261 flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
2262 NULL, NULL, &r->server);
2264 case 0: /* Success */
2266 case HDB_ERR_NOT_FOUND_HERE:
2267 kdc_log(r->context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
2271 msg = krb5_get_error_message(r->context, ret);
2272 kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->sname, msg);
2273 krb5_free_error_message(r->context, msg);
2274 ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
2279 * Select an enctype for the to-be-issued ticket's session key using the
2280 * intersection of the client's requested enctypes and the server's (like a
2281 * root krbtgt, but not necessarily) etypes from its HDB entry.
2283 ret = _kdc_find_etype(r, (is_tgs ? KFE_IS_TGS:0) | KFE_USE_CLIENT,
2284 b->etype.val, b->etype.len,
2285 &r->sessionetype, NULL, NULL);
2287 kdc_log(r->context, config, 4,
2288 "Client (%s) from %s has no common enctypes with KDC "
2289 "to use for the session key",
2295 * Pre-auth processing
2301 log_patypes(r, req->padata);
2303 /* Check if preauth matching */
2305 for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
2306 if (pat[n].validate == NULL)
2308 if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
2311 kdc_log(r->context, config, 5,
2312 "Looking for %s pa-data -- %s", pat[n].name, r->cname);
2314 pa = _kdc_find_padata(req, &i, pat[n].type);
2316 struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_INVALID, NULL, NULL};
2318 if (r->client->entry.flags.synthetic &&
2319 !(pat[n].flags & PA_SYNTHETIC_OK)) {
2320 kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2321 ret = HDB_ERR_NOENTRY;
2324 _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
2326 ret = pat[n].validate(r, pa, &auth_status);
2328 krb5_error_code ret2;
2330 krb5_boolean default_salt;
2332 if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID)
2333 auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_FAILURE;
2334 _kdc_audit_auth_status(r,
2337 free(auth_status.free_ptr);
2340 * If there is a client key, send ETYPE_INFO{,2}
2342 ret2 = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2343 b->etype.val, b->etype.len,
2344 NULL, &ckey, &default_salt);
2346 ret2 = get_pa_etype_info_both(r->context, config, &b->etype,
2347 r->rep.padata, ckey, !default_salt);
2353 kdc_log(r->context, config, 4,
2354 "%s pre-authentication succeeded -- %s",
2355 pat[n].name, r->cname);
2357 r->pa_used = &pat[n];
2359 if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID)
2360 auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_SUCCESS;
2362 _kdc_audit_auth_status(r, &auth_status, r->pa_used->name);
2363 free(auth_status.free_ptr);
2364 r->et.flags.pre_authent = 1;
2369 if (found_pa == 0) {
2372 krb5_boolean default_salt;
2374 if (r->client->entry.flags.synthetic) {
2375 kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
2376 ret = HDB_ERR_NOENTRY;
2380 for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
2381 if ((pat[n].flags & PA_ANNOUNCE) == 0)
2384 if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
2386 if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
2387 if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
2389 if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
2393 ret = krb5_padata_add(r->context, r->rep.padata,
2394 pat[n].type, NULL, 0);
2400 * If there is a client key, send ETYPE_INFO{,2}
2402 ret = _kdc_find_etype(r, KFE_IS_PREAUTH|KFE_USE_CLIENT,
2403 b->etype.val, b->etype.len,
2404 NULL, &ckey, &default_salt);
2406 ret = get_pa_etype_info_both(r->context, config, &b->etype,
2407 r->rep.padata, ckey, !default_salt);
2413 * send requre preauth is its required or anon is requested,
2414 * anon is today only allowed via preauth mechanisms.
2416 if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
2417 ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
2418 _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
2423 ret = KRB5KDC_ERR_CLIENT_NOTYET;
2424 _kdc_set_e_text(r, "Doesn't have a client key available");
2427 krb5_free_keyblock_contents(r->context, &r->reply_key);
2428 ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
2434 * Verify flags after the user been required to prove its identity
2435 * with in a preauth mech.
2438 ret = _kdc_check_access(r);
2442 if (_kdc_is_anon_request(&r->req)) {
2443 ret = _kdc_check_anon_policy(r);
2445 _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
2449 r->et.flags.anonymous = 1;
2453 struct kdc_pa_auth_status auth_status
2454 = {HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS,
2458 _kdc_audit_auth_status(r, &auth_status, NULL);
2462 * Select the best encryption type for the KDC with out regard to
2463 * the client since the client never needs to read that data.
2466 ret = _kdc_get_preferred_key(r->context, config,
2467 r->server, r->sname,
2472 /* If server is not krbtgt, fetch local krbtgt key for signing authdata */
2476 ret = get_local_tgs(r->context, config, r->server_princ->realm,
2481 ret = _kdc_get_preferred_key(r->context, config, krbtgt,
2482 r->server_princ->realm,
2488 if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
2489 ret = KRB5KDC_ERR_BADOPTION;
2490 _kdc_set_e_text(r, "Bad KDC options");
2498 rep->msg_type = krb_as_rep;
2500 if (!config->historical_anon_realm &&
2501 _kdc_is_anonymous(r->context, r->client_princ)) {
2502 Realm anon_realm = KRB5_ANON_REALM;
2503 ret = copy_Realm(&anon_realm, &rep->crealm);
2504 } else if (f.canonicalize || r->client->entry.flags.force_canonicalize)
2505 ret = copy_Realm(&r->client->entry.principal->realm, &rep->crealm);
2507 ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
2510 if (r->et.flags.anonymous)
2511 ret = _kdc_make_anonymous_principalname(&rep->cname);
2512 else if (f.canonicalize || r->client->entry.flags.force_canonicalize)
2513 ret = _krb5_principal2principalname(&rep->cname, r->client->entry.principal);
2515 ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
2519 rep->ticket.tkt_vno = 5;
2520 if (f.canonicalize || r->server->entry.flags.force_canonicalize)
2521 ret = copy_Realm(&r->server->entry.principal->realm, &rep->ticket.realm);
2523 ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
2526 if (f.canonicalize || r->server->entry.flags.force_canonicalize)
2527 _krb5_principal2principalname(&rep->ticket.sname,
2528 r->server->entry.principal);
2530 _krb5_principal2principalname(&rep->ticket.sname,
2532 /* java 1.6 expects the name to be the same type, lets allow that
2533 * uncomplicated name-types, when f.canonicalize is not set (to
2534 * match Windows Server 1709). */
2535 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2537 && (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))) {
2538 rep->ticket.sname.name_type = b->sname->name_type;
2542 r->et.flags.initial = 1;
2543 if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
2544 r->et.flags.forwardable = f.forwardable;
2545 if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
2546 r->et.flags.proxiable = f.proxiable;
2547 else if (f.proxiable) {
2548 _kdc_set_e_text(r, "Ticket may not be proxiable");
2549 ret = KRB5KDC_ERR_POLICY;
2552 if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
2553 r->et.flags.may_postdate = f.allow_postdate;
2554 else if (f.allow_postdate){
2555 _kdc_set_e_text(r, "Ticket may not be postdate");
2556 ret = KRB5KDC_ERR_POLICY;
2561 _kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
2563 /* check for valid set of addresses */
2564 if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
2565 if (r->config->warn_ticket_addresses) {
2566 _kdc_audit_addkv((kdc_request_t)r, 0, "wrongaddr", "yes");
2568 _kdc_set_e_text(r, "Request from wrong address");
2569 ret = KRB5KRB_AP_ERR_BADADDR;
2574 ret = copy_PrincipalName(&rep->cname, &r->et.cname);
2577 ret = copy_Realm(&rep->crealm, &r->et.crealm);
2585 start = r->et.authtime = kdc_time;
2587 if(f.postdated && req->req_body.from){
2588 ALLOC(r->et.starttime);
2589 start = *r->et.starttime = *req->req_body.from;
2590 r->et.flags.invalid = 1;
2591 r->et.flags.postdated = 1; /* XXX ??? */
2593 _kdc_fix_time(&b->till);
2596 /* be careful not overflowing */
2599 * Pre-auth can override r->client->entry.max_life if configured.
2601 * See pre-auth methods, specifically PKINIT, which can get or derive
2602 * this from the client's certificate.
2604 if (r->pa_max_life > 0)
2605 t = start + min(t - start, r->pa_max_life);
2606 else if (r->client->entry.max_life)
2607 t = start + min(t - start, *r->client->entry.max_life);
2609 if (r->server->entry.max_life)
2610 t = start + min(t - start, *r->server->entry.max_life);
2612 /* Pre-auth can bound endtime as well */
2613 if (r->pa_endtime > 0)
2614 t = start + min(t - start, r->pa_endtime);
2616 t = min(t, start + realm->max_life);
2619 if(f.renewable_ok && r->et.endtime < *b->till){
2621 if(b->rtime == NULL){
2625 if(*b->rtime < *b->till)
2626 *b->rtime = *b->till;
2628 if(f.renewable && b->rtime){
2632 if(r->client->entry.max_renew)
2633 t = start + min(t - start, *r->client->entry.max_renew);
2634 if(r->server->entry.max_renew)
2635 t = start + min(t - start, *r->server->entry.max_renew);
2637 t = min(t, start + realm->max_renew);
2639 ALLOC(r->et.renew_till);
2640 *r->et.renew_till = t;
2641 r->et.flags.renewable = 1;
2647 copy_HostAddresses(b->addresses, r->et.caddr);
2650 r->et.transited.tr_type = domain_X500_Compress;
2651 krb5_data_zero(&r->et.transited.contents);
2653 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
2654 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
2655 * incapable of correctly decoding SEQUENCE OF's of zero length.
2657 * To fix this, always send at least one no-op last_req
2659 * If there's a pw_end or valid_end we will use that,
2660 * otherwise just a dummy lr.
2662 r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
2663 if (r->ek.last_req.val == NULL) {
2667 r->ek.last_req.len = 0;
2668 if (r->client->entry.pw_end
2669 && (config->kdc_warn_pwexpire == 0
2670 || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
2671 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
2672 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
2673 ++r->ek.last_req.len;
2675 if (r->client->entry.valid_end) {
2676 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
2677 r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
2678 ++r->ek.last_req.len;
2680 if (r->ek.last_req.len == 0) {
2681 r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
2682 r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
2683 ++r->ek.last_req.len;
2685 r->ek.nonce = b->nonce;
2686 if (r->client->entry.valid_end || r->client->entry.pw_end) {
2687 ALLOC(r->ek.key_expiration);
2688 if (r->client->entry.valid_end) {
2689 if (r->client->entry.pw_end)
2690 *r->ek.key_expiration = min(*r->client->entry.valid_end,
2691 *r->client->entry.pw_end);
2693 *r->ek.key_expiration = *r->client->entry.valid_end;
2695 *r->ek.key_expiration = *r->client->entry.pw_end;
2697 r->ek.key_expiration = NULL;
2698 r->ek.flags = r->et.flags;
2699 r->ek.authtime = r->et.authtime;
2700 if (r->et.starttime) {
2701 ALLOC(r->ek.starttime);
2702 *r->ek.starttime = *r->et.starttime;
2704 r->ek.endtime = r->et.endtime;
2705 if (r->et.renew_till) {
2706 ALLOC(r->ek.renew_till);
2707 *r->ek.renew_till = *r->et.renew_till;
2709 ret = copy_Realm(&rep->ticket.realm, &r->ek.srealm);
2712 ret = copy_PrincipalName(&rep->ticket.sname, &r->ek.sname);
2717 copy_HostAddresses(r->et.caddr, r->ek.caddr);
2721 * Check and session and reply keys
2724 if (r->session_key.keytype == ETYPE_NULL) {
2725 ret = krb5_generate_random_keyblock(r->context, r->sessionetype, &r->session_key);
2730 if (r->reply_key.keytype == ETYPE_NULL) {
2731 _kdc_set_e_text(r, "Client have no reply key");
2732 ret = KRB5KDC_ERR_CLIENT_NOTYET;
2736 ret = copy_EncryptionKey(&r->session_key, &r->et.key);
2740 ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
2745 if (!r->et.flags.anonymous) {
2746 generate_pac(r, skey, krbtgt_key, is_tgs);
2749 if (r->client->entry.flags.synthetic) {
2750 ret = add_synthetic_princ_ad(r);
2755 _kdc_log_timestamp(r, "AS-REQ", r->et.authtime,
2756 r->et.starttime, r->et.endtime,
2759 _log_astgs_req(r, setype);
2762 * We always say we support FAST/enc-pa-rep
2765 r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
2768 * update reply-key with strengthen-key
2771 ret = _kdc_fast_strengthen_reply_key(r);
2776 * Add REQ_ENC_PA_REP if client supports it
2780 pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
2783 ret = add_enc_pa_rep(r);
2785 msg = krb5_get_error_message(r->context, ret);
2786 _kdc_r_log(r, 4, "add_enc_pa_rep failed: %s: %d", msg, ret);
2787 krb5_free_error_message(r->context, msg);
2793 * Last chance for plugins to update reply
2795 ret = _kdc_finalize_reply(r);
2800 * Don't send kvno from client entry if the pre-authentication
2801 * mechanism replaced the reply key.
2804 ret = _kdc_encode_reply(r->context, config,
2805 r, req->req_body.nonce, setype,
2806 r->server->entry.kvno, &skey->key,
2807 pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->entry.kvno,
2813 * Check if message too large
2815 if (r->datagram_reply && r->reply->length > config->max_datagram_reply_length) {
2816 krb5_data_free(r->reply);
2817 ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2818 _kdc_set_e_text(r, "Reply packet too large");
2823 * In case of a non proxy error, build an error message.
2825 if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && r->reply->length == 0)
2826 ret = _kdc_fast_mk_error(r,
2836 if (r->pa_used && r->pa_used->cleanup)
2837 r->pa_used->cleanup(r);
2839 free_AS_REP(&r->rep);
2840 free_EncTicketPart(&r->et);
2841 free_EncKDCRepPart(&r->ek);
2842 _kdc_free_fast_state(&r->fast);
2844 if (r->client_princ) {
2845 krb5_free_principal(r->context, r->client_princ);
2846 r->client_princ = NULL;
2848 if (r->server_princ){
2849 krb5_free_principal(r->context, r->server_princ);
2850 r->server_princ = NULL;
2853 _kdc_free_ent(r->context, r->client);
2855 _kdc_free_ent(r->context, r->server);
2857 _kdc_free_ent(r->context, krbtgt);
2858 if (r->armor_crypto) {
2859 krb5_crypto_destroy(r->context, r->armor_crypto);
2860 r->armor_crypto = NULL;
2862 if (r->armor_ticket)
2863 krb5_free_ticket(r->context, r->armor_ticket);
2864 if (r->armor_server)
2865 _kdc_free_ent(r->context, r->armor_server);
2866 krb5_free_keyblock_contents(r->context, &r->reply_key);
2867 krb5_free_keyblock_contents(r->context, &r->session_key);
2868 krb5_free_keyblock_contents(r->context, &r->strengthen_key);
2869 krb5_pac_free(r->context, r->pac);