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 <rpcsvc/ypclnt.h>
#include <errno.h>
#include <sys/ioctl.h>
+#include <ctype.h>
#include <pthread.h>
#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;
+ }
}
}