1 /*
2  * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "kdc_locl.h"
35 
36 RCSID("$Id: kerberos5.c,v 1.225 2006/11/10 03:36:32 lha Exp $");
37 
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39 
40 void
_kdc_fix_time(time_t ** t)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
realloc_method_data(METHOD_DATA * md)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
set_salt_padata(METHOD_DATA * md,Salt * salt)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 PA_DATA*
_kdc_find_padata(KDC_REQ * req,int * start,int type)74 _kdc_find_padata(KDC_REQ *req, int *start, int type)
75 {
76     while(*start < req->padata->len){
77 	(*start)++;
78 	if(req->padata->val[*start - 1].padata_type == type)
79 	    return &req->padata->val[*start - 1];
80     }
81     return NULL;
82 }
83 
84 /*
85  * return the first appropriate key of `princ' in `ret_key'.  Look for
86  * all the etypes in (`etypes', `len'), stopping as soon as we find
87  * one, but preferring one that has default salt
88  */
89 
90 krb5_error_code
_kdc_find_etype(krb5_context context,const hdb_entry_ex * princ,krb5_enctype * etypes,unsigned len,Key ** ret_key,krb5_enctype * ret_etype)91 _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ,
92 		krb5_enctype *etypes, unsigned len,
93 		Key **ret_key, krb5_enctype *ret_etype)
94 {
95     int i;
96     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
97 
98     for(i = 0; ret != 0 && i < len ; i++) {
99 	Key *key = NULL;
100 
101 	if (krb5_enctype_valid(context, etypes[i]) != 0)
102 	    continue;
103 
104 	while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
105 	    if (key->key.keyvalue.length == 0) {
106 		ret = KRB5KDC_ERR_NULL_KEY;
107 		continue;
108 	    }
109 	    *ret_key   = key;
110 	    *ret_etype = etypes[i];
111 	    ret = 0;
112 	    if (key->salt == NULL)
113 		return ret;
114 	}
115     }
116     return ret;
117 }
118 
119 krb5_error_code
_kdc_make_anonymous_principalname(PrincipalName * pn)120 _kdc_make_anonymous_principalname (PrincipalName *pn)
121 {
122     pn->name_type = KRB5_NT_PRINCIPAL;
123     pn->name_string.len = 1;
124     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
125     if (pn->name_string.val == NULL)
126 	return ENOMEM;
127     pn->name_string.val[0] = strdup("anonymous");
128     if (pn->name_string.val[0] == NULL) {
129 	free(pn->name_string.val);
130 	pn->name_string.val = NULL;
131 	return ENOMEM;
132     }
133     return 0;
134 }
135 
136 void
_kdc_log_timestamp(krb5_context context,krb5_kdc_configuration * config,const char * type,KerberosTime authtime,KerberosTime * starttime,KerberosTime endtime,KerberosTime * renew_till)137 _kdc_log_timestamp(krb5_context context,
138 		   krb5_kdc_configuration *config,
139 		   const char *type,
140 		   KerberosTime authtime, KerberosTime *starttime,
141 		   KerberosTime endtime, KerberosTime *renew_till)
142 {
143     char authtime_str[100], starttime_str[100],
144 	endtime_str[100], renewtime_str[100];
145 
146     krb5_format_time(context, authtime,
147 		     authtime_str, sizeof(authtime_str), TRUE);
148     if (starttime)
149 	krb5_format_time(context, *starttime,
150 			 starttime_str, sizeof(starttime_str), TRUE);
151     else
152 	strlcpy(starttime_str, "unset", sizeof(starttime_str));
153     krb5_format_time(context, endtime,
154 		     endtime_str, sizeof(endtime_str), TRUE);
155     if (renew_till)
156 	krb5_format_time(context, *renew_till,
157 			 renewtime_str, sizeof(renewtime_str), TRUE);
158     else
159 	strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
160 
161     kdc_log(context, config, 5,
162 	    "%s authtime: %s starttime: %s endtime: %s renew till: %s",
163 	    type, authtime_str, starttime_str, endtime_str, renewtime_str);
164 }
165 
166 static void
log_patypes(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * padata)167 log_patypes(krb5_context context,
168 	    krb5_kdc_configuration *config,
169 	    METHOD_DATA *padata)
170 {
171     struct rk_strpool *p = NULL;
172     char *str;
173     int i;
174 
175     for (i = 0; i < padata->len; i++) {
176 	switch(padata->val[i].padata_type) {
177 	case KRB5_PADATA_PK_AS_REQ:
178 	    p = rk_strpoolprintf(p, "PK-INIT(ietf)");
179 	    break;
180 	case KRB5_PADATA_PK_AS_REQ_WIN:
181 	    p = rk_strpoolprintf(p, "PK-INIT(win2k)");
182 	    break;
183 	case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
184 	    p = rk_strpoolprintf(p, "OCSP");
185 	    break;
186 	case KRB5_PADATA_ENC_TIMESTAMP:
187 	    p = rk_strpoolprintf(p, "encrypted-timestamp");
188 	    break;
189 	default:
190 	    p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
191 	    break;
192 	}
193 	if (p && i + 1 < padata->len)
194 	    p = rk_strpoolprintf(p, ", ");
195 	if (p == NULL) {
196 	    kdc_log(context, config, 0, "out of memory");
197 	    return;
198 	}
199     }
200     if (p == NULL)
201 	p = rk_strpoolprintf(p, "none");
202 
203     str = rk_strpoolcollect(p);
204     kdc_log(context, config, 0, "Client sent patypes: %s", str);
205     free(str);
206 }
207 
208 /*
209  *
210  */
211 
212 
213 krb5_error_code
_kdc_encode_reply(krb5_context context,krb5_kdc_configuration * config,KDC_REP * rep,const EncTicketPart * et,EncKDCRepPart * ek,krb5_enctype etype,int skvno,const EncryptionKey * skey,int ckvno,const EncryptionKey * ckey,const char ** e_text,krb5_data * reply)214 _kdc_encode_reply(krb5_context context,
215 		  krb5_kdc_configuration *config,
216 		  KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
217 		  krb5_enctype etype,
218 		  int skvno, const EncryptionKey *skey,
219 		  int ckvno, const EncryptionKey *ckey,
220 		  const char **e_text,
221 		  krb5_data *reply)
222 {
223     unsigned char *buf;
224     size_t buf_size;
225     size_t len;
226     krb5_error_code ret;
227     krb5_crypto crypto;
228 
229     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
230     if(ret) {
231 	kdc_log(context, config, 0, "Failed to encode ticket: %s",
232 		krb5_get_err_text(context, ret));
233 	return ret;
234     }
235     if(buf_size != len) {
236 	free(buf);
237 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
238 	*e_text = "KDC internal error";
239 	return KRB5KRB_ERR_GENERIC;
240     }
241 
242     ret = krb5_crypto_init(context, skey, etype, &crypto);
243     if (ret) {
244 	free(buf);
245 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
246 		krb5_get_err_text(context, ret));
247 	return ret;
248     }
249 
250     ret = krb5_encrypt_EncryptedData(context,
251 				     crypto,
252 				     KRB5_KU_TICKET,
253 				     buf,
254 				     len,
255 				     skvno,
256 				     &rep->ticket.enc_part);
257     free(buf);
258     krb5_crypto_destroy(context, crypto);
259     if(ret) {
260 	kdc_log(context, config, 0, "Failed to encrypt data: %s",
261 		krb5_get_err_text(context, ret));
262 	return ret;
263     }
264 
265     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
266 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
267     else
268 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
269     if(ret) {
270 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
271 		krb5_get_err_text(context, ret));
272 	return ret;
273     }
274     if(buf_size != len) {
275 	free(buf);
276 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
277 	*e_text = "KDC internal error";
278 	return KRB5KRB_ERR_GENERIC;
279     }
280     ret = krb5_crypto_init(context, ckey, 0, &crypto);
281     if (ret) {
282 	free(buf);
283 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
284 		krb5_get_err_text(context, ret));
285 	return ret;
286     }
287     if(rep->msg_type == krb_as_rep) {
288 	krb5_encrypt_EncryptedData(context,
289 				   crypto,
290 				   KRB5_KU_AS_REP_ENC_PART,
291 				   buf,
292 				   len,
293 				   ckvno,
294 				   &rep->enc_part);
295 	free(buf);
296 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
297     } else {
298 	krb5_encrypt_EncryptedData(context,
299 				   crypto,
300 				   KRB5_KU_TGS_REP_ENC_PART_SESSION,
301 				   buf,
302 				   len,
303 				   ckvno,
304 				   &rep->enc_part);
305 	free(buf);
306 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
307     }
308     krb5_crypto_destroy(context, crypto);
309     if(ret) {
310 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
311 		krb5_get_err_text(context, ret));
312 	return ret;
313     }
314     if(buf_size != len) {
315 	free(buf);
316 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
317 	*e_text = "KDC internal error";
318 	return KRB5KRB_ERR_GENERIC;
319     }
320     reply->data = buf;
321     reply->length = buf_size;
322     return 0;
323 }
324 
325 static krb5_error_code
make_etype_info_entry(krb5_context context,ETYPE_INFO_ENTRY * ent,Key * key)326 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
327 {
328     ent->etype = key->key.keytype;
329     if(key->salt){
330 #if 0
331 	ALLOC(ent->salttype);
332 
333 	if(key->salt->type == hdb_pw_salt)
334 	    *ent->salttype = 0; /* or 1? or NULL? */
335 	else if(key->salt->type == hdb_afs3_salt)
336 	    *ent->salttype = 2;
337 	else {
338 	    kdc_log(context, config, 0, "unknown salt-type: %d",
339 		    key->salt->type);
340 	    return KRB5KRB_ERR_GENERIC;
341 	}
342 	/* according to `the specs', we can't send a salt if
343 	   we have AFS3 salted key, but that requires that you
344 	   *know* what cell you are using (e.g by assuming
345 	   that the cell is the same as the realm in lower
346 	   case) */
347 #elif 0
348 	ALLOC(ent->salttype);
349 	*ent->salttype = key->salt->type;
350 #else
351 	/*
352 	 * We shouldn't sent salttype since its incompatible with the
353 	 * specification and its break windows clients.  The afs
354 	 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
355 	 * implemented in Heimdal 0.7 and later.
356 	 */
357 	ent->salttype = NULL;
358 #endif
359 	krb5_copy_data(context, &key->salt->salt,
360 		       &ent->salt);
361     } else {
362 	/* we return no salt type at all, as that should indicate
363 	 * the default salt type and make everybody happy.  some
364 	 * systems (like w2k) dislike being told the salt type
365 	 * here. */
366 
367 	ent->salttype = NULL;
368 	ent->salt = NULL;
369     }
370     return 0;
371 }
372 
373 static krb5_error_code
get_pa_etype_info(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,hdb_entry * client,ENCTYPE * etypes,unsigned int etypes_len)374 get_pa_etype_info(krb5_context context,
375 		  krb5_kdc_configuration *config,
376 		  METHOD_DATA *md, hdb_entry *client,
377 		  ENCTYPE *etypes, unsigned int etypes_len)
378 {
379     krb5_error_code ret = 0;
380     int i, j;
381     unsigned int n = 0;
382     ETYPE_INFO pa;
383     unsigned char *buf;
384     size_t len;
385 
386 
387     pa.len = client->keys.len;
388     if(pa.len > UINT_MAX/sizeof(*pa.val))
389 	return ERANGE;
390     pa.val = malloc(pa.len * sizeof(*pa.val));
391     if(pa.val == NULL)
392 	return ENOMEM;
393     memset(pa.val, 0, pa.len * sizeof(*pa.val));
394 
395     for(j = 0; j < etypes_len; j++) {
396 	for (i = 0; i < n; i++)
397 	    if (pa.val[i].etype == etypes[j])
398 		goto skip1;
399 	for(i = 0; i < client->keys.len; i++) {
400 	    if(client->keys.val[i].key.keytype == etypes[j]) {
401  		if (krb5_enctype_valid(context, etypes[j]) != 0)
402  		    continue;
403 		if((ret = make_etype_info_entry(context,
404 						&pa.val[n++],
405 						&client->keys.val[i])) != 0) {
406 		    free_ETYPE_INFO(&pa);
407 		    return ret;
408 		}
409 	    }
410 	}
411     skip1:;
412     }
413     for(i = 0; i < client->keys.len; i++) {
414 	for(j = 0; j < etypes_len; j++) {
415 	    if(client->keys.val[i].key.keytype == etypes[j])
416 		goto skip2;
417 	}
418 	if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
419 	    continue;
420 	if((ret = make_etype_info_entry(context,
421 					&pa.val[n++],
422 					&client->keys.val[i])) != 0) {
423 	    free_ETYPE_INFO(&pa);
424 	    return ret;
425 	}
426     skip2:;
427     }
428 
429     if(n != pa.len) {
430 	char *name;
431 	ret = krb5_unparse_name(context, client->principal, &name);
432 	if (ret)
433 	    name = "<unparse_name failed>";
434 	kdc_log(context, config, 0, "internal error in get_pa_etype_info(%s): %d != %d",
435 		name, n, pa.len);
436 	if (ret == 0)
437 	    free(name);
438  	pa.len = n;
439     }
440 
441     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
442     free_ETYPE_INFO(&pa);
443     if(ret)
444 	return ret;
445     ret = realloc_method_data(md);
446     if(ret) {
447 	free(buf);
448 	return ret;
449     }
450     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
451     md->val[md->len - 1].padata_value.length = len;
452     md->val[md->len - 1].padata_value.data = buf;
453     return 0;
454 }
455 
456 /*
457  *
458  */
459 
460 extern int _krb5_AES_string_to_default_iterator;
461 
462 static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY * ent,Key * key)463 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
464 {
465     ent->etype = key->key.keytype;
466     if(key->salt) {
467 	ALLOC(ent->salt);
468 	if (ent->salt == NULL)
469 	    return ENOMEM;
470 	*ent->salt = malloc(key->salt->salt.length + 1);
471 	if (*ent->salt == NULL) {
472 	    free(ent->salt);
473 	    ent->salt = NULL;
474 	    return ENOMEM;
475 	}
476 	memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
477 	(*ent->salt)[key->salt->salt.length] = '\0';
478     } else
479 	ent->salt = NULL;
480 
481     ent->s2kparams = NULL;
482 
483     switch (key->key.keytype) {
484     case ETYPE_AES128_CTS_HMAC_SHA1_96:
485     case ETYPE_AES256_CTS_HMAC_SHA1_96:
486 	ALLOC(ent->s2kparams);
487 	if (ent->s2kparams == NULL)
488 	    return ENOMEM;
489 	ent->s2kparams->length = 4;
490 	ent->s2kparams->data = malloc(ent->s2kparams->length);
491 	if (ent->s2kparams->data == NULL) {
492 	    free(ent->s2kparams);
493 	    ent->s2kparams = NULL;
494 	    return ENOMEM;
495 	}
496 	_krb5_put_int(ent->s2kparams->data,
497 		      _krb5_AES_string_to_default_iterator,
498 		      ent->s2kparams->length);
499 	break;
500     case ETYPE_DES_CBC_CRC:
501     case ETYPE_DES_CBC_MD4:
502     case ETYPE_DES_CBC_MD5:
503 	/* Check if this was a AFS3 salted key */
504 	if(key->salt && key->salt->type == hdb_afs3_salt){
505 	    ALLOC(ent->s2kparams);
506 	    if (ent->s2kparams == NULL)
507 		return ENOMEM;
508 	    ent->s2kparams->length = 1;
509 	    ent->s2kparams->data = malloc(ent->s2kparams->length);
510 	    if (ent->s2kparams->data == NULL) {
511 		free(ent->s2kparams);
512 		ent->s2kparams = NULL;
513 		return ENOMEM;
514 	    }
515 	    _krb5_put_int(ent->s2kparams->data,
516 			  1,
517 			  ent->s2kparams->length);
518 	}
519 	break;
520     default:
521 	break;
522     }
523     return 0;
524 }
525 
526 /*
527  * Return 1 if the client have only older enctypes, this is for
528  * determining if the server should send ETYPE_INFO2 or not.
529  */
530 
531 static int
only_older_enctype_p(const KDC_REQ * req)532 only_older_enctype_p(const KDC_REQ *req)
533 {
534     int i;
535 
536     for(i = 0; i < req->req_body.etype.len; i++) {
537 	switch (req->req_body.etype.val[i]) {
538 	case ETYPE_DES_CBC_CRC:
539 	case ETYPE_DES_CBC_MD4:
540 	case ETYPE_DES_CBC_MD5:
541 	case ETYPE_DES3_CBC_SHA1:
542 	case ETYPE_ARCFOUR_HMAC_MD5:
543 	case ETYPE_ARCFOUR_HMAC_MD5_56:
544 	    break;
545 	default:
546 	    return 0;
547 	}
548     }
549     return 1;
550 }
551 
552 /*
553  *
554  */
555 
556 static krb5_error_code
get_pa_etype_info2(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,hdb_entry * client,ENCTYPE * etypes,unsigned int etypes_len)557 get_pa_etype_info2(krb5_context context,
558 		   krb5_kdc_configuration *config,
559 		   METHOD_DATA *md, hdb_entry *client,
560 		   ENCTYPE *etypes, unsigned int etypes_len)
561 {
562     krb5_error_code ret = 0;
563     int i, j;
564     unsigned int n = 0;
565     ETYPE_INFO2 pa;
566     unsigned char *buf;
567     size_t len;
568 
569     pa.len = client->keys.len;
570     if(pa.len > UINT_MAX/sizeof(*pa.val))
571 	return ERANGE;
572     pa.val = malloc(pa.len * sizeof(*pa.val));
573     if(pa.val == NULL)
574 	return ENOMEM;
575     memset(pa.val, 0, pa.len * sizeof(*pa.val));
576 
577     for(j = 0; j < etypes_len; j++) {
578 	for (i = 0; i < n; i++)
579 	    if (pa.val[i].etype == etypes[j])
580 		goto skip1;
581 	for(i = 0; i < client->keys.len; i++) {
582 	    if(client->keys.val[i].key.keytype == etypes[j]) {
583 		if (krb5_enctype_valid(context, etypes[j]) != 0)
584 		    continue;
585 		if((ret = make_etype_info2_entry(&pa.val[n++],
586 						 &client->keys.val[i])) != 0) {
587 		    free_ETYPE_INFO2(&pa);
588 		    return ret;
589 		}
590 	    }
591 	}
592     skip1:;
593     }
594     for(i = 0; i < client->keys.len; i++) {
595 	for(j = 0; j < etypes_len; j++) {
596 	    if(client->keys.val[i].key.keytype == etypes[j])
597 		goto skip2;
598 	}
599 	if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
600 	    continue;
601 	if((ret = make_etype_info2_entry(&pa.val[n++],
602 					 &client->keys.val[i])) != 0) {
603 	    free_ETYPE_INFO2(&pa);
604 	    return ret;
605 	}
606       skip2:;
607     }
608 
609     if(n != pa.len) {
610 	char *name;
611 	ret = krb5_unparse_name(context, client->principal, &name);
612 	if (ret)
613 	    name = "<unparse_name failed>";
614 	kdc_log(context, config, 0,
615 		"internal error in get_pa_etype_info2(%s): %d != %d",
616 		name, n, pa.len);
617 	if (ret == 0)
618 	    free(name);
619  	pa.len = n;
620     }
621 
622     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
623     free_ETYPE_INFO2(&pa);
624     if(ret)
625 	return ret;
626     ret = realloc_method_data(md);
627     if(ret) {
628 	free(buf);
629 	return ret;
630     }
631     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
632     md->val[md->len - 1].padata_value.length = len;
633     md->val[md->len - 1].padata_value.data = buf;
634     return 0;
635 }
636 
637 /*
638  * verify the flags on `client' and `server', returning 0
639  * if they are OK and generating an error messages and returning
640  * and error code otherwise.
641  */
642 
643 krb5_error_code
_kdc_check_flags(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client_ex,const char * client_name,hdb_entry_ex * server_ex,const char * server_name,krb5_boolean is_as_req)644 _kdc_check_flags(krb5_context context,
645 		 krb5_kdc_configuration *config,
646 		 hdb_entry_ex *client_ex, const char *client_name,
647 		 hdb_entry_ex *server_ex, const char *server_name,
648 		 krb5_boolean is_as_req)
649 {
650     if(client_ex != NULL) {
651 	hdb_entry *client = &client_ex->entry;
652 
653 	/* check client */
654 	if (client->flags.invalid) {
655 	    kdc_log(context, config, 0,
656 		    "Client (%s) has invalid bit set", client_name);
657 	    return KRB5KDC_ERR_POLICY;
658 	}
659 
660 	if(!client->flags.client){
661 	    kdc_log(context, config, 0,
662 		    "Principal may not act as client -- %s", client_name);
663 	    return KRB5KDC_ERR_POLICY;
664 	}
665 
666 	if (client->valid_start && *client->valid_start > kdc_time) {
667 	    char starttime_str[100];
668 	    krb5_format_time(context, *client->valid_start,
669 			     starttime_str, sizeof(starttime_str), TRUE);
670 	    kdc_log(context, config, 0,
671 		    "Client not yet valid until %s -- %s",
672 		    starttime_str, client_name);
673 	    return KRB5KDC_ERR_CLIENT_NOTYET;
674 	}
675 
676 	if (client->valid_end && *client->valid_end < kdc_time) {
677 	    char endtime_str[100];
678 	    krb5_format_time(context, *client->valid_end,
679 			     endtime_str, sizeof(endtime_str), TRUE);
680 	    kdc_log(context, config, 0,
681 		    "Client expired at %s -- %s",
682 		    endtime_str, client_name);
683 	    return KRB5KDC_ERR_NAME_EXP;
684 	}
685 
686 	if (client->pw_end && *client->pw_end < kdc_time
687 	    && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
688 	    char pwend_str[100];
689 	    krb5_format_time(context, *client->pw_end,
690 			     pwend_str, sizeof(pwend_str), TRUE);
691 	    kdc_log(context, config, 0,
692 		    "Client's key has expired at %s -- %s",
693 		    pwend_str, client_name);
694 	    return KRB5KDC_ERR_KEY_EXPIRED;
695 	}
696     }
697 
698     /* check server */
699 
700     if (server_ex != NULL) {
701 	hdb_entry *server = &server_ex->entry;
702 
703 	if (server->flags.invalid) {
704 	    kdc_log(context, config, 0,
705 		    "Server has invalid flag set -- %s", server_name);
706 	    return KRB5KDC_ERR_POLICY;
707 	}
708 
709 	if(!server->flags.server){
710 	    kdc_log(context, config, 0,
711 		    "Principal may not act as server -- %s", server_name);
712 	    return KRB5KDC_ERR_POLICY;
713 	}
714 
715 	if(!is_as_req && server->flags.initial) {
716 	    kdc_log(context, config, 0,
717 		    "AS-REQ is required for server -- %s", server_name);
718 	    return KRB5KDC_ERR_POLICY;
719 	}
720 
721 	if (server->valid_start && *server->valid_start > kdc_time) {
722 	    char starttime_str[100];
723 	    krb5_format_time(context, *server->valid_start,
724 			     starttime_str, sizeof(starttime_str), TRUE);
725 	    kdc_log(context, config, 0,
726 		    "Server not yet valid until %s -- %s",
727 		    starttime_str, server_name);
728 	    return KRB5KDC_ERR_SERVICE_NOTYET;
729 	}
730 
731 	if (server->valid_end && *server->valid_end < kdc_time) {
732 	    char endtime_str[100];
733 	    krb5_format_time(context, *server->valid_end,
734 			     endtime_str, sizeof(endtime_str), TRUE);
735 	    kdc_log(context, config, 0,
736 		    "Server expired at %s -- %s",
737 		    endtime_str, server_name);
738 	    return KRB5KDC_ERR_SERVICE_EXP;
739 	}
740 
741 	if (server->pw_end && *server->pw_end < kdc_time) {
742 	    char pwend_str[100];
743 	    krb5_format_time(context, *server->pw_end,
744 			     pwend_str, sizeof(pwend_str), TRUE);
745 	    kdc_log(context, config, 0,
746 		    "Server's key has expired at -- %s",
747 		    pwend_str, server_name);
748 	    return KRB5KDC_ERR_KEY_EXPIRED;
749 	}
750     }
751     return 0;
752 }
753 
754 /*
755  * Return TRUE if `from' is part of `addresses' taking into consideration
756  * the configuration variables that tells us how strict we should be about
757  * these checks
758  */
759 
760 krb5_boolean
_kdc_check_addresses(krb5_context context,krb5_kdc_configuration * config,HostAddresses * addresses,const struct sockaddr * from)761 _kdc_check_addresses(krb5_context context,
762 		     krb5_kdc_configuration *config,
763 		     HostAddresses *addresses, const struct sockaddr *from)
764 {
765     krb5_error_code ret;
766     krb5_address addr;
767     krb5_boolean result;
768     krb5_boolean only_netbios = TRUE;
769     int i;
770 
771     if(config->check_ticket_addresses == 0)
772 	return TRUE;
773 
774     if(addresses == NULL)
775 	return config->allow_null_ticket_addresses;
776 
777     for (i = 0; i < addresses->len; ++i) {
778 	if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
779 	    only_netbios = FALSE;
780 	}
781     }
782 
783     /* Windows sends it's netbios name, which I can only assume is
784      * used for the 'allowed workstations' check.  This is painful,
785      * but we still want to check IP addresses if they happen to be
786      * present.
787      */
788 
789     if(only_netbios)
790 	return config->allow_null_ticket_addresses;
791 
792     ret = krb5_sockaddr2address (context, from, &addr);
793     if(ret)
794 	return FALSE;
795 
796     result = krb5_address_search(context, &addr, addresses);
797     krb5_free_address (context, &addr);
798     return result;
799 }
800 
801 krb5_error_code
_kdc_as_rep(krb5_context context,krb5_kdc_configuration * config,KDC_REQ * req,const krb5_data * req_buffer,krb5_data * reply,const char * from,struct sockaddr * from_addr,int datagram_reply)802 _kdc_as_rep(krb5_context context,
803 	    krb5_kdc_configuration *config,
804 	    KDC_REQ *req,
805 	    const krb5_data *req_buffer,
806 	    krb5_data *reply,
807 	    const char *from,
808 	    struct sockaddr *from_addr,
809 	    int datagram_reply)
810 {
811     KDC_REQ_BODY *b = &req->req_body;
812     AS_REP rep;
813     KDCOptions f = b->kdc_options;
814     hdb_entry_ex *client = NULL, *server = NULL;
815     krb5_enctype cetype, setype, sessionetype;
816     EncTicketPart et;
817     EncKDCRepPart ek;
818     krb5_principal client_princ = NULL, server_princ = NULL;
819     char *client_name = NULL, *server_name = NULL;
820     krb5_error_code ret = 0;
821     const char *e_text = NULL;
822     krb5_crypto crypto;
823     Key *ckey, *skey;
824     EncryptionKey *reply_key;
825 #ifdef PKINIT
826     pk_client_params *pkp = NULL;
827 #endif
828 
829     memset(&rep, 0, sizeof(rep));
830 
831     if(b->sname == NULL){
832 	ret = KRB5KRB_ERR_GENERIC;
833 	e_text = "No server in request";
834     } else{
835 	_krb5_principalname2krb5_principal (context,
836 					    &server_princ,
837 					    *(b->sname),
838 					    b->realm);
839 	ret = krb5_unparse_name(context, server_princ, &server_name);
840     }
841     if (ret) {
842 	kdc_log(context, config, 0,
843 		"AS-REQ malformed server name from %s", from);
844 	goto out;
845     }
846 
847     if(b->cname == NULL){
848 	ret = KRB5KRB_ERR_GENERIC;
849 	e_text = "No client in request";
850     } else {
851 	_krb5_principalname2krb5_principal (context,
852 					    &client_princ,
853 					    *(b->cname),
854 					    b->realm);
855 	ret = krb5_unparse_name(context, client_princ, &client_name);
856     }
857     if (ret) {
858 	kdc_log(context, config, 0,
859 		"AS-REQ malformed client name from %s", from);
860 	goto out;
861     }
862 
863     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
864 	    client_name, from, server_name);
865 
866     ret = _kdc_db_fetch(context, config, client_princ,
867 			HDB_F_GET_CLIENT, NULL, &client);
868     if(ret){
869 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
870 		krb5_get_err_text(context, ret));
871 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
872 	goto out;
873     }
874 
875     ret = _kdc_db_fetch(context, config, server_princ,
876 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
877 			NULL, &server);
878     if(ret){
879 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
880 		krb5_get_err_text(context, ret));
881 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
882 	goto out;
883     }
884 
885     ret = _kdc_check_flags(context, config,
886 			   client, client_name,
887 			   server, server_name,
888 			   TRUE);
889     if(ret)
890 	goto out;
891 
892     if (client->check_client_access) {
893 	ret = client->check_client_access(context, client,
894 					  b->addresses);
895 	if(ret)
896 	    goto out;
897     }
898 
899     memset(&et, 0, sizeof(et));
900     memset(&ek, 0, sizeof(ek));
901 
902     if(req->padata){
903 	int i;
904 	PA_DATA *pa;
905 	int found_pa = 0;
906 
907 	log_patypes(context, config, req->padata);
908 
909 #ifdef PKINIT
910 	kdc_log(context, config, 5,
911 		"Looking for PKINIT pa-data -- %s", client_name);
912 
913 	e_text = "No PKINIT PA found";
914 
915 	i = 0;
916 	if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
917 	    ;
918 	if (pa == NULL) {
919 	    i = 0;
920 	    if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
921 		;
922 	}
923 	if (pa) {
924 	    char *client_cert = NULL;
925 
926 	    ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
927 	    if (ret) {
928 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
929 		kdc_log(context, config, 5,
930 			"Failed to decode PKINIT PA-DATA -- %s",
931 			client_name);
932 		goto ts_enc;
933 	    }
934 	    if (ret == 0 && pkp == NULL)
935 		goto ts_enc;
936 
937 	    ret = _kdc_pk_check_client(context,
938 				       config,
939 				       client,
940 				       pkp,
941 				       &client_cert);
942 	    if (ret) {
943 		e_text = "PKINIT certificate not allowed to "
944 		    "impersonate principal";
945 		_kdc_pk_free_client_param(context, pkp);
946 
947 		kdc_log(context, config, 0, "%s", e_text);
948 		pkp = NULL;
949 		goto ts_enc;
950 	    }
951 	    found_pa = 1;
952 	    et.flags.pre_authent = 1;
953 	    kdc_log(context, config, 0,
954 		    "PKINIT pre-authentication succeeded -- %s using %s",
955 		    client_name, client_cert);
956 	    free(client_cert);
957 	    if (pkp)
958 		goto preauth_done;
959 	}
960     ts_enc:
961 #endif
962 	kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
963 		client_name);
964 
965 	i = 0;
966 	e_text = "No ENC-TS found";
967 	while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
968 	    krb5_data ts_data;
969 	    PA_ENC_TS_ENC p;
970 	    size_t len;
971 	    EncryptedData enc_data;
972 	    Key *pa_key;
973 	    char *str;
974 
975 	    found_pa = 1;
976 
977 	    ret = decode_EncryptedData(pa->padata_value.data,
978 				       pa->padata_value.length,
979 				       &enc_data,
980 				       &len);
981 	    if (ret) {
982 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
983 		kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
984 			client_name);
985 		goto out;
986 	    }
987 
988 	    ret = hdb_enctype2key(context, &client->entry,
989 				  enc_data.etype, &pa_key);
990 	    if(ret){
991 		char *estr;
992 		e_text = "No key matches pa-data";
993 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
994 		if(krb5_enctype_to_string(context, enc_data.etype, &estr))
995 		    estr = NULL;
996 		if(estr == NULL)
997 		    kdc_log(context, config, 5,
998 			    "No client key matching pa-data (%d) -- %s",
999 			    enc_data.etype, client_name);
1000 		else
1001 		    kdc_log(context, config, 5,
1002 			    "No client key matching pa-data (%s) -- %s",
1003 			    estr, client_name);
1004 		free(estr);
1005 
1006 		free_EncryptedData(&enc_data);
1007 		continue;
1008 	    }
1009 
1010 	try_next_key:
1011 	    ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1012 	    if (ret) {
1013 		kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1014 			krb5_get_err_text(context, ret));
1015 		free_EncryptedData(&enc_data);
1016 		continue;
1017 	    }
1018 
1019 	    ret = krb5_decrypt_EncryptedData (context,
1020 					      crypto,
1021 					      KRB5_KU_PA_ENC_TIMESTAMP,
1022 					      &enc_data,
1023 					      &ts_data);
1024 	    krb5_crypto_destroy(context, crypto);
1025 	    if(ret){
1026 		krb5_error_code ret2;
1027 		ret2 = krb5_enctype_to_string(context,
1028 					      pa_key->key.keytype, &str);
1029 		if (ret2)
1030 		    str = NULL;
1031 		kdc_log(context, config, 5,
1032 			"Failed to decrypt PA-DATA -- %s "
1033 			"(enctype %s) error %s",
1034 			client_name,
1035 			str ? str : "unknown enctype",
1036 			krb5_get_err_text(context, ret));
1037 		free(str);
1038 
1039 		if(hdb_next_enctype2key(context, &client->entry,
1040 					enc_data.etype, &pa_key) == 0)
1041 		    goto try_next_key;
1042 		e_text = "Failed to decrypt PA-DATA";
1043 
1044 		free_EncryptedData(&enc_data);
1045 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1046 		continue;
1047 	    }
1048 	    free_EncryptedData(&enc_data);
1049 	    ret = decode_PA_ENC_TS_ENC(ts_data.data,
1050 				       ts_data.length,
1051 				       &p,
1052 				       &len);
1053 	    krb5_data_free(&ts_data);
1054 	    if(ret){
1055 		e_text = "Failed to decode PA-ENC-TS-ENC";
1056 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1057 		kdc_log(context, config,
1058 			5, "Failed to decode PA-ENC-TS_ENC -- %s",
1059 			client_name);
1060 		continue;
1061 	    }
1062 	    free_PA_ENC_TS_ENC(&p);
1063 	    if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1064 		char client_time[100];
1065 
1066 		krb5_format_time(context, p.patimestamp,
1067 				 client_time, sizeof(client_time), TRUE);
1068 
1069  		ret = KRB5KRB_AP_ERR_SKEW;
1070  		kdc_log(context, config, 0,
1071 			"Too large time skew, "
1072 			"client time %s is out by %u > %u seconds -- %s",
1073 			client_time,
1074 			(unsigned)abs(kdc_time - p.patimestamp),
1075 			context->max_skew,
1076 			client_name);
1077 		/*
1078 		 * the following is needed to make windows clients
1079 		 * to retry using the timestamp in the error message
1080 		 *
1081 		 * this is maybe a bug in windows to not trying when e_text
1082 		 * is present...
1083 		 */
1084 		e_text = NULL;
1085 		goto out;
1086 	    }
1087 	    et.flags.pre_authent = 1;
1088 
1089 	    ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str);
1090 	    if (ret)
1091 		str = NULL;
1092 
1093 	    kdc_log(context, config, 2,
1094 		    "ENC-TS Pre-authentication succeeded -- %s using %s",
1095 		    client_name, str ? str : "unknown enctype");
1096 	    free(str);
1097 	    break;
1098 	}
1099 #ifdef PKINIT
1100     preauth_done:
1101 #endif
1102 	if(found_pa == 0 && config->require_preauth)
1103 	    goto use_pa;
1104 	/* We come here if we found a pa-enc-timestamp, but if there
1105            was some problem with it, other than too large skew */
1106 	if(found_pa && et.flags.pre_authent == 0){
1107 	    kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1108 	    e_text = NULL;
1109 	    goto out;
1110 	}
1111     }else if (config->require_preauth
1112 	      || client->entry.flags.require_preauth
1113 	      || server->entry.flags.require_preauth) {
1114 	METHOD_DATA method_data;
1115 	PA_DATA *pa;
1116 	unsigned char *buf;
1117 	size_t len;
1118 	krb5_data foo_data;
1119 
1120     use_pa:
1121 	method_data.len = 0;
1122 	method_data.val = NULL;
1123 
1124 	ret = realloc_method_data(&method_data);
1125 	pa = &method_data.val[method_data.len-1];
1126 	pa->padata_type		= KRB5_PADATA_ENC_TIMESTAMP;
1127 	pa->padata_value.length	= 0;
1128 	pa->padata_value.data	= NULL;
1129 
1130 #ifdef PKINIT
1131 	ret = realloc_method_data(&method_data);
1132 	pa = &method_data.val[method_data.len-1];
1133 	pa->padata_type		= KRB5_PADATA_PK_AS_REQ;
1134 	pa->padata_value.length	= 0;
1135 	pa->padata_value.data	= NULL;
1136 #endif
1137 
1138 	/*
1139 	 * RFC4120 requires:
1140 	 * - If the client only knows about old enctypes, then send
1141 	 *   both info replies (we send 'info' first in the list).
1142 	 * - If the client is 'modern', because it knows about 'new'
1143 	 *   enctype types, then only send the 'info2' reply.
1144 	 */
1145 
1146 	/* XXX check ret */
1147 	if (only_older_enctype_p(req))
1148 	    ret = get_pa_etype_info(context, config,
1149 				    &method_data, &client->entry,
1150 				    b->etype.val, b->etype.len);
1151 	/* XXX check ret */
1152 	ret = get_pa_etype_info2(context, config, &method_data,
1153 				 &client->entry, b->etype.val, b->etype.len);
1154 
1155 
1156 	ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1157 	free_METHOD_DATA(&method_data);
1158 	foo_data.data   = buf;
1159 	foo_data.length = len;
1160 
1161 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1162 	krb5_mk_error(context,
1163 		      ret,
1164 		      "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1165 		      &foo_data,
1166 		      client_princ,
1167 		      server_princ,
1168 		      NULL,
1169 		      NULL,
1170 		      reply);
1171 	free(buf);
1172 	kdc_log(context, config, 0,
1173 		"No preauth found, returning PREAUTH-REQUIRED -- %s",
1174 		client_name);
1175 	ret = 0;
1176 	goto out2;
1177     }
1178 
1179     /*
1180      * Find the client key (for preauth ENC-TS verification and reply
1181      * encryption).  Then the best encryption type for the KDC and
1182      * last the best session key that shared between the client and
1183      * KDC runtime enctypes.
1184      */
1185 
1186     ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
1187 			  &ckey, &cetype);
1188     if (ret) {
1189 	kdc_log(context, config, 0,
1190 		"Client (%s) has no support for etypes", client_name);
1191 	goto out;
1192     }
1193 
1194     ret = _kdc_get_preferred_key(context, config,
1195 				 server, server_name,
1196 				 &setype, &skey);
1197     if(ret)
1198 	goto out;
1199 
1200     {
1201 	const krb5_enctype *p;
1202 	int i, j;
1203 
1204 	p = krb5_kerberos_enctypes(context);
1205 
1206 	sessionetype = ETYPE_NULL;
1207 
1208 	for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) {
1209 	    if (krb5_enctype_valid(context, p[i]) != 0)
1210 		continue;
1211 	    for (j = 0; j < b->etype.len; j++) {
1212 		if (p[i] == b->etype.val[j]) {
1213 		    sessionetype = p[i];
1214 		    break;
1215 		}
1216 	    }
1217 	}
1218 	if (sessionetype == ETYPE_NULL) {
1219 	    kdc_log(context, config, 0,
1220 		    "Client (%s) from %s has no common enctypes with KDC"
1221 		    "to use for the session key",
1222 		    client_name, from);
1223 	    goto out;
1224 	}
1225     }
1226 
1227     {
1228 	struct rk_strpool *p = NULL;
1229 	char *str;
1230 	int i;
1231 
1232 	for (i = 0; i < b->etype.len; i++) {
1233 	    ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1234 	    if (ret == 0) {
1235 		p = rk_strpoolprintf(p, "%s", str);
1236 		free(str);
1237 	    } else
1238 		p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1239 	    if (p && i + 1 < b->etype.len)
1240 		p = rk_strpoolprintf(p, ", ");
1241 	    if (p == NULL) {
1242 		kdc_log(context, config, 0, "out of memory");
1243 		goto out;
1244 	    }
1245 	}
1246 	if (p == NULL)
1247 	    p = rk_strpoolprintf(p, "no encryption types");
1248 
1249 	str = rk_strpoolcollect(p);
1250 	kdc_log(context, config, 0, "Client supported enctypes: %s", str);
1251 	free(str);
1252     }
1253     {
1254 	char *cet;
1255 	char *set;
1256 
1257 	ret = krb5_enctype_to_string(context, cetype, &cet);
1258 	if(ret == 0) {
1259 	    ret = krb5_enctype_to_string(context, setype, &set);
1260 	    if (ret == 0) {
1261 		kdc_log(context, config, 5, "Using %s/%s", cet, set);
1262 		free(set);
1263 	    }
1264 	    free(cet);
1265 	}
1266 	if (ret != 0)
1267 	    kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
1268     }
1269 
1270     {
1271 	char str[128];
1272 	unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(),
1273 		      str, sizeof(str));
1274 	if(*str)
1275 	    kdc_log(context, config, 2, "Requested flags: %s", str);
1276     }
1277 
1278 
1279     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1280        || (f.request_anonymous && !config->allow_anonymous)) {
1281 	ret = KRB5KDC_ERR_BADOPTION;
1282 	kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1283 	goto out;
1284     }
1285 
1286     rep.pvno = 5;
1287     rep.msg_type = krb_as_rep;
1288     copy_Realm(&client->entry.principal->realm, &rep.crealm);
1289     if (f.request_anonymous)
1290 	_kdc_make_anonymous_principalname (&rep.cname);
1291     else
1292 	_krb5_principal2principalname(&rep.cname,
1293 				      client->entry.principal);
1294     rep.ticket.tkt_vno = 5;
1295     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1296     _krb5_principal2principalname(&rep.ticket.sname,
1297 				  server->entry.principal);
1298 
1299     et.flags.initial = 1;
1300     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1301 	et.flags.forwardable = f.forwardable;
1302     else if (f.forwardable) {
1303 	ret = KRB5KDC_ERR_POLICY;
1304 	kdc_log(context, config, 0,
1305 		"Ticket may not be forwardable -- %s", client_name);
1306 	goto out;
1307     }
1308     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1309 	et.flags.proxiable = f.proxiable;
1310     else if (f.proxiable) {
1311 	ret = KRB5KDC_ERR_POLICY;
1312 	kdc_log(context, config, 0,
1313 		"Ticket may not be proxiable -- %s", client_name);
1314 	goto out;
1315     }
1316     if(client->entry.flags.postdate && server->entry.flags.postdate)
1317 	et.flags.may_postdate = f.allow_postdate;
1318     else if (f.allow_postdate){
1319 	ret = KRB5KDC_ERR_POLICY;
1320 	kdc_log(context, config, 0,
1321 		"Ticket may not be postdatable -- %s", client_name);
1322 	goto out;
1323     }
1324 
1325     /* check for valid set of addresses */
1326     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1327 	ret = KRB5KRB_AP_ERR_BADADDR;
1328 	kdc_log(context, config, 0,
1329 		"Bad address list requested -- %s", client_name);
1330 	goto out;
1331     }
1332 
1333     krb5_generate_random_keyblock(context, sessionetype, &et.key);
1334     copy_PrincipalName(&rep.cname, &et.cname);
1335     copy_Realm(&rep.crealm, &et.crealm);
1336 
1337     {
1338 	time_t start;
1339 	time_t t;
1340 
1341 	start = et.authtime = kdc_time;
1342 
1343 	if(f.postdated && req->req_body.from){
1344 	    ALLOC(et.starttime);
1345 	    start = *et.starttime = *req->req_body.from;
1346 	    et.flags.invalid = 1;
1347 	    et.flags.postdated = 1; /* XXX ??? */
1348 	}
1349 	_kdc_fix_time(&b->till);
1350 	t = *b->till;
1351 
1352 	/* be careful not overflowing */
1353 
1354 	if(client->entry.max_life)
1355 	    t = start + min(t - start, *client->entry.max_life);
1356 	if(server->entry.max_life)
1357 	    t = start + min(t - start, *server->entry.max_life);
1358 #if 0
1359 	t = min(t, start + realm->max_life);
1360 #endif
1361 	et.endtime = t;
1362 	if(f.renewable_ok && et.endtime < *b->till){
1363 	    f.renewable = 1;
1364 	    if(b->rtime == NULL){
1365 		ALLOC(b->rtime);
1366 		*b->rtime = 0;
1367 	    }
1368 	    if(*b->rtime < *b->till)
1369 		*b->rtime = *b->till;
1370 	}
1371 	if(f.renewable && b->rtime){
1372 	    t = *b->rtime;
1373 	    if(t == 0)
1374 		t = MAX_TIME;
1375 	    if(client->entry.max_renew)
1376 		t = start + min(t - start, *client->entry.max_renew);
1377 	    if(server->entry.max_renew)
1378 		t = start + min(t - start, *server->entry.max_renew);
1379 #if 0
1380 	    t = min(t, start + realm->max_renew);
1381 #endif
1382 	    ALLOC(et.renew_till);
1383 	    *et.renew_till = t;
1384 	    et.flags.renewable = 1;
1385 	}
1386     }
1387 
1388     if (f.request_anonymous)
1389 	et.flags.anonymous = 1;
1390 
1391     if(b->addresses){
1392 	ALLOC(et.caddr);
1393 	copy_HostAddresses(b->addresses, et.caddr);
1394     }
1395 
1396     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1397     krb5_data_zero(&et.transited.contents);
1398 
1399     copy_EncryptionKey(&et.key, &ek.key);
1400 
1401     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1402      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1403      * incapable of correctly decoding SEQUENCE OF's of zero length.
1404      *
1405      * To fix this, always send at least one no-op last_req
1406      *
1407      * If there's a pw_end or valid_end we will use that,
1408      * otherwise just a dummy lr.
1409      */
1410     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1411     ek.last_req.len = 0;
1412     if (client->entry.pw_end
1413 	&& (config->kdc_warn_pwexpire == 0
1414 	    || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1415 	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1416 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1417 	++ek.last_req.len;
1418     }
1419     if (client->entry.valid_end) {
1420 	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1421 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1422 	++ek.last_req.len;
1423     }
1424     if (ek.last_req.len == 0) {
1425 	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1426 	ek.last_req.val[ek.last_req.len].lr_value = 0;
1427 	++ek.last_req.len;
1428     }
1429     ek.nonce = b->nonce;
1430     if (client->entry.valid_end || client->entry.pw_end) {
1431 	ALLOC(ek.key_expiration);
1432 	if (client->entry.valid_end) {
1433 	    if (client->entry.pw_end)
1434 		*ek.key_expiration = min(*client->entry.valid_end,
1435 					 *client->entry.pw_end);
1436 	    else
1437 		*ek.key_expiration = *client->entry.valid_end;
1438 	} else
1439 	    *ek.key_expiration = *client->entry.pw_end;
1440     } else
1441 	ek.key_expiration = NULL;
1442     ek.flags = et.flags;
1443     ek.authtime = et.authtime;
1444     if (et.starttime) {
1445 	ALLOC(ek.starttime);
1446 	*ek.starttime = *et.starttime;
1447     }
1448     ek.endtime = et.endtime;
1449     if (et.renew_till) {
1450 	ALLOC(ek.renew_till);
1451 	*ek.renew_till = *et.renew_till;
1452     }
1453     copy_Realm(&rep.ticket.realm, &ek.srealm);
1454     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1455     if(et.caddr){
1456 	ALLOC(ek.caddr);
1457 	copy_HostAddresses(et.caddr, ek.caddr);
1458     }
1459 
1460     ALLOC(rep.padata);
1461     rep.padata->len = 0;
1462     rep.padata->val = NULL;
1463 
1464     reply_key = &ckey->key;
1465 #if PKINIT
1466     if (pkp) {
1467 	ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1468 				  req, req_buffer,
1469 				  &reply_key, rep.padata);
1470 	if (ret)
1471 	    goto out;
1472     }
1473 #endif
1474 
1475     set_salt_padata (rep.padata, ckey->salt);
1476 
1477     if (rep.padata->len == 0) {
1478 	free(rep.padata);
1479 	rep.padata = NULL;
1480     }
1481 
1482     /* Add the PAC, via a HDB abstraction */
1483     if (client->authz_data_as_req) {
1484 	    ret = client->authz_data_as_req(context, client,
1485 					    req->padata,
1486 					    et.authtime,
1487 					    &skey->key,
1488 					    &et.key,
1489 					    &et.authorization_data);
1490 	    if (ret)
1491 		    goto out;
1492     }
1493 
1494     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1495 		       et.endtime, et.renew_till);
1496 
1497     /* do this as the last thing since this signs the EncTicketPart */
1498     ret = _kdc_add_KRB5SignedPath(context,
1499 				  config,
1500 				  server,
1501 				  setype,
1502 				  NULL,
1503 				  NULL,
1504 				  &et);
1505     if (ret)
1506 	goto out;
1507 
1508     ret = _kdc_encode_reply(context, config,
1509 			    &rep, &et, &ek, setype, server->entry.kvno,
1510 			    &skey->key, client->entry.kvno,
1511 			    reply_key, &e_text, reply);
1512     free_EncTicketPart(&et);
1513     free_EncKDCRepPart(&ek);
1514     if (ret)
1515 	goto out;
1516 
1517     /* */
1518     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1519 	krb5_data_free(reply);
1520 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1521 	e_text = "Reply packet too large";
1522     }
1523 
1524 out:
1525     free_AS_REP(&rep);
1526     if(ret){
1527 	krb5_mk_error(context,
1528 		      ret,
1529 		      e_text,
1530 		      NULL,
1531 		      client_princ,
1532 		      server_princ,
1533 		      NULL,
1534 		      NULL,
1535 		      reply);
1536 	ret = 0;
1537     }
1538 out2:
1539 #ifdef PKINIT
1540     if (pkp)
1541 	_kdc_pk_free_client_param(context, pkp);
1542 #endif
1543     if (client_princ)
1544 	krb5_free_principal(context, client_princ);
1545     free(client_name);
1546     if (server_princ)
1547 	krb5_free_principal(context, server_princ);
1548     free(server_name);
1549     if(client)
1550 	_kdc_free_ent(context, client);
1551     if(server)
1552 	_kdc_free_ent(context, server);
1553     return ret;
1554 }
1555