xref: /freebsd/crypto/heimdal/kdc/kerberos5.c (revision 0cadf2f4d7b9f212800448d915003abd40c2e40d)
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.143 2002/09/09 14:03:02 nectar 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 	    } else
720 		free(cet);
721 	} else
722 	    kdc_log(5, "Using e-types %d/%d", cetype, setype);
723     }
724 
725     {
726 	char str[128];
727 	unparse_flags(KDCOptions2int(f), KDCOptions_units, str, sizeof(str));
728 	if(*str)
729 	    kdc_log(2, "Requested flags: %s", str);
730     }
731 
732 
733     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
734        || (f.request_anonymous && !allow_anonymous)) {
735 	ret = KRB5KDC_ERR_BADOPTION;
736 	kdc_log(0, "Bad KDC options -- %s", client_name);
737 	goto out;
738     }
739 
740     rep.pvno = 5;
741     rep.msg_type = krb_as_rep;
742     copy_Realm(&b->realm, &rep.crealm);
743     if (f.request_anonymous)
744 	make_anonymous_principalname (&rep.cname);
745     else
746 	copy_PrincipalName(b->cname, &rep.cname);
747     rep.ticket.tkt_vno = 5;
748     copy_Realm(&b->realm, &rep.ticket.realm);
749     copy_PrincipalName(b->sname, &rep.ticket.sname);
750 
751     et.flags.initial = 1;
752     if(client->flags.forwardable && server->flags.forwardable)
753 	et.flags.forwardable = f.forwardable;
754     else if (f.forwardable) {
755 	ret = KRB5KDC_ERR_POLICY;
756 	kdc_log(0, "Ticket may not be forwardable -- %s", client_name);
757 	goto out;
758     }
759     if(client->flags.proxiable && server->flags.proxiable)
760 	et.flags.proxiable = f.proxiable;
761     else if (f.proxiable) {
762 	ret = KRB5KDC_ERR_POLICY;
763 	kdc_log(0, "Ticket may not be proxiable -- %s", client_name);
764 	goto out;
765     }
766     if(client->flags.postdate && server->flags.postdate)
767 	et.flags.may_postdate = f.allow_postdate;
768     else if (f.allow_postdate){
769 	ret = KRB5KDC_ERR_POLICY;
770 	kdc_log(0, "Ticket may not be postdatable -- %s", client_name);
771 	goto out;
772     }
773 
774     /* check for valid set of addresses */
775     if(!check_addresses(b->addresses, from_addr)) {
776 	ret = KRB5KRB_AP_ERR_BADADDR;
777 	kdc_log(0, "Bad address list requested -- %s", client_name);
778 	goto out;
779     }
780 
781     krb5_generate_random_keyblock(context, setype, &et.key);
782     copy_PrincipalName(&rep.cname, &et.cname);
783     copy_Realm(&b->realm, &et.crealm);
784 
785     {
786 	time_t start;
787 	time_t t;
788 
789 	start = et.authtime = kdc_time;
790 
791 	if(f.postdated && req->req_body.from){
792 	    ALLOC(et.starttime);
793 	    start = *et.starttime = *req->req_body.from;
794 	    et.flags.invalid = 1;
795 	    et.flags.postdated = 1; /* XXX ??? */
796 	}
797 	fix_time(&b->till);
798 	t = *b->till;
799 
800 	/* be careful not overflowing */
801 
802 	if(client->max_life)
803 	    t = start + min(t - start, *client->max_life);
804 	if(server->max_life)
805 	    t = start + min(t - start, *server->max_life);
806 #if 0
807 	t = min(t, start + realm->max_life);
808 #endif
809 	et.endtime = t;
810 	if(f.renewable_ok && et.endtime < *b->till){
811 	    f.renewable = 1;
812 	    if(b->rtime == NULL){
813 		ALLOC(b->rtime);
814 		*b->rtime = 0;
815 	    }
816 	    if(*b->rtime < *b->till)
817 		*b->rtime = *b->till;
818 	}
819 	if(f.renewable && b->rtime){
820 	    t = *b->rtime;
821 	    if(t == 0)
822 		t = MAX_TIME;
823 	    if(client->max_renew)
824 		t = start + min(t - start, *client->max_renew);
825 	    if(server->max_renew)
826 		t = start + min(t - start, *server->max_renew);
827 #if 0
828 	    t = min(t, start + realm->max_renew);
829 #endif
830 	    ALLOC(et.renew_till);
831 	    *et.renew_till = t;
832 	    et.flags.renewable = 1;
833 	}
834     }
835 
836     if (f.request_anonymous)
837 	et.flags.anonymous = 1;
838 
839     if(b->addresses){
840 	ALLOC(et.caddr);
841 	copy_HostAddresses(b->addresses, et.caddr);
842     }
843 
844     {
845 	krb5_data empty_string;
846 
847 	krb5_data_zero(&empty_string);
848 	et.transited.tr_type = DOMAIN_X500_COMPRESS;
849 	et.transited.contents = empty_string;
850     }
851 
852     copy_EncryptionKey(&et.key, &ek.key);
853 
854     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
855      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
856      * incapable of correctly decoding SEQUENCE OF's of zero length.
857      *
858      * To fix this, always send at least one no-op last_req
859      *
860      * If there's a pw_end or valid_end we will use that,
861      * otherwise just a dummy lr.
862      */
863     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
864     ek.last_req.len = 0;
865     if (client->pw_end
866 	&& (kdc_warn_pwexpire == 0
867 	    || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) {
868 	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
869 	ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
870 	++ek.last_req.len;
871     }
872     if (client->valid_end) {
873 	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
874 	ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
875 	++ek.last_req.len;
876     }
877     if (ek.last_req.len == 0) {
878 	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
879 	ek.last_req.val[ek.last_req.len].lr_value = 0;
880 	++ek.last_req.len;
881     }
882     ek.nonce = b->nonce;
883     if (client->valid_end || client->pw_end) {
884 	ALLOC(ek.key_expiration);
885 	if (client->valid_end) {
886 	    if (client->pw_end)
887 		*ek.key_expiration = min(*client->valid_end, *client->pw_end);
888 	    else
889 		*ek.key_expiration = *client->valid_end;
890 	} else
891 	    *ek.key_expiration = *client->pw_end;
892     } else
893 	ek.key_expiration = NULL;
894     ek.flags = et.flags;
895     ek.authtime = et.authtime;
896     if (et.starttime) {
897 	ALLOC(ek.starttime);
898 	*ek.starttime = *et.starttime;
899     }
900     ek.endtime = et.endtime;
901     if (et.renew_till) {
902 	ALLOC(ek.renew_till);
903 	*ek.renew_till = *et.renew_till;
904     }
905     copy_Realm(&rep.ticket.realm, &ek.srealm);
906     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
907     if(et.caddr){
908 	ALLOC(ek.caddr);
909 	copy_HostAddresses(et.caddr, ek.caddr);
910     }
911 
912     set_salt_padata (&rep.padata, ckey->salt);
913     ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key,
914 		       client->kvno, &ckey->key, &e_text, reply);
915     free_EncTicketPart(&et);
916     free_EncKDCRepPart(&ek);
917     free_AS_REP(&rep);
918   out:
919     if(ret){
920 	krb5_mk_error(context,
921 		      ret,
922 		      e_text,
923 		      NULL,
924 		      client_princ,
925 		      server_princ,
926 		      NULL,
927 		      NULL,
928 		      reply);
929 	ret = 0;
930     }
931   out2:
932     krb5_free_principal(context, client_princ);
933     free(client_name);
934     krb5_free_principal(context, server_princ);
935     free(server_name);
936     if(client)
937 	free_ent(client);
938     if(server)
939 	free_ent(server);
940     return ret;
941 }
942 
943 
944 static krb5_error_code
945 check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
946 {
947     KDCOptions f = b->kdc_options;
948 
949     if(f.validate){
950 	if(!tgt->flags.invalid || tgt->starttime == NULL){
951 	    kdc_log(0, "Bad request to validate ticket");
952 	    return KRB5KDC_ERR_BADOPTION;
953 	}
954 	if(*tgt->starttime > kdc_time){
955 	    kdc_log(0, "Early request to validate ticket");
956 	    return KRB5KRB_AP_ERR_TKT_NYV;
957 	}
958 	/* XXX  tkt = tgt */
959 	et->flags.invalid = 0;
960     }else if(tgt->flags.invalid){
961 	kdc_log(0, "Ticket-granting ticket has INVALID flag set");
962 	return KRB5KRB_AP_ERR_TKT_INVALID;
963     }
964 
965     if(f.forwardable){
966 	if(!tgt->flags.forwardable){
967 	    kdc_log(0, "Bad request for forwardable ticket");
968 	    return KRB5KDC_ERR_BADOPTION;
969 	}
970 	et->flags.forwardable = 1;
971     }
972     if(f.forwarded){
973 	if(!tgt->flags.forwardable){
974 	    kdc_log(0, "Request to forward non-forwardable ticket");
975 	    return KRB5KDC_ERR_BADOPTION;
976 	}
977 	et->flags.forwarded = 1;
978 	et->caddr = b->addresses;
979     }
980     if(tgt->flags.forwarded)
981 	et->flags.forwarded = 1;
982 
983     if(f.proxiable){
984 	if(!tgt->flags.proxiable){
985 	    kdc_log(0, "Bad request for proxiable ticket");
986 	    return KRB5KDC_ERR_BADOPTION;
987 	}
988 	et->flags.proxiable = 1;
989     }
990     if(f.proxy){
991 	if(!tgt->flags.proxiable){
992 	    kdc_log(0, "Request to proxy non-proxiable ticket");
993 	    return KRB5KDC_ERR_BADOPTION;
994 	}
995 	et->flags.proxy = 1;
996 	et->caddr = b->addresses;
997     }
998     if(tgt->flags.proxy)
999 	et->flags.proxy = 1;
1000 
1001     if(f.allow_postdate){
1002 	if(!tgt->flags.may_postdate){
1003 	    kdc_log(0, "Bad request for post-datable ticket");
1004 	    return KRB5KDC_ERR_BADOPTION;
1005 	}
1006 	et->flags.may_postdate = 1;
1007     }
1008     if(f.postdated){
1009 	if(!tgt->flags.may_postdate){
1010 	    kdc_log(0, "Bad request for postdated ticket");
1011 	    return KRB5KDC_ERR_BADOPTION;
1012 	}
1013 	if(b->from)
1014 	    *et->starttime = *b->from;
1015 	et->flags.postdated = 1;
1016 	et->flags.invalid = 1;
1017     }else if(b->from && *b->from > kdc_time + context->max_skew){
1018 	kdc_log(0, "Ticket cannot be postdated");
1019 	return KRB5KDC_ERR_CANNOT_POSTDATE;
1020     }
1021 
1022     if(f.renewable){
1023 	if(!tgt->flags.renewable){
1024 	    kdc_log(0, "Bad request for renewable ticket");
1025 	    return KRB5KDC_ERR_BADOPTION;
1026 	}
1027 	et->flags.renewable = 1;
1028 	ALLOC(et->renew_till);
1029 	fix_time(&b->rtime);
1030 	*et->renew_till = *b->rtime;
1031     }
1032     if(f.renew){
1033 	time_t old_life;
1034 	if(!tgt->flags.renewable || tgt->renew_till == NULL){
1035 	    kdc_log(0, "Request to renew non-renewable ticket");
1036 	    return KRB5KDC_ERR_BADOPTION;
1037 	}
1038 	old_life = tgt->endtime;
1039 	if(tgt->starttime)
1040 	    old_life -= *tgt->starttime;
1041 	else
1042 	    old_life -= tgt->authtime;
1043 	et->endtime = *et->starttime + old_life;
1044 	if (et->renew_till != NULL)
1045 	    et->endtime = min(*et->renew_till, et->endtime);
1046     }
1047 
1048     /* checks for excess flags */
1049     if(f.request_anonymous && !allow_anonymous){
1050 	kdc_log(0, "Request for anonymous ticket");
1051 	return KRB5KDC_ERR_BADOPTION;
1052     }
1053     return 0;
1054 }
1055 
1056 static krb5_error_code
1057 fix_transited_encoding(TransitedEncoding *tr,
1058 		       const char *client_realm,
1059 		       const char *server_realm,
1060 		       const char *tgt_realm)
1061 {
1062     krb5_error_code ret = 0;
1063     if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){
1064 	char **realms = NULL, **tmp;
1065 	int num_realms = 0;
1066 	int i;
1067 	if(tr->tr_type && tr->contents.length != 0) {
1068 	    if(tr->tr_type != DOMAIN_X500_COMPRESS){
1069 		kdc_log(0, "Unknown transited type: %u",
1070 			tr->tr_type);
1071 		return KRB5KDC_ERR_TRTYPE_NOSUPP;
1072 	    }
1073 	    ret = krb5_domain_x500_decode(context,
1074 					  tr->contents,
1075 					  &realms,
1076 					  &num_realms,
1077 					  client_realm,
1078 					  server_realm);
1079 	    if(ret){
1080 		krb5_warn(context, ret, "Decoding transited encoding");
1081 		return ret;
1082 	    }
1083 	}
1084 	if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
1085 	    ret = ERANGE;
1086 	    goto free_realms;
1087 	}
1088 	tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
1089 	if(tmp == NULL){
1090 	    ret = ENOMEM;
1091 	    goto free_realms;
1092 	}
1093 	realms = tmp;
1094 	realms[num_realms] = strdup(tgt_realm);
1095 	if(realms[num_realms] == NULL){
1096 	    ret = ENOMEM;
1097 	    goto free_realms;
1098 	}
1099 	num_realms++;
1100 	free_TransitedEncoding(tr);
1101 	tr->tr_type = DOMAIN_X500_COMPRESS;
1102 	ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents);
1103 	if(ret)
1104 	    krb5_warn(context, ret, "Encoding transited encoding");
1105     free_realms:
1106 	for(i = 0; i < num_realms; i++)
1107 	    free(realms[i]);
1108 	free(realms);
1109     }
1110     return ret;
1111 }
1112 
1113 
1114 static krb5_error_code
1115 tgs_make_reply(KDC_REQ_BODY *b,
1116 	       EncTicketPart *tgt,
1117 	       EncTicketPart *adtkt,
1118 	       AuthorizationData *auth_data,
1119 	       hdb_entry *server,
1120 	       hdb_entry *client,
1121 	       krb5_principal client_principal,
1122 	       hdb_entry *krbtgt,
1123 	       krb5_enctype cetype,
1124 	       const char **e_text,
1125 	       krb5_data *reply)
1126 {
1127     KDC_REP rep;
1128     EncKDCRepPart ek;
1129     EncTicketPart et;
1130     KDCOptions f = b->kdc_options;
1131     krb5_error_code ret;
1132     krb5_enctype etype;
1133     Key *skey;
1134     EncryptionKey *ekey;
1135 
1136     if(adtkt) {
1137 	int i;
1138 	krb5_keytype kt;
1139 	ekey = &adtkt->key;
1140 	for(i = 0; i < b->etype.len; i++){
1141 	    ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
1142 	    if(ret)
1143 		continue;
1144 	    if(adtkt->key.keytype == kt)
1145 		break;
1146 	}
1147 	if(i == b->etype.len)
1148 	    return KRB5KDC_ERR_ETYPE_NOSUPP;
1149 	etype = b->etype.val[i];
1150     }else{
1151 	ret = find_keys(NULL, server, NULL, NULL, &skey, &etype,
1152 			b->etype.val, b->etype.len);
1153 	if(ret) {
1154 	    kdc_log(0, "Server has no support for etypes");
1155 	    return ret;
1156 	}
1157 	ekey = &skey->key;
1158     }
1159 
1160     memset(&rep, 0, sizeof(rep));
1161     memset(&et, 0, sizeof(et));
1162     memset(&ek, 0, sizeof(ek));
1163 
1164     rep.pvno = 5;
1165     rep.msg_type = krb_tgs_rep;
1166 
1167     et.authtime = tgt->authtime;
1168     fix_time(&b->till);
1169     et.endtime = min(tgt->endtime, *b->till);
1170     ALLOC(et.starttime);
1171     *et.starttime = kdc_time;
1172 
1173     ret = check_tgs_flags(b, tgt, &et);
1174     if(ret)
1175 	return ret;
1176 
1177     copy_TransitedEncoding(&tgt->transited, &et.transited);
1178     ret = fix_transited_encoding(&et.transited,
1179 				 *krb5_princ_realm(context, client_principal),
1180 				 *krb5_princ_realm(context, server->principal),
1181 				 *krb5_princ_realm(context, krbtgt->principal));
1182     if(ret){
1183 	free_TransitedEncoding(&et.transited);
1184 	return ret;
1185     }
1186 
1187 
1188     copy_Realm(krb5_princ_realm(context, server->principal),
1189 	       &rep.ticket.realm);
1190     krb5_principal2principalname(&rep.ticket.sname, server->principal);
1191     copy_Realm(&tgt->crealm, &rep.crealm);
1192     if (f.request_anonymous)
1193 	make_anonymous_principalname (&tgt->cname);
1194     else
1195 	copy_PrincipalName(&tgt->cname, &rep.cname);
1196     rep.ticket.tkt_vno = 5;
1197 
1198     ek.caddr = et.caddr;
1199     if(et.caddr == NULL)
1200 	et.caddr = tgt->caddr;
1201 
1202     {
1203 	time_t life;
1204 	life = et.endtime - *et.starttime;
1205 	if(client && client->max_life)
1206 	    life = min(life, *client->max_life);
1207 	if(server->max_life)
1208 	    life = min(life, *server->max_life);
1209 	et.endtime = *et.starttime + life;
1210     }
1211     if(f.renewable_ok && tgt->flags.renewable &&
1212        et.renew_till == NULL && et.endtime < *b->till){
1213 	et.flags.renewable = 1;
1214 	ALLOC(et.renew_till);
1215 	*et.renew_till = *b->till;
1216     }
1217     if(et.renew_till){
1218 	time_t renew;
1219 	renew = *et.renew_till - et.authtime;
1220 	if(client && client->max_renew)
1221 	    renew = min(renew, *client->max_renew);
1222 	if(server->max_renew)
1223 	    renew = min(renew, *server->max_renew);
1224 	*et.renew_till = et.authtime + renew;
1225     }
1226 
1227     if(et.renew_till){
1228 	*et.renew_till = min(*et.renew_till, *tgt->renew_till);
1229 	*et.starttime = min(*et.starttime, *et.renew_till);
1230 	et.endtime = min(et.endtime, *et.renew_till);
1231     }
1232 
1233     *et.starttime = min(*et.starttime, et.endtime);
1234 
1235     if(*et.starttime == et.endtime){
1236 	ret = KRB5KDC_ERR_NEVER_VALID;
1237 	goto out;
1238     }
1239     if(et.renew_till && et.endtime == *et.renew_till){
1240 	free(et.renew_till);
1241 	et.renew_till = NULL;
1242 	et.flags.renewable = 0;
1243     }
1244 
1245     et.flags.pre_authent = tgt->flags.pre_authent;
1246     et.flags.hw_authent  = tgt->flags.hw_authent;
1247     et.flags.anonymous   = tgt->flags.anonymous;
1248 
1249     /* XXX Check enc-authorization-data */
1250     et.authorization_data = auth_data;
1251 
1252     krb5_generate_random_keyblock(context, etype, &et.key);
1253     et.crealm = tgt->crealm;
1254     et.cname = tgt->cname;
1255 
1256     ek.key = et.key;
1257     /* MIT must have at least one last_req */
1258     ek.last_req.len = 1;
1259     ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
1260     ek.nonce = b->nonce;
1261     ek.flags = et.flags;
1262     ek.authtime = et.authtime;
1263     ek.starttime = et.starttime;
1264     ek.endtime = et.endtime;
1265     ek.renew_till = et.renew_till;
1266     ek.srealm = rep.ticket.realm;
1267     ek.sname = rep.ticket.sname;
1268 
1269     /* It is somewhat unclear where the etype in the following
1270        encryption should come from. What we have is a session
1271        key in the passed tgt, and a list of preferred etypes
1272        *for the new ticket*. Should we pick the best possible
1273        etype, given the keytype in the tgt, or should we look
1274        at the etype list here as well?  What if the tgt
1275        session key is DES3 and we want a ticket with a (say)
1276        CAST session key. Should the DES3 etype be added to the
1277        etype list, even if we don't want a session key with
1278        DES3? */
1279     ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
1280 		       0, &tgt->key, e_text, reply);
1281 out:
1282     free_TGS_REP(&rep);
1283     free_TransitedEncoding(&et.transited);
1284     if(et.starttime)
1285 	free(et.starttime);
1286     if(et.renew_till)
1287 	free(et.renew_till);
1288     free_LastReq(&ek.last_req);
1289     memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
1290     free_EncryptionKey(&et.key);
1291     return ret;
1292 }
1293 
1294 static krb5_error_code
1295 tgs_check_authenticator(krb5_auth_context ac,
1296 			KDC_REQ_BODY *b,
1297 			const char **e_text,
1298 			krb5_keyblock *key)
1299 {
1300     krb5_authenticator auth;
1301     size_t len;
1302     unsigned char *buf;
1303     size_t buf_size;
1304     krb5_error_code ret;
1305     krb5_crypto crypto;
1306 
1307     krb5_auth_con_getauthenticator(context, ac, &auth);
1308     if(auth->cksum == NULL){
1309 	kdc_log(0, "No authenticator in request");
1310 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
1311 	goto out;
1312     }
1313     /*
1314      * according to RFC1510 it doesn't need to be keyed,
1315      * but according to the latest draft it needs to.
1316      */
1317     if (
1318 #if 0
1319 !krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
1320 	||
1321 #endif
1322  !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
1323 	kdc_log(0, "Bad checksum type in authenticator: %d",
1324 		auth->cksum->cksumtype);
1325 	ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
1326 	goto out;
1327     }
1328 
1329     /* XXX should not re-encode this */
1330     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
1331     if(ret){
1332 	kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
1333 		krb5_get_err_text(context, ret));
1334 	goto out;
1335     }
1336     if(buf_size != len) {
1337 	free(buf);
1338 	kdc_log(0, "Internal error in ASN.1 encoder");
1339 	*e_text = "KDC internal error";
1340 	ret = KRB5KRB_ERR_GENERIC;
1341 	goto out;
1342     }
1343     ret = krb5_crypto_init(context, key, 0, &crypto);
1344     if (ret) {
1345 	free(buf);
1346 	kdc_log(0, "krb5_crypto_init failed: %s",
1347 		krb5_get_err_text(context, ret));
1348 	goto out;
1349     }
1350     ret = krb5_verify_checksum(context,
1351 			       crypto,
1352 			       KRB5_KU_TGS_REQ_AUTH_CKSUM,
1353 			       buf,
1354 			       len,
1355 			       auth->cksum);
1356     free(buf);
1357     krb5_crypto_destroy(context, crypto);
1358     if(ret){
1359 	kdc_log(0, "Failed to verify checksum: %s",
1360 		krb5_get_err_text(context, ret));
1361     }
1362 out:
1363     free_Authenticator(auth);
1364     free(auth);
1365     return ret;
1366 }
1367 
1368 /*
1369  * return the realm of a krbtgt-ticket or NULL
1370  */
1371 
1372 static Realm
1373 get_krbtgt_realm(const PrincipalName *p)
1374 {
1375     if(p->name_string.len == 2
1376        && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
1377 	return p->name_string.val[1];
1378     else
1379 	return NULL;
1380 }
1381 
1382 static Realm
1383 find_rpath(Realm r)
1384 {
1385     const char *new_realm = krb5_config_get_string(context,
1386 						   NULL,
1387 						   "libdefaults",
1388 						   "capath",
1389 						   r,
1390 						   NULL);
1391     return (Realm)new_realm;
1392 }
1393 
1394 
1395 static krb5_boolean
1396 need_referral(krb5_principal server, krb5_realm **realms)
1397 {
1398     if(server->name.name_type != KRB5_NT_SRV_INST ||
1399        server->name.name_string.len != 2)
1400 	return FALSE;
1401 
1402     return krb5_get_host_realm_int(context, server->name.name_string.val[1],
1403 				   FALSE, realms) == 0;
1404 }
1405 
1406 static krb5_error_code
1407 tgs_rep2(KDC_REQ_BODY *b,
1408 	 PA_DATA *tgs_req,
1409 	 krb5_data *reply,
1410 	 const char *from,
1411 	 const struct sockaddr *from_addr,
1412 	 time_t **csec,
1413 	 int **cusec)
1414 {
1415     krb5_ap_req ap_req;
1416     krb5_error_code ret;
1417     krb5_principal princ;
1418     krb5_auth_context ac = NULL;
1419     krb5_ticket *ticket = NULL;
1420     krb5_flags ap_req_options;
1421     krb5_flags verify_ap_req_flags;
1422     const char *e_text = NULL;
1423     krb5_crypto crypto;
1424 
1425     hdb_entry *krbtgt = NULL;
1426     EncTicketPart *tgt;
1427     Key *tkey;
1428     krb5_enctype cetype;
1429     krb5_principal cp = NULL;
1430     krb5_principal sp = NULL;
1431     AuthorizationData *auth_data = NULL;
1432 
1433     *csec  = NULL;
1434     *cusec = NULL;
1435 
1436     memset(&ap_req, 0, sizeof(ap_req));
1437     ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1438     if(ret){
1439 	kdc_log(0, "Failed to decode AP-REQ: %s",
1440 		krb5_get_err_text(context, ret));
1441 	goto out2;
1442     }
1443 
1444     if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1445 	/* XXX check for ticket.sname == req.sname */
1446 	kdc_log(0, "PA-DATA is not a ticket-granting ticket");
1447 	ret = KRB5KDC_ERR_POLICY; /* ? */
1448 	goto out2;
1449     }
1450 
1451     principalname2krb5_principal(&princ,
1452 				 ap_req.ticket.sname,
1453 				 ap_req.ticket.realm);
1454 
1455     ret = db_fetch(princ, &krbtgt);
1456 
1457     if(ret) {
1458 	char *p;
1459 	krb5_unparse_name(context, princ, &p);
1460 	kdc_log(0, "Ticket-granting ticket not found in database: %s: %s",
1461 		p, krb5_get_err_text(context, ret));
1462 	free(p);
1463 	ret = KRB5KRB_AP_ERR_NOT_US;
1464 	goto out2;
1465     }
1466 
1467     if(ap_req.ticket.enc_part.kvno &&
1468        *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
1469 	char *p;
1470 
1471 	krb5_unparse_name (context, princ, &p);
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