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