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