1/*	$NetBSD: kerberos5.c,v 1.9 2023/06/19 21:41:41 christos Exp $	*/
2
3/*
4 * Copyright (c) 1997-2007 Kungliga Tekniska H��gskolan
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
40void
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
50static int
51realloc_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
62static void
63set_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
73const 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
92krb5_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
109static krb5_boolean
110is_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
130static krb5_boolean
131is_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
139krb5_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
161krb5_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
284krb5_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
303failed:
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
313static 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
324static 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
331void
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
367static krb5_error_code
368pa_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
422static krb5_error_code
423make_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
469static krb5_error_code
470pa_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
620static krb5_error_code
621pa_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
769struct 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
778static 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
814static void
815log_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
851krb5_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
1035static int
1036older_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
1062static krb5_error_code
1063make_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
1110static krb5_error_code
1111get_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
1151extern int _krb5_AES_SHA1_string_to_default_iterator;
1152extern int _krb5_AES_SHA2_string_to_default_iterator;
1153
1154static krb5_error_code
1155make_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
1173static krb5_error_code
1174make_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
1229static krb5_error_code
1230get_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
1269static void
1270log_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
1337krb5_error_code
1338kdc_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
1472krb5_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 */
1516krb5_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
1535static krb5_boolean
1536send_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
1564static krb5_error_code
1565generate_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
1604krb5_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
1610static int
1611require_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
1623static krb5_error_code
1624add_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
1669krb5_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
2295out:
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    }
2317out2:
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
2360krb5_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