xref: /freebsd/crypto/heimdal/kdc/kerberos5.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * Copyright (c) 1997-2003 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.145.2.4 2004/08/13 19:28:26 lha Exp $");
37 
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39 
40 static void
41 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 void
51 set_salt_padata (METHOD_DATA **m, Salt *salt)
52 {
53     if (salt) {
54 	ALLOC(*m);
55 	(*m)->len = 1;
56 	ALLOC((*m)->val);
57 	(*m)->val->padata_type = salt->type;
58 	copy_octet_string(&salt->salt,
59 			  &(*m)->val->padata_value);
60     }
61 }
62 
63 static PA_DATA*
64 find_padata(KDC_REQ *req, int *start, int type)
65 {
66     while(*start < req->padata->len){
67 	(*start)++;
68 	if(req->padata->val[*start - 1].padata_type == type)
69 	    return &req->padata->val[*start - 1];
70     }
71     return NULL;
72 }
73 
74 /*
75  * return the first appropriate key of `princ' in `ret_key'.  Look for
76  * all the etypes in (`etypes', `len'), stopping as soon as we find
77  * one, but preferring one that has default salt
78  */
79 
80 static krb5_error_code
81 find_etype(hdb_entry *princ, krb5_enctype *etypes, unsigned len,
82 	   Key **ret_key, krb5_enctype *ret_etype)
83 {
84     int i;
85     krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
86 
87     for(i = 0; ret != 0 && i < len ; i++) {
88 	Key *key = NULL;
89 
90 	while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
91 	    if (key->key.keyvalue.length == 0) {
92 		ret = KRB5KDC_ERR_NULL_KEY;
93 		continue;
94 	    }
95 	    *ret_key   = key;
96 	    *ret_etype = etypes[i];
97 	    ret = 0;
98 	    if (key->salt == NULL)
99 		return ret;
100 	}
101     }
102     return ret;
103 }
104 
105 static krb5_error_code
106 find_keys(hdb_entry *client,
107 	  hdb_entry *server,
108 	  Key **ckey,
109 	  krb5_enctype *cetype,
110 	  Key **skey,
111 	  krb5_enctype *setype,
112 	  krb5_enctype *etypes,
113 	  unsigned num_etypes)
114 {
115     krb5_error_code ret;
116 
117     if(client){
118 	/* find client key */
119 	ret = find_etype(client, etypes, num_etypes, ckey, cetype);
120 	if (ret) {
121 	    kdc_log(0, "Client has no support for etypes");
122 	    return ret;
123 	}
124     }
125 
126     if(server){
127 	/* find server key */
128 	ret = find_etype(server, etypes, num_etypes, skey, setype);
129 	if (ret) {
130 	    kdc_log(0, "Server has no support for etypes");
131 	    return ret;
132 	}
133     }
134     return 0;
135 }
136 
137 static krb5_error_code
138 make_anonymous_principalname (PrincipalName *pn)
139 {
140     pn->name_type = KRB5_NT_PRINCIPAL;
141     pn->name_string.len = 1;
142     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
143     if (pn->name_string.val == NULL)
144 	return ENOMEM;
145     pn->name_string.val[0] = strdup("anonymous");
146     if (pn->name_string.val[0] == NULL) {
147 	free(pn->name_string.val);
148 	pn->name_string.val = NULL;
149 	return ENOMEM;
150     }
151     return 0;
152 }
153 
154 static krb5_error_code
155 encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
156 	     krb5_enctype etype,
157 	     int skvno, EncryptionKey *skey,
158 	     int ckvno, EncryptionKey *ckey,
159 	     const char **e_text,
160 	     krb5_data *reply)
161 {
162     unsigned char *buf;
163     size_t buf_size;
164     size_t len;
165     krb5_error_code ret;
166     krb5_crypto crypto;
167 
168     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
169     if(ret) {
170 	kdc_log(0, "Failed to encode ticket: %s",
171 		krb5_get_err_text(context, ret));
172 	return ret;
173     }
174     if(buf_size != len) {
175 	free(buf);
176 	kdc_log(0, "Internal error in ASN.1 encoder");
177 	*e_text = "KDC internal error";
178 	return KRB5KRB_ERR_GENERIC;
179     }
180 
181     ret = krb5_crypto_init(context, skey, etype, &crypto);
182     if (ret) {
183 	free(buf);
184 	kdc_log(0, "krb5_crypto_init failed: %s",
185 		krb5_get_err_text(context, ret));
186 	return ret;
187     }
188 
189     ret = krb5_encrypt_EncryptedData(context,
190 				     crypto,
191 				     KRB5_KU_TICKET,
192 				     buf,
193 				     len,
194 				     skvno,
195 				     &rep->ticket.enc_part);
196     free(buf);
197     krb5_crypto_destroy(context, crypto);
198     if(ret) {
199 	kdc_log(0, "Failed to encrypt data: %s",
200 		krb5_get_err_text(context, ret));
201 	return ret;
202     }
203 
204     if(rep->msg_type == krb_as_rep && !encode_as_rep_as_tgs_rep)
205 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
206     else
207 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
208     if(ret) {
209 	kdc_log(0, "Failed to encode KDC-REP: %s",
210 		krb5_get_err_text(context, ret));
211 	return ret;
212     }
213     if(buf_size != len) {
214 	free(buf);
215 	kdc_log(0, "Internal error in ASN.1 encoder");
216 	*e_text = "KDC internal error";
217 	return KRB5KRB_ERR_GENERIC;
218     }
219     ret = krb5_crypto_init(context, ckey, 0, &crypto);
220     if (ret) {
221 	free(buf);
222 	kdc_log(0, "krb5_crypto_init failed: %s",
223 		krb5_get_err_text(context, ret));
224 	return ret;
225     }
226     if(rep->msg_type == krb_as_rep) {
227 	krb5_encrypt_EncryptedData(context,
228 				   crypto,
229 				   KRB5_KU_AS_REP_ENC_PART,
230 				   buf,
231 				   len,
232 				   ckvno,
233 				   &rep->enc_part);
234 	free(buf);
235 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
236     } else {
237 	krb5_encrypt_EncryptedData(context,
238 				   crypto,
239 				   KRB5_KU_TGS_REP_ENC_PART_SESSION,
240 				   buf,
241 				   len,
242 				   ckvno,
243 				   &rep->enc_part);
244 	free(buf);
245 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
246     }
247     krb5_crypto_destroy(context, crypto);
248     if(ret) {
249 	kdc_log(0, "Failed to encode KDC-REP: %s",
250 		krb5_get_err_text(context, ret));
251 	return ret;
252     }
253     if(buf_size != len) {
254 	free(buf);
255 	kdc_log(0, "Internal error in ASN.1 encoder");
256 	*e_text = "KDC internal error";
257 	return KRB5KRB_ERR_GENERIC;
258     }
259     reply->data = buf;
260     reply->length = buf_size;
261     return 0;
262 }
263 
264 static int
265 realloc_method_data(METHOD_DATA *md)
266 {
267     PA_DATA *pa;
268     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
269     if(pa == NULL)
270 	return ENOMEM;
271     md->val = pa;
272     md->len++;
273     return 0;
274 }
275 
276 static krb5_error_code
277 make_etype_info_entry(ETYPE_INFO_ENTRY *ent, Key *key)
278 {
279     ent->etype = key->key.keytype;
280     if(key->salt){
281 	ALLOC(ent->salttype);
282 #if 0
283 	if(key->salt->type == hdb_pw_salt)
284 	    *ent->salttype = 0; /* or 1? or NULL? */
285 	else if(key->salt->type == hdb_afs3_salt)
286 	    *ent->salttype = 2;
287 	else {
288 	    kdc_log(0, "unknown salt-type: %d",
289 		    key->salt->type);
290 	    return KRB5KRB_ERR_GENERIC;
291 	}
292 	/* according to `the specs', we can't send a salt if
293 	   we have AFS3 salted key, but that requires that you
294 	   *know* what cell you are using (e.g by assuming
295 	   that the cell is the same as the realm in lower
296 	   case) */
297 #else
298 	*ent->salttype = key->salt->type;
299 #endif
300 	krb5_copy_data(context, &key->salt->salt,
301 		       &ent->salt);
302     } else {
303 	/* we return no salt type at all, as that should indicate
304 	 * the default salt type and make everybody happy.  some
305 	 * systems (like w2k) dislike being told the salt type
306 	 * here. */
307 
308 	ent->salttype = NULL;
309 	ent->salt = NULL;
310     }
311     return 0;
312 }
313 
314 static krb5_error_code
315 get_pa_etype_info(METHOD_DATA *md, hdb_entry *client,
316 		  ENCTYPE *etypes, unsigned int etypes_len)
317 {
318     krb5_error_code ret = 0;
319     int i, j;
320     unsigned int n = 0;
321     ETYPE_INFO pa;
322     unsigned char *buf;
323     size_t len;
324 
325 
326     pa.len = client->keys.len;
327     if(pa.len > UINT_MAX/sizeof(*pa.val))
328 	return ERANGE;
329     pa.val = malloc(pa.len * sizeof(*pa.val));
330     if(pa.val == NULL)
331 	return ENOMEM;
332 
333     for(j = 0; j < etypes_len; j++) {
334 	for (i = 0; i < n; i++)
335 	    if (pa.val[i].etype == etypes[j])
336 		goto skip1;
337 	for(i = 0; i < client->keys.len; i++) {
338 	    if(client->keys.val[i].key.keytype == etypes[j])
339 		if((ret = make_etype_info_entry(&pa.val[n++],
340 						&client->keys.val[i])) != 0) {
341 		    free_ETYPE_INFO(&pa);
342 		    return ret;
343 		}
344 	}
345     skip1:;
346     }
347     for(i = 0; i < client->keys.len; i++) {
348 	for(j = 0; j < etypes_len; j++) {
349 	    if(client->keys.val[i].key.keytype == etypes[j])
350 		goto skip2;
351 	}
352 	if((ret = make_etype_info_entry(&pa.val[n++],
353 					&client->keys.val[i])) != 0) {
354 	    free_ETYPE_INFO(&pa);
355 	    return ret;
356 	}
357       skip2:;
358     }
359 
360     if(n != pa.len) {
361 	char *name;
362 	krb5_unparse_name(context, client->principal, &name);
363 	kdc_log(0, "internal error in get_pa_etype_info(%s): %d != %d",
364 		name, n, pa.len);
365 	free(name);
366 	pa.len = n;
367     }
368 
369     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
370     free_ETYPE_INFO(&pa);
371     if(ret)
372 	return ret;
373     ret = realloc_method_data(md);
374     if(ret) {
375 	free(buf);
376 	return ret;
377     }
378     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
379     md->val[md->len - 1].padata_value.length = len;
380     md->val[md->len - 1].padata_value.data = buf;
381     return 0;
382 }
383 
384 /*
385  * verify the flags on `client' and `server', returning 0
386  * if they are OK and generating an error messages and returning
387  * and error code otherwise.
388  */
389 
390 krb5_error_code
391 check_flags(hdb_entry *client, const char *client_name,
392 	    hdb_entry *server, const char *server_name,
393 	    krb5_boolean is_as_req)
394 {
395     if(client != NULL) {
396 	/* check client */
397 	if (client->flags.invalid) {
398 	    kdc_log(0, "Client (%s) has invalid bit set", client_name);
399 	    return KRB5KDC_ERR_POLICY;
400 	}
401 
402 	if(!client->flags.client){
403 	    kdc_log(0, "Principal may not act as client -- %s",
404 		    client_name);
405 	    return KRB5KDC_ERR_POLICY;
406 	}
407 
408 	if (client->valid_start && *client->valid_start > kdc_time) {
409 	    kdc_log(0, "Client not yet valid -- %s", client_name);
410 	    return KRB5KDC_ERR_CLIENT_NOTYET;
411 	}
412 
413 	if (client->valid_end && *client->valid_end < kdc_time) {
414 	    kdc_log(0, "Client expired -- %s", client_name);
415 	    return KRB5KDC_ERR_NAME_EXP;
416 	}
417 
418 	if (client->pw_end && *client->pw_end < kdc_time
419 	    && !server->flags.change_pw) {
420 	    kdc_log(0, "Client's key has expired -- %s", client_name);
421 	    return KRB5KDC_ERR_KEY_EXPIRED;
422 	}
423     }
424 
425     /* check server */
426 
427     if (server != NULL) {
428 	if (server->flags.invalid) {
429 	    kdc_log(0, "Server has invalid flag set -- %s", server_name);
430 	    return KRB5KDC_ERR_POLICY;
431 	}
432 
433 	if(!server->flags.server){
434 	    kdc_log(0, "Principal may not act as server -- %s",
435 		    server_name);
436 	    return KRB5KDC_ERR_POLICY;
437 	}
438 
439 	if(!is_as_req && server->flags.initial) {
440 	    kdc_log(0, "AS-REQ is required for server -- %s", server_name);
441 	    return KRB5KDC_ERR_POLICY;
442 	}
443 
444 	if (server->valid_start && *server->valid_start > kdc_time) {
445 	    kdc_log(0, "Server not yet valid -- %s", server_name);
446 	    return KRB5KDC_ERR_SERVICE_NOTYET;
447 	}
448 
449 	if (server->valid_end && *server->valid_end < kdc_time) {
450 	    kdc_log(0, "Server expired -- %s", server_name);
451 	    return KRB5KDC_ERR_SERVICE_EXP;
452 	}
453 
454 	if (server->pw_end && *server->pw_end < kdc_time) {
455 	    kdc_log(0, "Server's key has expired -- %s", server_name);
456 	    return KRB5KDC_ERR_KEY_EXPIRED;
457 	}
458     }
459     return 0;
460 }
461 
462 /*
463  * Return TRUE if `from' is part of `addresses' taking into consideration
464  * the configuration variables that tells us how strict we should be about
465  * these checks
466  */
467 
468 static krb5_boolean
469 check_addresses(HostAddresses *addresses, const struct sockaddr *from)
470 {
471     krb5_error_code ret;
472     krb5_address addr;
473     krb5_boolean result;
474 
475     if(check_ticket_addresses == 0)
476 	return TRUE;
477 
478     if(addresses == NULL)
479 	return allow_null_ticket_addresses;
480 
481     ret = krb5_sockaddr2address (context, from, &addr);
482     if(ret)
483 	return FALSE;
484 
485     result = krb5_address_search(context, &addr, addresses);
486     krb5_free_address (context, &addr);
487     return result;
488 }
489 
490 krb5_error_code
491 as_rep(KDC_REQ *req,
492        krb5_data *reply,
493        const char *from,
494        struct sockaddr *from_addr)
495 {
496     KDC_REQ_BODY *b = &req->req_body;
497     AS_REP rep;
498     KDCOptions f = b->kdc_options;
499     hdb_entry *client = NULL, *server = NULL;
500     krb5_enctype cetype, setype;
501     EncTicketPart et;
502     EncKDCRepPart ek;
503     krb5_principal client_princ = NULL, server_princ = NULL;
504     char *client_name = NULL, *server_name = NULL;
505     krb5_error_code ret = 0;
506     const char *e_text = NULL;
507     krb5_crypto crypto;
508     Key *ckey, *skey;
509 
510     memset(&rep, 0, sizeof(rep));
511 
512     if(b->sname == NULL){
513 	ret = KRB5KRB_ERR_GENERIC;
514 	e_text = "No server in request";
515     } else{
516 	principalname2krb5_principal (&server_princ, *(b->sname), b->realm);
517 	krb5_unparse_name(context, server_princ, &server_name);
518     }
519     if (ret) {
520 	kdc_log(0, "AS-REQ malformed server name from %s", from);
521 	goto out;
522     }
523 
524     if(b->cname == NULL){
525 	ret = KRB5KRB_ERR_GENERIC;
526 	e_text = "No client in request";
527     } else {
528 	principalname2krb5_principal (&client_princ, *(b->cname), b->realm);
529 	krb5_unparse_name(context, client_princ, &client_name);
530     }
531     if (ret) {
532 	kdc_log(0, "AS-REQ malformed client name from %s", from);
533 	goto out;
534     }
535 
536     kdc_log(0, "AS-REQ %s from %s for %s", client_name, from, server_name);
537 
538     ret = db_fetch(client_princ, &client);
539     if(ret){
540 	kdc_log(0, "UNKNOWN -- %s: %s", client_name,
541 		krb5_get_err_text(context, ret));
542 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
543 	goto out;
544     }
545 
546     ret = db_fetch(server_princ, &server);
547     if(ret){
548 	kdc_log(0, "UNKNOWN -- %s: %s", server_name,
549 		krb5_get_err_text(context, ret));
550 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
551 	goto out;
552     }
553 
554     ret = check_flags(client, client_name, server, server_name, TRUE);
555     if(ret)
556 	goto out;
557 
558     memset(&et, 0, sizeof(et));
559     memset(&ek, 0, sizeof(ek));
560 
561     if(req->padata){
562 	int i = 0;
563 	PA_DATA *pa;
564 	int found_pa = 0;
565 	kdc_log(5, "Looking for pa-data -- %s", client_name);
566 	while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
567 	    krb5_data ts_data;
568 	    PA_ENC_TS_ENC p;
569 	    time_t patime;
570 	    size_t len;
571 	    EncryptedData enc_data;
572 	    Key *pa_key;
573 
574 	    found_pa = 1;
575 
576 	    ret = decode_EncryptedData(pa->padata_value.data,
577 				       pa->padata_value.length,
578 				       &enc_data,
579 				       &len);
580 	    if (ret) {
581 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
582 		kdc_log(5, "Failed to decode PA-DATA -- %s",
583 			client_name);
584 		goto out;
585 	    }
586 
587 	    ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
588 	    if(ret){
589 		char *estr;
590 		e_text = "No key matches pa-data";
591 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
592 		if(krb5_enctype_to_string(context, enc_data.etype, &estr))
593 		    estr = NULL;
594 		if(estr == NULL)
595 		    kdc_log(5, "No client key matching pa-data (%d) -- %s",
596 			    enc_data.etype, client_name);
597 		else
598 		    kdc_log(5, "No client key matching pa-data (%s) -- %s",
599 			    estr, client_name);
600 		free(estr);
601 
602 		free_EncryptedData(&enc_data);
603 		continue;
604 	    }
605 
606 	  try_next_key:
607 	    ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
608 	    if (ret) {
609 		kdc_log(0, "krb5_crypto_init failed: %s",
610 			krb5_get_err_text(context, ret));
611 		free_EncryptedData(&enc_data);
612 		continue;
613 	    }
614 
615 	    ret = krb5_decrypt_EncryptedData (context,
616 					      crypto,
617 					      KRB5_KU_PA_ENC_TIMESTAMP,
618 					      &enc_data,
619 					      &ts_data);
620 	    krb5_crypto_destroy(context, crypto);
621 	    if(ret){
622 		if(hdb_next_enctype2key(context, client,
623 					enc_data.etype, &pa_key) == 0)
624 		    goto try_next_key;
625 		free_EncryptedData(&enc_data);
626 		e_text = "Failed to decrypt PA-DATA";
627 		kdc_log (5, "Failed to decrypt PA-DATA -- %s",
628 			 client_name);
629 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
630 		continue;
631 	    }
632 	    free_EncryptedData(&enc_data);
633 	    ret = decode_PA_ENC_TS_ENC(ts_data.data,
634 				       ts_data.length,
635 				       &p,
636 				       &len);
637 	    krb5_data_free(&ts_data);
638 	    if(ret){
639 		e_text = "Failed to decode PA-ENC-TS-ENC";
640 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
641 		kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s",
642 			 client_name);
643 		continue;
644 	    }
645 	    patime = p.patimestamp;
646 	    free_PA_ENC_TS_ENC(&p);
647 	    if (abs(kdc_time - p.patimestamp) > context->max_skew) {
648 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
649 		e_text = "Too large time skew";
650 		kdc_log(0, "Too large time skew -- %s", client_name);
651 		goto out;
652 	    }
653 	    et.flags.pre_authent = 1;
654 	    kdc_log(2, "Pre-authentication succeded -- %s", client_name);
655 	    break;
656 	}
657 	if(found_pa == 0 && require_preauth)
658 	    goto use_pa;
659 	/* We come here if we found a pa-enc-timestamp, but if there
660            was some problem with it, other than too large skew */
661 	if(found_pa && et.flags.pre_authent == 0){
662 	    kdc_log(0, "%s -- %s", e_text, client_name);
663 	    e_text = NULL;
664 	    goto out;
665 	}
666     }else if (require_preauth
667 	      || client->flags.require_preauth
668 	      || server->flags.require_preauth) {
669 	METHOD_DATA method_data;
670 	PA_DATA *pa;
671 	unsigned char *buf;
672 	size_t len;
673 	krb5_data foo_data;
674 
675       use_pa:
676 	method_data.len = 0;
677 	method_data.val = NULL;
678 
679 	ret = realloc_method_data(&method_data);
680 	pa = &method_data.val[method_data.len-1];
681 	pa->padata_type		= KRB5_PADATA_ENC_TIMESTAMP;
682 	pa->padata_value.length	= 0;
683 	pa->padata_value.data	= NULL;
684 
685 	ret = get_pa_etype_info(&method_data, client,
686 				b->etype.val, b->etype.len); /* XXX check ret */
687 
688 	ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
689 	free_METHOD_DATA(&method_data);
690 	foo_data.data   = buf;
691 	foo_data.length = len;
692 
693 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
694 	krb5_mk_error(context,
695 		      ret,
696 		      "Need to use PA-ENC-TIMESTAMP",
697 		      &foo_data,
698 		      client_princ,
699 		      server_princ,
700 		      NULL,
701 		      NULL,
702 		      reply);
703 	free(buf);
704 	kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name);
705 	ret = 0;
706 	goto out2;
707     }
708 
709     ret = find_keys(client, server, &ckey, &cetype, &skey, &setype,
710 		    b->etype.val, b->etype.len);
711     if(ret) {
712 	kdc_log(0, "Server/client has no support for etypes");
713 	goto out;
714     }
715 
716     {
717 	char *cet;
718 	char *set;
719 
720 	ret = krb5_enctype_to_string(context, cetype, &cet);
721 	if(ret == 0) {
722 	    ret = krb5_enctype_to_string(context, setype, &set);
723 	    if (ret == 0) {
724 		kdc_log(5, "Using %s/%s", cet, set);
725 		free(set);
726 	    }
727 	    free(cet);
728 	}
729 	if (ret != 0)
730 	    kdc_log(5, "Using e-types %d/%d", cetype, setype);
731     }
732 
733     {
734 	char str[128];
735 	unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str));
736 	if(*str)
737 	    kdc_log(2, "Requested flags: %s", str);
738     }
739 
740 
741     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
742        || (f.request_anonymous && !allow_anonymous)) {
743 	ret = KRB5KDC_ERR_BADOPTION;
744 	kdc_log(0, "Bad KDC options -- %s", client_name);
745 	goto out;
746     }
747 
748     rep.pvno = 5;
749     rep.msg_type = krb_as_rep;
750     copy_Realm(&b->realm, &rep.crealm);
751     if (f.request_anonymous)
752 	make_anonymous_principalname (&rep.cname);
753     else
754 	copy_PrincipalName(b->cname, &rep.cname);
755     rep.ticket.tkt_vno = 5;
756     copy_Realm(&b->realm, &rep.ticket.realm);
757     copy_PrincipalName(b->sname, &rep.ticket.sname);
758 
759     et.flags.initial = 1;
760     if(client->flags.forwardable && server->flags.forwardable)
761 	et.flags.forwardable = f.forwardable;
762     else if (f.forwardable) {
763 	ret = KRB5KDC_ERR_POLICY;
764 	kdc_log(0, "Ticket may not be forwardable -- %s", client_name);
765 	goto out;
766     }
767     if(client->flags.proxiable && server->flags.proxiable)
768 	et.flags.proxiable = f.proxiable;
769     else if (f.proxiable) {
770 	ret = KRB5KDC_ERR_POLICY;
771 	kdc_log(0, "Ticket may not be proxiable -- %s", client_name);
772 	goto out;
773     }
774     if(client->flags.postdate && server->flags.postdate)
775 	et.flags.may_postdate = f.allow_postdate;
776     else if (f.allow_postdate){
777 	ret = KRB5KDC_ERR_POLICY;
778 	kdc_log(0, "Ticket may not be postdatable -- %s", client_name);
779 	goto out;
780     }
781 
782     /* check for valid set of addresses */
783     if(!check_addresses(b->addresses, from_addr)) {
784 	ret = KRB5KRB_AP_ERR_BADADDR;
785 	kdc_log(0, "Bad address list requested -- %s", client_name);
786 	goto out;
787     }
788 
789     krb5_generate_random_keyblock(context, setype, &et.key);
790     copy_PrincipalName(&rep.cname, &et.cname);
791     copy_Realm(&b->realm, &et.crealm);
792 
793     {
794 	time_t start;
795 	time_t t;
796 
797 	start = et.authtime = kdc_time;
798 
799 	if(f.postdated && req->req_body.from){
800 	    ALLOC(et.starttime);
801 	    start = *et.starttime = *req->req_body.from;
802 	    et.flags.invalid = 1;
803 	    et.flags.postdated = 1; /* XXX ??? */
804 	}
805 	fix_time(&b->till);
806 	t = *b->till;
807 
808 	/* be careful not overflowing */
809 
810 	if(client->max_life)
811 	    t = start + min(t - start, *client->max_life);
812 	if(server->max_life)
813 	    t = start + min(t - start, *server->max_life);
814 #if 0
815 	t = min(t, start + realm->max_life);
816 #endif
817 	et.endtime = t;
818 	if(f.renewable_ok && et.endtime < *b->till){
819 	    f.renewable = 1;
820 	    if(b->rtime == NULL){
821 		ALLOC(b->rtime);
822 		*b->rtime = 0;
823 	    }
824 	    if(*b->rtime < *b->till)
825 		*b->rtime = *b->till;
826 	}
827 	if(f.renewable && b->rtime){
828 	    t = *b->rtime;
829 	    if(t == 0)
830 		t = MAX_TIME;
831 	    if(client->max_renew)
832 		t = start + min(t - start, *client->max_renew);
833 	    if(server->max_renew)
834 		t = start + min(t - start, *server->max_renew);
835 #if 0
836 	    t = min(t, start + realm->max_renew);
837 #endif
838 	    ALLOC(et.renew_till);
839 	    *et.renew_till = t;
840 	    et.flags.renewable = 1;
841 	}
842     }
843 
844     if (f.request_anonymous)
845 	et.flags.anonymous = 1;
846 
847     if(b->addresses){
848 	ALLOC(et.caddr);
849 	copy_HostAddresses(b->addresses, et.caddr);
850     }
851 
852     et.transited.tr_type = DOMAIN_X500_COMPRESS;
853     krb5_data_zero(&et.transited.contents);
854 
855     copy_EncryptionKey(&et.key, &ek.key);
856 
857     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
858      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
859      * incapable of correctly decoding SEQUENCE OF's of zero length.
860      *
861      * To fix this, always send at least one no-op last_req
862      *
863      * If there's a pw_end or valid_end we will use that,
864      * otherwise just a dummy lr.
865      */
866     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
867     ek.last_req.len = 0;
868     if (client->pw_end
869 	&& (kdc_warn_pwexpire == 0
870 	    || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) {
871 	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
872 	ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
873 	++ek.last_req.len;
874     }
875     if (client->valid_end) {
876 	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
877 	ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
878 	++ek.last_req.len;
879     }
880     if (ek.last_req.len == 0) {
881 	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
882 	ek.last_req.val[ek.last_req.len].lr_value = 0;
883 	++ek.last_req.len;
884     }
885     ek.nonce = b->nonce;
886     if (client->valid_end || client->pw_end) {
887 	ALLOC(ek.key_expiration);
888 	if (client->valid_end) {
889 	    if (client->pw_end)
890 		*ek.key_expiration = min(*client->valid_end, *client->pw_end);
891 	    else
892 		*ek.key_expiration = *client->valid_end;
893 	} else
894 	    *ek.key_expiration = *client->pw_end;
895     } else
896 	ek.key_expiration = NULL;
897     ek.flags = et.flags;
898     ek.authtime = et.authtime;
899     if (et.starttime) {
900 	ALLOC(ek.starttime);
901 	*ek.starttime = *et.starttime;
902     }
903     ek.endtime = et.endtime;
904     if (et.renew_till) {
905 	ALLOC(ek.renew_till);
906 	*ek.renew_till = *et.renew_till;
907     }
908     copy_Realm(&rep.ticket.realm, &ek.srealm);
909     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
910     if(et.caddr){
911 	ALLOC(ek.caddr);
912 	copy_HostAddresses(et.caddr, ek.caddr);
913     }
914 
915     set_salt_padata (&rep.padata, ckey->salt);
916     ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key,
917 		       client->kvno, &ckey->key, &e_text, reply);
918     free_EncTicketPart(&et);
919     free_EncKDCRepPart(&ek);
920   out:
921     free_AS_REP(&rep);
922     if(ret){
923 	krb5_mk_error(context,
924 		      ret,
925 		      e_text,
926 		      NULL,
927 		      client_princ,
928 		      server_princ,
929 		      NULL,
930 		      NULL,
931 		      reply);
932 	ret = 0;
933     }
934   out2:
935     if (client_princ)
936 	krb5_free_principal(context, client_princ);
937     free(client_name);
938     if (server_princ)
939 	krb5_free_principal(context, server_princ);
940     free(server_name);
941     if(client)
942 	free_ent(client);
943     if(server)
944 	free_ent(server);
945     return ret;
946 }
947 
948 
949 static krb5_error_code
950 check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
951 {
952     KDCOptions f = b->kdc_options;
953 
954     if(f.validate){
955 	if(!tgt->flags.invalid || tgt->starttime == NULL){
956 	    kdc_log(0, "Bad request to validate ticket");
957 	    return KRB5KDC_ERR_BADOPTION;
958 	}
959 	if(*tgt->starttime > kdc_time){
960 	    kdc_log(0, "Early request to validate ticket");
961 	    return KRB5KRB_AP_ERR_TKT_NYV;
962 	}
963 	/* XXX  tkt = tgt */
964 	et->flags.invalid = 0;
965     }else if(tgt->flags.invalid){
966 	kdc_log(0, "Ticket-granting ticket has INVALID flag set");
967 	return KRB5KRB_AP_ERR_TKT_INVALID;
968     }
969 
970     if(f.forwardable){
971 	if(!tgt->flags.forwardable){
972 	    kdc_log(0, "Bad request for forwardable ticket");
973 	    return KRB5KDC_ERR_BADOPTION;
974 	}
975 	et->flags.forwardable = 1;
976     }
977     if(f.forwarded){
978 	if(!tgt->flags.forwardable){
979 	    kdc_log(0, "Request to forward non-forwardable ticket");
980 	    return KRB5KDC_ERR_BADOPTION;
981 	}
982 	et->flags.forwarded = 1;
983 	et->caddr = b->addresses;
984     }
985     if(tgt->flags.forwarded)
986 	et->flags.forwarded = 1;
987 
988     if(f.proxiable){
989 	if(!tgt->flags.proxiable){
990 	    kdc_log(0, "Bad request for proxiable ticket");
991 	    return KRB5KDC_ERR_BADOPTION;
992 	}
993 	et->flags.proxiable = 1;
994     }
995     if(f.proxy){
996 	if(!tgt->flags.proxiable){
997 	    kdc_log(0, "Request to proxy non-proxiable ticket");
998 	    return KRB5KDC_ERR_BADOPTION;
999 	}
1000 	et->flags.proxy = 1;
1001 	et->caddr = b->addresses;
1002     }
1003     if(tgt->flags.proxy)
1004 	et->flags.proxy = 1;
1005 
1006     if(f.allow_postdate){
1007 	if(!tgt->flags.may_postdate){
1008 	    kdc_log(0, "Bad request for post-datable ticket");
1009 	    return KRB5KDC_ERR_BADOPTION;
1010 	}
1011 	et->flags.may_postdate = 1;
1012     }
1013     if(f.postdated){
1014 	if(!tgt->flags.may_postdate){
1015 	    kdc_log(0, "Bad request for postdated ticket");
1016 	    return KRB5KDC_ERR_BADOPTION;
1017 	}
1018 	if(b->from)
1019 	    *et->starttime = *b->from;
1020 	et->flags.postdated = 1;
1021 	et->flags.invalid = 1;
1022     }else if(b->from && *b->from > kdc_time + context->max_skew){
1023 	kdc_log(0, "Ticket cannot be postdated");
1024 	return KRB5KDC_ERR_CANNOT_POSTDATE;
1025     }
1026 
1027     if(f.renewable){
1028 	if(!tgt->flags.renewable){
1029 	    kdc_log(0, "Bad request for renewable ticket");
1030 	    return KRB5KDC_ERR_BADOPTION;
1031 	}
1032 	et->flags.renewable = 1;
1033 	ALLOC(et->renew_till);
1034 	fix_time(&b->rtime);
1035 	*et->renew_till = *b->rtime;
1036     }
1037     if(f.renew){
1038 	time_t old_life;
1039 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
1040 	    kdc_log(0, "Request to renew non-renewable ticket");
1041 	    return KRB5KDC_ERR_BADOPTION;
1042 	}
1043 	old_life = tgt->endtime;
1044 	if(tgt->starttime)
1045 	    old_life -= *tgt->starttime;
1046 	else
1047 	    old_life -= tgt->authtime;
1048 	et->endtime = *et->starttime + old_life;
1049 	if (et->renew_till != NULL)
1050 	    et->endtime = min(*et->renew_till, et->endtime);
1051     }
1052 
1053     /* checks for excess flags */
1054     if(f.request_anonymous && !allow_anonymous){
1055 	kdc_log(0, "Request for anonymous ticket");
1056 	return KRB5KDC_ERR_BADOPTION;
1057     }
1058     return 0;
1059 }
1060 
1061 static krb5_error_code
1062 fix_transited_encoding(krb5_boolean check_policy,
1063 		       TransitedEncoding *tr,
1064 		       EncTicketPart *et,
1065 		       const char *client_realm,
1066 		       const char *server_realm,
1067 		       const char *tgt_realm)
1068 {
1069     krb5_error_code ret = 0;
1070     char **realms, **tmp;
1071     int num_realms;
1072     int i;
1073 
1074     if(tr->tr_type != DOMAIN_X500_COMPRESS) {
1075 	kdc_log(0, "Unknown transited type: %u", tr->tr_type);
1076 	return KRB5KDC_ERR_TRTYPE_NOSUPP;
1077     }
1078 
1079     ret = krb5_domain_x500_decode(context,
1080 				  tr->contents,
1081 				  &realms,
1082 				  &num_realms,
1083 				  client_realm,
1084 				  server_realm);
1085     if(ret){
1086 	krb5_warn(context, ret, "Decoding transited encoding");
1087 	return ret;
1088     }
1089     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
1090 	/* not us, so add the previous realm to transited set */
1091 	if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1092 	    ret = ERANGE;
1093 	    goto free_realms;
1094 	}
1095 	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1096 	if(tmp == NULL){
1097 	    ret = ENOMEM;
1098 	    goto free_realms;
1099 	}
1100 	realms = tmp;
1101 	realms[num_realms] = strdup(tgt_realm);
1102 	if(realms[num_realms] == NULL){
1103 	    ret = ENOMEM;
1104 	    goto free_realms;
1105 	}
1106 	num_realms++;
1107     }
1108     if(num_realms == 0) {
1109 	if(strcmp(client_realm, server_realm))
1110 	    kdc_log(0, "cross-realm %s -> %s", client_realm, server_realm);
1111     } else {
1112 	size_t l = 0;
1113 	char *rs;
1114 	for(i = 0; i < num_realms; i++)
1115 	    l += strlen(realms[i]) + 2;
1116 	rs = malloc(l);
1117 	if(rs != NULL) {
1118 	    *rs = '\0';
1119 	    for(i = 0; i < num_realms; i++) {
1120 		if(i > 0)
1121 		    strlcat(rs, ", ", l);
1122 		strlcat(rs, realms[i], l);
1123 	    }
1124 	    kdc_log(0, "cross-realm %s -> %s via [%s]", client_realm, server_realm, rs);
1125 	    free(rs);
1126 	}
1127     }
1128     if(check_policy) {
1129 	ret = krb5_check_transited(context, client_realm,
1130 				   server_realm,
1131 				   realms, num_realms, NULL);
1132 	if(ret) {
1133 	    krb5_warn(context, ret, "cross-realm %s -> %s",
1134 		      client_realm, server_realm);
1135 	    goto free_realms;
1136 	}
1137 	et->flags.transited_policy_checked = 1;
1138     }
1139     et->transited.tr_type = DOMAIN_X500_COMPRESS;
1140     ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
1141     if(ret)
1142 	krb5_warn(context, ret, "Encoding transited encoding");
1143   free_realms:
1144     for(i = 0; i < num_realms; i++)
1145 	free(realms[i]);
1146     free(realms);
1147     return ret;
1148 }
1149 
1150 
1151 static krb5_error_code
1152 tgs_make_reply(KDC_REQ_BODY *b,
1153 	       EncTicketPart *tgt,
1154 	       EncTicketPart *adtkt,
1155 	       AuthorizationData *auth_data,
1156 	       hdb_entry *server,
1157 	       hdb_entry *client,
1158 	       krb5_principal client_principal,
1159 	       hdb_entry *krbtgt,
1160 	       krb5_enctype cetype,
1161 	       const char **e_text,
1162 	       krb5_data *reply)
1163 {
1164     KDC_REP rep;
1165     EncKDCRepPart ek;
1166     EncTicketPart et;
1167     KDCOptions f = b->kdc_options;
1168     krb5_error_code ret;
1169     krb5_enctype etype;
1170     Key *skey;
1171     EncryptionKey *ekey;
1172 
1173     if(adtkt) {
1174 	int i;
1175 	krb5_keytype kt;
1176 	ekey = &adtkt->key;
1177 	for(i = 0; i < b->etype.len; i++){
1178 	    ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1179 	    if(ret)
1180 		continue;
1181 	    if(adtkt->key.keytype == kt)
1182 		break;
1183 	}
1184 	if(i == b->etype.len)
1185 	    return KRB5KDC_ERR_ETYPE_NOSUPP;
1186 	etype = b->etype.val[i];
1187     }else{
1188 	ret = find_keys(NULL, server, NULL, NULL, &skey, &etype,
1189 			b->etype.val, b->etype.len);
1190 	if(ret) {
1191 	    kdc_log(0, "Server has no support for etypes");
1192 	    return ret;
1193 	}
1194 	ekey = &skey->key;
1195     }
1196 
1197     memset(&rep, 0, sizeof(rep));
1198     memset(&et, 0, sizeof(et));
1199     memset(&ek, 0, sizeof(ek));
1200 
1201     rep.pvno = 5;
1202     rep.msg_type = krb_tgs_rep;
1203 
1204     et.authtime = tgt->authtime;
1205     fix_time(&b->till);
1206     et.endtime = min(tgt->endtime, *b->till);
1207     ALLOC(et.starttime);
1208     *et.starttime = kdc_time;
1209 
1210     ret = check_tgs_flags(b, tgt, &et);
1211     if(ret)
1212 	goto out;
1213 
1214     /* We should check the transited encoding if:
1215        1) the request doesn't ask not to be checked
1216        2) globally enforcing a check
1217        3) principal requires checking
1218        4) we allow non-check per-principal, but principal isn't marked as allowing this
1219        5) we don't globally allow this
1220     */
1221 
1222 #define GLOBAL_FORCE_TRANSITED_CHECK		(trpolicy == TRPOLICY_ALWAYS_CHECK)
1223 #define GLOBAL_ALLOW_PER_PRINCIPAL		(trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
1224 #define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK	(trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
1225 /* these will consult the database in future release */
1226 #define PRINCIPAL_FORCE_TRANSITED_CHECK(P)		0
1227 #define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)	0
1228 
1229     ret = fix_transited_encoding(!f.disable_transited_check ||
1230 				 GLOBAL_FORCE_TRANSITED_CHECK ||
1231 				 PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
1232 				 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
1233 				    PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
1234 				   GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
1235 				 &tgt->transited, &et,
1236 				 *krb5_princ_realm(context, client_principal),
1237 				 *krb5_princ_realm(context, server->principal),
1238 				 *krb5_princ_realm(context, krbtgt->principal));
1239     if(ret)
1240 	goto out;
1241 
1242     copy_Realm(krb5_princ_realm(context, server->principal),
1243 	       &rep.ticket.realm);
1244     krb5_principal2principalname(&rep.ticket.sname, server->principal);
1245     copy_Realm(&tgt->crealm, &rep.crealm);
1246     if (f.request_anonymous)
1247 	make_anonymous_principalname (&tgt->cname);
1248     else
1249 	copy_PrincipalName(&tgt->cname, &rep.cname);
1250     rep.ticket.tkt_vno = 5;
1251 
1252     ek.caddr = et.caddr;
1253     if(et.caddr == NULL)
1254 	et.caddr = tgt->caddr;
1255 
1256     {
1257 	time_t life;
1258 	life = et.endtime - *et.starttime;
1259 	if(client && client->max_life)
1260 	    life = min(life, *client->max_life);
1261 	if(server->max_life)
1262 	    life = min(life, *server->max_life);
1263 	et.endtime = *et.starttime + life;
1264     }
1265     if(f.renewable_ok && tgt->flags.renewable &&
1266        et.renew_till == NULL && et.endtime < *b->till){
1267 	et.flags.renewable = 1;
1268 	ALLOC(et.renew_till);
1269 	*et.renew_till = *b->till;
1270     }
1271     if(et.renew_till){
1272 	time_t renew;
1273 	renew = *et.renew_till - et.authtime;
1274 	if(client && client->max_renew)
1275 	    renew = min(renew, *client->max_renew);
1276 	if(server->max_renew)
1277 	    renew = min(renew, *server->max_renew);
1278 	*et.renew_till = et.authtime + renew;
1279     }
1280 
1281     if(et.renew_till){
1282 	*et.renew_till = min(*et.renew_till, *tgt->renew_till);
1283 	*et.starttime = min(*et.starttime, *et.renew_till);
1284 	et.endtime = min(et.endtime, *et.renew_till);
1285     }
1286 
1287     *et.starttime = min(*et.starttime, et.endtime);
1288 
1289     if(*et.starttime == et.endtime){
1290 	ret = KRB5KDC_ERR_NEVER_VALID;
1291 	goto out;
1292     }
1293     if(et.renew_till && et.endtime == *et.renew_till){
1294 	free(et.renew_till);
1295 	et.renew_till = NULL;
1296 	et.flags.renewable = 0;
1297     }
1298 
1299     et.flags.pre_authent = tgt->flags.pre_authent;
1300     et.flags.hw_authent  = tgt->flags.hw_authent;
1301     et.flags.anonymous   = tgt->flags.anonymous;
1302 
1303     /* XXX Check enc-authorization-data */
1304     et.authorization_data = auth_data;
1305 
1306     krb5_generate_random_keyblock(context, etype, &et.key);
1307     et.crealm = tgt->crealm;
1308     et.cname = tgt->cname;
1309 
1310     ek.key = et.key;
1311     /* MIT must have at least one last_req */
1312     ek.last_req.len = 1;
1313     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1314     ek.nonce = b->nonce;
1315     ek.flags = et.flags;
1316     ek.authtime = et.authtime;
1317     ek.starttime = et.starttime;
1318     ek.endtime = et.endtime;
1319     ek.renew_till = et.renew_till;
1320     ek.srealm = rep.ticket.realm;
1321     ek.sname = rep.ticket.sname;
1322 
1323     /* It is somewhat unclear where the etype in the following
1324        encryption should come from. What we have is a session
1325        key in the passed tgt, and a list of preferred etypes
1326        *for the new ticket*. Should we pick the best possible
1327        etype, given the keytype in the tgt, or should we look
1328        at the etype list here as well?  What if the tgt
1329        session key is DES3 and we want a ticket with a (say)
1330        CAST session key. Should the DES3 etype be added to the
1331        etype list, even if we don't want a session key with
1332        DES3? */
1333     ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1334 		       0, &tgt->key, e_text, reply);
1335   out:
1336     free_TGS_REP(&rep);
1337     free_TransitedEncoding(&et.transited);
1338     if(et.starttime)
1339 	free(et.starttime);
1340     if(et.renew_till)
1341 	free(et.renew_till);
1342     free_LastReq(&ek.last_req);
1343     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1344     free_EncryptionKey(&et.key);
1345     return ret;
1346 }
1347 
1348 static krb5_error_code
1349 tgs_check_authenticator(krb5_auth_context ac,
1350 			KDC_REQ_BODY *b,
1351 			const char **e_text,
1352 			krb5_keyblock *key)
1353 {
1354     krb5_authenticator auth;
1355     size_t len;
1356     unsigned char *buf;
1357     size_t buf_size;
1358     krb5_error_code ret;
1359     krb5_crypto crypto;
1360 
1361     krb5_auth_con_getauthenticator(context, ac, &auth);
1362     if(auth->cksum == NULL){
1363 	kdc_log(0, "No authenticator in request");
1364 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1365 	goto out;
1366     }
1367     /*
1368      * according to RFC1510 it doesn't need to be keyed,
1369      * but according to the latest draft it needs to.
1370      */
1371     if (
1372 #if 0
1373 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1374 	||
1375 #endif
1376  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1377 	kdc_log(0, "Bad checksum type in authenticator: %d",
1378 		auth->cksum->cksumtype);
1379 	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
1380 	goto out;
1381     }
1382 
1383     /* XXX should not re-encode this */
1384     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1385     if(ret){
1386 	kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
1387 		krb5_get_err_text(context, ret));
1388 	goto out;
1389     }
1390     if(buf_size != len) {
1391 	free(buf);
1392 	kdc_log(0, "Internal error in ASN.1 encoder");
1393 	*e_text = "KDC internal error";
1394 	ret = KRB5KRB_ERR_GENERIC;
1395 	goto out;
1396     }
1397     ret = krb5_crypto_init(context, key, 0, &crypto);
1398     if (ret) {
1399 	free(buf);
1400 	kdc_log(0, "krb5_crypto_init failed: %s",
1401 		krb5_get_err_text(context, ret));
1402 	goto out;
1403     }
1404     ret = krb5_verify_checksum(context,
1405 			       crypto,
1406 			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
1407 			       buf,
1408 			       len,
1409 			       auth->cksum);
1410     free(buf);
1411     krb5_crypto_destroy(context, crypto);
1412     if(ret){
1413 	kdc_log(0, "Failed to verify checksum: %s",
1414 		krb5_get_err_text(context, ret));
1415     }
1416 out:
1417     free_Authenticator(auth);
1418     free(auth);
1419     return ret;
1420 }
1421 
1422 /*
1423  * return the realm of a krbtgt-ticket or NULL
1424  */
1425 
1426 static Realm
1427 get_krbtgt_realm(const PrincipalName *p)
1428 {
1429     if(p->name_string.len == 2
1430        && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1431 	return p->name_string.val[1];
1432     else
1433 	return NULL;
1434 }
1435 
1436 static Realm
1437 find_rpath(Realm crealm, Realm srealm)
1438 {
1439     const char *new_realm = krb5_config_get_string(context,
1440 						   NULL,
1441 						   "capaths",
1442 						   crealm,
1443 						   srealm,
1444 						   NULL);
1445     return (Realm)new_realm;
1446 }
1447 
1448 
1449 static krb5_boolean
1450 need_referral(krb5_principal server, krb5_realm **realms)
1451 {
1452     if(server->name.name_type != KRB5_NT_SRV_INST ||
1453        server->name.name_string.len != 2)
1454 	return FALSE;
1455 
1456     return krb5_get_host_realm_int(context, server->name.name_string.val[1],
1457 				   FALSE, realms) == 0;
1458 }
1459 
1460 static krb5_error_code
1461 tgs_rep2(KDC_REQ_BODY *b,
1462 	 PA_DATA *tgs_req,
1463 	 krb5_data *reply,
1464 	 const char *from,
1465 	 const struct sockaddr *from_addr,
1466 	 time_t **csec,
1467 	 int **cusec)
1468 {
1469     krb5_ap_req ap_req;
1470     krb5_error_code ret;
1471     krb5_principal princ;
1472     krb5_auth_context ac = NULL;
1473     krb5_ticket *ticket = NULL;
1474     krb5_flags ap_req_options;
1475     krb5_flags verify_ap_req_flags;
1476     const char *e_text = NULL;
1477     krb5_crypto crypto;
1478 
1479     hdb_entry *krbtgt = NULL;
1480     EncTicketPart *tgt;
1481     Key *tkey;
1482     krb5_enctype cetype;
1483     krb5_principal cp = NULL;
1484     krb5_principal sp = NULL;
1485     AuthorizationData *auth_data = NULL;
1486 
1487     *csec  = NULL;
1488     *cusec = NULL;
1489 
1490     memset(&ap_req, 0, sizeof(ap_req));
1491     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1492     if(ret){
1493 	kdc_log(0, "Failed to decode AP-REQ: %s",
1494 		krb5_get_err_text(context, ret));
1495 	goto out2;
1496     }
1497 
1498     if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1499 	/* XXX check for ticket.sname == req.sname */
1500 	kdc_log(0, "PA-DATA is not a ticket-granting ticket");
1501 	ret = KRB5KDC_ERR_POLICY; /* ? */
1502 	goto out2;
1503     }
1504 
1505     principalname2krb5_principal(&princ,
1506 				 ap_req.ticket.sname,
1507 				 ap_req.ticket.realm);
1508 
1509     ret = db_fetch(princ, &krbtgt);
1510 
1511     if(ret) {
1512 	char *p;
1513 	krb5_unparse_name(context, princ, &p);
1514 	krb5_free_principal(context, princ);
1515 	kdc_log(0, "Ticket-granting ticket not found in database: %s: %s",
1516 		p, krb5_get_err_text(context, ret));
1517 	free(p);
1518 	ret = KRB5KRB_AP_ERR_NOT_US;
1519 	goto out2;
1520     }
1521 
1522     if(ap_req.ticket.enc_part.kvno &&
1523        *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1524 	char *p;
1525 
1526 	krb5_unparse_name (context, princ, &p);
1527 	krb5_free_principal(context, princ);
1528 	kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)",
1529 		*ap_req.ticket.enc_part.kvno,
1530 		krbtgt->kvno,
1531 		p);
1532 	free (p);
1533 	ret = KRB5KRB_AP_ERR_BADKEYVER;
1534 	goto out2;
1535     }
1536 
1537     ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
1538     if(ret){
1539 	char *str;
1540 	krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1541 	kdc_log(0, "No server key found for %s", str);
1542 	free(str);
1543 	ret = KRB5KRB_AP_ERR_BADKEYVER;
1544 	goto out2;
1545     }
1546 
1547     if (b->kdc_options.validate)
1548 	verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1549     else
1550 	verify_ap_req_flags = 0;
1551 
1552     ret = krb5_verify_ap_req2(context,
1553 			      &ac,
1554 			      &ap_req,
1555 			      princ,
1556 			      &tkey->key,
1557 			      verify_ap_req_flags,
1558 			      &ap_req_options,
1559 			      &ticket,
1560 			      KRB5_KU_TGS_REQ_AUTH);
1561 
1562     krb5_free_principal(context, princ);
1563     if(ret) {
1564 	kdc_log(0, "Failed to verify AP-REQ: %s",
1565 		krb5_get_err_text(context, ret));
1566 	goto out2;
1567     }
1568 
1569     {
1570 	krb5_authenticator auth;
1571 
1572 	ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1573 	if (ret == 0) {
1574 	    *csec   = malloc(sizeof(**csec));
1575 	    if (*csec == NULL) {
1576 		krb5_free_authenticator(context, &auth);
1577 		kdc_log(0, "malloc failed");
1578 		goto out2;
1579 	    }
1580 	    **csec  = auth->ctime;
1581 	    *cusec  = malloc(sizeof(**cusec));
1582 	    if (*cusec == NULL) {
1583 		krb5_free_authenticator(context, &auth);
1584 		kdc_log(0, "malloc failed");
1585 		goto out2;
1586 	    }
1587 	    **csec  = auth->cusec;
1588 	    krb5_free_authenticator(context, &auth);
1589 	}
1590     }
1591 
1592     cetype = ap_req.authenticator.etype;
1593 
1594     tgt = &ticket->ticket;
1595 
1596     ret = tgs_check_authenticator(ac, b, &e_text, &tgt->key);
1597 
1598     if (b->enc_authorization_data) {
1599 	krb5_keyblock *subkey;
1600 	krb5_data ad;
1601 	ret = krb5_auth_con_getremotesubkey(context,
1602 					    ac,
1603 					    &subkey);
1604 	if(ret){
1605 	    krb5_auth_con_free(context, ac);
1606 	    kdc_log(0, "Failed to get remote subkey: %s",
1607 		    krb5_get_err_text(context, ret));
1608 	    goto out2;
1609 	}
1610 	if(subkey == NULL){
1611 	    ret = krb5_auth_con_getkey(context, ac, &subkey);
1612 	    if(ret) {
1613 		krb5_auth_con_free(context, ac);
1614 		kdc_log(0, "Failed to get session key: %s",
1615 			krb5_get_err_text(context, ret));
1616 		goto out2;
1617 	    }
1618 	}
1619 	if(subkey == NULL){
1620 	    krb5_auth_con_free(context, ac);
1621 	    kdc_log(0, "Failed to get key for enc-authorization-data");
1622 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1623 	    goto out2;
1624 	}
1625 	ret = krb5_crypto_init(context, subkey, 0, &crypto);
1626 	if (ret) {
1627 	    krb5_auth_con_free(context, ac);
1628 	    kdc_log(0, "krb5_crypto_init failed: %s",
1629 		    krb5_get_err_text(context, ret));
1630 	    goto out2;
1631 	}
1632 	ret = krb5_decrypt_EncryptedData (context,
1633 					  crypto,
1634 					  KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
1635 					  b->enc_authorization_data,
1636 					  &ad);
1637 	krb5_crypto_destroy(context, crypto);
1638 	if(ret){
1639 	    krb5_auth_con_free(context, ac);
1640 	    kdc_log(0, "Failed to decrypt enc-authorization-data");
1641 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1642 	    goto out2;
1643 	}
1644 	krb5_free_keyblock(context, subkey);
1645 	ALLOC(auth_data);
1646 	ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
1647 	if(ret){
1648 	    krb5_auth_con_free(context, ac);
1649 	    free(auth_data);
1650 	    auth_data = NULL;
1651 	    kdc_log(0, "Failed to decode authorization data");
1652 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1653 	    goto out2;
1654 	}
1655     }
1656 
1657     krb5_auth_con_free(context, ac);
1658 
1659     if(ret){
1660 	kdc_log(0, "Failed to verify authenticator: %s",
1661 		krb5_get_err_text(context, ret));
1662 	goto out2;
1663     }
1664 
1665     {
1666 	PrincipalName *s;
1667 	Realm r;
1668 	char *spn = NULL, *cpn = NULL;
1669 	hdb_entry *server = NULL, *client = NULL;
1670 	int loop = 0;
1671 	EncTicketPart adtkt;
1672 	char opt_str[128];
1673 
1674 	s = b->sname;
1675 	r = b->realm;
1676 	if(b->kdc_options.enc_tkt_in_skey){
1677 	    Ticket *t;
1678 	    hdb_entry *uu;
1679 	    krb5_principal p;
1680 	    Key *tkey;
1681 
1682 	    if(b->additional_tickets == NULL ||
1683 	       b->additional_tickets->len == 0){
1684 		ret = KRB5KDC_ERR_BADOPTION; /* ? */
1685 		kdc_log(0, "No second ticket present in request");
1686 		goto out;
1687 	    }
1688 	    t = &b->additional_tickets->val[0];
1689 	    if(!get_krbtgt_realm(&t->sname)){
1690 		kdc_log(0, "Additional ticket is not a ticket-granting ticket");
1691 		ret = KRB5KDC_ERR_POLICY;
1692 		goto out2;
1693 	    }
1694 	    principalname2krb5_principal(&p, t->sname, t->realm);
1695 	    ret = db_fetch(p, &uu);
1696 	    krb5_free_principal(context, p);
1697 	    if(ret){
1698 		if (ret == HDB_ERR_NOENTRY)
1699 		    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1700 		goto out;
1701 	    }
1702 	    ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey);
1703 	    if(ret){
1704 		ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1705 		goto out;
1706 	    }
1707 	    ret = krb5_decrypt_ticket(context, t, &tkey->key, &adtkt, 0);
1708 
1709 	    if(ret)
1710 		goto out;
1711 	    s = &adtkt.cname;
1712 	    r = adtkt.crealm;
1713 	}
1714 
1715 	principalname2krb5_principal(&sp, *s, r);
1716 	krb5_unparse_name(context, sp, &spn);
1717 	principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
1718 	krb5_unparse_name(context, cp, &cpn);
1719 	unparse_flags (KDCOptions2int(b->kdc_options), KDCOptions_units,
1720 		       opt_str, sizeof(opt_str));
1721 	if(*opt_str)
1722 	    kdc_log(0, "TGS-REQ %s from %s for %s [%s]",
1723 		    cpn, from, spn, opt_str);
1724 	else
1725 	    kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn);
1726     server_lookup:
1727 	ret = db_fetch(sp, &server);
1728 
1729 	if(ret){
1730 	    Realm req_rlm, new_rlm;
1731 	    krb5_realm *realms;
1732 
1733 	    if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1734 		if(loop++ < 2) {
1735 		    new_rlm = find_rpath(tgt->crealm, req_rlm);
1736 		    if(new_rlm) {
1737 			kdc_log(5, "krbtgt for realm %s not found, trying %s",
1738 				req_rlm, new_rlm);
1739 			krb5_free_principal(context, sp);
1740 			free(spn);
1741 			krb5_make_principal(context, &sp, r,
1742 					    KRB5_TGS_NAME, new_rlm, NULL);
1743 			krb5_unparse_name(context, sp, &spn);
1744 			goto server_lookup;
1745 		    }
1746 		}
1747 	    } else if(need_referral(sp, &realms)) {
1748 		if (strcmp(realms[0], sp->realm) != 0) {
1749 		    kdc_log(5, "returning a referral to realm %s for "
1750 			    "server %s that was not found",
1751 			    realms[0], spn);
1752 		    krb5_free_principal(context, sp);
1753 		    free(spn);
1754 		    krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1755 					realms[0], NULL);
1756 		    krb5_unparse_name(context, sp, &spn);
1757 		    krb5_free_host_realm(context, realms);
1758 		    goto server_lookup;
1759 		}
1760 		krb5_free_host_realm(context, realms);
1761 	    }
1762 	    kdc_log(0, "Server not found in database: %s: %s", spn,
1763 		    krb5_get_err_text(context, ret));
1764 	    if (ret == HDB_ERR_NOENTRY)
1765 		ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1766 	    goto out;
1767 	}
1768 
1769 	ret = db_fetch(cp, &client);
1770 	if(ret)
1771 	    kdc_log(1, "Client not found in database: %s: %s",
1772 		    cpn, krb5_get_err_text(context, ret));
1773 #if 0
1774 	/* XXX check client only if same realm as krbtgt-instance */
1775 	if(ret){
1776 	    kdc_log(0, "Client not found in database: %s: %s",
1777 		    cpn, krb5_get_err_text(context, ret));
1778 	    if (ret == HDB_ERR_NOENTRY)
1779 		ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1780 	    goto out;
1781 	}
1782 #endif
1783 
1784 	if(strcmp(krb5_principal_get_realm(context, sp),
1785 		  krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
1786 	    char *tpn;
1787 	    ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
1788 	    kdc_log(0, "Request with wrong krbtgt: %s", (ret == 0) ? tpn : "<unknown>");
1789 	    if(ret == 0)
1790 		free(tpn);
1791 	    ret = KRB5KRB_AP_ERR_NOT_US;
1792 	    goto out;
1793 
1794 	}
1795 
1796 	ret = check_flags(client, cpn, server, spn, FALSE);
1797 	if(ret)
1798 	    goto out;
1799 
1800 	if((b->kdc_options.validate || b->kdc_options.renew) &&
1801 	   !krb5_principal_compare(context,
1802 				   krbtgt->principal,
1803 				   server->principal)){
1804 	    kdc_log(0, "Inconsistent request.");
1805 	    ret = KRB5KDC_ERR_SERVER_NOMATCH;
1806 	    goto out;
1807 	}
1808 
1809 	/* check for valid set of addresses */
1810 	if(!check_addresses(tgt->caddr, from_addr)) {
1811 	    ret = KRB5KRB_AP_ERR_BADADDR;
1812 	    kdc_log(0, "Request from wrong address");
1813 	    goto out;
1814 	}
1815 
1816 	ret = tgs_make_reply(b,
1817 			     tgt,
1818 			     b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
1819 			     auth_data,
1820 			     server,
1821 			     client,
1822 			     cp,
1823 			     krbtgt,
1824 			     cetype,
1825 			     &e_text,
1826 			     reply);
1827 
1828     out:
1829 	free(spn);
1830 	free(cpn);
1831 
1832 	if(server)
1833 	    free_ent(server);
1834 	if(client)
1835 	    free_ent(client);
1836     }
1837 out2:
1838     if(ret) {
1839 	krb5_mk_error(context,
1840 		      ret,
1841 		      e_text,
1842 		      NULL,
1843 		      cp,
1844 		      sp,
1845 		      NULL,
1846 		      NULL,
1847 		      reply);
1848 	free(*csec);
1849 	free(*cusec);
1850 	*csec  = NULL;
1851 	*cusec = NULL;
1852     }
1853     krb5_free_principal(context, cp);
1854     krb5_free_principal(context, sp);
1855     if (ticket) {
1856 	krb5_free_ticket(context, ticket);
1857 	free(ticket);
1858     }
1859     free_AP_REQ(&ap_req);
1860     if(auth_data){
1861 	free_AuthorizationData(auth_data);
1862 	free(auth_data);
1863     }
1864 
1865     if(krbtgt)
1866 	free_ent(krbtgt);
1867 
1868     return ret;
1869 }
1870 
1871 
1872 krb5_error_code
1873 tgs_rep(KDC_REQ *req,
1874 	krb5_data *data,
1875 	const char *from,
1876 	struct sockaddr *from_addr)
1877 {
1878     krb5_error_code ret;
1879     int i = 0;
1880     PA_DATA *tgs_req = NULL;
1881     time_t *csec = NULL;
1882     int *cusec = NULL;
1883 
1884     if(req->padata == NULL){
1885 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
1886 	kdc_log(0, "TGS-REQ from %s without PA-DATA", from);
1887 	goto out;
1888     }
1889 
1890     tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
1891 
1892     if(tgs_req == NULL){
1893 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
1894 
1895 	kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from);
1896 	goto out;
1897     }
1898     ret = tgs_rep2(&req->req_body, tgs_req, data, from, from_addr,
1899 		   &csec, &cusec);
1900 out:
1901     if(ret && data->data == NULL){
1902 	krb5_mk_error(context,
1903 		      ret,
1904 		      NULL,
1905 		      NULL,
1906 		      NULL,
1907 		      NULL,
1908 		      csec,
1909 		      cusec,
1910 		      data);
1911     }
1912     free(csec);
1913     free(cusec);
1914     return 0;
1915 }
1916