]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Detect partial prefixes / incomplete IPv4 address in acls.
authorMark Andrews <marka@isc.org>
Mon, 15 Jul 2019 00:25:36 +0000 (10:25 +1000)
committerMark Andrews <marka@isc.org>
Sun, 13 Oct 2019 13:28:07 +0000 (00:28 +1100)
CHANGES
bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-ipv4-prefix2.conf [new file with mode: 0644]
lib/isc/include/isc/result.h
lib/isc/result.c
lib/isccfg/parser.c

diff --git a/CHANGES b/CHANGES
index eb6286b022d95a4bdba4f17ff4079f89944aa2f5..d34cc8b978bf1048c50c6bc8f490bc7395bcf967 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+5301.  [bug]           Detect partial prefixes / incomplete IPv4 address in
+                       acls. [GL #1143]
+
 5300.  [bug]           dig/mdig/delv: Add a colon after EDNS option names,
                        even when the option is empty, to improve
                        readability and allow correct parsing of YAML
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf
new file mode 100644 (file)
index 0000000..e07cc83
--- /dev/null
@@ -0,0 +1,3 @@
+acl myacl {
+       127.1; /* Incomplete dotted IPv4 address / prefix */
+};
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf
new file mode 100644 (file)
index 0000000..ae098be
--- /dev/null
@@ -0,0 +1,3 @@
+acl myacl {
+       127.1/8; /* No-zero bits */
+};
diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix2.conf
new file mode 100644 (file)
index 0000000..4d7738c
--- /dev/null
@@ -0,0 +1,3 @@
+acl myacl {
+       127; /* Non-dotted quad IPv4 address (0.0.0.127) / prefix without length. */
+};
index 634a343b5dafe272efff6900764561c15c8c80b5..96f5f2bdff77db663e9fe8b5733842cd012120e0 100644 (file)
 #define ISC_R_DISCQUOTA                        66      /*%< disc quota */
 #define ISC_R_DISCFULL                 67      /*%< disc full */
 #define ISC_R_DEFAULT                  68      /*%< default */
+#define ISC_R_IPV4PREFIX               69      /*%< IPv4 prefix */
 
 /*% Not a result code: the number of results. */
-#define ISC_R_NRESULTS                         69
+#define ISC_R_NRESULTS                         70
 
 ISC_LANG_BEGINDECLS
 
index 3cfaa86c72555987ce18315f84f031ab4c56c690..ff3ca024138f7cd1b24fd6751a543406ebe6e61c 100644 (file)
@@ -100,6 +100,7 @@ static const char *description[ISC_R_NRESULTS] = {
        "disc quota",                           /*%< 66 */
        "disc full",                            /*%< 67 */
        "default",                              /*%< 68 */
+       "IPv4 prefix",                          /*%< 69 */
 };
 
 static const char *identifier[ISC_R_NRESULTS] = {
@@ -172,6 +173,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
        "ISC_R_DISCQUOTA",
        "ISC_R_DISCFULL",
        "ISC_R_DEFAULT",
+       "ISC_R_IPV4PREFIX",
 };
 
 #define ISC_RESULT_RESULTSET                   2
index c744e296f46d5eff21f398ebabf0727825c0d9cb..0c7987b8810273157556ba872fac4fb9db7f2fba 100644 (file)
@@ -2618,7 +2618,7 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
                                strlcat(buf, ".0", sizeof(buf));
                                if (inet_pton(AF_INET, buf, &in4a) == 1) {
                                        isc_netaddr_fromin(na, &in4a);
-                                       return (ISC_R_SUCCESS);
+                                       return (ISC_R_IPV4PREFIX);
                                }
                        }
                }
@@ -2694,7 +2694,7 @@ cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags) {
        REQUIRE(pctx != NULL);
 
        result = token_addr(pctx, flags, &na_dummy);
-       return (result == ISC_R_SUCCESS);
+       return (result == ISC_R_SUCCESS || result == ISC_R_IPV4PREFIX);
 }
 
 isc_result_t
@@ -2858,14 +2858,18 @@ cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
        isc_result_t result;
        isc_netaddr_t netaddr;
        unsigned int addrlen = 0, prefixlen;
+       bool expectprefix;
 
        REQUIRE(pctx != NULL);
        REQUIRE(ret != NULL && *ret == NULL);
 
        UNUSED(type);
 
-       CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
-                               CFG_ADDR_V6OK, &netaddr));
+       result = cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
+                                  CFG_ADDR_V6OK, &netaddr);
+       if (result != ISC_R_SUCCESS && result != ISC_R_IPV4PREFIX) {
+               CHECK(result);
+       }
        switch (netaddr.family) {
        case AF_INET:
                addrlen = 32;
@@ -2877,6 +2881,7 @@ cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
                INSIST(0);
                ISC_UNREACHABLE();
        }
+       expectprefix = (result == ISC_R_IPV4PREFIX);
        CHECK(cfg_peektoken(pctx, 0));
        if (pctx->token.type == isc_tokentype_special &&
            pctx->token.value.as_char == '/') {
@@ -2884,16 +2889,30 @@ cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
                CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
                if (pctx->token.type != isc_tokentype_number) {
                        cfg_parser_error(pctx, CFG_LOG_NEAR,
-                                    "expected prefix length");
+                                        "expected prefix length");
                        return (ISC_R_UNEXPECTEDTOKEN);
                }
                prefixlen = pctx->token.value.as_ulong;
                if (prefixlen > addrlen) {
                        cfg_parser_error(pctx, CFG_LOG_NOPREP,
-                                    "invalid prefix length");
+                                        "invalid prefix length");
                        return (ISC_R_RANGE);
                }
+               result = isc_netaddr_prefixok(&netaddr, prefixlen);
+               if (result != ISC_R_SUCCESS) {
+                       char buf[ISC_NETADDR_FORMATSIZE + 1];
+                       isc_netaddr_format(&netaddr, buf, sizeof(buf));
+                       cfg_parser_error(pctx, CFG_LOG_NOPREP,
+                                        "'%s/%u': address/prefix length "
+                                        "mismatch", buf, prefixlen);
+                       return (ISC_R_FAILURE);
+               }
        } else {
+               if (expectprefix) {
+                       cfg_parser_error(pctx, CFG_LOG_NEAR,
+                                        "incomplete IPv4 address or prefix");
+                       return (ISC_R_FAILURE);
+               }
                prefixlen = addrlen;
        }
        CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));