From: Lennart Poettering Date: Thu, 14 Dec 2017 05:08:21 +0000 (+0100) Subject: resolved: fix "in-between" logic when boundaries are equal (#7590) X-Git-Tag: v236~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=59f2725cc816e1c8d3bbea30a499990ade9e8653;p=thirdparty%2Fsystemd.git resolved: fix "in-between" logic when boundaries are equal (#7590) This changes dns_name_between() to deal properly with checking whether B is between A and C if A and C are equal. Previously we simply returned -EINVAL in this case, refusing checking. With this change we correct behaviour: if A and C are equal, then B is "between" both if it is different from them. That's logical, since we do < and > comparisons, not <= and >=, and that means that anything "right of A" and "left of C" lies in between with wrap-around at the ends. And if A and C are equal that means everything lies between, except for A itself. This fixes handling of domains using NSEC3 "white lies", for example the .it TLD. Fixes: #7421 --- diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index bdef67dc4f0..8c807e0e238 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -693,23 +693,26 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char } int dns_name_between(const char *a, const char *b, const char *c) { - int n; - /* Determine if b is strictly greater than a and strictly smaller than c. We consider the order of names to be circular, so that if a is strictly greater than c, we consider b to be between them if it is either greater than a or smaller than c. This is how the canonical DNS name order used in NSEC records work. */ - n = dns_name_compare_func(a, c); - if (n == 0) - return -EINVAL; - else if (n < 0) - /* a<---b--->c */ + if (dns_name_compare_func(a, c) < 0) + /* + a and c are properly ordered: + a<---b--->c + */ return dns_name_compare_func(a, b) < 0 && dns_name_compare_func(b, c) < 0; else - /* <--b--c a--b--> */ + /* + a and c are equal or 'reversed': + <--b--c a-----> + or: + <-----c a--b--> + */ return dns_name_compare_func(b, c) < 0 || dns_name_compare_func(a, b) < 0; } diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c index 3105c14ee6c..0ad7d088aa4 100644 --- a/src/test/test-dns-domain.c +++ b/src/test/test-dns-domain.c @@ -230,7 +230,7 @@ static void test_dns_name_between_one(const char *a, const char *b, const char * r = dns_name_between(c, b, a); if (ret >= 0) - assert_se(r == 0); + assert_se(r == 0 || dns_name_equal(a, c) > 0); else assert_se(r == ret); } @@ -249,7 +249,8 @@ static void test_dns_name_between(void) { test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true); test_dns_name_between_one("\\200.z.example", "example", "a.example", true); - test_dns_name_between_one("example", "a.example", "example", -EINVAL); + test_dns_name_between_one("example", "a.example", "example", true); + test_dns_name_between_one("example", "example", "example", false); test_dns_name_between_one("example", "example", "yljkjljk.a.example", false); test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false); }