xref: /freebsd/crypto/heimdal/kdc/kerberos5.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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.109 2000/01/18 03:13:00 assar 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
575 	      || client->flags.require_preauth
576 	      || server->flags.require_preauth) {
577 	METHOD_DATA method_data;
578 	PA_DATA *pa;
579 	unsigned char *buf;
580 	size_t len;
581 	krb5_data foo_data;
582 
583     use_pa:
584 	method_data.len = 0;
585 	method_data.val = NULL;
586 
587 	ret = realloc_method_data(&method_data);
588 	pa = &method_data.val[method_data.len-1];
589 	pa->padata_type		= pa_enc_timestamp;
590 	pa->padata_value.length	= 0;
591 	pa->padata_value.data	= NULL;
592 
593 	ret = get_pa_etype_info(&method_data, client); /* XXX check ret */
594 
595 	len = length_METHOD_DATA(&method_data);
596 	buf = malloc(len);
597 	encode_METHOD_DATA(buf + len - 1,
598 			   len,
599 			   &method_data,
600 			   &len);
601 	free_METHOD_DATA(&method_data);
602 	foo_data.length = len;
603 	foo_data.data   = buf;
604 
605 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
606 	krb5_mk_error(context,
607 		      ret,
608 		      "Need to use PA-ENC-TIMESTAMP",
609 		      &foo_data,
610 		      client_princ,
611 		      server_princ,
612 		      0,
613 		      reply);
614 	free(buf);
615 	kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name);
616 	ret = 0;
617 	goto out2;
618     }
619 
620     ret = find_keys(client, server, &ckey, &cetype, &skey, &setype,
621 		    b->etype.val, b->etype.len);
622     if(ret) {
623 	kdc_log(0, "Server/client has no support for etypes");
624 	goto out;
625     }
626 
627     {
628 	char *cet;
629 	char *set;
630 	krb5_enctype_to_string(context, cetype, &cet);
631 	krb5_enctype_to_string(context, setype, &set);
632 	kdc_log(5, "Using %s/%s", cet, set);
633 	free(cet);
634 	free(set);
635     }
636 
637 
638     memset(&rep, 0, sizeof(rep));
639     rep.pvno = 5;
640     rep.msg_type = krb_as_rep;
641     copy_Realm(&b->realm, &rep.crealm);
642     copy_PrincipalName(b->cname, &rep.cname);
643     rep.ticket.tkt_vno = 5;
644     copy_Realm(&b->realm, &rep.ticket.realm);
645     copy_PrincipalName(b->sname, &rep.ticket.sname);
646 
647     {
648 	char str[128];
649 	unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str));
650 	if(*str)
651 	    kdc_log(2, "Requested flags: %s", str);
652     }
653 
654     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey ||
655        f.request_anonymous){
656 	ret = KRB5KDC_ERR_BADOPTION;
657 	kdc_log(0, "Bad KDC options -- %s", client_name);
658 	goto out;
659     }
660 
661     et.flags.initial = 1;
662     if(client->flags.forwardable && server->flags.forwardable)
663 	et.flags.forwardable = f.forwardable;
664     else if (f.forwardable) {
665 	ret = KRB5KDC_ERR_POLICY;
666 	kdc_log(0, "Ticket may not be forwardable -- %s", client_name);
667 	goto out;
668     }
669     if(client->flags.proxiable && server->flags.proxiable)
670 	et.flags.proxiable = f.proxiable;
671     else if (f.proxiable) {
672 	ret = KRB5KDC_ERR_POLICY;
673 	kdc_log(0, "Ticket may not be proxiable -- %s", client_name);
674 	goto out;
675     }
676     if(client->flags.postdate && server->flags.postdate)
677 	et.flags.may_postdate = f.allow_postdate;
678     else if (f.allow_postdate){
679 	ret = KRB5KDC_ERR_POLICY;
680 	kdc_log(0, "Ticket may not be postdatable -- %s", client_name);
681 	goto out;
682     }
683 
684     /* check for valid set of addresses */
685     if(!check_addresses(b->addresses, from_addr)) {
686 	ret = KRB5KRB_AP_ERR_BADADDR;
687 	kdc_log(0, "Bad address list requested -- %s", client_name);
688 	goto out;
689     }
690 
691     krb5_generate_random_keyblock(context, setype, &et.key);
692     copy_PrincipalName(b->cname, &et.cname);
693     copy_Realm(&b->realm, &et.crealm);
694 
695     {
696 	time_t start;
697 	time_t t;
698 
699 	start = et.authtime = kdc_time;
700 
701 	if(f.postdated && req->req_body.from){
702 	    ALLOC(et.starttime);
703 	    start = *et.starttime = *req->req_body.from;
704 	    et.flags.invalid = 1;
705 	    et.flags.postdated = 1; /* XXX ??? */
706 	}
707 	fix_time(&b->till);
708 	t = *b->till;
709 	if(client->max_life)
710 	    t = min(t, start + *client->max_life);
711 	if(server->max_life)
712 	    t = min(t, start + *server->max_life);
713 #if 0
714 	t = min(t, start + realm->max_life);
715 #endif
716 	et.endtime = t;
717 	if(f.renewable_ok && et.endtime < *b->till){
718 	    f.renewable = 1;
719 	    if(b->rtime == NULL){
720 		ALLOC(b->rtime);
721 		*b->rtime = 0;
722 	    }
723 	    if(*b->rtime < *b->till)
724 		*b->rtime = *b->till;
725 	}
726 	if(f.renewable && b->rtime){
727 	    t = *b->rtime;
728 	    if(t == 0)
729 		t = MAX_TIME;
730 	    if(client->max_renew)
731 		t = min(t, start + *client->max_renew);
732 	    if(server->max_renew)
733 		t = min(t, start + *server->max_renew);
734 #if 0
735 	    t = min(t, start + realm->max_renew);
736 #endif
737 	    ALLOC(et.renew_till);
738 	    *et.renew_till = t;
739 	    et.flags.renewable = 1;
740 	}
741     }
742 
743     if(b->addresses){
744 	ALLOC(et.caddr);
745 	copy_HostAddresses(b->addresses, et.caddr);
746     }
747 
748     {
749 	krb5_data empty_string;
750 
751 	krb5_data_zero(&empty_string);
752 	et.transited.tr_type = DOMAIN_X500_COMPRESS;
753 	et.transited.contents = empty_string;
754     }
755 
756     copy_EncryptionKey(&et.key, &ek.key);
757 
758     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
759      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
760      * incapable of correctly decoding SEQUENCE OF's of zero length.
761      *
762      * To fix this, always send at least one no-op last_req
763      *
764      * If there's a pw_end or valid_end we will use that,
765      * otherwise just a dummy lr.
766      */
767     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
768     ek.last_req.len = 0;
769     if (client->pw_end
770 	&& (kdc_warn_pwexpire == 0
771 	    || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) {
772 	ek.last_req.val[ek.last_req.len].lr_type  = 6;
773 	ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
774 	++ek.last_req.len;
775     }
776     if (client->valid_end) {
777 	ek.last_req.val[ek.last_req.len].lr_type  = 7;
778 	ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
779 	++ek.last_req.len;
780     }
781     if (ek.last_req.len == 0) {
782 	ek.last_req.val[ek.last_req.len].lr_type  = 0;
783 	ek.last_req.val[ek.last_req.len].lr_value = 0;
784 	++ek.last_req.len;
785     }
786     ek.nonce = b->nonce;
787     if (client->valid_end || client->pw_end) {
788 	ALLOC(ek.key_expiration);
789 	if (client->valid_end) {
790 	    if (client->pw_end)
791 		*ek.key_expiration = min(*client->valid_end, *client->pw_end);
792 	    else
793 		*ek.key_expiration = *client->valid_end;
794 	} else
795 	    *ek.key_expiration = *client->pw_end;
796     } else
797 	ek.key_expiration = NULL;
798     ek.flags = et.flags;
799     ek.authtime = et.authtime;
800     if (et.starttime) {
801 	ALLOC(ek.starttime);
802 	*ek.starttime = *et.starttime;
803     }
804     ek.endtime = et.endtime;
805     if (et.renew_till) {
806 	ALLOC(ek.renew_till);
807 	*ek.renew_till = *et.renew_till;
808     }
809     copy_Realm(&rep.ticket.realm, &ek.srealm);
810     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
811     if(et.caddr){
812 	ALLOC(ek.caddr);
813 	copy_HostAddresses(et.caddr, ek.caddr);
814     }
815 
816     set_salt_padata (&rep.padata, ckey->salt);
817     ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key,
818 		       client->kvno, &ckey->key, reply);
819     free_EncTicketPart(&et);
820     free_EncKDCRepPart(&ek);
821     free_AS_REP(&rep);
822 out:
823     if(ret){
824 	krb5_mk_error(context,
825 		      ret,
826 		      e_text,
827 		      NULL,
828 		      client_princ,
829 		      server_princ,
830 		      0,
831 		      reply);
832 	ret = 0;
833     }
834 out2:
835     krb5_free_principal(context, client_princ);
836     free(client_name);
837     krb5_free_principal(context, server_princ);
838     free(server_name);
839     if(client){
840 	hdb_free_entry(context, client);
841 	free(client);
842     }
843     if(server){
844 	hdb_free_entry(context, server);
845 	free(server);
846     }
847 
848     return ret;
849 }
850 
851 
852 static krb5_error_code
853 check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
854 {
855     KDCOptions f = b->kdc_options;
856 
857     if(f.validate){
858 	if(!tgt->flags.invalid || tgt->starttime == NULL){
859 	    kdc_log(0, "Bad request to validate ticket");
860 	    return KRB5KDC_ERR_BADOPTION;
861 	}
862 	if(*tgt->starttime > kdc_time){
863 	    kdc_log(0, "Early request to validate ticket");
864 	    return KRB5KRB_AP_ERR_TKT_NYV;
865 	}
866 	/* XXX  tkt = tgt */
867 	et->flags.invalid = 0;
868     }else if(tgt->flags.invalid){
869 	kdc_log(0, "Ticket-granting ticket has INVALID flag set");
870 	return KRB5KRB_AP_ERR_TKT_INVALID;
871     }
872 
873     if(f.forwardable){
874 	if(!tgt->flags.forwardable){
875 	    kdc_log(0, "Bad request for forwardable ticket");
876 	    return KRB5KDC_ERR_BADOPTION;
877 	}
878 	et->flags.forwardable = 1;
879     }
880     if(f.forwarded){
881 	if(!tgt->flags.forwardable){
882 	    kdc_log(0, "Request to forward non-forwardable ticket");
883 	    return KRB5KDC_ERR_BADOPTION;
884 	}
885 	et->flags.forwarded = 1;
886 	et->caddr = b->addresses;
887     }
888     if(tgt->flags.forwarded)
889 	et->flags.forwarded = 1;
890 
891     if(f.proxiable){
892 	if(!tgt->flags.proxiable){
893 	    kdc_log(0, "Bad request for proxiable ticket");
894 	    return KRB5KDC_ERR_BADOPTION;
895 	}
896 	et->flags.proxiable = 1;
897     }
898     if(f.proxy){
899 	if(!tgt->flags.proxiable){
900 	    kdc_log(0, "Request to proxy non-proxiable ticket");
901 	    return KRB5KDC_ERR_BADOPTION;
902 	}
903 	et->flags.proxy = 1;
904 	et->caddr = b->addresses;
905     }
906     if(tgt->flags.proxy)
907 	et->flags.proxy = 1;
908 
909     if(f.allow_postdate){
910 	if(!tgt->flags.may_postdate){
911 	    kdc_log(0, "Bad request for post-datable ticket");
912 	    return KRB5KDC_ERR_BADOPTION;
913 	}
914 	et->flags.may_postdate = 1;
915     }
916     if(f.postdated){
917 	if(!tgt->flags.may_postdate){
918 	    kdc_log(0, "Bad request for postdated ticket");
919 	    return KRB5KDC_ERR_BADOPTION;
920 	}
921 	if(b->from)
922 	    *et->starttime = *b->from;
923 	et->flags.postdated = 1;
924 	et->flags.invalid = 1;
925     }else if(b->from && *b->from > kdc_time + context->max_skew){
926 	kdc_log(0, "Ticket cannot be postdated");
927 	return KRB5KDC_ERR_CANNOT_POSTDATE;
928     }
929 
930     if(f.renewable){
931 	if(!tgt->flags.renewable){
932 	    kdc_log(0, "Bad request for renewable ticket");
933 	    return KRB5KDC_ERR_BADOPTION;
934 	}
935 	et->flags.renewable = 1;
936 	ALLOC(et->renew_till);
937 	fix_time(&b->rtime);
938 	*et->renew_till = *b->rtime;
939     }
940     if(f.renew){
941 	time_t old_life;
942 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
943 	    kdc_log(0, "Request to renew non-renewable ticket");
944 	    return KRB5KDC_ERR_BADOPTION;
945 	}
946 	old_life = tgt->endtime;
947 	if(tgt->starttime)
948 	    old_life -= *tgt->starttime;
949 	else
950 	    old_life -= tgt->authtime;
951 	et->endtime = min(*b->till, *et->starttime + old_life);
952     }
953 
954     /* checks for excess flags */
955     if(f.request_anonymous){
956 	kdc_log(0, "Request for anonymous ticket");
957 	return KRB5KDC_ERR_BADOPTION;
958     }
959     return 0;
960 }
961 
962 static krb5_error_code
963 fix_transited_encoding(TransitedEncoding *tr,
964 		       const char *client_realm,
965 		       const char *server_realm,
966 		       const char *tgt_realm)
967 {
968     krb5_error_code ret = 0;
969     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){
970 	char **realms = NULL, **tmp;
971 	int num_realms = 0;
972 	int i;
973 	if(tr->tr_type && tr->contents.length != 0) {
974 	    if(tr->tr_type != DOMAIN_X500_COMPRESS){
975 		kdc_log(0, "Unknown transited type: %u",
976 			tr->tr_type);
977 		return KRB5KDC_ERR_TRTYPE_NOSUPP;
978 	    }
979 	    ret = krb5_domain_x500_decode(tr->contents,
980 					  &realms,
981 					  &num_realms,
982 					  client_realm,
983 					  server_realm);
984 	    if(ret){
985 		krb5_warn(context, ret, "Decoding transited encoding");
986 		return ret;
987 	    }
988 	}
989 	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
990 	if(tmp == NULL){
991 	    ret = ENOMEM;
992 	    goto free_realms;
993 	}
994 	realms = tmp;
995 	realms[num_realms] = strdup(tgt_realm);
996 	if(realms[num_realms] == NULL){
997 	    ret = ENOMEM;
998 	    goto free_realms;
999 	}
1000 	num_realms++;
1001 	free_TransitedEncoding(tr);
1002 	tr->tr_type = DOMAIN_X500_COMPRESS;
1003 	ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents);
1004 	if(ret)
1005 	    krb5_warn(context, ret, "Encoding transited encoding");
1006     free_realms:
1007 	for(i = 0; i < num_realms; i++)
1008 	    free(realms[i]);
1009 	free(realms);
1010     }
1011     return ret;
1012 }
1013 
1014 
1015 static krb5_error_code
1016 tgs_make_reply(KDC_REQ_BODY *b,
1017 	       EncTicketPart *tgt,
1018 	       EncTicketPart *adtkt,
1019 	       AuthorizationData *auth_data,
1020 	       hdb_entry *server,
1021 	       hdb_entry *client,
1022 	       krb5_principal client_principal,
1023 	       hdb_entry *krbtgt,
1024 	       krb5_enctype cetype,
1025 	       krb5_data *reply)
1026 {
1027     KDC_REP rep;
1028     EncKDCRepPart ek;
1029     EncTicketPart et;
1030     KDCOptions f = b->kdc_options;
1031     krb5_error_code ret;
1032     krb5_enctype etype;
1033     Key *skey;
1034     EncryptionKey *ekey;
1035 
1036     if(adtkt) {
1037 	int i;
1038 	krb5_keytype kt;
1039 	ekey = &adtkt->key;
1040 	for(i = 0; i < b->etype.len; i++){
1041 	    ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1042 	    if(ret)
1043 		continue;
1044 	    if(adtkt->key.keytype == kt)
1045 		break;
1046 	}
1047 	if(i == b->etype.len)
1048 	    return KRB5KDC_ERR_ETYPE_NOSUPP;
1049 	etype = b->etype.val[i];
1050     }else{
1051 	ret = find_keys(NULL, server, NULL, NULL, &skey, &etype,
1052 			b->etype.val, b->etype.len);
1053 	if(ret) {
1054 	    kdc_log(0, "Server has no support for etypes");
1055 	    return ret;
1056 	}
1057 	ekey = &skey->key;
1058     }
1059 
1060     memset(&rep, 0, sizeof(rep));
1061     memset(&et, 0, sizeof(et));
1062     memset(&ek, 0, sizeof(ek));
1063 
1064     rep.pvno = 5;
1065     rep.msg_type = krb_tgs_rep;
1066 
1067     et.authtime = tgt->authtime;
1068     fix_time(&b->till);
1069     et.endtime = min(tgt->endtime, *b->till);
1070     ALLOC(et.starttime);
1071     *et.starttime = kdc_time;
1072 
1073     ret = check_tgs_flags(b, tgt, &et);
1074     if(ret)
1075 	return ret;
1076 
1077     copy_TransitedEncoding(&tgt->transited, &et.transited);
1078     ret = fix_transited_encoding(&et.transited,
1079 				 *krb5_princ_realm(context, client_principal),
1080 				 *krb5_princ_realm(context, server->principal),
1081 				 *krb5_princ_realm(context, krbtgt->principal));
1082     if(ret){
1083 	free_TransitedEncoding(&et.transited);
1084 	return ret;
1085     }
1086 
1087 
1088     copy_Realm(krb5_princ_realm(context, server->principal),
1089 	       &rep.ticket.realm);
1090     krb5_principal2principalname(&rep.ticket.sname, server->principal);
1091     copy_Realm(&tgt->crealm, &rep.crealm);
1092     copy_PrincipalName(&tgt->cname, &rep.cname);
1093     rep.ticket.tkt_vno = 5;
1094 
1095     ek.caddr = et.caddr;
1096     if(et.caddr == NULL)
1097 	et.caddr = tgt->caddr;
1098 
1099     {
1100 	time_t life;
1101 	life = et.endtime - *et.starttime;
1102 	if(client && client->max_life)
1103 	    life = min(life, *client->max_life);
1104 	if(server->max_life)
1105 	    life = min(life, *server->max_life);
1106 	et.endtime = *et.starttime + life;
1107     }
1108     if(f.renewable_ok && tgt->flags.renewable &&
1109        et.renew_till == NULL && et.endtime < *b->till){
1110 	et.flags.renewable = 1;
1111 	ALLOC(et.renew_till);
1112 	*et.renew_till = *b->till;
1113     }
1114     if(et.renew_till){
1115 	time_t renew;
1116 	renew = *et.renew_till - et.authtime;
1117 	if(client && client->max_renew)
1118 	    renew = min(renew, *client->max_renew);
1119 	if(server->max_renew)
1120 	    renew = min(renew, *server->max_renew);
1121 	*et.renew_till = et.authtime + renew;
1122     }
1123 
1124     if(et.renew_till){
1125 	*et.renew_till = min(*et.renew_till, *tgt->renew_till);
1126 	*et.starttime = min(*et.starttime, *et.renew_till);
1127 	et.endtime = min(et.endtime, *et.renew_till);
1128     }
1129 
1130     *et.starttime = min(*et.starttime, et.endtime);
1131 
1132     if(*et.starttime == et.endtime){
1133 	ret = KRB5KDC_ERR_NEVER_VALID;
1134 	goto out;
1135     }
1136     if(et.renew_till && et.endtime == *et.renew_till){
1137 	free(et.renew_till);
1138 	et.renew_till = NULL;
1139 	et.flags.renewable = 0;
1140     }
1141 
1142     et.flags.pre_authent = tgt->flags.pre_authent;
1143     et.flags.hw_authent = tgt->flags.hw_authent;
1144 
1145     /* XXX Check enc-authorization-data */
1146     et.authorization_data = auth_data;
1147 
1148     krb5_generate_random_keyblock(context, etype, &et.key);
1149     et.crealm = tgt->crealm;
1150     et.cname = tgt->cname;
1151 
1152     ek.key = et.key;
1153     /* MIT must have at least one last_req */
1154     ek.last_req.len = 1;
1155     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1156     ek.nonce = b->nonce;
1157     ek.flags = et.flags;
1158     ek.authtime = et.authtime;
1159     ek.starttime = et.starttime;
1160     ek.endtime = et.endtime;
1161     ek.renew_till = et.renew_till;
1162     ek.srealm = rep.ticket.realm;
1163     ek.sname = rep.ticket.sname;
1164 
1165     /* It is somewhat unclear where the etype in the following
1166        encryption should come from. What we have is a session
1167        key in the passed tgt, and a list of preferred etypes
1168        *for the new ticket*. Should we pick the best possible
1169        etype, given the keytype in the tgt, or should we look
1170        at the etype list here as well?  What if the tgt
1171        session key is DES3 and we want a ticket with a (say)
1172        CAST session key. Should the DES3 etype be added to the
1173        etype list, even if we don't want a session key with
1174        DES3? */
1175     ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1176 		       0, &tgt->key, reply);
1177 out:
1178     free_TGS_REP(&rep);
1179     free_TransitedEncoding(&et.transited);
1180     if(et.starttime)
1181 	free(et.starttime);
1182     if(et.renew_till)
1183 	free(et.renew_till);
1184     free_LastReq(&ek.last_req);
1185     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1186     free_EncryptionKey(&et.key);
1187     return ret;
1188 }
1189 
1190 static krb5_error_code
1191 tgs_check_authenticator(krb5_auth_context ac,
1192 			KDC_REQ_BODY *b,
1193 			krb5_keyblock *key)
1194 {
1195     krb5_authenticator auth;
1196     size_t len;
1197     unsigned char buf[8192];
1198     krb5_error_code ret;
1199     krb5_crypto crypto;
1200 
1201     krb5_auth_getauthenticator(context, ac, &auth);
1202     if(auth->cksum == NULL){
1203 	kdc_log(0, "No authenticator in request");
1204 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1205 	goto out;
1206     }
1207     /*
1208      * according to RFC1510 it doesn't need to be keyed,
1209      * but according to the latest draft it needs to.
1210      */
1211     if (
1212 #if 0
1213 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1214 	||
1215 #endif
1216  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1217 	kdc_log(0, "Bad checksum type in authenticator: %d",
1218 		auth->cksum->cksumtype);
1219 	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
1220 	goto out;
1221     }
1222 
1223     /* XXX should not re-encode this */
1224     ret = encode_KDC_REQ_BODY(buf + sizeof(buf) - 1, sizeof(buf),
1225 			      b, &len);
1226     if(ret){
1227 	kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
1228 		krb5_get_err_text(context, ret));
1229 	goto out;
1230     }
1231     krb5_crypto_init(context, key, 0, &crypto);
1232     ret = krb5_verify_checksum(context,
1233 			       crypto,
1234 			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
1235 			       buf + sizeof(buf) - len,
1236 			       len,
1237 			       auth->cksum);
1238     krb5_crypto_destroy(context, crypto);
1239     if(ret){
1240 	kdc_log(0, "Failed to verify checksum: %s",
1241 		krb5_get_err_text(context, ret));
1242     }
1243 out:
1244     free_Authenticator(auth);
1245     free(auth);
1246     return ret;
1247 }
1248 
1249 static Realm
1250 is_krbtgt(PrincipalName *p)
1251 {
1252     if(p->name_string.len == 2 && strcmp(p->name_string.val[0], "krbtgt") == 0)
1253 	return p->name_string.val[1];
1254     else
1255 	return NULL;
1256 }
1257 
1258 static Realm
1259 find_rpath(Realm r)
1260 {
1261     const char *new_realm = krb5_config_get_string(context,
1262 						   NULL,
1263 						   "libdefaults",
1264 						   "capath",
1265 						   r,
1266 						   NULL);
1267     return (Realm)new_realm;
1268 }
1269 
1270 
1271 static krb5_error_code
1272 tgs_rep2(KDC_REQ_BODY *b,
1273 	 PA_DATA *tgs_req,
1274 	 krb5_data *reply,
1275 	 const char *from,
1276 	 struct sockaddr *from_addr)
1277 {
1278     krb5_ap_req ap_req;
1279     krb5_error_code ret;
1280     krb5_principal princ;
1281     krb5_auth_context ac = NULL;
1282     krb5_ticket *ticket = NULL;
1283     krb5_flags ap_req_options;
1284     krb5_flags verify_ap_req_flags;
1285     const char *e_text = NULL;
1286     krb5_crypto crypto;
1287 
1288     hdb_entry *krbtgt = NULL;
1289     EncTicketPart *tgt;
1290     Key *tkey;
1291     krb5_enctype cetype;
1292     krb5_principal cp = NULL;
1293     krb5_principal sp = NULL;
1294     AuthorizationData *auth_data = NULL;
1295 
1296     memset(&ap_req, 0, sizeof(ap_req));
1297     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1298     if(ret){
1299 	kdc_log(0, "Failed to decode AP-REQ: %s",
1300 		krb5_get_err_text(context, ret));
1301 	goto out2;
1302     }
1303 
1304     if(!is_krbtgt(&ap_req.ticket.sname)){
1305 	/* XXX check for ticket.sname == req.sname */
1306 	kdc_log(0, "PA-DATA is not a ticket-granting ticket");
1307 	ret = KRB5KDC_ERR_POLICY; /* ? */
1308 	goto out2;
1309     }
1310 
1311     principalname2krb5_principal(&princ,
1312 				 ap_req.ticket.sname,
1313 				 ap_req.ticket.realm);
1314 
1315     krbtgt = db_fetch(princ);
1316 
1317     if(krbtgt == NULL) {
1318 	char *p;
1319 	krb5_unparse_name(context, princ, &p);
1320 	kdc_log(0, "Ticket-granting ticket not found in database: %s", p);
1321 	free(p);
1322 	ret = KRB5KRB_AP_ERR_NOT_US;
1323 	goto out2;
1324     }
1325 
1326     if(ap_req.ticket.enc_part.kvno &&
1327        *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1328 	char *p;
1329 
1330 	krb5_unparse_name (context, princ, &p);
1331 	kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)",
1332 		*ap_req.ticket.enc_part.kvno,
1333 		krbtgt->kvno,
1334 		p);
1335 	free (p);
1336 	ret = KRB5KRB_AP_ERR_BADKEYVER;
1337 	goto out2;
1338     }
1339 
1340     ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
1341     if(ret){
1342 	char *str;
1343 	krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1344 	kdc_log(0, "No server key found for %s", str);
1345 	free(str);
1346 	ret = KRB5KRB_AP_ERR_BADKEYVER;
1347 	goto out2;
1348     }
1349 
1350     if (b->kdc_options.validate)
1351 	verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1352     else
1353 	verify_ap_req_flags = 0;
1354 
1355     ret = krb5_verify_ap_req(context,
1356 			     &ac,
1357 			     &ap_req,
1358 			     princ,
1359 			     &tkey->key,
1360 			     verify_ap_req_flags,
1361 			     &ap_req_options,
1362 			     &ticket);
1363 
1364     krb5_free_principal(context, princ);
1365     if(ret) {
1366 	kdc_log(0, "Failed to verify AP-REQ: %s",
1367 		krb5_get_err_text(context, ret));
1368 	goto out2;
1369     }
1370 
1371     cetype = ap_req.authenticator.etype;
1372 
1373     tgt = &ticket->ticket;
1374 
1375     ret = tgs_check_authenticator(ac, b, &tgt->key);
1376 
1377     if (b->enc_authorization_data) {
1378 	krb5_keyblock *subkey;
1379 	krb5_data ad;
1380 	ret = krb5_auth_con_getremotesubkey(context,
1381 					    ac,
1382 					    &subkey);
1383 	if(ret){
1384 	    kdc_log(0, "Failed to get remote subkey: %s",
1385 		    krb5_get_err_text(context, ret));
1386 	    goto out2;
1387 	}
1388 	if(subkey == NULL){
1389 	    ret = krb5_auth_con_getkey(context, ac, &subkey);
1390 	    if(ret) {
1391 		kdc_log(0, "Failed to get session key: %s",
1392 			krb5_get_err_text(context, ret));
1393 		goto out2;
1394 	    }
1395 	}
1396 	if(subkey == NULL){
1397 	    kdc_log(0, "Failed to get key for enc-authorization-data");
1398 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1399 	    goto out2;
1400 	}
1401 	krb5_crypto_init(context, subkey, 0, &crypto);
1402 	ret = krb5_decrypt_EncryptedData (context,
1403 					  crypto,
1404 					  KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
1405 					  b->enc_authorization_data,
1406 					  &ad);
1407 	krb5_crypto_destroy(context, crypto);
1408 	if(ret){
1409 	    kdc_log(0, "Failed to decrypt enc-authorization-data");
1410 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1411 	    goto out2;
1412 	}
1413 	krb5_free_keyblock(context, subkey);
1414 	ALLOC(auth_data);
1415 	ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
1416 	if(ret){
1417 	    free(auth_data);
1418 	    auth_data = NULL;
1419 	    kdc_log(0, "Failed to decode authorization data");
1420 	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1421 	    goto out2;
1422 	}
1423     }
1424 
1425     krb5_auth_con_free(context, ac);
1426 
1427     if(ret){
1428 	kdc_log(0, "Failed to verify authenticator: %s",
1429 		krb5_get_err_text(context, ret));
1430 	goto out2;
1431     }
1432 
1433     {
1434 	PrincipalName *s;
1435 	Realm r;
1436 	char *spn = NULL, *cpn = NULL;
1437 	hdb_entry *server = NULL, *client = NULL;
1438 	int loop = 0;
1439 	EncTicketPart adtkt;
1440 	char opt_str[128];
1441 
1442 	s = b->sname;
1443 	r = b->realm;
1444 	if(b->kdc_options.enc_tkt_in_skey){
1445 	    Ticket *t;
1446 	    hdb_entry *uu;
1447 	    krb5_principal p;
1448 	    Key *tkey;
1449 
1450 	    if(b->additional_tickets == NULL ||
1451 	       b->additional_tickets->len == 0){
1452 		ret = KRB5KDC_ERR_BADOPTION; /* ? */
1453 		kdc_log(0, "No second ticket present in request");
1454 		goto out;
1455 	    }
1456 	    t = &b->additional_tickets->val[0];
1457 	    if(!is_krbtgt(&t->sname)){
1458 		kdc_log(0, "Additional ticket is not a ticket-granting ticket");
1459 		ret = KRB5KDC_ERR_POLICY;
1460 		goto out2;
1461 	    }
1462 	    principalname2krb5_principal(&p, t->sname, t->realm);
1463 	    uu = db_fetch(p);
1464 	    krb5_free_principal(context, p);
1465 	    if(uu == NULL){
1466 		ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1467 		goto out;
1468 	    }
1469 	    ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey);
1470 	    if(ret){
1471 		ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1472 		goto out;
1473 	    }
1474 	    ret = krb5_decrypt_ticket(context, t, &tkey->key, &adtkt, 0);
1475 
1476 	    if(ret)
1477 		goto out;
1478 	    s = &adtkt.cname;
1479 	    r = adtkt.crealm;
1480 	}
1481 
1482 	principalname2krb5_principal(&sp, *s, r);
1483 	krb5_unparse_name(context, sp, &spn);
1484 	principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
1485 	krb5_unparse_name(context, cp, &cpn);
1486 	unparse_flags (KDCOptions2int(b->kdc_options), KDCOptions_units,
1487 		       opt_str, sizeof(opt_str));
1488 	if(*opt_str)
1489 	    kdc_log(0, "TGS-REQ %s from %s for %s [%s]",
1490 		    cpn, from, spn, opt_str);
1491 	else
1492 	    kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn);
1493     server_lookup:
1494 	server = db_fetch(sp);
1495 
1496 
1497 	if(server == NULL){
1498 	    Realm req_rlm, new_rlm;
1499 	    if(loop++ < 2 && (req_rlm = is_krbtgt(&sp->name))){
1500 		new_rlm = find_rpath(req_rlm);
1501 		if(new_rlm) {
1502 		    kdc_log(5, "krbtgt for realm %s not found, trying %s",
1503 			    req_rlm, new_rlm);
1504 		    krb5_free_principal(context, sp);
1505 		    free(spn);
1506 		    krb5_make_principal(context, &sp, r,
1507 					"krbtgt", new_rlm, NULL);
1508 		    krb5_unparse_name(context, sp, &spn);
1509 		    goto server_lookup;
1510 		}
1511 	    }
1512 	    kdc_log(0, "Server not found in database: %s", spn);
1513 	    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1514 	    goto out;
1515 	}
1516 
1517 	client = db_fetch(cp);
1518 	if(client == NULL)
1519 	    kdc_log(1, "Client not found in database: %s", cpn);
1520 #if 0
1521 	/* XXX check client only if same realm as krbtgt-instance */
1522 	if(client == NULL){
1523 	    kdc_log(0, "Client not found in database: %s", cpn);
1524 	    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1525 	    goto out;
1526 	}
1527 #endif
1528 
1529 	ret = check_flags(client, cpn, server, spn, FALSE);
1530 	if(ret)
1531 	    goto out;
1532 
1533 	if((b->kdc_options.validate || b->kdc_options.renew) &&
1534 	   !krb5_principal_compare(context,
1535 				   krbtgt->principal,
1536 				   server->principal)){
1537 	    kdc_log(0, "Inconsistent request.");
1538 	    ret = KRB5KDC_ERR_SERVER_NOMATCH;
1539 	    goto out;
1540 	}
1541 
1542 	/* check for valid set of addresses */
1543 	if(!check_addresses(tgt->caddr, from_addr)) {
1544 	    ret = KRB5KRB_AP_ERR_BADADDR;
1545 	    kdc_log(0, "Request from wrong address");
1546 	    goto out;
1547 	}
1548 
1549 	ret = tgs_make_reply(b,
1550 			     tgt,
1551 			     b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL,
1552 			     auth_data,
1553 			     server,
1554 			     client,
1555 			     cp,
1556 			     krbtgt,
1557 			     cetype,
1558 			     reply);
1559 
1560     out:
1561 	free(spn);
1562 	free(cpn);
1563 
1564 	if(server){
1565 	    hdb_free_entry(context, server);
1566 	    free(server);
1567 	}
1568 	if(client){
1569 	    hdb_free_entry(context, client);
1570 	    free(client);
1571 	}
1572 
1573     }
1574 out2:
1575     if(ret)
1576 	krb5_mk_error(context,
1577 		      ret,
1578 		      e_text,
1579 		      NULL,
1580 		      cp,
1581 		      sp,
1582 		      0,
1583 		      reply);
1584     krb5_free_principal(context, cp);
1585     krb5_free_principal(context, sp);
1586     if (ticket) {
1587 	krb5_free_ticket(context, ticket);
1588 	free(ticket);
1589     }
1590     free_AP_REQ(&ap_req);
1591     if(auth_data){
1592 	free_AuthorizationData(auth_data);
1593 	free(auth_data);
1594     }
1595 
1596     if(krbtgt){
1597 	hdb_free_entry(context, krbtgt);
1598 	free(krbtgt);
1599     }
1600     return ret;
1601 }
1602 
1603 
1604 krb5_error_code
1605 tgs_rep(KDC_REQ *req,
1606 	krb5_data *data,
1607 	const char *from,
1608 	struct sockaddr *from_addr)
1609 {
1610     krb5_error_code ret;
1611     int i = 0;
1612     PA_DATA *tgs_req = NULL;
1613 
1614     if(req->padata == NULL){
1615 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
1616 	kdc_log(0, "TGS-REQ from %s without PA-DATA", from);
1617 	goto out;
1618     }
1619 
1620     tgs_req = find_padata(req, &i, pa_tgs_req);
1621 
1622     if(tgs_req == NULL){
1623 	ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
1624 
1625 	kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from);
1626 	goto out;
1627     }
1628     ret = tgs_rep2(&req->req_body, tgs_req, data, from, from_addr);
1629 out:
1630     if(ret && data->data == NULL){
1631 	krb5_mk_error(context,
1632 		      ret,
1633 		      NULL,
1634 		      NULL,
1635 		      NULL,
1636 		      NULL,
1637 		      0,
1638 		      data);
1639     }
1640     return 0;
1641 }
1642