No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / krb5 / get_in_tkt.c
blobb3868479fe1f381acbf0ad5ec23e50b8b9a89be5
1 /*
2 * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "krb5_locl.h"
36 __RCSID("$Heimdal: get_in_tkt.c 20226 2007-02-16 03:31:50Z lha $"
37 "$NetBSD$");
39 krb5_error_code KRB5_LIB_FUNCTION
40 krb5_init_etype (krb5_context context,
41 unsigned *len,
42 krb5_enctype **val,
43 const krb5_enctype *etypes)
45 int i;
46 krb5_error_code ret;
47 krb5_enctype *tmp = NULL;
49 ret = 0;
50 if (etypes == NULL) {
51 ret = krb5_get_default_in_tkt_etypes(context,
52 &tmp);
53 if (ret)
54 return ret;
55 etypes = tmp;
58 for (i = 0; etypes[i]; ++i)
60 *len = i;
61 *val = malloc(i * sizeof(**val));
62 if (i != 0 && *val == NULL) {
63 ret = ENOMEM;
64 krb5_set_error_string(context, "malloc: out of memory");
65 goto cleanup;
67 memmove (*val,
68 etypes,
69 i * sizeof(*tmp));
70 cleanup:
71 if (tmp != NULL)
72 free (tmp);
73 return ret;
77 static krb5_error_code
78 decrypt_tkt (krb5_context context,
79 krb5_keyblock *key,
80 krb5_key_usage usage,
81 krb5_const_pointer decrypt_arg,
82 krb5_kdc_rep *dec_rep)
84 krb5_error_code ret;
85 krb5_data data;
86 size_t size;
87 krb5_crypto crypto;
89 ret = krb5_crypto_init(context, key, 0, &crypto);
90 if (ret)
91 return ret;
93 ret = krb5_decrypt_EncryptedData (context,
94 crypto,
95 usage,
96 &dec_rep->kdc_rep.enc_part,
97 &data);
98 krb5_crypto_destroy(context, crypto);
100 if (ret)
101 return ret;
103 ret = krb5_decode_EncASRepPart(context,
104 data.data,
105 data.length,
106 &dec_rep->enc_part,
107 &size);
108 if (ret)
109 ret = krb5_decode_EncTGSRepPart(context,
110 data.data,
111 data.length,
112 &dec_rep->enc_part,
113 &size);
114 krb5_data_free (&data);
115 if (ret)
116 return ret;
117 return 0;
121 _krb5_extract_ticket(krb5_context context,
122 krb5_kdc_rep *rep,
123 krb5_creds *creds,
124 krb5_keyblock *key,
125 krb5_const_pointer keyseed,
126 krb5_key_usage key_usage,
127 krb5_addresses *addrs,
128 unsigned nonce,
129 unsigned flags,
130 krb5_decrypt_proc decrypt_proc,
131 krb5_const_pointer decryptarg)
133 krb5_error_code ret;
134 krb5_principal tmp_principal;
135 int tmp;
136 size_t len;
137 time_t tmp_time;
138 krb5_timestamp sec_now;
140 ret = _krb5_principalname2krb5_principal (context,
141 &tmp_principal,
142 rep->kdc_rep.cname,
143 rep->kdc_rep.crealm);
144 if (ret)
145 goto out;
147 /* compare client */
149 if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0){
150 tmp = krb5_principal_compare (context, tmp_principal, creds->client);
151 if (!tmp) {
152 krb5_free_principal (context, tmp_principal);
153 krb5_clear_error_string (context);
154 ret = KRB5KRB_AP_ERR_MODIFIED;
155 goto out;
159 krb5_free_principal (context, creds->client);
160 creds->client = tmp_principal;
162 /* extract ticket */
163 ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
164 &rep->kdc_rep.ticket, &len, ret);
165 if(ret)
166 goto out;
167 if (creds->ticket.length != len)
168 krb5_abortx(context, "internal error in ASN.1 encoder");
169 creds->second_ticket.length = 0;
170 creds->second_ticket.data = NULL;
172 /* compare server */
174 ret = _krb5_principalname2krb5_principal (context,
175 &tmp_principal,
176 rep->kdc_rep.ticket.sname,
177 rep->kdc_rep.ticket.realm);
178 if (ret)
179 goto out;
180 if(flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH){
181 krb5_free_principal(context, creds->server);
182 creds->server = tmp_principal;
183 tmp_principal = NULL;
184 } else {
185 tmp = krb5_principal_compare (context, tmp_principal,
186 creds->server);
187 krb5_free_principal (context, tmp_principal);
188 if (!tmp) {
189 ret = KRB5KRB_AP_ERR_MODIFIED;
190 krb5_clear_error_string (context);
191 goto out;
195 /* decrypt */
197 if (decrypt_proc == NULL)
198 decrypt_proc = decrypt_tkt;
200 ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
201 if (ret)
202 goto out;
204 /* verify names */
205 if(flags & EXTRACT_TICKET_MATCH_REALM){
206 const char *srealm = krb5_principal_get_realm(context, creds->server);
207 const char *crealm = krb5_principal_get_realm(context, creds->client);
209 if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
210 strcmp(rep->enc_part.srealm, crealm) != 0)
212 ret = KRB5KRB_AP_ERR_MODIFIED;
213 krb5_clear_error_string(context);
214 goto out;
218 /* compare nonces */
220 if (nonce != rep->enc_part.nonce) {
221 ret = KRB5KRB_AP_ERR_MODIFIED;
222 krb5_set_error_string(context, "malloc: out of memory");
223 goto out;
226 /* set kdc-offset */
228 krb5_timeofday (context, &sec_now);
229 if (rep->enc_part.flags.initial
230 && context->kdc_sec_offset == 0
231 && krb5_config_get_bool (context, NULL,
232 "libdefaults",
233 "kdc_timesync",
234 NULL)) {
235 context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
236 krb5_timeofday (context, &sec_now);
239 /* check all times */
241 if (rep->enc_part.starttime) {
242 tmp_time = *rep->enc_part.starttime;
243 } else
244 tmp_time = rep->enc_part.authtime;
246 if (creds->times.starttime == 0
247 && abs(tmp_time - sec_now) > context->max_skew) {
248 ret = KRB5KRB_AP_ERR_SKEW;
249 krb5_set_error_string (context,
250 "time skew (%d) larger than max (%d)",
251 abs(tmp_time - sec_now),
252 (int)context->max_skew);
253 goto out;
256 if (creds->times.starttime != 0
257 && tmp_time != creds->times.starttime) {
258 krb5_clear_error_string (context);
259 ret = KRB5KRB_AP_ERR_MODIFIED;
260 goto out;
263 creds->times.starttime = tmp_time;
265 if (rep->enc_part.renew_till) {
266 tmp_time = *rep->enc_part.renew_till;
267 } else
268 tmp_time = 0;
270 if (creds->times.renew_till != 0
271 && tmp_time > creds->times.renew_till) {
272 krb5_clear_error_string (context);
273 ret = KRB5KRB_AP_ERR_MODIFIED;
274 goto out;
277 creds->times.renew_till = tmp_time;
279 creds->times.authtime = rep->enc_part.authtime;
281 if (creds->times.endtime != 0
282 && rep->enc_part.endtime > creds->times.endtime) {
283 krb5_clear_error_string (context);
284 ret = KRB5KRB_AP_ERR_MODIFIED;
285 goto out;
288 creds->times.endtime = rep->enc_part.endtime;
290 if(rep->enc_part.caddr)
291 krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
292 else if(addrs)
293 krb5_copy_addresses (context, addrs, &creds->addresses);
294 else {
295 creds->addresses.len = 0;
296 creds->addresses.val = NULL;
298 creds->flags.b = rep->enc_part.flags;
300 creds->authdata.len = 0;
301 creds->authdata.val = NULL;
302 creds->session.keyvalue.length = 0;
303 creds->session.keyvalue.data = NULL;
304 creds->session.keytype = rep->enc_part.key.keytype;
305 ret = krb5_data_copy (&creds->session.keyvalue,
306 rep->enc_part.key.keyvalue.data,
307 rep->enc_part.key.keyvalue.length);
309 out:
310 memset (rep->enc_part.key.keyvalue.data, 0,
311 rep->enc_part.key.keyvalue.length);
312 return ret;
316 static krb5_error_code
317 make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
318 krb5_enctype etype, krb5_keyblock *key)
320 PA_ENC_TS_ENC p;
321 unsigned char *buf;
322 size_t buf_size;
323 size_t len;
324 EncryptedData encdata;
325 krb5_error_code ret;
326 int32_t usec;
327 int usec2;
328 krb5_crypto crypto;
330 krb5_us_timeofday (context, &p.patimestamp, &usec);
331 usec2 = usec;
332 p.pausec = &usec2;
334 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
335 if (ret)
336 return ret;
337 if(buf_size != len)
338 krb5_abortx(context, "internal error in ASN.1 encoder");
339 ret = krb5_crypto_init(context, key, 0, &crypto);
340 if (ret) {
341 free(buf);
342 return ret;
344 ret = krb5_encrypt_EncryptedData(context,
345 crypto,
346 KRB5_KU_PA_ENC_TIMESTAMP,
347 buf,
348 len,
350 &encdata);
351 free(buf);
352 krb5_crypto_destroy(context, crypto);
353 if (ret)
354 return ret;
356 ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
357 free_EncryptedData(&encdata);
358 if (ret)
359 return ret;
360 if(buf_size != len)
361 krb5_abortx(context, "internal error in ASN.1 encoder");
362 pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
363 pa->padata_value.length = len;
364 pa->padata_value.data = buf;
365 return 0;
368 static krb5_error_code
369 add_padata(krb5_context context,
370 METHOD_DATA *md,
371 krb5_principal client,
372 krb5_key_proc key_proc,
373 krb5_const_pointer keyseed,
374 krb5_enctype *enctypes,
375 unsigned netypes,
376 krb5_salt *salt)
378 krb5_error_code ret;
379 PA_DATA *pa2;
380 krb5_salt salt2;
381 krb5_enctype *ep;
382 int i;
384 if(salt == NULL) {
385 /* default to standard salt */
386 ret = krb5_get_pw_salt (context, client, &salt2);
387 salt = &salt2;
389 if (!enctypes) {
390 enctypes = context->etypes;
391 netypes = 0;
392 for (ep = enctypes; *ep != ETYPE_NULL; ep++)
393 netypes++;
395 pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val));
396 if (pa2 == NULL) {
397 krb5_set_error_string(context, "malloc: out of memory");
398 return ENOMEM;
400 md->val = pa2;
402 for (i = 0; i < netypes; ++i) {
403 krb5_keyblock *key;
405 ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key);
406 if (ret)
407 continue;
408 ret = make_pa_enc_timestamp (context, &md->val[md->len],
409 enctypes[i], key);
410 krb5_free_keyblock (context, key);
411 if (ret)
412 return ret;
413 ++md->len;
415 if(salt == &salt2)
416 krb5_free_salt(context, salt2);
417 return 0;
420 static krb5_error_code
421 init_as_req (krb5_context context,
422 KDCOptions opts,
423 krb5_creds *creds,
424 const krb5_addresses *addrs,
425 const krb5_enctype *etypes,
426 const krb5_preauthtype *ptypes,
427 const krb5_preauthdata *preauth,
428 krb5_key_proc key_proc,
429 krb5_const_pointer keyseed,
430 unsigned nonce,
431 AS_REQ *a)
433 krb5_error_code ret;
434 krb5_salt salt;
436 memset(a, 0, sizeof(*a));
438 a->pvno = 5;
439 a->msg_type = krb_as_req;
440 a->req_body.kdc_options = opts;
441 a->req_body.cname = malloc(sizeof(*a->req_body.cname));
442 if (a->req_body.cname == NULL) {
443 ret = ENOMEM;
444 krb5_set_error_string(context, "malloc: out of memory");
445 goto fail;
447 a->req_body.sname = malloc(sizeof(*a->req_body.sname));
448 if (a->req_body.sname == NULL) {
449 ret = ENOMEM;
450 krb5_set_error_string(context, "malloc: out of memory");
451 goto fail;
453 ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
454 if (ret)
455 goto fail;
456 ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
457 if (ret)
458 goto fail;
459 ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
460 if (ret)
461 goto fail;
463 if(creds->times.starttime) {
464 a->req_body.from = malloc(sizeof(*a->req_body.from));
465 if (a->req_body.from == NULL) {
466 ret = ENOMEM;
467 krb5_set_error_string(context, "malloc: out of memory");
468 goto fail;
470 *a->req_body.from = creds->times.starttime;
472 if(creds->times.endtime){
473 ALLOC(a->req_body.till, 1);
474 *a->req_body.till = creds->times.endtime;
476 if(creds->times.renew_till){
477 a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
478 if (a->req_body.rtime == NULL) {
479 ret = ENOMEM;
480 krb5_set_error_string(context, "malloc: out of memory");
481 goto fail;
483 *a->req_body.rtime = creds->times.renew_till;
485 a->req_body.nonce = nonce;
486 ret = krb5_init_etype (context,
487 &a->req_body.etype.len,
488 &a->req_body.etype.val,
489 etypes);
490 if (ret)
491 goto fail;
494 * This means no addresses
497 if (addrs && addrs->len == 0) {
498 a->req_body.addresses = NULL;
499 } else {
500 a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
501 if (a->req_body.addresses == NULL) {
502 ret = ENOMEM;
503 krb5_set_error_string(context, "malloc: out of memory");
504 goto fail;
507 if (addrs)
508 ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
509 else {
510 ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
511 if(ret == 0 && a->req_body.addresses->len == 0) {
512 free(a->req_body.addresses);
513 a->req_body.addresses = NULL;
516 if (ret)
517 return ret;
520 a->req_body.enc_authorization_data = NULL;
521 a->req_body.additional_tickets = NULL;
523 if(preauth != NULL) {
524 int i;
525 ALLOC(a->padata, 1);
526 if(a->padata == NULL) {
527 ret = ENOMEM;
528 krb5_set_error_string(context, "malloc: out of memory");
529 goto fail;
531 a->padata->val = NULL;
532 a->padata->len = 0;
533 for(i = 0; i < preauth->len; i++) {
534 if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){
535 int j;
537 for(j = 0; j < preauth->val[i].info.len; j++) {
538 krb5_salt *sp = &salt;
539 if(preauth->val[i].info.val[j].salttype)
540 salt.salttype = *preauth->val[i].info.val[j].salttype;
541 else
542 salt.salttype = KRB5_PW_SALT;
543 if(preauth->val[i].info.val[j].salt)
544 salt.saltvalue = *preauth->val[i].info.val[j].salt;
545 else
546 if(salt.salttype == KRB5_PW_SALT)
547 sp = NULL;
548 else
549 krb5_data_zero(&salt.saltvalue);
550 ret = add_padata(context, a->padata, creds->client,
551 key_proc, keyseed,
552 &preauth->val[i].info.val[j].etype, 1,
553 sp);
554 if (ret == 0)
555 break;
559 } else
560 /* not sure this is the way to use `ptypes' */
561 if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE)
562 a->padata = NULL;
563 else if (*ptypes == KRB5_PADATA_ENC_TIMESTAMP) {
564 ALLOC(a->padata, 1);
565 if (a->padata == NULL) {
566 ret = ENOMEM;
567 krb5_set_error_string(context, "malloc: out of memory");
568 goto fail;
570 a->padata->len = 0;
571 a->padata->val = NULL;
573 /* make a v5 salted pa-data */
574 add_padata(context, a->padata, creds->client,
575 key_proc, keyseed, a->req_body.etype.val,
576 a->req_body.etype.len, NULL);
578 /* make a v4 salted pa-data */
579 salt.salttype = KRB5_PW_SALT;
580 krb5_data_zero(&salt.saltvalue);
581 add_padata(context, a->padata, creds->client,
582 key_proc, keyseed, a->req_body.etype.val,
583 a->req_body.etype.len, &salt);
584 } else {
585 krb5_set_error_string (context, "pre-auth type %d not supported",
586 *ptypes);
587 ret = KRB5_PREAUTH_BAD_TYPE;
588 goto fail;
590 return 0;
591 fail:
592 free_AS_REQ(a);
593 return ret;
596 static int
597 set_ptypes(krb5_context context,
598 KRB_ERROR *error,
599 const krb5_preauthtype **ptypes,
600 krb5_preauthdata **preauth)
602 static krb5_preauthdata preauth2;
603 static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE };
605 if(error->e_data) {
606 METHOD_DATA md;
607 int i;
608 decode_METHOD_DATA(error->e_data->data,
609 error->e_data->length,
610 &md,
611 NULL);
612 for(i = 0; i < md.len; i++){
613 switch(md.val[i].padata_type){
614 case KRB5_PADATA_ENC_TIMESTAMP:
615 *ptypes = ptypes2;
616 break;
617 case KRB5_PADATA_ETYPE_INFO:
618 *preauth = &preauth2;
619 ALLOC_SEQ(*preauth, 1);
620 (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
621 krb5_decode_ETYPE_INFO(context,
622 md.val[i].padata_value.data,
623 md.val[i].padata_value.length,
624 &(*preauth)->val[0].info,
625 NULL);
626 break;
627 default:
628 break;
631 free_METHOD_DATA(&md);
632 } else {
633 *ptypes = ptypes2;
635 return(1);
638 krb5_error_code KRB5_LIB_FUNCTION
639 krb5_get_in_cred(krb5_context context,
640 krb5_flags options,
641 const krb5_addresses *addrs,
642 const krb5_enctype *etypes,
643 const krb5_preauthtype *ptypes,
644 const krb5_preauthdata *preauth,
645 krb5_key_proc key_proc,
646 krb5_const_pointer keyseed,
647 krb5_decrypt_proc decrypt_proc,
648 krb5_const_pointer decryptarg,
649 krb5_creds *creds,
650 krb5_kdc_rep *ret_as_reply)
652 krb5_error_code ret;
653 AS_REQ a;
654 krb5_kdc_rep rep;
655 krb5_data req, resp;
656 size_t len;
657 krb5_salt salt;
658 krb5_keyblock *key;
659 size_t size;
660 KDCOptions opts;
661 PA_DATA *pa;
662 krb5_enctype etype;
663 krb5_preauthdata *my_preauth = NULL;
664 unsigned nonce;
665 int done;
667 opts = int2KDCOptions(options);
669 krb5_generate_random_block (&nonce, sizeof(nonce));
670 nonce &= 0xffffffff;
672 do {
673 done = 1;
674 ret = init_as_req (context,
675 opts,
676 creds,
677 addrs,
678 etypes,
679 ptypes,
680 preauth,
681 key_proc,
682 keyseed,
683 nonce,
684 &a);
685 if (my_preauth) {
686 free_ETYPE_INFO(&my_preauth->val[0].info);
687 free (my_preauth->val);
688 my_preauth = NULL;
690 if (ret)
691 return ret;
693 ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret);
694 free_AS_REQ(&a);
695 if (ret)
696 return ret;
697 if(len != req.length)
698 krb5_abortx(context, "internal error in ASN.1 encoder");
700 ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp);
701 krb5_data_free(&req);
702 if (ret)
703 return ret;
705 memset (&rep, 0, sizeof(rep));
706 ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
707 if(ret) {
708 /* let's try to parse it as a KRB-ERROR */
709 KRB_ERROR error;
710 int ret2;
712 ret2 = krb5_rd_error(context, &resp, &error);
713 if(ret2 && resp.data && ((char*)resp.data)[0] == 4)
714 ret = KRB5KRB_AP_ERR_V4_REPLY;
715 krb5_data_free(&resp);
716 if (ret2 == 0) {
717 ret = krb5_error_from_rd_error(context, &error, creds);
718 /* if no preauth was set and KDC requires it, give it
719 one more try */
720 if (!ptypes && !preauth
721 && ret == KRB5KDC_ERR_PREAUTH_REQUIRED
722 #if 0
723 || ret == KRB5KDC_ERR_BADOPTION
724 #endif
725 && set_ptypes(context, &error, &ptypes, &my_preauth)) {
726 done = 0;
727 preauth = my_preauth;
728 krb5_free_error_contents(context, &error);
729 krb5_clear_error_string(context);
730 continue;
732 if(ret_as_reply)
733 ret_as_reply->error = error;
734 else
735 free_KRB_ERROR (&error);
736 return ret;
738 return ret;
740 krb5_data_free(&resp);
741 } while(!done);
743 pa = NULL;
744 etype = rep.kdc_rep.enc_part.etype;
745 if(rep.kdc_rep.padata){
746 int i = 0;
747 pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len,
748 KRB5_PADATA_PW_SALT, &i);
749 if(pa == NULL) {
750 i = 0;
751 pa = krb5_find_padata(rep.kdc_rep.padata->val,
752 rep.kdc_rep.padata->len,
753 KRB5_PADATA_AFS3_SALT, &i);
756 if(pa) {
757 salt.salttype = pa->padata_type;
758 salt.saltvalue = pa->padata_value;
760 ret = (*key_proc)(context, etype, salt, keyseed, &key);
761 } else {
762 /* make a v5 salted pa-data */
763 ret = krb5_get_pw_salt (context, creds->client, &salt);
765 if (ret)
766 goto out;
767 ret = (*key_proc)(context, etype, salt, keyseed, &key);
768 krb5_free_salt(context, salt);
770 if (ret)
771 goto out;
774 unsigned flags = 0;
775 if (opts.request_anonymous)
776 flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
778 ret = _krb5_extract_ticket(context,
779 &rep,
780 creds,
781 key,
782 keyseed,
783 KRB5_KU_AS_REP_ENC_PART,
784 NULL,
785 nonce,
786 flags,
787 decrypt_proc,
788 decryptarg);
790 memset (key->keyvalue.data, 0, key->keyvalue.length);
791 krb5_free_keyblock_contents (context, key);
792 free (key);
794 out:
795 if (ret == 0 && ret_as_reply)
796 *ret_as_reply = rep;
797 else
798 krb5_free_kdc_rep (context, &rep);
799 return ret;
802 krb5_error_code KRB5_LIB_FUNCTION
803 krb5_get_in_tkt(krb5_context context,
804 krb5_flags options,
805 const krb5_addresses *addrs,
806 const krb5_enctype *etypes,
807 const krb5_preauthtype *ptypes,
808 krb5_key_proc key_proc,
809 krb5_const_pointer keyseed,
810 krb5_decrypt_proc decrypt_proc,
811 krb5_const_pointer decryptarg,
812 krb5_creds *creds,
813 krb5_ccache ccache,
814 krb5_kdc_rep *ret_as_reply)
816 krb5_error_code ret;
818 ret = krb5_get_in_cred (context,
819 options,
820 addrs,
821 etypes,
822 ptypes,
823 NULL,
824 key_proc,
825 keyseed,
826 decrypt_proc,
827 decryptarg,
828 creds,
829 ret_as_reply);
830 if(ret)
831 return ret;
832 if (ccache)
833 ret = krb5_cc_store_cred (context, ccache, creds);
834 return ret;