diff --git a/CHANGELOG b/CHANGELOG index fe7ae00..ca171a4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -34,6 +34,7 @@ - fix lack of ferror() checking when reading files. - fix typo in autofs(5) man page. - fix map entry expansion when undefined macro is present. +- remove unused export validation code. 18/06/2007 autofs-5.0.2 ----------------------- diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c index 831d456..d79a94f 100644 --- a/lib/rpc_subs.c +++ b/lib/rpc_subs.c @@ -52,10 +52,7 @@ /* Get numeric value of the n bits starting at position p */ #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) -static char *domain = NULL; - inline void dump_core(void); -static pthread_mutex_t networks_mutex = PTHREAD_MUTEX_INITIALIZER; /* * Create a UDP RPC client @@ -764,573 +761,6 @@ void rpc_exports_free(exports list) return; } -static int masked_match(const char *addr, const char *mask) -{ - char buf[MAX_IFC_BUF], *ptr; - struct sockaddr_in saddr; - struct sockaddr_in6 saddr6; - struct ifconf ifc; - struct ifreq *ifr; - int sock, cl_flags, ret, i, is_ipv4, is_ipv6; - unsigned int msize; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(LOGOPT_ANY, "socket creation failed: %s", estr); - return 0; - } - - if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { - cl_flags |= FD_CLOEXEC; - fcntl(sock, F_SETFD, cl_flags); - } - - ifc.ifc_len = sizeof(buf); - ifc.ifc_req = (struct ifreq *) buf; - ret = ioctl(sock, SIOCGIFCONF, &ifc); - if (ret == -1) { - close(sock); - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(LOGOPT_ANY, "ioctl: %s", estr); - return 0; - } - - is_ipv4 = is_ipv6 = 0; - is_ipv4 = inet_pton(AF_INET, addr, &saddr.sin_addr); - if (!is_ipv4) - is_ipv6 = inet_pton(AF_INET6, addr, &saddr6.sin6_addr); - - if (strchr(mask, '.')) { - struct sockaddr_in maddr; - uint32_t ma; - int i = 0; - - ret = inet_aton(mask, &maddr.sin_addr); - if (!ret) { - close(sock); - return 0; - } - - ma = ntohl((uint32_t) maddr.sin_addr.s_addr); - while (!(ma & 1)) { - i++; - ma = ma >> 1; - } - - msize = i; - } else - msize = atoi(mask); - - i = 0; - ptr = (char *) &ifc.ifc_buf[0]; - - while (ptr < buf + ifc.ifc_len) { - ifr = (struct ifreq *) ptr; - - switch (ifr->ifr_addr.sa_family) { - case AF_INET: - { - struct sockaddr_in *if_addr; - uint32_t m, ia, ha; - - if (!is_ipv4 || msize > 32) - break; - - m = -1; - m = m << (32 - msize); - ha = ntohl((uint32_t) saddr.sin_addr.s_addr); - - if_addr = (struct sockaddr_in *) &ifr->ifr_addr; - ia = ntohl((uint32_t) if_addr->sin_addr.s_addr); - - if ((ia & m) == (ha & m)) { - close(sock); - return 1; - } - break; - } - - /* glibc rpc only understands IPv4 atm */ - case AF_INET6: - break; - - default: - break; - } - - i++; - ptr = (char *) &ifc.ifc_req[i]; - } - - close(sock); - return 0; -} - -/* - * This function has been adapted from the match_patern function - * found in OpenSSH and is used in accordance with the copyright - * notice found their. - * - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland. - */ -/* - * Returns true if the given string matches the pattern (which - * may contain ? and * as wildcards), and zero if it does not - * match. - */ -static int pattern_match(const char *s, const char *pattern) -{ - for (;;) { - /* If at end of pattern, accept if also at end of string. */ - if (!*pattern) - return !*s; - - if (*pattern == '*') { - /* Skip the asterisk. */ - pattern++; - - /* If at end of pattern, accept immediately. */ - if (!*pattern) - return 1; - - /* If next character in pattern is known, optimize. */ - if (*pattern != '?' && *pattern != '*') { - /* - * Look instances of the next character in - * pattern, and try to match starting from - * those. - */ - for (; *s; s++) - if (*s == *pattern && - pattern_match(s + 1, pattern + 1)) - return 1; - - /* Failed. */ - return 0; - } - /* - * Move ahead one character at a time and try to - * match at each position. - */ - for (; *s; s++) - if (pattern_match(s, pattern)) - return 1; - /* Failed. */ - return 0; - } - /* - * There must be at least one more character in the string. - * If we are at the end, fail. - */ - if (!*s) - return 0; - - /* Check if the next character of the string is acceptable. */ - if (*pattern != '?' && *pattern != *s) - return 0; - - /* Move to the next character, both in string and in pattern. */ - s++; - pattern++; - } - /* NOTREACHED */ -} - -static int name_match(const char *name, const char *pattern) -{ - int ret; - - if (strchr(pattern, '*') || strchr(pattern, '?')) - ret = pattern_match(name, pattern); - else { - ret = !memcmp(name, pattern, strlen(pattern)); - /* Name could still be a netgroup (Solaris) */ - if (!ret) - ret = innetgr(pattern, name, NULL, domain); - } - - return ret; -} - -static int fqdn_match(const char *pattern) -{ - char buf[MAX_IFC_BUF], *ptr; - struct ifconf ifc; - struct ifreq *ifr; - int sock, cl_flags, ret, i; - char fqdn[NI_MAXHOST + 1]; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(LOGOPT_ANY, "socket creation failed: %s", estr); - return 0; - } - - if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { - cl_flags |= FD_CLOEXEC; - fcntl(sock, F_SETFD, cl_flags); - } - - ifc.ifc_len = sizeof(buf); - ifc.ifc_req = (struct ifreq *) buf; - ret = ioctl(sock, SIOCGIFCONF, &ifc); - if (ret == -1) { - close(sock); - char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(LOGOPT_ANY, "ioctl: %s", estr); - return 0; - } - - i = 0; - ptr = (char *) &ifc.ifc_buf[0]; - - while (ptr < buf + ifc.ifc_len) { - ifr = (struct ifreq *) ptr; - - switch (ifr->ifr_addr.sa_family) { - case AF_INET: - { - socklen_t slen = sizeof(struct sockaddr); - - ret = getnameinfo(&ifr->ifr_addr, slen, fqdn, - NI_MAXHOST, NULL, 0, NI_NAMEREQD); - if (!ret) { - ret = name_match(fqdn, pattern); - if (ret) { - close(sock); - return 1; - } - } - break; - } - - /* glibc rpc only understands IPv4 atm */ - case AF_INET6: - break; - - default: - break; - } - - i++; - ptr = (char *) &ifc.ifc_req[i]; - } - - close(sock); - return 0; -} - -static int string_match(const char *myname, const char *pattern) -{ - struct addrinfo hints, *ni; - int ret; - - /* Try simple name match first */ - ret = name_match(myname, pattern); - if (ret) - goto done; - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = 0; - hints.ai_socktype = 0; - - /* See if our canonical name matches */ - if (getaddrinfo(myname, NULL, &hints, &ni) == 0) { - ret = name_match(ni->ai_canonname, pattern); - freeaddrinfo(ni); - } else - warn(LOGOPT_ANY, "name lookup failed: %s", gai_strerror(ret)); - if (ret) - goto done; - - /* Lastly see if the name of an interfaces matches */ - ret = fqdn_match(pattern); -done: - return ret; -} - -static unsigned int inet_get_net_len(uint32_t net) -{ - int i; - - for (i = 0; i < 32; i += 8) { - if (getbits(net, i + 7, 8)) - break; - } - - return (unsigned int) 32 - i; -} - -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; - - if (!isdigit(*net_num)) - return NULL; - - *net = '\0'; - strcpy(net, net_num); - - np = net; - while (*np++) { - if (*np == '.') { - np++; - dots--; - if (!*np && dots) - strcat(net, "0"); - continue; - } - - if ((*np && !isdigit(*np)) || dots < 0) { - *net = '\0'; - return NULL; - } - } - - while (dots--) - strcat(net, ".0"); - - return net; -} - -static int match_network(const char *network) -{ - struct netent *pnent, nent; - const char *pcnet; - char *net, cnet[MAX_NETWORK_LEN], mask[4], *pmask; - unsigned int size; - size_t l_network = strlen(network) + 1; - int status; - - 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, '/'))) - *pmask++ = '\0'; - - status = pthread_mutex_lock(&networks_mutex); - if (status) - fatal(status); - - pnent = getnetbyname(net); - if (pnent) - memcpy(&nent, pnent, sizeof(struct netent)); - - status = pthread_mutex_unlock(&networks_mutex); - if (status) - fatal(status); - - if (pnent) { - uint32_t n_net; - - 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; - - default: - return 0; - } - } else { - int ret; - - if (strchr(net, ':')) { - return 0; - } else { - struct in_addr addr; - - pcnet = inet_fill_net(net, cnet); - if (!pcnet) - return 0; - - 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; - } - } - } - - if (!pmask) { - if (sprintf(mask, "%u", size) <= 0) - return 0; - pmask = mask; - } - - debug(LOGOPT_ANY, "pcnet %s pmask %s", pcnet, pmask); - - return masked_match(pcnet, pmask); -} - -/* - * Two export formats need to be understood to cater for different - * NFS server exports. - * - * (host|wildcard|network[/mask]|@netgroup) - * - * A host name which can be cannonical. - * A wildcard host name containing "*" and "?" with the usual meaning. - * A network in numbers and dots form with optional mask given as - * either a length or as numbers and dots. - * A netgroup identified by the prefix "@". - * - * [-](host|domain suffix|netgroup|@network[/mask]) - * - * A host name which can be cannonical. - * A domain suffix identified by a leading "." which will match all - * hosts in the given domain. - * A netgroup. - * A network identified by the prefix "@" given in numbers and dots - * form or as a network name with optional mask given as either a - * length or as numbers and dots. - * A "-" prefix can be appended to indicate access is denied. - */ -static int host_match(char *pattern) -{ - unsigned int negate = (*pattern == '-'); - const char *m_pattern = (negate ? pattern + 1 : pattern); - char myname[MAXHOSTNAMELEN + 1] = "\0"; - int ret = 0; - - if (gethostname(myname, MAXHOSTNAMELEN)) - return 0; - - if (yp_get_default_domain(&domain)) - domain = NULL; - - if (*m_pattern == '@') { - /* - * The pattern begins with an "@" so it's a network - * spec or it's a netgroup. - */ - ret = match_network(m_pattern + 1); - if (!ret) - ret = innetgr(m_pattern + 1, myname, NULL, domain); - } else if (*m_pattern == '.') { - size_t m_len = strlen(m_pattern); - char *has_dot = strchr(myname, '.'); - /* - * The pattern starts with a "." so it's a domain spec - * of some sort. - * - * If the host name contains a dot then it must be either - * a cannonical name or a simple NIS name.domain. So - * perform a string match. Otherwise, append the domain - * pattern to our simple name and try a wildcard pattern - * match against the interfaces. - */ - if (has_dot) { - if (strlen(has_dot) == m_len) - ret = !memcmp(has_dot, m_pattern, m_len); - } else { - char *w_pattern = alloca(m_len + 2); - if (w_pattern) { - strcpy(w_pattern, "*"); - strcat(w_pattern, m_pattern); - ret = fqdn_match(w_pattern); - } - } - } else if (!strcmp(m_pattern, "gss/krb5")) { - /* Leave this to the GSS layer */ - return 1; - } else { - /* - * Otherwise it's a network name or host name - */ - ret = match_network(m_pattern); - if (!ret) - /* if not then try to match host name */ - ret = string_match(myname, m_pattern); - } - - if (negate && ret) - ret = -1; - - return ret; -} - -static int rpc_export_allowed(groups grouplist) -{ - groups grp = grouplist; - - /* NULL group list => everyone */ - if (!grp) - return 1; - - while (grp) { - int allowed = host_match(grp->gr_name); - /* Explicitly denied access */ - if (allowed == -1) - return 0; - else if (allowed) - return 1; - grp = grp->gr_next; - } - return 0; -} - -exports rpc_exports_prune(exports list) -{ - exports head = list; - exports exp; - exports last; - int res; - - exp = list; - last = NULL; - while (exp) { - res = rpc_export_allowed(exp->ex_groups); - if (!res) { - if (last == NULL) { - head = exp->ex_next; - rpc_export_free(exp); - exp = head; - } else { - last->ex_next = exp->ex_next; - rpc_export_free(exp); - exp = last->ex_next; - } - continue; - } - last = exp; - exp = exp->ex_next; - } - return head; -} - exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option) { struct conn_info info; diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c index 1f8fa15..d711611 100644 --- a/modules/lookup_hosts.c +++ b/modules/lookup_hosts.c @@ -45,7 +45,6 @@ struct lookup_context { int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option); -exports rpc_exports_prune(exports list); void rpc_exports_free(exports list); int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) @@ -207,9 +206,6 @@ done: exp = rpc_get_exports(name, 10, 0, RPC_CLOSE_NOLINGER); - /* Check exports for obvious ones we don't have access to */ - /*exp = rpc_exports_prune(exp);*/ - mapent = NULL; while (exp) { if (mapent) {