Accepting request 319256 from home:okir:branches:network:utilities
Fix breakage of IPv6 address handling [bsc#914527, bsc#899185] OBS-URL: https://build.opensuse.org/request/show/319256 OBS-URL: https://build.opensuse.org/package/show/network:utilities/tcpd?expand=0&rev=23
This commit is contained in:
parent
977a6cdbdf
commit
a4faf550b7
364
tcp_wrappers_7.6-ipv6-host-match.patch
Normal file
364
tcp_wrappers_7.6-ipv6-host-match.patch
Normal file
@ -0,0 +1,364 @@
|
||||
---
|
||||
hosts_access.c | 271 ++++++++++++++++++++++++++++++++++-----------------------
|
||||
misc.c | 18 +++
|
||||
tcpd.h | 2
|
||||
3 files changed, 183 insertions(+), 108 deletions(-)
|
||||
|
||||
Index: tcp_wrappers_7.6/hosts_access.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/hosts_access.c
|
||||
+++ tcp_wrappers_7.6/hosts_access.c
|
||||
@@ -88,6 +88,10 @@ static int server_match();
|
||||
static int client_match();
|
||||
static int host_match();
|
||||
static int string_match();
|
||||
+static int masked_match();
|
||||
+#ifdef INET6
|
||||
+static void ipv6_mask();
|
||||
+#endif
|
||||
|
||||
/* Size of logical line buffer. */
|
||||
|
||||
@@ -293,6 +297,74 @@ struct hosts_info *host;
|
||||
return (match);
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+host_info_ipv6addr(const struct host_info *host, struct in6_addr *addrbuf)
|
||||
+{
|
||||
+ /*
|
||||
+ * In some cases we don't get the sockaddr, only the addr.
|
||||
+ * We use inet_pton to convert it to its binary representation
|
||||
+ * and match against that.
|
||||
+ */
|
||||
+ if (host->sin == NULL) {
|
||||
+ if (host->addr == NULL || inet_pton(AF_INET6, host->addr, addrbuf) != 1)
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+ } else
|
||||
+ if (host->sin->ss_family == AF_INET6) {
|
||||
+ *addrbuf = ((struct sockaddr_in6 *) host->sin)->sin6_addr;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+token_ipv6addr_and_mask(char *tok, struct in6_addr *addrbuf, unsigned int *maskbits)
|
||||
+{
|
||||
+ char *cbr;
|
||||
+ char *slash;
|
||||
+
|
||||
+ if (*tok != '[')
|
||||
+ return 0;
|
||||
+
|
||||
+ *maskbits = 128;
|
||||
+
|
||||
+ ++tok; /* now points to the beginning of the IPv6 addr string */
|
||||
+ if ((cbr = strchr(tok, ']')) == NULL) {
|
||||
+ tcpd_warn("bad IP6 address specification");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ *cbr++ = '\0';
|
||||
+
|
||||
+ /*
|
||||
+ * A /nnn prefix specifies how many bits of the address we
|
||||
+ * need to check.
|
||||
+ * Note, we support both [x::y/64] and [x::y]/64
|
||||
+ */
|
||||
+ if ((slash = strchr(tok, '/')) == NULL && *cbr == '/')
|
||||
+ slash = cbr;
|
||||
+
|
||||
+ if (slash != NULL) {
|
||||
+ int mask;
|
||||
+
|
||||
+ *slash++ = '\0';
|
||||
+ mask = atoi(slash);
|
||||
+ if (mask < 0 || mask > 128) {
|
||||
+ tcpd_warn("bad IP6 prefix specification");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ *maskbits = mask;
|
||||
+ }
|
||||
+
|
||||
+ if (inet_pton(AF_INET6, tok, addrbuf) != 1) {
|
||||
+ tcpd_warn("bad IP6 address specification");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/* host_match - match host name and/or address against pattern */
|
||||
|
||||
static int host_match(tok, host)
|
||||
@@ -328,12 +400,68 @@ struct host_info *host;
|
||||
} else if (STR_EQ(tok, "LOCAL")) { /* local: no dots in name */
|
||||
char *name = eval_hostname(host);
|
||||
return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name));
|
||||
+ } else if (tok[0] == '[') { /* IPv6 address */
|
||||
+#ifdef INET6
|
||||
+ struct in6_addr match_addr, host_addr;
|
||||
+ unsigned int mask = 128;
|
||||
+
|
||||
+ if (!host_info_ipv6addr(host, &host_addr))
|
||||
+ return (NO);
|
||||
+
|
||||
+ if (!token_ipv6addr_and_mask(tok, &match_addr, &mask))
|
||||
+ return (NO);
|
||||
+
|
||||
+ /*
|
||||
+ * Zero the bits we're not interested in in both addresses
|
||||
+ * then compare. Note that we take a copy of the host info
|
||||
+ * in that case.
|
||||
+ */
|
||||
+ if (mask != 128) {
|
||||
+ ipv6_mask(&match_addr, mask);
|
||||
+ ipv6_mask(&host_addr, mask);
|
||||
+ }
|
||||
+ if (memcmp(&match_addr, &host_addr, sizeof(struct in6_addr)) == 0)
|
||||
+ return (YES);
|
||||
+#endif
|
||||
+ return (NO);
|
||||
+ } else if ((mask = split_at(tok, '/')) != 0) { /* net/mask */
|
||||
+ return (masked_match(tok, mask, eval_hostaddr(host)));
|
||||
} else { /* anything else */
|
||||
- return (string_match(tok, eval_hostaddr(host))
|
||||
- || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
|
||||
+ return (string_match(tok, eval_hostaddr(host))
|
||||
+ || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
|
||||
}
|
||||
}
|
||||
|
||||
+static int masked_match(net_tok, mask_tok, string)
|
||||
+char *net_tok;
|
||||
+char *mask_tok;
|
||||
+char *string;
|
||||
+{
|
||||
+ unsigned long net;
|
||||
+ unsigned long mask;
|
||||
+ unsigned long addr;
|
||||
+
|
||||
+ /*
|
||||
+ * Disallow forms other than dotted quad: the treatment that inet_addr()
|
||||
+ * gives to forms with less than four components is inconsistent with the
|
||||
+ * access control language. John P. Rouillard <rouilj@cs.umb.edu>.
|
||||
+ */
|
||||
+
|
||||
+ if ((addr = dot_quad_addr(string)) == INADDR_NONE)
|
||||
+ return (NO);
|
||||
+ if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
|
||||
+ || ((mask = dot_quad_addr(mask_tok)) == INADDR_NONE
|
||||
+ && strcmp(mask_tok, "255.255.255.255")
|
||||
+ && (mask = prefix_to_netmask(mask_tok)) == INADDR_NONE
|
||||
+ && strcmp(mask_tok, "32"))) {
|
||||
+ /* 255.255.255.255 == INADDR_NONE, separate check needed. TJ. */
|
||||
+ /* 32 == INADDR_NONE, separate check needed. philipp */
|
||||
+ tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
|
||||
+ return (NO); /* not tcpd_jump() */
|
||||
+ }
|
||||
+ return ((addr & mask) == net);
|
||||
+}
|
||||
+
|
||||
/* string_match - match string against pattern
|
||||
*
|
||||
* tok = data read from /etc/hosts.*
|
||||
@@ -359,113 +487,14 @@ char *string;
|
||||
return (YES);
|
||||
} else if (STR_EQ(tok, "KNOWN")) { /* not unknown */
|
||||
return (STR_NE(string, unknown));
|
||||
- } else if (STR_EQ(tok, string)) /* exact match */
|
||||
- return (YES);
|
||||
-#ifdef INET6
|
||||
- else /* IP addresses match - not needed for IPv4 */
|
||||
- {
|
||||
- /* For simplicity we convert everything to IPv6 (or v4 mapped) */
|
||||
- struct in6_addr pat, addr;
|
||||
- int len, ret, prefixlen=128, nof_periods = 0;
|
||||
- char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition;
|
||||
-
|
||||
- /* If prefix was given, handle it */
|
||||
- if ((mask = split_at(tok, '/')) != 0)
|
||||
- {
|
||||
- if (strchr(mask, '.') != NULL) /* We have something
|
||||
- like 255.255.0.0 */
|
||||
- {
|
||||
- int b1, b2, b3, b4;
|
||||
- uint32_t netmask;
|
||||
-
|
||||
- if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4)
|
||||
- {
|
||||
- tcpd_warn ("Wrong netmask in %s", tok);
|
||||
- return (NO);
|
||||
- }
|
||||
- netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4;
|
||||
- prefixlen = 0;
|
||||
- while (netmask > 0)
|
||||
- {
|
||||
- ++prefixlen;
|
||||
- netmask <<= 1;
|
||||
- }
|
||||
- }
|
||||
- else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0)
|
||||
- {
|
||||
- tcpd_warn ("Wrong prefix length in %s", tok);
|
||||
- return (NO);
|
||||
- }
|
||||
-
|
||||
- if (is_v4_string (tok))
|
||||
- prefixlen += 96; /* extend to v4mapped */
|
||||
-
|
||||
- if (prefixlen > 128)
|
||||
- {
|
||||
- tcpd_warn ("Prefix too long in %s", tok);
|
||||
- return (NO);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- len = strlen(tok);
|
||||
- if (tok[len - 1] == '.') { /* prefix */
|
||||
- char *ptok = tok;
|
||||
-
|
||||
- while ((ptok = strchr(ptok, '.')) != NULL){
|
||||
- nof_periods++;
|
||||
- ptok++;
|
||||
- }
|
||||
- switch(nof_periods){
|
||||
- case 1:
|
||||
- addition = "0.0.0";
|
||||
- prefixlen = 8;
|
||||
- break;
|
||||
- case 2:
|
||||
- addition = "0.0";
|
||||
- prefixlen = 16;
|
||||
- break;
|
||||
- case 3:
|
||||
- addition = "0";
|
||||
- prefixlen = 24;
|
||||
- break;
|
||||
- default:
|
||||
- tcpd_warn ("Wrong prefix %s", tok);
|
||||
- return (NO);
|
||||
- }
|
||||
- snprintf(token, sizeof(token), "%s%s", tok, addition);
|
||||
- prefixlen += 96; /* extend to v4mapped */
|
||||
- }
|
||||
- else if (*tok == '[' && tok[len - 1] == ']')
|
||||
- {
|
||||
- ch = tok[len - 1];
|
||||
- tok[len - 1] = '\0';
|
||||
- snprintf(token, sizeof(token), "%s", tok+1);
|
||||
- tok[len - 1] = ch;
|
||||
- }
|
||||
- else
|
||||
- snprintf(token, sizeof(token), "%s", tok);
|
||||
-
|
||||
- memset (&pat, 0, sizeof(pat));
|
||||
- memset (&addr, 0, sizeof(addr));
|
||||
-
|
||||
- if (inet_pton_mapped(AF_INET6, token, &pat) != 1)
|
||||
- return (NO);
|
||||
-
|
||||
- if (inet_pton_mapped(AF_INET6, string, &addr) != 1)
|
||||
- {
|
||||
- tcpd_warn("Unable to handle client address: %s", string);
|
||||
- return (NO);
|
||||
- }
|
||||
-
|
||||
- if (prefixlen < 128)
|
||||
- {
|
||||
- apply_v6_prefix (&pat, prefixlen);
|
||||
- apply_v6_prefix (&addr, prefixlen);
|
||||
- }
|
||||
-
|
||||
- return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
|
||||
+ } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
|
||||
+ return (STRN_EQ(tok, string, n));
|
||||
+ } else if ((STR_EQ(tok, "localhost") || STR_EQ(tok, "localhost.localdomain"))
|
||||
+ && (STR_EQ(string, "localhost") || STR_EQ(string, "localhost.localdomain"))) {
|
||||
+ return (YES); /* these localhosts are equivalent */
|
||||
+ } else { /* exact match */
|
||||
+ return (STR_EQ(tok, string));
|
||||
}
|
||||
-#endif
|
||||
}
|
||||
|
||||
#ifndef DISABLE_WILDCARD_MATCHING
|
||||
@@ -535,3 +564,29 @@ int match_pattern_ylo(const char *s, con
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif /* DISABLE_WILDCARD_MATCHING */
|
||||
+
|
||||
+#ifdef INET6
|
||||
+/*
|
||||
+ * Function that zeros all but the first "maskbits" bits of the IPV6 address
|
||||
+ * This function can be made generic by specifying an address length as
|
||||
+ * extra parameter. (So Wietse can implement 1.2.3.4/16)
|
||||
+ */
|
||||
+static void ipv6_mask(in6p, maskbits)
|
||||
+struct in6_addr *in6p;
|
||||
+int maskbits;
|
||||
+{
|
||||
+ unsigned char *p = (unsigned char*) in6p;
|
||||
+
|
||||
+ if (maskbits < 0 || maskbits >= 128)
|
||||
+ return;
|
||||
+
|
||||
+ p += maskbits / 8;
|
||||
+ maskbits %= 8;
|
||||
+
|
||||
+ if (maskbits != 0)
|
||||
+ *p++ &= 0xff << (8 - maskbits);
|
||||
+
|
||||
+ while (p < (((unsigned char*) in6p)) + sizeof(*in6p))
|
||||
+ *p++ = 0;
|
||||
+}
|
||||
+#endif
|
||||
Index: tcp_wrappers_7.6/misc.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/misc.c
|
||||
+++ tcp_wrappers_7.6/misc.c
|
||||
@@ -107,3 +107,21 @@ char *str;
|
||||
}
|
||||
return (runs == 4 ? inet_addr(str) : INADDR_NONE);
|
||||
}
|
||||
+
|
||||
+/* prefix_to_netmask - convert prefix (0-32) to netmask */
|
||||
+
|
||||
+unsigned long prefix_to_netmask(str)
|
||||
+char *str;
|
||||
+{
|
||||
+ unsigned long prefix;
|
||||
+ char *endptr;
|
||||
+
|
||||
+ if (!isdigit(str[0]))
|
||||
+ return INADDR_NONE;
|
||||
+
|
||||
+ prefix = strtoul(str, &endptr, 10);
|
||||
+ if ((endptr == str) || (*endptr != '\0') || (prefix > 32))
|
||||
+ return INADDR_NONE;
|
||||
+
|
||||
+ return htonl(~0UL << (32 - prefix));
|
||||
+}
|
||||
Index: tcp_wrappers_7.6/tcpd.h
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/tcpd.h
|
||||
+++ tcp_wrappers_7.6/tcpd.h
|
||||
@@ -88,6 +88,7 @@ extern void refuse(struct request_info *
|
||||
extern char *xgets(char *, int, FILE *);
|
||||
extern char *split_at(char *, int);
|
||||
extern unsigned long dot_quad_addr(char *);
|
||||
+extern char *skip_ipv6_addrs(char *);
|
||||
#else
|
||||
extern int hosts_access(); /* access control */
|
||||
extern void shell_cmd(); /* execute shell command */
|
||||
@@ -98,6 +99,7 @@ extern void refuse(); /* clean up and
|
||||
extern char *xgets(); /* fgets() on steroids */
|
||||
extern char *split_at(); /* strchr() and split */
|
||||
extern unsigned long dot_quad_addr(); /* restricted inet_addr() */
|
||||
+extern char *skip_ipv6_addrs();
|
||||
#endif
|
||||
|
||||
/* Global variables. */
|
56
tcp_wrappers_7.6-ipv6-mapped-v4.patch
Normal file
56
tcp_wrappers_7.6-ipv6-mapped-v4.patch
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
hosts_access.c | 2 +-
|
||||
socket.c | 14 +++++++++-----
|
||||
2 files changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
Index: tcp_wrappers_7.6/hosts_access.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/hosts_access.c
|
||||
+++ tcp_wrappers_7.6/hosts_access.c
|
||||
@@ -461,7 +461,7 @@ char *string;
|
||||
}
|
||||
return ((addr & mask) == net);
|
||||
}
|
||||
-
|
||||
+
|
||||
/* string_match - match string against pattern
|
||||
*
|
||||
* tok = data read from /etc/hosts.*
|
||||
Index: tcp_wrappers_7.6/socket.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/socket.c
|
||||
+++ tcp_wrappers_7.6/socket.c
|
||||
@@ -187,24 +187,28 @@ struct host_info *host;
|
||||
#ifdef INET6
|
||||
struct sockaddr *sin = (struct sockaddr *) host->sin;
|
||||
char *ap;
|
||||
- int alen;
|
||||
+ int af;
|
||||
|
||||
if (!sin)
|
||||
return;
|
||||
- switch (sin->sa_family) {
|
||||
+
|
||||
+ af = sin->sa_family;
|
||||
+ switch (af) {
|
||||
case AF_INET:
|
||||
ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
|
||||
- alen = sizeof(struct in_addr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
|
||||
- alen = sizeof(struct in6_addr);
|
||||
+ if (IN6_IS_ADDR_V4MAPPED(ap)) {
|
||||
+ ap = &((struct in6_addr *) ap)->s6_addr32[3];
|
||||
+ af = AF_INET;
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
host->addr[0] = '\0';
|
||||
- inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
|
||||
+ inet_ntop(af, ap, host->addr, sizeof(host->addr));
|
||||
#else
|
||||
struct sockaddr_in *sin = host->sin;
|
||||
|
297
tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
Normal file
297
tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
Normal file
@ -0,0 +1,297 @@
|
||||
---
|
||||
ip6utils.h | 2 +
|
||||
rfc931.c | 101 +++++++++++++++++++++++++++++++++++++++----------------------
|
||||
scaffold.c | 9 +----
|
||||
socket.c | 14 +-------
|
||||
tcpd.h | 8 +---
|
||||
update.c | 4 +-
|
||||
6 files changed, 76 insertions(+), 62 deletions(-)
|
||||
|
||||
Index: tcp_wrappers_7.6/ip6utils.h
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/ip6utils.h
|
||||
+++ tcp_wrappers_7.6/ip6utils.h
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef IP6UTILS_H
|
||||
#define IP6UTILS_H
|
||||
|
||||
+#include <netinet/in.h>
|
||||
+
|
||||
/* inet_pton_mapped()
|
||||
- works like inet_pton(3) but always returns IPv6 address
|
||||
in dst - either "real" or v4mapped (::ffff:1.2.3.4) in
|
||||
Index: tcp_wrappers_7.6/rfc931.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/rfc931.c
|
||||
+++ tcp_wrappers_7.6/rfc931.c
|
||||
@@ -65,28 +65,69 @@ int sig;
|
||||
siglongjmp(timebuf, sig);
|
||||
}
|
||||
|
||||
+static inline unsigned int
|
||||
+sockaddr_len(const struct sockaddr_storage *ap)
|
||||
+{
|
||||
+ switch (ap->ss_family) {
|
||||
+ case AF_INET:
|
||||
+ return sizeof(struct sockaddr_in);
|
||||
+
|
||||
+ case AF_INET6:
|
||||
+ return sizeof(struct sockaddr_in6);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline unsigned short
|
||||
+sockaddr_port(const struct sockaddr_storage *ap)
|
||||
+{
|
||||
+ unsigned short num;
|
||||
+
|
||||
+ switch (ap->ss_family) {
|
||||
+ case AF_INET:
|
||||
+ num = ((const struct sockaddr_in *) ap)->sin_port;
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ num = ((const struct sockaddr_in6 *) ap)->sin6_port;
|
||||
+ break;
|
||||
+ default:
|
||||
+ num = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ntohs(num);
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+sockaddr_set_port(struct sockaddr_storage *ap, unsigned short port)
|
||||
+{
|
||||
+ unsigned short num = htons(port);
|
||||
+
|
||||
+ switch (ap->ss_family) {
|
||||
+ case AF_INET:
|
||||
+ ((struct sockaddr_in *) ap)->sin_port = num;
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ ((struct sockaddr_in6 *) ap)->sin6_port = num;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* rfc931 - return remote user name, given socket structures */
|
||||
|
||||
void rfc931(rmt_sin, our_sin, dest)
|
||||
-#ifdef INET6
|
||||
-struct sockaddr *rmt_sin;
|
||||
-struct sockaddr *our_sin;
|
||||
-#else
|
||||
-struct sockaddr_in *rmt_sin;
|
||||
-struct sockaddr_in *our_sin;
|
||||
-#endif
|
||||
+struct sockaddr_storage *rmt_sin;
|
||||
+struct sockaddr_storage *our_sin;
|
||||
char *dest;
|
||||
{
|
||||
unsigned rmt_port;
|
||||
unsigned our_port;
|
||||
-#ifdef INET6
|
||||
struct sockaddr_storage rmt_query_sin;
|
||||
struct sockaddr_storage our_query_sin;
|
||||
int alen;
|
||||
-#else
|
||||
- struct sockaddr_in rmt_query_sin;
|
||||
- struct sockaddr_in our_query_sin;
|
||||
-#endif
|
||||
char user[256]; /* XXX */
|
||||
char buffer[512]; /* XXX */
|
||||
char *cp;
|
||||
@@ -97,18 +138,13 @@ char *dest;
|
||||
|
||||
#ifdef INET6
|
||||
/* address family must be the same */
|
||||
- if (rmt_sin->sa_family != our_sin->sa_family) {
|
||||
+ if (rmt_sin->ss_family != our_sin->ss_family) {
|
||||
STRN_CPY(dest, result, STRING_LENGTH);
|
||||
return;
|
||||
}
|
||||
- switch (our_sin->sa_family) {
|
||||
- case AF_INET:
|
||||
- alen = sizeof(struct sockaddr_in);
|
||||
- break;
|
||||
- case AF_INET6:
|
||||
- alen = sizeof(struct sockaddr_in6);
|
||||
- break;
|
||||
- default:
|
||||
+
|
||||
+ alen = sockaddr_len(our_sin);
|
||||
+ if (alen == 0) {
|
||||
STRN_CPY(dest, result, STRING_LENGTH);
|
||||
return;
|
||||
}
|
||||
@@ -125,7 +161,7 @@ char *dest;
|
||||
*/
|
||||
|
||||
#ifdef INET6
|
||||
- if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
|
||||
+ if ((fp = fsocket(our_sin->ss_family, SOCK_STREAM, 0)) != 0) {
|
||||
#else
|
||||
if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
|
||||
#endif
|
||||
@@ -154,18 +190,11 @@ char *dest;
|
||||
*/
|
||||
|
||||
#ifdef INET6
|
||||
- memcpy(&our_query_sin, our_sin, alen);
|
||||
- memcpy(&rmt_query_sin, rmt_sin, alen);
|
||||
- switch (our_sin->sa_family) {
|
||||
- case AF_INET:
|
||||
- ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
|
||||
- ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
|
||||
- break;
|
||||
- case AF_INET6:
|
||||
- ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
|
||||
- ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
|
||||
- break;
|
||||
- }
|
||||
+ our_query_sin = *our_sin;
|
||||
+ sockaddr_set_port(&our_query_sin, ANY_PORT);
|
||||
+
|
||||
+ rmt_query_sin = *rmt_sin;
|
||||
+ sockaddr_set_port(&rmt_query_sin, RFC931_PORT);
|
||||
|
||||
if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
|
||||
alen) >= 0 &&
|
||||
@@ -191,8 +220,8 @@ char *dest;
|
||||
|
||||
fprintf(fp, "%u,%u\r\n",
|
||||
#ifdef INET6
|
||||
- ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
|
||||
- ntohs(((struct sockaddr_in *)our_sin)->sin_port));
|
||||
+ sockaddr_port(rmt_sin),
|
||||
+ sockaddr_port(our_sin));
|
||||
#else
|
||||
ntohs(rmt_sin->sin_port),
|
||||
ntohs(our_sin->sin_port));
|
||||
Index: tcp_wrappers_7.6/scaffold.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/scaffold.c
|
||||
+++ tcp_wrappers_7.6/scaffold.c
|
||||
@@ -336,13 +336,8 @@ struct request_info *request;
|
||||
/* ARGSUSED */
|
||||
|
||||
void rfc931(rmt_sin, our_sin, dest)
|
||||
-#ifndef INET6
|
||||
-struct sockaddr_in *rmt_sin;
|
||||
-struct sockaddr_in *our_sin;
|
||||
-#else
|
||||
-struct sockaddr *rmt_sin;
|
||||
-struct sockaddr *our_sin;
|
||||
-#endif
|
||||
+struct sockaddr_storage *rmt_sin;
|
||||
+struct sockaddr_storage *our_sin;
|
||||
char *dest;
|
||||
{
|
||||
strcpy(dest, unknown);
|
||||
Index: tcp_wrappers_7.6/tcpd.h
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/tcpd.h
|
||||
+++ tcp_wrappers_7.6/tcpd.h
|
||||
@@ -19,11 +19,7 @@
|
||||
struct host_info {
|
||||
char name[STRING_LENGTH]; /* access via eval_hostname(host) */
|
||||
char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */
|
||||
-#ifdef INET6
|
||||
- struct sockaddr *sin; /* socket address or 0 */
|
||||
-#else
|
||||
- struct sockaddr_in *sin; /* socket address or 0 */
|
||||
-#endif
|
||||
+ struct sockaddr_storage *sin; /* socket address or 0 */
|
||||
struct t_unitdata *unit; /* TLI transport address or 0 */
|
||||
struct request_info *request; /* for shared information */
|
||||
};
|
||||
@@ -86,7 +82,7 @@ extern void fromhost(); /* get/validat
|
||||
extern int hosts_access(struct request_info *);
|
||||
extern void shell_cmd(char *);
|
||||
extern char *percent_x(char *, int, char *, struct request_info *);
|
||||
-extern void rfc931(struct sockaddr *, struct sockaddr *, char *);
|
||||
+extern void rfc931(struct sockaddr_storage *, struct sockaddr_storage *, char *);
|
||||
extern void clean_exit(struct request_info *);
|
||||
extern void refuse(struct request_info *);
|
||||
extern char *xgets(char *, int, FILE *);
|
||||
Index: tcp_wrappers_7.6/socket.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/socket.c
|
||||
+++ tcp_wrappers_7.6/socket.c
|
||||
@@ -116,11 +116,7 @@ struct request_info *request;
|
||||
memset(buf, 0 sizeof(buf));
|
||||
#endif
|
||||
}
|
||||
-#ifdef INET6
|
||||
- request->client->sin = (struct sockaddr *)&client;
|
||||
-#else
|
||||
request->client->sin = &client;
|
||||
-#endif
|
||||
|
||||
/*
|
||||
* Determine the server binding. This is used for client username
|
||||
@@ -133,11 +129,7 @@ struct request_info *request;
|
||||
tcpd_warn("getsockname: %m");
|
||||
return;
|
||||
}
|
||||
-#ifdef INET6
|
||||
- request->server->sin = (struct sockaddr *)&server;
|
||||
-#else
|
||||
request->server->sin = &server;
|
||||
-#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +172,7 @@ struct request_info *request;
|
||||
sock_methods(request);
|
||||
|
||||
memcpy(&client, res->ai_addr, res->ai_addrlen);
|
||||
- request->client->sin = (struct sockaddr *)&client;
|
||||
+ request->client->sin = &client;
|
||||
freeaddrinfo(res);
|
||||
|
||||
request->client->name[0] = 0;
|
||||
@@ -193,7 +185,7 @@ void sock_hostaddr(host)
|
||||
struct host_info *host;
|
||||
{
|
||||
#ifdef INET6
|
||||
- struct sockaddr *sin = host->sin;
|
||||
+ struct sockaddr *sin = (struct sockaddr *) host->sin;
|
||||
char *ap;
|
||||
int alen;
|
||||
|
||||
@@ -227,7 +219,7 @@ void
|
||||
sock_hostname(struct host_info *host)
|
||||
{
|
||||
struct addrinfo hints, *res, *resbase;
|
||||
- struct sockaddr *sa = host->sin;
|
||||
+ struct sockaddr *sa = (struct sockaddr *) host->sin;
|
||||
struct sockaddr_in6 *sin6, sin6buf;
|
||||
int errcode;
|
||||
|
||||
Index: tcp_wrappers_7.6/update.c
|
||||
===================================================================
|
||||
--- tcp_wrappers_7.6.orig/update.c
|
||||
+++ tcp_wrappers_7.6/update.c
|
||||
@@ -48,14 +48,14 @@ va_list ap;
|
||||
continue;
|
||||
case RQ_CLIENT_SIN:
|
||||
#ifdef INET6
|
||||
- request->client->sin = va_arg(ap, struct sockaddr *);
|
||||
+ request->client->sin = va_arg(ap, struct sockaddr_storage *);
|
||||
#else
|
||||
request->client->sin = va_arg(ap, struct sockaddr_in *);
|
||||
#endif
|
||||
continue;
|
||||
case RQ_SERVER_SIN:
|
||||
#ifdef INET6
|
||||
- request->server->sin = va_arg(ap, struct sockaddr *);
|
||||
+ request->server->sin = va_arg(ap, struct sockaddr_storage *);
|
||||
#else
|
||||
request->server->sin = va_arg(ap, struct sockaddr_in *);
|
||||
#endif
|
101
tcp_wrappers_7.6-ipv6-subnet.diff
Normal file
101
tcp_wrappers_7.6-ipv6-subnet.diff
Normal file
@ -0,0 +1,101 @@
|
||||
--- hosts_access.c 2014/10/11 17:16:13 1.57
|
||||
+++ hosts_access.c 2014/10/12 16:11:45
|
||||
@@ -367,41 +367,10 @@
|
||||
/* For simplicity we convert everything to IPv6 (or v4 mapped) */
|
||||
struct in6_addr pat, addr;
|
||||
int len, ret, prefixlen=128, nof_periods = 0;
|
||||
- char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition;
|
||||
- len = strlen(tok);
|
||||
- if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
|
||||
- while ((ptok = strchr(ptok, '.')) != NULL){
|
||||
- nof_periods++;
|
||||
- ptok++;
|
||||
- }
|
||||
- switch(nof_periods){
|
||||
- case 1:
|
||||
- addition = "0.0.0/8";
|
||||
- break;
|
||||
- case 2:
|
||||
- addition = "0.0/16";
|
||||
- break;
|
||||
- case 3:
|
||||
- addition = "0/24";
|
||||
- break;
|
||||
- default:
|
||||
- tcpd_warn ("Wrong prefix %s", tok);
|
||||
- return (NO);
|
||||
- }
|
||||
- snprintf(token, sizeof(token), "%s%s", tok, addition);
|
||||
- }
|
||||
- else if (*tok == '[' && tok[len - 1] == ']')
|
||||
- {
|
||||
- ch = tok[len - 1];
|
||||
- tok[len - 1] = '\0';
|
||||
- snprintf(token, sizeof(token), "%s", tok+1);
|
||||
- tok[len - 1] = ch;
|
||||
- }
|
||||
- else
|
||||
- snprintf(token, sizeof(token), "%s", tok);
|
||||
-
|
||||
+ char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition;
|
||||
+
|
||||
/* If prefix was given, handle it */
|
||||
- if ((mask = split_at(token, '/')) != 0)
|
||||
+ if ((mask = split_at(tok, '/')) != 0)
|
||||
{
|
||||
if (strchr(mask, '.') != NULL) /* We have something
|
||||
like 255.255.0.0 */
|
||||
@@ -428,7 +397,7 @@
|
||||
return (NO);
|
||||
}
|
||||
|
||||
- if (is_v4_string (token))
|
||||
+ if (is_v4_string (tok))
|
||||
prefixlen += 96; /* extend to v4mapped */
|
||||
|
||||
if (prefixlen > 128)
|
||||
@@ -437,6 +406,44 @@
|
||||
return (NO);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ len = strlen(tok);
|
||||
+ if (tok[len - 1] == '.') { /* prefix */
|
||||
+ char *ptok = tok;
|
||||
+
|
||||
+ while ((ptok = strchr(ptok, '.')) != NULL){
|
||||
+ nof_periods++;
|
||||
+ ptok++;
|
||||
+ }
|
||||
+ switch(nof_periods){
|
||||
+ case 1:
|
||||
+ addition = "0.0.0";
|
||||
+ prefixlen = 8;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ addition = "0.0";
|
||||
+ prefixlen = 16;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ addition = "0";
|
||||
+ prefixlen = 24;
|
||||
+ break;
|
||||
+ default:
|
||||
+ tcpd_warn ("Wrong prefix %s", tok);
|
||||
+ return (NO);
|
||||
+ }
|
||||
+ snprintf(token, sizeof(token), "%s%s", tok, addition);
|
||||
+ prefixlen += 96; /* extend to v4mapped */
|
||||
+ }
|
||||
+ else if (*tok == '[' && tok[len - 1] == ']')
|
||||
+ {
|
||||
+ ch = tok[len - 1];
|
||||
+ tok[len - 1] = '\0';
|
||||
+ snprintf(token, sizeof(token), "%s", tok+1);
|
||||
+ tok[len - 1] = ch;
|
||||
+ }
|
||||
+ else
|
||||
+ snprintf(token, sizeof(token), "%s", tok);
|
||||
|
||||
memset (&pat, 0, sizeof(pat));
|
||||
memset (&addr, 0, sizeof(addr));
|
11
tcpd.changes
11
tcpd.changes
@ -1,3 +1,14 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Jul 20 14:08:16 UTC 2015 - okir@suse.com
|
||||
|
||||
- Fix breakage of IPv6 address handling [bsc#914527, bsc#899185]
|
||||
Added patches:
|
||||
tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
|
||||
tcp_wrappers_7.6-ipv6-subnet.diff
|
||||
tcp_wrappers_7.6-ipv6-host-match.patch
|
||||
tcp_wrappers_7.6-ipv6-mapped-v4.patch
|
||||
- Re-added static library
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Nov 28 13:18:37 UTC 2014 - tchvatal@suse.com
|
||||
|
||||
|
28
tcpd.spec
28
tcpd.spec
@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package tcpd
|
||||
#
|
||||
# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
%define lname libwrap0
|
||||
|
||||
Name: tcpd
|
||||
Version: 7.6
|
||||
Release: 0
|
||||
@ -56,8 +57,16 @@ Patch26: tcp_wrappers_%{version}-fedora-bug17795.diff
|
||||
Patch27: tcp_wrappers_%{version}-fedora-bug17847.diff
|
||||
Patch28: tcp_wrappers_7.6-implicit-decl.patch
|
||||
Patch29: tcpd-ocloexec.patch
|
||||
Patch30: tcp_wrappers_%{version}-ipv6-sockaddr-storage.patch
|
||||
Patch31: tcp_wrappers_%{version}-ipv6-subnet.diff
|
||||
Patch32: tcp_wrappers_%{version}-ipv6-host-match.patch
|
||||
Patch33: tcp_wrappers_%{version}-ipv6-mapped-v4.patch
|
||||
BuildRequires: linux-kernel-headers
|
||||
Provides: nkitb:%{_sbindir}/tcpd
|
||||
# bug437293
|
||||
%ifarch ppc64
|
||||
Obsoletes: tcpd-64bit
|
||||
%endif
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
%description
|
||||
@ -78,6 +87,11 @@ Summary: Include Files and Libraries for the TCP wrapper library
|
||||
Group: Development/Languages/C and C++
|
||||
Requires: %{lname} = %{version}
|
||||
Requires: glibc-devel
|
||||
# bug437293
|
||||
%ifarch ppc64
|
||||
Obsoletes: tcpd-devel-64bit
|
||||
%endif
|
||||
#
|
||||
|
||||
%description devel
|
||||
This package contains the library and header files, which are necessary
|
||||
@ -115,9 +129,13 @@ to compile and link programs against the TCP wrapper library.
|
||||
%patch27
|
||||
%patch28
|
||||
%patch29
|
||||
%patch30 -p1
|
||||
%patch31
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags} linux CC=cc
|
||||
make %{?_smp_mflags} linux CC="cc"
|
||||
|
||||
%install
|
||||
install -d -m 755 %{buildroot}%{_includedir}
|
||||
@ -126,6 +144,7 @@ install -d -m 755 %{buildroot}%{_sbindir}
|
||||
install -d -m 755 %{buildroot}%{_mandir}/man{1,3,5,8}
|
||||
install -d -m 755 %{buildroot}/%{_lib}
|
||||
install -m 644 ip6utils.h tcpd.h %{buildroot}%{_includedir}
|
||||
install -m 644 libwrap.a %{buildroot}/%{_libdir}
|
||||
install -m 755 safe_finger tcpd tcpdchk tcpdmatch try-from %{buildroot}%{_sbindir}
|
||||
install -m 644 hosts_access.3 %{buildroot}%{_mandir}/man3
|
||||
install -m 644 hosts_access.5 hosts_options.5 %{buildroot}%{_mandir}/man5
|
||||
@ -141,7 +160,7 @@ ln -sf /%{_lib}/libwrap.so.0.%{version} libwrap.so
|
||||
%postun -n %{lname} -p /sbin/ldconfig
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%defattr(644,root,root,755)
|
||||
%doc BLURB CHANGES DISCLAIMER README README.ipv6 README.NIS
|
||||
%doc %{_mandir}/man?/*
|
||||
%attr(755,root,root) %{_sbindir}/*
|
||||
@ -152,9 +171,10 @@ ln -sf /%{_lib}/libwrap.so.0.%{version} libwrap.so
|
||||
%attr(755,root,root) /%{_lib}/libwrap.so.0*
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
%defattr(644,root,root,755)
|
||||
%{_includedir}/tcpd.h
|
||||
%{_includedir}/ip6utils.h
|
||||
%{_libdir}/libwrap.a
|
||||
%{_libdir}/libwrap.so
|
||||
|
||||
%changelog
|
||||
|
Loading…
Reference in New Issue
Block a user