2 * Copyright (c) 1997-2011 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2010 - 2011 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 static krb5_error_code
39 salt_fastuser_crypto(astgs_request_t r
,
40 krb5_const_principal salt_principal
,
42 krb5_crypto fast_crypto
,
43 krb5_crypto
*salted_crypto
)
46 krb5_principal client_princ
= NULL
;
51 *salted_crypto
= NULL
;
53 krb5_data_zero(&salt
);
54 krb5_keyblock_zero(&dkey
);
56 if (salt_principal
== NULL
) {
57 if (r
->req
.req_body
.cname
== NULL
) {
58 ret
= KRB5KRB_ERR_GENERIC
;
62 ret
= _krb5_principalname2krb5_principal(r
->context
, &client_princ
,
63 *(r
->req
.req_body
.cname
),
64 r
->req
.req_body
.realm
);
68 salt_principal
= client_princ
;
71 ret
= krb5_unparse_name(r
->context
, salt_principal
, (char **)&salt
.data
);
75 salt
.length
= strlen(salt
.data
);
77 kdc_log(r
->context
, r
->config
, 10,
78 "salt_fastuser_crypto: salt principal is %s (%d)",
79 (char *)salt
.data
, enctype
);
81 ret
= krb5_enctype_keysize(r
->context
, enctype
, &size
);
85 ret
= krb5_crypto_prfplus(r
->context
, fast_crypto
, &salt
,
86 size
, &dkey
.keyvalue
);
90 dkey
.keytype
= enctype
;
92 ret
= krb5_crypto_init(r
->context
, &dkey
, ENCTYPE_NULL
, salted_crypto
);
97 krb5_free_keyblock_contents(r
->context
, &dkey
);
98 krb5_data_free(&salt
);
99 krb5_free_principal(r
->context
, client_princ
);
104 static krb5_error_code
105 get_fastuser_crypto(astgs_request_t r
,
106 krb5_const_principal ticket_client
,
107 krb5_enctype enctype
,
110 krb5_principal fast_princ
;
112 hdb_entry
*fast_user
= NULL
;
113 Key
*cookie_key
= NULL
;
114 krb5_crypto fast_crypto
= NULL
;
119 ret
= krb5_make_principal(r
->context
, &fast_princ
,
120 KRB5_WELLKNOWN_ORG_H5L_REALM
,
121 KRB5_WELLKNOWN_NAME
, "org.h5l.fast-cookie", NULL
);
125 ret
= _kdc_db_fetch(r
->context
, r
->config
, fast_princ
,
126 HDB_F_GET_FAST_COOKIE
, NULL
, &fast_db
, &fast_user
);
130 if (enctype
== KRB5_ENCTYPE_NULL
)
131 ret
= _kdc_get_preferred_key(r
->context
, r
->config
, fast_user
,
132 "fast-cookie", &enctype
, &cookie_key
);
134 ret
= hdb_enctype2key(r
->context
, fast_user
, NULL
,
135 enctype
, &cookie_key
);
139 ret
= krb5_crypto_init(r
->context
, &cookie_key
->key
,
140 ENCTYPE_NULL
, &fast_crypto
);
144 ret
= salt_fastuser_crypto(r
, ticket_client
,
145 cookie_key
->key
.keytype
,
146 fast_crypto
, crypto
);
152 _kdc_free_ent(r
->context
, fast_db
, fast_user
);
154 krb5_crypto_destroy(r
->context
, fast_crypto
);
155 krb5_free_principal(r
->context
, fast_princ
);
161 static krb5_error_code
162 fast_parse_cookie(astgs_request_t r
,
163 krb5_const_principal ticket_client
,
166 krb5_crypto crypto
= NULL
;
172 ret
= decode_KDCFastCookie(pa
->padata_value
.data
,
173 pa
->padata_value
.length
,
178 if (len
!= pa
->padata_value
.length
|| strcmp("H5L1", data
.version
) != 0) {
179 free_KDCFastCookie(&data
);
180 return KRB5KDC_ERR_POLICY
;
183 ret
= get_fastuser_crypto(r
, ticket_client
, data
.cookie
.etype
, &crypto
);
187 ret
= krb5_decrypt_EncryptedData(r
->context
, crypto
,
190 krb5_crypto_destroy(r
->context
, crypto
);
194 ret
= decode_KDCFastState(d1
.data
, d1
.length
, &r
->fast
, &len
);
199 if (r
->fast
.expiration
< kdc_time
) {
200 kdc_log(r
->context
, r
->config
, 2, "FAST cookie expired");
201 ret
= KRB5KDC_ERR_POLICY
;
206 free_KDCFastCookie(&data
);
211 static krb5_error_code
212 fast_add_cookie(astgs_request_t r
,
213 krb5_const_principal ticket_client
,
214 METHOD_DATA
*method_data
)
216 krb5_crypto crypto
= NULL
;
222 memset(&shell
, 0, sizeof(shell
));
224 r
->fast
.expiration
= kdc_time
+ FAST_EXPIRATION_TIME
;
226 ASN1_MALLOC_ENCODE(KDCFastState
, data
.data
, data
.length
,
227 &r
->fast
, &size
, ret
);
230 heim_assert(size
== data
.length
, "internal asn.1 encoder error");
232 ret
= get_fastuser_crypto(r
, ticket_client
, KRB5_ENCTYPE_NULL
, &crypto
);
234 kdc_log(r
->context
, r
->config
, 0,
235 "Failed to find FAST principal for cookie encryption: %d", ret
);
239 ret
= krb5_encrypt_EncryptedData(r
->context
, crypto
,
241 data
.data
, data
.length
, 0,
243 krb5_crypto_destroy(r
->context
, crypto
);
247 krb5_data_free(&data
);
249 shell
.version
= "H5L1";
251 ASN1_MALLOC_ENCODE(KDCFastCookie
, data
.data
, data
.length
,
253 free_EncryptedData(&shell
.cookie
);
256 heim_assert(size
== data
.length
, "internal asn.1 encoder error");
258 ret
= krb5_padata_add(r
->context
, method_data
,
259 KRB5_PADATA_FX_COOKIE
,
260 data
.data
, data
.length
);
262 krb5_data_zero(&data
);
265 krb5_data_free(&data
);
269 static krb5_error_code
270 fast_add_dummy_cookie(astgs_request_t r
,
271 METHOD_DATA
*method_data
)
275 const krb5_data
*dummy_fast_cookie
= &r
->config
->dummy_fast_cookie
;
277 if (dummy_fast_cookie
->data
== NULL
)
280 ret
= krb5_data_copy(&data
,
281 dummy_fast_cookie
->data
,
282 dummy_fast_cookie
->length
);
286 ret
= krb5_padata_add(r
->context
, method_data
,
287 KRB5_PADATA_FX_COOKIE
,
288 data
.data
, data
.length
);
290 krb5_data_free(&data
);
297 _kdc_fast_mk_response(krb5_context context
,
298 krb5_crypto armor_crypto
,
299 METHOD_DATA
*pa_data
,
300 krb5_keyblock
*strengthen_key
,
301 KrbFastFinished
*finished
,
305 PA_FX_FAST_REPLY fxfastrep
;
306 KrbFastResponse fastrep
;
311 memset(&fxfastrep
, 0, sizeof(fxfastrep
));
312 memset(&fastrep
, 0, sizeof(fastrep
));
313 krb5_data_zero(data
);
316 fastrep
.padata
.val
= pa_data
->val
;
317 fastrep
.padata
.len
= pa_data
->len
;
319 fastrep
.strengthen_key
= strengthen_key
;
320 fastrep
.finished
= finished
;
321 fastrep
.nonce
= nonce
;
323 ASN1_MALLOC_ENCODE(KrbFastResponse
, buf
.data
, buf
.length
,
324 &fastrep
, &size
, ret
);
327 heim_assert(size
== buf
.length
, "internal asn.1 encoder error");
329 fxfastrep
.element
= choice_PA_FX_FAST_REPLY_armored_data
;
331 ret
= krb5_encrypt_EncryptedData(context
,
337 &fxfastrep
.u
.armored_data
.enc_fast_rep
);
338 krb5_data_free(&buf
);
342 ASN1_MALLOC_ENCODE(PA_FX_FAST_REPLY
, data
->data
, data
->length
,
343 &fxfastrep
, &size
, ret
);
344 free_PA_FX_FAST_REPLY(&fxfastrep
);
347 heim_assert(size
== data
->length
, "internal asn.1 encoder error");
353 static krb5_error_code
354 _kdc_fast_mk_e_data(astgs_request_t r
,
355 METHOD_DATA
*error_method
,
356 krb5_crypto armor_crypto
,
357 const KDC_REQ_BODY
*req_body
,
358 krb5_error_code outer_error
,
359 krb5_principal error_client
,
360 krb5_principal error_server
,
361 time_t *csec
, int *cusec
,
364 krb5_error_code ret
= 0;
368 * FX-COOKIE can be used outside of FAST, e.g. SRP or GSS.
370 if (armor_crypto
|| r
->fast
.fast_state
.len
) {
371 if (r
->config
->enable_fast_cookie
) {
372 kdc_log(r
->context
, r
->config
, 5, "Adding FAST cookie for KRB-ERROR");
373 ret
= fast_add_cookie(r
, error_client
, error_method
);
375 kdc_log(r
->context
, r
->config
, 1,
376 "Failed to add FAST cookie: %d", ret
);
377 free_METHOD_DATA(error_method
);
381 kdc_log(r
->context
, r
->config
, 5, "Adding dummy FAST cookie for KRB-ERROR");
382 ret
= fast_add_dummy_cookie(r
, error_method
);
384 kdc_log(r
->context
, r
->config
, 1,
385 "Failed to add dummy FAST cookie: %d", ret
);
386 free_METHOD_DATA(error_method
);
393 PA_FX_FAST_REPLY fxfastrep
;
394 KrbFastResponse fastrep
;
396 memset(&fxfastrep
, 0, sizeof(fxfastrep
));
397 memset(&fastrep
, 0, sizeof(fastrep
));
399 kdc_log(r
->context
, r
->config
, 5, "Making FAST inner KRB-ERROR");
401 /* first add the KRB-ERROR to the fast errors */
403 ret
= krb5_mk_error(r
->context
,
413 kdc_log(r
->context
, r
->config
, 1,
414 "Failed to make inner KRB-ERROR: %d", ret
);
418 ret
= krb5_padata_add(r
->context
, error_method
,
419 KRB5_PADATA_FX_ERROR
,
420 e_data
->data
, e_data
->length
);
422 kdc_log(r
->context
, r
->config
, 1,
423 "Failed to make add FAST PADATA to inner KRB-ERROR: %d", ret
);
424 krb5_data_free(e_data
);
430 ret
= _kdc_fast_mk_response(r
->context
, armor_crypto
,
431 error_method
, NULL
, NULL
,
432 req_body
->nonce
, e_data
);
433 free_METHOD_DATA(error_method
);
435 kdc_log(r
->context
, r
->config
, 1,
436 "Failed to make outer KRB-ERROR: %d", ret
);
440 ret
= krb5_padata_add(r
->context
, error_method
,
442 e_data
->data
, e_data
->length
);
444 kdc_log(r
->context
, r
->config
, 1,
445 "Failed to make add FAST PADATA to outer KRB-ERROR: %d", ret
);
449 kdc_log(r
->context
, r
->config
, 5, "Making non-FAST KRB-ERROR");
451 if (error_method
&& error_method
->len
) {
452 ASN1_MALLOC_ENCODE(METHOD_DATA
, e_data
->data
, e_data
->length
,
453 error_method
, &size
, ret
);
455 kdc_log(r
->context
, r
->config
, 1,
456 "Failed to make encode METHOD-DATA: %d", ret
);
459 heim_assert(size
== e_data
->length
, "internal asn.1 encoder error");
467 _kdc_fast_mk_error(astgs_request_t r
,
468 METHOD_DATA
*error_method
,
469 krb5_crypto armor_crypto
,
470 const KDC_REQ_BODY
*req_body
,
471 krb5_error_code outer_error
,
472 krb5_principal error_client
,
473 krb5_principal error_server
,
474 time_t *csec
, int *cusec
,
475 krb5_data
*error_msg
)
479 krb5_data
*e_data
= NULL
;
481 krb5_data_zero(&_e_data
);
483 heim_assert(r
!= NULL
, "invalid request in _kdc_fast_mk_error");
485 if (!armor_crypto
&& r
->e_data
.length
) {
487 * If we’re not armoring the response with FAST, r->e_data
488 * takes precedence over the e‐data that would normally be
489 * generated. r->e_data typically contains a
490 * Microsoft‐specific NTSTATUS code.
492 * But if FAST is in use, Windows Server suppresses the
493 * NTSTATUS code in favour of an armored response
494 * encapsulating an ordinary KRB‐ERROR. So we ignore r->e_data
499 ret
= _kdc_fast_mk_e_data(r
,
509 kdc_log(r
->context
, r
->config
, 1,
510 "Failed to make FAST e-data: %d", ret
);
518 if (r
->fast
.flags
.requested_hidden_names
) {
526 ret
= krb5_mk_error(r
->context
,
529 (e_data
->length
? e_data
: NULL
),
535 krb5_data_free(&_e_data
);
538 kdc_log(r
->context
, r
->config
, 1,
539 "Failed to make encode KRB-ERROR: %d", ret
);
544 static krb5_error_code
545 fast_unwrap_request(astgs_request_t r
,
546 krb5_ticket
*tgs_ticket
,
547 krb5_auth_context tgs_ac
)
549 krb5_principal armor_server_principal
= NULL
;
550 char *armor_client_principal_name
= NULL
;
551 char *armor_server_principal_name
= NULL
;
552 PA_FX_FAST_REQUEST fxreq
;
553 krb5_auth_context ac
= NULL
;
554 krb5_ticket
*ticket
= NULL
;
555 krb5_flags ap_req_options
;
556 krb5_keyblock armorkey
;
557 krb5_keyblock explicit_armorkey
;
566 memset(&fxreq
, 0, sizeof(fxreq
));
567 memset(&fastreq
, 0, sizeof(fastreq
));
569 pa
= _kdc_find_padata(&r
->req
, &i
, KRB5_PADATA_FX_FAST
);
571 if (tgs_ac
&& r
->fast_asserted
) {
572 kdc_log(r
->context
, r
->config
, 1,
573 "Client asserted FAST but did not include FX-FAST pa-data");
574 ret
= KRB5KRB_AP_ERR_MODIFIED
;
578 kdc_log(r
->context
, r
->config
, 10, "Not a FAST request");
582 ret
= decode_PA_FX_FAST_REQUEST(pa
->padata_value
.data
,
583 pa
->padata_value
.length
,
587 kdc_log(r
->context
, r
->config
, 4,
588 "Failed to decode PA-FX-FAST-REQUEST: %d", ret
);
592 if (fxreq
.element
!= choice_PA_FX_FAST_REQUEST_armored_data
) {
593 kdc_log(r
->context
, r
->config
, 4,
594 "PA-FX-FAST-REQUEST contains unknown type: %d",
596 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
601 * If check for armor data or it's not a TGS-REQ with implicit
604 if (fxreq
.u
.armored_data
.armor
== NULL
&& tgs_ac
== NULL
) {
605 kdc_log(r
->context
, r
->config
, 4,
606 "AS-REQ armor missing");
607 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
611 r
->explicit_armor_present
= fxreq
.u
.armored_data
.armor
!= NULL
&& tgs_ac
!= NULL
;
616 if (fxreq
.u
.armored_data
.armor
!= NULL
) {
618 krb5uint32
*kvno_ptr
= NULL
;
620 if (fxreq
.u
.armored_data
.armor
->armor_type
!= 1) {
621 kdc_log(r
->context
, r
->config
, 4,
622 "Incorrect AS-REQ armor type");
623 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
627 ret
= krb5_decode_ap_req(r
->context
,
628 &fxreq
.u
.armored_data
.armor
->armor_value
,
631 kdc_log(r
->context
, r
->config
, 4, "Failed to decode AP-REQ");
635 /* Save that principal that was in the request */
636 ret
= _krb5_principalname2krb5_principal(r
->context
,
637 &armor_server_principal
,
639 ap_req
.ticket
.realm
);
641 free_AP_REQ(&ap_req
);
645 if (ap_req
.ticket
.enc_part
.kvno
!= NULL
) {
646 kvno
= *ap_req
.ticket
.enc_part
.kvno
;
650 ret
= _kdc_db_fetch(r
->context
, r
->config
, armor_server_principal
,
651 HDB_F_GET_KRBTGT
| HDB_F_DELAY_NEW_KEYS
,
653 &r
->armor_serverdb
, &r
->armor_server
);
654 if(ret
== HDB_ERR_NOT_FOUND_HERE
) {
655 free_AP_REQ(&ap_req
);
656 kdc_log(r
->context
, r
->config
, 5,
657 "Armor key does not have secrets at this KDC, "
661 free_AP_REQ(&ap_req
);
662 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
666 ret
= hdb_enctype2key(r
->context
, r
->armor_server
, NULL
,
667 ap_req
.ticket
.enc_part
.etype
,
670 free_AP_REQ(&ap_req
);
674 ret
= krb5_verify_ap_req2(r
->context
, &ac
,
676 armor_server_principal
,
681 KRB5_KU_AP_REQ_AUTH
);
682 free_AP_REQ(&ap_req
);
686 ret
= krb5_unparse_name(r
->context
, armor_server_principal
,
687 &armor_server_principal_name
);
691 /* FIXME krb5_verify_ap_req2() also checks this */
692 ret
= _kdc_verify_flags(r
->context
, r
->config
,
693 &r
->armor_ticket
->ticket
,
694 armor_server_principal_name
);
696 kdc_audit_addreason((kdc_request_t
)r
,
697 "Armor TGT expired or invalid");
700 ticket
= r
->armor_ticket
;
702 heim_assert(tgs_ticket
!= NULL
, "TGS authentication context without ticket");
707 (void) krb5_unparse_name(r
->context
, ticket
->client
, &armor_client_principal_name
);
708 kdc_audit_addkv((kdc_request_t
)r
, 0, "armor_client_name", "%s",
709 armor_client_principal_name
?
710 armor_client_principal_name
:
713 if (ac
->remote_subkey
== NULL
) {
714 krb5_auth_con_free(r
->context
, ac
);
715 kdc_log(r
->context
, r
->config
, 2,
716 "FAST AP-REQ remote subkey missing");
717 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
721 r
->fast
.flags
.kdc_verified
=
722 !_kdc_is_anonymous_pkinit(r
->context
, ticket
->client
);
724 ret
= _krb5_fast_armor_key(r
->context
,
728 r
->explicit_armor_present
? NULL
: &r
->armor_crypto
);
732 if (r
->explicit_armor_present
) {
733 ret
= _krb5_fast_explicit_armor_key(r
->context
,
735 tgs_ac
->remote_subkey
,
741 krb5_free_keyblock_contents(r
->context
, &explicit_armorkey
);
744 krb5_free_keyblock_contents(r
->context
, &armorkey
);
746 ret
= krb5_decrypt_EncryptedData(r
->context
, r
->armor_crypto
,
748 &fxreq
.u
.armored_data
.enc_fast_req
,
751 kdc_log(r
->context
, r
->config
, 2,
752 "Failed to decrypt FAST request");
756 ret
= decode_KrbFastReq(data
.data
, data
.length
, &fastreq
, NULL
);
757 krb5_data_free(&data
);
762 * verify req-checksum of the outer body
766 * -- For TGS, contains the checksum performed over the type
767 * -- AP-REQ in the PA-TGS-REQ padata.
770 pa
= _kdc_find_padata(&r
->req
, &i
, KRB5_PADATA_TGS_REQ
);
772 kdc_log(r
->context
, r
->config
, 4,
773 "FAST TGS request missing TGS-REQ padata");
774 ret
= KRB5KRB_ERR_GENERIC
;
778 ret
= _kdc_verify_checksum(r
->context
, r
->armor_crypto
,
779 KRB5_KU_FAST_REQ_CHKSUM
,
781 &fxreq
.u
.armored_data
.req_checksum
);
783 kdc_log(r
->context
, r
->config
, 2,
784 "Bad checksum in FAST TGS request");
789 * -- For AS, contains the checksum performed over the type
790 * -- KDC-REQ-BODY for the req-body field of the KDC-REQ
793 ret
= _kdc_verify_checksum(r
->context
, r
->armor_crypto
,
794 KRB5_KU_FAST_REQ_CHKSUM
,
795 &r
->req
.req_body
._save
,
796 &fxreq
.u
.armored_data
.req_checksum
);
798 kdc_log(r
->context
, r
->config
, 2,
799 "Bad checksum in FAST AS request");
805 * check for unsupported mandatory options
807 if (FastOptions2int(fastreq
.fast_options
) & 0xfffc) {
808 kdc_log(r
->context
, r
->config
, 2,
809 "FAST unsupported mandatory option set");
810 ret
= KRB5_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS
;
814 r
->fast
.flags
.requested_hidden_names
= fastreq
.fast_options
.hide_client_names
;
816 /* KDC MUST ignore outer pa data preauth-14 - 6.5.5 */
818 free_METHOD_DATA(r
->req
.padata
);
820 ALLOC(r
->req
.padata
);
822 ret
= copy_METHOD_DATA(&fastreq
.padata
, r
->req
.padata
);
826 free_KDC_REQ_BODY(&r
->req
.req_body
);
827 ret
= copy_KDC_REQ_BODY(&fastreq
.req_body
, &r
->req
.req_body
);
831 kdc_log(r
->context
, r
->config
, 5, "Client selected FAST");
834 if (ac
&& ac
!= tgs_ac
)
835 krb5_auth_con_free(r
->context
, ac
);
837 krb5_free_principal(r
->context
, armor_server_principal
);
838 krb5_xfree(armor_client_principal_name
);
839 krb5_xfree(armor_server_principal_name
);
841 free_KrbFastReq(&fastreq
);
842 free_PA_FX_FAST_REQUEST(&fxreq
);
851 _kdc_fast_unwrap_request(astgs_request_t r
,
852 krb5_ticket
*tgs_ticket
,
853 krb5_auth_context tgs_ac
)
859 if (!r
->config
->enable_fast
)
862 ret
= fast_unwrap_request(r
, tgs_ticket
, tgs_ac
);
866 if (r
->config
->enable_fast_cookie
) {
868 * FX-COOKIE can be used outside of FAST, e.g. SRP or GSS.
870 pa
= _kdc_find_padata(&r
->req
, &i
, KRB5_PADATA_FX_COOKIE
);
872 krb5_const_principal ticket_client
= NULL
;
875 ticket_client
= tgs_ticket
->client
;
877 ret
= fast_parse_cookie(r
, ticket_client
, pa
);
885 * Strengthen reply key by mixing with a random key that is
889 _kdc_fast_strengthen_reply_key(astgs_request_t r
)
891 if (r
->armor_crypto
) {
892 krb5_keyblock new_reply_key
;
895 kdc_log(r
->context
, r
->config
, 5,
896 "FAST strengthen reply key with strengthen-key");
898 heim_assert(r
->reply_key
.keytype
!= KRB5_ENCTYPE_NULL
, "NULL reply key enctype");
900 ret
= krb5_generate_random_keyblock(r
->context
, r
->reply_key
.keytype
,
903 kdc_log(r
->context
, r
->config
, 0, "failed to prepare random keyblock");
907 ret
= _krb5_fast_cf2(r
->context
,
908 &r
->strengthen_key
, "strengthenkey",
909 &r
->reply_key
, "replykey",
910 &new_reply_key
, NULL
);
914 krb5_free_keyblock_contents(r
->context
, &r
->reply_key
);
915 r
->reply_key
= new_reply_key
;
922 * Zero and free KDCFastState
925 _kdc_free_fast_state(KDCFastState
*state
)
929 for (i
= 0; i
< state
->fast_state
.len
; i
++) {
930 PA_DATA
*pa
= &state
->fast_state
.val
[i
];
932 if (pa
->padata_value
.data
)
933 memset_s(pa
->padata_value
.data
, 0,
934 pa
->padata_value
.length
, pa
->padata_value
.length
);
936 free_KDCFastState(state
);
940 _kdc_fast_check_armor_pac(astgs_request_t r
, int flags
)
943 krb5_boolean ad_kdc_issued
= FALSE
;
944 krb5_pac mspac
= NULL
;
945 krb5_principal armor_client_principal
= NULL
;
947 hdb_entry
*armor_client
= NULL
;
948 char *armor_client_principal_name
= NULL
;
950 flags
|= HDB_F_ARMOR_PRINCIPAL
;
951 if (_kdc_synthetic_princ_used_p(r
->context
, r
->armor_ticket
))
952 flags
|= HDB_F_SYNTHETIC_OK
;
953 if (r
->req
.req_body
.kdc_options
.canonicalize
)
954 flags
|= HDB_F_CANON
;
956 ret
= _krb5_principalname2krb5_principal(r
->context
,
957 &armor_client_principal
,
958 r
->armor_ticket
->ticket
.cname
,
959 r
->armor_ticket
->ticket
.crealm
);
963 ret
= krb5_unparse_name(r
->context
, armor_client_principal
,
964 &armor_client_principal_name
);
968 ret
= _kdc_db_fetch_client(r
->context
, r
->config
, flags
,
969 armor_client_principal
, armor_client_principal_name
,
970 r
->req
.req_body
.realm
, &armor_db
, &armor_client
);
974 ret
= kdc_check_flags(r
, FALSE
, armor_client
, NULL
);
978 ret
= _kdc_check_pac(r
, armor_client_principal
, NULL
,
979 armor_client
, r
->armor_server
,
980 r
->armor_server
, r
->armor_server
,
981 &r
->armor_key
->key
, &r
->armor_key
->key
,
982 &r
->armor_ticket
->ticket
, &ad_kdc_issued
, &mspac
, NULL
, NULL
);
984 const char *msg
= krb5_get_error_message(r
->context
, ret
);
986 kdc_log(r
->context
, r
->config
, 4,
987 "Verify armor PAC (%s) failed for %s (%s) from %s with %s (%s)",
988 armor_client_principal_name
, r
->cname
, r
->sname
,
989 r
->from
, msg
, mspac
? "Ticket unsigned" : "No PAC");
991 krb5_free_error_message(r
->context
, msg
);
996 r
->armor_clientdb
= armor_db
;
999 r
->armor_client
= armor_client
;
1000 armor_client
= NULL
;
1002 r
->armor_pac
= mspac
;
1006 krb5_xfree(armor_client_principal_name
);
1008 _kdc_free_ent(r
->context
, armor_db
, armor_client
);
1009 krb5_free_principal(r
->context
, armor_client_principal
);
1010 krb5_pac_free(r
->context
, mspac
);