diff --git a/CHANGELOG b/CHANGELOG index 0bb91e9..34fad3e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ ----------------------- - fix return check for getpwuid_r and getgrgid_r. - give up trying to update exports list while host is mounted. +- fix to "@network" matching. 20/2/2007 autofs-5.0.1 ---------------------- diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c index f51ca82..2c5b5d5 100644 --- a/lib/rpc_subs.c +++ b/lib/rpc_subs.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "mount.h" @@ -46,6 +47,8 @@ #define MAX_IFC_BUF 1024 #define MAX_ERR_BUF 128 +#define MAX_NETWORK_LEN 255 + /* Get numeric value of the n bits starting at position p */ #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) @@ -1066,6 +1069,9 @@ static char *inet_fill_net(const char *net_num, char *net) char *np; unsigned int dots = 3; + if (strlen(net_num) > INET_ADDRSTRLEN) + return NULL; + *net = '\0'; strcpy(net, net_num); @@ -1076,6 +1082,11 @@ static char *inet_fill_net(const char *net_num, char *net) if (!*np && dots) strcat(net, "0"); } + + if (!isdigit(*np) || dots < 0) { + *net = '\0'; + return NULL; + } } while (dots--) @@ -1088,13 +1099,21 @@ static int match_network(const char *network) { struct netent *pnent, nent; const char *pcnet; - char *net, cnet[INET_ADDRSTRLEN + 1], mask[4], *pmask; + char *net, cnet[MAX_NETWORK_LEN], mask[4], *pmask; unsigned int size; + size_t l_network = strlen(network) + 1; int status; - net = alloca(strlen(network) + 1); + if (l_network > MAX_NETWORK_LEN) { + error(LOGOPT_ANY, + "match string \"%s\" too long", network); + return 0; + } + + net = alloca(l_network); if (!net) return 0; + memset(net, 0, l_network); strcpy(net, network); if ((pmask = strchr(net, '/'))) @@ -1115,32 +1134,48 @@ static int match_network(const char *network) if (pnent) { uint32_t n_net; - n_net = ntohl(nent.n_net); - pcnet = inet_ntop(nent.n_addrtype, &n_net, cnet, INET_ADDRSTRLEN); - if (!pcnet) + switch (nent.n_addrtype) { + case AF_INET: + n_net = ntohl(nent.n_net); + pcnet = inet_ntop(AF_INET, &n_net, cnet, INET_ADDRSTRLEN); + if (!pcnet) + return 0; + + if (!pmask) { + size = inet_get_net_len(nent.n_net); + if (!size) + return 0; + } + break; + + case AF_INET6: return 0; - if (!pmask) { - size = inet_get_net_len(nent.n_net); - if (!size) - return 0; + default: + return 0; } } else { - struct in_addr addr; int ret; - pcnet = inet_fill_net(net, cnet); - if (!pcnet) + if (strchr(net, ':')) { return 0; + } else { + struct in_addr addr; - ret = inet_pton(AF_INET, pcnet, &addr); - if (ret <= 0) - return 0; + pcnet = inet_fill_net(net, cnet); + if (!pcnet) + return 0; - if (!pmask) { - size = inet_get_net_len(htonl(addr.s_addr)); - if (!size) + ret = inet_pton(AF_INET, pcnet, &addr); + if (ret <= 0) return 0; + + if (!pmask) { + uint32_t nl_addr = htonl(addr.s_addr); + size = inet_get_net_len(nl_addr); + if (!size) + return 0; + } } }