2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
34 #include "krb5_locl.h"
38 krb5_error_code KRB5_LIB_FUNCTION
39 krb5_init_etype (krb5_context context
,
42 const krb5_enctype
*etypes
)
46 krb5_enctype
*tmp
= NULL
;
50 ret
= krb5_get_default_in_tkt_etypes(context
,
57 for (i
= 0; etypes
[i
]; ++i
)
60 *val
= malloc(i
* sizeof(**val
));
61 if (i
!= 0 && *val
== NULL
) {
63 krb5_set_error_message(context
, ret
, "malloc: out of memory");
75 static krb5_error_code
76 check_server_referral(krb5_context context
,
79 krb5_const_principal requested
,
80 krb5_const_principal returned
,
81 const krb5_keyblock
const * key
)
84 PA_ServerReferralData ref
;
92 if (rep
->kdc_rep
.padata
== NULL
)
95 pa
= krb5_find_padata(rep
->kdc_rep
.padata
->val
,
96 rep
->kdc_rep
.padata
->len
,
97 KRB5_PADATA_SERVER_REFERRAL
, &i
);
101 memset(&ed
, 0, sizeof(ed
));
102 memset(&ref
, 0, sizeof(ref
));
104 ret
= decode_EncryptedData(pa
->padata_value
.data
,
105 pa
->padata_value
.length
,
109 if (len
!= pa
->padata_value
.length
) {
110 free_EncryptedData(&ed
);
111 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
, "Referral EncryptedData wrong");
112 return KRB5KRB_AP_ERR_MODIFIED
;
115 ret
= krb5_crypto_init(context
, key
, 0, &session
);
117 free_EncryptedData(&ed
);
121 ret
= krb5_decrypt_EncryptedData(context
, session
,
122 KRB5_KU_PA_SERVER_REFERRAL
,
124 free_EncryptedData(&ed
);
125 krb5_crypto_destroy(context
, session
);
129 ret
= decode_PA_ServerReferralData(data
.data
, data
.length
, &ref
, &len
);
131 krb5_data_free(&data
);
134 krb5_data_free(&data
);
136 if (strcmp(requested
->realm
, returned
->realm
) != 0) {
137 free_PA_ServerReferralData(&ref
);
138 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
139 "server ref realm mismatch");
140 return KRB5KRB_AP_ERR_MODIFIED
;
143 if (returned
->name
.name_string
.len
== 2 &&
144 strcmp(returned
->name
.name_string
.val
[0], KRB5_TGS_NAME
) == 0)
146 const char *realm
= returned
->name
.name_string
.val
[1];
148 if (ref
.referred_realm
== NULL
149 || strcmp(*ref
.referred_realm
, realm
) != 0)
151 free_PA_ServerReferralData(&ref
);
152 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
153 "tgt returned with wrong ref");
154 return KRB5KRB_AP_ERR_MODIFIED
;
156 } else if (krb5_principal_compare(context
, returned
, requested
) == 0) {
157 free_PA_ServerReferralData(&ref
);
158 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
159 "req princ no same as returned");
160 return KRB5KRB_AP_ERR_MODIFIED
;
163 if (ref
.requested_principal_name
) {
164 cmp
= _krb5_principal_compare_PrincipalName(context
,
166 ref
.requested_principal_name
);
168 free_PA_ServerReferralData(&ref
);
169 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
170 "compare requested failed");
171 return KRB5KRB_AP_ERR_MODIFIED
;
173 } else if (flags
& EXTRACT_TICKET_AS_REQ
) {
174 free_PA_ServerReferralData(&ref
);
175 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
176 "Requested principal missing on AS-REQ");
177 return KRB5KRB_AP_ERR_MODIFIED
;
180 free_PA_ServerReferralData(&ref
);
184 if (krb5_principal_compare(context
, requested
, returned
) == FALSE
) {
185 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
186 "Not same server principal returned "
188 return KRB5KRB_AP_ERR_MODIFIED
;
195 * Verify referral data
199 static krb5_error_code
200 check_client_referral(krb5_context context
,
202 krb5_const_principal requested
,
203 krb5_const_principal mapped
,
204 krb5_keyblock
const * key
)
207 PA_ClientCanonicalized canon
;
214 if (rep
->kdc_rep
.padata
== NULL
)
217 pa
= krb5_find_padata(rep
->kdc_rep
.padata
->val
,
218 rep
->kdc_rep
.padata
->len
,
219 KRB5_PADATA_CLIENT_CANONICALIZED
, &i
);
223 ret
= decode_PA_ClientCanonicalized(pa
->padata_value
.data
,
224 pa
->padata_value
.length
,
227 krb5_set_error_message(context
, ret
, "Failed to decode "
228 "PA_ClientCanonicalized");
232 ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames
, data
.data
, data
.length
,
233 &canon
.names
, &len
, ret
);
235 free_PA_ClientCanonicalized(&canon
);
238 if (data
.length
!= len
)
239 krb5_abortx(context
, "internal asn.1 error");
241 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
244 free_PA_ClientCanonicalized(&canon
);
248 ret
= krb5_verify_checksum(context
, crypto
, KRB5_KU_CANONICALIZED_NAMES
,
249 data
.data
, data
.length
,
250 &canon
.canon_checksum
);
251 krb5_crypto_destroy(context
, crypto
);
254 krb5_set_error_message(context
, ret
, "Failed to verify "
255 "client canonicalized data");
256 free_PA_ClientCanonicalized(&canon
);
260 if (!_krb5_principal_compare_PrincipalName(context
,
262 &canon
.names
.requested_name
))
264 free_PA_ClientCanonicalized(&canon
);
265 krb5_set_error_message(context
, KRB5_PRINC_NOMATCH
,
266 "Requested name doesn't match"
267 " in client referral");
268 return KRB5_PRINC_NOMATCH
;
270 if (!_krb5_principal_compare_PrincipalName(context
,
272 &canon
.names
.mapped_name
))
274 free_PA_ClientCanonicalized(&canon
);
275 krb5_set_error_message(context
, KRB5_PRINC_NOMATCH
,
276 "Mapped name doesn't match"
277 " in client referral");
278 return KRB5_PRINC_NOMATCH
;
284 if (krb5_principal_compare(context
, requested
, mapped
) == FALSE
) {
285 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
286 "Not same client principal returned "
288 return KRB5KRB_AP_ERR_MODIFIED
;
295 static krb5_error_code
296 decrypt_tkt (krb5_context context
,
298 krb5_key_usage usage
,
299 krb5_const_pointer decrypt_arg
,
300 krb5_kdc_rep
*dec_rep
)
307 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
311 ret
= krb5_decrypt_EncryptedData (context
,
314 &dec_rep
->kdc_rep
.enc_part
,
316 krb5_crypto_destroy(context
, crypto
);
321 ret
= krb5_decode_EncASRepPart(context
,
327 ret
= krb5_decode_EncTGSRepPart(context
,
332 krb5_data_free (&data
);
339 _krb5_extract_ticket(krb5_context context
,
343 krb5_const_pointer keyseed
,
344 krb5_key_usage key_usage
,
345 krb5_addresses
*addrs
,
348 krb5_decrypt_proc decrypt_proc
,
349 krb5_const_pointer decryptarg
)
352 krb5_principal tmp_principal
;
355 krb5_timestamp sec_now
;
359 if (decrypt_proc
== NULL
)
360 decrypt_proc
= decrypt_tkt
;
362 ret
= (*decrypt_proc
)(context
, key
, key_usage
, decryptarg
, rep
);
366 /* save session key */
368 creds
->session
.keyvalue
.length
= 0;
369 creds
->session
.keyvalue
.data
= NULL
;
370 creds
->session
.keytype
= rep
->enc_part
.key
.keytype
;
371 ret
= krb5_data_copy (&creds
->session
.keyvalue
,
372 rep
->enc_part
.key
.keyvalue
.data
,
373 rep
->enc_part
.key
.keyvalue
.length
);
375 krb5_clear_error_string(context
);
381 * this is really a ugly hack, to support using the Netbios Domain Name
382 * as realm against windows KDC's, they always return the full realm
383 * based on the DNS Name.
385 flags
|= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
;
386 flags
|= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH
;
388 /* compare client and save */
389 ret
= _krb5_principalname2krb5_principal (context
,
392 rep
->kdc_rep
.crealm
);
396 /* check client referral and save principal */
397 /* anonymous here ? */
398 if((flags
& EXTRACT_TICKET_ALLOW_CNAME_MISMATCH
) == 0) {
399 ret
= check_client_referral(context
, rep
,
404 krb5_free_principal (context
, tmp_principal
);
408 krb5_free_principal (context
, creds
->client
);
409 creds
->client
= tmp_principal
;
411 /* check server referral and save principal */
412 ret
= _krb5_principalname2krb5_principal (context
,
414 rep
->kdc_rep
.ticket
.sname
,
415 rep
->kdc_rep
.ticket
.realm
);
418 if((flags
& EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
) == 0){
419 ret
= check_server_referral(context
,
426 krb5_free_principal (context
, tmp_principal
);
430 krb5_free_principal(context
, creds
->server
);
431 creds
->server
= tmp_principal
;
434 if(flags
& EXTRACT_TICKET_MATCH_REALM
){
435 const char *srealm
= krb5_principal_get_realm(context
, creds
->server
);
436 const char *crealm
= krb5_principal_get_realm(context
, creds
->client
);
438 if (strcmp(rep
->enc_part
.srealm
, srealm
) != 0 ||
439 strcmp(rep
->enc_part
.srealm
, crealm
) != 0)
441 ret
= KRB5KRB_AP_ERR_MODIFIED
;
442 krb5_clear_error_string(context
);
449 if (nonce
!= rep
->enc_part
.nonce
) {
450 ret
= KRB5KRB_AP_ERR_MODIFIED
;
451 krb5_set_error_message(context
, ret
, "malloc: out of memory");
457 krb5_timeofday (context
, &sec_now
);
458 if (rep
->enc_part
.flags
.initial
459 && context
->kdc_sec_offset
== 0
460 && krb5_config_get_bool (context
, NULL
,
464 context
->kdc_sec_offset
= rep
->enc_part
.authtime
- sec_now
;
465 krb5_timeofday (context
, &sec_now
);
468 /* check all times */
470 if (rep
->enc_part
.starttime
) {
471 tmp_time
= *rep
->enc_part
.starttime
;
473 tmp_time
= rep
->enc_part
.authtime
;
475 if (creds
->times
.starttime
== 0
476 && abs(tmp_time
- sec_now
) > context
->max_skew
) {
477 ret
= KRB5KRB_AP_ERR_SKEW
;
478 krb5_set_error_message (context
, ret
,
479 "time skew (%d) larger than max (%d)",
480 abs(tmp_time
- sec_now
),
481 (int)context
->max_skew
);
485 if (creds
->times
.starttime
!= 0
486 && tmp_time
!= creds
->times
.starttime
) {
487 krb5_clear_error_string (context
);
488 ret
= KRB5KRB_AP_ERR_MODIFIED
;
492 creds
->times
.starttime
= tmp_time
;
494 if (rep
->enc_part
.renew_till
) {
495 tmp_time
= *rep
->enc_part
.renew_till
;
499 if (creds
->times
.renew_till
!= 0
500 && tmp_time
> creds
->times
.renew_till
) {
501 krb5_clear_error_string (context
);
502 ret
= KRB5KRB_AP_ERR_MODIFIED
;
506 creds
->times
.renew_till
= tmp_time
;
508 creds
->times
.authtime
= rep
->enc_part
.authtime
;
510 if (creds
->times
.endtime
!= 0
511 && rep
->enc_part
.endtime
> creds
->times
.endtime
) {
512 krb5_clear_error_string (context
);
513 ret
= KRB5KRB_AP_ERR_MODIFIED
;
517 creds
->times
.endtime
= rep
->enc_part
.endtime
;
519 if(rep
->enc_part
.caddr
)
520 krb5_copy_addresses (context
, rep
->enc_part
.caddr
, &creds
->addresses
);
522 krb5_copy_addresses (context
, addrs
, &creds
->addresses
);
524 creds
->addresses
.len
= 0;
525 creds
->addresses
.val
= NULL
;
527 creds
->flags
.b
= rep
->enc_part
.flags
;
529 creds
->authdata
.len
= 0;
530 creds
->authdata
.val
= NULL
;
533 ASN1_MALLOC_ENCODE(Ticket
, creds
->ticket
.data
, creds
->ticket
.length
,
534 &rep
->kdc_rep
.ticket
, &len
, ret
);
537 if (creds
->ticket
.length
!= len
)
538 krb5_abortx(context
, "internal error in ASN.1 encoder");
539 creds
->second_ticket
.length
= 0;
540 creds
->second_ticket
.data
= NULL
;
544 memset (rep
->enc_part
.key
.keyvalue
.data
, 0,
545 rep
->enc_part
.key
.keyvalue
.length
);
550 static krb5_error_code
551 make_pa_enc_timestamp(krb5_context context
, PA_DATA
*pa
,
552 krb5_enctype etype
, krb5_keyblock
*key
)
558 EncryptedData encdata
;
564 krb5_us_timeofday (context
, &p
.patimestamp
, &usec
);
568 ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC
, buf
, buf_size
, &p
, &len
, ret
);
572 krb5_abortx(context
, "internal error in ASN.1 encoder");
573 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
578 ret
= krb5_encrypt_EncryptedData(context
,
580 KRB5_KU_PA_ENC_TIMESTAMP
,
586 krb5_crypto_destroy(context
, crypto
);
590 ASN1_MALLOC_ENCODE(EncryptedData
, buf
, buf_size
, &encdata
, &len
, ret
);
591 free_EncryptedData(&encdata
);
595 krb5_abortx(context
, "internal error in ASN.1 encoder");
596 pa
->padata_type
= KRB5_PADATA_ENC_TIMESTAMP
;
597 pa
->padata_value
.length
= len
;
598 pa
->padata_value
.data
= buf
;
602 static krb5_error_code
603 add_padata(krb5_context context
,
605 krb5_principal client
,
606 krb5_key_proc key_proc
,
607 krb5_const_pointer keyseed
,
608 krb5_enctype
*enctypes
,
619 /* default to standard salt */
620 ret
= krb5_get_pw_salt (context
, client
, &salt2
);
624 enctypes
= context
->etypes
;
626 for (ep
= enctypes
; *ep
!= ETYPE_NULL
; ep
++)
629 pa2
= realloc (md
->val
, (md
->len
+ netypes
) * sizeof(*md
->val
));
631 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
636 for (i
= 0; i
< netypes
; ++i
) {
639 ret
= (*key_proc
)(context
, enctypes
[i
], *salt
, keyseed
, &key
);
642 ret
= make_pa_enc_timestamp (context
, &md
->val
[md
->len
],
644 krb5_free_keyblock (context
, key
);
650 krb5_free_salt(context
, salt2
);
654 static krb5_error_code
655 init_as_req (krb5_context context
,
658 const krb5_addresses
*addrs
,
659 const krb5_enctype
*etypes
,
660 const krb5_preauthtype
*ptypes
,
661 const krb5_preauthdata
*preauth
,
662 krb5_key_proc key_proc
,
663 krb5_const_pointer keyseed
,
670 memset(a
, 0, sizeof(*a
));
673 a
->msg_type
= krb_as_req
;
674 a
->req_body
.kdc_options
= opts
;
675 a
->req_body
.cname
= malloc(sizeof(*a
->req_body
.cname
));
676 if (a
->req_body
.cname
== NULL
) {
678 krb5_set_error_message(context
, ret
, "malloc: out of memory");
681 a
->req_body
.sname
= malloc(sizeof(*a
->req_body
.sname
));
682 if (a
->req_body
.sname
== NULL
) {
684 krb5_set_error_message(context
, ret
, "malloc: out of memory");
687 ret
= _krb5_principal2principalname (a
->req_body
.cname
, creds
->client
);
690 ret
= _krb5_principal2principalname (a
->req_body
.sname
, creds
->server
);
693 ret
= copy_Realm(&creds
->client
->realm
, &a
->req_body
.realm
);
697 if(creds
->times
.starttime
) {
698 a
->req_body
.from
= malloc(sizeof(*a
->req_body
.from
));
699 if (a
->req_body
.from
== NULL
) {
701 krb5_set_error_message(context
, ret
, "malloc: out of memory");
704 *a
->req_body
.from
= creds
->times
.starttime
;
706 if(creds
->times
.endtime
){
707 ALLOC(a
->req_body
.till
, 1);
708 *a
->req_body
.till
= creds
->times
.endtime
;
710 if(creds
->times
.renew_till
){
711 a
->req_body
.rtime
= malloc(sizeof(*a
->req_body
.rtime
));
712 if (a
->req_body
.rtime
== NULL
) {
714 krb5_set_error_message(context
, ret
, "malloc: out of memory");
717 *a
->req_body
.rtime
= creds
->times
.renew_till
;
719 a
->req_body
.nonce
= nonce
;
720 ret
= krb5_init_etype (context
,
721 &a
->req_body
.etype
.len
,
722 &a
->req_body
.etype
.val
,
728 * This means no addresses
731 if (addrs
&& addrs
->len
== 0) {
732 a
->req_body
.addresses
= NULL
;
734 a
->req_body
.addresses
= malloc(sizeof(*a
->req_body
.addresses
));
735 if (a
->req_body
.addresses
== NULL
) {
737 krb5_set_error_message(context
, ret
, "malloc: out of memory");
742 ret
= krb5_copy_addresses(context
, addrs
, a
->req_body
.addresses
);
744 ret
= krb5_get_all_client_addrs (context
, a
->req_body
.addresses
);
745 if(ret
== 0 && a
->req_body
.addresses
->len
== 0) {
746 free(a
->req_body
.addresses
);
747 a
->req_body
.addresses
= NULL
;
754 a
->req_body
.enc_authorization_data
= NULL
;
755 a
->req_body
.additional_tickets
= NULL
;
757 if(preauth
!= NULL
) {
760 if(a
->padata
== NULL
) {
762 krb5_set_error_message(context
, ret
, "malloc: out of memory");
765 a
->padata
->val
= NULL
;
767 for(i
= 0; i
< preauth
->len
; i
++) {
768 if(preauth
->val
[i
].type
== KRB5_PADATA_ENC_TIMESTAMP
){
771 for(j
= 0; j
< preauth
->val
[i
].info
.len
; j
++) {
772 krb5_salt
*sp
= &salt
;
773 if(preauth
->val
[i
].info
.val
[j
].salttype
)
774 salt
.salttype
= *preauth
->val
[i
].info
.val
[j
].salttype
;
776 salt
.salttype
= KRB5_PW_SALT
;
777 if(preauth
->val
[i
].info
.val
[j
].salt
)
778 salt
.saltvalue
= *preauth
->val
[i
].info
.val
[j
].salt
;
780 if(salt
.salttype
== KRB5_PW_SALT
)
783 krb5_data_zero(&salt
.saltvalue
);
784 ret
= add_padata(context
, a
->padata
, creds
->client
,
786 &preauth
->val
[i
].info
.val
[j
].etype
, 1,
794 /* not sure this is the way to use `ptypes' */
795 if (ptypes
== NULL
|| *ptypes
== KRB5_PADATA_NONE
)
797 else if (*ptypes
== KRB5_PADATA_ENC_TIMESTAMP
) {
799 if (a
->padata
== NULL
) {
801 krb5_set_error_message(context
, ret
, "malloc: out of memory");
805 a
->padata
->val
= NULL
;
807 /* make a v5 salted pa-data */
808 add_padata(context
, a
->padata
, creds
->client
,
809 key_proc
, keyseed
, a
->req_body
.etype
.val
,
810 a
->req_body
.etype
.len
, NULL
);
812 /* make a v4 salted pa-data */
813 salt
.salttype
= KRB5_PW_SALT
;
814 krb5_data_zero(&salt
.saltvalue
);
815 add_padata(context
, a
->padata
, creds
->client
,
816 key_proc
, keyseed
, a
->req_body
.etype
.val
,
817 a
->req_body
.etype
.len
, &salt
);
819 ret
= KRB5_PREAUTH_BAD_TYPE
;
820 krb5_set_error_message (context
, ret
, "pre-auth type %d not supported",
831 set_ptypes(krb5_context context
,
833 const krb5_preauthtype
**ptypes
,
834 krb5_preauthdata
**preauth
)
836 static krb5_preauthdata preauth2
;
837 static krb5_preauthtype ptypes2
[] = { KRB5_PADATA_ENC_TIMESTAMP
, KRB5_PADATA_NONE
};
842 decode_METHOD_DATA(error
->e_data
->data
,
843 error
->e_data
->length
,
846 for(i
= 0; i
< md
.len
; i
++){
847 switch(md
.val
[i
].padata_type
){
848 case KRB5_PADATA_ENC_TIMESTAMP
:
851 case KRB5_PADATA_ETYPE_INFO
:
852 *preauth
= &preauth2
;
853 ALLOC_SEQ(*preauth
, 1);
854 (*preauth
)->val
[0].type
= KRB5_PADATA_ENC_TIMESTAMP
;
855 krb5_decode_ETYPE_INFO(context
,
856 md
.val
[i
].padata_value
.data
,
857 md
.val
[i
].padata_value
.length
,
858 &(*preauth
)->val
[0].info
,
865 free_METHOD_DATA(&md
);
872 krb5_error_code KRB5_LIB_FUNCTION
873 krb5_get_in_cred(krb5_context context
,
875 const krb5_addresses
*addrs
,
876 const krb5_enctype
*etypes
,
877 const krb5_preauthtype
*ptypes
,
878 const krb5_preauthdata
*preauth
,
879 krb5_key_proc key_proc
,
880 krb5_const_pointer keyseed
,
881 krb5_decrypt_proc decrypt_proc
,
882 krb5_const_pointer decryptarg
,
884 krb5_kdc_rep
*ret_as_reply
)
897 krb5_preauthdata
*my_preauth
= NULL
;
901 opts
= int2KDCOptions(options
);
903 krb5_generate_random_block (&nonce
, sizeof(nonce
));
908 ret
= init_as_req (context
,
920 free_ETYPE_INFO(&my_preauth
->val
[0].info
);
921 free (my_preauth
->val
);
927 ASN1_MALLOC_ENCODE(AS_REQ
, req
.data
, req
.length
, &a
, &len
, ret
);
931 if(len
!= req
.length
)
932 krb5_abortx(context
, "internal error in ASN.1 encoder");
934 ret
= krb5_sendto_kdc (context
, &req
, &creds
->client
->realm
, &resp
);
935 krb5_data_free(&req
);
939 memset (&rep
, 0, sizeof(rep
));
940 ret
= decode_AS_REP(resp
.data
, resp
.length
, &rep
.kdc_rep
, &size
);
942 /* let's try to parse it as a KRB-ERROR */
946 ret2
= krb5_rd_error(context
, &resp
, &error
);
947 if(ret2
&& resp
.data
&& ((char*)resp
.data
)[0] == 4)
948 ret
= KRB5KRB_AP_ERR_V4_REPLY
;
949 krb5_data_free(&resp
);
951 ret
= krb5_error_from_rd_error(context
, &error
, creds
);
952 /* if no preauth was set and KDC requires it, give it
954 if (!ptypes
&& !preauth
955 && ret
== KRB5KDC_ERR_PREAUTH_REQUIRED
957 || ret
== KRB5KDC_ERR_BADOPTION
959 && set_ptypes(context
, &error
, &ptypes
, &my_preauth
)) {
961 preauth
= my_preauth
;
962 krb5_free_error_contents(context
, &error
);
963 krb5_clear_error_string(context
);
967 ret_as_reply
->error
= error
;
969 free_KRB_ERROR (&error
);
974 krb5_data_free(&resp
);
978 etype
= rep
.kdc_rep
.enc_part
.etype
;
979 if(rep
.kdc_rep
.padata
){
981 pa
= krb5_find_padata(rep
.kdc_rep
.padata
->val
, rep
.kdc_rep
.padata
->len
,
982 KRB5_PADATA_PW_SALT
, &i
);
985 pa
= krb5_find_padata(rep
.kdc_rep
.padata
->val
,
986 rep
.kdc_rep
.padata
->len
,
987 KRB5_PADATA_AFS3_SALT
, &i
);
991 salt
.salttype
= pa
->padata_type
;
992 salt
.saltvalue
= pa
->padata_value
;
994 ret
= (*key_proc
)(context
, etype
, salt
, keyseed
, &key
);
996 /* make a v5 salted pa-data */
997 ret
= krb5_get_pw_salt (context
, creds
->client
, &salt
);
1001 ret
= (*key_proc
)(context
, etype
, salt
, keyseed
, &key
);
1002 krb5_free_salt(context
, salt
);
1009 if (opts
.request_anonymous
)
1010 flags
|= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH
;
1012 ret
= _krb5_extract_ticket(context
,
1017 KRB5_KU_AS_REP_ENC_PART
,
1024 memset (key
->keyvalue
.data
, 0, key
->keyvalue
.length
);
1025 krb5_free_keyblock_contents (context
, key
);
1029 if (ret
== 0 && ret_as_reply
)
1030 *ret_as_reply
= rep
;
1032 krb5_free_kdc_rep (context
, &rep
);
1036 krb5_error_code KRB5_LIB_FUNCTION
1037 krb5_get_in_tkt(krb5_context context
,
1039 const krb5_addresses
*addrs
,
1040 const krb5_enctype
*etypes
,
1041 const krb5_preauthtype
*ptypes
,
1042 krb5_key_proc key_proc
,
1043 krb5_const_pointer keyseed
,
1044 krb5_decrypt_proc decrypt_proc
,
1045 krb5_const_pointer decryptarg
,
1048 krb5_kdc_rep
*ret_as_reply
)
1050 krb5_error_code ret
;
1052 ret
= krb5_get_in_cred (context
,
1067 ret
= krb5_cc_store_cred (context
, ccache
, creds
);