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