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