resolved-dns-trust-anchor.c revision 105f6c4bdcdd9c7233370f1bc143913d5ab0d099
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2015 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poetteringstatic const char trust_anchor_dirs[] = CONF_PATHS_NULSTR("dnssec-trust-anchors.d");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering/* The DS RR from https://data.iana.org/root-anchors/root-anchors.xml, retrieved December 2015 */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering { 0x49, 0xAA, 0xC1, 0x1D, 0x7B, 0x6F, 0x64, 0x46, 0x70, 0x2E, 0x54, 0xA1, 0x60, 0x73, 0x71, 0x60,
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering 0x7A, 0x1A, 0x41, 0x85, 0x52, 0x00, 0xFD, 0x2C, 0xE1, 0xCD, 0xDE, 0x32, 0xF2, 0x4E, 0x8F, 0xB5 };
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic int dns_trust_anchor_add_builtin(DnsTrustAnchor *d) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, ".")))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DNSKEY, ".")))
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Add the RR from https://data.iana.org/root-anchors/root-anchors.xml */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "");
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering rr->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering rr->ds.digest_type = DNSSEC_DIGEST_SHA256;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering rr->ds.digest_size = sizeof(root_digest);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering rr->ds.digest = memdup(root_digest, rr->ds.digest_size);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = hashmap_put(d->positive_by_key, rr->key, answer);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_free_ char *domain = NULL, *class = NULL, *type = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering const char *p = s;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return log_warning_errno(r, "Unable to parse domain in line %s:%u: %m", path, line);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = extract_many_words(&p, NULL, 0, &class, &type, NULL);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return log_warning_errno(r, "Unable to parse class and type in line %s:%u: %m", path, line);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering log_warning("Missing class or type in line %s:%u", path, line);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering log_warning("RR class %s is not supported, ignoring line %s:%u.", class, path, line);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Missing DS parameters on line %s:%u", path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return log_warning_errno(r, "Failed to parse DS key tag %s on line %s:%u: %m", key_tag, path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering a = dnssec_algorithm_from_string(algorithm);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_warning("Failed to parse DS algorithm %s on line %s:%u", algorithm, path, line);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering dt = dnssec_digest_from_string(digest_type);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse DS digest type %s on line %s:%u", digest_type, path, line);
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering r = unhexmem(digest, strlen(digest), &dd, &l);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, domain);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering log_warning("Missing DNSKEY parameters on line %s:%u", path, line);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering log_warning("DNSKEY Protocol is not 3 on line %s:%u", path, line);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return log_warning_errno(r, "Failed to parse DNSKEY flags field %s on line %s:%u", flags, path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("DNSKEY lacks zone key bit set on line %s:%u", path, line);
06820eafdbc3dd89cb1f7563564c7d91426709caLennart Poettering log_warning("DNSKEY is already revoked on line %s:%u", path, line);
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering a = dnssec_algorithm_from_string(algorithm);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering log_warning("Failed to parse DNSKEY algorithm %s on line %s:%u", algorithm, path, line);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering r = unbase64mem(key, strlen(key), &k, &l);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering old_answer = hashmap_get(d->positive_by_key, rr->key);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return log_error_errno(r, "Failed to add trust anchor RR: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = hashmap_replace(d->positive_by_key, rr->key, answer);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return log_error_errno(r, "Failed to add answer to trust anchor: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering old_answer = dns_answer_unref(old_answer);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_trust_anchor_load_negative(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering const char *p = s;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = extract_first_word(&p, &domain, NULL, EXTRACT_QUOTES);
9030ca462bd13cd6536299814e4a71d5c5e85be9Lennart Poettering return log_warning_errno(r, "Unable to parse line %s:%u: %m", path, line);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Trailing garbage at line %s:%u, ignoring line.", path, line);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = set_put(d->negative_by_name, domain);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int (*loader)(DnsTrustAnchor *d, const char *path, unsigned n, const char *line)) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = conf_files_list_nulstr(&files, suffix, NULL, trust_anchor_dirs);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering unsigned n = 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering log_warning_errno(errno, "Failed to open %s: %m", *f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering FOREACH_LINE(line, g, log_warning_errno(errno, "Failed to read %s, ignoring: %m", *f)) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (*l == ';')
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering (void) loader(d, *f, n, l);
554604b3073467af75dc94fac9e2343148603289Lennart Poetteringstatic void dns_trust_anchor_dump(DnsTrustAnchor *d) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_info("No positive trust anchors defined.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering HASHMAP_FOREACH(a, d->positive_by_key, i) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("%s", dns_resource_record_to_string(rr));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("No negative trust anchors defined.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_info("%s%s", n, endswith(n, ".") ? "" : ".");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_trust_anchor_load(DnsTrustAnchor *d) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* If loading things from disk fails, we don't consider this fatal */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering (void) dns_trust_anchor_load_files(d, ".positive", dns_trust_anchor_load_positive);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering (void) dns_trust_anchor_load_files(d, ".negative", dns_trust_anchor_load_negative);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* However, if the built-in DS fails, then we have a problem. */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return log_error_errno(r, "Failed to add trust anchor built-in: %m");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringvoid dns_trust_anchor_flush(DnsTrustAnchor *d) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering while ((a = hashmap_steal_first(d->positive_by_key)))
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering d->positive_by_key = hashmap_free(d->positive_by_key);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering d->negative_by_name = set_free_free(d->negative_by_name);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringint dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey *key, DnsAnswer **ret) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* We only serve DS and DNSKEY RRs. */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (!IN_SET(key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering a = hashmap_get(d->positive_by_key, key);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringint dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return set_contains(d->negative_by_name, name);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringstatic int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *new_answer = NULL;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering old_answer = hashmap_get(d->positive_by_key, rr->key);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = dns_answer_remove_by_rr(&new_answer, rr);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* We found the key! Warn the user */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED),
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering LOG_MESSAGE("DNSSEC Trust anchor %s has been revoked. Please update the trust anchor, or upgrade your operating system."), strna(dns_resource_record_to_string(rr)),
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr),
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = hashmap_replace(d->positive_by_key, new_answer->items[0].rr->key, new_answer);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceRecord *revoked_dnskey) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering assert(revoked_dnskey->key->type == DNS_TYPE_DNSKEY);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering assert(revoked_dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering a = hashmap_get(d->positive_by_key, revoked_dnskey->key);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* First, look for the precise DNSKEY in our trust anchor database */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (anchor->dnskey.protocol != revoked_dnskey->dnskey.protocol)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (anchor->dnskey.algorithm != revoked_dnskey->dnskey.algorithm)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (anchor->dnskey.key_size != revoked_dnskey->dnskey.key_size)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (((anchor->dnskey.flags ^ revoked_dnskey->dnskey.flags) | DNSKEY_FLAG_REVOKE) != DNSKEY_FLAG_REVOKE)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (memcmp(anchor->dnskey.key, revoked_dnskey->dnskey.key, anchor->dnskey.key_size) != 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_trust_anchor_remove_revoked(d, anchor);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(revoked_dnskey->key)));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* Second, look for DS RRs matching this DNSKEY in our trust anchor database */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = dnssec_verify_dnskey(revoked_dnskey, anchor, true);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering dns_trust_anchor_remove_revoked(d, anchor);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic bool dns_trust_anchor_knows_domain(DnsTrustAnchor *d, const char *name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Returns true if there's an entry for the specified domain
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering * name in our trust anchor */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DNSKEY, name)) ||
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, name));
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringint dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsAnswer *rrs, const DnsResourceKey *key) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Looks for self-signed DNSKEY RRs in "rrs" that have been revoked. */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = dns_resource_key_equal(key, dnskey->key);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Is this DNSKEY revoked? */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if ((dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE) == 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Could this be interesting to us at all? If not,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * there's no point in looking for and verifying a
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * self-signed RRSIG. */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!dns_trust_anchor_knows_domain(d, DNS_RESOURCE_KEY_NAME(dnskey->key)))
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Look for a self-signed RRSIG */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = dnssec_rrsig_match_dnskey(rrsig, dnskey, true);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = dnssec_verify_rrset(rrs, key, rrsig, dnskey, USEC_INFINITY, &result);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Bingo! Now, act! */