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,
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");
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,
} 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,
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");
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");
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");