/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include "sd-messages.h"
#include "fd-util.h"
#include "fileio.h"
#include "hexdecoct.h"
+#include "nulstr-util.h"
#include "parse-util.h"
-#include "resolved-dns-trust-anchor.h"
#include "resolved-dns-dnssec.h"
+#include "resolved-dns-trust-anchor.h"
#include "set.h"
+#include "sort-util.h"
#include "string-util.h"
#include "strv.h"
if (r < 0)
return log_warning_errno(r, "Unable to parse domain in line %s:%u: %m", path, line);
- if (!dns_name_is_valid(domain)) {
+ r = dns_name_is_valid(domain);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to check validity of domain name '%s', at line %s:%u, ignoring line: %m", domain, path, line);
+ if (r == 0) {
log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
return -EINVAL;
}
}
if (strcaseeq(type, "DS")) {
- _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL;
+ _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL;
_cleanup_free_ void *dd = NULL;
uint16_t kt;
int a, dt;
size_t l;
- r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL);
+ r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line);
return -EINVAL;
}
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DS parameters on line %s:%u", path, line);
return -EINVAL;
}
return -EINVAL;
}
- r = unhexmem(digest, strlen(digest), &dd, &l);
+ if (isempty(p)) {
+ log_warning("Missing DS digest on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unhexmem(p, strlen(p), &dd, &l);
if (r < 0) {
- log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line);
+ log_warning("Failed to parse DS digest %s on line %s:%u", p, path, line);
return -EINVAL;
}
rr->ds.algorithm = a;
rr->ds.digest_type = dt;
rr->ds.digest_size = l;
- rr->ds.digest = dd;
- dd = NULL;
+ rr->ds.digest = TAKE_PTR(dd);
} else if (strcaseeq(type, "DNSKEY")) {
- _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL;
+ _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL;
_cleanup_free_ void *k = NULL;
uint16_t f;
size_t l;
int a;
- r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL);
+ r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, NULL);
if (r < 0)
return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line);
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DNSKEY parameters on line %s:%u", path, line);
return -EINVAL;
}
return -EINVAL;
}
- r = unbase64mem(key, strlen(key), &k, &l);
+ if (isempty(p)) {
+ log_warning("Missing DNSKEY key on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unbase64mem(p, strlen(p), &k, &l);
if (r < 0)
- return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line);
+ return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", p, path, line);
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain);
if (!rr)
rr->dnskey.protocol = 3;
rr->dnskey.algorithm = a;
rr->dnskey.key_size = l;
- rr->dnskey.key = k;
- k = NULL;
+ rr->dnskey.key = TAKE_PTR(k);
} else {
log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line);
return -EINVAL;
}
- if (!isempty(p)) {
- log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line);
- return -EINVAL;
- }
-
r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
if (r < 0)
return log_oom();
if (r < 0)
return log_warning_errno(r, "Unable to parse line %s:%u: %m", path, line);
- if (!dns_name_is_valid(domain)) {
+ r = dns_name_is_valid(domain);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to check validity of domain name '%s', at line %s:%u, ignoring line: %m", domain, path, line);
+ if (r == 0) {
log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line);
return -EINVAL;
}
STRV_FOREACH(f, files) {
_cleanup_fclose_ FILE *g = NULL;
- char line[LINE_MAX];
unsigned n = 0;
g = fopen(*f, "r");
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to open %s: %m", *f);
+ log_warning_errno(errno, "Failed to open '%s', ignoring: %m", *f);
continue;
}
- FOREACH_LINE(line, g, log_warning_errno(errno, "Failed to read %s, ignoring: %m", *f)) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
char *l;
+ r = read_line(g, LONG_LINE_MAX, &line);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to read '%s', ignoring: %m", *f);
+ break;
+ }
+ if (r == 0)
+ break;
+
n++;
l = strstrip(line);
return 0;
}
-static int domain_name_cmp(const void *a, const void *b) {
- char **x = (char**) a, **y = (char**) b;
-
- return dns_name_compare_func(*x, *y);
+static int domain_name_cmp(char * const *a, char * const *b) {
+ return dns_name_compare_func(*a, *b);
}
static int dns_trust_anchor_dump(DnsTrustAnchor *d) {
if (!l)
return log_oom();
- qsort_safe(l, set_size(d->negative_by_name), sizeof(char*), domain_name_cmp);
+ typesafe_qsort(l, set_size(d->negative_by_name), domain_name_cmp);
j = strv_join(l, " ");
if (!j)
}
void dns_trust_anchor_flush(DnsTrustAnchor *d) {
- DnsAnswer *a;
- DnsResourceRecord *rr;
-
assert(d);
- while ((a = hashmap_steal_first(d->positive_by_key)))
- dns_answer_unref(a);
- d->positive_by_key = hashmap_free(d->positive_by_key);
-
- while ((rr = set_steal_first(d->revoked_by_rr)))
- dns_resource_record_unref(rr);
- d->revoked_by_rr = set_free(d->revoked_by_rr);
-
+ d->positive_by_key = hashmap_free_with_destructor(d->positive_by_key, dns_answer_unref);
+ d->revoked_by_rr = set_free_with_destructor(d->revoked_by_rr, dns_resource_record_unref);
d->negative_by_name = set_free_free(d->negative_by_name);
}
/* We found the key! Warn the user */
log_struct(LOG_WARNING,
"MESSAGE_ID=" SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR,
- 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)),
- "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr),
- NULL);
+ LOG_MESSAGE("DNSSEC trust anchor %s has been revoked.\n"
+ "Please update the trust anchor, or upgrade your operating system.",
+ strna(dns_resource_record_to_string(rr))),
+ "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr));
if (dns_answer_size(new_answer) <= 0) {
assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer);