Home | History | Annotate | Line # | Download | only in kdc
      1 /*	$NetBSD: kerberos5.c,v 1.9 2023/06/19 21:41:41 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997-2007 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of the Institute nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include "kdc_locl.h"
     37 
     38 #define MAX_TIME ((time_t)((1U << 31) - 1))
     39 
     40 void
     41 _kdc_fix_time(time_t **t)
     42 {
     43     if(*t == NULL){
     44 	ALLOC(*t);
     45 	**t = MAX_TIME;
     46     }
     47     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
     48 }
     49 
     50 static int
     51 realloc_method_data(METHOD_DATA *md)
     52 {
     53     PA_DATA *pa;
     54     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
     55     if(pa == NULL)
     56 	return ENOMEM;
     57     md->val = pa;
     58     md->len++;
     59     return 0;
     60 }
     61 
     62 static void
     63 set_salt_padata(METHOD_DATA *md, Salt *salt)
     64 {
     65     if (salt) {
     66        realloc_method_data(md);
     67        md->val[md->len - 1].padata_type = salt->type;
     68        der_copy_octet_string(&salt->salt,
     69                              &md->val[md->len - 1].padata_value);
     70     }
     71 }
     72 
     73 const PA_DATA*
     74 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
     75 {
     76     if (req->padata == NULL)
     77 	return NULL;
     78 
     79     while((size_t)*start < req->padata->len){
     80 	(*start)++;
     81 	if(req->padata->val[*start - 1].padata_type == (unsigned)type)
     82 	    return &req->padata->val[*start - 1];
     83     }
     84     return NULL;
     85 }
     86 
     87 /*
     88  * This is a hack to allow predefined weak services, like afs to
     89  * still use weak types
     90  */
     91 
     92 krb5_boolean
     93 _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
     94 {
     95     if (principal->name.name_string.len > 0 &&
     96 	strcmp(principal->name.name_string.val[0], "afs") == 0 &&
     97 	(etype == (krb5_enctype)ETYPE_DES_CBC_CRC
     98 	 || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
     99 	 || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
    100 	return TRUE;
    101     return FALSE;
    102 }
    103 
    104 
    105 /*
    106  * Detect if `key' is the using the the precomputed `default_salt'.
    107  */
    108 
    109 static krb5_boolean
    110 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
    111 {
    112     if (key->salt == NULL)
    113 	return TRUE;
    114     if (default_salt->salttype != key->salt->type)
    115 	return FALSE;
    116     if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
    117 	return FALSE;
    118     return TRUE;
    119 }
    120 
    121 /*
    122  * Detect if `key' is the using the the precomputed `default_salt'
    123  * (for des-cbc-crc) or any salt otherwise.
    124  *
    125  * This is for avoiding Kerberos v4 (yes really) keys in AS-REQ as
    126  * that salt is strange, and a buggy client will try to use the
    127  * principal as the salt and not the returned value.
    128  */
    129 
    130 static krb5_boolean
    131 is_good_salt_p(const krb5_salt *default_salt, const Key *key)
    132 {
    133     if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
    134 	return is_default_salt_p(default_salt, key);
    135 
    136     return TRUE;
    137 }
    138 
    139 krb5_boolean
    140 _kdc_is_anon_request(const KDC_REQ *req)
    141 {
    142     const KDC_REQ_BODY *b = &req->req_body;
    143 
    144     /*
    145      * Versions of Heimdal from 0.9rc1 through 1.50 use bit 14 instead
    146      * of 16 for request_anonymous, as indicated in the anonymous draft
    147      * prior to version 11. Bit 14 is assigned to S4U2Proxy, but S4U2Proxy
    148      * requests are only sent to the TGS and, in any case, would have an
    149      * additional ticket present.
    150      */
    151     return b->kdc_options.request_anonymous ||
    152 	   (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
    153 }
    154 
    155 /*
    156  * return the first appropriate key of `princ' in `ret_key'.  Look for
    157  * all the etypes in (`etypes', `len'), stopping as soon as we find
    158  * one, but preferring one that has default salt.
    159  */
    160 
    161 krb5_error_code
    162 _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
    163 		krb5_boolean is_preauth, hdb_entry_ex *princ,
    164 		krb5_enctype *etypes, unsigned len,
    165 		krb5_enctype *ret_enctype, Key **ret_key)
    166 {
    167     krb5_error_code ret;
    168     krb5_salt def_salt;
    169     krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
    170     const krb5_enctype *p;
    171     Key *key = NULL;
    172     int i, k;
    173 
    174     /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
    175     ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
    176     if (ret)
    177 	return ret;
    178 
    179     ret = KRB5KDC_ERR_ETYPE_NOSUPP;
    180 
    181     if (use_strongest_session_key) {
    182 
    183 	/*
    184 	 * Pick the strongest key that the KDC, target service, and
    185 	 * client all support, using the local cryptosystem enctype
    186 	 * list in strongest-to-weakest order to drive the search.
    187 	 *
    188 	 * This is not what RFC4120 says to do, but it encourages
    189 	 * adoption of stronger enctypes.  This doesn't play well with
    190 	 * clients that have multiple Kerberos client implementations
    191 	 * available with different supported enctype lists.
    192 	 */
    193 
    194 	/* drive the search with local supported enctypes list */
    195 	p = krb5_kerberos_enctypes(context);
    196 	for (i = 0;
    197 	    p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
    198 	    i++) {
    199 	    if (krb5_enctype_valid(context, p[i]) != 0 &&
    200                 !_kdc_is_weak_exception(princ->entry.principal, p[i]))
    201 		continue;
    202 
    203 	    /* check that the client supports it too */
    204 	    for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
    205 
    206 		if (p[i] != etypes[k])
    207 		    continue;
    208 
    209                 /* check target princ support */
    210 		key = NULL;
    211 		while (hdb_next_enctype2key(context, &princ->entry, NULL,
    212 					     p[i], &key) == 0) {
    213 		    if (key->key.keyvalue.length == 0) {
    214 			ret = KRB5KDC_ERR_NULL_KEY;
    215 			continue;
    216 		    }
    217 		    enctype = p[i];
    218 		    ret = 0;
    219 		    if (is_preauth && ret_key != NULL &&
    220 			!is_good_salt_p(&def_salt, key))
    221 			continue;
    222 		}
    223 	    }
    224 	}
    225     } else {
    226 	/*
    227 	 * Pick the first key from the client's enctype list that is
    228 	 * supported by the cryptosystem and by the given principal.
    229 	 *
    230 	 * RFC4120 says we SHOULD pick the first _strong_ key from the
    231 	 * client's list... not the first key...  If the admin disallows
    232 	 * weak enctypes in krb5.conf and selects this key selection
    233 	 * algorithm, then we get exactly what RFC4120 says.
    234 	 */
    235 	for(i = 0; ret != 0 && i < len; i++) {
    236 
    237 	    if (krb5_enctype_valid(context, etypes[i]) != 0 &&
    238 		!_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
    239 		continue;
    240 
    241 	    key = NULL;
    242 	    while (ret != 0 &&
    243                    hdb_next_enctype2key(context, &princ->entry, NULL,
    244 					etypes[i], &key) == 0) {
    245 		if (key->key.keyvalue.length == 0) {
    246 		    ret = KRB5KDC_ERR_NULL_KEY;
    247 		    continue;
    248 		}
    249                 enctype = etypes[i];
    250 		ret = 0;
    251 		if (is_preauth && ret_key != NULL &&
    252 		    !is_good_salt_p(&def_salt, key))
    253 		    continue;
    254 	    }
    255 	}
    256     }
    257 
    258     if (enctype == (krb5_enctype)ETYPE_NULL) {
    259         /*
    260          * if the service principal is one for which there is a known 1DES
    261          * exception and no other enctype matches both the client request and
    262          * the service key list, provide a DES-CBC-CRC key.
    263          */
    264 	if (ret_key == NULL &&
    265 	    _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
    266             ret = 0;
    267             enctype = ETYPE_DES_CBC_CRC;
    268         } else {
    269             ret = KRB5KDC_ERR_ETYPE_NOSUPP;
    270         }
    271     }
    272 
    273     if (ret == 0) {
    274 	if (ret_enctype != NULL)
    275 	    *ret_enctype = enctype;
    276 	if (ret_key != NULL)
    277 	    *ret_key = key;
    278     }
    279 
    280     krb5_free_salt (context, def_salt);
    281     return ret;
    282 }
    283 
    284 krb5_error_code
    285 _kdc_make_anonymous_principalname (PrincipalName *pn)
    286 {
    287     pn->name_type = KRB5_NT_WELLKNOWN;
    288     pn->name_string.len = 2;
    289     pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
    290     if (pn->name_string.val == NULL)
    291 	goto failed;
    292 
    293     pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
    294     if (pn->name_string.val[0] == NULL)
    295 	goto failed;
    296 
    297     pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
    298     if (pn->name_string.val[1] == NULL)
    299 	goto failed;
    300 
    301     return 0;
    302 
    303 failed:
    304     free_PrincipalName(pn);
    305 
    306     pn->name_type = KRB5_NT_UNKNOWN;
    307     pn->name_string.len = 0;
    308     pn->name_string.val = NULL;
    309 
    310     return ENOMEM;
    311 }
    312 
    313 static void
    314 _kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
    315 {
    316     va_list ap;
    317     char *s;
    318     va_start(ap, fmt);
    319     s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
    320     if(s) free(s);
    321     va_end(ap);
    322 }
    323 
    324 static void
    325 _kdc_set_e_text(kdc_request_t r, const char *e_text)
    326 {
    327     r->e_text = e_text;
    328     kdc_log(r->context, r->config, 0, "%s", e_text);
    329 }
    330 
    331 void
    332 _kdc_log_timestamp(krb5_context context,
    333 		   krb5_kdc_configuration *config,
    334 		   const char *type,
    335 		   KerberosTime authtime, KerberosTime *starttime,
    336 		   KerberosTime endtime, KerberosTime *renew_till)
    337 {
    338     char authtime_str[100], starttime_str[100],
    339 	endtime_str[100], renewtime_str[100];
    340 
    341     krb5_format_time(context, authtime,
    342 		     authtime_str, sizeof(authtime_str), TRUE);
    343     if (starttime)
    344 	krb5_format_time(context, *starttime,
    345 			 starttime_str, sizeof(starttime_str), TRUE);
    346     else
    347 	strlcpy(starttime_str, "unset", sizeof(starttime_str));
    348     krb5_format_time(context, endtime,
    349 		     endtime_str, sizeof(endtime_str), TRUE);
    350     if (renew_till)
    351 	krb5_format_time(context, *renew_till,
    352 			 renewtime_str, sizeof(renewtime_str), TRUE);
    353     else
    354 	strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
    355 
    356     kdc_log(context, config, 5,
    357 	    "%s authtime: %s starttime: %s endtime: %s renew till: %s",
    358 	    type, authtime_str, starttime_str, endtime_str, renewtime_str);
    359 }
    360 
    361 /*
    362  *
    363  */
    364 
    365 #ifdef PKINIT
    366 
    367 static krb5_error_code
    368 pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
    369 {
    370     pk_client_params *pkp = NULL;
    371     char *client_cert = NULL;
    372     krb5_error_code ret;
    373 
    374     ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
    375     if (ret || pkp == NULL) {
    376 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
    377 	_kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s",
    378 		   r->client_name);
    379 	goto out;
    380     }
    381 
    382     ret = _kdc_pk_check_client(r->context,
    383 			       r->config,
    384 			       r->clientdb,
    385 			       r->client,
    386 			       pkp,
    387 			       &client_cert);
    388     if (ret) {
    389 	_kdc_set_e_text(r, "PKINIT certificate not allowed to "
    390 			"impersonate principal");
    391 	goto out;
    392     }
    393 
    394     _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s",
    395 	       r->client_name, client_cert);
    396     free(client_cert);
    397 
    398     ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
    399 			      r->sessionetype, &r->req, &r->request,
    400 			      &r->reply_key, &r->session_key, &r->outpadata);
    401     if (ret) {
    402 	_kdc_set_e_text(r, "Failed to build PK-INIT reply");
    403 	goto out;
    404     }
    405 #if 0
    406     ret = _kdc_add_inital_verified_cas(r->context, r->config,
    407 				       pkp, &r->et);
    408 #endif
    409  out:
    410     if (pkp)
    411 	_kdc_pk_free_client_param(r->context, pkp);
    412 
    413     return ret;
    414 }
    415 
    416 #endif /* PKINIT */
    417 
    418 /*
    419  *
    420  */
    421 
    422 static krb5_error_code
    423 make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
    424 		      krb5_crypto crypto)
    425 {
    426     PA_ENC_TS_ENC p;
    427     unsigned char *buf;
    428     size_t buf_size;
    429     size_t len;
    430     EncryptedData encdata;
    431     krb5_error_code ret;
    432     int32_t usec;
    433     int usec2;
    434 
    435     krb5_us_timeofday (context, &p.patimestamp, &usec);
    436     usec2         = usec;
    437     p.pausec      = &usec2;
    438 
    439     ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
    440     if (ret)
    441 	return ret;
    442     if(buf_size != len)
    443 	krb5_abortx(context, "internal error in ASN.1 encoder");
    444 
    445     ret = krb5_encrypt_EncryptedData(context,
    446 				     crypto,
    447 				     KRB5_KU_ENC_CHALLENGE_KDC,
    448 				     buf,
    449 				     len,
    450 				     0,
    451 				     &encdata);
    452     free(buf);
    453     if (ret)
    454 	return ret;
    455 
    456     ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
    457     free_EncryptedData(&encdata);
    458     if (ret)
    459 	return ret;
    460     if(buf_size != len)
    461 	krb5_abortx(context, "internal error in ASN.1 encoder");
    462 
    463     ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len);
    464     if (ret)
    465 	free(buf);
    466     return ret;
    467 }
    468 
    469 static krb5_error_code
    470 pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
    471 {
    472     krb5_data pepper1, pepper2, ts_data;
    473     int invalidPassword = 0;
    474     EncryptedData enc_data;
    475     krb5_enctype aenctype;
    476     krb5_error_code ret;
    477     struct Key *k;
    478     size_t size;
    479     int i;
    480 
    481     heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
    482 
    483     if (_kdc_is_anon_request(&r->req)) {
    484 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
    485 	kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon");
    486 	return ret;
    487     }
    488 
    489     ret = decode_EncryptedData(pa->padata_value.data,
    490 			       pa->padata_value.length,
    491 			       &enc_data,
    492 			       &size);
    493     if (ret) {
    494 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
    495 	_kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
    496 		   r->client_name);
    497 	return ret;
    498     }
    499 
    500     pepper1.data = "clientchallengearmor";
    501     pepper1.length = strlen(pepper1.data);
    502     pepper2.data = "challengelongterm";
    503     pepper2.length = strlen(pepper2.data);
    504 
    505     krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
    506 
    507     for (i = 0; i < r->client->entry.keys.len; i++) {
    508 	krb5_crypto challangecrypto, longtermcrypto;
    509 	krb5_keyblock challangekey;
    510 	PA_ENC_TS_ENC p;
    511 
    512 	k = &r->client->entry.keys.val[i];
    513 
    514 	ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
    515 	if (ret)
    516 	    continue;
    517 
    518 	ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
    519 				 &pepper1, &pepper2, aenctype,
    520 				 &challangekey);
    521 	krb5_crypto_destroy(r->context, longtermcrypto);
    522 	if (ret)
    523 	    continue;
    524 
    525 	ret = krb5_crypto_init(r->context, &challangekey, 0,
    526 			       &challangecrypto);
    527 	if (ret)
    528 	    continue;
    529 
    530 	ret = krb5_decrypt_EncryptedData(r->context, challangecrypto,
    531 					 KRB5_KU_ENC_CHALLENGE_CLIENT,
    532 					 &enc_data,
    533 					 &ts_data);
    534 	if (ret) {
    535 	    const char *msg = krb5_get_error_message(r->context, ret);
    536 	    krb5_error_code ret2;
    537 	    char *str = NULL;
    538 
    539 	    invalidPassword = 1;
    540 
    541 	    ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
    542 	    if (ret2)
    543 		str = NULL;
    544 	    _kdc_r_log(r, 5, "Failed to decrypt ENC-CHAL -- %s "
    545 		       "(enctype %s) error %s",
    546 		       r->client_name, str ? str : "unknown enctype", msg);
    547 	    krb5_free_error_message(r->context, msg);
    548 	    free(str);
    549 
    550 	    continue;
    551 	}
    552 
    553 	ret = decode_PA_ENC_TS_ENC(ts_data.data,
    554 				   ts_data.length,
    555 				   &p,
    556 				   &size);
    557 	krb5_data_free(&ts_data);
    558 	if(ret){
    559 	    krb5_crypto_destroy(r->context, challangecrypto);
    560 	    ret = KRB5KDC_ERR_PREAUTH_FAILED;
    561 	    _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
    562 		       r->client_name);
    563 	    continue;
    564 	}
    565 
    566 	if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
    567 	    char client_time[100];
    568 
    569 	    krb5_crypto_destroy(r->context, challangecrypto);
    570 
    571 	    krb5_format_time(r->context, p.patimestamp,
    572 			     client_time, sizeof(client_time), TRUE);
    573 
    574 	    ret = KRB5KRB_AP_ERR_SKEW;
    575 	    _kdc_r_log(r, 0, "Too large time skew, "
    576 		       "client time %s is out by %u > %u seconds -- %s",
    577 		       client_time,
    578 		       (unsigned)labs(kdc_time - p.patimestamp),
    579 		       r->context->max_skew,
    580 		       r->client_name);
    581 
    582 	    free_PA_ENC_TS_ENC(&p);
    583 	    goto out;
    584 	}
    585 
    586 	free_PA_ENC_TS_ENC(&p);
    587 
    588 	ret = make_pa_enc_challange(r->context, &r->outpadata,
    589 				    challangecrypto);
    590 	krb5_crypto_destroy(r->context, challangecrypto);
    591 	if (ret)
    592 	    goto out;
    593 
    594 	set_salt_padata(&r->outpadata, k->salt);
    595 	krb5_free_keyblock_contents(r->context,  &r->reply_key);
    596 	ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
    597 	if (ret)
    598 	    goto out;
    599 
    600 	/*
    601 	 * Success
    602 	 */
    603 	if (r->clientdb->hdb_auth_status)
    604 	    r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
    605 					 HDB_AUTH_SUCCESS);
    606 	goto out;
    607     }
    608 
    609     if (invalidPassword && r->clientdb->hdb_auth_status) {
    610 	r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
    611 				     HDB_AUTH_WRONG_PASSWORD);
    612 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
    613     }
    614  out:
    615     free_EncryptedData(&enc_data);
    616 
    617     return ret;
    618 }
    619 
    620 static krb5_error_code
    621 pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
    622 {
    623     EncryptedData enc_data;
    624     krb5_error_code ret;
    625     krb5_crypto crypto;
    626     krb5_data ts_data;
    627     PA_ENC_TS_ENC p;
    628     size_t len;
    629     Key *pa_key;
    630     char *str;
    631 
    632     ret = decode_EncryptedData(pa->padata_value.data,
    633 			       pa->padata_value.length,
    634 			       &enc_data,
    635 			       &len);
    636     if (ret) {
    637 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
    638 	_kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
    639 		   r->client_name);
    640 	goto out;
    641     }
    642 
    643     ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
    644 			  enc_data.etype, &pa_key);
    645     if(ret){
    646 	char *estr;
    647 	_kdc_set_e_text(r, "No key matching entype");
    648 	ret = KRB5KDC_ERR_ETYPE_NOSUPP;
    649 	if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
    650 	    estr = NULL;
    651 	if(estr == NULL)
    652 	    _kdc_r_log(r, 5,
    653 		       "No client key matching pa-data (%d) -- %s",
    654 		       enc_data.etype, r->client_name);
    655 	else
    656 	    _kdc_r_log(r, 5,
    657 		       "No client key matching pa-data (%s) -- %s",
    658 		       estr, r->client_name);
    659 	free(estr);
    660 	free_EncryptedData(&enc_data);
    661 	goto out;
    662     }
    663 
    664  try_next_key:
    665     ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
    666     if (ret) {
    667 	const char *msg = krb5_get_error_message(r->context, ret);
    668 	_kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg);
    669 	krb5_free_error_message(r->context, msg);
    670 	free_EncryptedData(&enc_data);
    671 	goto out;
    672     }
    673 
    674     ret = krb5_decrypt_EncryptedData (r->context,
    675 				      crypto,
    676 				      KRB5_KU_PA_ENC_TIMESTAMP,
    677 				      &enc_data,
    678 				      &ts_data);
    679     krb5_crypto_destroy(r->context, crypto);
    680     /*
    681      * Since the user might have several keys with the same
    682      * enctype but with diffrent salting, we need to try all
    683      * the keys with the same enctype.
    684      */
    685     if(ret){
    686 	krb5_error_code ret2;
    687 	const char *msg = krb5_get_error_message(r->context, ret);
    688 
    689 	ret2 = krb5_enctype_to_string(r->context,
    690 				      pa_key->key.keytype, &str);
    691 	if (ret2)
    692 	    str = NULL;
    693 	_kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s "
    694 		   "(enctype %s) error %s",
    695 		   r->client_name, str ? str : "unknown enctype", msg);
    696 	krb5_free_error_message(r->context, msg);
    697 	free(str);
    698 
    699 	if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
    700 				enc_data.etype, &pa_key) == 0)
    701 	    goto try_next_key;
    702 
    703 	free_EncryptedData(&enc_data);
    704 
    705 	if (r->clientdb->hdb_auth_status)
    706 	    r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
    707 					 HDB_AUTH_WRONG_PASSWORD);
    708 
    709 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
    710 	goto out;
    711     }
    712     free_EncryptedData(&enc_data);
    713     ret = decode_PA_ENC_TS_ENC(ts_data.data,
    714 			       ts_data.length,
    715 			       &p,
    716 			       &len);
    717     krb5_data_free(&ts_data);
    718     if(ret){
    719 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
    720 	_kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
    721 		   r->client_name);
    722 	goto out;
    723     }
    724     if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
    725 	char client_time[100];
    726 
    727 	krb5_format_time(r->context, p.patimestamp,
    728 			 client_time, sizeof(client_time), TRUE);
    729 
    730 	ret = KRB5KRB_AP_ERR_SKEW;
    731 	_kdc_r_log(r, 0, "Too large time skew, "
    732 		   "client time %s is out by %u > %u seconds -- %s",
    733 		   client_time,
    734 		   (unsigned)labs(kdc_time - p.patimestamp),
    735 		   r->context->max_skew,
    736 		   r->client_name);
    737 
    738 	/*
    739 	 * The following is needed to make windows clients to
    740 	 * retry using the timestamp in the error message, if
    741 	 * there is a e_text, they become unhappy.
    742 	 */
    743 	r->e_text = NULL;
    744 	free_PA_ENC_TS_ENC(&p);
    745 	goto out;
    746     }
    747     free_PA_ENC_TS_ENC(&p);
    748 
    749     set_salt_padata(&r->outpadata, pa_key->salt);
    750 
    751     ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
    752     if (ret)
    753 	return ret;
    754 
    755     ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
    756     if (ret)
    757 	str = NULL;
    758     _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s",
    759 	       r->client_name, str ? str : "unknown enctype");
    760     free(str);
    761 
    762     ret = 0;
    763 
    764  out:
    765 
    766     return ret;
    767 }
    768 
    769 struct kdc_patypes {
    770     int type;
    771     char *name;
    772     unsigned int flags;
    773 #define PA_ANNOUNCE	1
    774 #define PA_REQ_FAST	2 /* only use inside fast */
    775     krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
    776 };
    777 
    778 static const struct kdc_patypes pat[] = {
    779 #ifdef PKINIT
    780     {
    781 	KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
    782 	pa_pkinit_validate
    783     },
    784     {
    785 	KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
    786 	pa_pkinit_validate
    787     },
    788     {
    789 	KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
    790 	NULL
    791     },
    792 #else
    793     { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
    794     { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
    795     { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL },
    796 #endif
    797     { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
    798     {
    799 	KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
    800 	PA_ANNOUNCE,
    801 	pa_enc_ts_validate
    802     },
    803     {
    804 	KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
    805 	PA_ANNOUNCE | PA_REQ_FAST,
    806 	pa_enc_chal_validate
    807     },
    808     { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
    809     { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
    810     { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
    811     { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
    812 };
    813 
    814 static void
    815 log_patypes(krb5_context context,
    816 	    krb5_kdc_configuration *config,
    817 	    METHOD_DATA *padata)
    818 {
    819     struct rk_strpool *p = NULL;
    820     char *str;
    821     size_t n, m;
    822 
    823     for (n = 0; n < padata->len; n++) {
    824 	for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
    825 	    if (padata->val[n].padata_type == pat[m].type) {
    826 		p = rk_strpoolprintf(p, "%s", pat[m].name);
    827 		break;
    828 	    }
    829 	}
    830 	if (m == sizeof(pat) / sizeof(pat[0]))
    831 	    p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
    832 	if (p && n + 1 < padata->len)
    833 	    p = rk_strpoolprintf(p, ", ");
    834 	if (p == NULL) {
    835 	    kdc_log(context, config, 0, "out of memory");
    836 	    return;
    837 	}
    838     }
    839     if (p == NULL)
    840 	p = rk_strpoolprintf(p, "none");
    841 
    842     str = rk_strpoolcollect(p);
    843     kdc_log(context, config, 0, "Client sent patypes: %s", str);
    844     free(str);
    845 }
    846 
    847 /*
    848  *
    849  */
    850 
    851 krb5_error_code
    852 _kdc_encode_reply(krb5_context context,
    853 		  krb5_kdc_configuration *config,
    854 		  krb5_crypto armor_crypto, uint32_t nonce,
    855 		  KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
    856 		  krb5_enctype etype,
    857 		  int skvno, const EncryptionKey *skey,
    858 		  int ckvno, const EncryptionKey *reply_key,
    859 		  int rk_is_subkey,
    860 		  const char **e_text,
    861 		  krb5_data *reply)
    862 {
    863     unsigned char *buf;
    864     size_t buf_size;
    865     size_t len = 0;
    866     krb5_error_code ret;
    867     krb5_crypto crypto;
    868 
    869     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
    870     if(ret) {
    871 	const char *msg = krb5_get_error_message(context, ret);
    872 	kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
    873 	krb5_free_error_message(context, msg);
    874 	return ret;
    875     }
    876     if(buf_size != len)
    877 	krb5_abortx(context, "Internal error in ASN.1 encoder");
    878 
    879     ret = krb5_crypto_init(context, skey, etype, &crypto);
    880     if (ret) {
    881         const char *msg = krb5_get_error_message(context, ret);
    882 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
    883 	krb5_free_error_message(context, msg);
    884 	free(buf);
    885 	return ret;
    886     }
    887 
    888     ret = krb5_encrypt_EncryptedData(context,
    889 				     crypto,
    890 				     KRB5_KU_TICKET,
    891 				     buf,
    892 				     len,
    893 				     skvno,
    894 				     &rep->ticket.enc_part);
    895     free(buf);
    896     krb5_crypto_destroy(context, crypto);
    897     if(ret) {
    898 	const char *msg = krb5_get_error_message(context, ret);
    899 	kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
    900 	krb5_free_error_message(context, msg);
    901 	return ret;
    902     }
    903 
    904     if (armor_crypto) {
    905 	krb5_data data;
    906 	krb5_keyblock *strengthen_key = NULL;
    907 	KrbFastFinished finished;
    908 
    909 	kdc_log(context, config, 0, "FAST armor protection");
    910 
    911 	memset(&finished, 0, sizeof(finished));
    912 	krb5_data_zero(&data);
    913 
    914 	finished.timestamp = kdc_time;
    915 	finished.usec = 0;
    916 	finished.crealm = et->crealm;
    917 	finished.cname = et->cname;
    918 
    919 	ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
    920 			   &rep->ticket, &len, ret);
    921 	if (ret)
    922 	    return ret;
    923 	if (data.length != len)
    924 	    krb5_abortx(context, "internal asn.1 error");
    925 
    926 	ret = krb5_create_checksum(context, armor_crypto,
    927 				   KRB5_KU_FAST_FINISHED, 0,
    928 				   data.data, data.length,
    929 				   &finished.ticket_checksum);
    930 	krb5_data_free(&data);
    931 	if (ret)
    932 	    return ret;
    933 
    934 	ret = _kdc_fast_mk_response(context, armor_crypto,
    935 				    rep->padata, strengthen_key, &finished,
    936 				    nonce, &data);
    937 	free_Checksum(&finished.ticket_checksum);
    938 	if (ret)
    939 	    return ret;
    940 
    941 	if (rep->padata) {
    942 	    free_METHOD_DATA(rep->padata);
    943 	} else {
    944 	    rep->padata = calloc(1, sizeof(*(rep->padata)));
    945 	    if (rep->padata == NULL) {
    946 		krb5_data_free(&data);
    947 		return ENOMEM;
    948 	    }
    949 	}
    950 
    951 	ret = krb5_padata_add(context, rep->padata,
    952 			      KRB5_PADATA_FX_FAST,
    953 			      data.data, data.length);
    954 	if (ret)
    955 	    return ret;
    956 
    957 	/*
    958 	 * Hide client name of privacy reasons
    959 	 */
    960 	if (1 /* r->fast_options.hide_client_names */) {
    961 	    rep->crealm[0] = '\0';
    962 	    free_PrincipalName(&rep->cname);
    963 	    rep->cname.name_type = 0;
    964 	}
    965     }
    966 
    967     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
    968 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
    969     else
    970 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
    971     if(ret) {
    972 	const char *msg = krb5_get_error_message(context, ret);
    973 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
    974 	krb5_free_error_message(context, msg);
    975 	return ret;
    976     }
    977     if(buf_size != len) {
    978 	free(buf);
    979 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
    980 	*e_text = "KDC internal error";
    981 	return KRB5KRB_ERR_GENERIC;
    982     }
    983     ret = krb5_crypto_init(context, reply_key, 0, &crypto);
    984     if (ret) {
    985 	const char *msg = krb5_get_error_message(context, ret);
    986 	free(buf);
    987 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
    988 	krb5_free_error_message(context, msg);
    989 	return ret;
    990     }
    991     if(rep->msg_type == krb_as_rep) {
    992 	krb5_encrypt_EncryptedData(context,
    993 				   crypto,
    994 				   KRB5_KU_AS_REP_ENC_PART,
    995 				   buf,
    996 				   len,
    997 				   ckvno,
    998 				   &rep->enc_part);
    999 	free(buf);
   1000 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
   1001     } else {
   1002 	krb5_encrypt_EncryptedData(context,
   1003 				   crypto,
   1004 				   rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
   1005 				   buf,
   1006 				   len,
   1007 				   ckvno,
   1008 				   &rep->enc_part);
   1009 	free(buf);
   1010 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
   1011     }
   1012     krb5_crypto_destroy(context, crypto);
   1013     if(ret) {
   1014 	const char *msg = krb5_get_error_message(context, ret);
   1015 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
   1016 	krb5_free_error_message(context, msg);
   1017 	return ret;
   1018     }
   1019     if(buf_size != len) {
   1020 	free(buf);
   1021 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
   1022 	*e_text = "KDC internal error";
   1023 	return KRB5KRB_ERR_GENERIC;
   1024     }
   1025     reply->data = buf;
   1026     reply->length = buf_size;
   1027     return 0;
   1028 }
   1029 
   1030 /*
   1031  * Return 1 if the client have only older enctypes, this is for
   1032  * determining if the server should send ETYPE_INFO2 or not.
   1033  */
   1034 
   1035 static int
   1036 older_enctype(krb5_enctype enctype)
   1037 {
   1038     switch (enctype) {
   1039     case ETYPE_DES_CBC_CRC:
   1040     case ETYPE_DES_CBC_MD4:
   1041     case ETYPE_DES_CBC_MD5:
   1042     case ETYPE_DES3_CBC_SHA1:
   1043     case ETYPE_ARCFOUR_HMAC_MD5:
   1044     case ETYPE_ARCFOUR_HMAC_MD5_56:
   1045     /*
   1046      * The following three is "old" windows enctypes and is needed for
   1047      * windows 2000 hosts.
   1048      */
   1049     case ETYPE_ARCFOUR_MD4:
   1050     case ETYPE_ARCFOUR_HMAC_OLD:
   1051     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
   1052 	return 1;
   1053     default:
   1054 	return 0;
   1055     }
   1056 }
   1057 
   1058 /*
   1059  *
   1060  */
   1061 
   1062 static krb5_error_code
   1063 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
   1064 {
   1065     ent->etype = key->key.keytype;
   1066     if(key->salt){
   1067 #if 0
   1068 	ALLOC(ent->salttype);
   1069 
   1070 	if(key->salt->type == hdb_pw_salt)
   1071 	    *ent->salttype = 0; /* or 1? or NULL? */
   1072 	else if(key->salt->type == hdb_afs3_salt)
   1073 	    *ent->salttype = 2;
   1074 	else {
   1075 	    kdc_log(context, config, 0, "unknown salt-type: %d",
   1076 		    key->salt->type);
   1077 	    return KRB5KRB_ERR_GENERIC;
   1078 	}
   1079 	/* according to `the specs', we can't send a salt if
   1080 	   we have AFS3 salted key, but that requires that you
   1081 	   *know* what cell you are using (e.g by assuming
   1082 	   that the cell is the same as the realm in lower
   1083 	   case) */
   1084 #elif 0
   1085 	ALLOC(ent->salttype);
   1086 	*ent->salttype = key->salt->type;
   1087 #else
   1088 	/*
   1089 	 * We shouldn't sent salttype since it is incompatible with the
   1090 	 * specification and it breaks windows clients.  The afs
   1091 	 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
   1092 	 * implemented in Heimdal 0.7 and later.
   1093 	 */
   1094 	ent->salttype = NULL;
   1095 #endif
   1096 	krb5_copy_data(context, &key->salt->salt,
   1097 		       &ent->salt);
   1098     } else {
   1099 	/* we return no salt type at all, as that should indicate
   1100 	 * the default salt type and make everybody happy.  some
   1101 	 * systems (like w2k) dislike being told the salt type
   1102 	 * here. */
   1103 
   1104 	ent->salttype = NULL;
   1105 	ent->salt = NULL;
   1106     }
   1107     return 0;
   1108 }
   1109 
   1110 static krb5_error_code
   1111 get_pa_etype_info(krb5_context context,
   1112 		  krb5_kdc_configuration *config,
   1113 		  METHOD_DATA *md, Key *ckey)
   1114 {
   1115     krb5_error_code ret = 0;
   1116     ETYPE_INFO pa;
   1117     unsigned char *buf;
   1118     size_t len;
   1119 
   1120 
   1121     pa.len = 1;
   1122     pa.val = calloc(1, sizeof(pa.val[0]));
   1123     if(pa.val == NULL)
   1124 	return ENOMEM;
   1125 
   1126     ret = make_etype_info_entry(context, &pa.val[0], ckey);
   1127     if (ret) {
   1128 	free_ETYPE_INFO(&pa);
   1129 	return ret;
   1130     }
   1131 
   1132     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
   1133     free_ETYPE_INFO(&pa);
   1134     if(ret)
   1135 	return ret;
   1136     ret = realloc_method_data(md);
   1137     if(ret) {
   1138 	free(buf);
   1139 	return ret;
   1140     }
   1141     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
   1142     md->val[md->len - 1].padata_value.length = len;
   1143     md->val[md->len - 1].padata_value.data = buf;
   1144     return 0;
   1145 }
   1146 
   1147 /*
   1148  *
   1149  */
   1150 
   1151 extern int _krb5_AES_SHA1_string_to_default_iterator;
   1152 extern int _krb5_AES_SHA2_string_to_default_iterator;
   1153 
   1154 static krb5_error_code
   1155 make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
   1156 {
   1157     krb5_data *s2kparams;
   1158     krb5_error_code ret;
   1159 
   1160     ALLOC(s2kparams);
   1161     if (s2kparams == NULL)
   1162 	return ENOMEM;
   1163     ret = krb5_data_alloc(s2kparams, len);
   1164     if (ret) {
   1165 	free(s2kparams);
   1166 	return ret;
   1167     }
   1168     _krb5_put_int(s2kparams->data, value, len);
   1169     *ps2kparams = s2kparams;
   1170     return 0;
   1171 }
   1172 
   1173 static krb5_error_code
   1174 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
   1175 {
   1176     krb5_error_code ret;
   1177 
   1178     ent->etype = key->key.keytype;
   1179     if(key->salt) {
   1180 	ALLOC(ent->salt);
   1181 	if (ent->salt == NULL)
   1182 	    return ENOMEM;
   1183 	*ent->salt = malloc(key->salt->salt.length + 1);
   1184 	if (*ent->salt == NULL) {
   1185 	    free(ent->salt);
   1186 	    ent->salt = NULL;
   1187 	    return ENOMEM;
   1188 	}
   1189 	memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
   1190 	(*ent->salt)[key->salt->salt.length] = '\0';
   1191     } else
   1192 	ent->salt = NULL;
   1193 
   1194     ent->s2kparams = NULL;
   1195 
   1196     switch (key->key.keytype) {
   1197     case ETYPE_AES128_CTS_HMAC_SHA1_96:
   1198     case ETYPE_AES256_CTS_HMAC_SHA1_96:
   1199 	ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
   1200 			     4, &ent->s2kparams);
   1201 	break;
   1202     case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
   1203     case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
   1204 	ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
   1205 			     4, &ent->s2kparams);
   1206 	break;
   1207     case ETYPE_DES_CBC_CRC:
   1208     case ETYPE_DES_CBC_MD4:
   1209     case ETYPE_DES_CBC_MD5:
   1210 	/* Check if this was a AFS3 salted key */
   1211 	if(key->salt && key->salt->type == hdb_afs3_salt)
   1212 	    ret = make_s2kparams(1, 1, &ent->s2kparams);
   1213 	else
   1214 	    ret = 0;
   1215 	break;
   1216     default:
   1217 	ret = 0;
   1218 	break;
   1219     }
   1220     return ret;
   1221 }
   1222 
   1223 /*
   1224  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
   1225  * database (client supported enctypes first, then the unsupported
   1226  * enctypes).
   1227  */
   1228 
   1229 static krb5_error_code
   1230 get_pa_etype_info2(krb5_context context,
   1231 		   krb5_kdc_configuration *config,
   1232 		   METHOD_DATA *md, Key *ckey)
   1233 {
   1234     krb5_error_code ret = 0;
   1235     ETYPE_INFO2 pa;
   1236     unsigned char *buf;
   1237     size_t len;
   1238 
   1239     pa.len = 1;
   1240     pa.val = calloc(1, sizeof(pa.val[0]));
   1241     if(pa.val == NULL)
   1242 	return ENOMEM;
   1243 
   1244     ret = make_etype_info2_entry(&pa.val[0], ckey);
   1245     if (ret) {
   1246 	free_ETYPE_INFO2(&pa);
   1247 	return ret;
   1248     }
   1249 
   1250     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
   1251     free_ETYPE_INFO2(&pa);
   1252     if(ret)
   1253 	return ret;
   1254     ret = realloc_method_data(md);
   1255     if(ret) {
   1256 	free(buf);
   1257 	return ret;
   1258     }
   1259     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
   1260     md->val[md->len - 1].padata_value.length = len;
   1261     md->val[md->len - 1].padata_value.data = buf;
   1262     return 0;
   1263 }
   1264 
   1265 /*
   1266  *
   1267  */
   1268 
   1269 static void
   1270 log_as_req(krb5_context context,
   1271 	   krb5_kdc_configuration *config,
   1272 	   krb5_enctype cetype,
   1273 	   krb5_enctype setype,
   1274 	   const KDC_REQ_BODY *b)
   1275 {
   1276     krb5_error_code ret;
   1277     struct rk_strpool *p;
   1278     char *str;
   1279     size_t i;
   1280 
   1281     p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
   1282 
   1283     for (i = 0; i < b->etype.len; i++) {
   1284 	ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
   1285 	if (ret == 0) {
   1286 	    p = rk_strpoolprintf(p, "%s", str);
   1287 	    free(str);
   1288 	} else
   1289 	    p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
   1290 	if (p && i + 1 < b->etype.len)
   1291 	    p = rk_strpoolprintf(p, ", ");
   1292 	if (p == NULL) {
   1293 	    kdc_log(context, config, 0, "out of memory");
   1294 	    return;
   1295 	}
   1296     }
   1297     if (p == NULL)
   1298 	p = rk_strpoolprintf(p, "no encryption types");
   1299 
   1300     {
   1301 	char *cet;
   1302 	char *set;
   1303 
   1304 	ret = krb5_enctype_to_string(context, cetype, &cet);
   1305 	if(ret == 0) {
   1306 	    ret = krb5_enctype_to_string(context, setype, &set);
   1307 	    if (ret == 0) {
   1308 		p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
   1309 		free(set);
   1310 	    }
   1311 	    free(cet);
   1312 	}
   1313 	if (ret != 0)
   1314 	    p = rk_strpoolprintf(p, ", using enctypes %d/%d",
   1315 				 cetype, setype);
   1316     }
   1317 
   1318     str = rk_strpoolcollect(p);
   1319     kdc_log(context, config, 0, "%s", str);
   1320     free(str);
   1321 
   1322     {
   1323 	char fixedstr[128];
   1324 	unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
   1325 		      fixedstr, sizeof(fixedstr));
   1326 	if(*fixedstr)
   1327 	    kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
   1328     }
   1329 }
   1330 
   1331 /*
   1332  * verify the flags on `client' and `server', returning 0
   1333  * if they are OK and generating an error messages and returning
   1334  * and error code otherwise.
   1335  */
   1336 
   1337 krb5_error_code
   1338 kdc_check_flags(krb5_context context,
   1339 		krb5_kdc_configuration *config,
   1340 		hdb_entry_ex *client_ex, const char *client_name,
   1341 		hdb_entry_ex *server_ex, const char *server_name,
   1342 		krb5_boolean is_as_req)
   1343 {
   1344     if(client_ex != NULL) {
   1345 	hdb_entry *client = &client_ex->entry;
   1346 
   1347 	/* check client */
   1348 	if (client->flags.locked_out) {
   1349 	    kdc_log(context, config, 0,
   1350 		    "Client (%s) is locked out", client_name);
   1351 	    return KRB5KDC_ERR_POLICY;
   1352 	}
   1353 
   1354 	if (client->flags.invalid) {
   1355 	    kdc_log(context, config, 0,
   1356 		    "Client (%s) has invalid bit set", client_name);
   1357 	    return KRB5KDC_ERR_POLICY;
   1358 	}
   1359 
   1360 	if(!client->flags.client){
   1361 	    kdc_log(context, config, 0,
   1362 		    "Principal may not act as client -- %s", client_name);
   1363 	    return KRB5KDC_ERR_POLICY;
   1364 	}
   1365 
   1366 	if (client->valid_start && *client->valid_start > kdc_time) {
   1367 	    char starttime_str[100];
   1368 	    krb5_format_time(context, *client->valid_start,
   1369 			     starttime_str, sizeof(starttime_str), TRUE);
   1370 	    kdc_log(context, config, 0,
   1371 		    "Client not yet valid until %s -- %s",
   1372 		    starttime_str, client_name);
   1373 	    return KRB5KDC_ERR_CLIENT_NOTYET;
   1374 	}
   1375 
   1376 	if (client->valid_end && *client->valid_end < kdc_time) {
   1377 	    char endtime_str[100];
   1378 	    krb5_format_time(context, *client->valid_end,
   1379 			     endtime_str, sizeof(endtime_str), TRUE);
   1380 	    kdc_log(context, config, 0,
   1381 		    "Client expired at %s -- %s",
   1382 		    endtime_str, client_name);
   1383 	    return KRB5KDC_ERR_NAME_EXP;
   1384 	}
   1385 
   1386 	if (client->flags.require_pwchange &&
   1387 	    (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
   1388 	    kdc_log(context, config, 0,
   1389 		    "Client's key must be changed -- %s", client_name);
   1390 	    return KRB5KDC_ERR_KEY_EXPIRED;
   1391 	}
   1392 
   1393 	if (client->pw_end && *client->pw_end < kdc_time
   1394 	    && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
   1395 	    char pwend_str[100];
   1396 	    krb5_format_time(context, *client->pw_end,
   1397 			     pwend_str, sizeof(pwend_str), TRUE);
   1398 	    kdc_log(context, config, 0,
   1399 		    "Client's key has expired at %s -- %s",
   1400 		    pwend_str, client_name);
   1401 	    return KRB5KDC_ERR_KEY_EXPIRED;
   1402 	}
   1403     }
   1404 
   1405     /* check server */
   1406 
   1407     if (server_ex != NULL) {
   1408 	hdb_entry *server = &server_ex->entry;
   1409 
   1410 	if (server->flags.locked_out) {
   1411 	    kdc_log(context, config, 0,
   1412 		    "Client server locked out -- %s", server_name);
   1413 	    return KRB5KDC_ERR_POLICY;
   1414 	}
   1415 	if (server->flags.invalid) {
   1416 	    kdc_log(context, config, 0,
   1417 		    "Server has invalid flag set -- %s", server_name);
   1418 	    return KRB5KDC_ERR_POLICY;
   1419 	}
   1420 
   1421 	if(!server->flags.server){
   1422 	    kdc_log(context, config, 0,
   1423 		    "Principal may not act as server -- %s", server_name);
   1424 	    return KRB5KDC_ERR_POLICY;
   1425 	}
   1426 
   1427 	if(!is_as_req && server->flags.initial) {
   1428 	    kdc_log(context, config, 0,
   1429 		    "AS-REQ is required for server -- %s", server_name);
   1430 	    return KRB5KDC_ERR_POLICY;
   1431 	}
   1432 
   1433 	if (server->valid_start && *server->valid_start > kdc_time) {
   1434 	    char starttime_str[100];
   1435 	    krb5_format_time(context, *server->valid_start,
   1436 			     starttime_str, sizeof(starttime_str), TRUE);
   1437 	    kdc_log(context, config, 0,
   1438 		    "Server not yet valid until %s -- %s",
   1439 		    starttime_str, server_name);
   1440 	    return KRB5KDC_ERR_SERVICE_NOTYET;
   1441 	}
   1442 
   1443 	if (server->valid_end && *server->valid_end < kdc_time) {
   1444 	    char endtime_str[100];
   1445 	    krb5_format_time(context, *server->valid_end,
   1446 			     endtime_str, sizeof(endtime_str), TRUE);
   1447 	    kdc_log(context, config, 0,
   1448 		    "Server expired at %s -- %s",
   1449 		    endtime_str, server_name);
   1450 	    return KRB5KDC_ERR_SERVICE_EXP;
   1451 	}
   1452 
   1453 	if (server->pw_end && *server->pw_end < kdc_time) {
   1454 	    char pwend_str[100];
   1455 	    krb5_format_time(context, *server->pw_end,
   1456 			     pwend_str, sizeof(pwend_str), TRUE);
   1457 	    kdc_log(context, config, 0,
   1458 		    "Server's key has expired at -- %s",
   1459 		    pwend_str, server_name);
   1460 	    return KRB5KDC_ERR_KEY_EXPIRED;
   1461 	}
   1462     }
   1463     return 0;
   1464 }
   1465 
   1466 /*
   1467  * Return TRUE if `from' is part of `addresses' taking into consideration
   1468  * the configuration variables that tells us how strict we should be about
   1469  * these checks
   1470  */
   1471 
   1472 krb5_boolean
   1473 _kdc_check_addresses(krb5_context context,
   1474 		     krb5_kdc_configuration *config,
   1475 		     HostAddresses *addresses, const struct sockaddr *from)
   1476 {
   1477     krb5_error_code ret;
   1478     krb5_address addr;
   1479     krb5_boolean result;
   1480     krb5_boolean only_netbios = TRUE;
   1481     size_t i;
   1482 
   1483     if(config->check_ticket_addresses == 0)
   1484 	return TRUE;
   1485 
   1486     if(addresses == NULL)
   1487 	return config->allow_null_ticket_addresses;
   1488 
   1489     for (i = 0; i < addresses->len; ++i) {
   1490 	if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
   1491 	    only_netbios = FALSE;
   1492 	}
   1493     }
   1494 
   1495     /* Windows sends it's netbios name, which I can only assume is
   1496      * used for the 'allowed workstations' check.  This is painful,
   1497      * but we still want to check IP addresses if they happen to be
   1498      * present.
   1499      */
   1500 
   1501     if(only_netbios)
   1502 	return config->allow_null_ticket_addresses;
   1503 
   1504     ret = krb5_sockaddr2address (context, from, &addr);
   1505     if(ret)
   1506 	return FALSE;
   1507 
   1508     result = krb5_address_search(context, &addr, addresses);
   1509     krb5_free_address (context, &addr);
   1510     return result;
   1511 }
   1512 
   1513 /*
   1514  *
   1515  */
   1516 krb5_error_code
   1517 _kdc_check_anon_policy (krb5_context context,
   1518 			krb5_kdc_configuration *config,
   1519 			hdb_entry_ex *client,
   1520 			hdb_entry_ex *server)
   1521 {
   1522     if (!config->allow_anonymous){
   1523 	kdc_log(context, config, 0,
   1524 		"Request for anonymous ticket denied by local policy");
   1525 	return KRB5KDC_ERR_POLICY;
   1526     }
   1527 
   1528     return 0;
   1529 }
   1530 
   1531 /*
   1532  *
   1533  */
   1534 
   1535 static krb5_boolean
   1536 send_pac_p(krb5_context context, KDC_REQ *req)
   1537 {
   1538     krb5_error_code ret;
   1539     PA_PAC_REQUEST pacreq;
   1540     const PA_DATA *pa;
   1541     int i = 0;
   1542 
   1543     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
   1544     if (pa == NULL)
   1545 	return TRUE;
   1546 
   1547     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
   1548 				pa->padata_value.length,
   1549 				&pacreq,
   1550 				NULL);
   1551     if (ret)
   1552 	return TRUE;
   1553     i = pacreq.include_pac;
   1554     free_PA_PAC_REQUEST(&pacreq);
   1555     if (i == 0)
   1556 	return FALSE;
   1557     return TRUE;
   1558 }
   1559 
   1560 /*
   1561  *
   1562  */
   1563 
   1564 static krb5_error_code
   1565 generate_pac(kdc_request_t r, Key *skey)
   1566 {
   1567     krb5_error_code ret;
   1568     krb5_pac p = NULL;
   1569     krb5_data data;
   1570 
   1571     ret = _kdc_pac_generate(r->context, r->client, &p);
   1572     if (ret) {
   1573 	_kdc_r_log(r, 0, "PAC generation failed for -- %s",
   1574 		   r->client_name);
   1575 	return ret;
   1576     }
   1577     if (p == NULL)
   1578 	return 0;
   1579 
   1580     ret = _krb5_pac_sign(r->context, p, r->et.authtime,
   1581 			 r->client->entry.principal,
   1582 			 &skey->key, /* Server key */
   1583 			 &skey->key, /* FIXME: should be krbtgt key */
   1584 			 &data);
   1585     krb5_pac_free(r->context, p);
   1586     if (ret) {
   1587 	_kdc_r_log(r, 0, "PAC signing failed for -- %s",
   1588 		   r->client_name);
   1589 	return ret;
   1590     }
   1591 
   1592     ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
   1593 				      KRB5_AUTHDATA_WIN2K_PAC,
   1594 				      &data);
   1595     krb5_data_free(&data);
   1596 
   1597     return ret;
   1598 }
   1599 
   1600 /*
   1601  *
   1602  */
   1603 
   1604 krb5_boolean
   1605 _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
   1606 {
   1607     return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
   1608 }
   1609 
   1610 static int
   1611 require_preauth_p(kdc_request_t r)
   1612 {
   1613     return r->config->require_preauth
   1614 	|| r->client->entry.flags.require_preauth
   1615 	|| r->server->entry.flags.require_preauth;
   1616 }
   1617 
   1618 
   1619 /*
   1620  *
   1621  */
   1622 
   1623 static krb5_error_code
   1624 add_enc_pa_rep(kdc_request_t r)
   1625 {
   1626     krb5_error_code ret;
   1627     krb5_crypto crypto;
   1628     Checksum checksum;
   1629     krb5_data cdata;
   1630     size_t len;
   1631 
   1632     ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
   1633     if (ret)
   1634 	return ret;
   1635 
   1636     ret = krb5_create_checksum(r->context, crypto,
   1637 			       KRB5_KU_AS_REQ, 0,
   1638 			       r->request.data, r->request.length,
   1639 			       &checksum);
   1640     krb5_crypto_destroy(r->context, crypto);
   1641     if (ret)
   1642 	return ret;
   1643 
   1644     ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
   1645 		       &checksum, &len, ret);
   1646     free_Checksum(&checksum);
   1647     if (ret)
   1648 	return ret;
   1649     heim_assert(cdata.length == len, "ASN.1 internal error");
   1650 
   1651     if (r->ek.encrypted_pa_data == NULL) {
   1652 	ALLOC(r->ek.encrypted_pa_data);
   1653 	if (r->ek.encrypted_pa_data == NULL)
   1654 	    return ENOMEM;
   1655     }
   1656     ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
   1657 			  KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
   1658     if (ret)
   1659 	return ret;
   1660 
   1661     return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
   1662 			   KRB5_PADATA_FX_FAST, NULL, 0);
   1663 }
   1664 
   1665 /*
   1666  *
   1667  */
   1668 
   1669 krb5_error_code
   1670 _kdc_as_rep(kdc_request_t r,
   1671 	    krb5_data *reply,
   1672 	    const char *from,
   1673 	    struct sockaddr *from_addr,
   1674 	    int datagram_reply)
   1675 {
   1676     krb5_context context = r->context;
   1677     krb5_kdc_configuration *config = r->config;
   1678     KDC_REQ *req = &r->req;
   1679     KDC_REQ_BODY *b = NULL;
   1680     AS_REP rep;
   1681     KDCOptions f;
   1682     krb5_enctype setype;
   1683     krb5_error_code ret = 0;
   1684     Key *skey;
   1685     int found_pa = 0;
   1686     int i, flags = HDB_F_FOR_AS_REQ;
   1687     METHOD_DATA error_method;
   1688     const PA_DATA *pa;
   1689 
   1690     memset(&rep, 0, sizeof(rep));
   1691     error_method.len = 0;
   1692     error_method.val = NULL;
   1693 
   1694     /*
   1695      * Look for FAST armor and unwrap
   1696      */
   1697     ret = _kdc_fast_unwrap_request(r);
   1698     if (ret) {
   1699 	_kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
   1700 	goto out;
   1701     }
   1702 
   1703     b = &req->req_body;
   1704     f = b->kdc_options;
   1705 
   1706     if (f.canonicalize)
   1707 	flags |= HDB_F_CANON;
   1708 
   1709     if(b->sname == NULL){
   1710 	ret = KRB5KRB_ERR_GENERIC;
   1711 	_kdc_set_e_text(r, "No server in request");
   1712     } else{
   1713 	ret = _krb5_principalname2krb5_principal (context,
   1714 						  &r->server_princ,
   1715 						  *(b->sname),
   1716 						  b->realm);
   1717 	if (ret == 0)
   1718 	    ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
   1719     }
   1720     if (ret) {
   1721 	kdc_log(context, config, 0,
   1722 		"AS-REQ malformed server name from %s", from);
   1723 	goto out;
   1724     }
   1725     if(b->cname == NULL){
   1726 	ret = KRB5KRB_ERR_GENERIC;
   1727 	_kdc_set_e_text(r, "No client in request");
   1728     } else {
   1729 	ret = _krb5_principalname2krb5_principal (context,
   1730 						  &r->client_princ,
   1731 						  *(b->cname),
   1732 						  b->realm);
   1733 	if (ret)
   1734 	    goto out;
   1735 
   1736 	ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
   1737     }
   1738     if (ret) {
   1739 	kdc_log(context, config, 0,
   1740 		"AS-REQ malformed client name from %s", from);
   1741 	goto out;
   1742     }
   1743 
   1744     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
   1745 	    r->client_name, from, r->server_name);
   1746 
   1747     /*
   1748      *
   1749      */
   1750 
   1751     if (_kdc_is_anonymous(context, r->client_princ) &&
   1752 	!_kdc_is_anon_request(&r->req)) {
   1753 	kdc_log(context, config, 0, "Anonymous client w/o anonymous flag");
   1754 	ret = KRB5KDC_ERR_BADOPTION;
   1755 	goto out;
   1756     }
   1757 
   1758     /*
   1759      *
   1760      */
   1761 
   1762     ret = _kdc_db_fetch(context, config, r->client_princ,
   1763 			HDB_F_GET_CLIENT | flags, NULL,
   1764 			&r->clientdb, &r->client);
   1765     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1766 	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
   1767 		r->client_name);
   1768 	goto out;
   1769     } else if (ret == HDB_ERR_WRONG_REALM) {
   1770 	char *fixed_client_name = NULL;
   1771 
   1772 	ret = krb5_unparse_name(context, r->client->entry.principal,
   1773 				&fixed_client_name);
   1774 	if (ret) {
   1775 	    goto out;
   1776 	}
   1777 
   1778 	kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
   1779 		r->client_name, fixed_client_name);
   1780 	free(fixed_client_name);
   1781 
   1782 	ret = _kdc_fast_mk_error(context, r,
   1783 				 &error_method,
   1784 				 r->armor_crypto,
   1785 				 &req->req_body,
   1786 				 KRB5_KDC_ERR_WRONG_REALM,
   1787 				 NULL,
   1788 				 r->server_princ,
   1789 				 NULL,
   1790 				 &r->client->entry.principal->realm,
   1791 				 NULL, NULL,
   1792 				 reply);
   1793 	goto out;
   1794     } else if(ret){
   1795 	const char *msg = krb5_get_error_message(context, ret);
   1796 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
   1797 	krb5_free_error_message(context, msg);
   1798 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   1799 	goto out;
   1800     }
   1801     ret = _kdc_db_fetch(context, config, r->server_princ,
   1802 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
   1803 			NULL, NULL, &r->server);
   1804     if(ret == HDB_ERR_NOT_FOUND_HERE) {
   1805 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
   1806 		r->server_name);
   1807 	goto out;
   1808     } else if(ret){
   1809 	const char *msg = krb5_get_error_message(context, ret);
   1810 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
   1811 	krb5_free_error_message(context, msg);
   1812 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
   1813 	goto out;
   1814     }
   1815 
   1816     /*
   1817      * Select a session enctype from the list of the crypto system
   1818      * supported enctypes that is supported by the client and is one of
   1819      * the enctype of the enctype of the service (likely krbtgt).
   1820      *
   1821      * The latter is used as a hint of what enctypes all KDC support,
   1822      * to make sure a newer version of KDC won't generate a session
   1823      * enctype that an older version of a KDC in the same realm can't
   1824      * decrypt.
   1825      */
   1826 
   1827     ret = _kdc_find_etype(context,
   1828 			  krb5_principal_is_krbtgt(context, r->server_princ) ?
   1829 			  config->tgt_use_strongest_session_key :
   1830 			  config->svc_use_strongest_session_key, FALSE,
   1831 			  r->client, b->etype.val, b->etype.len, &r->sessionetype,
   1832 			  NULL);
   1833     if (ret) {
   1834 	kdc_log(context, config, 0,
   1835 		"Client (%s) from %s has no common enctypes with KDC "
   1836 		"to use for the session key",
   1837 		r->client_name, from);
   1838 	goto out;
   1839     }
   1840 
   1841     /*
   1842      * Pre-auth processing
   1843      */
   1844 
   1845     if(req->padata){
   1846 	unsigned int n;
   1847 
   1848 	log_patypes(context, config, req->padata);
   1849 
   1850 	/* Check if preauth matching */
   1851 
   1852 	for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
   1853 	    if (pat[n].validate == NULL)
   1854 		continue;
   1855 	    if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
   1856 		continue;
   1857 
   1858 	    kdc_log(context, config, 5,
   1859 		    "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
   1860 	    i = 0;
   1861 	    pa = _kdc_find_padata(req, &i, pat[n].type);
   1862 	    if (pa) {
   1863 		ret = pat[n].validate(r, pa);
   1864 		if (ret != 0) {
   1865 		    goto out;
   1866 		}
   1867 		kdc_log(context, config, 0,
   1868 			"%s pre-authentication succeeded -- %s",
   1869 			pat[n].name, r->client_name);
   1870 		found_pa = 1;
   1871 		r->et.flags.pre_authent = 1;
   1872 	    }
   1873 	}
   1874     }
   1875 
   1876     if (found_pa == 0) {
   1877 	Key *ckey = NULL;
   1878 	size_t n;
   1879 
   1880 	for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
   1881 	    if ((pat[n].flags & PA_ANNOUNCE) == 0)
   1882 		continue;
   1883 	    ret = krb5_padata_add(context, &error_method,
   1884 				  pat[n].type, NULL, 0);
   1885 	    if (ret)
   1886 		goto out;
   1887 	}
   1888 
   1889 	/*
   1890 	 * If there is a client key, send ETYPE_INFO{,2}
   1891 	 */
   1892 	ret = _kdc_find_etype(context,
   1893 			      config->preauth_use_strongest_session_key, TRUE,
   1894 			      r->client, b->etype.val, b->etype.len, NULL, &ckey);
   1895 	if (ret == 0) {
   1896 
   1897 	    /*
   1898 	     * RFC4120 requires:
   1899 	     * - If the client only knows about old enctypes, then send
   1900 	     *   both info replies (we send 'info' first in the list).
   1901 	     * - If the client is 'modern', because it knows about 'new'
   1902 	     *   enctype types, then only send the 'info2' reply.
   1903 	     *
   1904 	     * Before we send the full list of etype-info data, we pick
   1905 	     * the client key we would have used anyway below, just pick
   1906 	     * that instead.
   1907 	     */
   1908 
   1909 	    if (older_enctype(ckey->key.keytype)) {
   1910 		ret = get_pa_etype_info(context, config,
   1911 					&error_method, ckey);
   1912 		if (ret)
   1913 		    goto out;
   1914 	    }
   1915 	    ret = get_pa_etype_info2(context, config,
   1916 				     &error_method, ckey);
   1917 	    if (ret)
   1918 		goto out;
   1919 	}
   1920 
   1921 	/*
   1922 	 * send requre preauth is its required or anon is requested,
   1923 	 * anon is today only allowed via preauth mechanisms.
   1924 	 */
   1925 	if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
   1926 	    ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
   1927 	    _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
   1928 	    goto out;
   1929 	}
   1930 
   1931 	if (ckey == NULL) {
   1932 	    ret = KRB5KDC_ERR_CLIENT_NOTYET;
   1933 	    _kdc_set_e_text(r, "Doesn't have a client key available");
   1934 	    goto out;
   1935 	}
   1936 	krb5_free_keyblock_contents(r->context,  &r->reply_key);
   1937 	ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
   1938 	if (ret)
   1939 	    goto out;
   1940     }
   1941 
   1942     if (r->clientdb->hdb_auth_status) {
   1943 	r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
   1944 				     HDB_AUTH_SUCCESS);
   1945     }
   1946 
   1947     /*
   1948      * Verify flags after the user been required to prove its identity
   1949      * with in a preauth mech.
   1950      */
   1951 
   1952     ret = _kdc_check_access(context, config, r->client, r->client_name,
   1953 			    r->server, r->server_name,
   1954 			    req, &error_method);
   1955     if(ret)
   1956 	goto out;
   1957 
   1958     if (_kdc_is_anon_request(&r->req)) {
   1959 	ret = _kdc_check_anon_policy(context, config, r->client, r->server);
   1960 	if (ret) {
   1961 	    _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
   1962 	    goto out;
   1963 	}
   1964 
   1965 	r->et.flags.anonymous = 1;
   1966     }
   1967 
   1968     /*
   1969      * Select the best encryption type for the KDC with out regard to
   1970      * the client since the client never needs to read that data.
   1971      */
   1972 
   1973     ret = _kdc_get_preferred_key(context, config,
   1974 				 r->server, r->server_name,
   1975 				 &setype, &skey);
   1976     if(ret)
   1977 	goto out;
   1978 
   1979     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
   1980 	ret = KRB5KDC_ERR_BADOPTION;
   1981 	_kdc_set_e_text(r, "Bad KDC options");
   1982 	goto out;
   1983     }
   1984 
   1985     /*
   1986      * Build reply
   1987      */
   1988 
   1989     rep.pvno = 5;
   1990     rep.msg_type = krb_as_rep;
   1991 
   1992     if (!config->historical_anon_realm &&
   1993         _kdc_is_anonymous(context, r->client_princ)) {
   1994 	Realm anon_realm = KRB5_ANON_REALM;
   1995 	ret = copy_Realm(&anon_realm, &rep.crealm);
   1996     } else
   1997 	ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
   1998     if (ret)
   1999 	goto out;
   2000     if (r->et.flags.anonymous)
   2001 	ret = _kdc_make_anonymous_principalname(&rep.cname);
   2002     else
   2003         ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
   2004     if (ret)
   2005 	goto out;
   2006 
   2007     rep.ticket.tkt_vno = 5;
   2008     ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
   2009     if (ret)
   2010 	goto out;
   2011     _krb5_principal2principalname(&rep.ticket.sname,
   2012 				  r->server->entry.principal);
   2013     /* java 1.6 expects the name to be the same type, lets allow that
   2014      * uncomplicated name-types. */
   2015 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
   2016     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
   2017 	rep.ticket.sname.name_type = b->sname->name_type;
   2018 #undef CNT
   2019 
   2020     r->et.flags.initial = 1;
   2021     if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
   2022 	r->et.flags.forwardable = f.forwardable;
   2023     else if (f.forwardable) {
   2024 	_kdc_set_e_text(r, "Ticket may not be forwardable");
   2025 	ret = KRB5KDC_ERR_POLICY;
   2026 	goto out;
   2027     }
   2028     if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
   2029 	r->et.flags.proxiable = f.proxiable;
   2030     else if (f.proxiable) {
   2031 	_kdc_set_e_text(r, "Ticket may not be proxiable");
   2032 	ret = KRB5KDC_ERR_POLICY;
   2033 	goto out;
   2034     }
   2035     if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
   2036 	r->et.flags.may_postdate = f.allow_postdate;
   2037     else if (f.allow_postdate){
   2038 	_kdc_set_e_text(r, "Ticket may not be postdate");
   2039 	ret = KRB5KDC_ERR_POLICY;
   2040 	goto out;
   2041     }
   2042 
   2043     /* check for valid set of addresses */
   2044     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
   2045 	_kdc_set_e_text(r, "Bad address list in requested");
   2046 	ret = KRB5KRB_AP_ERR_BADADDR;
   2047 	goto out;
   2048     }
   2049 
   2050     ret = copy_PrincipalName(&rep.cname, &r->et.cname);
   2051     if (ret)
   2052 	goto out;
   2053     ret = copy_Realm(&rep.crealm, &r->et.crealm);
   2054     if (ret)
   2055 	goto out;
   2056 
   2057     {
   2058 	time_t start;
   2059 	time_t t;
   2060 
   2061 	start = r->et.authtime = kdc_time;
   2062 
   2063 	if(f.postdated && req->req_body.from){
   2064 	    ALLOC(r->et.starttime);
   2065 	    start = *r->et.starttime = *req->req_body.from;
   2066 	    r->et.flags.invalid = 1;
   2067 	    r->et.flags.postdated = 1; /* XXX ??? */
   2068 	}
   2069 	_kdc_fix_time(&b->till);
   2070 	t = *b->till;
   2071 
   2072 	/* be careful not overflowing */
   2073 
   2074 	if(r->client->entry.max_life)
   2075 	    t = start + min(t - start, *r->client->entry.max_life);
   2076 	if(r->server->entry.max_life)
   2077 	    t = start + min(t - start, *r->server->entry.max_life);
   2078 #if 0
   2079 	t = min(t, start + realm->max_life);
   2080 #endif
   2081 	r->et.endtime = t;
   2082 	if(f.renewable_ok && r->et.endtime < *b->till){
   2083 	    f.renewable = 1;
   2084 	    if(b->rtime == NULL){
   2085 		ALLOC(b->rtime);
   2086 		*b->rtime = 0;
   2087 	    }
   2088 	    if(*b->rtime < *b->till)
   2089 		*b->rtime = *b->till;
   2090 	}
   2091 	if(f.renewable && b->rtime){
   2092 	    t = *b->rtime;
   2093 	    if(t == 0)
   2094 		t = MAX_TIME;
   2095 	    if(r->client->entry.max_renew)
   2096 		t = start + min(t - start, *r->client->entry.max_renew);
   2097 	    if(r->server->entry.max_renew)
   2098 		t = start + min(t - start, *r->server->entry.max_renew);
   2099 #if 0
   2100 	    t = min(t, start + realm->max_renew);
   2101 #endif
   2102 	    ALLOC(r->et.renew_till);
   2103 	    *r->et.renew_till = t;
   2104 	    r->et.flags.renewable = 1;
   2105 	}
   2106     }
   2107 
   2108     if(b->addresses){
   2109 	ALLOC(r->et.caddr);
   2110 	copy_HostAddresses(b->addresses, r->et.caddr);
   2111     }
   2112 
   2113     r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
   2114     krb5_data_zero(&r->et.transited.contents);
   2115 
   2116     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
   2117      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
   2118      * incapable of correctly decoding SEQUENCE OF's of zero length.
   2119      *
   2120      * To fix this, always send at least one no-op last_req
   2121      *
   2122      * If there's a pw_end or valid_end we will use that,
   2123      * otherwise just a dummy lr.
   2124      */
   2125     r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
   2126     if (r->ek.last_req.val == NULL) {
   2127 	ret = ENOMEM;
   2128 	goto out;
   2129     }
   2130     r->ek.last_req.len = 0;
   2131     if (r->client->entry.pw_end
   2132 	&& (config->kdc_warn_pwexpire == 0
   2133 	    || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
   2134 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
   2135 	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
   2136 	++r->ek.last_req.len;
   2137     }
   2138     if (r->client->entry.valid_end) {
   2139 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
   2140 	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
   2141 	++r->ek.last_req.len;
   2142     }
   2143     if (r->ek.last_req.len == 0) {
   2144 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_NONE;
   2145 	r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
   2146 	++r->ek.last_req.len;
   2147     }
   2148     r->ek.nonce = b->nonce;
   2149     if (r->client->entry.valid_end || r->client->entry.pw_end) {
   2150 	ALLOC(r->ek.key_expiration);
   2151 	if (r->client->entry.valid_end) {
   2152 	    if (r->client->entry.pw_end)
   2153 		*r->ek.key_expiration = min(*r->client->entry.valid_end,
   2154 					 *r->client->entry.pw_end);
   2155 	    else
   2156 		*r->ek.key_expiration = *r->client->entry.valid_end;
   2157 	} else
   2158 	    *r->ek.key_expiration = *r->client->entry.pw_end;
   2159     } else
   2160 	r->ek.key_expiration = NULL;
   2161     r->ek.flags = r->et.flags;
   2162     r->ek.authtime = r->et.authtime;
   2163     if (r->et.starttime) {
   2164 	ALLOC(r->ek.starttime);
   2165 	*r->ek.starttime = *r->et.starttime;
   2166     }
   2167     r->ek.endtime = r->et.endtime;
   2168     if (r->et.renew_till) {
   2169 	ALLOC(r->ek.renew_till);
   2170 	*r->ek.renew_till = *r->et.renew_till;
   2171     }
   2172     ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
   2173     if (ret)
   2174 	goto out;
   2175     ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
   2176     if (ret)
   2177 	goto out;
   2178     if(r->et.caddr){
   2179 	ALLOC(r->ek.caddr);
   2180 	copy_HostAddresses(r->et.caddr, r->ek.caddr);
   2181     }
   2182 
   2183     /*
   2184      * Check and session and reply keys
   2185      */
   2186 
   2187     if (r->session_key.keytype == ETYPE_NULL) {
   2188 	ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
   2189 	if (ret)
   2190 	    goto out;
   2191     }
   2192 
   2193     if (r->reply_key.keytype == ETYPE_NULL) {
   2194 	_kdc_set_e_text(r, "Client have no reply key");
   2195 	ret = KRB5KDC_ERR_CLIENT_NOTYET;
   2196 	goto out;
   2197     }
   2198 
   2199     ret = copy_EncryptionKey(&r->session_key, &r->et.key);
   2200     if (ret)
   2201 	goto out;
   2202 
   2203     ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
   2204     if (ret)
   2205 	goto out;
   2206 
   2207     if (r->outpadata.len) {
   2208 
   2209 	ALLOC(rep.padata);
   2210 	if (rep.padata == NULL) {
   2211 	    ret = ENOMEM;
   2212 	    goto out;
   2213 	}
   2214 	ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
   2215 	if (ret)
   2216 	    goto out;
   2217     }
   2218 
   2219     /* Add the PAC */
   2220     if (send_pac_p(context, req) && !r->et.flags.anonymous) {
   2221 	generate_pac(r, skey);
   2222     }
   2223 
   2224     _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
   2225 		       r->et.endtime, r->et.renew_till);
   2226 
   2227     {
   2228 	krb5_principal client_principal;
   2229 
   2230 	ret = _krb5_principalname2krb5_principal(context, &client_principal,
   2231 						 rep.cname, rep.crealm);
   2232 	if (ret)
   2233 	    goto out;
   2234 
   2235 	/* do this as the last thing since this signs the EncTicketPart */
   2236 	ret = _kdc_add_KRB5SignedPath(context,
   2237 				      config,
   2238 				      r->server,
   2239 				      setype,
   2240 				      client_principal,
   2241 				      NULL,
   2242 				      NULL,
   2243 				      &r->et);
   2244 	krb5_free_principal(context, client_principal);
   2245 	if (ret)
   2246 	    goto out;
   2247     }
   2248 
   2249     log_as_req(context, config, r->reply_key.keytype, setype, b);
   2250 
   2251     /*
   2252      * We always say we support FAST/enc-pa-rep
   2253      */
   2254 
   2255     r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
   2256 
   2257     /*
   2258      * Add REQ_ENC_PA_REP if client supports it
   2259      */
   2260 
   2261     i = 0;
   2262     pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
   2263     if (pa) {
   2264 
   2265 	ret = add_enc_pa_rep(r);
   2266 	if (ret) {
   2267 	    const char *msg = krb5_get_error_message(r->context, ret);
   2268 	    _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
   2269 	    krb5_free_error_message(r->context, msg);
   2270 	    goto out;
   2271 	}
   2272     }
   2273 
   2274     /*
   2275      *
   2276      */
   2277 
   2278     ret = _kdc_encode_reply(context, config,
   2279 			    r->armor_crypto, req->req_body.nonce,
   2280 			    &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
   2281 			    &skey->key, r->client->entry.kvno,
   2282 			    &r->reply_key, 0, &r->e_text, reply);
   2283     if (ret)
   2284 	goto out;
   2285 
   2286     /*
   2287      * Check if message too large
   2288      */
   2289     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
   2290 	krb5_data_free(reply);
   2291 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
   2292 	_kdc_set_e_text(r, "Reply packet too large");
   2293     }
   2294 
   2295 out:
   2296     free_AS_REP(&rep);
   2297 
   2298     /*
   2299      * In case of a non proxy error, build an error message.
   2300      */
   2301     if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
   2302 	ret = _kdc_fast_mk_error(context, r,
   2303 				 &error_method,
   2304 				 r->armor_crypto,
   2305 				 &req->req_body,
   2306 				 ret, r->e_text,
   2307 				 r->server_princ,
   2308 				 r->client_princ ?
   2309                                      &r->client_princ->name : NULL,
   2310 				 r->client_princ ?
   2311                                      &r->client_princ->realm : NULL,
   2312 				 NULL, NULL,
   2313 				 reply);
   2314 	if (ret)
   2315 	    goto out2;
   2316     }
   2317 out2:
   2318     free_EncTicketPart(&r->et);
   2319     free_EncKDCRepPart(&r->ek);
   2320     free_KDCFastState(&r->fast);
   2321 
   2322     if (error_method.len)
   2323 	free_METHOD_DATA(&error_method);
   2324     if (r->outpadata.len)
   2325 	free_METHOD_DATA(&r->outpadata);
   2326     if (r->client_princ) {
   2327 	krb5_free_principal(context, r->client_princ);
   2328 	r->client_princ = NULL;
   2329     }
   2330     if (r->client_name) {
   2331 	free(r->client_name);
   2332 	r->client_name = NULL;
   2333     }
   2334     if (r->server_princ){
   2335 	krb5_free_principal(context, r->server_princ);
   2336 	r->server_princ = NULL;
   2337     }
   2338     if (r->server_name) {
   2339 	free(r->server_name);
   2340 	r->server_name = NULL;
   2341     }
   2342     if (r->client)
   2343 	_kdc_free_ent(context, r->client);
   2344     if (r->server)
   2345 	_kdc_free_ent(context, r->server);
   2346     if (r->armor_crypto) {
   2347 	krb5_crypto_destroy(r->context, r->armor_crypto);
   2348 	r->armor_crypto = NULL;
   2349     }
   2350     krb5_free_keyblock_contents(r->context, &r->reply_key);
   2351     krb5_free_keyblock_contents(r->context, &r->session_key);
   2352     return ret;
   2353 }
   2354 
   2355 /*
   2356  * Add the AuthorizationData `data of `type to the last element in
   2357  * the sequence of authorization_data in `tkt wrapped in an IF_RELEVANT
   2358  */
   2359 
   2360 krb5_error_code
   2361 _kdc_tkt_add_if_relevant_ad(krb5_context context,
   2362 			    EncTicketPart *tkt,
   2363 			    int type,
   2364 			    const krb5_data *data)
   2365 {
   2366     krb5_error_code ret;
   2367     size_t size = 0;
   2368 
   2369     if (tkt->authorization_data == NULL) {
   2370 	tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
   2371 	if (tkt->authorization_data == NULL) {
   2372 	    krb5_set_error_message(context, ENOMEM, "out of memory");
   2373 	    return ENOMEM;
   2374 	}
   2375     }
   2376 
   2377     /* add the entry to the last element */
   2378     {
   2379 	AuthorizationData ad = { 0, NULL };
   2380 	AuthorizationDataElement ade;
   2381 
   2382 	ade.ad_type = type;
   2383 	ade.ad_data = *data;
   2384 
   2385 	ret = add_AuthorizationData(&ad, &ade);
   2386 	if (ret) {
   2387 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
   2388 	    return ret;
   2389 	}
   2390 
   2391 	ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
   2392 
   2393 	ASN1_MALLOC_ENCODE(AuthorizationData,
   2394 			   ade.ad_data.data, ade.ad_data.length,
   2395 			   &ad, &size, ret);
   2396 	free_AuthorizationData(&ad);
   2397 	if (ret) {
   2398 	    krb5_set_error_message(context, ret, "ASN.1 encode of "
   2399 				   "AuthorizationData failed");
   2400 	    return ret;
   2401 	}
   2402 	if (ade.ad_data.length != size)
   2403 	    krb5_abortx(context, "internal asn.1 encoder error");
   2404 
   2405 	ret = add_AuthorizationData(tkt->authorization_data, &ade);
   2406 	der_free_octet_string(&ade.ad_data);
   2407 	if (ret) {
   2408 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
   2409 	    return ret;
   2410 	}
   2411     }
   2412 
   2413     return 0;
   2414 }
   2415