diff --git a/mysql-test/main/grant_cidr.result b/mysql-test/main/grant_cidr.result new file mode 100644 index 0000000000000..fb527be92fe79 --- /dev/null +++ b/mysql-test/main/grant_cidr.result @@ -0,0 +1,203 @@ +# Valid CIDR prefixes +CREATE USER c01@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER c02@'127.0.0.0/24' IDENTIFIED BY 'p'; +CREATE USER c03@'127.0.0.1/32' IDENTIFIED BY 'p'; +CREATE USER c18@'127.0.0.0/31' IDENTIFIED BY 'p'; +CREATE USER c19@'127.0.0.0/30' IDENTIFIED BY 'p'; +CREATE USER c06@'0.0.0.0/1' IDENTIFIED BY 'p'; +connect con1,127.0.0.1,c01,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c01@127.0.0.0/8 +disconnect con1; +connection default; +connect con1,127.0.0.1,c02,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c02@127.0.0.0/24 +disconnect con1; +connection default; +connect con1,127.0.0.1,c03,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c03@127.0.0.1/32 +disconnect con1; +connection default; +connect con1,127.0.0.1,c18,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c18@127.0.0.0/31 +disconnect con1; +connection default; +connect con1,127.0.0.1,c19,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c19@127.0.0.0/30 +disconnect con1; +connection default; +connect con1,127.0.0.1,c06,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +c06@0.0.0.0/1 +disconnect con1; +connection default; +# Malformed prefixes must be inert, but login denied. +CREATE USER c08@'127.0.0.0/0' IDENTIFIED BY 'p'; +CREATE USER c09@'127.0.0.1/0' IDENTIFIED BY 'p'; +CREATE USER c10@'127.0.0.0/33' IDENTIFIED BY 'p'; +CREATE USER c11@'127.0.0.0/-1' IDENTIFIED BY 'p'; +CREATE USER c12@'127.0.0.0/abc' IDENTIFIED BY 'p'; +CREATE USER c13@'127.0.0.0/' IDENTIFIED BY 'p'; +CREATE USER c14@'127.0.0.0/24x' IDENTIFIED BY 'p'; +connect(127.0.0.1,c08,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c08,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c08'@'localhost' (using password: YES) +# If this CONNECTS, /0 was accepted and collapsed to /32 (regression). +connect(127.0.0.1,c09,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c09,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c09'@'localhost' (using password: YES) +connect(127.0.0.1,c10,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c10,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c10'@'localhost' (using password: YES) +connect(127.0.0.1,c11,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c11,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c11'@'localhost' (using password: YES) +connect(127.0.0.1,c12,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c12,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c12'@'localhost' (using password: YES) +connect(127.0.0.1,c13,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c13,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c13'@'localhost' (using password: YES) +connect(127.0.0.1,c14,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c14,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c14'@'localhost' (using password: YES) +# CIDR == netmask parity +CREATE USER n01@'127.0.0.0/255.0.0.0' IDENTIFIED BY 'p'; +CREATE USER n02@'127.0.0.0/255.255.255.0' IDENTIFIED BY 'p'; +CREATE USER n03@'127.0.0.1/255.255.255.255' IDENTIFIED BY 'p'; +CREATE USER n04@'127.0.0.0/255.255.255.255' IDENTIFIED BY 'p'; +CREATE USER n05@'127.0.0.0/0.0.0.0' IDENTIFIED BY 'p'; +CREATE USER c04@'127.0.0.0/32' IDENTIFIED BY 'p'; +connect con1,127.0.0.1,n01,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +n01@127.0.0.0/255.0.0.0 +disconnect con1; +connection default; +connect con1,127.0.0.1,n02,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +n02@127.0.0.0/255.255.255.0 +disconnect con1; +connection default; +connect con1,127.0.0.1,n03,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +n03@127.0.0.1/255.255.255.255 +disconnect con1; +connection default; +connect(127.0.0.1,n04,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,n04,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'n04'@'localhost' (using password: YES) +connect(127.0.0.1,c04,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c04,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c04'@'localhost' (using password: YES) +connect(127.0.0.1,n05,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,n05,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'n05'@'localhost' (using password: YES) +# The address is masked, not compared verbatim +CREATE USER c05@'127.0.0.0/1' IDENTIFIED BY 'p'; +CREATE USER c07@'127.0.0.1/24' IDENTIFIED BY 'p'; +CREATE USER n07@'127.0.0.1/255.255.255.0' IDENTIFIED BY 'p'; +connect(127.0.0.1,c05,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c05,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c05'@'localhost' (using password: YES) +connect(127.0.0.1,c07,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,c07,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'c07'@'localhost' (using password: YES) +connect(127.0.0.1,n07,p,test,MASTER_PORT,MASTER_SOCKET); +connect con1,127.0.0.1,n07,p,,$MASTER_MYPORT,; +ERROR 28000: Access denied for user 'n07'@'localhost' (using password: YES) +# Part 5: host specificity ordering +CREATE USER ord1@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER ord1@'127.0.0.0/24' IDENTIFIED BY 'p'; +CREATE USER ord2@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER ord2@'127.0.0.0/16' IDENTIFIED BY 'p'; +CREATE USER ord3@'127.0.0.0/9' IDENTIFIED BY 'p'; +CREATE USER ord3@'127.0.0.1/32' IDENTIFIED BY 'p'; +CREATE USER ord4@'127.0.0.0/255.255.255.0' IDENTIFIED BY 'p'; +CREATE USER ord4@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER ord5@'127.0.0.0/255.0.0.0' IDENTIFIED BY 'p'; +CREATE USER ord5@'127.0.0.0/24' IDENTIFIED BY 'p'; +connect con1,127.0.0.1,ord1,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +ord1@127.0.0.0/24 +disconnect con1; +connection default; +connect con1,127.0.0.1,ord2,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +ord2@127.0.0.0/16 +disconnect con1; +connection default; +connect con1,127.0.0.1,ord3,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +ord3@127.0.0.1/32 +disconnect con1; +connection default; +connect con1,127.0.0.1,ord4,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +ord4@127.0.0.0/255.255.255.0 +disconnect con1; +connection default; +connect con1,127.0.0.1,ord5,p,,$MASTER_MYPORT,; +connection con1; +SELECT CURRENT_USER(); +CURRENT_USER() +ord5@127.0.0.0/24 +disconnect con1; +connection default; +# Cleanup +DROP USER c01@'127.0.0.0/8'; +DROP USER c02@'127.0.0.0/24'; +DROP USER c03@'127.0.0.1/32'; +DROP USER c04@'127.0.0.0/32'; +DROP USER c05@'127.0.0.0/1'; +DROP USER c06@'0.0.0.0/1'; +DROP USER c07@'127.0.0.1/24'; +DROP USER c08@'127.0.0.0/0'; +DROP USER c09@'127.0.0.1/0'; +DROP USER c10@'127.0.0.0/33'; +DROP USER c11@'127.0.0.0/-1'; +DROP USER c12@'127.0.0.0/abc'; +DROP USER c13@'127.0.0.0/'; +DROP USER c14@'127.0.0.0/24x'; +DROP USER c18@'127.0.0.0/31'; +DROP USER c19@'127.0.0.0/30'; +DROP USER n01@'127.0.0.0/255.0.0.0'; +DROP USER n02@'127.0.0.0/255.255.255.0'; +DROP USER n03@'127.0.0.1/255.255.255.255'; +DROP USER n04@'127.0.0.0/255.255.255.255'; +DROP USER n05@'127.0.0.0/0.0.0.0'; +DROP USER n07@'127.0.0.1/255.255.255.0'; +DROP USER ord1@'127.0.0.0/8', ord1@'127.0.0.0/24'; +DROP USER ord2@'127.0.0.0/8', ord2@'127.0.0.0/16'; +DROP USER ord3@'127.0.0.0/9', ord3@'127.0.0.1/32'; +DROP USER ord4@'127.0.0.0/255.255.255.0', ord4@'127.0.0.0/8'; +DROP USER ord5@'127.0.0.0/255.0.0.0', ord5@'127.0.0.0/24'; diff --git a/mysql-test/main/grant_cidr.test b/mysql-test/main/grant_cidr.test new file mode 100644 index 0000000000000..740f338087f32 --- /dev/null +++ b/mysql-test/main/grant_cidr.test @@ -0,0 +1,221 @@ +# +# MDEV-25515 User Account Host Names using CIDR notation +# + +--source include/not_embedded.inc + +--echo # Valid CIDR prefixes +CREATE USER c01@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER c02@'127.0.0.0/24' IDENTIFIED BY 'p'; +CREATE USER c03@'127.0.0.1/32' IDENTIFIED BY 'p'; +CREATE USER c18@'127.0.0.0/31' IDENTIFIED BY 'p'; +CREATE USER c19@'127.0.0.0/30' IDENTIFIED BY 'p'; +CREATE USER c06@'0.0.0.0/1' IDENTIFIED BY 'p'; + +connect (con1,127.0.0.1,c01,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,c02,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,c03,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,c18,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,c19,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,c06,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +--echo # Malformed prefixes must be inert, but login denied. +CREATE USER c08@'127.0.0.0/0' IDENTIFIED BY 'p'; +CREATE USER c09@'127.0.0.1/0' IDENTIFIED BY 'p'; +CREATE USER c10@'127.0.0.0/33' IDENTIFIED BY 'p'; +CREATE USER c11@'127.0.0.0/-1' IDENTIFIED BY 'p'; +CREATE USER c12@'127.0.0.0/abc' IDENTIFIED BY 'p'; +CREATE USER c13@'127.0.0.0/' IDENTIFIED BY 'p'; +CREATE USER c14@'127.0.0.0/24x' IDENTIFIED BY 'p'; + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c08,p,,$MASTER_MYPORT,); + +--echo # If this CONNECTS, /0 was accepted and collapsed to /32 (regression). +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c09,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c10,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c11,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c12,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c13,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c14,p,,$MASTER_MYPORT,); + +--echo # CIDR == netmask parity +CREATE USER n01@'127.0.0.0/255.0.0.0' IDENTIFIED BY 'p'; +CREATE USER n02@'127.0.0.0/255.255.255.0' IDENTIFIED BY 'p'; +CREATE USER n03@'127.0.0.1/255.255.255.255' IDENTIFIED BY 'p'; +CREATE USER n04@'127.0.0.0/255.255.255.255' IDENTIFIED BY 'p'; +CREATE USER n05@'127.0.0.0/0.0.0.0' IDENTIFIED BY 'p'; +CREATE USER c04@'127.0.0.0/32' IDENTIFIED BY 'p'; + +connect (con1,127.0.0.1,n01,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,n02,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,n03,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,n04,p,,$MASTER_MYPORT,); +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c04,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,n05,p,,$MASTER_MYPORT,); + +--echo # The address is masked, not compared verbatim +CREATE USER c05@'127.0.0.0/1' IDENTIFIED BY 'p'; +CREATE USER c07@'127.0.0.1/24' IDENTIFIED BY 'p'; +CREATE USER n07@'127.0.0.1/255.255.255.0' IDENTIFIED BY 'p'; + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c05,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,c07,p,,$MASTER_MYPORT,); + +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR +connect (con1,127.0.0.1,n07,p,,$MASTER_MYPORT,); + +--echo # Part 5: host specificity ordering +CREATE USER ord1@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER ord1@'127.0.0.0/24' IDENTIFIED BY 'p'; + +CREATE USER ord2@'127.0.0.0/8' IDENTIFIED BY 'p'; +CREATE USER ord2@'127.0.0.0/16' IDENTIFIED BY 'p'; + +CREATE USER ord3@'127.0.0.0/9' IDENTIFIED BY 'p'; +CREATE USER ord3@'127.0.0.1/32' IDENTIFIED BY 'p'; + +CREATE USER ord4@'127.0.0.0/255.255.255.0' IDENTIFIED BY 'p'; +CREATE USER ord4@'127.0.0.0/8' IDENTIFIED BY 'p'; + +CREATE USER ord5@'127.0.0.0/255.0.0.0' IDENTIFIED BY 'p'; +CREATE USER ord5@'127.0.0.0/24' IDENTIFIED BY 'p'; + +connect (con1,127.0.0.1,ord1,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,ord2,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,ord3,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,ord4,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +connect (con1,127.0.0.1,ord5,p,,$MASTER_MYPORT,); +connection con1; +SELECT CURRENT_USER(); +disconnect con1; +connection default; + +--echo # Cleanup + +DROP USER c01@'127.0.0.0/8'; +DROP USER c02@'127.0.0.0/24'; +DROP USER c03@'127.0.0.1/32'; +DROP USER c04@'127.0.0.0/32'; +DROP USER c05@'127.0.0.0/1'; +DROP USER c06@'0.0.0.0/1'; +DROP USER c07@'127.0.0.1/24'; +DROP USER c08@'127.0.0.0/0'; +DROP USER c09@'127.0.0.1/0'; +DROP USER c10@'127.0.0.0/33'; +DROP USER c11@'127.0.0.0/-1'; +DROP USER c12@'127.0.0.0/abc'; +DROP USER c13@'127.0.0.0/'; +DROP USER c14@'127.0.0.0/24x'; +DROP USER c18@'127.0.0.0/31'; +DROP USER c19@'127.0.0.0/30'; +DROP USER n01@'127.0.0.0/255.0.0.0'; +DROP USER n02@'127.0.0.0/255.255.255.0'; +DROP USER n03@'127.0.0.1/255.255.255.255'; +DROP USER n04@'127.0.0.0/255.255.255.255'; +DROP USER n05@'127.0.0.0/0.0.0.0'; +DROP USER n07@'127.0.0.1/255.255.255.0'; +DROP USER ord1@'127.0.0.0/8', ord1@'127.0.0.0/24'; +DROP USER ord2@'127.0.0.0/8', ord2@'127.0.0.0/16'; +DROP USER ord3@'127.0.0.0/9', ord3@'127.0.0.1/32'; +DROP USER ord4@'127.0.0.0/255.255.255.0', ord4@'127.0.0.0/8'; +DROP USER ord5@'127.0.0.0/255.0.0.0', ord5@'127.0.0.0/24'; + +# +# End of MDEV-25515 tests +# diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1a2af68394868..de9cf3d387529 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -707,6 +707,8 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, /* Flag to mark that on_node was already called for this role */ #define ROLE_OPENED (1L << 3) +#define mask_of(h) ((h).ip_mask ? (h).ip_mask : 0xFFFFFFFFL) /* unmasked literal == /32 */ + static DYNAMIC_ARRAY acl_hosts, acl_users, acl_proxy_users; static Dynamic_array acl_dbs(PSI_INSTRUMENT_MEM, 0, 50); static HASH acl_roles; @@ -3890,6 +3892,9 @@ static int acl_user_compare(const void *a_, const void *b_) if (res) return res; + if (mask_of(a->host) != mask_of(b->host)) + return mask_of(a->host) > mask_of(b->host) ? -1 : 1; /* more bits = fewer IPs = first */ + /* For more deterministic results, resolve ambiguity between "localhost" and "127.0.0.1"/"::1" by sorting "localhost" before @@ -5402,19 +5407,54 @@ static const char *calc_ip(const char *ip, long *val, char end) return ip; } +static const char *calc_cidr(const char *ip, long *val) +{ + long prefix; + /* + CIDR prefix length must be between 1 and 32. + Examples: + /8 -> 255.0.0.0 + /16 -> 255.255.0.0 + /24 -> 255.255.255.0 + /32 -> 255.255.255.255 + */ + if (!(ip=str2int(ip, 10, 0, 32, &prefix)) || *ip != '\0' || !prefix) + return 0; + + *val = (long) (uint32) (0xFFFFFFFFU << (32 - prefix)); + return ip; +} + static void update_hostname(acl_host_and_ip *host, const char *hostname) { // fix historical undocumented convention that empty host is the same as '%' hostname=const_cast(hostname ? hostname : host_not_specified.str); host->hostname=(char*) hostname; // This will not be modified! - if (!(hostname= calc_ip(hostname,&host->ip,'/')) || - !(hostname= calc_ip(hostname+1,&host->ip_mask,'\0'))) + + if (!(hostname=calc_ip(hostname, &host->ip, '/'))) { - host->ip= host->ip_mask=0; // Not a masked ip + host->ip = host->ip_mask = 0; // Not a masked IP + return; } -} + /* + hostname currently points to '/' + + Try old style: + 10.20.0.0/255.255.0.0 + + If that fails: + 10.20.0.0/16 + */ + const char *mask_start = hostname + 1; + + if (!calc_ip(mask_start, &host->ip_mask, '\0') && + !calc_cidr(mask_start, &host->ip_mask)) + { + host->ip = host->ip_mask = 0; + } +} static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, const char *ip)