mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
resolved: rework dnssec validation results
This adds a new validation result DNSSEC_UNSUPPORTED_ALGORITHM which is returned when we encounter an unsupported crypto algorithm when trying to validate RRSIG/DNSKEY combinations. Previously we'd return ENOTSUPP in this case, but it's better to consider this a non-error DNSSEC validation result, since our reaction to this case needs to be more like in cases such as expired or missing keys: we need to keep continue validation looking for another RRSIG/DNSKEY combination that works better for us. This also reworks how dnssec_validate_rrsig_search() propagates errors from dnssec_validate_rrsig(). Previously, errors such as unsupported algorithms or expired signatures would not be propagated, but simply be returned as "missing-key".
This commit is contained in:
parent
79e2493138
commit
203f1b35d9
@ -295,8 +295,10 @@ int dnssec_verify_rrset(
|
||||
* using the signature "rrsig" and the key "dnskey". It's
|
||||
* assumed the RRSIG and DNSKEY match. */
|
||||
|
||||
if (!dnssec_algorithm_supported(rrsig->rrsig.algorithm))
|
||||
return -EOPNOTSUPP;
|
||||
if (!dnssec_algorithm_supported(rrsig->rrsig.algorithm)) {
|
||||
*result = DNSSEC_UNSUPPORTED_ALGORITHM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->n_rrs > VERIFY_RRS_MAX)
|
||||
return -E2BIG;
|
||||
@ -508,7 +510,7 @@ int dnssec_verify_rrset_search(
|
||||
usec_t realtime,
|
||||
DnssecResult *result) {
|
||||
|
||||
bool found_rrsig = false, found_dnskey = false;
|
||||
bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
|
||||
DnsResourceRecord *rrsig;
|
||||
int r;
|
||||
|
||||
@ -524,6 +526,7 @@ int dnssec_verify_rrset_search(
|
||||
DNS_ANSWER_FOREACH(rrsig, a) {
|
||||
DnsResourceRecord *dnskey;
|
||||
|
||||
/* Is this an RRSIG RR that applies to RRs matching our key? */
|
||||
r = dnssec_key_match_rrsig(key, rrsig);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -536,14 +539,13 @@ int dnssec_verify_rrset_search(
|
||||
DNS_ANSWER_FOREACH(dnskey, validated_dnskeys) {
|
||||
DnssecResult one_result;
|
||||
|
||||
/* Is this a DNSKEY RR that matches they key of our RRSIG? */
|
||||
r = dnssec_rrsig_match_dnskey(rrsig, dnskey);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
found_dnskey = true;
|
||||
|
||||
/* Take the time here, if it isn't set yet, so
|
||||
* that we do all validations with the same
|
||||
* time. */
|
||||
@ -556,22 +558,53 @@ int dnssec_verify_rrset_search(
|
||||
* combination. */
|
||||
|
||||
r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
|
||||
if (r < 0 && r != EOPNOTSUPP)
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (one_result == DNSSEC_VALIDATED) {
|
||||
|
||||
switch (one_result) {
|
||||
|
||||
case DNSSEC_VALIDATED:
|
||||
/* Yay, the RR has been validated,
|
||||
* return immediately. */
|
||||
*result = DNSSEC_VALIDATED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the signature is invalid, or done using
|
||||
an unsupported algorithm, let's try another
|
||||
key and/or signature. After all they
|
||||
key_tags and stuff are not unique, and
|
||||
might be shared by multiple keys. */
|
||||
case DNSSEC_INVALID:
|
||||
/* If the signature is invalid, let's try another
|
||||
key and/or signature. After all they
|
||||
key_tags and stuff are not unique, and
|
||||
might be shared by multiple keys. */
|
||||
found_invalid = true;
|
||||
continue;
|
||||
|
||||
case DNSSEC_UNSUPPORTED_ALGORITHM:
|
||||
/* If the key algorithm is
|
||||
unsupported, try another
|
||||
RRSIG/DNSKEY pair, but remember we
|
||||
encountered this, so that we can
|
||||
return a proper error when we
|
||||
encounter nothing better. */
|
||||
found_unsupported_algorithm = true;
|
||||
continue;
|
||||
|
||||
case DNSSEC_SIGNATURE_EXPIRED:
|
||||
/* If the signature is expired, try
|
||||
another one, but remember it, so
|
||||
that we can return this */
|
||||
found_expired_rrsig = true;
|
||||
continue;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected DNSSEC validation result");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_dnskey)
|
||||
if (found_expired_rrsig)
|
||||
*result = DNSSEC_SIGNATURE_EXPIRED;
|
||||
else if (found_unsupported_algorithm)
|
||||
*result = DNSSEC_UNSUPPORTED_ALGORITHM;
|
||||
else if (found_invalid)
|
||||
*result = DNSSEC_INVALID;
|
||||
else if (found_rrsig)
|
||||
*result = DNSSEC_MISSING_KEY;
|
||||
@ -756,10 +789,11 @@ DEFINE_STRING_TABLE_LOOKUP(dnssec_mode, DnssecMode);
|
||||
static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
|
||||
[DNSSEC_VALIDATED] = "validated",
|
||||
[DNSSEC_INVALID] = "invalid",
|
||||
[DNSSEC_UNSIGNED] = "unsigned",
|
||||
[DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
|
||||
[DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
|
||||
[DNSSEC_NO_SIGNATURE] = "no-signature",
|
||||
[DNSSEC_MISSING_KEY] = "missing-key",
|
||||
[DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
|
||||
[DNSSEC_UNSIGNED] = "unsigned",
|
||||
[DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
|
||||
};
|
||||
DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
|
||||
|
@ -43,12 +43,18 @@ enum DnssecMode {
|
||||
};
|
||||
|
||||
enum DnssecResult {
|
||||
/* These four are returned by dnssec_verify_rrset() */
|
||||
DNSSEC_VALIDATED,
|
||||
DNSSEC_INVALID,
|
||||
DNSSEC_UNSIGNED,
|
||||
DNSSEC_SIGNATURE_EXPIRED,
|
||||
DNSSEC_UNSUPPORTED_ALGORITHM,
|
||||
|
||||
/* These two are added by dnssec_verify_rrset_search() */
|
||||
DNSSEC_NO_SIGNATURE,
|
||||
DNSSEC_MISSING_KEY,
|
||||
DNSSEC_SIGNATURE_EXPIRED,
|
||||
|
||||
/* These two are added by the DnsTransaction logic */
|
||||
DNSSEC_UNSIGNED,
|
||||
DNSSEC_FAILED_AUXILIARY,
|
||||
_DNSSEC_RESULT_MAX,
|
||||
_DNSSEC_RESULT_INVALID = -1
|
||||
|
Loading…
Reference in New Issue
Block a user