From: Joseph Sutton Date: Mon, 21 Jun 2021 02:14:48 +0000 (+1200) Subject: s4:torture/krb5/kdc-heimdal: Automatically determine AS-REP enctype to check against X-Git-Tag: tevent-0.11.0~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf71fa038e9b97f770e06e88226e885d67342d47;p=thirdparty%2Fsamba.git s4:torture/krb5/kdc-heimdal: Automatically determine AS-REP enctype to check against This enables us to more easily switch to a different algorithm to find the strongest key in _kdc_find_etype(). Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher --- diff --git a/selftest/knownfail b/selftest/knownfail index bd3a05c6d8e..b2c09e73393 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -291,10 +291,6 @@ ^samba4.winbind.struct.lookup_name_sid\(ad_member:local\) ^samba4.winbind.struct.getdcname\(nt4_member:local\) # Works in other modes, just not against the classic/NT4 DC # -# Differences in our KDC compared to windows -# -^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally -# # This will fail against the classic DC, because it requires kerberos # ^samba4.winbind.pac.*\(nt4_member:local\) # No KDC on a classic DC @@ -333,7 +329,7 @@ # ^samba4.smb.signing.*disabled.*client-protection=off.*\(ad_dc\) # fl2000dc doesn't support AES -^samba4.krb5.kdc.*as-req-aes.*fl2000dc +^samba4.krb5.kdc.*as-req-aes.fl2000dc # nt4_member and ad_member don't support ntlmv1 (not even over SMB1) ^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.member.creds.*as.user.*_member ^samba3.blackbox.smbclient_auth.plain.*option=clientntlmv2auth=no.*mNT1.member.creds.*as.user.*_member diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index db40b0614fa..fffa5c3cd7e 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -641,3 +641,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_None.fl2008r2dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2003dc ^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_as_req_no_preauth_rc4_pac_True.fl2008r2dc +# Differences in our KDC compared to windows +# +^samba4.krb5.kdc .*.as-req-pac-request # We should reply to a request for a PAC over UDP with KRB5KRB_ERR_RESPONSE_TOO_BIG unconditionally +# +# fl2000dc doesn't support AES +^samba4.krb5.kdc.*as-req-aes.*fl2000dc diff --git a/source4/torture/krb5/kdc-heimdal.c b/source4/torture/krb5/kdc-heimdal.c index 86b5ec3d72f..acb814b6041 100644 --- a/source4/torture/krb5/kdc-heimdal.c +++ b/source4/torture/krb5/kdc-heimdal.c @@ -204,11 +204,12 @@ static bool torture_check_krb5_error(struct torture_krb5_context *test_context, static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_context, const krb5_data *reply, - krb5_enctype expected_enctype) + const krb5_enctype* allowed_enctypes) { ENCTYPE reply_enctype = { 0 }; size_t used = 0; int rc; + int expected_enctype = ETYPE_NULL; rc = decode_AS_REP(reply->data, reply->length, @@ -230,8 +231,84 @@ static bool torture_check_krb5_as_rep_enctype(struct torture_krb5_context *test_ test_context->as_rep.ticket.enc_part.kvno, "Did not get a KVNO in test_context->as_rep.ticket.enc_part.kvno"); - reply_enctype = test_context->as_rep.enc_part.etype; + if (test_context->as_req.padata) { + /* + * If the AS-REQ contains a PA-ENC-TIMESTAMP, then + * that encryption type is used to determine the reply + * enctype. + */ + int i = 0; + const PA_DATA *pa = krb5_find_padata(test_context->as_req.padata->val, + test_context->as_req.padata->len, + KRB5_PADATA_ENC_TIMESTAMP, + &i); + if (pa) { + EncryptedData ed; + size_t len; + krb5_error_code ret = decode_EncryptedData(pa->padata_value.data, + pa->padata_value.length, + &ed, &len); + torture_assert_int_equal(test_context->tctx, + ret, + 0, + "decode_EncryptedData failed"); + expected_enctype = ed.etype; + free_EncryptedData(&ed); + } + } + if (expected_enctype == ETYPE_NULL) { + /* + * Otherwise, find the strongest enctype contained in + * the AS-REQ supported enctypes list. + */ + const krb5_enctype *p = NULL; + + for (p = krb5_kerberos_enctypes(NULL); *p != (krb5_enctype)ETYPE_NULL; ++p) { + int j; + + if ((*p == (krb5_enctype)ETYPE_AES256_CTS_HMAC_SHA1_96 || + *p == (krb5_enctype)ETYPE_AES128_CTS_HMAC_SHA1_96) && + !test_context->as_req.req_body.kdc_options.canonicalize) + { + /* + * AES encryption types are only used here when + * we set the canonicalize flag, as the salt + * needs to match. + */ + continue; + } + + for (j = 0; j < test_context->as_req.req_body.etype.len; ++j) { + krb5_enctype etype = test_context->as_req.req_body.etype.val[j]; + if (*p == etype) { + expected_enctype = etype; + break; + } + } + + if (expected_enctype != (krb5_enctype)ETYPE_NULL) { + break; + } + } + } + + { + /* Ensure the enctype to check against is an expected type. */ + const krb5_enctype *p = NULL; + bool found = false; + for (p = allowed_enctypes; *p != (krb5_enctype)ETYPE_NULL; ++p) { + if (*p == expected_enctype) { + found = true; + break; + } + } + torture_assert(test_context->tctx, + found, + "Calculated enctype not in allowed list"); + } + + reply_enctype = test_context->as_rep.enc_part.etype; torture_assert_int_equal(test_context->tctx, reply_enctype, expected_enctype, "Ticket encrypted with invalid algorithm"); @@ -310,7 +387,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex if (test_context->packet_count == 0) { ok = torture_check_krb5_error(test_context, recv_buf, - KRB5KRB_ERR_RESPONSE_TOO_BIG, + KRB5KDC_ERR_PREAUTH_REQUIRED, false); torture_assert(test_context->tctx, ok, @@ -318,7 +395,7 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex } else if (test_context->packet_count == 1) { ok = torture_check_krb5_error(test_context, recv_buf, - KRB5KDC_ERR_PREAUTH_REQUIRED, + KRB5KRB_ERR_RESPONSE_TOO_BIG, false); torture_assert(test_context->tctx, ok, @@ -411,9 +488,13 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed"); @@ -443,9 +524,13 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_ARCFOUR_HMAC_MD5); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed"); @@ -475,9 +560,14 @@ static bool torture_krb5_post_recv_test(struct torture_krb5_context *test_contex ok, "torture_check_krb5_error failed"); } else { + const krb5_enctype allowed_enctypes[] = { + KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, + KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, + ETYPE_NULL + }; ok = torture_check_krb5_as_rep_enctype(test_context, recv_buf, - KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96); + allowed_enctypes); torture_assert(test_context->tctx, ok, "torture_check_krb5_as_rep_enctype failed");