xref: /freebsd/crypto/heimdal/kdc/kerberos5.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2ae771770SStanislav Sedov  * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "kdc_locl.h"
35b528cefcSMark Murray 
36b528cefcSMark Murray #define MAX_TIME ((time_t)((1U << 31) - 1))
37b528cefcSMark Murray 
38c19800e8SDoug Rabson void
_kdc_fix_time(time_t ** t)39c19800e8SDoug Rabson _kdc_fix_time(time_t **t)
40b528cefcSMark Murray {
41b528cefcSMark Murray     if(*t == NULL){
42b528cefcSMark Murray 	ALLOC(*t);
43b528cefcSMark Murray 	**t = MAX_TIME;
44b528cefcSMark Murray     }
45b528cefcSMark Murray     if(**t == 0) **t = MAX_TIME; /* fix for old clients */
46b528cefcSMark Murray }
47b528cefcSMark Murray 
48c19800e8SDoug Rabson static int
realloc_method_data(METHOD_DATA * md)49c19800e8SDoug Rabson realloc_method_data(METHOD_DATA *md)
50c19800e8SDoug Rabson {
51c19800e8SDoug Rabson     PA_DATA *pa;
52c19800e8SDoug Rabson     pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
53c19800e8SDoug Rabson     if(pa == NULL)
54c19800e8SDoug Rabson 	return ENOMEM;
55c19800e8SDoug Rabson     md->val = pa;
56c19800e8SDoug Rabson     md->len++;
57c19800e8SDoug Rabson     return 0;
58c19800e8SDoug Rabson }
59c19800e8SDoug Rabson 
60b528cefcSMark Murray static void
set_salt_padata(METHOD_DATA * md,Salt * salt)61c19800e8SDoug Rabson set_salt_padata(METHOD_DATA *md, Salt *salt)
62b528cefcSMark Murray {
63b528cefcSMark Murray     if (salt) {
64c19800e8SDoug Rabson        realloc_method_data(md);
65c19800e8SDoug Rabson        md->val[md->len - 1].padata_type = salt->type;
66c19800e8SDoug Rabson        der_copy_octet_string(&salt->salt,
67c19800e8SDoug Rabson                              &md->val[md->len - 1].padata_value);
68b528cefcSMark Murray     }
69b528cefcSMark Murray }
70b528cefcSMark Murray 
71c19800e8SDoug Rabson const PA_DATA*
_kdc_find_padata(const KDC_REQ * req,int * start,int type)72c19800e8SDoug Rabson _kdc_find_padata(const KDC_REQ *req, int *start, int type)
73b528cefcSMark Murray {
74c19800e8SDoug Rabson     if (req->padata == NULL)
75c19800e8SDoug Rabson 	return NULL;
76c19800e8SDoug Rabson 
77ae771770SStanislav Sedov     while((size_t)*start < req->padata->len){
78b528cefcSMark Murray 	(*start)++;
79ae771770SStanislav Sedov 	if(req->padata->val[*start - 1].padata_type == (unsigned)type)
80b528cefcSMark Murray 	    return &req->padata->val[*start - 1];
81b528cefcSMark Murray     }
82b528cefcSMark Murray     return NULL;
83b528cefcSMark Murray }
84b528cefcSMark Murray 
855e9cd1aeSAssar Westerlund /*
86ae771770SStanislav Sedov  * This is a hack to allow predefined weak services, like afs to
87ae771770SStanislav Sedov  * still use weak types
88ae771770SStanislav Sedov  */
89ae771770SStanislav Sedov 
90ae771770SStanislav Sedov krb5_boolean
_kdc_is_weak_exception(krb5_principal principal,krb5_enctype etype)91ae771770SStanislav Sedov _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
92ae771770SStanislav Sedov {
93ae771770SStanislav Sedov     if (principal->name.name_string.len > 0 &&
94ae771770SStanislav Sedov 	strcmp(principal->name.name_string.val[0], "afs") == 0 &&
95ae771770SStanislav Sedov 	(etype == ETYPE_DES_CBC_CRC
96ae771770SStanislav Sedov 	 || etype == ETYPE_DES_CBC_MD4
97ae771770SStanislav Sedov 	 || etype == ETYPE_DES_CBC_MD5))
98ae771770SStanislav Sedov 	return TRUE;
99ae771770SStanislav Sedov     return FALSE;
100ae771770SStanislav Sedov }
101ae771770SStanislav Sedov 
102ae771770SStanislav Sedov 
103ae771770SStanislav Sedov /*
104c19800e8SDoug Rabson  * Detect if `key' is the using the the precomputed `default_salt'.
105c19800e8SDoug Rabson  */
106c19800e8SDoug Rabson 
107c19800e8SDoug Rabson static krb5_boolean
is_default_salt_p(const krb5_salt * default_salt,const Key * key)108c19800e8SDoug Rabson is_default_salt_p(const krb5_salt *default_salt, const Key *key)
109c19800e8SDoug Rabson {
110c19800e8SDoug Rabson     if (key->salt == NULL)
111c19800e8SDoug Rabson 	return TRUE;
112c19800e8SDoug Rabson     if (default_salt->salttype != key->salt->type)
113c19800e8SDoug Rabson 	return FALSE;
114c19800e8SDoug Rabson     if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
115c19800e8SDoug Rabson 	return FALSE;
116c19800e8SDoug Rabson     return TRUE;
117c19800e8SDoug Rabson }
118c19800e8SDoug Rabson 
119c19800e8SDoug Rabson /*
1205e9cd1aeSAssar Westerlund  * return the first appropriate key of `princ' in `ret_key'.  Look for
1215e9cd1aeSAssar Westerlund  * all the etypes in (`etypes', `len'), stopping as soon as we find
1225e9cd1aeSAssar Westerlund  * one, but preferring one that has default salt
1235e9cd1aeSAssar Westerlund  */
124b528cefcSMark Murray 
125c19800e8SDoug Rabson krb5_error_code
_kdc_find_etype(krb5_context context,krb5_boolean use_strongest_session_key,krb5_boolean is_preauth,hdb_entry_ex * princ,krb5_enctype * etypes,unsigned len,krb5_enctype * ret_enctype,Key ** ret_key)126ae771770SStanislav Sedov _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
127ae771770SStanislav Sedov 		krb5_boolean is_preauth, hdb_entry_ex *princ,
128c19800e8SDoug Rabson 		krb5_enctype *etypes, unsigned len,
129ae771770SStanislav Sedov 		krb5_enctype *ret_enctype, Key **ret_key)
130b528cefcSMark Murray {
131ae771770SStanislav Sedov     krb5_error_code ret;
132c19800e8SDoug Rabson     krb5_salt def_salt;
133ae771770SStanislav Sedov     krb5_enctype enctype = ETYPE_NULL;
134ae771770SStanislav Sedov     Key *key;
135ae771770SStanislav Sedov     int i;
136c19800e8SDoug Rabson 
137ae771770SStanislav Sedov     /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
138ae771770SStanislav Sedov     ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
139ae771770SStanislav Sedov     if (ret)
140ae771770SStanislav Sedov 	return ret;
141b528cefcSMark Murray 
142ae771770SStanislav Sedov     ret = KRB5KDC_ERR_ETYPE_NOSUPP;
143b528cefcSMark Murray 
144ae771770SStanislav Sedov     if (use_strongest_session_key) {
145ae771770SStanislav Sedov 	const krb5_enctype *p;
146ae771770SStanislav Sedov 	krb5_enctype clientbest = ETYPE_NULL;
147ae771770SStanislav Sedov 	int j;
148ae771770SStanislav Sedov 
149ae771770SStanislav Sedov 	/*
150ae771770SStanislav Sedov 	 * Pick the strongest key that the KDC, target service, and
151ae771770SStanislav Sedov 	 * client all support, using the local cryptosystem enctype
152ae771770SStanislav Sedov 	 * list in strongest-to-weakest order to drive the search.
153ae771770SStanislav Sedov 	 *
154ae771770SStanislav Sedov 	 * This is not what RFC4120 says to do, but it encourages
155ae771770SStanislav Sedov 	 * adoption of stronger enctypes.  This doesn't play well with
156ae771770SStanislav Sedov 	 * clients that have multiple Kerberos client implementations
157ae771770SStanislav Sedov 	 * available with different supported enctype lists.
158ae771770SStanislav Sedov 	 */
159ae771770SStanislav Sedov 
160ae771770SStanislav Sedov 	/* drive the search with local supported enctypes list */
161ae771770SStanislav Sedov 	p = krb5_kerberos_enctypes(context);
162ae771770SStanislav Sedov 	for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) {
163ae771770SStanislav Sedov 	    if (krb5_enctype_valid(context, p[i]) != 0)
164ae771770SStanislav Sedov 		continue;
165ae771770SStanislav Sedov 
166ae771770SStanislav Sedov 	    /* check that the client supports it too */
167ae771770SStanislav Sedov 	    for (j = 0; j < len && enctype == ETYPE_NULL; j++) {
168ae771770SStanislav Sedov 		if (p[i] != etypes[j])
169ae771770SStanislav Sedov 		    continue;
170ae771770SStanislav Sedov 		/* save best of union of { client, crypto system } */
171ae771770SStanislav Sedov 		if (clientbest == ETYPE_NULL)
172ae771770SStanislav Sedov 		    clientbest = p[i];
173ae771770SStanislav Sedov 		/* check target princ support */
174ae771770SStanislav Sedov 		ret = hdb_enctype2key(context, &princ->entry, p[i], &key);
175ae771770SStanislav Sedov 		if (ret)
176ae771770SStanislav Sedov 		    continue;
177ae771770SStanislav Sedov 		if (is_preauth && !is_default_salt_p(&def_salt, key))
178ae771770SStanislav Sedov 		    continue;
179ae771770SStanislav Sedov 		enctype = p[i];
180ae771770SStanislav Sedov 	    }
181ae771770SStanislav Sedov 	}
182ae771770SStanislav Sedov 	if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL)
183ae771770SStanislav Sedov 	    enctype = clientbest;
184ae771770SStanislav Sedov 	else if (enctype == ETYPE_NULL)
185ae771770SStanislav Sedov 	    ret = KRB5KDC_ERR_ETYPE_NOSUPP;
186ae771770SStanislav Sedov 	if (ret == 0 && ret_enctype != NULL)
187ae771770SStanislav Sedov 	    *ret_enctype = enctype;
188ae771770SStanislav Sedov 	if (ret == 0 && ret_key != NULL)
189ae771770SStanislav Sedov 	    *ret_key = key;
190ae771770SStanislav Sedov     } else {
191ae771770SStanislav Sedov 	/*
192ae771770SStanislav Sedov 	 * Pick the first key from the client's enctype list that is
193ae771770SStanislav Sedov 	 * supported by the cryptosystem and by the given principal.
194ae771770SStanislav Sedov 	 *
195ae771770SStanislav Sedov 	 * RFC4120 says we SHOULD pick the first _strong_ key from the
196ae771770SStanislav Sedov 	 * client's list... not the first key...  If the admin disallows
197ae771770SStanislav Sedov 	 * weak enctypes in krb5.conf and selects this key selection
198ae771770SStanislav Sedov 	 * algorithm, then we get exactly what RFC4120 says.
199ae771770SStanislav Sedov 	 */
200ae771770SStanislav Sedov 	for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) {
201ae771770SStanislav Sedov 
202ae771770SStanislav Sedov 	    if (krb5_enctype_valid(context, etypes[i]) != 0 &&
203ae771770SStanislav Sedov 		!_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
204c19800e8SDoug Rabson 		continue;
205c19800e8SDoug Rabson 
206c19800e8SDoug Rabson 	    while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
2075e9cd1aeSAssar Westerlund 		if (key->key.keyvalue.length == 0) {
208b528cefcSMark Murray 		    ret = KRB5KDC_ERR_NULL_KEY;
2095e9cd1aeSAssar Westerlund 		    continue;
2105e9cd1aeSAssar Westerlund 		}
211ae771770SStanislav Sedov 		if (ret_key != NULL)
2125e9cd1aeSAssar Westerlund 		    *ret_key = key;
213ae771770SStanislav Sedov 		if (ret_enctype != NULL)
214ae771770SStanislav Sedov 		    *ret_enctype = etypes[i];
2155e9cd1aeSAssar Westerlund 		ret = 0;
216ae771770SStanislav Sedov 		if (is_preauth && is_default_salt_p(&def_salt, key))
217ae771770SStanislav Sedov 		    goto out;
218b528cefcSMark Murray 	    }
219b528cefcSMark Murray 	}
220c19800e8SDoug Rabson     }
221ae771770SStanislav Sedov 
222ae771770SStanislav Sedov out:
223c19800e8SDoug Rabson     krb5_free_salt (context, def_salt);
224b528cefcSMark Murray     return ret;
225b528cefcSMark Murray }
226b528cefcSMark Murray 
227c19800e8SDoug Rabson krb5_error_code
_kdc_make_anonymous_principalname(PrincipalName * pn)228c19800e8SDoug Rabson _kdc_make_anonymous_principalname (PrincipalName *pn)
2295e9cd1aeSAssar Westerlund {
2305e9cd1aeSAssar Westerlund     pn->name_type = KRB5_NT_PRINCIPAL;
2315e9cd1aeSAssar Westerlund     pn->name_string.len = 1;
2325e9cd1aeSAssar Westerlund     pn->name_string.val = malloc(sizeof(*pn->name_string.val));
2335e9cd1aeSAssar Westerlund     if (pn->name_string.val == NULL)
2345e9cd1aeSAssar Westerlund 	return ENOMEM;
2355e9cd1aeSAssar Westerlund     pn->name_string.val[0] = strdup("anonymous");
2365e9cd1aeSAssar Westerlund     if (pn->name_string.val[0] == NULL) {
2375e9cd1aeSAssar Westerlund 	free(pn->name_string.val);
2385e9cd1aeSAssar Westerlund 	pn->name_string.val = NULL;
2395e9cd1aeSAssar Westerlund 	return ENOMEM;
2405e9cd1aeSAssar Westerlund     }
2415e9cd1aeSAssar Westerlund     return 0;
2425e9cd1aeSAssar Westerlund }
243b528cefcSMark Murray 
244c19800e8SDoug Rabson void
_kdc_log_timestamp(krb5_context context,krb5_kdc_configuration * config,const char * type,KerberosTime authtime,KerberosTime * starttime,KerberosTime endtime,KerberosTime * renew_till)245c19800e8SDoug Rabson _kdc_log_timestamp(krb5_context context,
246c19800e8SDoug Rabson 		   krb5_kdc_configuration *config,
247c19800e8SDoug Rabson 		   const char *type,
248c19800e8SDoug Rabson 		   KerberosTime authtime, KerberosTime *starttime,
249c19800e8SDoug Rabson 		   KerberosTime endtime, KerberosTime *renew_till)
250c19800e8SDoug Rabson {
251c19800e8SDoug Rabson     char authtime_str[100], starttime_str[100],
252c19800e8SDoug Rabson 	endtime_str[100], renewtime_str[100];
253c19800e8SDoug Rabson 
254c19800e8SDoug Rabson     krb5_format_time(context, authtime,
255c19800e8SDoug Rabson 		     authtime_str, sizeof(authtime_str), TRUE);
256c19800e8SDoug Rabson     if (starttime)
257c19800e8SDoug Rabson 	krb5_format_time(context, *starttime,
258c19800e8SDoug Rabson 			 starttime_str, sizeof(starttime_str), TRUE);
259c19800e8SDoug Rabson     else
260c19800e8SDoug Rabson 	strlcpy(starttime_str, "unset", sizeof(starttime_str));
261c19800e8SDoug Rabson     krb5_format_time(context, endtime,
262c19800e8SDoug Rabson 		     endtime_str, sizeof(endtime_str), TRUE);
263c19800e8SDoug Rabson     if (renew_till)
264c19800e8SDoug Rabson 	krb5_format_time(context, *renew_till,
265c19800e8SDoug Rabson 			 renewtime_str, sizeof(renewtime_str), TRUE);
266c19800e8SDoug Rabson     else
267c19800e8SDoug Rabson 	strlcpy(renewtime_str, "unset", sizeof(renewtime_str));
268c19800e8SDoug Rabson 
269c19800e8SDoug Rabson     kdc_log(context, config, 5,
270c19800e8SDoug Rabson 	    "%s authtime: %s starttime: %s endtime: %s renew till: %s",
271c19800e8SDoug Rabson 	    type, authtime_str, starttime_str, endtime_str, renewtime_str);
272c19800e8SDoug Rabson }
273c19800e8SDoug Rabson 
274c19800e8SDoug Rabson static void
log_patypes(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * padata)275c19800e8SDoug Rabson log_patypes(krb5_context context,
276c19800e8SDoug Rabson 	    krb5_kdc_configuration *config,
277c19800e8SDoug Rabson 	    METHOD_DATA *padata)
278c19800e8SDoug Rabson {
279c19800e8SDoug Rabson     struct rk_strpool *p = NULL;
280c19800e8SDoug Rabson     char *str;
281ae771770SStanislav Sedov     size_t i;
282c19800e8SDoug Rabson 
283c19800e8SDoug Rabson     for (i = 0; i < padata->len; i++) {
284c19800e8SDoug Rabson 	switch(padata->val[i].padata_type) {
285c19800e8SDoug Rabson 	case KRB5_PADATA_PK_AS_REQ:
286c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "PK-INIT(ietf)");
287c19800e8SDoug Rabson 	    break;
288c19800e8SDoug Rabson 	case KRB5_PADATA_PK_AS_REQ_WIN:
289c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "PK-INIT(win2k)");
290c19800e8SDoug Rabson 	    break;
291c19800e8SDoug Rabson 	case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
292c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "OCSP");
293c19800e8SDoug Rabson 	    break;
294c19800e8SDoug Rabson 	case KRB5_PADATA_ENC_TIMESTAMP:
295c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "encrypted-timestamp");
296c19800e8SDoug Rabson 	    break;
297c19800e8SDoug Rabson 	default:
298c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
299c19800e8SDoug Rabson 	    break;
300c19800e8SDoug Rabson 	}
301c19800e8SDoug Rabson 	if (p && i + 1 < padata->len)
302c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, ", ");
303c19800e8SDoug Rabson 	if (p == NULL) {
304c19800e8SDoug Rabson 	    kdc_log(context, config, 0, "out of memory");
305c19800e8SDoug Rabson 	    return;
306c19800e8SDoug Rabson 	}
307c19800e8SDoug Rabson     }
308c19800e8SDoug Rabson     if (p == NULL)
309c19800e8SDoug Rabson 	p = rk_strpoolprintf(p, "none");
310c19800e8SDoug Rabson 
311c19800e8SDoug Rabson     str = rk_strpoolcollect(p);
312c19800e8SDoug Rabson     kdc_log(context, config, 0, "Client sent patypes: %s", str);
313c19800e8SDoug Rabson     free(str);
314c19800e8SDoug Rabson }
315c19800e8SDoug Rabson 
316c19800e8SDoug Rabson /*
317c19800e8SDoug Rabson  *
318c19800e8SDoug Rabson  */
319c19800e8SDoug Rabson 
320c19800e8SDoug Rabson 
321c19800e8SDoug Rabson krb5_error_code
_kdc_encode_reply(krb5_context context,krb5_kdc_configuration * config,KDC_REP * rep,const EncTicketPart * et,EncKDCRepPart * ek,krb5_enctype etype,int skvno,const EncryptionKey * skey,int ckvno,const EncryptionKey * reply_key,int rk_is_subkey,const char ** e_text,krb5_data * reply)322c19800e8SDoug Rabson _kdc_encode_reply(krb5_context context,
323c19800e8SDoug Rabson 		  krb5_kdc_configuration *config,
324c19800e8SDoug Rabson 		  KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
325b528cefcSMark Murray 		  krb5_enctype etype,
326c19800e8SDoug Rabson 		  int skvno, const EncryptionKey *skey,
327ae771770SStanislav Sedov 		  int ckvno, const EncryptionKey *reply_key,
328ae771770SStanislav Sedov 		  int rk_is_subkey,
3290cadf2f4SJacques Vidrine 		  const char **e_text,
330b528cefcSMark Murray 		  krb5_data *reply)
331b528cefcSMark Murray {
3320cadf2f4SJacques Vidrine     unsigned char *buf;
3330cadf2f4SJacques Vidrine     size_t buf_size;
334ae771770SStanislav Sedov     size_t len = 0;
335b528cefcSMark Murray     krb5_error_code ret;
336b528cefcSMark Murray     krb5_crypto crypto;
337b528cefcSMark Murray 
3380cadf2f4SJacques Vidrine     ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
339b528cefcSMark Murray     if(ret) {
340ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
341ae771770SStanislav Sedov 	kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
342ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
343b528cefcSMark Murray 	return ret;
344b528cefcSMark Murray     }
3450cadf2f4SJacques Vidrine     if(buf_size != len) {
3460cadf2f4SJacques Vidrine 	free(buf);
347c19800e8SDoug Rabson 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
3480cadf2f4SJacques Vidrine 	*e_text = "KDC internal error";
3490cadf2f4SJacques Vidrine 	return KRB5KRB_ERR_GENERIC;
3500cadf2f4SJacques Vidrine     }
351b528cefcSMark Murray 
3525e9cd1aeSAssar Westerlund     ret = krb5_crypto_init(context, skey, etype, &crypto);
3535e9cd1aeSAssar Westerlund     if (ret) {
354ae771770SStanislav Sedov         const char *msg;
3550cadf2f4SJacques Vidrine 	free(buf);
356ae771770SStanislav Sedov 	msg = krb5_get_error_message(context, ret);
357ae771770SStanislav Sedov 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
358ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
3595e9cd1aeSAssar Westerlund 	return ret;
3605e9cd1aeSAssar Westerlund     }
361b528cefcSMark Murray 
3620cadf2f4SJacques Vidrine     ret = krb5_encrypt_EncryptedData(context,
363b528cefcSMark Murray 				     crypto,
364b528cefcSMark Murray 				     KRB5_KU_TICKET,
3650cadf2f4SJacques Vidrine 				     buf,
366b528cefcSMark Murray 				     len,
367b528cefcSMark Murray 				     skvno,
368b528cefcSMark Murray 				     &rep->ticket.enc_part);
3690cadf2f4SJacques Vidrine     free(buf);
370b528cefcSMark Murray     krb5_crypto_destroy(context, crypto);
3710cadf2f4SJacques Vidrine     if(ret) {
372ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
373ae771770SStanislav Sedov 	kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
374ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
3750cadf2f4SJacques Vidrine 	return ret;
3760cadf2f4SJacques Vidrine     }
377b528cefcSMark Murray 
378c19800e8SDoug Rabson     if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
3790cadf2f4SJacques Vidrine 	ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
380b528cefcSMark Murray     else
3810cadf2f4SJacques Vidrine 	ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
382b528cefcSMark Murray     if(ret) {
383ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
384ae771770SStanislav Sedov 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
385ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
386b528cefcSMark Murray 	return ret;
387b528cefcSMark Murray     }
3880cadf2f4SJacques Vidrine     if(buf_size != len) {
3890cadf2f4SJacques Vidrine 	free(buf);
390c19800e8SDoug Rabson 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
3910cadf2f4SJacques Vidrine 	*e_text = "KDC internal error";
3920cadf2f4SJacques Vidrine 	return KRB5KRB_ERR_GENERIC;
3930cadf2f4SJacques Vidrine     }
394ae771770SStanislav Sedov     ret = krb5_crypto_init(context, reply_key, 0, &crypto);
3955e9cd1aeSAssar Westerlund     if (ret) {
396ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
3970cadf2f4SJacques Vidrine 	free(buf);
398ae771770SStanislav Sedov 	kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
399ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
4005e9cd1aeSAssar Westerlund 	return ret;
4015e9cd1aeSAssar Westerlund     }
402b528cefcSMark Murray     if(rep->msg_type == krb_as_rep) {
403b528cefcSMark Murray 	krb5_encrypt_EncryptedData(context,
404b528cefcSMark Murray 				   crypto,
405b528cefcSMark Murray 				   KRB5_KU_AS_REP_ENC_PART,
4060cadf2f4SJacques Vidrine 				   buf,
407b528cefcSMark Murray 				   len,
408b528cefcSMark Murray 				   ckvno,
409b528cefcSMark Murray 				   &rep->enc_part);
4100cadf2f4SJacques Vidrine 	free(buf);
4110cadf2f4SJacques Vidrine 	ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
412b528cefcSMark Murray     } else {
413b528cefcSMark Murray 	krb5_encrypt_EncryptedData(context,
414b528cefcSMark Murray 				   crypto,
415ae771770SStanislav Sedov 				   rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
4160cadf2f4SJacques Vidrine 				   buf,
417b528cefcSMark Murray 				   len,
418b528cefcSMark Murray 				   ckvno,
419b528cefcSMark Murray 				   &rep->enc_part);
4200cadf2f4SJacques Vidrine 	free(buf);
4210cadf2f4SJacques Vidrine 	ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
422b528cefcSMark Murray     }
423b528cefcSMark Murray     krb5_crypto_destroy(context, crypto);
424b528cefcSMark Murray     if(ret) {
425ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
426ae771770SStanislav Sedov 	kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
427ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
428b528cefcSMark Murray 	return ret;
429b528cefcSMark Murray     }
4300cadf2f4SJacques Vidrine     if(buf_size != len) {
4310cadf2f4SJacques Vidrine 	free(buf);
432c19800e8SDoug Rabson 	kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
4330cadf2f4SJacques Vidrine 	*e_text = "KDC internal error";
4340cadf2f4SJacques Vidrine 	return KRB5KRB_ERR_GENERIC;
4350cadf2f4SJacques Vidrine     }
4360cadf2f4SJacques Vidrine     reply->data = buf;
4370cadf2f4SJacques Vidrine     reply->length = buf_size;
438b528cefcSMark Murray     return 0;
439b528cefcSMark Murray }
440b528cefcSMark Murray 
441c19800e8SDoug Rabson /*
442c19800e8SDoug Rabson  * Return 1 if the client have only older enctypes, this is for
443c19800e8SDoug Rabson  * determining if the server should send ETYPE_INFO2 or not.
444c19800e8SDoug Rabson  */
445c19800e8SDoug Rabson 
446b528cefcSMark Murray static int
older_enctype(krb5_enctype enctype)447c19800e8SDoug Rabson older_enctype(krb5_enctype enctype)
448b528cefcSMark Murray {
449c19800e8SDoug Rabson     switch (enctype) {
450c19800e8SDoug Rabson     case ETYPE_DES_CBC_CRC:
451c19800e8SDoug Rabson     case ETYPE_DES_CBC_MD4:
452c19800e8SDoug Rabson     case ETYPE_DES_CBC_MD5:
453c19800e8SDoug Rabson     case ETYPE_DES3_CBC_SHA1:
454c19800e8SDoug Rabson     case ETYPE_ARCFOUR_HMAC_MD5:
455c19800e8SDoug Rabson     case ETYPE_ARCFOUR_HMAC_MD5_56:
456c19800e8SDoug Rabson     /*
457c19800e8SDoug Rabson      * The following three is "old" windows enctypes and is needed for
458c19800e8SDoug Rabson      * windows 2000 hosts.
459c19800e8SDoug Rabson      */
460c19800e8SDoug Rabson     case ETYPE_ARCFOUR_MD4:
461c19800e8SDoug Rabson     case ETYPE_ARCFOUR_HMAC_OLD:
462c19800e8SDoug Rabson     case ETYPE_ARCFOUR_HMAC_OLD_EXP:
463c19800e8SDoug Rabson 	return 1;
464c19800e8SDoug Rabson     default:
465b528cefcSMark Murray 	return 0;
466b528cefcSMark Murray     }
467c19800e8SDoug Rabson }
468c19800e8SDoug Rabson 
469c19800e8SDoug Rabson /*
470c19800e8SDoug Rabson  *
471c19800e8SDoug Rabson  */
472b528cefcSMark Murray 
473b528cefcSMark Murray static krb5_error_code
make_etype_info_entry(krb5_context context,ETYPE_INFO_ENTRY * ent,Key * key)474c19800e8SDoug Rabson make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
4758373020dSJacques Vidrine {
4768373020dSJacques Vidrine     ent->etype = key->key.keytype;
4778373020dSJacques Vidrine     if(key->salt){
4788373020dSJacques Vidrine #if 0
479c19800e8SDoug Rabson 	ALLOC(ent->salttype);
480c19800e8SDoug Rabson 
4818373020dSJacques Vidrine 	if(key->salt->type == hdb_pw_salt)
4828373020dSJacques Vidrine 	    *ent->salttype = 0; /* or 1? or NULL? */
4838373020dSJacques Vidrine 	else if(key->salt->type == hdb_afs3_salt)
4848373020dSJacques Vidrine 	    *ent->salttype = 2;
4858373020dSJacques Vidrine 	else {
486c19800e8SDoug Rabson 	    kdc_log(context, config, 0, "unknown salt-type: %d",
4878373020dSJacques Vidrine 		    key->salt->type);
4888373020dSJacques Vidrine 	    return KRB5KRB_ERR_GENERIC;
4898373020dSJacques Vidrine 	}
4908373020dSJacques Vidrine 	/* according to `the specs', we can't send a salt if
4918373020dSJacques Vidrine 	   we have AFS3 salted key, but that requires that you
4928373020dSJacques Vidrine 	   *know* what cell you are using (e.g by assuming
4938373020dSJacques Vidrine 	   that the cell is the same as the realm in lower
4948373020dSJacques Vidrine 	   case) */
495c19800e8SDoug Rabson #elif 0
496c19800e8SDoug Rabson 	ALLOC(ent->salttype);
4978373020dSJacques Vidrine 	*ent->salttype = key->salt->type;
498c19800e8SDoug Rabson #else
499c19800e8SDoug Rabson 	/*
500c19800e8SDoug Rabson 	 * We shouldn't sent salttype since it is incompatible with the
501c19800e8SDoug Rabson 	 * specification and it breaks windows clients.  The afs
502c19800e8SDoug Rabson 	 * salting problem is solved by using KRB5-PADATA-AFS3-SALT
503c19800e8SDoug Rabson 	 * implemented in Heimdal 0.7 and later.
504c19800e8SDoug Rabson 	 */
505c19800e8SDoug Rabson 	ent->salttype = NULL;
5068373020dSJacques Vidrine #endif
5078373020dSJacques Vidrine 	krb5_copy_data(context, &key->salt->salt,
5088373020dSJacques Vidrine 		       &ent->salt);
5098373020dSJacques Vidrine     } else {
5108373020dSJacques Vidrine 	/* we return no salt type at all, as that should indicate
5118373020dSJacques Vidrine 	 * the default salt type and make everybody happy.  some
5128373020dSJacques Vidrine 	 * systems (like w2k) dislike being told the salt type
5138373020dSJacques Vidrine 	 * here. */
5148373020dSJacques Vidrine 
5158373020dSJacques Vidrine 	ent->salttype = NULL;
5168373020dSJacques Vidrine 	ent->salt = NULL;
5178373020dSJacques Vidrine     }
5188373020dSJacques Vidrine     return 0;
5198373020dSJacques Vidrine }
5208373020dSJacques Vidrine 
5218373020dSJacques Vidrine static krb5_error_code
get_pa_etype_info(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)522c19800e8SDoug Rabson get_pa_etype_info(krb5_context context,
523c19800e8SDoug Rabson 		  krb5_kdc_configuration *config,
524ae771770SStanislav Sedov 		  METHOD_DATA *md, Key *ckey)
525b528cefcSMark Murray {
526b528cefcSMark Murray     krb5_error_code ret = 0;
527b528cefcSMark Murray     ETYPE_INFO pa;
528b528cefcSMark Murray     unsigned char *buf;
529b528cefcSMark Murray     size_t len;
530b528cefcSMark Murray 
531b528cefcSMark Murray 
532ae771770SStanislav Sedov     pa.len = 1;
533ae771770SStanislav Sedov     pa.val = calloc(1, sizeof(pa.val[0]));
534b528cefcSMark Murray     if(pa.val == NULL)
535b528cefcSMark Murray 	return ENOMEM;
5365e9cd1aeSAssar Westerlund 
537ae771770SStanislav Sedov     ret = make_etype_info_entry(context, &pa.val[0], ckey);
538ae771770SStanislav Sedov     if (ret) {
5398373020dSJacques Vidrine 	free_ETYPE_INFO(&pa);
5408373020dSJacques Vidrine 	return ret;
541b528cefcSMark Murray     }
5428373020dSJacques Vidrine 
5430cadf2f4SJacques Vidrine     ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
544b528cefcSMark Murray     free_ETYPE_INFO(&pa);
5450cadf2f4SJacques Vidrine     if(ret)
546b528cefcSMark Murray 	return ret;
547b528cefcSMark Murray     ret = realloc_method_data(md);
548b528cefcSMark Murray     if(ret) {
549b528cefcSMark Murray 	free(buf);
550b528cefcSMark Murray 	return ret;
551b528cefcSMark Murray     }
5525e9cd1aeSAssar Westerlund     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
553b528cefcSMark Murray     md->val[md->len - 1].padata_value.length = len;
554b528cefcSMark Murray     md->val[md->len - 1].padata_value.data = buf;
555b528cefcSMark Murray     return 0;
556b528cefcSMark Murray }
557b528cefcSMark Murray 
5585e9cd1aeSAssar Westerlund /*
559c19800e8SDoug Rabson  *
560c19800e8SDoug Rabson  */
561c19800e8SDoug Rabson 
562c19800e8SDoug Rabson extern int _krb5_AES_string_to_default_iterator;
563c19800e8SDoug Rabson 
564c19800e8SDoug Rabson static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY * ent,Key * key)565c19800e8SDoug Rabson make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
566c19800e8SDoug Rabson {
567c19800e8SDoug Rabson     ent->etype = key->key.keytype;
568c19800e8SDoug Rabson     if(key->salt) {
569c19800e8SDoug Rabson 	ALLOC(ent->salt);
570c19800e8SDoug Rabson 	if (ent->salt == NULL)
571c19800e8SDoug Rabson 	    return ENOMEM;
572c19800e8SDoug Rabson 	*ent->salt = malloc(key->salt->salt.length + 1);
573c19800e8SDoug Rabson 	if (*ent->salt == NULL) {
574c19800e8SDoug Rabson 	    free(ent->salt);
575c19800e8SDoug Rabson 	    ent->salt = NULL;
576c19800e8SDoug Rabson 	    return ENOMEM;
577c19800e8SDoug Rabson 	}
578c19800e8SDoug Rabson 	memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
579c19800e8SDoug Rabson 	(*ent->salt)[key->salt->salt.length] = '\0';
580c19800e8SDoug Rabson     } else
581c19800e8SDoug Rabson 	ent->salt = NULL;
582c19800e8SDoug Rabson 
583c19800e8SDoug Rabson     ent->s2kparams = NULL;
584c19800e8SDoug Rabson 
585c19800e8SDoug Rabson     switch (key->key.keytype) {
586c19800e8SDoug Rabson     case ETYPE_AES128_CTS_HMAC_SHA1_96:
587c19800e8SDoug Rabson     case ETYPE_AES256_CTS_HMAC_SHA1_96:
588c19800e8SDoug Rabson 	ALLOC(ent->s2kparams);
589c19800e8SDoug Rabson 	if (ent->s2kparams == NULL)
590c19800e8SDoug Rabson 	    return ENOMEM;
591c19800e8SDoug Rabson 	ent->s2kparams->length = 4;
592c19800e8SDoug Rabson 	ent->s2kparams->data = malloc(ent->s2kparams->length);
593c19800e8SDoug Rabson 	if (ent->s2kparams->data == NULL) {
594c19800e8SDoug Rabson 	    free(ent->s2kparams);
595c19800e8SDoug Rabson 	    ent->s2kparams = NULL;
596c19800e8SDoug Rabson 	    return ENOMEM;
597c19800e8SDoug Rabson 	}
598c19800e8SDoug Rabson 	_krb5_put_int(ent->s2kparams->data,
599c19800e8SDoug Rabson 		      _krb5_AES_string_to_default_iterator,
600c19800e8SDoug Rabson 		      ent->s2kparams->length);
601c19800e8SDoug Rabson 	break;
602c19800e8SDoug Rabson     case ETYPE_DES_CBC_CRC:
603c19800e8SDoug Rabson     case ETYPE_DES_CBC_MD4:
604c19800e8SDoug Rabson     case ETYPE_DES_CBC_MD5:
605c19800e8SDoug Rabson 	/* Check if this was a AFS3 salted key */
606c19800e8SDoug Rabson 	if(key->salt && key->salt->type == hdb_afs3_salt){
607c19800e8SDoug Rabson 	    ALLOC(ent->s2kparams);
608c19800e8SDoug Rabson 	    if (ent->s2kparams == NULL)
609c19800e8SDoug Rabson 		return ENOMEM;
610c19800e8SDoug Rabson 	    ent->s2kparams->length = 1;
611c19800e8SDoug Rabson 	    ent->s2kparams->data = malloc(ent->s2kparams->length);
612c19800e8SDoug Rabson 	    if (ent->s2kparams->data == NULL) {
613c19800e8SDoug Rabson 		free(ent->s2kparams);
614c19800e8SDoug Rabson 		ent->s2kparams = NULL;
615c19800e8SDoug Rabson 		return ENOMEM;
616c19800e8SDoug Rabson 	    }
617c19800e8SDoug Rabson 	    _krb5_put_int(ent->s2kparams->data,
618c19800e8SDoug Rabson 			  1,
619c19800e8SDoug Rabson 			  ent->s2kparams->length);
620c19800e8SDoug Rabson 	}
621c19800e8SDoug Rabson 	break;
622c19800e8SDoug Rabson     default:
623c19800e8SDoug Rabson 	break;
624c19800e8SDoug Rabson     }
625c19800e8SDoug Rabson     return 0;
626c19800e8SDoug Rabson }
627c19800e8SDoug Rabson 
628c19800e8SDoug Rabson /*
629c19800e8SDoug Rabson  * Return an ETYPE-INFO2. Enctypes are storted the same way as in the
630c19800e8SDoug Rabson  * database (client supported enctypes first, then the unsupported
631c19800e8SDoug Rabson  * enctypes).
632c19800e8SDoug Rabson  */
633c19800e8SDoug Rabson 
634c19800e8SDoug Rabson static krb5_error_code
get_pa_etype_info2(krb5_context context,krb5_kdc_configuration * config,METHOD_DATA * md,Key * ckey)635c19800e8SDoug Rabson get_pa_etype_info2(krb5_context context,
636c19800e8SDoug Rabson 		   krb5_kdc_configuration *config,
637ae771770SStanislav Sedov 		   METHOD_DATA *md, Key *ckey)
638c19800e8SDoug Rabson {
639c19800e8SDoug Rabson     krb5_error_code ret = 0;
640c19800e8SDoug Rabson     ETYPE_INFO2 pa;
641c19800e8SDoug Rabson     unsigned char *buf;
642c19800e8SDoug Rabson     size_t len;
643c19800e8SDoug Rabson 
644ae771770SStanislav Sedov     pa.len = 1;
645ae771770SStanislav Sedov     pa.val = calloc(1, sizeof(pa.val[0]));
646c19800e8SDoug Rabson     if(pa.val == NULL)
647c19800e8SDoug Rabson 	return ENOMEM;
648c19800e8SDoug Rabson 
649ae771770SStanislav Sedov     ret = make_etype_info2_entry(&pa.val[0], ckey);
650ae771770SStanislav Sedov     if (ret) {
651c19800e8SDoug Rabson 	free_ETYPE_INFO2(&pa);
652c19800e8SDoug Rabson 	return ret;
653c19800e8SDoug Rabson     }
654c19800e8SDoug Rabson 
655c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
656c19800e8SDoug Rabson     free_ETYPE_INFO2(&pa);
657c19800e8SDoug Rabson     if(ret)
658c19800e8SDoug Rabson 	return ret;
659c19800e8SDoug Rabson     ret = realloc_method_data(md);
660c19800e8SDoug Rabson     if(ret) {
661c19800e8SDoug Rabson 	free(buf);
662c19800e8SDoug Rabson 	return ret;
663c19800e8SDoug Rabson     }
664c19800e8SDoug Rabson     md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
665c19800e8SDoug Rabson     md->val[md->len - 1].padata_value.length = len;
666c19800e8SDoug Rabson     md->val[md->len - 1].padata_value.data = buf;
667c19800e8SDoug Rabson     return 0;
668c19800e8SDoug Rabson }
669c19800e8SDoug Rabson 
670c19800e8SDoug Rabson /*
671c19800e8SDoug Rabson  *
672c19800e8SDoug Rabson  */
673c19800e8SDoug Rabson 
674c19800e8SDoug Rabson static void
log_as_req(krb5_context context,krb5_kdc_configuration * config,krb5_enctype cetype,krb5_enctype setype,const KDC_REQ_BODY * b)675c19800e8SDoug Rabson log_as_req(krb5_context context,
676c19800e8SDoug Rabson 	   krb5_kdc_configuration *config,
677c19800e8SDoug Rabson 	   krb5_enctype cetype,
678c19800e8SDoug Rabson 	   krb5_enctype setype,
679c19800e8SDoug Rabson 	   const KDC_REQ_BODY *b)
680c19800e8SDoug Rabson {
681c19800e8SDoug Rabson     krb5_error_code ret;
682ae771770SStanislav Sedov     struct rk_strpool *p;
683c19800e8SDoug Rabson     char *str;
684ae771770SStanislav Sedov     size_t i;
685ae771770SStanislav Sedov 
686ae771770SStanislav Sedov     p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
687c19800e8SDoug Rabson 
688c19800e8SDoug Rabson     for (i = 0; i < b->etype.len; i++) {
689c19800e8SDoug Rabson 	ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
690c19800e8SDoug Rabson 	if (ret == 0) {
691c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "%s", str);
692c19800e8SDoug Rabson 	    free(str);
693c19800e8SDoug Rabson 	} else
694c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, "%d", b->etype.val[i]);
695c19800e8SDoug Rabson 	if (p && i + 1 < b->etype.len)
696c19800e8SDoug Rabson 	    p = rk_strpoolprintf(p, ", ");
697c19800e8SDoug Rabson 	if (p == NULL) {
698c19800e8SDoug Rabson 	    kdc_log(context, config, 0, "out of memory");
699c19800e8SDoug Rabson 	    return;
700c19800e8SDoug Rabson 	}
701c19800e8SDoug Rabson     }
702c19800e8SDoug Rabson     if (p == NULL)
703c19800e8SDoug Rabson 	p = rk_strpoolprintf(p, "no encryption types");
704c19800e8SDoug Rabson 
705c19800e8SDoug Rabson     {
706c19800e8SDoug Rabson 	char *cet;
707c19800e8SDoug Rabson 	char *set;
708c19800e8SDoug Rabson 
709c19800e8SDoug Rabson 	ret = krb5_enctype_to_string(context, cetype, &cet);
710c19800e8SDoug Rabson 	if(ret == 0) {
711c19800e8SDoug Rabson 	    ret = krb5_enctype_to_string(context, setype, &set);
712c19800e8SDoug Rabson 	    if (ret == 0) {
713ae771770SStanislav Sedov 		p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
714c19800e8SDoug Rabson 		free(set);
715c19800e8SDoug Rabson 	    }
716c19800e8SDoug Rabson 	    free(cet);
717c19800e8SDoug Rabson 	}
718c19800e8SDoug Rabson 	if (ret != 0)
719ae771770SStanislav Sedov 	    p = rk_strpoolprintf(p, ", using enctypes %d/%d",
720ae771770SStanislav Sedov 				 cetype, setype);
721c19800e8SDoug Rabson     }
722c19800e8SDoug Rabson 
723ae771770SStanislav Sedov     str = rk_strpoolcollect(p);
724ae771770SStanislav Sedov     kdc_log(context, config, 0, "%s", str);
725ae771770SStanislav Sedov     free(str);
726ae771770SStanislav Sedov 
727c19800e8SDoug Rabson     {
728c19800e8SDoug Rabson 	char fixedstr[128];
729c19800e8SDoug Rabson 	unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
730c19800e8SDoug Rabson 		      fixedstr, sizeof(fixedstr));
731c19800e8SDoug Rabson 	if(*fixedstr)
732ae771770SStanislav Sedov 	    kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
733c19800e8SDoug Rabson     }
734c19800e8SDoug Rabson }
735c19800e8SDoug Rabson 
736c19800e8SDoug Rabson /*
7375e9cd1aeSAssar Westerlund  * verify the flags on `client' and `server', returning 0
7385e9cd1aeSAssar Westerlund  * if they are OK and generating an error messages and returning
7395e9cd1aeSAssar Westerlund  * and error code otherwise.
7405e9cd1aeSAssar Westerlund  */
7415e9cd1aeSAssar Westerlund 
7425e9cd1aeSAssar Westerlund krb5_error_code
kdc_check_flags(krb5_context context,krb5_kdc_configuration * config,hdb_entry_ex * client_ex,const char * client_name,hdb_entry_ex * server_ex,const char * server_name,krb5_boolean is_as_req)743ae771770SStanislav Sedov kdc_check_flags(krb5_context context,
744c19800e8SDoug Rabson 		krb5_kdc_configuration *config,
745c19800e8SDoug Rabson 		hdb_entry_ex *client_ex, const char *client_name,
746c19800e8SDoug Rabson 		hdb_entry_ex *server_ex, const char *server_name,
747b528cefcSMark Murray 		krb5_boolean is_as_req)
748b528cefcSMark Murray {
749c19800e8SDoug Rabson     if(client_ex != NULL) {
750c19800e8SDoug Rabson 	hdb_entry *client = &client_ex->entry;
751c19800e8SDoug Rabson 
752b528cefcSMark Murray 	/* check client */
753ae771770SStanislav Sedov 	if (client->flags.locked_out) {
754ae771770SStanislav Sedov 	    kdc_log(context, config, 0,
755ae771770SStanislav Sedov 		    "Client (%s) is locked out", client_name);
756ae771770SStanislav Sedov 	    return KRB5KDC_ERR_POLICY;
757ae771770SStanislav Sedov 	}
758ae771770SStanislav Sedov 
759b528cefcSMark Murray 	if (client->flags.invalid) {
760c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
761c19800e8SDoug Rabson 		    "Client (%s) has invalid bit set", client_name);
762b528cefcSMark Murray 	    return KRB5KDC_ERR_POLICY;
763b528cefcSMark Murray 	}
764b528cefcSMark Murray 
765b528cefcSMark Murray 	if(!client->flags.client){
766c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
767c19800e8SDoug Rabson 		    "Principal may not act as client -- %s", client_name);
768b528cefcSMark Murray 	    return KRB5KDC_ERR_POLICY;
769b528cefcSMark Murray 	}
770b528cefcSMark Murray 
771b528cefcSMark Murray 	if (client->valid_start && *client->valid_start > kdc_time) {
772c19800e8SDoug Rabson 	    char starttime_str[100];
773c19800e8SDoug Rabson 	    krb5_format_time(context, *client->valid_start,
774c19800e8SDoug Rabson 			     starttime_str, sizeof(starttime_str), TRUE);
775c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
776c19800e8SDoug Rabson 		    "Client not yet valid until %s -- %s",
777c19800e8SDoug Rabson 		    starttime_str, client_name);
778b528cefcSMark Murray 	    return KRB5KDC_ERR_CLIENT_NOTYET;
779b528cefcSMark Murray 	}
780b528cefcSMark Murray 
781b528cefcSMark Murray 	if (client->valid_end && *client->valid_end < kdc_time) {
782c19800e8SDoug Rabson 	    char endtime_str[100];
783c19800e8SDoug Rabson 	    krb5_format_time(context, *client->valid_end,
784c19800e8SDoug Rabson 			     endtime_str, sizeof(endtime_str), TRUE);
785c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
786c19800e8SDoug Rabson 		    "Client expired at %s -- %s",
787c19800e8SDoug Rabson 		    endtime_str, client_name);
788b528cefcSMark Murray 	    return KRB5KDC_ERR_NAME_EXP;
789b528cefcSMark Murray 	}
790b528cefcSMark Murray 
791b528cefcSMark Murray 	if (client->pw_end && *client->pw_end < kdc_time
792c19800e8SDoug Rabson 	    && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
793c19800e8SDoug Rabson 	    char pwend_str[100];
794c19800e8SDoug Rabson 	    krb5_format_time(context, *client->pw_end,
795c19800e8SDoug Rabson 			     pwend_str, sizeof(pwend_str), TRUE);
796c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
797c19800e8SDoug Rabson 		    "Client's key has expired at %s -- %s",
798c19800e8SDoug Rabson 		    pwend_str, client_name);
799b528cefcSMark Murray 	    return KRB5KDC_ERR_KEY_EXPIRED;
800b528cefcSMark Murray 	}
801b528cefcSMark Murray     }
802b528cefcSMark Murray 
803b528cefcSMark Murray     /* check server */
804b528cefcSMark Murray 
805c19800e8SDoug Rabson     if (server_ex != NULL) {
806c19800e8SDoug Rabson 	hdb_entry *server = &server_ex->entry;
807c19800e8SDoug Rabson 
808ae771770SStanislav Sedov 	if (server->flags.locked_out) {
809ae771770SStanislav Sedov 	    kdc_log(context, config, 0,
810ae771770SStanislav Sedov 		    "Client server locked out -- %s", server_name);
811ae771770SStanislav Sedov 	    return KRB5KDC_ERR_POLICY;
812ae771770SStanislav Sedov 	}
813b528cefcSMark Murray 	if (server->flags.invalid) {
814c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
815c19800e8SDoug Rabson 		    "Server has invalid flag set -- %s", server_name);
816b528cefcSMark Murray 	    return KRB5KDC_ERR_POLICY;
817b528cefcSMark Murray 	}
818b528cefcSMark Murray 
819b528cefcSMark Murray 	if(!server->flags.server){
820c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
821c19800e8SDoug Rabson 		    "Principal may not act as server -- %s", server_name);
822b528cefcSMark Murray 	    return KRB5KDC_ERR_POLICY;
823b528cefcSMark Murray 	}
824b528cefcSMark Murray 
825b528cefcSMark Murray 	if(!is_as_req && server->flags.initial) {
826c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
827c19800e8SDoug Rabson 		    "AS-REQ is required for server -- %s", server_name);
828b528cefcSMark Murray 	    return KRB5KDC_ERR_POLICY;
829b528cefcSMark Murray 	}
830b528cefcSMark Murray 
831b528cefcSMark Murray 	if (server->valid_start && *server->valid_start > kdc_time) {
832c19800e8SDoug Rabson 	    char starttime_str[100];
833c19800e8SDoug Rabson 	    krb5_format_time(context, *server->valid_start,
834c19800e8SDoug Rabson 			     starttime_str, sizeof(starttime_str), TRUE);
835c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
836c19800e8SDoug Rabson 		    "Server not yet valid until %s -- %s",
837c19800e8SDoug Rabson 		    starttime_str, server_name);
838b528cefcSMark Murray 	    return KRB5KDC_ERR_SERVICE_NOTYET;
839b528cefcSMark Murray 	}
840b528cefcSMark Murray 
841b528cefcSMark Murray 	if (server->valid_end && *server->valid_end < kdc_time) {
842c19800e8SDoug Rabson 	    char endtime_str[100];
843c19800e8SDoug Rabson 	    krb5_format_time(context, *server->valid_end,
844c19800e8SDoug Rabson 			     endtime_str, sizeof(endtime_str), TRUE);
845c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
846c19800e8SDoug Rabson 		    "Server expired at %s -- %s",
847c19800e8SDoug Rabson 		    endtime_str, server_name);
848b528cefcSMark Murray 	    return KRB5KDC_ERR_SERVICE_EXP;
849b528cefcSMark Murray 	}
850b528cefcSMark Murray 
851b528cefcSMark Murray 	if (server->pw_end && *server->pw_end < kdc_time) {
852c19800e8SDoug Rabson 	    char pwend_str[100];
853c19800e8SDoug Rabson 	    krb5_format_time(context, *server->pw_end,
854c19800e8SDoug Rabson 			     pwend_str, sizeof(pwend_str), TRUE);
855c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
856c19800e8SDoug Rabson 		    "Server's key has expired at -- %s",
857c19800e8SDoug Rabson 		    pwend_str, server_name);
858b528cefcSMark Murray 	    return KRB5KDC_ERR_KEY_EXPIRED;
859b528cefcSMark Murray 	}
860b528cefcSMark Murray     }
861b528cefcSMark Murray     return 0;
862b528cefcSMark Murray }
863b528cefcSMark Murray 
8645e9cd1aeSAssar Westerlund /*
8655e9cd1aeSAssar Westerlund  * Return TRUE if `from' is part of `addresses' taking into consideration
8665e9cd1aeSAssar Westerlund  * the configuration variables that tells us how strict we should be about
8675e9cd1aeSAssar Westerlund  * these checks
8685e9cd1aeSAssar Westerlund  */
8695e9cd1aeSAssar Westerlund 
870c19800e8SDoug Rabson krb5_boolean
_kdc_check_addresses(krb5_context context,krb5_kdc_configuration * config,HostAddresses * addresses,const struct sockaddr * from)871c19800e8SDoug Rabson _kdc_check_addresses(krb5_context context,
872c19800e8SDoug Rabson 		     krb5_kdc_configuration *config,
873c19800e8SDoug Rabson 		     HostAddresses *addresses, const struct sockaddr *from)
874b528cefcSMark Murray {
875b528cefcSMark Murray     krb5_error_code ret;
876b528cefcSMark Murray     krb5_address addr;
8775e9cd1aeSAssar Westerlund     krb5_boolean result;
878c19800e8SDoug Rabson     krb5_boolean only_netbios = TRUE;
879ae771770SStanislav Sedov     size_t i;
880b528cefcSMark Murray 
881c19800e8SDoug Rabson     if(config->check_ticket_addresses == 0)
882b528cefcSMark Murray 	return TRUE;
883b528cefcSMark Murray 
884b528cefcSMark Murray     if(addresses == NULL)
885c19800e8SDoug Rabson 	return config->allow_null_ticket_addresses;
886c19800e8SDoug Rabson 
887c19800e8SDoug Rabson     for (i = 0; i < addresses->len; ++i) {
888c19800e8SDoug Rabson 	if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) {
889c19800e8SDoug Rabson 	    only_netbios = FALSE;
890c19800e8SDoug Rabson 	}
891c19800e8SDoug Rabson     }
892c19800e8SDoug Rabson 
893c19800e8SDoug Rabson     /* Windows sends it's netbios name, which I can only assume is
894c19800e8SDoug Rabson      * used for the 'allowed workstations' check.  This is painful,
895c19800e8SDoug Rabson      * but we still want to check IP addresses if they happen to be
896c19800e8SDoug Rabson      * present.
897c19800e8SDoug Rabson      */
898c19800e8SDoug Rabson 
899c19800e8SDoug Rabson     if(only_netbios)
900c19800e8SDoug Rabson 	return config->allow_null_ticket_addresses;
901b528cefcSMark Murray 
902adb0ddaeSAssar Westerlund     ret = krb5_sockaddr2address (context, from, &addr);
903b528cefcSMark Murray     if(ret)
904b528cefcSMark Murray 	return FALSE;
905b528cefcSMark Murray 
9065e9cd1aeSAssar Westerlund     result = krb5_address_search(context, &addr, addresses);
9075e9cd1aeSAssar Westerlund     krb5_free_address (context, &addr);
9085e9cd1aeSAssar Westerlund     return result;
909b528cefcSMark Murray }
910b528cefcSMark Murray 
911c19800e8SDoug Rabson /*
912c19800e8SDoug Rabson  *
913c19800e8SDoug Rabson  */
914c19800e8SDoug Rabson 
915c19800e8SDoug Rabson static krb5_boolean
send_pac_p(krb5_context context,KDC_REQ * req)916c19800e8SDoug Rabson send_pac_p(krb5_context context, KDC_REQ *req)
917c19800e8SDoug Rabson {
918c19800e8SDoug Rabson     krb5_error_code ret;
919c19800e8SDoug Rabson     PA_PAC_REQUEST pacreq;
920c19800e8SDoug Rabson     const PA_DATA *pa;
921c19800e8SDoug Rabson     int i = 0;
922c19800e8SDoug Rabson 
923c19800e8SDoug Rabson     pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST);
924c19800e8SDoug Rabson     if (pa == NULL)
925c19800e8SDoug Rabson 	return TRUE;
926c19800e8SDoug Rabson 
927c19800e8SDoug Rabson     ret = decode_PA_PAC_REQUEST(pa->padata_value.data,
928c19800e8SDoug Rabson 				pa->padata_value.length,
929c19800e8SDoug Rabson 				&pacreq,
930c19800e8SDoug Rabson 				NULL);
931c19800e8SDoug Rabson     if (ret)
932c19800e8SDoug Rabson 	return TRUE;
933c19800e8SDoug Rabson     i = pacreq.include_pac;
934c19800e8SDoug Rabson     free_PA_PAC_REQUEST(&pacreq);
935c19800e8SDoug Rabson     if (i == 0)
936c19800e8SDoug Rabson 	return FALSE;
937c19800e8SDoug Rabson     return TRUE;
938c19800e8SDoug Rabson }
939c19800e8SDoug Rabson 
940ae771770SStanislav Sedov krb5_boolean
_kdc_is_anonymous(krb5_context context,krb5_principal principal)941ae771770SStanislav Sedov _kdc_is_anonymous(krb5_context context, krb5_principal principal)
942ae771770SStanislav Sedov {
943ae771770SStanislav Sedov     if (principal->name.name_type != KRB5_NT_WELLKNOWN ||
944ae771770SStanislav Sedov 	principal->name.name_string.len != 2 ||
945ae771770SStanislav Sedov 	strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
946ae771770SStanislav Sedov 	strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
947ae771770SStanislav Sedov 	return 0;
948ae771770SStanislav Sedov     return 1;
949ae771770SStanislav Sedov }
950ae771770SStanislav Sedov 
951c19800e8SDoug Rabson /*
952c19800e8SDoug Rabson  *
953c19800e8SDoug Rabson  */
954c19800e8SDoug Rabson 
955b528cefcSMark Murray krb5_error_code
_kdc_as_rep(krb5_context context,krb5_kdc_configuration * config,KDC_REQ * req,const krb5_data * req_buffer,krb5_data * reply,const char * from,struct sockaddr * from_addr,int datagram_reply)956c19800e8SDoug Rabson _kdc_as_rep(krb5_context context,
957c19800e8SDoug Rabson 	    krb5_kdc_configuration *config,
958c19800e8SDoug Rabson 	    KDC_REQ *req,
959c19800e8SDoug Rabson 	    const krb5_data *req_buffer,
960b528cefcSMark Murray 	    krb5_data *reply,
961b528cefcSMark Murray 	    const char *from,
962c19800e8SDoug Rabson 	    struct sockaddr *from_addr,
963c19800e8SDoug Rabson 	    int datagram_reply)
964b528cefcSMark Murray {
965b528cefcSMark Murray     KDC_REQ_BODY *b = &req->req_body;
966b528cefcSMark Murray     AS_REP rep;
967b528cefcSMark Murray     KDCOptions f = b->kdc_options;
968c19800e8SDoug Rabson     hdb_entry_ex *client = NULL, *server = NULL;
969ae771770SStanislav Sedov     HDB *clientdb;
970ae771770SStanislav Sedov     krb5_enctype setype, sessionetype;
971c19800e8SDoug Rabson     krb5_data e_data;
972b528cefcSMark Murray     EncTicketPart et;
973b528cefcSMark Murray     EncKDCRepPart ek;
9741c43270aSJacques Vidrine     krb5_principal client_princ = NULL, server_princ = NULL;
9751c43270aSJacques Vidrine     char *client_name = NULL, *server_name = NULL;
976b528cefcSMark Murray     krb5_error_code ret = 0;
977b528cefcSMark Murray     const char *e_text = NULL;
978b528cefcSMark Murray     krb5_crypto crypto;
979b528cefcSMark Murray     Key *ckey, *skey;
980ae771770SStanislav Sedov     EncryptionKey *reply_key = NULL, session_key;
981ae771770SStanislav Sedov     int flags = HDB_F_FOR_AS_REQ;
982c19800e8SDoug Rabson #ifdef PKINIT
983c19800e8SDoug Rabson     pk_client_params *pkp = NULL;
984c19800e8SDoug Rabson #endif
985b528cefcSMark Murray 
9865e9cd1aeSAssar Westerlund     memset(&rep, 0, sizeof(rep));
987ae771770SStanislav Sedov     memset(&session_key, 0, sizeof(session_key));
988c19800e8SDoug Rabson     krb5_data_zero(&e_data);
989c19800e8SDoug Rabson 
990ae771770SStanislav Sedov     ALLOC(rep.padata);
991ae771770SStanislav Sedov     rep.padata->len = 0;
992ae771770SStanislav Sedov     rep.padata->val = NULL;
993ae771770SStanislav Sedov 
994c19800e8SDoug Rabson     if (f.canonicalize)
995c19800e8SDoug Rabson 	flags |= HDB_F_CANON;
9965e9cd1aeSAssar Westerlund 
997b528cefcSMark Murray     if(b->sname == NULL){
998b528cefcSMark Murray 	ret = KRB5KRB_ERR_GENERIC;
999b528cefcSMark Murray 	e_text = "No server in request";
1000b528cefcSMark Murray     } else{
1001c19800e8SDoug Rabson 	ret = _krb5_principalname2krb5_principal (context,
1002c19800e8SDoug Rabson 						  &server_princ,
1003c19800e8SDoug Rabson 						  *(b->sname),
1004c19800e8SDoug Rabson 						  b->realm);
1005c19800e8SDoug Rabson 	if (ret == 0)
1006c19800e8SDoug Rabson 	    ret = krb5_unparse_name(context, server_princ, &server_name);
1007b528cefcSMark Murray     }
10081c43270aSJacques Vidrine     if (ret) {
1009c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1010c19800e8SDoug Rabson 		"AS-REQ malformed server name from %s", from);
10111c43270aSJacques Vidrine 	goto out;
10121c43270aSJacques Vidrine     }
1013b528cefcSMark Murray     if(b->cname == NULL){
1014b528cefcSMark Murray 	ret = KRB5KRB_ERR_GENERIC;
1015b528cefcSMark Murray 	e_text = "No client in request";
1016b528cefcSMark Murray     } else {
1017c19800e8SDoug Rabson 	ret = _krb5_principalname2krb5_principal (context,
1018c19800e8SDoug Rabson 						  &client_princ,
1019c19800e8SDoug Rabson 						  *(b->cname),
1020c19800e8SDoug Rabson 						  b->realm);
1021c19800e8SDoug Rabson 	if (ret)
1022c19800e8SDoug Rabson 	    goto out;
1023ae771770SStanislav Sedov 
1024c19800e8SDoug Rabson 	ret = krb5_unparse_name(context, client_princ, &client_name);
1025b528cefcSMark Murray     }
10261c43270aSJacques Vidrine     if (ret) {
1027c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1028c19800e8SDoug Rabson 		"AS-REQ malformed client name from %s", from);
1029b528cefcSMark Murray 	goto out;
10301c43270aSJacques Vidrine     }
10311c43270aSJacques Vidrine 
1032c19800e8SDoug Rabson     kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
1033c19800e8SDoug Rabson 	    client_name, from, server_name);
1034b528cefcSMark Murray 
1035ae771770SStanislav Sedov     /*
1036ae771770SStanislav Sedov      *
1037ae771770SStanislav Sedov      */
1038ae771770SStanislav Sedov 
1039ae771770SStanislav Sedov     if (_kdc_is_anonymous(context, client_princ)) {
1040ae771770SStanislav Sedov 	if (!b->kdc_options.request_anonymous) {
1041ae771770SStanislav Sedov 	    kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
1042ae771770SStanislav Sedov 	    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1043ae771770SStanislav Sedov 	    goto out;
1044ae771770SStanislav Sedov 	}
1045ae771770SStanislav Sedov     } else if (b->kdc_options.request_anonymous) {
1046ae771770SStanislav Sedov 	kdc_log(context, config, 0,
1047ae771770SStanislav Sedov 		"Request for a anonymous ticket with non "
1048ae771770SStanislav Sedov 		"anonymous client name: %s", client_name);
1049b528cefcSMark Murray 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1050b528cefcSMark Murray 	goto out;
1051b528cefcSMark Murray     }
1052b528cefcSMark Murray 
1053ae771770SStanislav Sedov     /*
1054ae771770SStanislav Sedov      *
1055ae771770SStanislav Sedov      */
1056ae771770SStanislav Sedov 
1057ae771770SStanislav Sedov     ret = _kdc_db_fetch(context, config, client_princ,
1058ae771770SStanislav Sedov 			HDB_F_GET_CLIENT | flags, NULL,
1059ae771770SStanislav Sedov 			&clientdb, &client);
1060ae771770SStanislav Sedov     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1061ae771770SStanislav Sedov 	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name);
1062ae771770SStanislav Sedov 	goto out;
1063ae771770SStanislav Sedov     } else if(ret){
1064ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
1065ae771770SStanislav Sedov 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
1066ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
1067ae771770SStanislav Sedov 	ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1068ae771770SStanislav Sedov 	goto out;
1069ae771770SStanislav Sedov     }
1070c19800e8SDoug Rabson     ret = _kdc_db_fetch(context, config, server_princ,
1071ae771770SStanislav Sedov 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
1072ae771770SStanislav Sedov 			NULL, NULL, &server);
1073ae771770SStanislav Sedov     if(ret == HDB_ERR_NOT_FOUND_HERE) {
1074ae771770SStanislav Sedov 	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name);
1075ae771770SStanislav Sedov 	goto out;
1076ae771770SStanislav Sedov     } else if(ret){
1077ae771770SStanislav Sedov 	const char *msg = krb5_get_error_message(context, ret);
1078ae771770SStanislav Sedov 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
1079ae771770SStanislav Sedov 	krb5_free_error_message(context, msg);
1080b528cefcSMark Murray 	ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1081b528cefcSMark Murray 	goto out;
1082b528cefcSMark Murray     }
1083b528cefcSMark Murray 
1084b528cefcSMark Murray     memset(&et, 0, sizeof(et));
1085b528cefcSMark Murray     memset(&ek, 0, sizeof(ek));
1086b528cefcSMark Murray 
1087ae771770SStanislav Sedov     /*
1088ae771770SStanislav Sedov      * Select a session enctype from the list of the crypto system
1089ae771770SStanislav Sedov      * supported enctypes that is supported by the client and is one of
1090ae771770SStanislav Sedov      * the enctype of the enctype of the service (likely krbtgt).
1091ae771770SStanislav Sedov      *
1092ae771770SStanislav Sedov      * The latter is used as a hint of what enctypes all KDC support,
1093ae771770SStanislav Sedov      * to make sure a newer version of KDC won't generate a session
1094ae771770SStanislav Sedov      * enctype that an older version of a KDC in the same realm can't
1095ae771770SStanislav Sedov      * decrypt.
1096ae771770SStanislav Sedov      */
1097*cf771f22SStanislav Sedov     ret = _kdc_find_etype(context,
1098*cf771f22SStanislav Sedov 			  krb5_principal_is_krbtgt(context, server_princ) ?
1099*cf771f22SStanislav Sedov 			  config->tgt_use_strongest_session_key :
1100*cf771f22SStanislav Sedov 			  config->svc_use_strongest_session_key, FALSE,
1101ae771770SStanislav Sedov 			  client, b->etype.val, b->etype.len, &sessionetype,
1102ae771770SStanislav Sedov 			  NULL);
1103ae771770SStanislav Sedov     if (ret) {
1104ae771770SStanislav Sedov 	kdc_log(context, config, 0,
1105ae771770SStanislav Sedov 		"Client (%s) from %s has no common enctypes with KDC "
1106ae771770SStanislav Sedov 		"to use for the session key",
1107ae771770SStanislav Sedov 		client_name, from);
1108ae771770SStanislav Sedov 	goto out;
1109ae771770SStanislav Sedov     }
1110ae771770SStanislav Sedov     /*
1111ae771770SStanislav Sedov      * But if the KDC admin is paranoid and doesn't want to have "not
1112ae771770SStanislav Sedov      * the best" enctypes on the krbtgt, lets save the best pick from
1113ae771770SStanislav Sedov      * the client list and hope that that will work for any other
1114ae771770SStanislav Sedov      * KDCs.
1115ae771770SStanislav Sedov      */
1116ae771770SStanislav Sedov 
1117ae771770SStanislav Sedov     /*
1118ae771770SStanislav Sedov      * Pre-auth processing
1119ae771770SStanislav Sedov      */
1120ae771770SStanislav Sedov 
1121b528cefcSMark Murray     if(req->padata){
1122c19800e8SDoug Rabson 	int i;
1123c19800e8SDoug Rabson 	const PA_DATA *pa;
1124b528cefcSMark Murray 	int found_pa = 0;
1125c19800e8SDoug Rabson 
1126c19800e8SDoug Rabson 	log_patypes(context, config, req->padata);
1127c19800e8SDoug Rabson 
1128c19800e8SDoug Rabson #ifdef PKINIT
1129c19800e8SDoug Rabson 	kdc_log(context, config, 5,
1130c19800e8SDoug Rabson 		"Looking for PKINIT pa-data -- %s", client_name);
1131c19800e8SDoug Rabson 
1132c19800e8SDoug Rabson 	e_text = "No PKINIT PA found";
1133c19800e8SDoug Rabson 
1134c19800e8SDoug Rabson 	i = 0;
1135ae771770SStanislav Sedov 	pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ);
1136c19800e8SDoug Rabson 	if (pa == NULL) {
1137c19800e8SDoug Rabson 	    i = 0;
1138ae771770SStanislav Sedov 	    pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN);
1139c19800e8SDoug Rabson 	}
1140c19800e8SDoug Rabson 	if (pa) {
1141c19800e8SDoug Rabson 	    char *client_cert = NULL;
1142c19800e8SDoug Rabson 
1143ae771770SStanislav Sedov 	    ret = _kdc_pk_rd_padata(context, config, req, pa, client, &pkp);
1144c19800e8SDoug Rabson 	    if (ret) {
1145c19800e8SDoug Rabson 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1146c19800e8SDoug Rabson 		kdc_log(context, config, 5,
1147c19800e8SDoug Rabson 			"Failed to decode PKINIT PA-DATA -- %s",
1148c19800e8SDoug Rabson 			client_name);
1149c19800e8SDoug Rabson 		goto ts_enc;
1150c19800e8SDoug Rabson 	    }
1151c19800e8SDoug Rabson 	    if (ret == 0 && pkp == NULL)
1152c19800e8SDoug Rabson 		goto ts_enc;
1153c19800e8SDoug Rabson 
1154c19800e8SDoug Rabson 	    ret = _kdc_pk_check_client(context,
1155c19800e8SDoug Rabson 				       config,
1156ae771770SStanislav Sedov 				       clientdb,
1157c19800e8SDoug Rabson 				       client,
1158c19800e8SDoug Rabson 				       pkp,
1159c19800e8SDoug Rabson 				       &client_cert);
1160c19800e8SDoug Rabson 	    if (ret) {
1161c19800e8SDoug Rabson 		e_text = "PKINIT certificate not allowed to "
1162c19800e8SDoug Rabson 		    "impersonate principal";
1163c19800e8SDoug Rabson 		_kdc_pk_free_client_param(context, pkp);
1164c19800e8SDoug Rabson 
1165c19800e8SDoug Rabson 		kdc_log(context, config, 0, "%s", e_text);
1166c19800e8SDoug Rabson 		pkp = NULL;
1167c19800e8SDoug Rabson 		goto out;
1168c19800e8SDoug Rabson 	    }
1169ae771770SStanislav Sedov 
1170c19800e8SDoug Rabson 	    found_pa = 1;
1171c19800e8SDoug Rabson 	    et.flags.pre_authent = 1;
1172c19800e8SDoug Rabson 	    kdc_log(context, config, 0,
1173c19800e8SDoug Rabson 		    "PKINIT pre-authentication succeeded -- %s using %s",
1174c19800e8SDoug Rabson 		    client_name, client_cert);
1175c19800e8SDoug Rabson 	    free(client_cert);
1176c19800e8SDoug Rabson 	    if (pkp)
1177c19800e8SDoug Rabson 		goto preauth_done;
1178c19800e8SDoug Rabson 	}
1179c19800e8SDoug Rabson     ts_enc:
1180c19800e8SDoug Rabson #endif
1181c19800e8SDoug Rabson 	kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
1182c19800e8SDoug Rabson 		client_name);
1183c19800e8SDoug Rabson 
1184c19800e8SDoug Rabson 	i = 0;
1185c19800e8SDoug Rabson 	e_text = "No ENC-TS found";
1186c19800e8SDoug Rabson 	while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
1187b528cefcSMark Murray 	    krb5_data ts_data;
1188b528cefcSMark Murray 	    PA_ENC_TS_ENC p;
1189b528cefcSMark Murray 	    size_t len;
1190b528cefcSMark Murray 	    EncryptedData enc_data;
1191b528cefcSMark Murray 	    Key *pa_key;
1192c19800e8SDoug Rabson 	    char *str;
1193b528cefcSMark Murray 
1194b528cefcSMark Murray 	    found_pa = 1;
1195b528cefcSMark Murray 
1196ae771770SStanislav Sedov 	    if (b->kdc_options.request_anonymous) {
1197ae771770SStanislav Sedov 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1198ae771770SStanislav Sedov 		kdc_log(context, config, 0, "ENC-TS doesn't support anon");
1199ae771770SStanislav Sedov 		goto out;
1200ae771770SStanislav Sedov 	    }
1201ae771770SStanislav Sedov 
1202b528cefcSMark Murray 	    ret = decode_EncryptedData(pa->padata_value.data,
1203b528cefcSMark Murray 				       pa->padata_value.length,
1204b528cefcSMark Murray 				       &enc_data,
1205b528cefcSMark Murray 				       &len);
1206b528cefcSMark Murray 	    if (ret) {
1207b528cefcSMark Murray 		ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1208c19800e8SDoug Rabson 		kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
1209b528cefcSMark Murray 			client_name);
1210b528cefcSMark Murray 		goto out;
1211b528cefcSMark Murray 	    }
1212b528cefcSMark Murray 
1213c19800e8SDoug Rabson 	    ret = hdb_enctype2key(context, &client->entry,
1214c19800e8SDoug Rabson 				  enc_data.etype, &pa_key);
1215b528cefcSMark Murray 	    if(ret){
1216b528cefcSMark Murray 		char *estr;
1217b528cefcSMark Murray 		e_text = "No key matches pa-data";
1218c19800e8SDoug Rabson 		ret = KRB5KDC_ERR_ETYPE_NOSUPP;
1219b528cefcSMark Murray 		if(krb5_enctype_to_string(context, enc_data.etype, &estr))
1220b528cefcSMark Murray 		    estr = NULL;
1221b528cefcSMark Murray 		if(estr == NULL)
1222c19800e8SDoug Rabson 		    kdc_log(context, config, 5,
1223c19800e8SDoug Rabson 			    "No client key matching pa-data (%d) -- %s",
1224b528cefcSMark Murray 			    enc_data.etype, client_name);
1225b528cefcSMark Murray 		else
1226c19800e8SDoug Rabson 		    kdc_log(context, config, 5,
1227c19800e8SDoug Rabson 			    "No client key matching pa-data (%s) -- %s",
1228b528cefcSMark Murray 			    estr, client_name);
1229b528cefcSMark Murray 		free(estr);
1230b528cefcSMark Murray 		free_EncryptedData(&enc_data);
1231ae771770SStanislav Sedov 
1232b528cefcSMark Murray 		continue;
1233b528cefcSMark Murray 	    }
1234b528cefcSMark Murray 
12358373020dSJacques Vidrine 	try_next_key:
12365e9cd1aeSAssar Westerlund 	    ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
12375e9cd1aeSAssar Westerlund 	    if (ret) {
1238ae771770SStanislav Sedov 		const char *msg = krb5_get_error_message(context, ret);
1239ae771770SStanislav Sedov 		kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
1240ae771770SStanislav Sedov 		krb5_free_error_message(context, msg);
12415e9cd1aeSAssar Westerlund 		free_EncryptedData(&enc_data);
12425e9cd1aeSAssar Westerlund 		continue;
12435e9cd1aeSAssar Westerlund 	    }
12445e9cd1aeSAssar Westerlund 
1245b528cefcSMark Murray 	    ret = krb5_decrypt_EncryptedData (context,
1246b528cefcSMark Murray 					      crypto,
1247b528cefcSMark Murray 					      KRB5_KU_PA_ENC_TIMESTAMP,
1248b528cefcSMark Murray 					      &enc_data,
1249b528cefcSMark Murray 					      &ts_data);
1250b528cefcSMark Murray 	    krb5_crypto_destroy(context, crypto);
1251ae771770SStanislav Sedov 	    /*
1252ae771770SStanislav Sedov 	     * Since the user might have several keys with the same
1253ae771770SStanislav Sedov 	     * enctype but with diffrent salting, we need to try all
1254ae771770SStanislav Sedov 	     * the keys with the same enctype.
1255ae771770SStanislav Sedov 	     */
1256b528cefcSMark Murray 	    if(ret){
1257c19800e8SDoug Rabson 		krb5_error_code ret2;
1258ae771770SStanislav Sedov 		const char *msg = krb5_get_error_message(context, ret);
1259ae771770SStanislav Sedov 
1260c19800e8SDoug Rabson 		ret2 = krb5_enctype_to_string(context,
1261c19800e8SDoug Rabson 					      pa_key->key.keytype, &str);
1262c19800e8SDoug Rabson 		if (ret2)
1263c19800e8SDoug Rabson 		    str = NULL;
1264c19800e8SDoug Rabson 		kdc_log(context, config, 5,
1265c19800e8SDoug Rabson 			"Failed to decrypt PA-DATA -- %s "
1266c19800e8SDoug Rabson 			"(enctype %s) error %s",
1267ae771770SStanislav Sedov 			client_name, str ? str : "unknown enctype", msg);
1268ae771770SStanislav Sedov 		krb5_free_error_message(context, msg);
1269c19800e8SDoug Rabson 		free(str);
1270c19800e8SDoug Rabson 
1271c19800e8SDoug Rabson 		if(hdb_next_enctype2key(context, &client->entry,
12728373020dSJacques Vidrine 					enc_data.etype, &pa_key) == 0)
12738373020dSJacques Vidrine 		    goto try_next_key;
1274b528cefcSMark Murray 		e_text = "Failed to decrypt PA-DATA";
1275c19800e8SDoug Rabson 
1276c19800e8SDoug Rabson 		free_EncryptedData(&enc_data);
1277ae771770SStanislav Sedov 
1278ae771770SStanislav Sedov 		if (clientdb->hdb_auth_status)
1279ae771770SStanislav Sedov 		    (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD);
1280ae771770SStanislav Sedov 
1281c19800e8SDoug Rabson 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
1282b528cefcSMark Murray 		continue;
1283b528cefcSMark Murray 	    }
12848373020dSJacques Vidrine 	    free_EncryptedData(&enc_data);
1285b528cefcSMark Murray 	    ret = decode_PA_ENC_TS_ENC(ts_data.data,
1286b528cefcSMark Murray 				       ts_data.length,
1287b528cefcSMark Murray 				       &p,
1288b528cefcSMark Murray 				       &len);
1289b528cefcSMark Murray 	    krb5_data_free(&ts_data);
1290b528cefcSMark Murray 	    if(ret){
1291b528cefcSMark Murray 		e_text = "Failed to decode PA-ENC-TS-ENC";
1292c19800e8SDoug Rabson 		ret = KRB5KDC_ERR_PREAUTH_FAILED;
1293c19800e8SDoug Rabson 		kdc_log(context, config,
1294c19800e8SDoug Rabson 			5, "Failed to decode PA-ENC-TS_ENC -- %s",
1295b528cefcSMark Murray 			client_name);
1296b528cefcSMark Murray 		continue;
1297b528cefcSMark Murray 	    }
1298b528cefcSMark Murray 	    free_PA_ENC_TS_ENC(&p);
1299b528cefcSMark Murray 	    if (abs(kdc_time - p.patimestamp) > context->max_skew) {
1300c19800e8SDoug Rabson 		char client_time[100];
1301c19800e8SDoug Rabson 
1302c19800e8SDoug Rabson 		krb5_format_time(context, p.patimestamp,
1303c19800e8SDoug Rabson 				 client_time, sizeof(client_time), TRUE);
1304c19800e8SDoug Rabson 
1305c19800e8SDoug Rabson  		ret = KRB5KRB_AP_ERR_SKEW;
1306c19800e8SDoug Rabson  		kdc_log(context, config, 0,
1307c19800e8SDoug Rabson 			"Too large time skew, "
1308c19800e8SDoug Rabson 			"client time %s is out by %u > %u seconds -- %s",
1309c19800e8SDoug Rabson 			client_time,
1310c19800e8SDoug Rabson 			(unsigned)abs(kdc_time - p.patimestamp),
1311c19800e8SDoug Rabson 			context->max_skew,
1312c19800e8SDoug Rabson 			client_name);
1313ae771770SStanislav Sedov 
1314c19800e8SDoug Rabson 		/*
1315ae771770SStanislav Sedov 		 * The following is needed to make windows clients to
1316ae771770SStanislav Sedov 		 * retry using the timestamp in the error message, if
1317ae771770SStanislav Sedov 		 * there is a e_text, they become unhappy.
1318c19800e8SDoug Rabson 		 */
1319c19800e8SDoug Rabson 		e_text = NULL;
1320b528cefcSMark Murray 		goto out;
1321b528cefcSMark Murray 	    }
1322b528cefcSMark Murray 	    et.flags.pre_authent = 1;
1323c19800e8SDoug Rabson 
1324ae771770SStanislav Sedov 	    set_salt_padata(rep.padata, pa_key->salt);
1325ae771770SStanislav Sedov 
1326ae771770SStanislav Sedov 	    reply_key = &pa_key->key;
1327ae771770SStanislav Sedov 
1328c19800e8SDoug Rabson 	    ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str);
1329c19800e8SDoug Rabson 	    if (ret)
1330c19800e8SDoug Rabson 		str = NULL;
1331c19800e8SDoug Rabson 
1332c19800e8SDoug Rabson 	    kdc_log(context, config, 2,
1333c19800e8SDoug Rabson 		    "ENC-TS Pre-authentication succeeded -- %s using %s",
1334c19800e8SDoug Rabson 		    client_name, str ? str : "unknown enctype");
1335c19800e8SDoug Rabson 	    free(str);
1336b528cefcSMark Murray 	    break;
1337b528cefcSMark Murray 	}
1338c19800e8SDoug Rabson #ifdef PKINIT
1339c19800e8SDoug Rabson     preauth_done:
1340c19800e8SDoug Rabson #endif
1341c19800e8SDoug Rabson 	if(found_pa == 0 && config->require_preauth)
1342b528cefcSMark Murray 	    goto use_pa;
1343b528cefcSMark Murray 	/* We come here if we found a pa-enc-timestamp, but if there
1344b528cefcSMark Murray            was some problem with it, other than too large skew */
1345b528cefcSMark Murray 	if(found_pa && et.flags.pre_authent == 0){
1346c19800e8SDoug Rabson 	    kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
1347b528cefcSMark Murray 	    e_text = NULL;
1348b528cefcSMark Murray 	    goto out;
1349b528cefcSMark Murray 	}
1350c19800e8SDoug Rabson     }else if (config->require_preauth
1351ae771770SStanislav Sedov 	      || b->kdc_options.request_anonymous /* hack to force anon */
1352c19800e8SDoug Rabson 	      || client->entry.flags.require_preauth
1353c19800e8SDoug Rabson 	      || server->entry.flags.require_preauth) {
1354b528cefcSMark Murray 	METHOD_DATA method_data;
1355b528cefcSMark Murray 	PA_DATA *pa;
1356b528cefcSMark Murray 	unsigned char *buf;
1357b528cefcSMark Murray 	size_t len;
1358b528cefcSMark Murray 
1359b528cefcSMark Murray     use_pa:
1360b528cefcSMark Murray 	method_data.len = 0;
1361b528cefcSMark Murray 	method_data.val = NULL;
1362b528cefcSMark Murray 
1363b528cefcSMark Murray 	ret = realloc_method_data(&method_data);
1364ae771770SStanislav Sedov 	if (ret) {
1365ae771770SStanislav Sedov 	    free_METHOD_DATA(&method_data);
1366ae771770SStanislav Sedov 	    goto out;
1367ae771770SStanislav Sedov 	}
1368b528cefcSMark Murray 	pa = &method_data.val[method_data.len-1];
13695e9cd1aeSAssar Westerlund 	pa->padata_type		= KRB5_PADATA_ENC_TIMESTAMP;
1370b528cefcSMark Murray 	pa->padata_value.length	= 0;
1371b528cefcSMark Murray 	pa->padata_value.data	= NULL;
1372b528cefcSMark Murray 
1373c19800e8SDoug Rabson #ifdef PKINIT
1374c19800e8SDoug Rabson 	ret = realloc_method_data(&method_data);
1375ae771770SStanislav Sedov 	if (ret) {
1376ae771770SStanislav Sedov 	    free_METHOD_DATA(&method_data);
1377ae771770SStanislav Sedov 	    goto out;
1378ae771770SStanislav Sedov 	}
1379c19800e8SDoug Rabson 	pa = &method_data.val[method_data.len-1];
1380c19800e8SDoug Rabson 	pa->padata_type		= KRB5_PADATA_PK_AS_REQ;
1381c19800e8SDoug Rabson 	pa->padata_value.length	= 0;
1382c19800e8SDoug Rabson 	pa->padata_value.data	= NULL;
1383c19800e8SDoug Rabson 
1384c19800e8SDoug Rabson 	ret = realloc_method_data(&method_data);
1385ae771770SStanislav Sedov 	if (ret) {
1386ae771770SStanislav Sedov 	    free_METHOD_DATA(&method_data);
1387ae771770SStanislav Sedov 	    goto out;
1388ae771770SStanislav Sedov 	}
1389c19800e8SDoug Rabson 	pa = &method_data.val[method_data.len-1];
1390c19800e8SDoug Rabson 	pa->padata_type		= KRB5_PADATA_PK_AS_REQ_WIN;
1391c19800e8SDoug Rabson 	pa->padata_value.length	= 0;
1392c19800e8SDoug Rabson 	pa->padata_value.data	= NULL;
1393c19800e8SDoug Rabson #endif
1394c19800e8SDoug Rabson 
1395c19800e8SDoug Rabson 	/*
1396ae771770SStanislav Sedov 	 * If there is a client key, send ETYPE_INFO{,2}
1397ae771770SStanislav Sedov 	 */
1398ae771770SStanislav Sedov 	ret = _kdc_find_etype(context,
1399ae771770SStanislav Sedov 			      config->preauth_use_strongest_session_key, TRUE,
1400ae771770SStanislav Sedov 			      client, b->etype.val, b->etype.len, NULL, &ckey);
1401ae771770SStanislav Sedov 	if (ret == 0) {
1402ae771770SStanislav Sedov 
1403ae771770SStanislav Sedov 	    /*
1404c19800e8SDoug Rabson 	     * RFC4120 requires:
1405c19800e8SDoug Rabson 	     * - If the client only knows about old enctypes, then send
1406c19800e8SDoug Rabson 	     *   both info replies (we send 'info' first in the list).
1407c19800e8SDoug Rabson 	     * - If the client is 'modern', because it knows about 'new'
1408c19800e8SDoug Rabson 	     *   enctype types, then only send the 'info2' reply.
1409ae771770SStanislav Sedov 	     *
1410ae771770SStanislav Sedov 	     * Before we send the full list of etype-info data, we pick
1411ae771770SStanislav Sedov 	     * the client key we would have used anyway below, just pick
1412ae771770SStanislav Sedov 	     * that instead.
1413c19800e8SDoug Rabson 	     */
1414c19800e8SDoug Rabson 
1415ae771770SStanislav Sedov 	    if (older_enctype(ckey->key.keytype)) {
1416c19800e8SDoug Rabson 		ret = get_pa_etype_info(context, config,
1417ae771770SStanislav Sedov 					&method_data, ckey);
1418ae771770SStanislav Sedov 		if (ret) {
1419ae771770SStanislav Sedov 		    free_METHOD_DATA(&method_data);
1420ae771770SStanislav Sedov 		    goto out;
1421ae771770SStanislav Sedov 		}
1422ae771770SStanislav Sedov 	    }
1423ae771770SStanislav Sedov 	    ret = get_pa_etype_info2(context, config,
1424ae771770SStanislav Sedov 				     &method_data, ckey);
1425ae771770SStanislav Sedov 	    if (ret) {
1426ae771770SStanislav Sedov 		free_METHOD_DATA(&method_data);
1427ae771770SStanislav Sedov 		goto out;
1428ae771770SStanislav Sedov 	    }
1429ae771770SStanislav Sedov 	}
1430b528cefcSMark Murray 
14310cadf2f4SJacques Vidrine 	ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
1432b528cefcSMark Murray 	free_METHOD_DATA(&method_data);
1433c19800e8SDoug Rabson 
1434c19800e8SDoug Rabson 	e_data.data   = buf;
1435c19800e8SDoug Rabson 	e_data.length = len;
1436c19800e8SDoug Rabson 	e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
1437b528cefcSMark Murray 
1438b528cefcSMark Murray 	ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
1439b528cefcSMark Murray 
1440c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1441c19800e8SDoug Rabson 		"No preauth found, returning PREAUTH-REQUIRED -- %s",
1442c19800e8SDoug Rabson 		client_name);
1443b528cefcSMark Murray 	goto out;
1444b528cefcSMark Murray     }
1445b528cefcSMark Murray 
1446ae771770SStanislav Sedov     if (clientdb->hdb_auth_status)
1447ae771770SStanislav Sedov 	(clientdb->hdb_auth_status)(context, clientdb, client,
1448ae771770SStanislav Sedov 				    HDB_AUTH_SUCCESS);
1449ae771770SStanislav Sedov 
1450c19800e8SDoug Rabson     /*
1451ae771770SStanislav Sedov      * Verify flags after the user been required to prove its identity
1452ae771770SStanislav Sedov      * with in a preauth mech.
1453c19800e8SDoug Rabson      */
1454c19800e8SDoug Rabson 
1455ae771770SStanislav Sedov     ret = _kdc_check_access(context, config, client, client_name,
1456ae771770SStanislav Sedov 			    server, server_name,
1457ae771770SStanislav Sedov 			    req, &e_data);
1458ae771770SStanislav Sedov     if(ret)
1459c19800e8SDoug Rabson 	goto out;
1460ae771770SStanislav Sedov 
1461ae771770SStanislav Sedov     /*
1462ae771770SStanislav Sedov      * Selelct the best encryption type for the KDC with out regard to
1463ae771770SStanislav Sedov      * the client since the client never needs to read that data.
1464ae771770SStanislav Sedov      */
1465c19800e8SDoug Rabson 
1466c19800e8SDoug Rabson     ret = _kdc_get_preferred_key(context, config,
1467c19800e8SDoug Rabson 				 server, server_name,
1468c19800e8SDoug Rabson 				 &setype, &skey);
1469c19800e8SDoug Rabson     if(ret)
1470c19800e8SDoug Rabson 	goto out;
1471c19800e8SDoug Rabson 
14725e9cd1aeSAssar Westerlund     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
1473c19800e8SDoug Rabson        || (f.request_anonymous && !config->allow_anonymous)) {
1474b528cefcSMark Murray 	ret = KRB5KDC_ERR_BADOPTION;
1475ae771770SStanislav Sedov 	e_text = "Bad KDC options";
1476c19800e8SDoug Rabson 	kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
1477b528cefcSMark Murray 	goto out;
1478b528cefcSMark Murray     }
1479b528cefcSMark Murray 
14805e9cd1aeSAssar Westerlund     rep.pvno = 5;
14815e9cd1aeSAssar Westerlund     rep.msg_type = krb_as_rep;
1482ae771770SStanislav Sedov 
1483ae771770SStanislav Sedov     ret = copy_Realm(&client->entry.principal->realm, &rep.crealm);
1484ae771770SStanislav Sedov     if (ret)
1485ae771770SStanislav Sedov 	goto out;
1486ae771770SStanislav Sedov     ret = _krb5_principal2principalname(&rep.cname, client->entry.principal);
1487ae771770SStanislav Sedov     if (ret)
1488ae771770SStanislav Sedov 	goto out;
1489ae771770SStanislav Sedov 
14905e9cd1aeSAssar Westerlund     rep.ticket.tkt_vno = 5;
1491c19800e8SDoug Rabson     copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
1492c19800e8SDoug Rabson     _krb5_principal2principalname(&rep.ticket.sname,
1493c19800e8SDoug Rabson 				  server->entry.principal);
1494c19800e8SDoug Rabson     /* java 1.6 expects the name to be the same type, lets allow that
1495c19800e8SDoug Rabson      * uncomplicated name-types. */
1496c19800e8SDoug Rabson #define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
1497c19800e8SDoug Rabson     if (CNT(b, UNKNOWN) || CNT(b, PRINCIPAL) || CNT(b, SRV_INST) || CNT(b, SRV_HST) || CNT(b, SRV_XHST))
1498c19800e8SDoug Rabson 	rep.ticket.sname.name_type = b->sname->name_type;
1499c19800e8SDoug Rabson #undef CNT
15005e9cd1aeSAssar Westerlund 
1501b528cefcSMark Murray     et.flags.initial = 1;
1502c19800e8SDoug Rabson     if(client->entry.flags.forwardable && server->entry.flags.forwardable)
1503b528cefcSMark Murray 	et.flags.forwardable = f.forwardable;
1504b528cefcSMark Murray     else if (f.forwardable) {
1505ae771770SStanislav Sedov 	e_text = "Ticket may not be forwardable";
1506b528cefcSMark Murray 	ret = KRB5KDC_ERR_POLICY;
1507c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1508c19800e8SDoug Rabson 		"Ticket may not be forwardable -- %s", client_name);
1509b528cefcSMark Murray 	goto out;
1510b528cefcSMark Murray     }
1511c19800e8SDoug Rabson     if(client->entry.flags.proxiable && server->entry.flags.proxiable)
1512b528cefcSMark Murray 	et.flags.proxiable = f.proxiable;
1513b528cefcSMark Murray     else if (f.proxiable) {
1514ae771770SStanislav Sedov 	e_text = "Ticket may not be proxiable";
1515b528cefcSMark Murray 	ret = KRB5KDC_ERR_POLICY;
1516c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1517c19800e8SDoug Rabson 		"Ticket may not be proxiable -- %s", client_name);
1518b528cefcSMark Murray 	goto out;
1519b528cefcSMark Murray     }
1520c19800e8SDoug Rabson     if(client->entry.flags.postdate && server->entry.flags.postdate)
1521b528cefcSMark Murray 	et.flags.may_postdate = f.allow_postdate;
1522b528cefcSMark Murray     else if (f.allow_postdate){
1523ae771770SStanislav Sedov 	e_text = "Ticket may not be postdate";
1524b528cefcSMark Murray 	ret = KRB5KDC_ERR_POLICY;
1525c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1526c19800e8SDoug Rabson 		"Ticket may not be postdatable -- %s", client_name);
1527b528cefcSMark Murray 	goto out;
1528b528cefcSMark Murray     }
1529b528cefcSMark Murray 
1530b528cefcSMark Murray     /* check for valid set of addresses */
1531c19800e8SDoug Rabson     if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
1532ae771770SStanislav Sedov 	e_text = "Bad address list in requested";
1533b528cefcSMark Murray 	ret = KRB5KRB_AP_ERR_BADADDR;
1534c19800e8SDoug Rabson 	kdc_log(context, config, 0,
1535c19800e8SDoug Rabson 		"Bad address list requested -- %s", client_name);
1536b528cefcSMark Murray 	goto out;
1537b528cefcSMark Murray     }
1538b528cefcSMark Murray 
1539ae771770SStanislav Sedov     ret = copy_PrincipalName(&rep.cname, &et.cname);
1540c19800e8SDoug Rabson     if (ret)
1541c19800e8SDoug Rabson 	goto out;
1542ae771770SStanislav Sedov     ret = copy_Realm(&rep.crealm, &et.crealm);
1543ae771770SStanislav Sedov     if (ret)
1544ae771770SStanislav Sedov 	goto out;
1545b528cefcSMark Murray 
1546b528cefcSMark Murray     {
1547b528cefcSMark Murray 	time_t start;
1548b528cefcSMark Murray 	time_t t;
1549b528cefcSMark Murray 
1550b528cefcSMark Murray 	start = et.authtime = kdc_time;
1551b528cefcSMark Murray 
1552b528cefcSMark Murray 	if(f.postdated && req->req_body.from){
1553b528cefcSMark Murray 	    ALLOC(et.starttime);
1554b528cefcSMark Murray 	    start = *et.starttime = *req->req_body.from;
1555b528cefcSMark Murray 	    et.flags.invalid = 1;
1556b528cefcSMark Murray 	    et.flags.postdated = 1; /* XXX ??? */
1557b528cefcSMark Murray 	}
1558c19800e8SDoug Rabson 	_kdc_fix_time(&b->till);
1559b528cefcSMark Murray 	t = *b->till;
15605e9cd1aeSAssar Westerlund 
15615e9cd1aeSAssar Westerlund 	/* be careful not overflowing */
15625e9cd1aeSAssar Westerlund 
1563c19800e8SDoug Rabson 	if(client->entry.max_life)
1564c19800e8SDoug Rabson 	    t = start + min(t - start, *client->entry.max_life);
1565c19800e8SDoug Rabson 	if(server->entry.max_life)
1566c19800e8SDoug Rabson 	    t = start + min(t - start, *server->entry.max_life);
1567b528cefcSMark Murray #if 0
1568b528cefcSMark Murray 	t = min(t, start + realm->max_life);
1569b528cefcSMark Murray #endif
1570b528cefcSMark Murray 	et.endtime = t;
1571b528cefcSMark Murray 	if(f.renewable_ok && et.endtime < *b->till){
1572b528cefcSMark Murray 	    f.renewable = 1;
1573b528cefcSMark Murray 	    if(b->rtime == NULL){
1574b528cefcSMark Murray 		ALLOC(b->rtime);
1575b528cefcSMark Murray 		*b->rtime = 0;
1576b528cefcSMark Murray 	    }
1577b528cefcSMark Murray 	    if(*b->rtime < *b->till)
1578b528cefcSMark Murray 		*b->rtime = *b->till;
1579b528cefcSMark Murray 	}
1580b528cefcSMark Murray 	if(f.renewable && b->rtime){
1581b528cefcSMark Murray 	    t = *b->rtime;
1582b528cefcSMark Murray 	    if(t == 0)
1583b528cefcSMark Murray 		t = MAX_TIME;
1584c19800e8SDoug Rabson 	    if(client->entry.max_renew)
1585c19800e8SDoug Rabson 		t = start + min(t - start, *client->entry.max_renew);
1586c19800e8SDoug Rabson 	    if(server->entry.max_renew)
1587c19800e8SDoug Rabson 		t = start + min(t - start, *server->entry.max_renew);
1588b528cefcSMark Murray #if 0
1589b528cefcSMark Murray 	    t = min(t, start + realm->max_renew);
1590b528cefcSMark Murray #endif
1591b528cefcSMark Murray 	    ALLOC(et.renew_till);
1592b528cefcSMark Murray 	    *et.renew_till = t;
1593b528cefcSMark Murray 	    et.flags.renewable = 1;
1594b528cefcSMark Murray 	}
1595b528cefcSMark Murray     }
1596b528cefcSMark Murray 
15975e9cd1aeSAssar Westerlund     if (f.request_anonymous)
15985e9cd1aeSAssar Westerlund 	et.flags.anonymous = 1;
15995e9cd1aeSAssar Westerlund 
1600b528cefcSMark Murray     if(b->addresses){
1601b528cefcSMark Murray 	ALLOC(et.caddr);
1602b528cefcSMark Murray 	copy_HostAddresses(b->addresses, et.caddr);
1603b528cefcSMark Murray     }
1604b528cefcSMark Murray 
1605b528cefcSMark Murray     et.transited.tr_type = DOMAIN_X500_COMPRESS;
16061c43270aSJacques Vidrine     krb5_data_zero(&et.transited.contents);
1607b528cefcSMark Murray 
1608b528cefcSMark Murray     /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
1609b528cefcSMark Murray      * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
1610b528cefcSMark Murray      * incapable of correctly decoding SEQUENCE OF's of zero length.
1611b528cefcSMark Murray      *
1612b528cefcSMark Murray      * To fix this, always send at least one no-op last_req
1613b528cefcSMark Murray      *
1614b528cefcSMark Murray      * If there's a pw_end or valid_end we will use that,
1615b528cefcSMark Murray      * otherwise just a dummy lr.
1616b528cefcSMark Murray      */
1617b528cefcSMark Murray     ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
1618c19800e8SDoug Rabson     if (ek.last_req.val == NULL) {
1619c19800e8SDoug Rabson 	ret = ENOMEM;
1620c19800e8SDoug Rabson 	goto out;
1621c19800e8SDoug Rabson     }
1622b528cefcSMark Murray     ek.last_req.len = 0;
1623c19800e8SDoug Rabson     if (client->entry.pw_end
1624c19800e8SDoug Rabson 	&& (config->kdc_warn_pwexpire == 0
1625c19800e8SDoug Rabson 	    || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
1626adb0ddaeSAssar Westerlund 	ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
1627c19800e8SDoug Rabson 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
1628b528cefcSMark Murray 	++ek.last_req.len;
1629b528cefcSMark Murray     }
1630c19800e8SDoug Rabson     if (client->entry.valid_end) {
1631adb0ddaeSAssar Westerlund 	ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
1632c19800e8SDoug Rabson 	ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
1633b528cefcSMark Murray 	++ek.last_req.len;
1634b528cefcSMark Murray     }
1635b528cefcSMark Murray     if (ek.last_req.len == 0) {
1636adb0ddaeSAssar Westerlund 	ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
1637b528cefcSMark Murray 	ek.last_req.val[ek.last_req.len].lr_value = 0;
1638b528cefcSMark Murray 	++ek.last_req.len;
1639b528cefcSMark Murray     }
1640b528cefcSMark Murray     ek.nonce = b->nonce;
1641c19800e8SDoug Rabson     if (client->entry.valid_end || client->entry.pw_end) {
1642b528cefcSMark Murray 	ALLOC(ek.key_expiration);
1643c19800e8SDoug Rabson 	if (client->entry.valid_end) {
1644c19800e8SDoug Rabson 	    if (client->entry.pw_end)
1645c19800e8SDoug Rabson 		*ek.key_expiration = min(*client->entry.valid_end,
1646c19800e8SDoug Rabson 					 *client->entry.pw_end);
1647b528cefcSMark Murray 	    else
1648c19800e8SDoug Rabson 		*ek.key_expiration = *client->entry.valid_end;
1649b528cefcSMark Murray 	} else
1650c19800e8SDoug Rabson 	    *ek.key_expiration = *client->entry.pw_end;
1651b528cefcSMark Murray     } else
1652b528cefcSMark Murray 	ek.key_expiration = NULL;
1653b528cefcSMark Murray     ek.flags = et.flags;
1654b528cefcSMark Murray     ek.authtime = et.authtime;
1655b528cefcSMark Murray     if (et.starttime) {
1656b528cefcSMark Murray 	ALLOC(ek.starttime);
1657b528cefcSMark Murray 	*ek.starttime = *et.starttime;
1658b528cefcSMark Murray     }
1659b528cefcSMark Murray     ek.endtime = et.endtime;
1660b528cefcSMark Murray     if (et.renew_till) {
1661b528cefcSMark Murray 	ALLOC(ek.renew_till);
1662b528cefcSMark Murray 	*ek.renew_till = *et.renew_till;
1663b528cefcSMark Murray     }
1664b528cefcSMark Murray     copy_Realm(&rep.ticket.realm, &ek.srealm);
1665b528cefcSMark Murray     copy_PrincipalName(&rep.ticket.sname, &ek.sname);
1666b528cefcSMark Murray     if(et.caddr){
1667b528cefcSMark Murray 	ALLOC(ek.caddr);
1668b528cefcSMark Murray 	copy_HostAddresses(et.caddr, ek.caddr);
1669b528cefcSMark Murray     }
1670b528cefcSMark Murray 
1671c19800e8SDoug Rabson #if PKINIT
1672c19800e8SDoug Rabson     if (pkp) {
1673ae771770SStanislav Sedov         e_text = "Failed to build PK-INIT reply";
1674c19800e8SDoug Rabson 	ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
1675ae771770SStanislav Sedov 				  sessionetype, req, req_buffer,
1676ae771770SStanislav Sedov 				  &reply_key, &et.key, rep.padata);
1677c19800e8SDoug Rabson 	if (ret)
1678c19800e8SDoug Rabson 	    goto out;
1679c19800e8SDoug Rabson 	ret = _kdc_add_inital_verified_cas(context,
1680c19800e8SDoug Rabson 					   config,
1681c19800e8SDoug Rabson 					   pkp,
1682c19800e8SDoug Rabson 					   &et);
1683c19800e8SDoug Rabson 	if (ret)
1684c19800e8SDoug Rabson 	    goto out;
1685c19800e8SDoug Rabson 
1686ae771770SStanislav Sedov     } else
1687ae771770SStanislav Sedov #endif
1688ae771770SStanislav Sedov     {
1689ae771770SStanislav Sedov 	ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
1690ae771770SStanislav Sedov 	if (ret)
1691ae771770SStanislav Sedov 	    goto out;
1692ae771770SStanislav Sedov     }
1693ae771770SStanislav Sedov 
1694ae771770SStanislav Sedov     if (reply_key == NULL) {
1695ae771770SStanislav Sedov 	e_text = "Client have no reply key";
1696ae771770SStanislav Sedov 	ret = KRB5KDC_ERR_CLIENT_NOTYET;
1697ae771770SStanislav Sedov 	goto out;
1698ae771770SStanislav Sedov     }
1699ae771770SStanislav Sedov 
1700ae771770SStanislav Sedov     ret = copy_EncryptionKey(&et.key, &ek.key);
1701ae771770SStanislav Sedov     if (ret)
1702ae771770SStanislav Sedov 	goto out;
1703c19800e8SDoug Rabson 
1704c19800e8SDoug Rabson     /* Add signing of alias referral */
1705c19800e8SDoug Rabson     if (f.canonicalize) {
1706c19800e8SDoug Rabson 	PA_ClientCanonicalized canon;
1707c19800e8SDoug Rabson 	krb5_data data;
1708c19800e8SDoug Rabson 	PA_DATA pa;
1709ae771770SStanislav Sedov 	krb5_crypto cryptox;
1710ae771770SStanislav Sedov 	size_t len = 0;
1711c19800e8SDoug Rabson 
1712c19800e8SDoug Rabson 	memset(&canon, 0, sizeof(canon));
1713c19800e8SDoug Rabson 
1714c19800e8SDoug Rabson 	canon.names.requested_name = *b->cname;
1715ae771770SStanislav Sedov 	canon.names.mapped_name = client->entry.principal->name;
1716c19800e8SDoug Rabson 
1717c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
1718c19800e8SDoug Rabson 			   &canon.names, &len, ret);
1719c19800e8SDoug Rabson 	if (ret)
1720c19800e8SDoug Rabson 	    goto out;
1721c19800e8SDoug Rabson 	if (data.length != len)
1722c19800e8SDoug Rabson 	    krb5_abortx(context, "internal asn.1 error");
1723c19800e8SDoug Rabson 
1724c19800e8SDoug Rabson 	/* sign using "returned session key" */
1725ae771770SStanislav Sedov 	ret = krb5_crypto_init(context, &et.key, 0, &cryptox);
1726c19800e8SDoug Rabson 	if (ret) {
1727c19800e8SDoug Rabson 	    free(data.data);
1728c19800e8SDoug Rabson 	    goto out;
1729c19800e8SDoug Rabson 	}
1730c19800e8SDoug Rabson 
1731ae771770SStanislav Sedov 	ret = krb5_create_checksum(context, cryptox,
1732c19800e8SDoug Rabson 				   KRB5_KU_CANONICALIZED_NAMES, 0,
1733c19800e8SDoug Rabson 				   data.data, data.length,
1734c19800e8SDoug Rabson 				   &canon.canon_checksum);
1735c19800e8SDoug Rabson 	free(data.data);
1736ae771770SStanislav Sedov 	krb5_crypto_destroy(context, cryptox);
1737c19800e8SDoug Rabson 	if (ret)
1738c19800e8SDoug Rabson 	    goto out;
1739c19800e8SDoug Rabson 
1740c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
1741c19800e8SDoug Rabson 			   &canon, &len, ret);
1742c19800e8SDoug Rabson 	free_Checksum(&canon.canon_checksum);
1743c19800e8SDoug Rabson 	if (ret)
1744c19800e8SDoug Rabson 	    goto out;
1745c19800e8SDoug Rabson 	if (data.length != len)
1746c19800e8SDoug Rabson 	    krb5_abortx(context, "internal asn.1 error");
1747c19800e8SDoug Rabson 
1748c19800e8SDoug Rabson 	pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
1749c19800e8SDoug Rabson 	pa.padata_value = data;
1750c19800e8SDoug Rabson 	ret = add_METHOD_DATA(rep.padata, &pa);
1751c19800e8SDoug Rabson 	free(data.data);
1752c19800e8SDoug Rabson 	if (ret)
1753c19800e8SDoug Rabson 	    goto out;
1754c19800e8SDoug Rabson     }
1755c19800e8SDoug Rabson 
1756c19800e8SDoug Rabson     if (rep.padata->len == 0) {
1757c19800e8SDoug Rabson 	free(rep.padata);
1758c19800e8SDoug Rabson 	rep.padata = NULL;
1759c19800e8SDoug Rabson     }
1760c19800e8SDoug Rabson 
1761c19800e8SDoug Rabson     /* Add the PAC */
1762c19800e8SDoug Rabson     if (send_pac_p(context, req)) {
1763c19800e8SDoug Rabson 	krb5_pac p = NULL;
1764c19800e8SDoug Rabson 	krb5_data data;
1765c19800e8SDoug Rabson 
1766c19800e8SDoug Rabson 	ret = _kdc_pac_generate(context, client, &p);
1767c19800e8SDoug Rabson 	if (ret) {
1768c19800e8SDoug Rabson 	    kdc_log(context, config, 0, "PAC generation failed for -- %s",
1769c19800e8SDoug Rabson 		    client_name);
1770c19800e8SDoug Rabson 	    goto out;
1771c19800e8SDoug Rabson 	}
1772c19800e8SDoug Rabson 	if (p != NULL) {
1773c19800e8SDoug Rabson 	    ret = _krb5_pac_sign(context, p, et.authtime,
1774c19800e8SDoug Rabson 				 client->entry.principal,
1775c19800e8SDoug Rabson 				 &skey->key, /* Server key */
1776c19800e8SDoug Rabson 				 &skey->key, /* FIXME: should be krbtgt key */
1777c19800e8SDoug Rabson 				 &data);
1778c19800e8SDoug Rabson 	    krb5_pac_free(context, p);
1779c19800e8SDoug Rabson 	    if (ret) {
1780c19800e8SDoug Rabson 		kdc_log(context, config, 0, "PAC signing failed for -- %s",
1781c19800e8SDoug Rabson 			client_name);
1782c19800e8SDoug Rabson 		goto out;
1783c19800e8SDoug Rabson 	    }
1784c19800e8SDoug Rabson 
1785c19800e8SDoug Rabson 	    ret = _kdc_tkt_add_if_relevant_ad(context, &et,
1786c19800e8SDoug Rabson 					      KRB5_AUTHDATA_WIN2K_PAC,
1787c19800e8SDoug Rabson 					      &data);
1788c19800e8SDoug Rabson 	    krb5_data_free(&data);
1789c19800e8SDoug Rabson 	    if (ret)
1790c19800e8SDoug Rabson 		goto out;
1791c19800e8SDoug Rabson 	}
1792c19800e8SDoug Rabson     }
1793c19800e8SDoug Rabson 
1794c19800e8SDoug Rabson     _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
1795c19800e8SDoug Rabson 		       et.endtime, et.renew_till);
1796c19800e8SDoug Rabson 
1797c19800e8SDoug Rabson     /* do this as the last thing since this signs the EncTicketPart */
1798c19800e8SDoug Rabson     ret = _kdc_add_KRB5SignedPath(context,
1799c19800e8SDoug Rabson 				  config,
1800c19800e8SDoug Rabson 				  server,
1801c19800e8SDoug Rabson 				  setype,
1802ae771770SStanislav Sedov 				  client->entry.principal,
1803c19800e8SDoug Rabson 				  NULL,
1804c19800e8SDoug Rabson 				  NULL,
1805c19800e8SDoug Rabson 				  &et);
1806c19800e8SDoug Rabson     if (ret)
1807c19800e8SDoug Rabson 	goto out;
1808c19800e8SDoug Rabson 
1809ae771770SStanislav Sedov     log_as_req(context, config, reply_key->keytype, setype, b);
1810ae771770SStanislav Sedov 
1811c19800e8SDoug Rabson     ret = _kdc_encode_reply(context, config,
1812c19800e8SDoug Rabson 			    &rep, &et, &ek, setype, server->entry.kvno,
1813c19800e8SDoug Rabson 			    &skey->key, client->entry.kvno,
1814ae771770SStanislav Sedov 			    reply_key, 0, &e_text, reply);
1815b528cefcSMark Murray     free_EncTicketPart(&et);
1816b528cefcSMark Murray     free_EncKDCRepPart(&ek);
1817c19800e8SDoug Rabson     if (ret)
1818c19800e8SDoug Rabson 	goto out;
1819c19800e8SDoug Rabson 
1820c19800e8SDoug Rabson     /* */
1821c19800e8SDoug Rabson     if (datagram_reply && reply->length > config->max_datagram_reply_length) {
1822c19800e8SDoug Rabson 	krb5_data_free(reply);
1823c19800e8SDoug Rabson 	ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
1824c19800e8SDoug Rabson 	e_text = "Reply packet too large";
1825c19800e8SDoug Rabson     }
1826c19800e8SDoug Rabson 
1827b528cefcSMark Murray out:
1828bbd80c28SJacques Vidrine     free_AS_REP(&rep);
1829ae771770SStanislav Sedov     if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){
1830b528cefcSMark Murray 	krb5_mk_error(context,
1831b528cefcSMark Murray 		      ret,
1832b528cefcSMark Murray 		      e_text,
1833c19800e8SDoug Rabson 		      (e_data.data ? &e_data : NULL),
1834b528cefcSMark Murray 		      client_princ,
1835b528cefcSMark Murray 		      server_princ,
1836adb0ddaeSAssar Westerlund 		      NULL,
1837adb0ddaeSAssar Westerlund 		      NULL,
1838b528cefcSMark Murray 		      reply);
1839b528cefcSMark Murray 	ret = 0;
1840b528cefcSMark Murray     }
1841c19800e8SDoug Rabson #ifdef PKINIT
1842c19800e8SDoug Rabson     if (pkp)
1843c19800e8SDoug Rabson 	_kdc_pk_free_client_param(context, pkp);
1844c19800e8SDoug Rabson #endif
1845c19800e8SDoug Rabson     if (e_data.data)
1846c19800e8SDoug Rabson         free(e_data.data);
18471c43270aSJacques Vidrine     if (client_princ)
1848b528cefcSMark Murray 	krb5_free_principal(context, client_princ);
1849b528cefcSMark Murray     free(client_name);
18501c43270aSJacques Vidrine     if (server_princ)
1851b528cefcSMark Murray 	krb5_free_principal(context, server_princ);
1852b528cefcSMark Murray     free(server_name);
18535e9cd1aeSAssar Westerlund     if(client)
1854c19800e8SDoug Rabson 	_kdc_free_ent(context, client);
18555e9cd1aeSAssar Westerlund     if(server)
1856c19800e8SDoug Rabson 	_kdc_free_ent(context, server);
1857b528cefcSMark Murray     return ret;
1858b528cefcSMark Murray }
1859b528cefcSMark Murray 
1860adb0ddaeSAssar Westerlund /*
1861ae771770SStanislav Sedov  * Add the AuthorizationData `data´ of `type´ to the last element in
1862ae771770SStanislav Sedov  * the sequence of authorization_data in `tkt´ wrapped in an IF_RELEVANT
1863adb0ddaeSAssar Westerlund  */
1864adb0ddaeSAssar Westerlund 
1865b528cefcSMark Murray krb5_error_code
_kdc_tkt_add_if_relevant_ad(krb5_context context,EncTicketPart * tkt,int type,const krb5_data * data)1866c19800e8SDoug Rabson _kdc_tkt_add_if_relevant_ad(krb5_context context,
1867c19800e8SDoug Rabson 			    EncTicketPart *tkt,
1868c19800e8SDoug Rabson 			    int type,
1869c19800e8SDoug Rabson 			    const krb5_data *data)
1870b528cefcSMark Murray {
1871b528cefcSMark Murray     krb5_error_code ret;
1872ae771770SStanislav Sedov     size_t size = 0;
1873b528cefcSMark Murray 
1874c19800e8SDoug Rabson     if (tkt->authorization_data == NULL) {
1875c19800e8SDoug Rabson 	tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data));
1876c19800e8SDoug Rabson 	if (tkt->authorization_data == NULL) {
1877ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOMEM, "out of memory");
1878c19800e8SDoug Rabson 	    return ENOMEM;
1879c19800e8SDoug Rabson 	}
1880b528cefcSMark Murray     }
1881b528cefcSMark Murray 
1882c19800e8SDoug Rabson     /* add the entry to the last element */
1883c19800e8SDoug Rabson     {
1884c19800e8SDoug Rabson 	AuthorizationData ad = { 0, NULL };
1885c19800e8SDoug Rabson 	AuthorizationDataElement ade;
1886b528cefcSMark Murray 
1887c19800e8SDoug Rabson 	ade.ad_type = type;
1888c19800e8SDoug Rabson 	ade.ad_data = *data;
1889b528cefcSMark Murray 
1890c19800e8SDoug Rabson 	ret = add_AuthorizationData(&ad, &ade);
1891c19800e8SDoug Rabson 	if (ret) {
1892ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
1893c19800e8SDoug Rabson 	    return ret;
1894b528cefcSMark Murray 	}
1895c19800e8SDoug Rabson 
1896c19800e8SDoug Rabson 	ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
1897c19800e8SDoug Rabson 
1898c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(AuthorizationData,
1899c19800e8SDoug Rabson 			   ade.ad_data.data, ade.ad_data.length,
1900c19800e8SDoug Rabson 			   &ad, &size, ret);
1901c19800e8SDoug Rabson 	free_AuthorizationData(&ad);
1902c19800e8SDoug Rabson 	if (ret) {
1903ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret, "ASN.1 encode of "
1904c19800e8SDoug Rabson 				   "AuthorizationData failed");
1905c19800e8SDoug Rabson 	    return ret;
1906b528cefcSMark Murray 	}
1907c19800e8SDoug Rabson 	if (ade.ad_data.length != size)
1908c19800e8SDoug Rabson 	    krb5_abortx(context, "internal asn.1 encoder error");
1909c19800e8SDoug Rabson 
1910c19800e8SDoug Rabson 	ret = add_AuthorizationData(tkt->authorization_data, &ade);
1911c19800e8SDoug Rabson 	der_free_octet_string(&ade.ad_data);
1912c19800e8SDoug Rabson 	if (ret) {
1913ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret, "add AuthorizationData failed");
1914c19800e8SDoug Rabson 	    return ret;
1915c19800e8SDoug Rabson 	}
1916c19800e8SDoug Rabson     }
1917c19800e8SDoug Rabson 
1918b528cefcSMark Murray     return 0;
1919b528cefcSMark Murray }
1920