summaryrefslogtreecommitdiffstats
path: root/contrib/tcp_wrappers/hosts_access.c
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>2000-02-03 10:27:03 +0000
committershin <shin@FreeBSD.org>2000-02-03 10:27:03 +0000
commit225d233deb08e4006d8cabd0a6572f76d729f90d (patch)
tree5e244ba219acd7cbeb17a0c5dc92b62227ab2828 /contrib/tcp_wrappers/hosts_access.c
parent22aa8f5f0343020efcf93d4ebc043c5f558995d5 (diff)
downloadFreeBSD-src-225d233deb08e4006d8cabd0a6572f76d729f90d.zip
FreeBSD-src-225d233deb08e4006d8cabd0a6572f76d729f90d.tar.gz
Missing tcp_wrapper IPv6 support seemed to be a bug, so commit it.
Now when tcp_wrapper is enabled by inetd -wW, several accesses which should be permitted are refused only for IPv6, if hostname is used to decide the host to be allowed. IPv6 users will be just upset. About security related concern. -All extensions are wrapped by #ifdef INET6, so people can completely disable the extension by recompile libwrap without INET6 option. -Access via IPv6 is not enabled by default. People need to enable IPv6 access by changing /etc/inetd.conf at first, by adding tcp6 and/or tcp46 entries. -The base of patches are from KAME package and are actually daily used for more than a year in several Japanese IPv6 environments. -Patches are reviewed by markm. Approved by: jkh Submitted by: Hajimu UMEMOTO <ume@mahoroba.org> Reviewed by: markm Obtained from: KAME project
Diffstat (limited to 'contrib/tcp_wrappers/hosts_access.c')
-rw-r--r--contrib/tcp_wrappers/hosts_access.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/contrib/tcp_wrappers/hosts_access.c b/contrib/tcp_wrappers/hosts_access.c
index 27dd81d..2b4dcee 100644
--- a/contrib/tcp_wrappers/hosts_access.c
+++ b/contrib/tcp_wrappers/hosts_access.c
@@ -26,7 +26,13 @@ static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
/* System libraries. */
#include <sys/types.h>
+#ifdef INT32_T
+ typedef uint32_t u_int32_t;
+#endif
#include <sys/param.h>
+#ifdef INET6
+#include <sys/socket.h>
+#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
@@ -84,6 +90,10 @@ static int client_match();
static int host_match();
static int string_match();
static int masked_match();
+#ifdef INET6
+static int masked_match4();
+static int masked_match6();
+#endif
/* Size of logical line buffer. */
@@ -313,6 +323,13 @@ char *string;
{
int n;
+#ifdef INET6
+ /* convert IPv4 mapped IPv6 address to IPv4 address */
+ if (STRN_EQ(string, "::ffff:", 7)
+ && dot_quad_addr(string + 7) != INADDR_NONE) {
+ string += 7;
+ }
+#endif
if (tok[0] == '.') { /* suffix */
n = strlen(string) - strlen(tok);
return (n > 0 && STR_EQ(tok, string + n));
@@ -323,20 +340,55 @@ char *string;
} else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
return (STRN_EQ(tok, string, n));
} else { /* exact match */
+#ifdef INET6
+ struct in6_addr pat, addr;
+ int len, ret;
+ char ch;
+
+ len = strlen(tok);
+ if (*tok == '[' && tok[len - 1] == ']') {
+ ch = tok[len - 1];
+ tok[len - 1] = '\0';
+ ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
+ tok[len - 1] = ch;
+ if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
+ return NO;
+ return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
+ }
+#endif
return (STR_EQ(tok, string));
}
}
/* masked_match - match address against netnumber/netmask */
+#ifdef INET6
static int masked_match(net_tok, mask_tok, string)
char *net_tok;
char *mask_tok;
char *string;
{
+ return (masked_match4(net_tok, mask_tok, string) ||
+ masked_match6(net_tok, mask_tok, string));
+}
+
+static int masked_match4(net_tok, mask_tok, string)
+#else
+static int masked_match(net_tok, mask_tok, string)
+#endif
+char *net_tok;
+char *mask_tok;
+char *string;
+{
+#ifdef INET6
+ u_int32_t net;
+ u_int32_t mask;
+ u_int32_t addr;
+#else
unsigned long net;
unsigned long mask;
unsigned long addr;
+#endif
/*
* Disallow forms other than dotted quad: the treatment that inet_addr()
@@ -348,8 +400,61 @@ char *string;
return (NO);
if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
+#ifndef INET6
tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
+#endif
return (NO); /* not tcpd_jump() */
}
return ((addr & mask) == net);
}
+
+#ifdef INET6
+static int masked_match6(net_tok, mask_tok, string)
+char *net_tok;
+char *mask_tok;
+char *string;
+{
+ struct in6_addr net, addr;
+ u_int32_t mask;
+ int len, mask_len, i = 0;
+ char ch;
+
+ if (inet_pton(AF_INET6, string, addr.s6_addr) != 1)
+ return NO;
+
+ if (IN6_IS_ADDR_V4MAPPED(&addr)) {
+ if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
+ || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
+ return (NO);
+ return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]);
+ }
+
+ /* match IPv6 address against netnumber/prefixlen */
+ len = strlen(net_tok);
+ if (*net_tok != '[' || net_tok[len - 1] != ']')
+ return NO;
+ ch = net_tok[len - 1];
+ net_tok[len - 1] = '\0';
+ if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
+ net_tok[len - 1] = ch;
+ return NO;
+ }
+ net_tok[len - 1] = ch;
+ if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
+ return NO;
+
+ while (mask_len > 0) {
+ if (mask_len < 32) {
+ mask = htonl(~(0xffffffff >> mask_len));
+ if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask))
+ return NO;
+ break;
+ }
+ if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
+ return NO;
+ i += 4;
+ mask_len -= 32;
+ }
+ return YES;
+}
+#endif /* INET6 */
OpenPOWER on IntegriCloud