2 * Copyright (c) 2011 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"
39 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
40 _krb5_fast_cf2(krb5_context context
,
45 krb5_keyblock
*armorkey
,
46 krb5_crypto
*armor_crypto
)
48 krb5_crypto crypto1
, crypto2
;
52 ret
= krb5_crypto_init(context
, key1
, 0, &crypto1
);
56 ret
= krb5_crypto_init(context
, key2
, 0, &crypto2
);
58 krb5_crypto_destroy(context
, crypto1
);
62 pa1
.data
= rk_UNCONST(pepper1
);
63 pa1
.length
= strlen(pepper1
);
64 pa2
.data
= rk_UNCONST(pepper2
);
65 pa2
.length
= strlen(pepper2
);
67 ret
= krb5_crypto_fx_cf2(context
, crypto1
, crypto2
, &pa1
, &pa2
,
68 key1
->keytype
, armorkey
);
69 krb5_crypto_destroy(context
, crypto1
);
70 krb5_crypto_destroy(context
, crypto2
);
75 ret
= krb5_crypto_init(context
, armorkey
, 0, armor_crypto
);
77 krb5_free_keyblock_contents(context
, armorkey
);
83 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
84 _krb5_fast_armor_key(krb5_context context
,
85 krb5_keyblock
*subkey
,
86 krb5_keyblock
*sessionkey
,
87 krb5_keyblock
*armorkey
,
88 krb5_crypto
*armor_crypto
)
90 return _krb5_fast_cf2(context
,
99 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
100 _krb5_fast_explicit_armor_key(krb5_context context
,
101 krb5_keyblock
*armorkey
,
102 krb5_keyblock
*subkey
,
103 krb5_keyblock
*explicit_armorkey
,
104 krb5_crypto
*explicit_armor_crypto
)
106 return _krb5_fast_cf2(context
,
112 explicit_armor_crypto
);
115 static krb5_error_code
116 check_fast(krb5_context context
, struct krb5_fast_state
*state
)
118 if (state
&& (state
->flags
& KRB5_FAST_EXPECTED
)) {
119 krb5_set_error_message(context
, KRB5KRB_AP_ERR_MODIFIED
,
120 "Expected FAST, but no FAST "
121 "was in the response from the KDC");
122 return KRB5KRB_AP_ERR_MODIFIED
;
127 static krb5_error_code
128 make_local_fast_ap_fxarmor(krb5_context context
,
129 krb5_ccache armor_ccache
,
130 krb5_const_realm realm
,
131 krb5_data
*armor_value
,
132 krb5_keyblock
*armor_key
,
133 krb5_crypto
*armor_crypto
)
135 krb5_auth_context auth_context
= NULL
;
136 krb5_creds cred
, *credp
= NULL
;
139 krb5_const_realm tgs_realm
;
141 if (armor_ccache
== NULL
) {
142 krb5_set_error_message(context
, EINVAL
,
143 "Armor credential cache required");
147 krb5_data_zero(&empty
);
148 memset(&cred
, 0, sizeof(cred
));
150 ret
= krb5_auth_con_init (context
, &auth_context
);
154 ret
= krb5_cc_get_principal(context
, armor_ccache
, &cred
.client
);
159 * Make sure we don't ask for a krbtgt/WELLKNOWN:ANONYMOUS
161 if (krb5_principal_is_anonymous(context
, cred
.client
,
162 KRB5_ANON_MATCH_UNAUTHENTICATED
))
165 tgs_realm
= cred
.client
->realm
;
167 ret
= krb5_make_principal(context
, &cred
.server
,
175 ret
= krb5_get_credentials(context
, 0, armor_ccache
, &cred
, &credp
);
179 ret
= krb5_auth_con_add_AuthorizationData(context
, auth_context
,
180 KRB5_AUTHDATA_FX_FAST_ARMOR
,
185 ret
= krb5_mk_req_extended(context
,
194 ret
= _krb5_fast_armor_key(context
,
195 auth_context
->local_subkey
,
196 auth_context
->keyblock
,
204 krb5_auth_con_free(context
, auth_context
);
206 krb5_free_creds(context
, credp
);
207 krb5_free_principal(context
, cred
.server
);
208 krb5_free_principal(context
, cred
.client
);
214 static heim_base_once_t armor_service_once
= HEIM_BASE_ONCE_INIT
;
215 static heim_ipc armor_service
= NULL
;
218 fast_armor_init_ipc(void *ctx
)
221 heim_ipc_init_context("ANY:org.h5l.armor-service", ipc
);
225 static krb5_error_code
226 make_fast_ap_fxarmor(krb5_context context
,
227 struct krb5_fast_state
*state
,
228 krb5_const_realm realm
,
229 KrbFastArmor
**armor
)
231 KrbFastArmor
*fxarmor
= NULL
;
237 if (fxarmor
== NULL
) {
242 if (state
->flags
& KRB5_FAST_AP_ARMOR_SERVICE
) {
244 krb5_set_error_message(context
, ENOTSUP
, "Fast armor IPC service not supportted yet on Windows");
248 KERB_ARMOR_SERVICE_REPLY msg
;
249 krb5_data request
, reply
;
251 heim_base_once_f(&armor_service_once
, &armor_service
, fast_armor_init_ipc
);
252 if (armor_service
== NULL
) {
253 krb5_set_error_message(context
, ENOENT
, "Failed to open fast armor service");
258 krb5_data_zero(&reply
);
260 request
.data
= rk_UNCONST(realm
);
261 request
.length
= strlen(realm
);
263 ret
= heim_ipc_call(armor_service
, &request
, &reply
, NULL
);
265 krb5_set_error_message(context
, ret
, "Failed to get armor service credential");
269 ret
= decode_KERB_ARMOR_SERVICE_REPLY(reply
.data
, reply
.length
, &msg
, NULL
);
270 krb5_data_free(&reply
);
274 ret
= copy_KrbFastArmor(&msg
.armor
, fxarmor
);
276 free_KERB_ARMOR_SERVICE_REPLY(&msg
);
280 ret
= krb5_copy_keyblock_contents(context
, &msg
.armor_key
, &state
->armor_key
);
281 free_KERB_ARMOR_SERVICE_REPLY(&msg
);
285 ret
= krb5_crypto_init(context
, &state
->armor_key
, 0, &state
->armor_crypto
);
290 fxarmor
->armor_type
= 1;
292 ret
= make_local_fast_ap_fxarmor(context
,
295 &fxarmor
->armor_value
,
297 &state
->armor_crypto
);
308 free_KrbFastArmor(fxarmor
);
314 static krb5_error_code
315 unwrap_fast_rep(krb5_context context
,
316 struct krb5_fast_state
*state
,
318 KrbFastResponse
*fastrep
)
320 PA_FX_FAST_REPLY fxfastrep
;
323 memset(&fxfastrep
, 0, sizeof(fxfastrep
));
325 ret
= decode_PA_FX_FAST_REPLY(pa
->padata_value
.data
,
326 pa
->padata_value
.length
,
331 if (fxfastrep
.element
== choice_PA_FX_FAST_REPLY_armored_data
) {
334 ret
= krb5_decrypt_EncryptedData(context
,
337 &fxfastrep
.u
.armored_data
.enc_fast_rep
,
342 ret
= decode_KrbFastResponse(data
.data
, data
.length
, fastrep
, NULL
);
343 krb5_data_free(&data
);
348 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
353 free_PA_FX_FAST_REPLY(&fxfastrep
);
358 static krb5_error_code
359 set_anon_principal(krb5_context context
, PrincipalName
**p
)
366 (*p
)->name_type
= KRB5_NT_PRINCIPAL
;
368 ALLOC_SEQ(&(*p
)->name_string
, 2);
369 if ((*p
)->name_string
.val
== NULL
)
372 (*p
)->name_string
.val
[0] = strdup(KRB5_WELLKNOWN_NAME
);
373 if ((*p
)->name_string
.val
[0] == NULL
)
376 (*p
)->name_string
.val
[1] = strdup(KRB5_ANON_NAME
);
377 if ((*p
)->name_string
.val
[1] == NULL
)
383 if ((*p
)->name_string
.val
) {
384 free((*p
)->name_string
.val
[0]);
385 free((*p
)->name_string
.val
[1]);
386 free((*p
)->name_string
.val
);
391 return krb5_enomem(context
);
395 _krb5_fast_create_armor(krb5_context context
,
396 struct krb5_fast_state
*state
,
401 if (state
->armor_crypto
== NULL
) {
402 if (state
->armor_ccache
|| state
->armor_ac
|| (state
->flags
& KRB5_FAST_AP_ARMOR_SERVICE
)) {
404 * Instead of keeping state in FX_COOKIE in the KDC, we
405 * rebuild a new armor key for every request, because this
406 * is what the MIT KDC expect and RFC6113 is vage about
407 * what the behavior should be.
409 state
->type
= choice_PA_FX_FAST_REQUEST_armored_data
;
411 return check_fast(context
, state
);
415 if (state
->type
== choice_PA_FX_FAST_REQUEST_armored_data
) {
416 if (state
->armor_crypto
) {
417 krb5_crypto_destroy(context
, state
->armor_crypto
);
418 state
->armor_crypto
= NULL
;
420 if (state
->strengthen_key
) {
421 krb5_free_keyblock(context
, state
->strengthen_key
);
422 state
->strengthen_key
= NULL
;
424 krb5_free_keyblock_contents(context
, &state
->armor_key
);
427 * If we have a armor auth context, its because the caller
428 * wants us to do an implicit FAST armor (TGS-REQ).
430 if (state
->armor_ac
) {
431 heim_assert((state
->flags
& KRB5_FAST_AS_REQ
) == 0, "FAST AS with AC");
433 ret
= _krb5_fast_armor_key(context
,
434 state
->armor_ac
->local_subkey
,
435 state
->armor_ac
->keyblock
,
437 &state
->armor_crypto
);
441 heim_assert((state
->flags
& KRB5_FAST_AS_REQ
) != 0, "FAST TGS without AC");
443 if (state
->armor_data
) {
444 free_KrbFastArmor(state
->armor_data
);
445 free(state
->armor_data
);
446 state
->armor_data
= NULL
;
448 ret
= make_fast_ap_fxarmor(context
, state
, realm
,
454 heim_abort("unknown state type: %d", (int)state
->type
);
462 _krb5_fast_wrap_req(krb5_context context
,
463 struct krb5_fast_state
*state
,
466 PA_FX_FAST_REQUEST fxreq
;
469 krb5_data data
, aschecksum_data
, tgschecksum_data
;
470 const krb5_data
*checksum_data
= NULL
;
472 krb5_boolean readd_padata_to_outer
= FALSE
;
474 if (state
->flags
& KRB5_FAST_DISABLED
) {
475 _krb5_debug(context
, 10, "fast disabled, not doing any fast wrapping");
479 memset(&fxreq
, 0, sizeof(fxreq
));
480 memset(&fastreq
, 0, sizeof(fastreq
));
481 krb5_data_zero(&data
);
482 krb5_data_zero(&aschecksum_data
);
483 krb5_data_zero(&tgschecksum_data
);
485 if (state
->armor_crypto
== NULL
)
486 return check_fast(context
, state
);
488 state
->flags
|= KRB5_FAST_EXPECTED
;
490 fastreq
.fast_options
.hide_client_names
= 1;
492 ret
= copy_KDC_REQ_BODY(&req
->req_body
, &fastreq
.req_body
);
497 * In the case of a AS-REQ, remove all account names. Want to this
498 * for TGS-REQ too, but due to layering this is tricky.
500 * 1. TGS-REQ need checksum of REQ-BODY
501 * 2. FAST needs checksum of TGS-REQ, so, FAST needs to happen after TGS-REQ
502 * 3. FAST privacy mangaling needs to happen before TGS-REQ does the checksum in 1.
504 * So lets not modify the bits for now for TGS-REQ
506 if (state
->flags
& KRB5_FAST_AS_REQ
) {
507 free_KDC_REQ_BODY(&req
->req_body
);
509 req
->req_body
.realm
= strdup(KRB5_ANON_REALM
);
510 if (req
->req_body
.realm
== NULL
) {
511 ret
= krb5_enomem(context
);
515 ret
= set_anon_principal(context
, &req
->req_body
.cname
);
519 ALLOC(req
->req_body
.till
, 1);
520 *req
->req_body
.till
= 0;
522 ASN1_MALLOC_ENCODE(KDC_REQ_BODY
,
523 aschecksum_data
.data
,
524 aschecksum_data
.length
,
529 heim_assert(aschecksum_data
.length
== size
, "ASN.1 internal error");
531 checksum_data
= &aschecksum_data
;
534 ret
= copy_METHOD_DATA(req
->padata
, &fastreq
.padata
);
535 free_METHOD_DATA(req
->padata
);
540 const PA_DATA
*tgs_req_ptr
= NULL
;
544 heim_assert(req
->padata
!= NULL
, "req->padata is NULL");
546 tgs_req_ptr
= krb5_find_padata(req
->padata
->val
,
550 heim_assert(tgs_req_ptr
!= NULL
, "KRB5_PADATA_TGS_REQ not found");
551 heim_assert(tgs_req_idx
== 0, "KRB5_PADATA_TGS_REQ not first");
553 tgschecksum_data
.data
= tgs_req_ptr
->padata_value
.data
;
554 tgschecksum_data
.length
= tgs_req_ptr
->padata_value
.length
;
555 checksum_data
= &tgschecksum_data
;
558 * Now copy all remaining once to
559 * the fastreq.padata and clear
560 * them in the outer req first,
561 * and remember to readd them later.
563 readd_padata_to_outer
= TRUE
;
565 for (i
= 1; i
< req
->padata
->len
; i
++) {
566 PA_DATA
*val
= &req
->padata
->val
[i
];
568 ret
= krb5_padata_add(context
,
571 val
->padata_value
.data
,
572 val
->padata_value
.length
);
574 krb5_set_error_message(context
, ret
,
575 N_("malloc: out of memory", ""));
578 val
->padata_value
.data
= NULL
;
579 val
->padata_value
.length
= 0;
583 * Only TGS-REQ remaining
585 req
->padata
->len
= 1;
588 if (req
->padata
== NULL
) {
589 ALLOC(req
->padata
, 1);
590 if (req
->padata
== NULL
) {
591 ret
= krb5_enomem(context
);
596 ASN1_MALLOC_ENCODE(KrbFastReq
, data
.data
, data
.length
, &fastreq
, &size
, ret
);
599 heim_assert(data
.length
== size
, "ASN.1 internal error");
601 fxreq
.element
= state
->type
;
603 if (state
->type
== choice_PA_FX_FAST_REQUEST_armored_data
) {
604 fxreq
.u
.armored_data
.armor
= state
->armor_data
;
605 state
->armor_data
= NULL
;
607 heim_assert(state
->armor_crypto
!= NULL
,
608 "FAST armor key missing when FAST started");
610 ret
= krb5_create_checksum(context
, state
->armor_crypto
,
611 KRB5_KU_FAST_REQ_CHKSUM
, 0,
613 checksum_data
->length
,
614 &fxreq
.u
.armored_data
.req_checksum
);
618 ret
= krb5_encrypt_EncryptedData(context
, state
->armor_crypto
,
623 &fxreq
.u
.armored_data
.enc_fast_req
);
624 krb5_data_free(&data
);
629 krb5_data_free(&data
);
630 heim_assert(false, "unknown FAST type, internal error");
633 ASN1_MALLOC_ENCODE(PA_FX_FAST_REQUEST
, data
.data
, data
.length
, &fxreq
, &size
, ret
);
636 heim_assert(data
.length
== size
, "ASN.1 internal error");
639 ret
= krb5_padata_add(context
, req
->padata
, KRB5_PADATA_FX_FAST
, data
.data
, data
.length
);
642 krb5_data_zero(&data
);
644 if (readd_padata_to_outer
) {
647 for (i
= 0; i
< fastreq
.padata
.len
; i
++) {
648 PA_DATA
*val
= &fastreq
.padata
.val
[i
];
650 ret
= krb5_padata_add(context
,
653 val
->padata_value
.data
,
654 val
->padata_value
.length
);
656 krb5_set_error_message(context
, ret
,
657 N_("malloc: out of memory", ""));
660 val
->padata_value
.data
= NULL
;
661 val
->padata_value
.length
= 0;
666 free_KrbFastReq(&fastreq
);
667 free_PA_FX_FAST_REQUEST(&fxreq
);
668 krb5_data_free(&data
);
669 krb5_data_free(&aschecksum_data
);
675 _krb5_fast_unwrap_error(krb5_context context
,
677 struct krb5_fast_state
*state
,
681 KrbFastResponse fastrep
;
686 if (state
->armor_crypto
== NULL
)
687 return check_fast(context
, state
);
689 memset(&fastrep
, 0, sizeof(fastrep
));
691 if (error
->error_code
!= KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED
)
692 _krb5_debug(context
, 10, "using FAST without FAST outer error code");
695 pa
= krb5_find_padata(md
->val
, md
->len
, KRB5_PADATA_FX_FAST
, &idx
);
698 * Typically _krb5_fast_wrap_req() has set KRB5_FAST_EXPECTED, which
699 * means check_fast() will complain and return KRB5KRB_AP_ERR_MODIFIED.
701 * But for TGS-REP init_tgs_req() clears KRB5_FAST_EXPECTED and we'll
702 * ignore a missing KRB5_PADATA_FX_FAST.
704 return check_fast(context
, state
);
707 ret
= unwrap_fast_rep(context
, state
, pa
, &fastrep
);
711 if (fastrep
.strengthen_key
|| nonce
!= (int32_t)fastrep
.nonce
) {
712 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
717 pa
= krb5_find_padata(fastrep
.padata
.val
, fastrep
.padata
.len
, KRB5_PADATA_FX_ERROR
, &idx
);
719 ret
= KRB5_KDCREP_MODIFIED
;
720 krb5_set_error_message(context
, ret
, N_("No wrapped error", ""));
724 free_KRB_ERROR(error
);
726 ret
= krb5_rd_error(context
, &pa
->padata_value
, error
);
731 _krb5_debug(context
, 10, "FAST wrapped KBB_ERROR contained e_data: %d",
732 (int)error
->e_data
->length
);
734 free_METHOD_DATA(md
);
735 md
->val
= fastrep
.padata
.val
;
736 md
->len
= fastrep
.padata
.len
;
738 fastrep
.padata
.val
= NULL
;
739 fastrep
.padata
.len
= 0;
742 free_KrbFastResponse(&fastrep
);
747 _krb5_fast_unwrap_kdc_rep(krb5_context context
, int32_t nonce
,
748 krb5_data
*chksumdata
,
749 struct krb5_fast_state
*state
, AS_REP
*rep
)
751 KrbFastResponse fastrep
;
756 if (state
== NULL
|| state
->armor_crypto
== NULL
|| rep
->padata
== NULL
)
757 return check_fast(context
, state
);
759 /* find PA_FX_FAST_REPLY */
761 pa
= krb5_find_padata(rep
->padata
->val
, rep
->padata
->len
,
762 KRB5_PADATA_FX_FAST
, &idx
);
764 return check_fast(context
, state
);
766 memset(&fastrep
, 0, sizeof(fastrep
));
768 ret
= unwrap_fast_rep(context
, state
, pa
, &fastrep
);
772 free_METHOD_DATA(rep
->padata
);
773 ret
= copy_METHOD_DATA(&fastrep
.padata
, rep
->padata
);
777 if (fastrep
.strengthen_key
) {
778 if (state
->strengthen_key
)
779 krb5_free_keyblock(context
, state
->strengthen_key
);
781 ret
= krb5_copy_keyblock(context
, fastrep
.strengthen_key
, &state
->strengthen_key
);
786 if (nonce
!= (int32_t)fastrep
.nonce
) {
787 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
790 if (fastrep
.finished
) {
792 krb5_realm crealm
= NULL
;
794 if (chksumdata
== NULL
) {
795 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
799 ret
= krb5_verify_checksum(context
, state
->armor_crypto
,
800 KRB5_KU_FAST_FINISHED
,
801 chksumdata
->data
, chksumdata
->length
,
802 &fastrep
.finished
->ticket_checksum
);
807 ret
= copy_Realm(&fastrep
.finished
->crealm
, &crealm
);
810 free_Realm(&rep
->crealm
);
811 rep
->crealm
= crealm
;
813 ret
= copy_PrincipalName(&fastrep
.finished
->cname
, &cname
);
816 free_PrincipalName(&rep
->cname
);
818 } else if (chksumdata
) {
819 /* expected fastrep.finish but didn't get it */
820 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
824 free_KrbFastResponse(&fastrep
);
829 _krb5_fast_free(krb5_context context
, struct krb5_fast_state
*state
)
831 if (state
->armor_ccache
) {
832 if (state
->flags
& KRB5_FAST_ANON_PKINIT_ARMOR
)
833 krb5_cc_destroy(context
, state
->armor_ccache
);
835 krb5_cc_close(context
, state
->armor_ccache
);
837 if (state
->armor_service
)
838 krb5_free_principal(context
, state
->armor_service
);
839 if (state
->armor_crypto
)
840 krb5_crypto_destroy(context
, state
->armor_crypto
);
841 if (state
->strengthen_key
)
842 krb5_free_keyblock(context
, state
->strengthen_key
);
843 krb5_free_keyblock_contents(context
, &state
->armor_key
);
844 if (state
->armor_data
) {
845 free_KrbFastArmor(state
->armor_data
);
846 free(state
->armor_data
);
849 if (state
->anon_pkinit_ctx
)
850 krb5_init_creds_free(context
, state
->anon_pkinit_ctx
);
851 if (state
->anon_pkinit_opt
)
852 krb5_get_init_creds_opt_free(context
, state
->anon_pkinit_opt
);
854 memset(state
, 0, sizeof(*state
));
858 _krb5_fast_anon_pkinit_step(krb5_context context
,
859 krb5_init_creds_context ctx
,
860 struct krb5_fast_state
*state
,
863 krb5_realm
*out_realm
,
867 krb5_const_realm realm
= _krb5_init_creds_get_cred_client(context
, ctx
)->realm
;
868 krb5_init_creds_context anon_pk_ctx
;
869 krb5_principal principal
= NULL
, anon_pk_client
;
870 krb5_ccache ccache
= NULL
;
872 krb5_data data
= { 3, rk_UNCONST("yes") };
877 memset(&cred
, 0, sizeof(cred
));
879 if (state
->anon_pkinit_opt
== NULL
) {
880 ret
= krb5_get_init_creds_opt_alloc(context
, &state
->anon_pkinit_opt
);
884 krb5_get_init_creds_opt_set_tkt_life(state
->anon_pkinit_opt
, 60);
885 krb5_get_init_creds_opt_set_anonymous(state
->anon_pkinit_opt
, TRUE
);
887 ret
= krb5_make_principal(context
, &principal
, realm
,
888 KRB5_WELLKNOWN_NAME
, KRB5_ANON_NAME
, NULL
);
892 ret
= krb5_get_init_creds_opt_set_pkinit(context
,
893 state
->anon_pkinit_opt
,
895 NULL
, NULL
, NULL
, NULL
,
896 KRB5_GIC_OPT_PKINIT_ANONYMOUS
|
897 KRB5_GIC_OPT_PKINIT_NO_KDC_ANCHOR
,
902 ret
= krb5_init_creds_init(context
, principal
, NULL
, NULL
,
903 _krb5_init_creds_get_cred_starttime(context
, ctx
),
904 state
->anon_pkinit_opt
,
905 &state
->anon_pkinit_ctx
);
910 anon_pk_ctx
= state
->anon_pkinit_ctx
;
912 ret
= krb5_init_creds_step(context
, anon_pk_ctx
, in
, out
, out_realm
, flags
);
914 (*flags
& KRB5_INIT_CREDS_STEP_FLAG_CONTINUE
))
917 ret
= krb5_process_last_request(context
, state
->anon_pkinit_opt
, anon_pk_ctx
);
921 ret
= krb5_cc_new_unique(context
, "MEMORY", NULL
, &ccache
);
925 ret
= krb5_init_creds_get_creds(context
, anon_pk_ctx
, &cred
);
929 if (!cred
.flags
.b
.enc_pa_rep
) {
930 ret
= KRB5KDC_ERR_BADOPTION
; /* KDC does not support FAST */
934 anon_pk_client
= _krb5_init_creds_get_cred_client(context
, anon_pk_ctx
);
936 ret
= krb5_cc_initialize(context
, ccache
, anon_pk_client
);
940 ret
= krb5_cc_store_cred(context
, ccache
, &cred
);
944 ret
= krb5_cc_set_config(context
, ccache
, cred
.server
,
945 "fast_avail", &data
);
946 if (ret
&& ret
!= KRB5_CC_NOSUPP
)
949 if (_krb5_pk_is_kdc_verified(context
, state
->anon_pkinit_opt
))
950 state
->flags
|= KRB5_FAST_KDC_VERIFIED
;
952 state
->flags
&= ~(KRB5_FAST_KDC_VERIFIED
);
954 state
->armor_ccache
= ccache
;
957 krb5_init_creds_free(context
, state
->anon_pkinit_ctx
);
958 state
->anon_pkinit_ctx
= NULL
;
960 krb5_get_init_creds_opt_free(context
, state
->anon_pkinit_opt
);
961 state
->anon_pkinit_opt
= NULL
;
964 krb5_free_principal(context
, principal
);
965 krb5_free_cred_contents(context
, &cred
);
967 krb5_cc_destroy(context
, ccache
);