xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/krb5/get_in_tkt.c (revision 241bea01a19bbb306af27777a870b86d41cb3fda)
1*241bea01Schristos /*	$NetBSD: get_in_tkt.c,v 1.3 2019/12/15 22:50:50 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
364f77a458Spettai #define KRB5_DEPRECATED_FUNCTION(x)
37ca1c9b0cSelric 
38ca1c9b0cSelric #include "krb5_locl.h"
39ca1c9b0cSelric 
40ca1c9b0cSelric #ifndef HEIMDAL_SMALLER
41ca1c9b0cSelric 
42ca1c9b0cSelric static krb5_error_code
make_pa_enc_timestamp(krb5_context context,PA_DATA * pa,krb5_enctype etype,krb5_keyblock * key)43ca1c9b0cSelric make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
44ca1c9b0cSelric 		      krb5_enctype etype, krb5_keyblock *key)
45ca1c9b0cSelric {
46ca1c9b0cSelric     PA_ENC_TS_ENC p;
47ca1c9b0cSelric     unsigned char *buf;
48ca1c9b0cSelric     size_t buf_size;
494f77a458Spettai     size_t len = 0;
50ca1c9b0cSelric     EncryptedData encdata;
51ca1c9b0cSelric     krb5_error_code ret;
52ca1c9b0cSelric     int32_t usec;
53ca1c9b0cSelric     int usec2;
54ca1c9b0cSelric     krb5_crypto crypto;
55ca1c9b0cSelric 
56ca1c9b0cSelric     krb5_us_timeofday (context, &p.patimestamp, &usec);
57ca1c9b0cSelric     usec2         = usec;
58ca1c9b0cSelric     p.pausec      = &usec2;
59ca1c9b0cSelric 
60ca1c9b0cSelric     ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
61ca1c9b0cSelric     if (ret)
62ca1c9b0cSelric 	return ret;
63ca1c9b0cSelric     if(buf_size != len)
64ca1c9b0cSelric 	krb5_abortx(context, "internal error in ASN.1 encoder");
65ca1c9b0cSelric     ret = krb5_crypto_init(context, key, 0, &crypto);
66ca1c9b0cSelric     if (ret) {
67ca1c9b0cSelric 	free(buf);
68ca1c9b0cSelric 	return ret;
69ca1c9b0cSelric     }
70ca1c9b0cSelric     ret = krb5_encrypt_EncryptedData(context,
71ca1c9b0cSelric 				     crypto,
72ca1c9b0cSelric 				     KRB5_KU_PA_ENC_TIMESTAMP,
73ca1c9b0cSelric 				     buf,
74ca1c9b0cSelric 				     len,
75ca1c9b0cSelric 				     0,
76ca1c9b0cSelric 				     &encdata);
77ca1c9b0cSelric     free(buf);
78ca1c9b0cSelric     krb5_crypto_destroy(context, crypto);
79ca1c9b0cSelric     if (ret)
80ca1c9b0cSelric 	return ret;
81ca1c9b0cSelric 
82ca1c9b0cSelric     ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
83ca1c9b0cSelric     free_EncryptedData(&encdata);
84ca1c9b0cSelric     if (ret)
85ca1c9b0cSelric 	return ret;
86ca1c9b0cSelric     if(buf_size != len)
87ca1c9b0cSelric 	krb5_abortx(context, "internal error in ASN.1 encoder");
88ca1c9b0cSelric     pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
89ca1c9b0cSelric     pa->padata_value.length = len;
90ca1c9b0cSelric     pa->padata_value.data = buf;
91ca1c9b0cSelric     return 0;
92ca1c9b0cSelric }
93ca1c9b0cSelric 
94ca1c9b0cSelric static krb5_error_code
add_padata(krb5_context context,METHOD_DATA * md,krb5_principal client,krb5_key_proc key_proc,krb5_const_pointer keyseed,krb5_enctype * enctypes,unsigned netypes,krb5_salt * salt)95ca1c9b0cSelric add_padata(krb5_context context,
96ca1c9b0cSelric 	   METHOD_DATA *md,
97ca1c9b0cSelric 	   krb5_principal client,
98ca1c9b0cSelric 	   krb5_key_proc key_proc,
99ca1c9b0cSelric 	   krb5_const_pointer keyseed,
100ca1c9b0cSelric 	   krb5_enctype *enctypes,
101ca1c9b0cSelric 	   unsigned netypes,
102ca1c9b0cSelric 	   krb5_salt *salt)
103ca1c9b0cSelric {
104ca1c9b0cSelric     krb5_error_code ret;
105ca1c9b0cSelric     PA_DATA *pa2;
106ca1c9b0cSelric     krb5_salt salt2;
107ca1c9b0cSelric     krb5_enctype *ep;
1084f77a458Spettai     size_t i;
109ca1c9b0cSelric 
110ca1c9b0cSelric     if(salt == NULL) {
111ca1c9b0cSelric 	/* default to standard salt */
112ca1c9b0cSelric 	ret = krb5_get_pw_salt (context, client, &salt2);
113ca1c9b0cSelric 	if (ret)
114ca1c9b0cSelric 	    return ret;
115ca1c9b0cSelric 	salt = &salt2;
116ca1c9b0cSelric     }
117ca1c9b0cSelric     if (!enctypes) {
118ca1c9b0cSelric 	enctypes = context->etypes;
119ca1c9b0cSelric 	netypes = 0;
120b9d004c6Schristos 	for (ep = enctypes; *ep != (krb5_enctype)ETYPE_NULL; ep++)
121ca1c9b0cSelric 	    netypes++;
122ca1c9b0cSelric     }
123ca1c9b0cSelric     pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val));
124b9d004c6Schristos     if (pa2 == NULL)
125b9d004c6Schristos 	return krb5_enomem(context);
126ca1c9b0cSelric     md->val = pa2;
127ca1c9b0cSelric 
128ca1c9b0cSelric     for (i = 0; i < netypes; ++i) {
129ca1c9b0cSelric 	krb5_keyblock *key;
130ca1c9b0cSelric 
131ca1c9b0cSelric 	ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key);
132ca1c9b0cSelric 	if (ret)
133ca1c9b0cSelric 	    continue;
134ca1c9b0cSelric 	ret = make_pa_enc_timestamp (context, &md->val[md->len],
135ca1c9b0cSelric 				     enctypes[i], key);
136ca1c9b0cSelric 	krb5_free_keyblock (context, key);
137ca1c9b0cSelric 	if (ret)
138ca1c9b0cSelric 	    return ret;
139ca1c9b0cSelric 	++md->len;
140ca1c9b0cSelric     }
141ca1c9b0cSelric     if(salt == &salt2)
142ca1c9b0cSelric 	krb5_free_salt(context, salt2);
143ca1c9b0cSelric     return 0;
144ca1c9b0cSelric }
145ca1c9b0cSelric 
146ca1c9b0cSelric static krb5_error_code
init_as_req(krb5_context context,KDCOptions opts,krb5_creds * creds,const krb5_addresses * addrs,const krb5_enctype * etypes,const krb5_preauthtype * ptypes,const krb5_preauthdata * preauth,krb5_key_proc key_proc,krb5_const_pointer keyseed,unsigned nonce,AS_REQ * a)147ca1c9b0cSelric init_as_req (krb5_context context,
148ca1c9b0cSelric 	     KDCOptions opts,
149ca1c9b0cSelric 	     krb5_creds *creds,
150ca1c9b0cSelric 	     const krb5_addresses *addrs,
151ca1c9b0cSelric 	     const krb5_enctype *etypes,
152ca1c9b0cSelric 	     const krb5_preauthtype *ptypes,
153ca1c9b0cSelric 	     const krb5_preauthdata *preauth,
154ca1c9b0cSelric 	     krb5_key_proc key_proc,
155ca1c9b0cSelric 	     krb5_const_pointer keyseed,
156ca1c9b0cSelric 	     unsigned nonce,
157ca1c9b0cSelric 	     AS_REQ *a)
158ca1c9b0cSelric {
159ca1c9b0cSelric     krb5_error_code ret;
160ca1c9b0cSelric     krb5_salt salt;
161ca1c9b0cSelric 
162ca1c9b0cSelric     memset(a, 0, sizeof(*a));
163ca1c9b0cSelric 
164ca1c9b0cSelric     a->pvno = 5;
165ca1c9b0cSelric     a->msg_type = krb_as_req;
166ca1c9b0cSelric     a->req_body.kdc_options = opts;
167ca1c9b0cSelric     a->req_body.cname = malloc(sizeof(*a->req_body.cname));
168ca1c9b0cSelric     if (a->req_body.cname == NULL) {
169b9d004c6Schristos 	ret = krb5_enomem(context);
170ca1c9b0cSelric 	goto fail;
171ca1c9b0cSelric     }
172ca1c9b0cSelric     a->req_body.sname = malloc(sizeof(*a->req_body.sname));
173ca1c9b0cSelric     if (a->req_body.sname == NULL) {
174b9d004c6Schristos 	ret = krb5_enomem(context);
175ca1c9b0cSelric 	goto fail;
176ca1c9b0cSelric     }
177ca1c9b0cSelric     ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
178ca1c9b0cSelric     if (ret)
179ca1c9b0cSelric 	goto fail;
180ca1c9b0cSelric     ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
181ca1c9b0cSelric     if (ret)
182ca1c9b0cSelric 	goto fail;
183ca1c9b0cSelric     ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
184ca1c9b0cSelric     if (ret)
185ca1c9b0cSelric 	goto fail;
186ca1c9b0cSelric 
187ca1c9b0cSelric     if(creds->times.starttime) {
188ca1c9b0cSelric 	a->req_body.from = malloc(sizeof(*a->req_body.from));
189ca1c9b0cSelric 	if (a->req_body.from == NULL) {
190b9d004c6Schristos 	    ret = krb5_enomem(context);
191ca1c9b0cSelric 	    goto fail;
192ca1c9b0cSelric 	}
193ca1c9b0cSelric 	*a->req_body.from = creds->times.starttime;
194ca1c9b0cSelric     }
195ca1c9b0cSelric     if(creds->times.endtime){
196ca1c9b0cSelric 	ALLOC(a->req_body.till, 1);
197ca1c9b0cSelric 	*a->req_body.till = creds->times.endtime;
198ca1c9b0cSelric     }
199ca1c9b0cSelric     if(creds->times.renew_till){
200ca1c9b0cSelric 	a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
201ca1c9b0cSelric 	if (a->req_body.rtime == NULL) {
202b9d004c6Schristos 	    ret = krb5_enomem(context);
203ca1c9b0cSelric 	    goto fail;
204ca1c9b0cSelric 	}
205ca1c9b0cSelric 	*a->req_body.rtime = creds->times.renew_till;
206ca1c9b0cSelric     }
207ca1c9b0cSelric     a->req_body.nonce = nonce;
2084f77a458Spettai     ret = _krb5_init_etype(context,
2094f77a458Spettai 			   KRB5_PDU_AS_REQUEST,
210ca1c9b0cSelric 			   &a->req_body.etype.len,
211ca1c9b0cSelric 			   &a->req_body.etype.val,
212ca1c9b0cSelric 			   etypes);
213ca1c9b0cSelric     if (ret)
214ca1c9b0cSelric 	goto fail;
215ca1c9b0cSelric 
216ca1c9b0cSelric     /*
217ca1c9b0cSelric      * This means no addresses
218ca1c9b0cSelric      */
219ca1c9b0cSelric 
220ca1c9b0cSelric     if (addrs && addrs->len == 0) {
221ca1c9b0cSelric 	a->req_body.addresses = NULL;
222ca1c9b0cSelric     } else {
223ca1c9b0cSelric 	a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
224ca1c9b0cSelric 	if (a->req_body.addresses == NULL) {
225b9d004c6Schristos 	    ret = krb5_enomem(context);
226ca1c9b0cSelric 	    goto fail;
227ca1c9b0cSelric 	}
228ca1c9b0cSelric 
229ca1c9b0cSelric 	if (addrs)
230ca1c9b0cSelric 	    ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
231ca1c9b0cSelric 	else {
232ca1c9b0cSelric 	    ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
233ca1c9b0cSelric 	    if(ret == 0 && a->req_body.addresses->len == 0) {
234ca1c9b0cSelric 		free(a->req_body.addresses);
235ca1c9b0cSelric 		a->req_body.addresses = NULL;
236ca1c9b0cSelric 	    }
237ca1c9b0cSelric 	}
238ca1c9b0cSelric 	if (ret)
239ca1c9b0cSelric 	    return ret;
240ca1c9b0cSelric     }
241ca1c9b0cSelric 
242ca1c9b0cSelric     a->req_body.enc_authorization_data = NULL;
243ca1c9b0cSelric     a->req_body.additional_tickets = NULL;
244ca1c9b0cSelric 
245ca1c9b0cSelric     if(preauth != NULL) {
2464f77a458Spettai 	size_t i;
247ca1c9b0cSelric 	ALLOC(a->padata, 1);
248ca1c9b0cSelric 	if(a->padata == NULL) {
249b9d004c6Schristos 	    ret = krb5_enomem(context);
250ca1c9b0cSelric 	    goto fail;
251ca1c9b0cSelric 	}
252ca1c9b0cSelric 	a->padata->val = NULL;
253ca1c9b0cSelric 	a->padata->len = 0;
254ca1c9b0cSelric 	for(i = 0; i < preauth->len; i++) {
255ca1c9b0cSelric 	    if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){
2564f77a458Spettai 		size_t j;
257ca1c9b0cSelric 
258ca1c9b0cSelric 		for(j = 0; j < preauth->val[i].info.len; j++) {
259ca1c9b0cSelric 		    krb5_salt *sp = &salt;
260ca1c9b0cSelric 		    if(preauth->val[i].info.val[j].salttype)
261ca1c9b0cSelric 			salt.salttype = *preauth->val[i].info.val[j].salttype;
262ca1c9b0cSelric 		    else
263ca1c9b0cSelric 			salt.salttype = KRB5_PW_SALT;
264ca1c9b0cSelric 		    if(preauth->val[i].info.val[j].salt)
265ca1c9b0cSelric 			salt.saltvalue = *preauth->val[i].info.val[j].salt;
266ca1c9b0cSelric 		    else
267ca1c9b0cSelric 			if(salt.salttype == KRB5_PW_SALT)
268ca1c9b0cSelric 			    sp = NULL;
269ca1c9b0cSelric 			else
270ca1c9b0cSelric 			    krb5_data_zero(&salt.saltvalue);
271ca1c9b0cSelric 		    ret = add_padata(context, a->padata, creds->client,
272ca1c9b0cSelric 				     key_proc, keyseed,
273ca1c9b0cSelric 				     &preauth->val[i].info.val[j].etype, 1,
274ca1c9b0cSelric 				     sp);
275ca1c9b0cSelric 		    if (ret == 0)
276ca1c9b0cSelric 			break;
277ca1c9b0cSelric 		}
278ca1c9b0cSelric 	    }
279ca1c9b0cSelric 	}
280ca1c9b0cSelric     } else
281ca1c9b0cSelric     /* not sure this is the way to use `ptypes' */
282ca1c9b0cSelric     if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE)
283ca1c9b0cSelric 	a->padata = NULL;
284ca1c9b0cSelric     else if (*ptypes ==  KRB5_PADATA_ENC_TIMESTAMP) {
285ca1c9b0cSelric 	ALLOC(a->padata, 1);
286ca1c9b0cSelric 	if (a->padata == NULL) {
287b9d004c6Schristos 	    ret = krb5_enomem(context);
288ca1c9b0cSelric 	    goto fail;
289ca1c9b0cSelric 	}
290ca1c9b0cSelric 	a->padata->len = 0;
291ca1c9b0cSelric 	a->padata->val = NULL;
292ca1c9b0cSelric 
293ca1c9b0cSelric 	/* make a v5 salted pa-data */
294ca1c9b0cSelric 	add_padata(context, a->padata, creds->client,
295ca1c9b0cSelric 		   key_proc, keyseed, a->req_body.etype.val,
296ca1c9b0cSelric 		   a->req_body.etype.len, NULL);
297ca1c9b0cSelric 
298ca1c9b0cSelric 	/* make a v4 salted pa-data */
299ca1c9b0cSelric 	salt.salttype = KRB5_PW_SALT;
300ca1c9b0cSelric 	krb5_data_zero(&salt.saltvalue);
301ca1c9b0cSelric 	add_padata(context, a->padata, creds->client,
302ca1c9b0cSelric 		   key_proc, keyseed, a->req_body.etype.val,
303ca1c9b0cSelric 		   a->req_body.etype.len, &salt);
304ca1c9b0cSelric     } else {
305ca1c9b0cSelric 	ret = KRB5_PREAUTH_BAD_TYPE;
306ca1c9b0cSelric 	krb5_set_error_message (context, ret,
307ca1c9b0cSelric 				N_("pre-auth type %d not supported", ""),
308ca1c9b0cSelric 			       *ptypes);
309ca1c9b0cSelric 	goto fail;
310ca1c9b0cSelric     }
311ca1c9b0cSelric     return 0;
312ca1c9b0cSelric fail:
313ca1c9b0cSelric     free_AS_REQ(a);
314ca1c9b0cSelric     return ret;
315ca1c9b0cSelric }
316ca1c9b0cSelric 
317ca1c9b0cSelric static int
set_ptypes(krb5_context context,KRB_ERROR * error,const krb5_preauthtype ** ptypes,krb5_preauthdata ** preauth)318ca1c9b0cSelric set_ptypes(krb5_context context,
319ca1c9b0cSelric 	   KRB_ERROR *error,
320ca1c9b0cSelric 	   const krb5_preauthtype **ptypes,
321ca1c9b0cSelric 	   krb5_preauthdata **preauth)
322ca1c9b0cSelric {
323ca1c9b0cSelric     static krb5_preauthdata preauth2;
324ca1c9b0cSelric     static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE };
325ca1c9b0cSelric 
326ca1c9b0cSelric     if(error->e_data) {
327ca1c9b0cSelric 	METHOD_DATA md;
3284f77a458Spettai 	size_t i;
329ca1c9b0cSelric 	decode_METHOD_DATA(error->e_data->data,
330ca1c9b0cSelric 			   error->e_data->length,
331ca1c9b0cSelric 			   &md,
332ca1c9b0cSelric 			   NULL);
333ca1c9b0cSelric 	for(i = 0; i < md.len; i++){
334ca1c9b0cSelric 	    switch(md.val[i].padata_type){
335ca1c9b0cSelric 	    case KRB5_PADATA_ENC_TIMESTAMP:
336ca1c9b0cSelric 		*ptypes = ptypes2;
337ca1c9b0cSelric 		break;
338ca1c9b0cSelric 	    case KRB5_PADATA_ETYPE_INFO:
339ca1c9b0cSelric 		*preauth = &preauth2;
340ca1c9b0cSelric 		ALLOC_SEQ(*preauth, 1);
341ca1c9b0cSelric 		(*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
342ca1c9b0cSelric 		decode_ETYPE_INFO(md.val[i].padata_value.data,
343ca1c9b0cSelric 				  md.val[i].padata_value.length,
344ca1c9b0cSelric 				  &(*preauth)->val[0].info,
345ca1c9b0cSelric 				  NULL);
346ca1c9b0cSelric 		break;
347ca1c9b0cSelric 	    default:
348ca1c9b0cSelric 		break;
349ca1c9b0cSelric 	    }
350ca1c9b0cSelric 	}
351ca1c9b0cSelric 	free_METHOD_DATA(&md);
352ca1c9b0cSelric     } else {
353ca1c9b0cSelric 	*ptypes = ptypes2;
354ca1c9b0cSelric     }
355ca1c9b0cSelric     return(1);
356ca1c9b0cSelric }
357ca1c9b0cSelric 
358ca1c9b0cSelric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_in_cred(krb5_context context,krb5_flags options,const krb5_addresses * addrs,const krb5_enctype * etypes,const krb5_preauthtype * ptypes,const krb5_preauthdata * preauth,krb5_key_proc key_proc,krb5_const_pointer keyseed,krb5_decrypt_proc decrypt_proc,krb5_const_pointer decryptarg,krb5_creds * creds,krb5_kdc_rep * ret_as_reply)359ca1c9b0cSelric krb5_get_in_cred(krb5_context context,
360ca1c9b0cSelric 		 krb5_flags options,
361ca1c9b0cSelric 		 const krb5_addresses *addrs,
362ca1c9b0cSelric 		 const krb5_enctype *etypes,
363ca1c9b0cSelric 		 const krb5_preauthtype *ptypes,
364ca1c9b0cSelric 		 const krb5_preauthdata *preauth,
365ca1c9b0cSelric 		 krb5_key_proc key_proc,
366ca1c9b0cSelric 		 krb5_const_pointer keyseed,
367ca1c9b0cSelric 		 krb5_decrypt_proc decrypt_proc,
368ca1c9b0cSelric 		 krb5_const_pointer decryptarg,
369ca1c9b0cSelric 		 krb5_creds *creds,
370ca1c9b0cSelric 		 krb5_kdc_rep *ret_as_reply)
3714f77a458Spettai     KRB5_DEPRECATED_FUNCTION("Use X instead")
372ca1c9b0cSelric {
373ca1c9b0cSelric     krb5_error_code ret;
374ca1c9b0cSelric     AS_REQ a;
375ca1c9b0cSelric     krb5_kdc_rep rep;
376ca1c9b0cSelric     krb5_data req, resp;
3774f77a458Spettai     size_t len = 0;
378ca1c9b0cSelric     krb5_salt salt;
379ca1c9b0cSelric     krb5_keyblock *key;
380ca1c9b0cSelric     size_t size;
381ca1c9b0cSelric     KDCOptions opts;
382ca1c9b0cSelric     PA_DATA *pa;
383ca1c9b0cSelric     krb5_enctype etype;
384ca1c9b0cSelric     krb5_preauthdata *my_preauth = NULL;
385ca1c9b0cSelric     unsigned nonce;
386ca1c9b0cSelric     int done;
387ca1c9b0cSelric 
388ca1c9b0cSelric     opts = int2KDCOptions(options);
389ca1c9b0cSelric 
390ca1c9b0cSelric     krb5_generate_random_block (&nonce, sizeof(nonce));
391ca1c9b0cSelric     nonce &= 0xffffffff;
392ca1c9b0cSelric 
393ca1c9b0cSelric     do {
394ca1c9b0cSelric 	done = 1;
395ca1c9b0cSelric 	ret = init_as_req (context,
396ca1c9b0cSelric 			   opts,
397ca1c9b0cSelric 			   creds,
398ca1c9b0cSelric 			   addrs,
399ca1c9b0cSelric 			   etypes,
400ca1c9b0cSelric 			   ptypes,
401ca1c9b0cSelric 			   preauth,
402ca1c9b0cSelric 			   key_proc,
403ca1c9b0cSelric 			   keyseed,
404ca1c9b0cSelric 			   nonce,
405ca1c9b0cSelric 			   &a);
406ca1c9b0cSelric 	if (my_preauth) {
407ca1c9b0cSelric 	    free_ETYPE_INFO(&my_preauth->val[0].info);
408ca1c9b0cSelric 	    free (my_preauth->val);
409ca1c9b0cSelric 	    my_preauth = NULL;
410ca1c9b0cSelric 	}
411ca1c9b0cSelric 	if (ret)
412ca1c9b0cSelric 	    return ret;
413ca1c9b0cSelric 
414ca1c9b0cSelric 	ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret);
415ca1c9b0cSelric 	free_AS_REQ(&a);
416ca1c9b0cSelric 	if (ret)
417ca1c9b0cSelric 	    return ret;
418ca1c9b0cSelric 	if(len != req.length)
419ca1c9b0cSelric 	    krb5_abortx(context, "internal error in ASN.1 encoder");
420ca1c9b0cSelric 
421ca1c9b0cSelric 	ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp);
422ca1c9b0cSelric 	krb5_data_free(&req);
423ca1c9b0cSelric 	if (ret)
424ca1c9b0cSelric 	    return ret;
425ca1c9b0cSelric 
426ca1c9b0cSelric 	memset (&rep, 0, sizeof(rep));
427ca1c9b0cSelric 	ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
428ca1c9b0cSelric 	if(ret) {
429ca1c9b0cSelric 	    /* let's try to parse it as a KRB-ERROR */
430ca1c9b0cSelric 	    KRB_ERROR error;
431ca1c9b0cSelric 	    int ret2;
432ca1c9b0cSelric 
433ca1c9b0cSelric 	    ret2 = krb5_rd_error(context, &resp, &error);
434ca1c9b0cSelric 	    if(ret2 && resp.data && ((char*)resp.data)[0] == 4)
435ca1c9b0cSelric 		ret = KRB5KRB_AP_ERR_V4_REPLY;
436ca1c9b0cSelric 	    krb5_data_free(&resp);
437ca1c9b0cSelric 	    if (ret2 == 0) {
438ca1c9b0cSelric 		ret = krb5_error_from_rd_error(context, &error, creds);
439ca1c9b0cSelric 		/* if no preauth was set and KDC requires it, give it
440ca1c9b0cSelric                    one more try */
441ca1c9b0cSelric 		if (!ptypes && !preauth
442ca1c9b0cSelric 		    && ret == KRB5KDC_ERR_PREAUTH_REQUIRED
443ca1c9b0cSelric #if 0
444ca1c9b0cSelric 			|| ret == KRB5KDC_ERR_BADOPTION
445ca1c9b0cSelric #endif
446ca1c9b0cSelric 		    && set_ptypes(context, &error, &ptypes, &my_preauth)) {
447ca1c9b0cSelric 		    done = 0;
448ca1c9b0cSelric 		    preauth = my_preauth;
449ca1c9b0cSelric 		    krb5_free_error_contents(context, &error);
450ca1c9b0cSelric 		    krb5_clear_error_message(context);
451ca1c9b0cSelric 		    continue;
452ca1c9b0cSelric 		}
453ca1c9b0cSelric 		if(ret_as_reply)
454ca1c9b0cSelric 		    ret_as_reply->error = error;
455ca1c9b0cSelric 		else
456ca1c9b0cSelric 		    free_KRB_ERROR (&error);
457ca1c9b0cSelric 		return ret;
458ca1c9b0cSelric 	    }
459ca1c9b0cSelric 	    return ret;
460ca1c9b0cSelric 	}
461ca1c9b0cSelric 	krb5_data_free(&resp);
462ca1c9b0cSelric     } while(!done);
463ca1c9b0cSelric 
464ca1c9b0cSelric     pa = NULL;
465ca1c9b0cSelric     etype = rep.kdc_rep.enc_part.etype;
466ca1c9b0cSelric     if(rep.kdc_rep.padata){
467ca1c9b0cSelric 	int i = 0;
468ca1c9b0cSelric 	pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len,
469ca1c9b0cSelric 			      KRB5_PADATA_PW_SALT, &i);
470ca1c9b0cSelric 	if(pa == NULL) {
471ca1c9b0cSelric 	    i = 0;
472ca1c9b0cSelric 	    pa = krb5_find_padata(rep.kdc_rep.padata->val,
473ca1c9b0cSelric 				  rep.kdc_rep.padata->len,
474ca1c9b0cSelric 				  KRB5_PADATA_AFS3_SALT, &i);
475ca1c9b0cSelric 	}
476ca1c9b0cSelric     }
477ca1c9b0cSelric     if(pa) {
4784f77a458Spettai 	salt.salttype = (krb5_salttype)pa->padata_type;
479ca1c9b0cSelric 	salt.saltvalue = pa->padata_value;
480ca1c9b0cSelric 
481ca1c9b0cSelric 	ret = (*key_proc)(context, etype, salt, keyseed, &key);
482ca1c9b0cSelric     } else {
483ca1c9b0cSelric 	/* make a v5 salted pa-data */
484ca1c9b0cSelric 	ret = krb5_get_pw_salt (context, creds->client, &salt);
485ca1c9b0cSelric 
486ca1c9b0cSelric 	if (ret)
487ca1c9b0cSelric 	    goto out;
488ca1c9b0cSelric 	ret = (*key_proc)(context, etype, salt, keyseed, &key);
489ca1c9b0cSelric 	krb5_free_salt(context, salt);
490ca1c9b0cSelric     }
491ca1c9b0cSelric     if (ret)
492ca1c9b0cSelric 	goto out;
493ca1c9b0cSelric 
494ca1c9b0cSelric     {
495ca1c9b0cSelric 	unsigned flags = EXTRACT_TICKET_TIMESYNC;
496ca1c9b0cSelric 	if (opts.request_anonymous)
497*241bea01Schristos 	    flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH | EXTRACT_TICKET_MATCH_ANON;
498ca1c9b0cSelric 
499ca1c9b0cSelric 	ret = _krb5_extract_ticket(context,
500ca1c9b0cSelric 				   &rep,
501ca1c9b0cSelric 				   creds,
502ca1c9b0cSelric 				   key,
503ca1c9b0cSelric 				   keyseed,
504ca1c9b0cSelric 				   KRB5_KU_AS_REP_ENC_PART,
505ca1c9b0cSelric 				   NULL,
506ca1c9b0cSelric 				   nonce,
507ca1c9b0cSelric 				   flags,
508b9d004c6Schristos 				   NULL,
509ca1c9b0cSelric 				   decrypt_proc,
510ca1c9b0cSelric 				   decryptarg);
511ca1c9b0cSelric     }
512ca1c9b0cSelric     memset (key->keyvalue.data, 0, key->keyvalue.length);
513ca1c9b0cSelric     krb5_free_keyblock_contents (context, key);
514ca1c9b0cSelric     free (key);
515ca1c9b0cSelric 
516ca1c9b0cSelric out:
517ca1c9b0cSelric     if (ret == 0 && ret_as_reply)
518ca1c9b0cSelric 	*ret_as_reply = rep;
519ca1c9b0cSelric     else
520ca1c9b0cSelric 	krb5_free_kdc_rep (context, &rep);
521ca1c9b0cSelric     return ret;
522ca1c9b0cSelric }
523ca1c9b0cSelric 
524ca1c9b0cSelric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_in_tkt(krb5_context context,krb5_flags options,const krb5_addresses * addrs,const krb5_enctype * etypes,const krb5_preauthtype * ptypes,krb5_key_proc key_proc,krb5_const_pointer keyseed,krb5_decrypt_proc decrypt_proc,krb5_const_pointer decryptarg,krb5_creds * creds,krb5_ccache ccache,krb5_kdc_rep * ret_as_reply)525ca1c9b0cSelric krb5_get_in_tkt(krb5_context context,
526ca1c9b0cSelric 		krb5_flags options,
527ca1c9b0cSelric 		const krb5_addresses *addrs,
528ca1c9b0cSelric 		const krb5_enctype *etypes,
529ca1c9b0cSelric 		const krb5_preauthtype *ptypes,
530ca1c9b0cSelric 		krb5_key_proc key_proc,
531ca1c9b0cSelric 		krb5_const_pointer keyseed,
532ca1c9b0cSelric 		krb5_decrypt_proc decrypt_proc,
533ca1c9b0cSelric 		krb5_const_pointer decryptarg,
534ca1c9b0cSelric 		krb5_creds *creds,
535ca1c9b0cSelric 		krb5_ccache ccache,
536ca1c9b0cSelric 		krb5_kdc_rep *ret_as_reply)
5374f77a458Spettai     KRB5_DEPRECATED_FUNCTION("Use X instead")
538ca1c9b0cSelric {
539ca1c9b0cSelric     krb5_error_code ret;
540ca1c9b0cSelric 
541ca1c9b0cSelric     ret = krb5_get_in_cred (context,
542ca1c9b0cSelric 			    options,
543ca1c9b0cSelric 			    addrs,
544ca1c9b0cSelric 			    etypes,
545ca1c9b0cSelric 			    ptypes,
546ca1c9b0cSelric 			    NULL,
547ca1c9b0cSelric 			    key_proc,
548ca1c9b0cSelric 			    keyseed,
549ca1c9b0cSelric 			    decrypt_proc,
550ca1c9b0cSelric 			    decryptarg,
551ca1c9b0cSelric 			    creds,
552ca1c9b0cSelric 			    ret_as_reply);
553ca1c9b0cSelric     if(ret)
554ca1c9b0cSelric 	return ret;
555ca1c9b0cSelric     if (ccache)
556ca1c9b0cSelric 	ret = krb5_cc_store_cred (context, ccache, creds);
557ca1c9b0cSelric     return ret;
558ca1c9b0cSelric }
559ca1c9b0cSelric 
560ca1c9b0cSelric #endif /* HEIMDAL_SMALLER */
561