xref: /netbsd-src/crypto/external/bsd/heimdal/dist/kdc/kerberos5.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: kerberos5.c,v 1.9 2023/06/19 21:41:41 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "kdc_locl.h"
37 
38 #define MAX_TIME ((time_t)((1U << 31) - 1))
39 
40 void
_kdc_fix_time(time_t ** t)41 _kdc_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 int
realloc_method_data(METHOD_DATA * md)51 realloc_method_data(METHOD_DATA *md)
52 {
53     PA_DATA *pa;
54     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
55     if(pa == NULL)
56 	return ENOMEM;
57     md->val = pa;
58     md->len++;
59     return 0;
60 }
61 
62 static void
set_salt_padata(METHOD_DATA * md,Salt * salt)63 set_salt_padata(METHOD_DATA *md, Salt *salt)
64 {
65     if (salt) {
66        realloc_method_data(md);
67        md->val[md->len - 1].padata_type = salt->type;
68        der_copy_octet_string(&salt->salt,
69                              &md->val[md->len - 1].padata_value);
70     }
71 }
72 
73 const PA_DATA*
_kdc_find_padata(const KDC_REQ * req,int * start,int type)74 _kdc_find_padata(const KDC_REQ *req, int *start, int type)
75 {
76     if (req->padata == NULL)
77 	return NULL;
78 
79     while((size_t)*start < req->padata->len){
80 	(*start)++;
81 	if(req->padata->val[*start - 1].padata_type == (unsigned)type)
82 	    return &req->padata->val[*start - 1];
83     }
84     return NULL;
85 }
86 
87 /*
88  * This is a hack to allow predefined weak services, like afs to
89  * still use weak types
90  */
91 
92 krb5_boolean
_kdc_is_weak_exception(krb5_principal principal,krb5_enctype etype)93 _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
94 {
95     if (principal->name.name_string.len > 0 &&
96 	strcmp(principal->name.name_string.val[0], "afs") == 0 &&
97 	(etype == (krb5_enctype)ETYPE_DES_CBC_CRC
98 	 || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
99 	 || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
100 	return TRUE;
101     return FALSE;
102 }
103 
104 
105 /*
106  * Detect if `key' is the using the the precomputed `default_salt'.
107  */
108 
109 static krb5_boolean
is_default_salt_p(const krb5_salt * default_salt,const Key * key)110 is_default_salt_p(const krb5_salt *default_salt, const Key *key)
111 {
112     if (key->salt == NULL)
113 	return TRUE;
114     if (default_salt->salttype != key->salt->type)
115 	return FALSE;
116     if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
117 	return FALSE;
118     return TRUE;
119 }
120 
121 /*
122  * Detect if `key' is the using the the precomputed `default_salt'
123  * (for des-cbc-crc) or any salt otherwise.
124  *
125  * This is for avoiding Kerberos v4 (yes really) keys in AS-REQ as
126  * that salt is strange, and a buggy client will try to use the
127  * principal as the salt and not the returned value.
128  */
129 
130 static krb5_boolean
is_good_salt_p(const krb5_salt * default_salt,const Key * key)131 is_good_salt_p(const krb5_salt *default_salt, const Key *key)
132 {
133     if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
134 	return is_default_salt_p(default_salt, key);
135 
136     return TRUE;
137 }
138 
139 krb5_boolean
_kdc_is_anon_request(const KDC_REQ * req)140 _kdc_is_anon_request(const KDC_REQ *req)
141 {
142     const KDC_REQ_BODY *b = &req->req_body;
143 
144     /*
145      * Versions of Heimdal from 0.9rc1 through 1.50 use bit 14 instead
146      * of 16 for request_anonymous, as indicated in the anonymous draft
147      * prior to version 11. Bit 14 is assigned to S4U2Proxy, but S4U2Proxy
148      * requests are only sent to the TGS and, in any case, would have an
149      * additional ticket present.
150      */
151     return b->kdc_options.request_anonymous ||
152 	   (b->kdc_options.cname_in_addl_tkt && !b->additional_tickets);
153 }
154 
155 /*
156  * return the first appropriate key of `princ' in `ret_key'.  Look for
157  * all the etypes in (`etypes', `len'), stopping as soon as we find
158  * one, but preferring one that has default salt.
159  */
160 
161 krb5_error_code
_kdc_find_etype(krb5_context context,krb5_boolean use_strongest_session_key,krb5_boolean is_preauth,hdb_entry_ex * princ,krb5_enctype * etypes,unsigned len,krb5_enctype * ret_enctype,Key ** ret_key)162 _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
163 		krb5_boolean is_preauth, hdb_entry_ex *princ,
164 		krb5_enctype *etypes, unsigned len,
165 		krb5_enctype *ret_enctype, Key **ret_key)
166 {
167     krb5_error_code ret;
168     krb5_salt def_salt;
169     krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
170     const krb5_enctype *p;
171     Key *key = NULL;
172     int i, k;
173 
174     /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
175     ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
176     if (ret)
177 	return ret;
178 
179     ret = KRB5KDC_ERR_ETYPE_NOSUPP;
180 
181     if (use_strongest_session_key) {
182 
183 	/*
184 	 * Pick the strongest key that the KDC, target service, and
185 	 * client all support, using the local cryptosystem enctype
186 	 * list in strongest-to-weakest order to drive the search.
187 	 *
188 	 * This is not what RFC4120 says to do, but it encourages
189 	 * adoption of stronger enctypes.  This doesn't play well with
190 	 * clients that have multiple Kerberos client implementations
191 	 * available with different supported enctype lists.
192 	 */
193 
194 	/* drive the search with local supported enctypes list */
195 	p = krb5_kerberos_enctypes(context);
196 	for (i = 0;
197 	    p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
198 	    i++) {
199 	    if (krb5_enctype_valid(context, p[i]) != 0 &&
200                 !_kdc_is_weak_exception(princ->entry.principal, p[i]))
201 		continue;
202 
203 	    /* check that the client supports it too */
204 	    for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
205 
206 		if (p[i] != etypes[k])
207 		    continue;
208 
209                 /* check target princ support */
210 		key = NULL;
211 		while (hdb_next_enctype2key(context, &princ->entry, NULL,
212 					     p[i], &key) == 0) {
213 		    if (key->key.keyvalue.length == 0) {
214 			ret = KRB5KDC_ERR_NULL_KEY;
215 			continue;
216 		    }
217 		    enctype = p[i];
218 		    ret = 0;
219 		    if (is_preauth && ret_key != NULL &&
220 			!is_good_salt_p(&def_salt, key))
221 			continue;
222 		}
223 	    }
224 	}
225     } else {
226 	/*
227 	 * Pick the first key from the client's enctype list that is
228 	 * supported by the cryptosystem and by the given principal.
229 	 *
230 	 * RFC4120 says we SHOULD pick the first _strong_ key from the
231 	 * client's list... not the first key...  If the admin disallows
232 	 * weak enctypes in krb5.conf and selects this key selection
233 	 * algorithm, then we get exactly what RFC4120 says.
234 	 */
235 	for(i = 0; ret != 0 && i < len; i++) {
236 
237 	    if (krb5_enctype_valid(context, etypes[i]) != 0 &&
238 		!_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
239 		continue;
240 
241 	    key = NULL;
242 	    while (ret != 0 &&
243                    hdb_next_enctype2key(context, &princ->entry, NULL,
244 					etypes[i], &key) == 0) {
245 		if (key->key.keyvalue.length == 0) {
246 		    ret = KRB5KDC_ERR_NULL_KEY;
247 		    continue;
248 		}
249                 enctype = etypes[i];
250 		ret = 0;
251 		if (is_preauth && ret_key != NULL &&
252 		    !is_good_salt_p(&def_salt, key))
253 		    continue;
254 	    }
255 	}
256     }
257 
258     if (enctype == (krb5_enctype)ETYPE_NULL) {
259         /*
260          * if the service principal is one for which there is a known 1DES
261          * exception and no other enctype matches both the client request and
262          * the service key list, provide a DES-CBC-CRC key.
263          */
264 	if (ret_key == NULL &&
265 	    _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
266             ret = 0;
267             enctype = ETYPE_DES_CBC_CRC;
268         } else {
269             ret = KRB5KDC_ERR_ETYPE_NOSUPP;
270         }
271     }
272 
273     if (ret == 0) {
274 	if (ret_enctype != NULL)
275 	    *ret_enctype = enctype;
276 	if (ret_key != NULL)
277 	    *ret_key = key;
278     }
279 
280     krb5_free_salt (context, def_salt);
281     return ret;
282 }
283 
284 krb5_error_code
_kdc_make_anonymous_principalname(PrincipalName * pn)285 _kdc_make_anonymous_principalname (PrincipalName *pn)
286 {
287     pn->name_type = KRB5_NT_WELLKNOWN;
288     pn->name_string.len = 2;
289     pn->name_string.val = calloc(2, sizeof(*pn->name_string.val));
290     if (pn->name_string.val == NULL)
291 	goto failed;
292 
293     pn->name_string.val[0] = strdup(KRB5_WELLKNOWN_NAME);
294     if (pn->name_string.val[0] == NULL)
295 	goto failed;
296 
297     pn->name_string.val[1] = strdup(KRB5_ANON_NAME);
298     if (pn->name_string.val[1] == NULL)
299 	goto failed;
300 
301     return 0;
302 
303 failed:
304     free_PrincipalName(pn);
305 
306     pn->name_type = KRB5_NT_UNKNOWN;
307     pn->name_string.len = 0;
308     pn->name_string.val = NULL;
309 
310     return ENOMEM;
311 }
312 
313 static void
_kdc_r_log(kdc_request_t r,int level,const char * fmt,...)314 _kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
315 {
316     va_list ap;
317     char *s;
318     va_start(ap, fmt);
319     s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
320     if(s) free(s);
321     va_end(ap);
322 }
323 
324 static void
_kdc_set_e_text(kdc_request_t r,const char * e_text)325 _kdc_set_e_text(kdc_request_t r, const char *e_text)
326 {
327     r->e_text = e_text;
328     kdc_log(r->context, r->config, 0, "%s", e_text);
329 }
330 
331 void
_kdc_log_timestamp(krb5_context context,krb5_kdc_configuration * config,const char * type,KerberosTime authtime,KerberosTime * starttime,KerberosTime endtime,KerberosTime * renew_till)332 _kdc_log_timestamp(krb5_context context,
333 		   krb5_kdc_configuration *config,
334 		   const char *type,
335 		   KerberosTime authtime, KerberosTime *starttime,
336 		   KerberosTime endtime, KerberosTime *renew_till)
337 {
338     char authtime_str[100], starttime_str[100],
339 	endtime_str[100], renewtime_str[100];
340 
341     krb5_format_time(context, authtime,
342 		     authtime_str, sizeof(authtime_str), TRUE);
343     if (starttime)
344 	krb5_format_time(context, *starttime,
345 			 starttime_str, sizeof(starttime_str), TRUE);
346     else
347 	strlcpy(starttime_str, "unset", sizeof(starttime_str));
348     krb5_format_time(context, endtime,
349 		     endtime_str, sizeof(endtime_str), TRUE);
350     if (renew_till)
351 	krb5_format_time(context, *renew_till,
352 			 renewtime_str, sizeof(renewtime_str), TRUE);
353     else
354 	strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
355 
356     kdc_log(context, config, 5,
357 	    "%s authtime: %s starttime: %s endtime: %s renew till: %s",
358 	    type, authtime_str, starttime_str, endtime_str, renewtime_str);
359 }
360 
361 /*
362  *
363  */
364 
365 #ifdef PKINIT
366 
367 static krb5_error_code
pa_pkinit_validate(kdc_request_t r,const PA_DATA * pa)368 pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
369 {
370     pk_client_params *pkp = NULL;
371     char *client_cert = NULL;
372     krb5_error_code ret;
373 
374     ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
375     if (ret || pkp == NULL) {
376 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
377 	_kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s",
378 		   r->client_name);
379 	goto out;
380     }
381 
382     ret = _kdc_pk_check_client(r->context,
383 			       r->config,
384 			       r->clientdb,
385 			       r->client,
386 			       pkp,
387 			       &client_cert);
388     if (ret) {
389 	_kdc_set_e_text(r, "PKINIT certificate not allowed to "
390 			"impersonate principal");
391 	goto out;
392     }
393 
394     _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s",
395 	       r->client_name, client_cert);
396     free(client_cert);
397 
398     ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
399 			      r->sessionetype, &r->req, &r->request,
400 			      &r->reply_key, &r->session_key, &r->outpadata);
401     if (ret) {
402 	_kdc_set_e_text(r, "Failed to build PK-INIT reply");
403 	goto out;
404     }
405 #if 0
406     ret = _kdc_add_inital_verified_cas(r->context, r->config,
407 				       pkp, &r->et);
408 #endif
409  out:
410     if (pkp)
411 	_kdc_pk_free_client_param(r->context, pkp);
412 
413     return ret;
414 }
415 
416 #endif /* PKINIT */
417 
418 /*
419  *
420  */
421 
422 static krb5_error_code
make_pa_enc_challange(krb5_context context,METHOD_DATA * md,krb5_crypto crypto)423 make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
424 		      krb5_crypto crypto)
425 {
426     PA_ENC_TS_ENC p;
427     unsigned char *buf;
428     size_t buf_size;
429     size_t len;
430     EncryptedData encdata;
431     krb5_error_code ret;
432     int32_t usec;
433     int usec2;
434 
435     krb5_us_timeofday (context, &p.patimestamp, &usec);
436     usec2         = usec;
437     p.pausec      = &usec2;
438 
439     ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
440     if (ret)
441 	return ret;
442     if(buf_size != len)
443 	krb5_abortx(context, "internal error in ASN.1 encoder");
444 
445     ret = krb5_encrypt_EncryptedData(context,
446 				     crypto,
447 				     KRB5_KU_ENC_CHALLENGE_KDC,
448 				     buf,
449 				     len,
450 				     0,
451 				     &encdata);
452     free(buf);
453     if (ret)
454 	return ret;
455 
456     ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
457     free_EncryptedData(&encdata);
458     if (ret)
459 	return ret;
460     if(buf_size != len)
461 	krb5_abortx(context, "internal error in ASN.1 encoder");
462 
463     ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len);
464     if (ret)
465 	free(buf);
466     return ret;
467 }
468 
469 static krb5_error_code
pa_enc_chal_validate(kdc_request_t r,const PA_DATA * pa)470 pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
471 {
472     krb5_data pepper1, pepper2, ts_data;
473     int invalidPassword = 0;
474     EncryptedData enc_data;
475     krb5_enctype aenctype;
476     krb5_error_code ret;
477     struct Key *k;
478     size_t size;
479     int i;
480 
481     heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
482 
483     if (_kdc_is_anon_request(&r->req)) {
484 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
485 	kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon");
486 	return ret;
487     }
488 
489     ret = decode_EncryptedData(pa->padata_value.data,
490 			       pa->padata_value.length,
491 			       &enc_data,
492 			       &size);
493     if (ret) {
494 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
495 	_kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
496 		   r->client_name);
497 	return ret;
498     }
499 
500     pepper1.data = "clientchallengearmor";
501     pepper1.length = strlen(pepper1.data);
502     pepper2.data = "challengelongterm";
503     pepper2.length = strlen(pepper2.data);
504 
505     krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
506 
507     for (i = 0; i < r->client->entry.keys.len; i++) {
508 	krb5_crypto challangecrypto, longtermcrypto;
509 	krb5_keyblock challangekey;
510 	PA_ENC_TS_ENC p;
511 
512 	k = &r->client->entry.keys.val[i];
513 
514 	ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
515 	if (ret)
516 	    continue;
517 
518 	ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
519 				 &pepper1, &pepper2, aenctype,
520 				 &challangekey);
521 	krb5_crypto_destroy(r->context, longtermcrypto);
522 	if (ret)
523 	    continue;
524 
525 	ret = krb5_crypto_init(r->context, &challangekey, 0,
526 			       &challangecrypto);
527 	if (ret)
528 	    continue;
529 
530 	ret = krb5_decrypt_EncryptedData(r->context, challangecrypto,
531 					 KRB5_KU_ENC_CHALLENGE_CLIENT,
532 					 &enc_data,
533 					 &ts_data);
534 	if (ret) {
535 	    const char *msg = krb5_get_error_message(r->context, ret);
536 	    krb5_error_code ret2;
537 	    char *str = NULL;
538 
539 	    invalidPassword = 1;
540 
541 	    ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
542 	    if (ret2)
543 		str = NULL;
544 	    _kdc_r_log(r, 5, "Failed to decrypt ENC-CHAL -- %s "
545 		       "(enctype %s) error %s",
546 		       r->client_name, str ? str : "unknown enctype", msg);
547 	    krb5_free_error_message(r->context, msg);
548 	    free(str);
549 
550 	    continue;
551 	}
552 
553 	ret = decode_PA_ENC_TS_ENC(ts_data.data,
554 				   ts_data.length,
555 				   &p,
556 				   &size);
557 	krb5_data_free(&ts_data);
558 	if(ret){
559 	    krb5_crypto_destroy(r->context, challangecrypto);
560 	    ret = KRB5KDC_ERR_PREAUTH_FAILED;
561 	    _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
562 		       r->client_name);
563 	    continue;
564 	}
565 
566 	if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
567 	    char client_time[100];
568 
569 	    krb5_crypto_destroy(r->context, challangecrypto);
570 
571 	    krb5_format_time(r->context, p.patimestamp,
572 			     client_time, sizeof(client_time), TRUE);
573 
574 	    ret = KRB5KRB_AP_ERR_SKEW;
575 	    _kdc_r_log(r, 0, "Too large time skew, "
576 		       "client time %s is out by %u > %u seconds -- %s",
577 		       client_time,
578 		       (unsigned)labs(kdc_time - p.patimestamp),
579 		       r->context->max_skew,
580 		       r->client_name);
581 
582 	    free_PA_ENC_TS_ENC(&p);
583 	    goto out;
584 	}
585 
586 	free_PA_ENC_TS_ENC(&p);
587 
588 	ret = make_pa_enc_challange(r->context, &r->outpadata,
589 				    challangecrypto);
590 	krb5_crypto_destroy(r->context, challangecrypto);
591 	if (ret)
592 	    goto out;
593 
594 	set_salt_padata(&r->outpadata, k->salt);
595 	krb5_free_keyblock_contents(r->context,  &r->reply_key);
596 	ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
597 	if (ret)
598 	    goto out;
599 
600 	/*
601 	 * Success
602 	 */
603 	if (r->clientdb->hdb_auth_status)
604 	    r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
605 					 HDB_AUTH_SUCCESS);
606 	goto out;
607     }
608 
609     if (invalidPassword && r->clientdb->hdb_auth_status) {
610 	r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
611 				     HDB_AUTH_WRONG_PASSWORD);
612 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
613     }
614  out:
615     free_EncryptedData(&enc_data);
616 
617     return ret;
618 }
619 
620 static krb5_error_code
pa_enc_ts_validate(kdc_request_t r,const PA_DATA * pa)621 pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
622 {
623     EncryptedData enc_data;
624     krb5_error_code ret;
625     krb5_crypto crypto;
626     krb5_data ts_data;
627     PA_ENC_TS_ENC p;
628     size_t len;
629     Key *pa_key;
630     char *str;
631 
632     ret = decode_EncryptedData(pa->padata_value.data,
633 			       pa->padata_value.length,
634 			       &enc_data,
635 			       &len);
636     if (ret) {
637 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
638 	_kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
639 		   r->client_name);
640 	goto out;
641     }
642 
643     ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
644 			  enc_data.etype, &pa_key);
645     if(ret){
646 	char *estr;
647 	_kdc_set_e_text(r, "No key matching entype");
648 	ret = KRB5KDC_ERR_ETYPE_NOSUPP;
649 	if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
650 	    estr = NULL;
651 	if(estr == NULL)
652 	    _kdc_r_log(r, 5,
653 		       "No client key matching pa-data (%d) -- %s",
654 		       enc_data.etype, r->client_name);
655 	else
656 	    _kdc_r_log(r, 5,
657 		       "No client key matching pa-data (%s) -- %s",
658 		       estr, r->client_name);
659 	free(estr);
660 	free_EncryptedData(&enc_data);
661 	goto out;
662     }
663 
664  try_next_key:
665     ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
666     if (ret) {
667 	const char *msg = krb5_get_error_message(r->context, ret);
668 	_kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg);
669 	krb5_free_error_message(r->context, msg);
670 	free_EncryptedData(&enc_data);
671 	goto out;
672     }
673 
674     ret = krb5_decrypt_EncryptedData (r->context,
675 				      crypto,
676 				      KRB5_KU_PA_ENC_TIMESTAMP,
677 				      &enc_data,
678 				      &ts_data);
679     krb5_crypto_destroy(r->context, crypto);
680     /*
681      * Since the user might have several keys with the same
682      * enctype but with diffrent salting, we need to try all
683      * the keys with the same enctype.
684      */
685     if(ret){
686 	krb5_error_code ret2;
687 	const char *msg = krb5_get_error_message(r->context, ret);
688 
689 	ret2 = krb5_enctype_to_string(r->context,
690 				      pa_key->key.keytype, &str);
691 	if (ret2)
692 	    str = NULL;
693 	_kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s "
694 		   "(enctype %s) error %s",
695 		   r->client_name, str ? str : "unknown enctype", msg);
696 	krb5_free_error_message(r->context, msg);
697 	free(str);
698 
699 	if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
700 				enc_data.etype, &pa_key) == 0)
701 	    goto try_next_key;
702 
703 	free_EncryptedData(&enc_data);
704 
705 	if (r->clientdb->hdb_auth_status)
706 	    r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
707 					 HDB_AUTH_WRONG_PASSWORD);
708 
709 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
710 	goto out;
711     }
712     free_EncryptedData(&enc_data);
713     ret = decode_PA_ENC_TS_ENC(ts_data.data,
714 			       ts_data.length,
715 			       &p,
716 			       &len);
717     krb5_data_free(&ts_data);
718     if(ret){
719 	ret = KRB5KDC_ERR_PREAUTH_FAILED;
720 	_kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
721 		   r->client_name);
722 	goto out;
723     }
724     if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
725 	char client_time[100];
726 
727 	krb5_format_time(r->context, p.patimestamp,
728 			 client_time, sizeof(client_time), TRUE);
729 
730 	ret = KRB5KRB_AP_ERR_SKEW;
731 	_kdc_r_log(r, 0, "Too large time skew, "
732 		   "client time %s is out by %u > %u seconds -- %s",
733 		   client_time,
734 		   (unsigned)labs(kdc_time - p.patimestamp),
735 		   r->context->max_skew,
736 		   r->client_name);
737 
738 	/*
739 	 * The following is needed to make windows clients to
740 	 * retry using the timestamp in the error message, if
741 	 * there is a e_text, they become unhappy.
742 	 */
743 	r->e_text = NULL;
744 	free_PA_ENC_TS_ENC(&p);
745 	goto out;
746     }
747     free_PA_ENC_TS_ENC(&p);
748 
749     set_salt_padata(&r->outpadata, pa_key->salt);
750 
751     ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
752     if (ret)
753 	return ret;
754 
755     ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
756     if (ret)
757 	str = NULL;
758     _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s",
759 	       r->client_name, str ? str : "unknown enctype");
760     free(str);
761 
762     ret = 0;
763 
764  out:
765 
766     return ret;
767 }
768 
769 struct kdc_patypes {
770     int type;
771     char *name;
772     unsigned int flags;
773 #define PA_ANNOUNCE	1
774 #define PA_REQ_FAST	2 /* only use inside fast */
775     krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
776 };
777 
778 static const struct kdc_patypes pat[] = {
779 #ifdef PKINIT
780     {
781 	KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
782 	pa_pkinit_validate
783     },
784     {
785 	KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
786 	pa_pkinit_validate
787     },
788     {
789 	KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
790 	NULL
791     },
792 #else
793     { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
794     { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
795     { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL },
796 #endif
797     { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
798     {
799 	KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
800 	PA_ANNOUNCE,
801 	pa_enc_ts_validate
802     },
803     {
804 	KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
805 	PA_ANNOUNCE | PA_REQ_FAST,
806 	pa_enc_chal_validate
807     },
808     { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
809     { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
810     { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
811     { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
812 };
813 
814 static void
log_patypes(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * padata)815 log_patypes(krb5_context context,
816 	    krb5_kdc_configuration *config,
817 	    METHOD_DATA *padata)
818 {
819     struct rk_strpool *p = NULL;
820     char *str;
821     size_t n, m;
822 
823     for (n = 0; n < padata->len; n++) {
824 	for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
825 	    if (padata->val[n].padata_type == pat[m].type) {
826 		p = rk_strpoolprintf(p, "%s", pat[m].name);
827 		break;
828 	    }
829 	}
830 	if (m == sizeof(pat) / sizeof(pat[0]))
831 	    p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
832 	if (p && n + 1 < padata->len)
833 	    p = rk_strpoolprintf(p, ", ");
834 	if (p == NULL) {
835 	    kdc_log(context, config, 0, "out of memory");
836 	    return;
837 	}
838     }
839     if (p == NULL)
840 	p = rk_strpoolprintf(p, "none");
841 
842     str = rk_strpoolcollect(p);
843     kdc_log(context, config, 0, "Client sent patypes: %s", str);
844     free(str);
845 }
846 
847 /*
848  *
849  */
850 
851 krb5_error_code
_kdc_encode_reply(krb5_context context,krb5_kdc_configuration * config,krb5_crypto armor_crypto,uint32_t nonce,KDC_REP * rep,EncTicketPart * et,EncKDCRepPart * ek,krb5_enctype etype,int skvno,const EncryptionKey * skey,int ckvno,const EncryptionKey * reply_key,int rk_is_subkey,const char ** e_text,krb5_data * reply)852 _kdc_encode_reply(krb5_context context,
853 		  krb5_kdc_configuration *config,
854 		  krb5_crypto armor_crypto, uint32_t nonce,
855 		  KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
856 		  krb5_enctype etype,
857 		  int skvno, const EncryptionKey *skey,
858 		  int ckvno, const EncryptionKey *reply_key,
859 		  int rk_is_subkey,
860 		  const char **e_text,
861 		  krb5_data *reply)
862 {
863     unsigned char *buf;
864     size_t buf_size;
865     size_t len = 0;
866     krb5_error_code ret;
867     krb5_crypto crypto;
868 
869     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
870     if(ret) {
871 	const char *msg = krb5_get_error_message(context, ret);
872 	kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
873 	krb5_free_error_message(context, msg);
874 	return ret;
875     }
876     if(buf_size != len)
877 	krb5_abortx(context, "Internal error in ASN.1 encoder");
878 
879     ret = krb5_crypto_init(context, skey, etype, &crypto);
880     if (ret) {
881         const char *msg = krb5_get_error_message(context, ret);
882 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
883 	krb5_free_error_message(context, msg);
884 	free(buf);
885 	return ret;
886     }
887 
888     ret = krb5_encrypt_EncryptedData(context,
889 				     crypto,
890 				     KRB5_KU_TICKET,
891 				     buf,
892 				     len,
893 				     skvno,
894 				     &rep->ticket.enc_part);
895     free(buf);
896     krb5_crypto_destroy(context, crypto);
897     if(ret) {
898 	const char *msg = krb5_get_error_message(context, ret);
899 	kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
900 	krb5_free_error_message(context, msg);
901 	return ret;
902     }
903 
904     if (armor_crypto) {
905 	krb5_data data;
906 	krb5_keyblock *strengthen_key = NULL;
907 	KrbFastFinished finished;
908 
909 	kdc_log(context, config, 0, "FAST armor protection");
910 
911 	memset(&finished, 0, sizeof(finished));
912 	krb5_data_zero(&data);
913 
914 	finished.timestamp = kdc_time;
915 	finished.usec = 0;
916 	finished.crealm = et->crealm;
917 	finished.cname = et->cname;
918 
919 	ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
920 			   &rep->ticket, &len, ret);
921 	if (ret)
922 	    return ret;
923 	if (data.length != len)
924 	    krb5_abortx(context, "internal asn.1 error");
925 
926 	ret = krb5_create_checksum(context, armor_crypto,
927 				   KRB5_KU_FAST_FINISHED, 0,
928 				   data.data, data.length,
929 				   &finished.ticket_checksum);
930 	krb5_data_free(&data);
931 	if (ret)
932 	    return ret;
933 
934 	ret = _kdc_fast_mk_response(context, armor_crypto,
935 				    rep->padata, strengthen_key, &finished,
936 				    nonce, &data);
937 	free_Checksum(&finished.ticket_checksum);
938 	if (ret)
939 	    return ret;
940 
941 	if (rep->padata) {
942 	    free_METHOD_DATA(rep->padata);
943 	} else {
944 	    rep->padata = calloc(1, sizeof(*(rep->padata)));
945 	    if (rep->padata == NULL) {
946 		krb5_data_free(&data);
947 		return ENOMEM;
948 	    }
949 	}
950 
951 	ret = krb5_padata_add(context, rep->padata,
952 			      KRB5_PADATA_FX_FAST,
953 			      data.data, data.length);
954 	if (ret)
955 	    return ret;
956 
957 	/*
958 	 * Hide client name of privacy reasons
959 	 */
960 	if (1 /* r->fast_options.hide_client_names */) {
961 	    rep->crealm[0] = '\0';
962 	    free_PrincipalName(&rep->cname);
963 	    rep->cname.name_type = 0;
964 	}
965     }
966 
967     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
968 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
969     else
970 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
971     if(ret) {
972 	const char *msg = krb5_get_error_message(context, ret);
973 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
974 	krb5_free_error_message(context, msg);
975 	return ret;
976     }
977     if(buf_size != len) {
978 	free(buf);
979 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
980 	*e_text = "KDC internal error";
981 	return KRB5KRB_ERR_GENERIC;
982     }
983     ret = krb5_crypto_init(context, reply_key, 0, &crypto);
984     if (ret) {
985 	const char *msg = krb5_get_error_message(context, ret);
986 	free(buf);
987 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
988 	krb5_free_error_message(context, msg);
989 	return ret;
990     }
991     if(rep->msg_type == krb_as_rep) {
992 	krb5_encrypt_EncryptedData(context,
993 				   crypto,
994 				   KRB5_KU_AS_REP_ENC_PART,
995 				   buf,
996 				   len,
997 				   ckvno,
998 				   &rep->enc_part);
999 	free(buf);
1000 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
1001     } else {
1002 	krb5_encrypt_EncryptedData(context,
1003 				   crypto,
1004 				   rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
1005 				   buf,
1006 				   len,
1007 				   ckvno,
1008 				   &rep->enc_part);
1009 	free(buf);
1010 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
1011     }
1012     krb5_crypto_destroy(context, crypto);
1013     if(ret) {
1014 	const char *msg = krb5_get_error_message(context, ret);
1015 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
1016 	krb5_free_error_message(context, msg);
1017 	return ret;
1018     }
1019     if(buf_size != len) {
1020 	free(buf);
1021 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
1022 	*e_text = "KDC internal error";
1023 	return KRB5KRB_ERR_GENERIC;
1024     }
1025     reply->data = buf;
1026     reply->length = buf_size;
1027     return 0;
1028 }
1029 
1030 /*
1031  * Return 1 if the client have only older enctypes, this is for
1032  * determining if the server should send ETYPE_INFO2 or not.
1033  */
1034 
1035 static int
older_enctype(krb5_enctype enctype)1036 older_enctype(krb5_enctype enctype)
1037 {
1038     switch (enctype) {
1039     case ETYPE_DES_CBC_CRC:
1040     case ETYPE_DES_CBC_MD4:
1041     case ETYPE_DES_CBC_MD5:
1042     case ETYPE_DES3_CBC_SHA1:
1043     case ETYPE_ARCFOUR_HMAC_MD5:
1044     case ETYPE_ARCFOUR_HMAC_MD5_56:
1045     /*
1046      * The following three is "old" windows enctypes and is needed for
1047      * windows 2000 hosts.
1048      */
1049     case ETYPE_ARCFOUR_MD4:
1050     case ETYPE_ARCFOUR_HMAC_OLD:
1051     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
1052 	return 1;
1053     default:
1054 	return 0;
1055     }
1056 }
1057 
1058 /*
1059  *
1060  */
1061 
1062 static krb5_error_code
make_etype_info_entry(krb5_context context,ETYPE_INFO_ENTRY * ent,Key * key)1063 make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
1064 {
1065     ent->etype = key->key.keytype;
1066     if(key->salt){
1067 #if 0
1068 	ALLOC(ent->salttype);
1069 
1070 	if(key->salt->type == hdb_pw_salt)
1071 	    *ent->salttype = 0; /* or 1? or NULL? */
1072 	else if(key->salt->type == hdb_afs3_salt)
1073 	    *ent->salttype = 2;
1074 	else {
1075 	    kdc_log(context, config, 0, "unknown salt-type: %d",
1076 		    key->salt->type);
1077 	    return KRB5KRB_ERR_GENERIC;
1078 	}
1079 	/* according to `the specs', we can't send a salt if
1080 	   we have AFS3 salted key, but that requires that you
1081 	   *know* what cell you are using (e.g by assuming
1082 	   that the cell is the same as the realm in lower
1083 	   case) */
1084 #elif 0
1085 	ALLOC(ent->salttype);
1086 	*ent->salttype = key->salt->type;
1087 #else
1088 	/*
1089 	 * We shouldn't sent salttype since it is incompatible with the
1090 	 * specification and it breaks windows clients.  The afs
1091 	 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
1092 	 * implemented in Heimdal 0.7 and later.
1093 	 */
1094 	ent->salttype = NULL;
1095 #endif
1096 	krb5_copy_data(context, &key->salt->salt,
1097 		       &ent->salt);
1098     } else {
1099 	/* we return no salt type at all, as that should indicate
1100 	 * the default salt type and make everybody happy.  some
1101 	 * systems (like w2k) dislike being told the salt type
1102 	 * here. */
1103 
1104 	ent->salttype = NULL;
1105 	ent->salt = NULL;
1106     }
1107     return 0;
1108 }
1109 
1110 static krb5_error_code
get_pa_etype_info(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)1111 get_pa_etype_info(krb5_context context,
1112 		  krb5_kdc_configuration *config,
1113 		  METHOD_DATA *md, Key *ckey)
1114 {
1115     krb5_error_code ret = 0;
1116     ETYPE_INFO pa;
1117     unsigned char *buf;
1118     size_t len;
1119 
1120 
1121     pa.len = 1;
1122     pa.val = calloc(1, sizeof(pa.val[0]));
1123     if(pa.val == NULL)
1124 	return ENOMEM;
1125 
1126     ret = make_etype_info_entry(context, &pa.val[0], ckey);
1127     if (ret) {
1128 	free_ETYPE_INFO(&pa);
1129 	return ret;
1130     }
1131 
1132     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
1133     free_ETYPE_INFO(&pa);
1134     if(ret)
1135 	return ret;
1136     ret = realloc_method_data(md);
1137     if(ret) {
1138 	free(buf);
1139 	return ret;
1140     }
1141     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
1142     md->val[md->len - 1].padata_value.length = len;
1143     md->val[md->len - 1].padata_value.data = buf;
1144     return 0;
1145 }
1146 
1147 /*
1148  *
1149  */
1150 
1151 extern int _krb5_AES_SHA1_string_to_default_iterator;
1152 extern int _krb5_AES_SHA2_string_to_default_iterator;
1153 
1154 static krb5_error_code
make_s2kparams(int value,size_t len,krb5_data ** ps2kparams)1155 make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
1156 {
1157     krb5_data *s2kparams;
1158     krb5_error_code ret;
1159 
1160     ALLOC(s2kparams);
1161     if (s2kparams == NULL)
1162 	return ENOMEM;
1163     ret = krb5_data_alloc(s2kparams, len);
1164     if (ret) {
1165 	free(s2kparams);
1166 	return ret;
1167     }
1168     _krb5_put_int(s2kparams->data, value, len);
1169     *ps2kparams = s2kparams;
1170     return 0;
1171 }
1172 
1173 static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY * ent,Key * key)1174 make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
1175 {
1176     krb5_error_code ret;
1177 
1178     ent->etype = key->key.keytype;
1179     if(key->salt) {
1180 	ALLOC(ent->salt);
1181 	if (ent->salt == NULL)
1182 	    return ENOMEM;
1183 	*ent->salt = malloc(key->salt->salt.length + 1);
1184 	if (*ent->salt == NULL) {
1185 	    free(ent->salt);
1186 	    ent->salt = NULL;
1187 	    return ENOMEM;
1188 	}
1189 	memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
1190 	(*ent->salt)[key->salt->salt.length] = '\0';
1191     } else
1192 	ent->salt = NULL;
1193 
1194     ent->s2kparams = NULL;
1195 
1196     switch (key->key.keytype) {
1197     case ETYPE_AES128_CTS_HMAC_SHA1_96:
1198     case ETYPE_AES256_CTS_HMAC_SHA1_96:
1199 	ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
1200 			     4, &ent->s2kparams);
1201 	break;
1202     case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
1203     case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
1204 	ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
1205 			     4, &ent->s2kparams);
1206 	break;
1207     case ETYPE_DES_CBC_CRC:
1208     case ETYPE_DES_CBC_MD4:
1209     case ETYPE_DES_CBC_MD5:
1210 	/* Check if this was a AFS3 salted key */
1211 	if(key->salt && key->salt->type == hdb_afs3_salt)
1212 	    ret = make_s2kparams(1, 1, &ent->s2kparams);
1213 	else
1214 	    ret = 0;
1215 	break;
1216     default:
1217 	ret = 0;
1218 	break;
1219     }
1220     return ret;
1221 }
1222 
1223 /*
1224  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
1225  * database (client supported enctypes first, then the unsupported
1226  * enctypes).
1227  */
1228 
1229 static krb5_error_code
get_pa_etype_info2(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)1230 get_pa_etype_info2(krb5_context context,
1231 		   krb5_kdc_configuration *config,
1232 		   METHOD_DATA *md, Key *ckey)
1233 {
1234     krb5_error_code ret = 0;
1235     ETYPE_INFO2 pa;
1236     unsigned char *buf;
1237     size_t len;
1238 
1239     pa.len = 1;
1240     pa.val = calloc(1, sizeof(pa.val[0]));
1241     if(pa.val == NULL)
1242 	return ENOMEM;
1243 
1244     ret = make_etype_info2_entry(&pa.val[0], ckey);
1245     if (ret) {
1246 	free_ETYPE_INFO2(&pa);
1247 	return ret;
1248     }
1249 
1250     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
1251     free_ETYPE_INFO2(&pa);
1252     if(ret)
1253 	return ret;
1254     ret = realloc_method_data(md);
1255     if(ret) {
1256 	free(buf);
1257 	return ret;
1258     }
1259     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
1260     md->val[md->len - 1].padata_value.length = len;
1261     md->val[md->len - 1].padata_value.data = buf;
1262     return 0;
1263 }
1264 
1265 /*
1266  *
1267  */
1268 
1269 static void
log_as_req(krb5_context context,krb5_kdc_configuration * config,krb5_enctype cetype,krb5_enctype setype,const KDC_REQ_BODY * b)1270 log_as_req(krb5_context context,
1271 	   krb5_kdc_configuration *config,
1272 	   krb5_enctype cetype,
1273 	   krb5_enctype setype,
1274 	   const KDC_REQ_BODY *b)
1275 {
1276     krb5_error_code ret;
1277     struct rk_strpool *p;
1278     char *str;
1279     size_t i;
1280 
1281     p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
1282 
1283     for (i = 0; i < b->etype.len; i++) {
1284 	ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
1285 	if (ret == 0) {
1286 	    p = rk_strpoolprintf(p, "%s", str);
1287 	    free(str);
1288 	} else
1289 	    p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
1290 	if (p && i + 1 < b->etype.len)
1291 	    p = rk_strpoolprintf(p, ", ");
1292 	if (p == NULL) {
1293 	    kdc_log(context, config, 0, "out of memory");
1294 	    return;
1295 	}
1296     }
1297     if (p == NULL)
1298 	p = rk_strpoolprintf(p, "no encryption types");
1299 
1300     {
1301 	char *cet;
1302 	char *set;
1303 
1304 	ret = krb5_enctype_to_string(context, cetype, &cet);
1305 	if(ret == 0) {
1306 	    ret = krb5_enctype_to_string(context, setype, &set);
1307 	    if (ret == 0) {
1308 		p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
1309 		free(set);
1310 	    }
1311 	    free(cet);
1312 	}
1313 	if (ret != 0)
1314 	    p = rk_strpoolprintf(p, ", using enctypes %d/%d",
1315 				 cetype, setype);
1316     }
1317 
1318     str = rk_strpoolcollect(p);
1319     kdc_log(context, config, 0, "%s", str);
1320     free(str);
1321 
1322     {
1323 	char fixedstr[128];
1324 	unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
1325 		      fixedstr, sizeof(fixedstr));
1326 	if(*fixedstr)
1327 	    kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
1328     }
1329 }
1330 
1331 /*
1332  * verify the flags on `client' and `server', returning 0
1333  * if they are OK and generating an error messages and returning
1334  * and error code otherwise.
1335  */
1336 
1337 krb5_error_code
kdc_check_flags(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client_ex,const char * client_name,hdb_entry_ex * server_ex,const char * server_name,krb5_boolean is_as_req)1338 kdc_check_flags(krb5_context context,
1339 		krb5_kdc_configuration *config,
1340 		hdb_entry_ex *client_ex, const char *client_name,
1341 		hdb_entry_ex *server_ex, const char *server_name,
1342 		krb5_boolean is_as_req)
1343 {
1344     if(client_ex != NULL) {
1345 	hdb_entry *client = &client_ex->entry;
1346 
1347 	/* check client */
1348 	if (client->flags.locked_out) {
1349 	    kdc_log(context, config, 0,
1350 		    "Client (%s) is locked out", client_name);
1351 	    return KRB5KDC_ERR_POLICY;
1352 	}
1353 
1354 	if (client->flags.invalid) {
1355 	    kdc_log(context, config, 0,
1356 		    "Client (%s) has invalid bit set", client_name);
1357 	    return KRB5KDC_ERR_POLICY;
1358 	}
1359 
1360 	if(!client->flags.client){
1361 	    kdc_log(context, config, 0,
1362 		    "Principal may not act as client -- %s", client_name);
1363 	    return KRB5KDC_ERR_POLICY;
1364 	}
1365 
1366 	if (client->valid_start && *client->valid_start > kdc_time) {
1367 	    char starttime_str[100];
1368 	    krb5_format_time(context, *client->valid_start,
1369 			     starttime_str, sizeof(starttime_str), TRUE);
1370 	    kdc_log(context, config, 0,
1371 		    "Client not yet valid until %s -- %s",
1372 		    starttime_str, client_name);
1373 	    return KRB5KDC_ERR_CLIENT_NOTYET;
1374 	}
1375 
1376 	if (client->valid_end && *client->valid_end < kdc_time) {
1377 	    char endtime_str[100];
1378 	    krb5_format_time(context, *client->valid_end,
1379 			     endtime_str, sizeof(endtime_str), TRUE);
1380 	    kdc_log(context, config, 0,
1381 		    "Client expired at %s -- %s",
1382 		    endtime_str, client_name);
1383 	    return KRB5KDC_ERR_NAME_EXP;
1384 	}
1385 
1386 	if (client->flags.require_pwchange &&
1387 	    (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1388 	    kdc_log(context, config, 0,
1389 		    "Client's key must be changed -- %s", client_name);
1390 	    return KRB5KDC_ERR_KEY_EXPIRED;
1391 	}
1392 
1393 	if (client->pw_end && *client->pw_end < kdc_time
1394 	    && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
1395 	    char pwend_str[100];
1396 	    krb5_format_time(context, *client->pw_end,
1397 			     pwend_str, sizeof(pwend_str), TRUE);
1398 	    kdc_log(context, config, 0,
1399 		    "Client's key has expired at %s -- %s",
1400 		    pwend_str, client_name);
1401 	    return KRB5KDC_ERR_KEY_EXPIRED;
1402 	}
1403     }
1404 
1405     /* check server */
1406 
1407     if (server_ex != NULL) {
1408 	hdb_entry *server = &server_ex->entry;
1409 
1410 	if (server->flags.locked_out) {
1411 	    kdc_log(context, config, 0,
1412 		    "Client server locked out -- %s", server_name);
1413 	    return KRB5KDC_ERR_POLICY;
1414 	}
1415 	if (server->flags.invalid) {
1416 	    kdc_log(context, config, 0,
1417 		    "Server has invalid flag set -- %s", server_name);
1418 	    return KRB5KDC_ERR_POLICY;
1419 	}
1420 
1421 	if(!server->flags.server){
1422 	    kdc_log(context, config, 0,
1423 		    "Principal may not act as server -- %s", server_name);
1424 	    return KRB5KDC_ERR_POLICY;
1425 	}
1426 
1427 	if(!is_as_req && server->flags.initial) {
1428 	    kdc_log(context, config, 0,
1429 		    "AS-REQ is required for server -- %s", server_name);
1430 	    return KRB5KDC_ERR_POLICY;
1431 	}
1432 
1433 	if (server->valid_start && *server->valid_start > kdc_time) {
1434 	    char starttime_str[100];
1435 	    krb5_format_time(context, *server->valid_start,
1436 			     starttime_str, sizeof(starttime_str), TRUE);
1437 	    kdc_log(context, config, 0,
1438 		    "Server not yet valid until %s -- %s",
1439 		    starttime_str, server_name);
1440 	    return KRB5KDC_ERR_SERVICE_NOTYET;
1441 	}
1442 
1443 	if (server->valid_end && *server->valid_end < kdc_time) {
1444 	    char endtime_str[100];
1445 	    krb5_format_time(context, *server->valid_end,
1446 			     endtime_str, sizeof(endtime_str), TRUE);
1447 	    kdc_log(context, config, 0,
1448 		    "Server expired at %s -- %s",
1449 		    endtime_str, server_name);
1450 	    return KRB5KDC_ERR_SERVICE_EXP;
1451 	}
1452 
1453 	if (server->pw_end && *server->pw_end < kdc_time) {
1454 	    char pwend_str[100];
1455 	    krb5_format_time(context, *server->pw_end,
1456 			     pwend_str, sizeof(pwend_str), TRUE);
1457 	    kdc_log(context, config, 0,
1458 		    "Server's key has expired at -- %s",
1459 		    pwend_str, server_name);
1460 	    return KRB5KDC_ERR_KEY_EXPIRED;
1461 	}
1462     }
1463     return 0;
1464 }
1465 
1466 /*
1467  * Return TRUE if `from' is part of `addresses' taking into consideration
1468  * the configuration variables that tells us how strict we should be about
1469  * these checks
1470  */
1471 
1472 krb5_boolean
_kdc_check_addresses(krb5_context context,krb5_kdc_configuration * config,HostAddresses * addresses,const struct sockaddr * from)1473 _kdc_check_addresses(krb5_context context,
1474 		     krb5_kdc_configuration *config,
1475 		     HostAddresses *addresses, const struct sockaddr *from)
1476 {
1477     krb5_error_code ret;
1478     krb5_address addr;
1479     krb5_boolean result;
1480     krb5_boolean only_netbios = TRUE;
1481     size_t i;
1482 
1483     if(config->check_ticket_addresses == 0)
1484 	return TRUE;
1485 
1486     if(addresses == NULL)
1487 	return config->allow_null_ticket_addresses;
1488 
1489     for (i = 0; i < addresses->len; ++i) {
1490 	if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
1491 	    only_netbios = FALSE;
1492 	}
1493     }
1494 
1495     /* Windows sends it's netbios name, which I can only assume is
1496      * used for the 'allowed workstations' check.  This is painful,
1497      * but we still want to check IP addresses if they happen to be
1498      * present.
1499      */
1500 
1501     if(only_netbios)
1502 	return config->allow_null_ticket_addresses;
1503 
1504     ret = krb5_sockaddr2address (context, from, &addr);
1505     if(ret)
1506 	return FALSE;
1507 
1508     result = krb5_address_search(context, &addr, addresses);
1509     krb5_free_address (context, &addr);
1510     return result;
1511 }
1512 
1513 /*
1514  *
1515  */
1516 krb5_error_code
_kdc_check_anon_policy(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client,hdb_entry_ex * server)1517 _kdc_check_anon_policy (krb5_context context,
1518 			krb5_kdc_configuration *config,
1519 			hdb_entry_ex *client,
1520 			hdb_entry_ex *server)
1521 {
1522     if (!config->allow_anonymous){
1523 	kdc_log(context, config, 0,
1524 		"Request for anonymous ticket denied by local policy");
1525 	return KRB5KDC_ERR_POLICY;
1526     }
1527 
1528     return 0;
1529 }
1530 
1531 /*
1532  *
1533  */
1534 
1535 static krb5_boolean
send_pac_p(krb5_context context,KDC_REQ * req)1536 send_pac_p(krb5_context context, KDC_REQ *req)
1537 {
1538     krb5_error_code ret;
1539     PA_PAC_REQUEST pacreq;
1540     const PA_DATA *pa;
1541     int i = 0;
1542 
1543     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
1544     if (pa == NULL)
1545 	return TRUE;
1546 
1547     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
1548 				pa->padata_value.length,
1549 				&pacreq,
1550 				NULL);
1551     if (ret)
1552 	return TRUE;
1553     i = pacreq.include_pac;
1554     free_PA_PAC_REQUEST(&pacreq);
1555     if (i == 0)
1556 	return FALSE;
1557     return TRUE;
1558 }
1559 
1560 /*
1561  *
1562  */
1563 
1564 static krb5_error_code
generate_pac(kdc_request_t r,Key * skey)1565 generate_pac(kdc_request_t r, Key *skey)
1566 {
1567     krb5_error_code ret;
1568     krb5_pac p = NULL;
1569     krb5_data data;
1570 
1571     ret = _kdc_pac_generate(r->context, r->client, &p);
1572     if (ret) {
1573 	_kdc_r_log(r, 0, "PAC generation failed for -- %s",
1574 		   r->client_name);
1575 	return ret;
1576     }
1577     if (p == NULL)
1578 	return 0;
1579 
1580     ret = _krb5_pac_sign(r->context, p, r->et.authtime,
1581 			 r->client->entry.principal,
1582 			 &skey->key, /* Server key */
1583 			 &skey->key, /* FIXME: should be krbtgt key */
1584 			 &data);
1585     krb5_pac_free(r->context, p);
1586     if (ret) {
1587 	_kdc_r_log(r, 0, "PAC signing failed for -- %s",
1588 		   r->client_name);
1589 	return ret;
1590     }
1591 
1592     ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
1593 				      KRB5_AUTHDATA_WIN2K_PAC,
1594 				      &data);
1595     krb5_data_free(&data);
1596 
1597     return ret;
1598 }
1599 
1600 /*
1601  *
1602  */
1603 
1604 krb5_boolean
_kdc_is_anonymous(krb5_context context,krb5_const_principal principal)1605 _kdc_is_anonymous(krb5_context context, krb5_const_principal principal)
1606 {
1607     return krb5_principal_is_anonymous(context, principal, KRB5_ANON_MATCH_ANY);
1608 }
1609 
1610 static int
require_preauth_p(kdc_request_t r)1611 require_preauth_p(kdc_request_t r)
1612 {
1613     return r->config->require_preauth
1614 	|| r->client->entry.flags.require_preauth
1615 	|| r->server->entry.flags.require_preauth;
1616 }
1617 
1618 
1619 /*
1620  *
1621  */
1622 
1623 static krb5_error_code
add_enc_pa_rep(kdc_request_t r)1624 add_enc_pa_rep(kdc_request_t r)
1625 {
1626     krb5_error_code ret;
1627     krb5_crypto crypto;
1628     Checksum checksum;
1629     krb5_data cdata;
1630     size_t len;
1631 
1632     ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
1633     if (ret)
1634 	return ret;
1635 
1636     ret = krb5_create_checksum(r->context, crypto,
1637 			       KRB5_KU_AS_REQ, 0,
1638 			       r->request.data, r->request.length,
1639 			       &checksum);
1640     krb5_crypto_destroy(r->context, crypto);
1641     if (ret)
1642 	return ret;
1643 
1644     ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
1645 		       &checksum, &len, ret);
1646     free_Checksum(&checksum);
1647     if (ret)
1648 	return ret;
1649     heim_assert(cdata.length == len, "ASN.1 internal error");
1650 
1651     if (r->ek.encrypted_pa_data == NULL) {
1652 	ALLOC(r->ek.encrypted_pa_data);
1653 	if (r->ek.encrypted_pa_data == NULL)
1654 	    return ENOMEM;
1655     }
1656     ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1657 			  KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
1658     if (ret)
1659 	return ret;
1660 
1661     return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
1662 			   KRB5_PADATA_FX_FAST, NULL, 0);
1663 }
1664 
1665 /*
1666  *
1667  */
1668 
1669 krb5_error_code
_kdc_as_rep(kdc_request_t r,krb5_data * reply,const char * from,struct sockaddr * from_addr,int datagram_reply)1670 _kdc_as_rep(kdc_request_t r,
1671 	    krb5_data *reply,
1672 	    const char *from,
1673 	    struct sockaddr *from_addr,
1674 	    int datagram_reply)
1675 {
1676     krb5_context context = r->context;
1677     krb5_kdc_configuration *config = r->config;
1678     KDC_REQ *req = &r->req;
1679     KDC_REQ_BODY *b = NULL;
1680     AS_REP rep;
1681     KDCOptions f;
1682     krb5_enctype setype;
1683     krb5_error_code ret = 0;
1684     Key *skey;
1685     int found_pa = 0;
1686     int i, flags = HDB_F_FOR_AS_REQ;
1687     METHOD_DATA error_method;
1688     const PA_DATA *pa;
1689 
1690     memset(&rep, 0, sizeof(rep));
1691     error_method.len = 0;
1692     error_method.val = NULL;
1693 
1694     /*
1695      * Look for FAST armor and unwrap
1696      */
1697     ret = _kdc_fast_unwrap_request(r);
1698     if (ret) {
1699 	_kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
1700 	goto out;
1701     }
1702 
1703     b = &req->req_body;
1704     f = b->kdc_options;
1705 
1706     if (f.canonicalize)
1707 	flags |= HDB_F_CANON;
1708 
1709     if(b->sname == NULL){
1710 	ret = KRB5KRB_ERR_GENERIC;
1711 	_kdc_set_e_text(r, "No server in request");
1712     } else{
1713 	ret = _krb5_principalname2krb5_principal (context,
1714 						  &r->server_princ,
1715 						  *(b->sname),
1716 						  b->realm);
1717 	if (ret == 0)
1718 	    ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
1719     }
1720     if (ret) {
1721 	kdc_log(context, config, 0,
1722 		"AS-REQ malformed server name from %s", from);
1723 	goto out;
1724     }
1725     if(b->cname == NULL){
1726 	ret = KRB5KRB_ERR_GENERIC;
1727 	_kdc_set_e_text(r, "No client in request");
1728     } else {
1729 	ret = _krb5_principalname2krb5_principal (context,
1730 						  &r->client_princ,
1731 						  *(b->cname),
1732 						  b->realm);
1733 	if (ret)
1734 	    goto out;
1735 
1736 	ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
1737     }
1738     if (ret) {
1739 	kdc_log(context, config, 0,
1740 		"AS-REQ malformed client name from %s", from);
1741 	goto out;
1742     }
1743 
1744     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1745 	    r->client_name, from, r->server_name);
1746 
1747     /*
1748      *
1749      */
1750 
1751     if (_kdc_is_anonymous(context, r->client_princ) &&
1752 	!_kdc_is_anon_request(&r->req)) {
1753 	kdc_log(context, config, 0, "Anonymous client w/o anonymous flag");
1754 	ret = KRB5KDC_ERR_BADOPTION;
1755 	goto out;
1756     }
1757 
1758     /*
1759      *
1760      */
1761 
1762     ret = _kdc_db_fetch(context, config, r->client_princ,
1763 			HDB_F_GET_CLIENT | flags, NULL,
1764 			&r->clientdb, &r->client);
1765     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1766 	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
1767 		r->client_name);
1768 	goto out;
1769     } else if (ret == HDB_ERR_WRONG_REALM) {
1770 	char *fixed_client_name = NULL;
1771 
1772 	ret = krb5_unparse_name(context, r->client->entry.principal,
1773 				&fixed_client_name);
1774 	if (ret) {
1775 	    goto out;
1776 	}
1777 
1778 	kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
1779 		r->client_name, fixed_client_name);
1780 	free(fixed_client_name);
1781 
1782 	ret = _kdc_fast_mk_error(context, r,
1783 				 &error_method,
1784 				 r->armor_crypto,
1785 				 &req->req_body,
1786 				 KRB5_KDC_ERR_WRONG_REALM,
1787 				 NULL,
1788 				 r->server_princ,
1789 				 NULL,
1790 				 &r->client->entry.principal->realm,
1791 				 NULL, NULL,
1792 				 reply);
1793 	goto out;
1794     } else if(ret){
1795 	const char *msg = krb5_get_error_message(context, ret);
1796 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
1797 	krb5_free_error_message(context, msg);
1798 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1799 	goto out;
1800     }
1801     ret = _kdc_db_fetch(context, config, r->server_princ,
1802 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
1803 			NULL, NULL, &r->server);
1804     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1805 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
1806 		r->server_name);
1807 	goto out;
1808     } else if(ret){
1809 	const char *msg = krb5_get_error_message(context, ret);
1810 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
1811 	krb5_free_error_message(context, msg);
1812 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1813 	goto out;
1814     }
1815 
1816     /*
1817      * Select a session enctype from the list of the crypto system
1818      * supported enctypes that is supported by the client and is one of
1819      * the enctype of the enctype of the service (likely krbtgt).
1820      *
1821      * The latter is used as a hint of what enctypes all KDC support,
1822      * to make sure a newer version of KDC won't generate a session
1823      * enctype that an older version of a KDC in the same realm can't
1824      * decrypt.
1825      */
1826 
1827     ret = _kdc_find_etype(context,
1828 			  krb5_principal_is_krbtgt(context, r->server_princ) ?
1829 			  config->tgt_use_strongest_session_key :
1830 			  config->svc_use_strongest_session_key, FALSE,
1831 			  r->client, b->etype.val, b->etype.len, &r->sessionetype,
1832 			  NULL);
1833     if (ret) {
1834 	kdc_log(context, config, 0,
1835 		"Client (%s) from %s has no common enctypes with KDC "
1836 		"to use for the session key",
1837 		r->client_name, from);
1838 	goto out;
1839     }
1840 
1841     /*
1842      * Pre-auth processing
1843      */
1844 
1845     if(req->padata){
1846 	unsigned int n;
1847 
1848 	log_patypes(context, config, req->padata);
1849 
1850 	/* Check if preauth matching */
1851 
1852 	for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
1853 	    if (pat[n].validate == NULL)
1854 		continue;
1855 	    if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
1856 		continue;
1857 
1858 	    kdc_log(context, config, 5,
1859 		    "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
1860 	    i = 0;
1861 	    pa = _kdc_find_padata(req, &i, pat[n].type);
1862 	    if (pa) {
1863 		ret = pat[n].validate(r, pa);
1864 		if (ret != 0) {
1865 		    goto out;
1866 		}
1867 		kdc_log(context, config, 0,
1868 			"%s pre-authentication succeeded -- %s",
1869 			pat[n].name, r->client_name);
1870 		found_pa = 1;
1871 		r->et.flags.pre_authent = 1;
1872 	    }
1873 	}
1874     }
1875 
1876     if (found_pa == 0) {
1877 	Key *ckey = NULL;
1878 	size_t n;
1879 
1880 	for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
1881 	    if ((pat[n].flags & PA_ANNOUNCE) == 0)
1882 		continue;
1883 	    ret = krb5_padata_add(context, &error_method,
1884 				  pat[n].type, NULL, 0);
1885 	    if (ret)
1886 		goto out;
1887 	}
1888 
1889 	/*
1890 	 * If there is a client key, send ETYPE_INFO{,2}
1891 	 */
1892 	ret = _kdc_find_etype(context,
1893 			      config->preauth_use_strongest_session_key, TRUE,
1894 			      r->client, b->etype.val, b->etype.len, NULL, &ckey);
1895 	if (ret == 0) {
1896 
1897 	    /*
1898 	     * RFC4120 requires:
1899 	     * - If the client only knows about old enctypes, then send
1900 	     *   both info replies (we send 'info' first in the list).
1901 	     * - If the client is 'modern', because it knows about 'new'
1902 	     *   enctype types, then only send the 'info2' reply.
1903 	     *
1904 	     * Before we send the full list of etype-info data, we pick
1905 	     * the client key we would have used anyway below, just pick
1906 	     * that instead.
1907 	     */
1908 
1909 	    if (older_enctype(ckey->key.keytype)) {
1910 		ret = get_pa_etype_info(context, config,
1911 					&error_method, ckey);
1912 		if (ret)
1913 		    goto out;
1914 	    }
1915 	    ret = get_pa_etype_info2(context, config,
1916 				     &error_method, ckey);
1917 	    if (ret)
1918 		goto out;
1919 	}
1920 
1921 	/*
1922 	 * send requre preauth is its required or anon is requested,
1923 	 * anon is today only allowed via preauth mechanisms.
1924 	 */
1925 	if (require_preauth_p(r) || _kdc_is_anon_request(&r->req)) {
1926 	    ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1927 	    _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
1928 	    goto out;
1929 	}
1930 
1931 	if (ckey == NULL) {
1932 	    ret = KRB5KDC_ERR_CLIENT_NOTYET;
1933 	    _kdc_set_e_text(r, "Doesn't have a client key available");
1934 	    goto out;
1935 	}
1936 	krb5_free_keyblock_contents(r->context,  &r->reply_key);
1937 	ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
1938 	if (ret)
1939 	    goto out;
1940     }
1941 
1942     if (r->clientdb->hdb_auth_status) {
1943 	r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
1944 				     HDB_AUTH_SUCCESS);
1945     }
1946 
1947     /*
1948      * Verify flags after the user been required to prove its identity
1949      * with in a preauth mech.
1950      */
1951 
1952     ret = _kdc_check_access(context, config, r->client, r->client_name,
1953 			    r->server, r->server_name,
1954 			    req, &error_method);
1955     if(ret)
1956 	goto out;
1957 
1958     if (_kdc_is_anon_request(&r->req)) {
1959 	ret = _kdc_check_anon_policy(context, config, r->client, r->server);
1960 	if (ret) {
1961 	    _kdc_set_e_text(r, "Anonymous ticket requests are disabled");
1962 	    goto out;
1963 	}
1964 
1965 	r->et.flags.anonymous = 1;
1966     }
1967 
1968     /*
1969      * Select the best encryption type for the KDC with out regard to
1970      * the client since the client never needs to read that data.
1971      */
1972 
1973     ret = _kdc_get_preferred_key(context, config,
1974 				 r->server, r->server_name,
1975 				 &setype, &skey);
1976     if(ret)
1977 	goto out;
1978 
1979     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) {
1980 	ret = KRB5KDC_ERR_BADOPTION;
1981 	_kdc_set_e_text(r, "Bad KDC options");
1982 	goto out;
1983     }
1984 
1985     /*
1986      * Build reply
1987      */
1988 
1989     rep.pvno = 5;
1990     rep.msg_type = krb_as_rep;
1991 
1992     if (!config->historical_anon_realm &&
1993         _kdc_is_anonymous(context, r->client_princ)) {
1994 	Realm anon_realm = KRB5_ANON_REALM;
1995 	ret = copy_Realm(&anon_realm, &rep.crealm);
1996     } else
1997 	ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
1998     if (ret)
1999 	goto out;
2000     if (r->et.flags.anonymous)
2001 	ret = _kdc_make_anonymous_principalname(&rep.cname);
2002     else
2003         ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
2004     if (ret)
2005 	goto out;
2006 
2007     rep.ticket.tkt_vno = 5;
2008     ret = copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
2009     if (ret)
2010 	goto out;
2011     _krb5_principal2principalname(&rep.ticket.sname,
2012 				  r->server->entry.principal);
2013     /* java 1.6 expects the name to be the same type, lets allow that
2014      * uncomplicated name-types. */
2015 #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
2016     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
2017 	rep.ticket.sname.name_type = b->sname->name_type;
2018 #undef CNT
2019 
2020     r->et.flags.initial = 1;
2021     if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
2022 	r->et.flags.forwardable = f.forwardable;
2023     else if (f.forwardable) {
2024 	_kdc_set_e_text(r, "Ticket may not be forwardable");
2025 	ret = KRB5KDC_ERR_POLICY;
2026 	goto out;
2027     }
2028     if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
2029 	r->et.flags.proxiable = f.proxiable;
2030     else if (f.proxiable) {
2031 	_kdc_set_e_text(r, "Ticket may not be proxiable");
2032 	ret = KRB5KDC_ERR_POLICY;
2033 	goto out;
2034     }
2035     if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
2036 	r->et.flags.may_postdate = f.allow_postdate;
2037     else if (f.allow_postdate){
2038 	_kdc_set_e_text(r, "Ticket may not be postdate");
2039 	ret = KRB5KDC_ERR_POLICY;
2040 	goto out;
2041     }
2042 
2043     /* check for valid set of addresses */
2044     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
2045 	_kdc_set_e_text(r, "Bad address list in requested");
2046 	ret = KRB5KRB_AP_ERR_BADADDR;
2047 	goto out;
2048     }
2049 
2050     ret = copy_PrincipalName(&rep.cname, &r->et.cname);
2051     if (ret)
2052 	goto out;
2053     ret = copy_Realm(&rep.crealm, &r->et.crealm);
2054     if (ret)
2055 	goto out;
2056 
2057     {
2058 	time_t start;
2059 	time_t t;
2060 
2061 	start = r->et.authtime = kdc_time;
2062 
2063 	if(f.postdated && req->req_body.from){
2064 	    ALLOC(r->et.starttime);
2065 	    start = *r->et.starttime = *req->req_body.from;
2066 	    r->et.flags.invalid = 1;
2067 	    r->et.flags.postdated = 1; /* XXX ??? */
2068 	}
2069 	_kdc_fix_time(&b->till);
2070 	t = *b->till;
2071 
2072 	/* be careful not overflowing */
2073 
2074 	if(r->client->entry.max_life)
2075 	    t = start + min(t - start, *r->client->entry.max_life);
2076 	if(r->server->entry.max_life)
2077 	    t = start + min(t - start, *r->server->entry.max_life);
2078 #if 0
2079 	t = min(t, start + realm->max_life);
2080 #endif
2081 	r->et.endtime = t;
2082 	if(f.renewable_ok && r->et.endtime < *b->till){
2083 	    f.renewable = 1;
2084 	    if(b->rtime == NULL){
2085 		ALLOC(b->rtime);
2086 		*b->rtime = 0;
2087 	    }
2088 	    if(*b->rtime < *b->till)
2089 		*b->rtime = *b->till;
2090 	}
2091 	if(f.renewable && b->rtime){
2092 	    t = *b->rtime;
2093 	    if(t == 0)
2094 		t = MAX_TIME;
2095 	    if(r->client->entry.max_renew)
2096 		t = start + min(t - start, *r->client->entry.max_renew);
2097 	    if(r->server->entry.max_renew)
2098 		t = start + min(t - start, *r->server->entry.max_renew);
2099 #if 0
2100 	    t = min(t, start + realm->max_renew);
2101 #endif
2102 	    ALLOC(r->et.renew_till);
2103 	    *r->et.renew_till = t;
2104 	    r->et.flags.renewable = 1;
2105 	}
2106     }
2107 
2108     if(b->addresses){
2109 	ALLOC(r->et.caddr);
2110 	copy_HostAddresses(b->addresses, r->et.caddr);
2111     }
2112 
2113     r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
2114     krb5_data_zero(&r->et.transited.contents);
2115 
2116     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
2117      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
2118      * incapable of correctly decoding SEQUENCE OF's of zero length.
2119      *
2120      * To fix this, always send at least one no-op last_req
2121      *
2122      * If there's a pw_end or valid_end we will use that,
2123      * otherwise just a dummy lr.
2124      */
2125     r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
2126     if (r->ek.last_req.val == NULL) {
2127 	ret = ENOMEM;
2128 	goto out;
2129     }
2130     r->ek.last_req.len = 0;
2131     if (r->client->entry.pw_end
2132 	&& (config->kdc_warn_pwexpire == 0
2133 	    || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
2134 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
2135 	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
2136 	++r->ek.last_req.len;
2137     }
2138     if (r->client->entry.valid_end) {
2139 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
2140 	r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
2141 	++r->ek.last_req.len;
2142     }
2143     if (r->ek.last_req.len == 0) {
2144 	r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_NONE;
2145 	r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
2146 	++r->ek.last_req.len;
2147     }
2148     r->ek.nonce = b->nonce;
2149     if (r->client->entry.valid_end || r->client->entry.pw_end) {
2150 	ALLOC(r->ek.key_expiration);
2151 	if (r->client->entry.valid_end) {
2152 	    if (r->client->entry.pw_end)
2153 		*r->ek.key_expiration = min(*r->client->entry.valid_end,
2154 					 *r->client->entry.pw_end);
2155 	    else
2156 		*r->ek.key_expiration = *r->client->entry.valid_end;
2157 	} else
2158 	    *r->ek.key_expiration = *r->client->entry.pw_end;
2159     } else
2160 	r->ek.key_expiration = NULL;
2161     r->ek.flags = r->et.flags;
2162     r->ek.authtime = r->et.authtime;
2163     if (r->et.starttime) {
2164 	ALLOC(r->ek.starttime);
2165 	*r->ek.starttime = *r->et.starttime;
2166     }
2167     r->ek.endtime = r->et.endtime;
2168     if (r->et.renew_till) {
2169 	ALLOC(r->ek.renew_till);
2170 	*r->ek.renew_till = *r->et.renew_till;
2171     }
2172     ret = copy_Realm(&rep.ticket.realm, &r->ek.srealm);
2173     if (ret)
2174 	goto out;
2175     ret = copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
2176     if (ret)
2177 	goto out;
2178     if(r->et.caddr){
2179 	ALLOC(r->ek.caddr);
2180 	copy_HostAddresses(r->et.caddr, r->ek.caddr);
2181     }
2182 
2183     /*
2184      * Check and session and reply keys
2185      */
2186 
2187     if (r->session_key.keytype == ETYPE_NULL) {
2188 	ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
2189 	if (ret)
2190 	    goto out;
2191     }
2192 
2193     if (r->reply_key.keytype == ETYPE_NULL) {
2194 	_kdc_set_e_text(r, "Client have no reply key");
2195 	ret = KRB5KDC_ERR_CLIENT_NOTYET;
2196 	goto out;
2197     }
2198 
2199     ret = copy_EncryptionKey(&r->session_key, &r->et.key);
2200     if (ret)
2201 	goto out;
2202 
2203     ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
2204     if (ret)
2205 	goto out;
2206 
2207     if (r->outpadata.len) {
2208 
2209 	ALLOC(rep.padata);
2210 	if (rep.padata == NULL) {
2211 	    ret = ENOMEM;
2212 	    goto out;
2213 	}
2214 	ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
2215 	if (ret)
2216 	    goto out;
2217     }
2218 
2219     /* Add the PAC */
2220     if (send_pac_p(context, req) && !r->et.flags.anonymous) {
2221 	generate_pac(r, skey);
2222     }
2223 
2224     _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
2225 		       r->et.endtime, r->et.renew_till);
2226 
2227     {
2228 	krb5_principal client_principal;
2229 
2230 	ret = _krb5_principalname2krb5_principal(context, &client_principal,
2231 						 rep.cname, rep.crealm);
2232 	if (ret)
2233 	    goto out;
2234 
2235 	/* do this as the last thing since this signs the EncTicketPart */
2236 	ret = _kdc_add_KRB5SignedPath(context,
2237 				      config,
2238 				      r->server,
2239 				      setype,
2240 				      client_principal,
2241 				      NULL,
2242 				      NULL,
2243 				      &r->et);
2244 	krb5_free_principal(context, client_principal);
2245 	if (ret)
2246 	    goto out;
2247     }
2248 
2249     log_as_req(context, config, r->reply_key.keytype, setype, b);
2250 
2251     /*
2252      * We always say we support FAST/enc-pa-rep
2253      */
2254 
2255     r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
2256 
2257     /*
2258      * Add REQ_ENC_PA_REP if client supports it
2259      */
2260 
2261     i = 0;
2262     pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
2263     if (pa) {
2264 
2265 	ret = add_enc_pa_rep(r);
2266 	if (ret) {
2267 	    const char *msg = krb5_get_error_message(r->context, ret);
2268 	    _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
2269 	    krb5_free_error_message(r->context, msg);
2270 	    goto out;
2271 	}
2272     }
2273 
2274     /*
2275      *
2276      */
2277 
2278     ret = _kdc_encode_reply(context, config,
2279 			    r->armor_crypto, req->req_body.nonce,
2280 			    &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
2281 			    &skey->key, r->client->entry.kvno,
2282 			    &r->reply_key, 0, &r->e_text, reply);
2283     if (ret)
2284 	goto out;
2285 
2286     /*
2287      * Check if message too large
2288      */
2289     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
2290 	krb5_data_free(reply);
2291 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2292 	_kdc_set_e_text(r, "Reply packet too large");
2293     }
2294 
2295 out:
2296     free_AS_REP(&rep);
2297 
2298     /*
2299      * In case of a non proxy error, build an error message.
2300      */
2301     if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
2302 	ret = _kdc_fast_mk_error(context, r,
2303 				 &error_method,
2304 				 r->armor_crypto,
2305 				 &req->req_body,
2306 				 ret, r->e_text,
2307 				 r->server_princ,
2308 				 r->client_princ ?
2309                                      &r->client_princ->name : NULL,
2310 				 r->client_princ ?
2311                                      &r->client_princ->realm : NULL,
2312 				 NULL, NULL,
2313 				 reply);
2314 	if (ret)
2315 	    goto out2;
2316     }
2317 out2:
2318     free_EncTicketPart(&r->et);
2319     free_EncKDCRepPart(&r->ek);
2320     free_KDCFastState(&r->fast);
2321 
2322     if (error_method.len)
2323 	free_METHOD_DATA(&error_method);
2324     if (r->outpadata.len)
2325 	free_METHOD_DATA(&r->outpadata);
2326     if (r->client_princ) {
2327 	krb5_free_principal(context, r->client_princ);
2328 	r->client_princ = NULL;
2329     }
2330     if (r->client_name) {
2331 	free(r->client_name);
2332 	r->client_name = NULL;
2333     }
2334     if (r->server_princ){
2335 	krb5_free_principal(context, r->server_princ);
2336 	r->server_princ = NULL;
2337     }
2338     if (r->server_name) {
2339 	free(r->server_name);
2340 	r->server_name = NULL;
2341     }
2342     if (r->client)
2343 	_kdc_free_ent(context, r->client);
2344     if (r->server)
2345 	_kdc_free_ent(context, r->server);
2346     if (r->armor_crypto) {
2347 	krb5_crypto_destroy(r->context, r->armor_crypto);
2348 	r->armor_crypto = NULL;
2349     }
2350     krb5_free_keyblock_contents(r->context, &r->reply_key);
2351     krb5_free_keyblock_contents(r->context, &r->session_key);
2352     return ret;
2353 }
2354 
2355 /*
2356  * Add the AuthorizationData `data´ of `type´ to the last element in
2357  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
2358  */
2359 
2360 krb5_error_code
_kdc_tkt_add_if_relevant_ad(krb5_context context,EncTicketPart * tkt,int type,const krb5_data * data)2361 _kdc_tkt_add_if_relevant_ad(krb5_context context,
2362 			    EncTicketPart *tkt,
2363 			    int type,
2364 			    const krb5_data *data)
2365 {
2366     krb5_error_code ret;
2367     size_t size = 0;
2368 
2369     if (tkt->authorization_data == NULL) {
2370 	tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
2371 	if (tkt->authorization_data == NULL) {
2372 	    krb5_set_error_message(context, ENOMEM, "out of memory");
2373 	    return ENOMEM;
2374 	}
2375     }
2376 
2377     /* add the entry to the last element */
2378     {
2379 	AuthorizationData ad = { 0, NULL };
2380 	AuthorizationDataElement ade;
2381 
2382 	ade.ad_type = type;
2383 	ade.ad_data = *data;
2384 
2385 	ret = add_AuthorizationData(&ad, &ade);
2386 	if (ret) {
2387 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
2388 	    return ret;
2389 	}
2390 
2391 	ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
2392 
2393 	ASN1_MALLOC_ENCODE(AuthorizationData,
2394 			   ade.ad_data.data, ade.ad_data.length,
2395 			   &ad, &size, ret);
2396 	free_AuthorizationData(&ad);
2397 	if (ret) {
2398 	    krb5_set_error_message(context, ret, "ASN.1 encode of "
2399 				   "AuthorizationData failed");
2400 	    return ret;
2401 	}
2402 	if (ade.ad_data.length != size)
2403 	    krb5_abortx(context, "internal asn.1 encoder error");
2404 
2405 	ret = add_AuthorizationData(tkt->authorization_data, &ade);
2406 	der_free_octet_string(&ade.ad_data);
2407 	if (ret) {
2408 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
2409 	    return ret;
2410 	}
2411     }
2412 
2413     return 0;
2414 }
2415