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