From: Lennart Poettering Date: Tue, 29 Sep 2020 09:52:15 +0000 (+0200) Subject: dns-domain: add helper that checks whether domain is dot suffixed X-Git-Tag: v247-rc1~157^2~1 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=commitdiff_plain;h=64c82c25ab9e7f18c6b1d8b4b01f528196e53d1a dns-domain: add helper that checks whether domain is dot suffixed --- diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index b812665315f..00e12e681fe 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -41,8 +41,9 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f /* Trailing dash */ return -EINVAL; - if (*n == '.') + if (n[0] == '.' && (n[1] != 0 || !FLAGS_SET(flags, DNS_LABEL_LEAVE_TRAILING_DOT))) n++; + break; } @@ -139,7 +140,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f return -EINVAL; /* More than one trailing dot? */ - if (*n == '.') + if (n[0] == '.' && !FLAGS_SET(flags, DNS_LABEL_LEAVE_TRAILING_DOT)) return -EINVAL; if (sz >= 1 && d) @@ -1372,3 +1373,19 @@ int dns_name_is_valid_or_address(const char *name) { return dns_name_is_valid(name); } + +int dns_name_dot_suffixed(const char *name) { + const char *p = name; + int r; + + for (;;) { + if (streq(p, ".")) + return true; + + r = dns_label_unescape(&p, NULL, DNS_LABEL_MAX, DNS_LABEL_LEAVE_TRAILING_DOT); + if (r < 0) + return r; + if (r == 0) + return false; + } +} diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h index 6ed512c6b16..60de7af2272 100644 --- a/src/shared/dns-domain.h +++ b/src/shared/dns-domain.h @@ -25,8 +25,9 @@ #define DNS_N_LABELS_MAX 127 typedef enum DNSLabelFlags { - DNS_LABEL_LDH = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */ - DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */ + DNS_LABEL_LDH = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */ + DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */ + DNS_LABEL_LEAVE_TRAILING_DOT = 1 << 2, /* Leave trailing dot in place */ } DNSLabelFlags; int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags); @@ -110,3 +111,5 @@ int dns_name_common_suffix(const char *a, const char *b, const char **ret); int dns_name_apply_idna(const char *name, char **ret); int dns_name_is_valid_or_address(const char *name); + +int dns_name_dot_suffixed(const char *name); diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c index ead5311705d..b73dc564656 100644 --- a/src/test/test-dns-domain.c +++ b/src/test/test-dns-domain.c @@ -780,6 +780,20 @@ static void test_dns_name_is_valid_or_address(void) { assert_se(dns_name_is_valid_or_address("::1") > 0); } +static void test_dns_name_dot_suffixed(void) { + log_info("/* %s */", __func__); + + assert_se(dns_name_dot_suffixed("") == 0); + assert_se(dns_name_dot_suffixed(".") > 0); + assert_se(dns_name_dot_suffixed("foo") == 0); + assert_se(dns_name_dot_suffixed("foo.") > 0); + assert_se(dns_name_dot_suffixed("foo\\..") > 0); + assert_se(dns_name_dot_suffixed("foo\\.") == 0); + assert_se(dns_name_dot_suffixed("foo.bar.") > 0); + assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\..") > 0); + assert_se(dns_name_dot_suffixed("foo.bar\\.\\.\\.\\.") == 0); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -810,6 +824,7 @@ int main(int argc, char *argv[]) { test_dns_name_common_suffix(); test_dns_name_apply_idna(); test_dns_name_is_valid_or_address(); + test_dns_name_dot_suffixed(); return 0; }