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