conf: rework allow/deny parser
Refactor the (cmd)allow/deny parser and make it more strict in what input it accepts. Check the scanned numbers and require whole input to be processed. Move the parser to cmdparse to make it available to the client.
This commit is contained in:
parent
3ac6a0c26c
commit
f5fe5452f6
3 changed files with 92 additions and 92 deletions
79
cmdparse.c
79
cmdparse.c
|
@ -181,6 +181,85 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
int
|
||||||
|
CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits)
|
||||||
|
{
|
||||||
|
char *p, *net, *slash;
|
||||||
|
uint32_t a, b, c;
|
||||||
|
int bits, len, n;
|
||||||
|
|
||||||
|
p = CPS_SplitWord(line);
|
||||||
|
|
||||||
|
if (strcmp(line, "all") == 0) {
|
||||||
|
*all = 1;
|
||||||
|
net = p;
|
||||||
|
p = CPS_SplitWord(p);
|
||||||
|
} else {
|
||||||
|
*all = 0;
|
||||||
|
net = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure there are no other arguments */
|
||||||
|
if (*p)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* No specified address or network means all IPv4 and IPv6 addresses */
|
||||||
|
if (!*net) {
|
||||||
|
ip->family = IPADDR_UNSPEC;
|
||||||
|
*subnet_bits = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
slash = strchr(net, '/');
|
||||||
|
if (slash) {
|
||||||
|
if (sscanf(slash + 1, "%d%n", &bits, &len) != 1 || slash[len + 1] || bits < 0)
|
||||||
|
return 0;
|
||||||
|
*slash = '\0';
|
||||||
|
} else {
|
||||||
|
bits = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UTI_StringToIP(net, ip)) {
|
||||||
|
if (bits >= 0)
|
||||||
|
*subnet_bits = bits;
|
||||||
|
else
|
||||||
|
*subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for a shortened IPv4 network notation using only 1, 2, or 3 decimal
|
||||||
|
numbers. This is different than the numbers-and-dots notation accepted
|
||||||
|
by inet_aton()! */
|
||||||
|
|
||||||
|
a = b = c = 0;
|
||||||
|
n = sscanf(net, "%"PRIu32"%n.%"PRIu32"%n.%"PRIu32"%n", &a, &len, &b, &len, &c, &len);
|
||||||
|
|
||||||
|
if (n > 0 && !net[len]) {
|
||||||
|
if (a > 255 || b > 255 || c > 255)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ip->family = IPADDR_INET4;
|
||||||
|
ip->addr.in4 = (a << 24) | (b << 16) | (c << 8);
|
||||||
|
|
||||||
|
if (bits >= 0)
|
||||||
|
*subnet_bits = bits;
|
||||||
|
else
|
||||||
|
*subnet_bits = n * 8;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last possibility is a hostname */
|
||||||
|
if (bits < 0 && DNS_Name2IPAddress(net, ip, 1) == DNS_Success) {
|
||||||
|
*subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
int
|
int
|
||||||
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,9 @@ typedef struct {
|
||||||
/* Parse a command to add an NTP server or peer */
|
/* Parse a command to add an NTP server or peer */
|
||||||
extern int CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src);
|
extern int CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src);
|
||||||
|
|
||||||
|
/* Parse a command to allow/deny access */
|
||||||
|
extern int CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits);
|
||||||
|
|
||||||
/* Parse a command to enable local reference */
|
/* Parse a command to enable local reference */
|
||||||
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance);
|
extern int CPS_ParseLocal(char *line, int *stratum, int *orphan, double *distance);
|
||||||
|
|
||||||
|
|
102
conf.c
102
conf.c
|
@ -1217,100 +1217,18 @@ parse_ntstrustedcerts(char *line)
|
||||||
static void
|
static void
|
||||||
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
|
parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
|
||||||
{
|
{
|
||||||
char *p;
|
int all, subnet_bits;
|
||||||
unsigned long a, b, c, d, n;
|
AllowDeny *node;
|
||||||
int all = 0;
|
IPAddr ip;
|
||||||
AllowDeny *new_node = NULL;
|
|
||||||
IPAddr ip_addr;
|
|
||||||
|
|
||||||
p = line;
|
if (!CPS_ParseAllowDeny(line, &all, &ip, &subnet_bits))
|
||||||
|
command_parse_error();
|
||||||
|
|
||||||
if (!strncmp(p, "all", 3)) {
|
node = ARR_GetNewElement(restrictions);
|
||||||
all = 1;
|
node->allow = allow;
|
||||||
p = CPS_SplitWord(line);
|
node->all = all;
|
||||||
}
|
node->ip = ip;
|
||||||
|
node->subnet_bits = subnet_bits;
|
||||||
if (!*p) {
|
|
||||||
/* Empty line applies to all addresses */
|
|
||||||
new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
|
|
||||||
new_node->allow = allow;
|
|
||||||
new_node->all = all;
|
|
||||||
new_node->ip.family = IPADDR_UNSPEC;
|
|
||||||
new_node->subnet_bits = 0;
|
|
||||||
} else {
|
|
||||||
char *slashpos;
|
|
||||||
slashpos = strchr(p, '/');
|
|
||||||
if (slashpos) *slashpos = 0;
|
|
||||||
|
|
||||||
check_number_of_args(p, 1);
|
|
||||||
n = 0;
|
|
||||||
if (UTI_StringToIP(p, &ip_addr) ||
|
|
||||||
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) >= 1) {
|
|
||||||
new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
|
|
||||||
new_node->allow = allow;
|
|
||||||
new_node->all = all;
|
|
||||||
|
|
||||||
if (n == 0) {
|
|
||||||
new_node->ip = ip_addr;
|
|
||||||
if (ip_addr.family == IPADDR_INET6)
|
|
||||||
new_node->subnet_bits = 128;
|
|
||||||
else
|
|
||||||
new_node->subnet_bits = 32;
|
|
||||||
} else {
|
|
||||||
new_node->ip.family = IPADDR_INET4;
|
|
||||||
|
|
||||||
a &= 0xff;
|
|
||||||
b &= 0xff;
|
|
||||||
c &= 0xff;
|
|
||||||
d &= 0xff;
|
|
||||||
|
|
||||||
switch (n) {
|
|
||||||
case 1:
|
|
||||||
new_node->ip.addr.in4 = (a<<24);
|
|
||||||
new_node->subnet_bits = 8;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
new_node->ip.addr.in4 = (a<<24) | (b<<16);
|
|
||||||
new_node->subnet_bits = 16;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8);
|
|
||||||
new_node->subnet_bits = 24;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
new_node->ip.addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
|
|
||||||
new_node->subnet_bits = 32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slashpos) {
|
|
||||||
int specified_subnet_bits, n;
|
|
||||||
n = sscanf(slashpos+1, "%d", &specified_subnet_bits);
|
|
||||||
if (n == 1) {
|
|
||||||
new_node->subnet_bits = specified_subnet_bits;
|
|
||||||
} else {
|
|
||||||
command_parse_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (!slashpos && DNS_Name2IPAddress(p, &ip_addr, 1) == DNS_Success) {
|
|
||||||
new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
|
|
||||||
new_node->allow = allow;
|
|
||||||
new_node->all = all;
|
|
||||||
new_node->ip = ip_addr;
|
|
||||||
if (ip_addr.family == IPADDR_INET6)
|
|
||||||
new_node->subnet_bits = 128;
|
|
||||||
else
|
|
||||||
new_node->subnet_bits = 32;
|
|
||||||
} else {
|
|
||||||
command_parse_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
Loading…
Reference in a new issue