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