1 /*	$NetBSD: kerberos5.c,v 1.5 2014/04/24 13:45:34 pettai 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
_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 const PA_DATA*
_kdc_find_padata(const KDC_REQ * req,int * start,int type)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
_kdc_is_weak_exception(krb5_principal principal,krb5_enctype etype)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 == ETYPE_DES_CBC_CRC
98 	 || etype == ETYPE_DES_CBC_MD4
99 	 || etype == 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
is_default_salt_p(const krb5_salt * default_salt,const Key * key)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  * return the first appropriate key of `princ' in `ret_key'.  Look for
123  * all the etypes in (`etypes', `len'), stopping as soon as we find
124  * one, but preferring one that has default salt.
125  */
126 
127 krb5_error_code
_kdc_find_etype(krb5_context context,krb5_boolean use_strongest_session_key,krb5_boolean is_preauth,hdb_entry_ex * princ,krb5_enctype * etypes,unsigned len,krb5_enctype * ret_enctype,Key ** ret_key)128 _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
129 		krb5_boolean is_preauth, hdb_entry_ex *princ,
130 		krb5_enctype *etypes, unsigned len,
131 		krb5_enctype *ret_enctype, Key **ret_key)
132 {
133     krb5_error_code ret;
134     krb5_salt def_salt;
135     krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
136     const krb5_enctype *p;
137     Key *key = NULL;
138     int i, k;
139 
140     /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
141     ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
142     if (ret)
143 	return ret;
144 
145     ret = KRB5KDC_ERR_ETYPE_NOSUPP;
146 
147     if (use_strongest_session_key) {
148 	/*
149 	 * Pick the strongest key that the KDC, target service, and
150 	 * client all support, using the local cryptosystem enctype
151 	 * list in strongest-to-weakest order to drive the search.
152 	 *
153 	 * This is not what RFC4120 says to do, but it encourages
154 	 * adoption of stronger enctypes.  This doesn't play well with
155 	 * clients that have multiple Kerberos client implementations
156 	 * available with different supported enctype lists.
157 	 */
158 
159 	/* drive the search with local supported enctypes list */
160 	p = krb5_kerberos_enctypes(context);
161 	for (i = 0;
162 	    p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
163 	    i++) {
164 	    if (krb5_enctype_valid(context, p[i]) != 0 &&
165 		!_kdc_is_weak_exception(princ->entry.principal, p[i]))
166 		continue;
167 
168 	    /* check that the client supports it too */
169 	    for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
170 
171 		if (p[i] != etypes[k])
172 		    continue;
173 
174 		/* check target princ support */
175 		key = NULL;
176 		while (hdb_next_enctype2key(context, &princ->entry,
177 					     p[i], &key) == 0) {
178 		    if (key->key.keyvalue.length == 0) {
179 			ret = KRB5KDC_ERR_NULL_KEY;
180 			continue;
181 		    }
182 		    enctype = p[i];
183 		    ret = 0;
184 		    if (is_preauth && ret_key != NULL &&
185 			!is_default_salt_p(&def_salt, key))
186 			continue;
187 		}
188 	    }
189 	}
190     } else {
191 	/*
192 	 * Pick the first key from the client's enctype list that is
193 	 * supported by the cryptosystem and by the given principal.
194 	 *
195 	 * RFC4120 says we SHOULD pick the first _strong_ key from the
196 	 * client's list... not the first key...  If the admin disallows
197 	 * weak enctypes in krb5.conf and selects this key selection
198 	 * algorithm, then we get exactly what RFC4120 says.
199 	 */
200 	for(i = 0; ret != 0 && i < len; i++) {
201 
202 	    if (krb5_enctype_valid(context, etypes[i]) != 0 &&
203 		!_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
204 		continue;
205 
206 	    key = NULL;
207 	    while (ret != 0 &&
208 		   hdb_next_enctype2key(context, &princ->entry,
209 					etypes[i], &key) == 0) {
210 		if (key->key.keyvalue.length == 0) {
211 		    ret = KRB5KDC_ERR_NULL_KEY;
212 		    continue;
213 		}
214 		enctype = etypes[i];
215 		ret = 0;
216 		if (is_preauth && ret_key != NULL &&
217 		    !is_default_salt_p(&def_salt, key))
218 		    continue;
219 	    }
220 	}
221     }
222 
223     if (enctype == (krb5_enctype)ETYPE_NULL) {
224 	/*
225 	 * if the service principal is one for which there is a known 1DES
226 	 * exception and no other enctype matches both the client request and
227 	 * the service key list, provide a DES-CBC-CRC key.
228 	 */
229 	if (ret_key == NULL &&
230 	    _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
231 	    ret = 0;
232 	    enctype = ETYPE_DES_CBC_CRC;
233 	} else {
234 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP;
235 	}
236     }
237 
238     if (ret == 0) {
239 	if (ret_enctype != NULL)
240 	    *ret_enctype = enctype;
241 	if (ret_key != NULL)
242 	    *ret_key = key;
243     }
244 
245     krb5_free_salt (context, def_salt);
246     return ret;
247 }
248 
249 krb5_error_code
_kdc_make_anonymous_principalname(PrincipalName * pn)250 _kdc_make_anonymous_principalname (PrincipalName *pn)
251 {
252     pn->name_type = KRB5_NT_PRINCIPAL;
253     pn->name_string.len = 1;
254     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
255     if (pn->name_string.val == NULL)
256 	return ENOMEM;
257     pn->name_string.val[0] = strdup("anonymous");
258     if (pn->name_string.val[0] == NULL) {
259 	free(pn->name_string.val);
260 	pn->name_string.val = NULL;
261 	return ENOMEM;
262     }
263     return 0;
264 }
265 
266 void
_kdc_log_timestamp(krb5_context context,krb5_kdc_configuration * config,const char * type,KerberosTime authtime,KerberosTime * starttime,KerberosTime endtime,KerberosTime * renew_till)267 _kdc_log_timestamp(krb5_context context,
268 		   krb5_kdc_configuration *config,
269 		   const char *type,
270 		   KerberosTime authtime, KerberosTime *starttime,
271 		   KerberosTime endtime, KerberosTime *renew_till)
272 {
273     char authtime_str[100], starttime_str[100],
274 	endtime_str[100], renewtime_str[100];
275 
276     krb5_format_time(context, authtime,
277 		     authtime_str, sizeof(authtime_str), TRUE);
278     if (starttime)
279 	krb5_format_time(context, *starttime,
280 			 starttime_str, sizeof(starttime_str), TRUE);
281     else
282 	strlcpy(starttime_str, "unset", sizeof(starttime_str));
283     krb5_format_time(context, endtime,
284 		     endtime_str, sizeof(endtime_str), TRUE);
285     if (renew_till)
286 	krb5_format_time(context, *renew_till,
287 			 renewtime_str, sizeof(renewtime_str), TRUE);
288     else
289 	strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
290 
291     kdc_log(context, config, 5,
292 	    "%s authtime: %s starttime: %s endtime: %s renew till: %s",
293 	    type, authtime_str, starttime_str, endtime_str, renewtime_str);
294 }
295 
296 static void
log_patypes(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * padata)297 log_patypes(krb5_context context,
298 	    krb5_kdc_configuration *config,
299 	    METHOD_DATA *padata)
300 {
301     struct rk_strpool *p = NULL;
302     char *str;
303     size_t i;
304 
305     for (i = 0; i < padata->len; i++) {
306 	switch(padata->val[i].padata_type) {
307 	case KRB5_PADATA_PK_AS_REQ:
308 	    p = rk_strpoolprintf(p, "PK-INIT(ietf)");
309 	    break;
310 	case KRB5_PADATA_PK_AS_REQ_WIN:
311 	    p = rk_strpoolprintf(p, "PK-INIT(win2k)");
312 	    break;
313 	case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
314 	    p = rk_strpoolprintf(p, "OCSP");
315 	    break;
316 	case KRB5_PADATA_ENC_TIMESTAMP:
317 	    p = rk_strpoolprintf(p, "encrypted-timestamp");
318 	    break;
319 	default:
320 	    p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
321 	    break;
322 	}
323 	if (p && i + 1 < padata->len)
324 	    p = rk_strpoolprintf(p, ", ");
325 	if (p == NULL) {
326 	    kdc_log(context, config, 0, "out of memory");
327 	    return;
328 	}
329     }
330     if (p == NULL)
331 	p = rk_strpoolprintf(p, "none");
332 
333     str = rk_strpoolcollect(p);
334     kdc_log(context, config, 0, "Client sent patypes: %s", str);
335     free(str);
336 }
337 
338 /*
339  *
340  */
341 
342 
343 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 * reply_key,int rk_is_subkey,const char ** e_text,krb5_data * reply)344 _kdc_encode_reply(krb5_context context,
345 		  krb5_kdc_configuration *config,
346 		  KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
347 		  krb5_enctype etype,
348 		  int skvno, const EncryptionKey *skey,
349 		  int ckvno, const EncryptionKey *reply_key,
350 		  int rk_is_subkey,
351 		  const char **e_text,
352 		  krb5_data *reply)
353 {
354     unsigned char *buf;
355     size_t buf_size;
356     size_t len = 0;
357     krb5_error_code ret;
358     krb5_crypto crypto;
359 
360     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
361     if(ret) {
362 	const char *msg = krb5_get_error_message(context, ret);
363 	kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
364 	krb5_free_error_message(context, msg);
365 	return ret;
366     }
367     if(buf_size != len) {
368 	free(buf);
369 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
370 	*e_text = "KDC internal error";
371 	return KRB5KRB_ERR_GENERIC;
372     }
373 
374     ret = krb5_crypto_init(context, skey, etype, &crypto);
375     if (ret) {
376         const char *msg;
377 	free(buf);
378 	msg = krb5_get_error_message(context, ret);
379 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
380 	krb5_free_error_message(context, msg);
381 	return ret;
382     }
383 
384     ret = krb5_encrypt_EncryptedData(context,
385 				     crypto,
386 				     KRB5_KU_TICKET,
387 				     buf,
388 				     len,
389 				     skvno,
390 				     &rep->ticket.enc_part);
391     free(buf);
392     krb5_crypto_destroy(context, crypto);
393     if(ret) {
394 	const char *msg = krb5_get_error_message(context, ret);
395 	kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
396 	krb5_free_error_message(context, msg);
397 	return ret;
398     }
399 
400     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
401 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
402     else
403 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
404     if(ret) {
405 	const char *msg = krb5_get_error_message(context, ret);
406 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
407 	krb5_free_error_message(context, msg);
408 	return ret;
409     }
410     if(buf_size != len) {
411 	free(buf);
412 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
413 	*e_text = "KDC internal error";
414 	return KRB5KRB_ERR_GENERIC;
415     }
416     ret = krb5_crypto_init(context, reply_key, 0, &crypto);
417     if (ret) {
418 	const char *msg = krb5_get_error_message(context, ret);
419 	free(buf);
420 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
421 	krb5_free_error_message(context, msg);
422 	return ret;
423     }
424     if(rep->msg_type == krb_as_rep) {
425 	krb5_encrypt_EncryptedData(context,
426 				   crypto,
427 				   KRB5_KU_AS_REP_ENC_PART,
428 				   buf,
429 				   len,
430 				   ckvno,
431 				   &rep->enc_part);
432 	free(buf);
433 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
434     } else {
435 	krb5_encrypt_EncryptedData(context,
436 				   crypto,
437 				   rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
438 				   buf,
439 				   len,
440 				   ckvno,
441 				   &rep->enc_part);
442 	free(buf);
443 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
444     }
445     krb5_crypto_destroy(context, crypto);
446     if(ret) {
447 	const char *msg = krb5_get_error_message(context, ret);
448 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
449 	krb5_free_error_message(context, msg);
450 	return ret;
451     }
452     if(buf_size != len) {
453 	free(buf);
454 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
455 	*e_text = "KDC internal error";
456 	return KRB5KRB_ERR_GENERIC;
457     }
458     reply->data = buf;
459     reply->length = buf_size;
460     return 0;
461 }
462 
463 /*
464  * Return 1 if the client have only older enctypes, this is for
465  * determining if the server should send ETYPE_INFO2 or not.
466  */
467 
468 static int
older_enctype(krb5_enctype enctype)469 older_enctype(krb5_enctype enctype)
470 {
471     switch (enctype) {
472     case ETYPE_DES_CBC_CRC:
473     case ETYPE_DES_CBC_MD4:
474     case ETYPE_DES_CBC_MD5:
475     case ETYPE_DES3_CBC_SHA1:
476     case ETYPE_ARCFOUR_HMAC_MD5:
477     case ETYPE_ARCFOUR_HMAC_MD5_56:
478     /*
479      * The following three is "old" windows enctypes and is needed for
480      * windows 2000 hosts.
481      */
482     case ETYPE_ARCFOUR_MD4:
483     case ETYPE_ARCFOUR_HMAC_OLD:
484     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
485 	return 1;
486     default:
487 	return 0;
488     }
489 }
490 
491 /*
492  *
493  */
494 
495 static krb5_error_code
make_etype_info_entry(krb5_context context,ETYPE_INFO_ENTRY * ent,Key * key)496 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
497 {
498     ent->etype = key->key.keytype;
499     if(key->salt){
500 #if 0
501 	ALLOC(ent->salttype);
502 
503 	if(key->salt->type == hdb_pw_salt)
504 	    *ent->salttype = 0; /* or 1? or NULL? */
505 	else if(key->salt->type == hdb_afs3_salt)
506 	    *ent->salttype = 2;
507 	else {
508 	    kdc_log(context, config, 0, "unknown salt-type: %d",
509 		    key->salt->type);
510 	    return KRB5KRB_ERR_GENERIC;
511 	}
512 	/* according to `the specs', we can't send a salt if
513 	   we have AFS3 salted key, but that requires that you
514 	   *know* what cell you are using (e.g by assuming
515 	   that the cell is the same as the realm in lower
516 	   case) */
517 #elif 0
518 	ALLOC(ent->salttype);
519 	*ent->salttype = key->salt->type;
520 #else
521 	/*
522 	 * We shouldn't sent salttype since it is incompatible with the
523 	 * specification and it breaks windows clients.  The afs
524 	 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
525 	 * implemented in Heimdal 0.7 and later.
526 	 */
527 	ent->salttype = NULL;
528 #endif
529 	krb5_copy_data(context, &key->salt->salt,
530 		       &ent->salt);
531     } else {
532 	/* we return no salt type at all, as that should indicate
533 	 * the default salt type and make everybody happy.  some
534 	 * systems (like w2k) dislike being told the salt type
535 	 * here. */
536 
537 	ent->salttype = NULL;
538 	ent->salt = NULL;
539     }
540     return 0;
541 }
542 
543 static krb5_error_code
get_pa_etype_info(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)544 get_pa_etype_info(krb5_context context,
545 		  krb5_kdc_configuration *config,
546 		  METHOD_DATA *md, Key *ckey)
547 {
548     krb5_error_code ret = 0;
549     ETYPE_INFO pa;
550     unsigned char *buf;
551     size_t len;
552 
553 
554     pa.len = 1;
555     pa.val = calloc(1, sizeof(pa.val[0]));
556     if(pa.val == NULL)
557 	return ENOMEM;
558 
559     ret = make_etype_info_entry(context, &pa.val[0], ckey);
560     if (ret) {
561 	free_ETYPE_INFO(&pa);
562 	return ret;
563     }
564 
565     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
566     free_ETYPE_INFO(&pa);
567     if(ret)
568 	return ret;
569     ret = realloc_method_data(md);
570     if(ret) {
571 	free(buf);
572 	return ret;
573     }
574     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
575     md->val[md->len - 1].padata_value.length = len;
576     md->val[md->len - 1].padata_value.data = buf;
577     return 0;
578 }
579 
580 /*
581  *
582  */
583 
584 extern int _krb5_AES_string_to_default_iterator;
585 
586 static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY * ent,Key * key)587 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
588 {
589     ent->etype = key->key.keytype;
590     if(key->salt) {
591 	ALLOC(ent->salt);
592 	if (ent->salt == NULL)
593 	    return ENOMEM;
594 	*ent->salt = malloc(key->salt->salt.length + 1);
595 	if (*ent->salt == NULL) {
596 	    free(ent->salt);
597 	    ent->salt = NULL;
598 	    return ENOMEM;
599 	}
600 	memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
601 	(*ent->salt)[key->salt->salt.length] = '\0';
602     } else
603 	ent->salt = NULL;
604 
605     ent->s2kparams = NULL;
606 
607     switch (key->key.keytype) {
608     case ETYPE_AES128_CTS_HMAC_SHA1_96:
609     case ETYPE_AES256_CTS_HMAC_SHA1_96:
610 	ALLOC(ent->s2kparams);
611 	if (ent->s2kparams == NULL)
612 	    return ENOMEM;
613 	ent->s2kparams->length = 4;
614 	ent->s2kparams->data = malloc(ent->s2kparams->length);
615 	if (ent->s2kparams->data == NULL) {
616 	    free(ent->s2kparams);
617 	    ent->s2kparams = NULL;
618 	    return ENOMEM;
619 	}
620 	_krb5_put_int(ent->s2kparams->data,
621 		      _krb5_AES_string_to_default_iterator,
622 		      ent->s2kparams->length);
623 	break;
624     case ETYPE_DES_CBC_CRC:
625     case ETYPE_DES_CBC_MD4:
626     case ETYPE_DES_CBC_MD5:
627 	/* Check if this was a AFS3 salted key */
628 	if(key->salt && key->salt->type == hdb_afs3_salt){
629 	    ALLOC(ent->s2kparams);
630 	    if (ent->s2kparams == NULL)
631 		return ENOMEM;
632 	    ent->s2kparams->length = 1;
633 	    ent->s2kparams->data = malloc(ent->s2kparams->length);
634 	    if (ent->s2kparams->data == NULL) {
635 		free(ent->s2kparams);
636 		ent->s2kparams = NULL;
637 		return ENOMEM;
638 	    }
639 	    _krb5_put_int(ent->s2kparams->data,
640 			  1,
641 			  ent->s2kparams->length);
642 	}
643 	break;
644     default:
645 	break;
646     }
647     return 0;
648 }
649 
650 /*
651  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
652  * database (client supported enctypes first, then the unsupported
653  * enctypes).
654  */
655 
656 static krb5_error_code
get_pa_etype_info2(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)657 get_pa_etype_info2(krb5_context context,
658 		   krb5_kdc_configuration *config,
659 		   METHOD_DATA *md, Key *ckey)
660 {
661     krb5_error_code ret = 0;
662     ETYPE_INFO2 pa;
663     unsigned char *buf;
664     size_t len;
665 
666     pa.len = 1;
667     pa.val = calloc(1, sizeof(pa.val[0]));
668     if(pa.val == NULL)
669 	return ENOMEM;
670 
671     ret = make_etype_info2_entry(&pa.val[0], ckey);
672     if (ret) {
673 	free_ETYPE_INFO2(&pa);
674 	return ret;
675     }
676 
677     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
678     free_ETYPE_INFO2(&pa);
679     if(ret)
680 	return ret;
681     ret = realloc_method_data(md);
682     if(ret) {
683 	free(buf);
684 	return ret;
685     }
686     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
687     md->val[md->len - 1].padata_value.length = len;
688     md->val[md->len - 1].padata_value.data = buf;
689     return 0;
690 }
691 
692 /*
693  *
694  */
695 
696 static void
log_as_req(krb5_context context,krb5_kdc_configuration * config,krb5_enctype cetype,krb5_enctype setype,const KDC_REQ_BODY * b)697 log_as_req(krb5_context context,
698 	   krb5_kdc_configuration *config,
699 	   krb5_enctype cetype,
700 	   krb5_enctype setype,
701 	   const KDC_REQ_BODY *b)
702 {
703     krb5_error_code ret;
704     struct rk_strpool *p;
705     char *str;
706     size_t i;
707 
708     p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
709 
710     for (i = 0; i < b->etype.len; i++) {
711 	ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
712 	if (ret == 0) {
713 	    p = rk_strpoolprintf(p, "%s", str);
714 	    free(str);
715 	} else
716 	    p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
717 	if (p && i + 1 < b->etype.len)
718 	    p = rk_strpoolprintf(p, ", ");
719 	if (p == NULL) {
720 	    kdc_log(context, config, 0, "out of memory");
721 	    return;
722 	}
723     }
724     if (p == NULL)
725 	p = rk_strpoolprintf(p, "no encryption types");
726 
727     {
728 	char *cet;
729 	char *set;
730 
731 	ret = krb5_enctype_to_string(context, cetype, &cet);
732 	if(ret == 0) {
733 	    ret = krb5_enctype_to_string(context, setype, &set);
734 	    if (ret == 0) {
735 		p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
736 		free(set);
737 	    }
738 	    free(cet);
739 	}
740 	if (ret != 0)
741 	    p = rk_strpoolprintf(p, ", using enctypes %d/%d",
742 				 cetype, setype);
743     }
744 
745     str = rk_strpoolcollect(p);
746     kdc_log(context, config, 0, "%s", str);
747     free(str);
748 
749     {
750 	char fixedstr[128];
751 	unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
752 		      fixedstr, sizeof(fixedstr));
753 	if(*fixedstr)
754 	    kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
755     }
756 }
757 
758 /*
759  * verify the flags on `client' and `server', returning 0
760  * if they are OK and generating an error messages and returning
761  * and error code otherwise.
762  */
763 
764 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)765 kdc_check_flags(krb5_context context,
766 		krb5_kdc_configuration *config,
767 		hdb_entry_ex *client_ex, const char *client_name,
768 		hdb_entry_ex *server_ex, const char *server_name,
769 		krb5_boolean is_as_req)
770 {
771     if(client_ex != NULL) {
772 	hdb_entry *client = &client_ex->entry;
773 
774 	/* check client */
775 	if (client->flags.locked_out) {
776 	    kdc_log(context, config, 0,
777 		    "Client (%s) is locked out", client_name);
778 	    return KRB5KDC_ERR_POLICY;
779 	}
780 
781 	if (client->flags.invalid) {
782 	    kdc_log(context, config, 0,
783 		    "Client (%s) has invalid bit set", client_name);
784 	    return KRB5KDC_ERR_POLICY;
785 	}
786 
787 	if(!client->flags.client){
788 	    kdc_log(context, config, 0,
789 		    "Principal may not act as client -- %s", client_name);
790 	    return KRB5KDC_ERR_POLICY;
791 	}
792 
793 	if (client->valid_start && *client->valid_start > kdc_time) {
794 	    char starttime_str[100];
795 	    krb5_format_time(context, *client->valid_start,
796 			     starttime_str, sizeof(starttime_str), TRUE);
797 	    kdc_log(context, config, 0,
798 		    "Client not yet valid until %s -- %s",
799 		    starttime_str, client_name);
800 	    return KRB5KDC_ERR_CLIENT_NOTYET;
801 	}
802 
803 	if (client->valid_end && *client->valid_end < kdc_time) {
804 	    char endtime_str[100];
805 	    krb5_format_time(context, *client->valid_end,
806 			     endtime_str, sizeof(endtime_str), TRUE);
807 	    kdc_log(context, config, 0,
808 		    "Client expired at %s -- %s",
809 		    endtime_str, client_name);
810 	    return KRB5KDC_ERR_NAME_EXP;
811 	}
812 
813 	if (client->pw_end && *client->pw_end < kdc_time
814 	    && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
815 	    char pwend_str[100];
816 	    krb5_format_time(context, *client->pw_end,
817 			     pwend_str, sizeof(pwend_str), TRUE);
818 	    kdc_log(context, config, 0,
819 		    "Client's key has expired at %s -- %s",
820 		    pwend_str, client_name);
821 	    return KRB5KDC_ERR_KEY_EXPIRED;
822 	}
823     }
824 
825     /* check server */
826 
827     if (server_ex != NULL) {
828 	hdb_entry *server = &server_ex->entry;
829 
830 	if (server->flags.locked_out) {
831 	    kdc_log(context, config, 0,
832 		    "Client server locked out -- %s", server_name);
833 	    return KRB5KDC_ERR_POLICY;
834 	}
835 	if (server->flags.invalid) {
836 	    kdc_log(context, config, 0,
837 		    "Server has invalid flag set -- %s", server_name);
838 	    return KRB5KDC_ERR_POLICY;
839 	}
840 
841 	if(!server->flags.server){
842 	    kdc_log(context, config, 0,
843 		    "Principal may not act as server -- %s", server_name);
844 	    return KRB5KDC_ERR_POLICY;
845 	}
846 
847 	if(!is_as_req && server->flags.initial) {
848 	    kdc_log(context, config, 0,
849 		    "AS-REQ is required for server -- %s", server_name);
850 	    return KRB5KDC_ERR_POLICY;
851 	}
852 
853 	if (server->valid_start && *server->valid_start > kdc_time) {
854 	    char starttime_str[100];
855 	    krb5_format_time(context, *server->valid_start,
856 			     starttime_str, sizeof(starttime_str), TRUE);
857 	    kdc_log(context, config, 0,
858 		    "Server not yet valid until %s -- %s",
859 		    starttime_str, server_name);
860 	    return KRB5KDC_ERR_SERVICE_NOTYET;
861 	}
862 
863 	if (server->valid_end && *server->valid_end < kdc_time) {
864 	    char endtime_str[100];
865 	    krb5_format_time(context, *server->valid_end,
866 			     endtime_str, sizeof(endtime_str), TRUE);
867 	    kdc_log(context, config, 0,
868 		    "Server expired at %s -- %s",
869 		    endtime_str, server_name);
870 	    return KRB5KDC_ERR_SERVICE_EXP;
871 	}
872 
873 	if (server->pw_end && *server->pw_end < kdc_time) {
874 	    char pwend_str[100];
875 	    krb5_format_time(context, *server->pw_end,
876 			     pwend_str, sizeof(pwend_str), TRUE);
877 	    kdc_log(context, config, 0,
878 		    "Server's key has expired at -- %s",
879 		    pwend_str, server_name);
880 	    return KRB5KDC_ERR_KEY_EXPIRED;
881 	}
882     }
883     return 0;
884 }
885 
886 /*
887  * Return TRUE if `from' is part of `addresses' taking into consideration
888  * the configuration variables that tells us how strict we should be about
889  * these checks
890  */
891 
892 krb5_boolean
_kdc_check_addresses(krb5_context context,krb5_kdc_configuration * config,HostAddresses * addresses,const struct sockaddr * from)893 _kdc_check_addresses(krb5_context context,
894 		     krb5_kdc_configuration *config,
895 		     HostAddresses *addresses, const struct sockaddr *from)
896 {
897     krb5_error_code ret;
898     krb5_address addr;
899     krb5_boolean result;
900     krb5_boolean only_netbios = TRUE;
901     size_t i;
902 
903     if(config->check_ticket_addresses == 0)
904 	return TRUE;
905 
906     if(addresses == NULL)
907 	return config->allow_null_ticket_addresses;
908 
909     for (i = 0; i < addresses->len; ++i) {
910 	if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
911 	    only_netbios = FALSE;
912 	}
913     }
914 
915     /* Windows sends it's netbios name, which I can only assume is
916      * used for the 'allowed workstations' check.  This is painful,
917      * but we still want to check IP addresses if they happen to be
918      * present.
919      */
920 
921     if(only_netbios)
922 	return config->allow_null_ticket_addresses;
923 
924     ret = krb5_sockaddr2address (context, from, &addr);
925     if(ret)
926 	return FALSE;
927 
928     result = krb5_address_search(context, &addr, addresses);
929     krb5_free_address (context, &addr);
930     return result;
931 }
932 
933 /*
934  *
935  */
936 
937 static krb5_boolean
send_pac_p(krb5_context context,KDC_REQ * req)938 send_pac_p(krb5_context context, KDC_REQ *req)
939 {
940     krb5_error_code ret;
941     PA_PAC_REQUEST pacreq;
942     const PA_DATA *pa;
943     int i = 0;
944 
945     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
946     if (pa == NULL)
947 	return TRUE;
948 
949     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
950 				pa->padata_value.length,
951 				&pacreq,
952 				NULL);
953     if (ret)
954 	return TRUE;
955     i = pacreq.include_pac;
956     free_PA_PAC_REQUEST(&pacreq);
957     if (i == 0)
958 	return FALSE;
959     return TRUE;
960 }
961 
962 krb5_boolean
_kdc_is_anonymous(krb5_context context,krb5_principal principal)963 _kdc_is_anonymous(krb5_context context, krb5_principal principal)
964 {
965     if (principal->name.name_type != KRB5_NT_WELLKNOWN ||
966 	principal->name.name_string.len != 2 ||
967 	strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
968 	strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
969 	return 0;
970     return 1;
971 }
972 
973 /*
974  *
975  */
976 
977 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)978 _kdc_as_rep(krb5_context context,
979 	    krb5_kdc_configuration *config,
980 	    KDC_REQ *req,
981 	    const krb5_data *req_buffer,
982 	    krb5_data *reply,
983 	    const char *from,
984 	    struct sockaddr *from_addr,
985 	    int datagram_reply)
986 {
987     KDC_REQ_BODY *b = &req->req_body;
988     AS_REP rep;
989     KDCOptions f = b->kdc_options;
990     hdb_entry_ex *client = NULL, *server = NULL;
991     HDB *clientdb;
992     krb5_enctype setype, sessionetype;
993     krb5_data e_data;
994     EncTicketPart et;
995     EncKDCRepPart ek;
996     krb5_principal client_princ = NULL, server_princ = NULL;
997     char *client_name = NULL, *server_name = NULL;
998     krb5_error_code ret = 0;
999     const char *e_text = NULL;
1000     krb5_crypto crypto;
1001     Key *ckey, *skey;
1002     EncryptionKey *reply_key = NULL, session_key;
1003     int flags = HDB_F_FOR_AS_REQ;
1004 #ifdef PKINIT
1005     pk_client_params *pkp = NULL;
1006 #endif
1007 
1008     memset(&rep, 0, sizeof(rep));
1009     memset(&session_key, 0, sizeof(session_key));
1010     krb5_data_zero(&e_data);
1011 
1012     ALLOC(rep.padata);
1013     rep.padata->len = 0;
1014     rep.padata->val = NULL;
1015 
1016     if (f.canonicalize)
1017 	flags |= HDB_F_CANON;
1018 
1019     if(b->sname == NULL){
1020 	ret = KRB5KRB_ERR_GENERIC;
1021 	e_text = "No server in request";
1022     } else{
1023 	ret = _krb5_principalname2krb5_principal (context,
1024 						  &server_princ,
1025 						  *(b->sname),
1026 						  b->realm);
1027 	if (ret == 0)
1028 	    ret = krb5_unparse_name(context, server_princ, &server_name);
1029     }
1030     if (ret) {
1031 	kdc_log(context, config, 0,
1032 		"AS-REQ malformed server name from %s", from);
1033 	goto out;
1034     }
1035     if(b->cname == NULL){
1036 	ret = KRB5KRB_ERR_GENERIC;
1037 	e_text = "No client in request";
1038     } else {
1039 	ret = _krb5_principalname2krb5_principal (context,
1040 						  &client_princ,
1041 						  *(b->cname),
1042 						  b->realm);
1043 	if (ret)
1044 	    goto out;
1045 
1046 	ret = krb5_unparse_name(context, client_princ, &client_name);
1047     }
1048     if (ret) {
1049 	kdc_log(context, config, 0,
1050 		"AS-REQ malformed client name from %s", from);
1051 	goto out;
1052     }
1053 
1054     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1055 	    client_name, from, server_name);
1056 
1057     /*
1058      *
1059      */
1060 
1061     if (_kdc_is_anonymous(context, client_princ)) {
1062 	if (!b->kdc_options.request_anonymous) {
1063 	    kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
1064 	    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1065 	    goto out;
1066 	}
1067     } else if (b->kdc_options.request_anonymous) {
1068 	kdc_log(context, config, 0,
1069 		"Request for a anonymous ticket with non "
1070 		"anonymous client name: %s", client_name);
1071 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1072 	goto out;
1073     }
1074 
1075     /*
1076      *
1077      */
1078 
1079     ret = _kdc_db_fetch(context, config, client_princ,
1080 			HDB_F_GET_CLIENT | flags, NULL,
1081 			&clientdb, &client);
1082     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1083 	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name);
1084 	goto out;
1085     } else if(ret){
1086 	const char *msg = krb5_get_error_message(context, ret);
1087 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
1088 	krb5_free_error_message(context, msg);
1089 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1090 	goto out;
1091     }
1092     ret = _kdc_db_fetch(context, config, server_princ,
1093 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
1094 			NULL, NULL, &server);
1095     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1096 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name);
1097 	goto out;
1098     } else if(ret){
1099 	const char *msg = krb5_get_error_message(context, ret);
1100 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
1101 	krb5_free_error_message(context, msg);
1102 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1103 	goto out;
1104     }
1105 
1106     memset(&et, 0, sizeof(et));
1107     memset(&ek, 0, sizeof(ek));
1108 
1109     /*
1110      * Select a session enctype from the list of the crypto system
1111      * supported enctypes that is supported by the client and is one of
1112      * the enctype of the enctype of the service (likely krbtgt).
1113      *
1114      * The latter is used as a hint of what enctypes all KDC support,
1115      * to make sure a newer version of KDC won't generate a session
1116      * enctype that an older version of a KDC in the same realm can't
1117      * decrypt.
1118      */
1119     ret = _kdc_find_etype(context,
1120 			  krb5_principal_is_krbtgt(context, server_princ) ?
1121 			  config->tgt_use_strongest_session_key :
1122 			  config->svc_use_strongest_session_key, FALSE,
1123 			  client, b->etype.val, b->etype.len, &sessionetype,
1124 			  NULL);
1125     if (ret) {
1126 	kdc_log(context, config, 0,
1127 		"Client (%s) from %s has no common enctypes with KDC "
1128 		"to use for the session key",
1129 		client_name, from);
1130 	goto out;
1131     }
1132     /*
1133      * But if the KDC admin is paranoid and doesn't want to have "not
1134      * the best" enctypes on the krbtgt, lets save the best pick from
1135      * the client list and hope that that will work for any other
1136      * KDCs.
1137      */
1138 
1139     /*
1140      * Pre-auth processing
1141      */
1142 
1143     if(req->padata){
1144 	int i;
1145 	const PA_DATA *pa;
1146 	int found_pa = 0;
1147 
1148 	log_patypes(context, config, req->padata);
1149 
1150 #ifdef PKINIT
1151 	kdc_log(context, config, 5,
1152 		"Looking for PKINIT pa-data -- %s", client_name);
1153 
1154 	e_text = "No PKINIT PA found";
1155 
1156 	i = 0;
1157 	pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ);
1158 	if (pa == NULL) {
1159 	    i = 0;
1160 	    pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN);
1161 	}
1162 	if (pa) {
1163 	    char *client_cert = NULL;
1164 
1165 	    ret = _kdc_pk_rd_padata(context, config, req, pa, client, &pkp);
1166 	    if (ret) {
1167 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1168 		kdc_log(context, config, 5,
1169 			"Failed to decode PKINIT PA-DATA -- %s",
1170 			client_name);
1171 		goto ts_enc;
1172 	    }
1173 	    if (ret == 0 && pkp == NULL)
1174 		goto ts_enc;
1175 
1176 	    ret = _kdc_pk_check_client(context,
1177 				       config,
1178 				       clientdb,
1179 				       client,
1180 				       pkp,
1181 				       &client_cert);
1182 	    if (ret) {
1183 		e_text = "PKINIT certificate not allowed to "
1184 		    "impersonate principal";
1185 		_kdc_pk_free_client_param(context, pkp);
1186 
1187 		kdc_log(context, config, 0, "%s", e_text);
1188 		pkp = NULL;
1189 		goto out;
1190 	    }
1191 
1192 	    found_pa = 1;
1193 	    et.flags.pre_authent = 1;
1194 	    kdc_log(context, config, 0,
1195 		    "PKINIT pre-authentication succeeded -- %s using %s",
1196 		    client_name, client_cert);
1197 	    free(client_cert);
1198 	    if (pkp)
1199 		goto preauth_done;
1200 	}
1201     ts_enc:
1202 #endif
1203 	kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
1204 		client_name);
1205 
1206 	i = 0;
1207 	e_text = "No ENC-TS found";
1208 	while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1209 	    krb5_data ts_data;
1210 	    PA_ENC_TS_ENC p;
1211 	    size_t len;
1212 	    EncryptedData enc_data;
1213 	    Key *pa_key;
1214 	    char *str;
1215 
1216 	    found_pa = 1;
1217 
1218 	    if (b->kdc_options.request_anonymous) {
1219 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1220 		kdc_log(context, config, 0, "ENC-TS doesn't support anon");
1221 		goto out;
1222 	    }
1223 
1224 	    ret = decode_EncryptedData(pa->padata_value.data,
1225 				       pa->padata_value.length,
1226 				       &enc_data,
1227 				       &len);
1228 	    if (ret) {
1229 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1230 		kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
1231 			client_name);
1232 		goto out;
1233 	    }
1234 
1235 	    ret = hdb_enctype2key(context, &client->entry,
1236 				  enc_data.etype, &pa_key);
1237 	    if(ret){
1238 		char *estr;
1239 		e_text = "No key matches pa-data";
1240 		ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1241 		if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1242 		    estr = NULL;
1243 		if(estr == NULL)
1244 		    kdc_log(context, config, 5,
1245 			    "No client key matching pa-data (%d) -- %s",
1246 			    enc_data.etype, client_name);
1247 		else
1248 		    kdc_log(context, config, 5,
1249 			    "No client key matching pa-data (%s) -- %s",
1250 			    estr, client_name);
1251 		free(estr);
1252 		free_EncryptedData(&enc_data);
1253 
1254 		continue;
1255 	    }
1256 
1257 	try_next_key:
1258 	    ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
1259 	    if (ret) {
1260 		const char *msg = krb5_get_error_message(context, ret);
1261 		kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1262 		krb5_free_error_message(context, msg);
1263 		free_EncryptedData(&enc_data);
1264 		continue;
1265 	    }
1266 
1267 	    ret = krb5_decrypt_EncryptedData (context,
1268 					      crypto,
1269 					      KRB5_KU_PA_ENC_TIMESTAMP,
1270 					      &enc_data,
1271 					      &ts_data);
1272 	    krb5_crypto_destroy(context, crypto);
1273 	    /*
1274 	     * Since the user might have several keys with the same
1275 	     * enctype but with diffrent salting, we need to try all
1276 	     * the keys with the same enctype.
1277 	     */
1278 	    if(ret){
1279 		krb5_error_code ret2;
1280 		const char *msg = krb5_get_error_message(context, ret);
1281 
1282 		ret2 = krb5_enctype_to_string(context,
1283 					      pa_key->key.keytype, &str);
1284 		if (ret2)
1285 		    str = NULL;
1286 		kdc_log(context, config, 5,
1287 			"Failed to decrypt PA-DATA -- %s "
1288 			"(enctype %s) error %s",
1289 			client_name, str ? str : "unknown enctype", msg);
1290 		krb5_free_error_message(context, msg);
1291 		free(str);
1292 
1293 		if(hdb_next_enctype2key(context, &client->entry,
1294 					enc_data.etype, &pa_key) == 0)
1295 		    goto try_next_key;
1296 		e_text = "Failed to decrypt PA-DATA";
1297 
1298 		free_EncryptedData(&enc_data);
1299 
1300 		if (clientdb->hdb_auth_status)
1301 		    (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD);
1302 
1303 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
1304 		continue;
1305 	    }
1306 	    free_EncryptedData(&enc_data);
1307 	    ret = decode_PA_ENC_TS_ENC(ts_data.data,
1308 				       ts_data.length,
1309 				       &p,
1310 				       &len);
1311 	    krb5_data_free(&ts_data);
1312 	    if(ret){
1313 		e_text = "Failed to decode PA-ENC-TS-ENC";
1314 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
1315 		kdc_log(context, config,
1316 			5, "Failed to decode PA-ENC-TS_ENC -- %s",
1317 			client_name);
1318 		continue;
1319 	    }
1320 	    free_PA_ENC_TS_ENC(&p);
1321 	    if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1322 		char client_time[100];
1323 
1324 		krb5_format_time(context, p.patimestamp,
1325 				 client_time, sizeof(client_time), TRUE);
1326 
1327  		ret = KRB5KRB_AP_ERR_SKEW;
1328  		kdc_log(context, config, 0,
1329 			"Too large time skew, "
1330 			"client time %s is out by %jd > %jd seconds -- %s",
1331 			client_time,
1332 			imaxabs(kdc_time - p.patimestamp),
1333 			(intmax_t)context->max_skew,
1334 			client_name);
1335 
1336 		/*
1337 		 * The following is needed to make windows clients to
1338 		 * retry using the timestamp in the error message, if
1339 		 * there is a e_text, they become unhappy.
1340 		 */
1341 		e_text = NULL;
1342 		goto out;
1343 	    }
1344 	    et.flags.pre_authent = 1;
1345 
1346 	    set_salt_padata(rep.padata, pa_key->salt);
1347 
1348 	    reply_key = &pa_key->key;
1349 
1350 	    ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str);
1351 	    if (ret)
1352 		str = NULL;
1353 
1354 	    kdc_log(context, config, 2,
1355 		    "ENC-TS Pre-authentication succeeded -- %s using %s",
1356 		    client_name, str ? str : "unknown enctype");
1357 	    free(str);
1358 	    break;
1359 	}
1360 #ifdef PKINIT
1361     preauth_done:
1362 #endif
1363 	if(found_pa == 0 && config->require_preauth)
1364 	    goto use_pa;
1365 	/* We come here if we found a pa-enc-timestamp, but if there
1366            was some problem with it, other than too large skew */
1367 	if(found_pa && et.flags.pre_authent == 0){
1368 	    kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1369 	    e_text = NULL;
1370 	    goto out;
1371 	}
1372     }else if (config->require_preauth
1373 	      || b->kdc_options.request_anonymous /* hack to force anon */
1374 	      || client->entry.flags.require_preauth
1375 	      || server->entry.flags.require_preauth) {
1376 	METHOD_DATA method_data;
1377 	PA_DATA *pa;
1378 	unsigned char *buf;
1379 	size_t len;
1380 
1381     use_pa:
1382 	method_data.len = 0;
1383 	method_data.val = NULL;
1384 
1385 	ret = realloc_method_data(&method_data);
1386 	if (ret) {
1387 	    free_METHOD_DATA(&method_data);
1388 	    goto out;
1389 	}
1390 	pa = &method_data.val[method_data.len-1];
1391 	pa->padata_type		= KRB5_PADATA_ENC_TIMESTAMP;
1392 	pa->padata_value.length	= 0;
1393 	pa->padata_value.data	= NULL;
1394 
1395 #ifdef PKINIT
1396 	ret = realloc_method_data(&method_data);
1397 	if (ret) {
1398 	    free_METHOD_DATA(&method_data);
1399 	    goto out;
1400 	}
1401 	pa = &method_data.val[method_data.len-1];
1402 	pa->padata_type		= KRB5_PADATA_PK_AS_REQ;
1403 	pa->padata_value.length	= 0;
1404 	pa->padata_value.data	= NULL;
1405 
1406 	ret = realloc_method_data(&method_data);
1407 	if (ret) {
1408 	    free_METHOD_DATA(&method_data);
1409 	    goto out;
1410 	}
1411 	pa = &method_data.val[method_data.len-1];
1412 	pa->padata_type		= KRB5_PADATA_PK_AS_REQ_WIN;
1413 	pa->padata_value.length	= 0;
1414 	pa->padata_value.data	= NULL;
1415 #endif
1416 
1417 	/*
1418 	 * If there is a client key, send ETYPE_INFO{,2}
1419 	 */
1420 	ret = _kdc_find_etype(context,
1421 			      config->preauth_use_strongest_session_key, TRUE,
1422 			      client, b->etype.val, b->etype.len, NULL, &ckey);
1423 	if (ret == 0) {
1424 
1425 	    /*
1426 	     * RFC4120 requires:
1427 	     * - If the client only knows about old enctypes, then send
1428 	     *   both info replies (we send 'info' first in the list).
1429 	     * - If the client is 'modern', because it knows about 'new'
1430 	     *   enctype types, then only send the 'info2' reply.
1431 	     *
1432 	     * Before we send the full list of etype-info data, we pick
1433 	     * the client key we would have used anyway below, just pick
1434 	     * that instead.
1435 	     */
1436 
1437 	    if (older_enctype(ckey->key.keytype)) {
1438 		ret = get_pa_etype_info(context, config,
1439 					&method_data, ckey);
1440 		if (ret) {
1441 		    free_METHOD_DATA(&method_data);
1442 		    goto out;
1443 		}
1444 	    }
1445 	    ret = get_pa_etype_info2(context, config,
1446 				     &method_data, ckey);
1447 	    if (ret) {
1448 		free_METHOD_DATA(&method_data);
1449 		goto out;
1450 	    }
1451 	}
1452 
1453 	ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1454 	free_METHOD_DATA(&method_data);
1455 
1456 	e_data.data   = buf;
1457 	e_data.length = len;
1458 	e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1459 
1460 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1461 
1462 	kdc_log(context, config, 0,
1463 		"No preauth found, returning PREAUTH-REQUIRED -- %s",
1464 		client_name);
1465 	goto out;
1466     }
1467 
1468     if (clientdb->hdb_auth_status)
1469 	(clientdb->hdb_auth_status)(context, clientdb, client,
1470 				    HDB_AUTH_SUCCESS);
1471 
1472     /*
1473      * Verify flags after the user been required to prove its identity
1474      * with in a preauth mech.
1475      */
1476 
1477     ret = _kdc_check_access(context, config, client, client_name,
1478 			    server, server_name,
1479 			    req, &e_data);
1480     if(ret)
1481 	goto out;
1482 
1483     /*
1484      * Selelct the best encryption type for the KDC with out regard to
1485      * the client since the client never needs to read that data.
1486      */
1487 
1488     ret = _kdc_get_preferred_key(context, config,
1489 				 server, server_name,
1490 				 &setype, &skey);
1491     if(ret)
1492 	goto out;
1493 
1494     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1495        || (f.request_anonymous && !config->allow_anonymous)) {
1496 	ret = KRB5KDC_ERR_BADOPTION;
1497 	e_text = "Bad KDC options";
1498 	kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1499 	goto out;
1500     }
1501 
1502     rep.pvno = 5;
1503     rep.msg_type = krb_as_rep;
1504 
1505     ret = copy_Realm(&client->entry.principal->realm, &rep.crealm);
1506     if (ret)
1507 	goto out;
1508     ret = _krb5_principal2principalname(&rep.cname, client->entry.principal);
1509     if (ret)
1510 	goto out;
1511 
1512     rep.ticket.tkt_vno = 5;
1513     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1514     _krb5_principal2principalname(&rep.ticket.sname,
1515 				  server->entry.principal);
1516     /* java 1.6 expects the name to be the same type, lets allow that
1517      * uncomplicated name-types. */
1518 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
1519     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
1520 	rep.ticket.sname.name_type = b->sname->name_type;
1521 #undef CNT
1522 
1523     et.flags.initial = 1;
1524     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1525 	et.flags.forwardable = f.forwardable;
1526     else if (f.forwardable) {
1527 	e_text = "Ticket may not be forwardable";
1528 	ret = KRB5KDC_ERR_POLICY;
1529 	kdc_log(context, config, 0,
1530 		"Ticket may not be forwardable -- %s", client_name);
1531 	goto out;
1532     }
1533     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1534 	et.flags.proxiable = f.proxiable;
1535     else if (f.proxiable) {
1536 	e_text = "Ticket may not be proxiable";
1537 	ret = KRB5KDC_ERR_POLICY;
1538 	kdc_log(context, config, 0,
1539 		"Ticket may not be proxiable -- %s", client_name);
1540 	goto out;
1541     }
1542     if(client->entry.flags.postdate && server->entry.flags.postdate)
1543 	et.flags.may_postdate = f.allow_postdate;
1544     else if (f.allow_postdate){
1545 	e_text = "Ticket may not be postdate";
1546 	ret = KRB5KDC_ERR_POLICY;
1547 	kdc_log(context, config, 0,
1548 		"Ticket may not be postdatable -- %s", client_name);
1549 	goto out;
1550     }
1551 
1552     /* check for valid set of addresses */
1553     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1554 	e_text = "Bad address list in requested";
1555 	ret = KRB5KRB_AP_ERR_BADADDR;
1556 	kdc_log(context, config, 0,
1557 		"Bad address list requested -- %s", client_name);
1558 	goto out;
1559     }
1560 
1561     ret = copy_PrincipalName(&rep.cname, &et.cname);
1562     if (ret)
1563 	goto out;
1564     ret = copy_Realm(&rep.crealm, &et.crealm);
1565     if (ret)
1566 	goto out;
1567 
1568     {
1569 	time_t start;
1570 	time_t t;
1571 
1572 	start = et.authtime = kdc_time;
1573 
1574 	if(f.postdated && req->req_body.from){
1575 	    ALLOC(et.starttime);
1576 	    start = *et.starttime = *req->req_body.from;
1577 	    et.flags.invalid = 1;
1578 	    et.flags.postdated = 1; /* XXX ??? */
1579 	}
1580 	_kdc_fix_time(&b->till);
1581 	t = *b->till;
1582 
1583 	/* be careful not overflowing */
1584 
1585 	if(client->entry.max_life)
1586 	    t = start + min(t - start, *client->entry.max_life);
1587 	if(server->entry.max_life)
1588 	    t = start + min(t - start, *server->entry.max_life);
1589 #if 0
1590 	t = min(t, start + realm->max_life);
1591 #endif
1592 	et.endtime = t;
1593 	if(f.renewable_ok && et.endtime < *b->till){
1594 	    f.renewable = 1;
1595 	    if(b->rtime == NULL){
1596 		ALLOC(b->rtime);
1597 		*b->rtime = 0;
1598 	    }
1599 	    if(*b->rtime < *b->till)
1600 		*b->rtime = *b->till;
1601 	}
1602 	if(f.renewable && b->rtime){
1603 	    t = *b->rtime;
1604 	    if(t == 0)
1605 		t = MAX_TIME;
1606 	    if(client->entry.max_renew)
1607 		t = start + min(t - start, *client->entry.max_renew);
1608 	    if(server->entry.max_renew)
1609 		t = start + min(t - start, *server->entry.max_renew);
1610 #if 0
1611 	    t = min(t, start + realm->max_renew);
1612 #endif
1613 	    ALLOC(et.renew_till);
1614 	    *et.renew_till = t;
1615 	    et.flags.renewable = 1;
1616 	}
1617     }
1618 
1619     if (f.request_anonymous)
1620 	et.flags.anonymous = 1;
1621 
1622     if(b->addresses){
1623 	ALLOC(et.caddr);
1624 	copy_HostAddresses(b->addresses, et.caddr);
1625     }
1626 
1627     et.transited.tr_type = DOMAIN_X500_COMPRESS;
1628     krb5_data_zero(&et.transited.contents);
1629 
1630     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1631      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1632      * incapable of correctly decoding SEQUENCE OF's of zero length.
1633      *
1634      * To fix this, always send at least one no-op last_req
1635      *
1636      * If there's a pw_end or valid_end we will use that,
1637      * otherwise just a dummy lr.
1638      */
1639     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1640     if (ek.last_req.val == NULL) {
1641 	ret = ENOMEM;
1642 	goto out;
1643     }
1644     ek.last_req.len = 0;
1645     if (client->entry.pw_end
1646 	&& (config->kdc_warn_pwexpire == 0
1647 	    || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1648 	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1649 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1650 	++ek.last_req.len;
1651     }
1652     if (client->entry.valid_end) {
1653 	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1654 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1655 	++ek.last_req.len;
1656     }
1657     if (ek.last_req.len == 0) {
1658 	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1659 	ek.last_req.val[ek.last_req.len].lr_value = 0;
1660 	++ek.last_req.len;
1661     }
1662     ek.nonce = b->nonce;
1663     if (client->entry.valid_end || client->entry.pw_end) {
1664 	ALLOC(ek.key_expiration);
1665 	if (client->entry.valid_end) {
1666 	    if (client->entry.pw_end)
1667 		*ek.key_expiration = min(*client->entry.valid_end,
1668 					 *client->entry.pw_end);
1669 	    else
1670 		*ek.key_expiration = *client->entry.valid_end;
1671 	} else
1672 	    *ek.key_expiration = *client->entry.pw_end;
1673     } else
1674 	ek.key_expiration = NULL;
1675     ek.flags = et.flags;
1676     ek.authtime = et.authtime;
1677     if (et.starttime) {
1678 	ALLOC(ek.starttime);
1679 	*ek.starttime = *et.starttime;
1680     }
1681     ek.endtime = et.endtime;
1682     if (et.renew_till) {
1683 	ALLOC(ek.renew_till);
1684 	*ek.renew_till = *et.renew_till;
1685     }
1686     copy_Realm(&rep.ticket.realm, &ek.srealm);
1687     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1688     if(et.caddr){
1689 	ALLOC(ek.caddr);
1690 	copy_HostAddresses(et.caddr, ek.caddr);
1691     }
1692 
1693 #if PKINIT
1694     if (pkp) {
1695         e_text = "Failed to build PK-INIT reply";
1696 	ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1697 				  sessionetype, req, req_buffer,
1698 				  &reply_key, &et.key, rep.padata);
1699 	if (ret)
1700 	    goto out;
1701 	ret = _kdc_add_inital_verified_cas(context,
1702 					   config,
1703 					   pkp,
1704 					   &et);
1705 	if (ret)
1706 	    goto out;
1707 
1708     } else
1709 #endif
1710     {
1711 	ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1712 	if (ret)
1713 	    goto out;
1714     }
1715 
1716     if (reply_key == NULL) {
1717 	e_text = "Client have no reply key";
1718 	ret = KRB5KDC_ERR_CLIENT_NOTYET;
1719 	goto out;
1720     }
1721 
1722     ret = copy_EncryptionKey(&et.key, &ek.key);
1723     if (ret)
1724 	goto out;
1725 
1726     /* Add signing of alias referral */
1727     if (f.canonicalize) {
1728 	PA_ClientCanonicalized canon;
1729 	krb5_data data;
1730 	PA_DATA pa;
1731 	krb5_crypto cryptox;
1732 	size_t len = 0;
1733 
1734 	memset(&canon, 0, sizeof(canon));
1735 
1736 	canon.names.requested_name = *b->cname;
1737 	canon.names.mapped_name = client->entry.principal->name;
1738 
1739 	ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
1740 			   &canon.names, &len, ret);
1741 	if (ret)
1742 	    goto out;
1743 	if (data.length != len)
1744 	    krb5_abortx(context, "internal asn.1 error");
1745 
1746 	/* sign using "returned session key" */
1747 	ret = krb5_crypto_init(context, &et.key, 0, &cryptox);
1748 	if (ret) {
1749 	    free(data.data);
1750 	    goto out;
1751 	}
1752 
1753 	ret = krb5_create_checksum(context, cryptox,
1754 				   KRB5_KU_CANONICALIZED_NAMES, 0,
1755 				   data.data, data.length,
1756 				   &canon.canon_checksum);
1757 	free(data.data);
1758 	krb5_crypto_destroy(context, cryptox);
1759 	if (ret)
1760 	    goto out;
1761 
1762 	ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
1763 			   &canon, &len, ret);
1764 	free_Checksum(&canon.canon_checksum);
1765 	if (ret)
1766 	    goto out;
1767 	if (data.length != len)
1768 	    krb5_abortx(context, "internal asn.1 error");
1769 
1770 	pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
1771 	pa.padata_value = data;
1772 	ret = add_METHOD_DATA(rep.padata, &pa);
1773 	free(data.data);
1774 	if (ret)
1775 	    goto out;
1776     }
1777 
1778     if (rep.padata->len == 0) {
1779 	free(rep.padata);
1780 	rep.padata = NULL;
1781     }
1782 
1783     /* Add the PAC */
1784     if (send_pac_p(context, req)) {
1785 	krb5_pac p = NULL;
1786 	krb5_data data;
1787 
1788 	ret = _kdc_pac_generate(context, client, &p);
1789 	if (ret) {
1790 	    kdc_log(context, config, 0, "PAC generation failed for -- %s",
1791 		    client_name);
1792 	    goto out;
1793 	}
1794 	if (p != NULL) {
1795 	    ret = _krb5_pac_sign(context, p, et.authtime,
1796 				 client->entry.principal,
1797 				 &skey->key, /* Server key */
1798 				 &skey->key, /* FIXME: should be krbtgt key */
1799 				 &data);
1800 	    krb5_pac_free(context, p);
1801 	    if (ret) {
1802 		kdc_log(context, config, 0, "PAC signing failed for -- %s",
1803 			client_name);
1804 		goto out;
1805 	    }
1806 
1807 	    ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1808 					      KRB5_AUTHDATA_WIN2K_PAC,
1809 					      &data);
1810 	    krb5_data_free(&data);
1811 	    if (ret)
1812 		goto out;
1813 	}
1814     }
1815 
1816     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1817 		       et.endtime, et.renew_till);
1818 
1819     /* do this as the last thing since this signs the EncTicketPart */
1820     ret = _kdc_add_KRB5SignedPath(context,
1821 				  config,
1822 				  server,
1823 				  setype,
1824 				  client->entry.principal,
1825 				  NULL,
1826 				  NULL,
1827 				  &et);
1828     if (ret)
1829 	goto out;
1830 
1831     log_as_req(context, config, reply_key->keytype, setype, b);
1832 
1833     ret = _kdc_encode_reply(context, config,
1834 			    &rep, &et, &ek, setype, server->entry.kvno,
1835 			    &skey->key, client->entry.kvno,
1836 			    reply_key, 0, &e_text, reply);
1837     free_EncTicketPart(&et);
1838     free_EncKDCRepPart(&ek);
1839     if (ret)
1840 	goto out;
1841 
1842     /* */
1843     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1844 	krb5_data_free(reply);
1845 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1846 	e_text = "Reply packet too large";
1847     }
1848 
1849 out:
1850     free_AS_REP(&rep);
1851     if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){
1852 	krb5_mk_error(context,
1853 		      ret,
1854 		      e_text,
1855 		      (e_data.data ? &e_data : NULL),
1856 		      client_princ,
1857 		      server_princ,
1858 		      NULL,
1859 		      NULL,
1860 		      reply);
1861 	ret = 0;
1862     }
1863 #ifdef PKINIT
1864     if (pkp)
1865 	_kdc_pk_free_client_param(context, pkp);
1866 #endif
1867     if (e_data.data)
1868         free(e_data.data);
1869     if (client_princ)
1870 	krb5_free_principal(context, client_princ);
1871     free(client_name);
1872     if (server_princ)
1873 	krb5_free_principal(context, server_princ);
1874     free(server_name);
1875     if(client)
1876 	_kdc_free_ent(context, client);
1877     if(server)
1878 	_kdc_free_ent(context, server);
1879     return ret;
1880 }
1881 
1882 /*
1883  * Add the AuthorizationData `data´ of `type´ to the last element in
1884  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1885  */
1886 
1887 krb5_error_code
_kdc_tkt_add_if_relevant_ad(krb5_context context,EncTicketPart * tkt,int type,const krb5_data * data)1888 _kdc_tkt_add_if_relevant_ad(krb5_context context,
1889 			    EncTicketPart *tkt,
1890 			    int type,
1891 			    const krb5_data *data)
1892 {
1893     krb5_error_code ret;
1894     size_t size = 0;
1895 
1896     if (tkt->authorization_data == NULL) {
1897 	tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1898 	if (tkt->authorization_data == NULL) {
1899 	    krb5_set_error_message(context, ENOMEM, "out of memory");
1900 	    return ENOMEM;
1901 	}
1902     }
1903 
1904     /* add the entry to the last element */
1905     {
1906 	AuthorizationData ad = { 0, NULL };
1907 	AuthorizationDataElement ade;
1908 
1909 	ade.ad_type = type;
1910 	ade.ad_data = *data;
1911 
1912 	ret = add_AuthorizationData(&ad, &ade);
1913 	if (ret) {
1914 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
1915 	    return ret;
1916 	}
1917 
1918 	ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1919 
1920 	ASN1_MALLOC_ENCODE(AuthorizationData,
1921 			   ade.ad_data.data, ade.ad_data.length,
1922 			   &ad, &size, ret);
1923 	free_AuthorizationData(&ad);
1924 	if (ret) {
1925 	    krb5_set_error_message(context, ret, "ASN.1 encode of "
1926 				   "AuthorizationData failed");
1927 	    return ret;
1928 	}
1929 	if (ade.ad_data.length != size)
1930 	    krb5_abortx(context, "internal asn.1 encoder error");
1931 
1932 	ret = add_AuthorizationData(tkt->authorization_data, &ade);
1933 	der_free_octet_string(&ade.ad_data);
1934 	if (ret) {
1935 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
1936 	    return ret;
1937 	}
1938     }
1939 
1940     return 0;
1941 }
1942