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