https://bugzilla.novell.com/show_bug.cgi?id=861989
https://bugzilla.novell.com/show_bug.cgi?id=861989#c0
Summary: libwrap0 gives invalid ipv4 checks -- disabling
security required
Classification: openSUSE
Product: openSUSE 13.1
Version: Final
Platform: All
OS/Version: openSUSE 13.1
Status: NEW
Severity: Major
Priority: P5 - None
Component: Security
AssignedTo: security-team@suse.de
ReportedBy: suse@tlinx.org
QAContact: qa-bugs@suse.de
Found By: ---
Blocker: ---
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.28)
Gecko/20120306 Firefox/3.6.28
libwrap0 gives invalid results for ipv4 checks.
This requires turning the host wrapper checks into warnings, which
compromises security. Example:
Since I upgraded to the new libwrap0 (I had patched this and noted this problem
before, but the patch didn't make it into the new version):
Jan 31 18:51:40 Ishtar sshd[51467]: warning: /etc/hosts.allow, line 63: host
name mismatch: Ishtar.tlinx.org != (null) (::ffff:192.168.3.1)
Jan 31 18:51:40 Ishtar sshd[51469]: warning: /etc/hosts.allow, line 63: host
name mismatch: Ishtar.tlinx.org != (null) (::ffff:192.168.3.1)
Jan 31 18:51:42 Ishtar xinetd[51471]: warning: /etc/hosts.allow, line 63: host
name mismatch: Ishtar.tlinx.org != (null) (::ffff:192.168.3.1)
Jan 31 18:51:42 Ishtar xinetd[51472]: warning: /etc/hosts.allow, line 63: host
name mismatch: Ishtar.tlinx.org != (null) (::ffff:192.168.3.1)
Jan 31 19:46:51 Ishtar sshd[57295]: warning: /etc/hosts.allow, line 63: host
name mismatch: Athenae != (null) (::ffff:192.168.4.12)
Feb 1 23:32:57 Ishtar sshd[20335]: warning: /etc/hosts.allow, line 63: host
name mismatch: Athenae != (null) (::ffff:192.168.4.12)
Feb 2 10:59:50 Ishtar sshd[31950]: warning: /etc/hosts.allow, line 63: host
name mismatch: Athenae != (null) (::ffff:192.168.4.12)
Feb 3 10:51:02 Ishtar sshd[6633]: warning: /etc/hosts.allow, line 63: host
name mismatch: Athenae != (null) (::ffff:192.168.4.12)
----
I do not have ipv6 enabled and do not have ipv6 addresses being returned
from my bind/named server.
Athenae properly resolves:
dig +short Athenae
192.168.4.12
As does Ishtar.tlinx.org
dig +short Ishtar.tlinx.org
173.164.175.65
What I am not sure of since libwrap shows Ishtar.tlinx.org as mapping to
null is if it really meant Ishtar:
dig +short Ishtar
192.168.4.1
-- 192.168.3.1 is also valid from some machines -- so that mapping
doesn't bother me so much -- but the thing is, with libwrap0 having
to be set to warn-only due to the above bug, it won't fail on wrong
resolutions.
I.e. because of the bogus check output -- it has to be set to warn --
which may be allowing things to pass that shouldn't.
Reproducible: Always
Steps to Reproduce:
1.
2.
3.
It might require a kernel with IPv6 disabled/not compiled in -- not sure.
named should only return ipv4 records as they are the ones that are being
mangled
In my /etc/hosts.allow, I have:
ALL: LOCAL, 192.168.4.0/255.255.255.0, 192.168.3.0/255.255.255.0 : ALLOW
Actual Results:
actual results are the bogus warning.
Note -- from the tcpd manpage --
If the sources are compiled with -DPARANOID, tcpd will drop the connec-
tion in case of a host name/address mismatch. Otherwise, the hostname
can be matched with the PARANOID wildcard, after which suitable action
can be taken.
----------
I.e. I seem to remember that with paranoid wildcard, it would drop instead
of warn.
Expected Results:
no errors on valid hostsnames..
For some reason I can't get the attachment function to work...
so will have to include it manually, but the "attachment" is a patch
for the tcpd source from 13.1
(spec file had added:
Patch30: socket-tcp.diff
%patch30
at appropriate places (after #29)...
diff file included in additional information.
--- socket.c 2013-05-23 14:08:58.000000000 -0700
+++ socket.c 2013-05-23 16:28:40.415779720 -0700
@@ -22,6 +22,8 @@
/* System libraries. */
#include
+#include
+#include
#include
#include
#include
@@ -38,6 +40,21 @@
#include "tcpd.h"
+
+static int ipv6_cached = -1;
+
+int ipv6 () {
+ int errstat;
+ struct stat buf;
+ if (ipv6_cached==-1) {
+ errstat=stat("/proc/sys/net/ipv6", &buf);
+ if (errstat==0 /* && (buf->mode_t & S_IFDIR)*/) ipv6_cached=1;
+ else ipv6_cached=0;
+ }
+ return ipv6_cached;
+}
+
+
/* Forward declarations. */
static void sock_sink();
@@ -66,10 +83,10 @@
} else {
sprintf(dot_name, "%s.", name);
hp = gethostbyname(dot_name);
- if (hp)
- return hp;
- else
- return (gethostbyname(name));
+ if (hp)
+ return hp;
+ else
+ return (gethostbyname(name));
}
}
@@ -79,15 +96,15 @@
/* sock_host - look up endpoint addresses and install conversion methods */
void sock_host(request)
-struct request_info *request;
-{
-#ifdef INET6
- static struct sockaddr_storage client;
- static struct sockaddr_storage server;
-#else
+struct request_info *request; {
+ static struct sockaddr_storage client6;
+ static struct sockaddr_storage server6;
static struct sockaddr_in client;
static struct sockaddr_in server;
-#endif
+
+ void * clientx = ipv6() ? &client6 : &client;
+ void * serverx = ipv6() ? &server6 : &server;
+
int len;
char buf[BUFSIZ];
int fd = request->fd;
@@ -103,12 +120,12 @@
* broken library code.
*/
- len = sizeof(client);
- if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) {
+ len = ipv6() ? sizeof(client6) : sizeof(client);
+ if (getpeername(fd, (struct sockaddr *) clientx, &len) < 0) {
request->sink = sock_sink;
- len = sizeof(client);
+ len = ipv6() ? sizeof(client6) : sizeof(client);
if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
- (struct sockaddr *) & client, &len) < 0) {
+ (struct sockaddr *) clientx, &len) < 0) {
tcpd_warn("can't get client address: %m");
return; /* give up */
}
@@ -116,11 +133,8 @@
memset(buf, 0 sizeof(buf));
#endif
}
-#ifdef INET6
- request->client->sin = (struct sockaddr *)&client;
-#else
- request->client->sin = &client;
-#endif
+
+ request->client->sin = (struct sockaddr *)clientx;
/*
* Determine the server binding. This is used for client username
@@ -128,16 +142,13 @@
* address or name.
*/
- len = sizeof(server);
- if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
+ len = ipv6() ? sizeof(server6) : sizeof(server);
+ if (getsockname(fd, (struct sockaddr *) serverx, &len) < 0) {
tcpd_warn("getsockname: %m");
return;
}
-#ifdef INET6
- request->server->sin = (struct sockaddr *)&server;
-#else
- request->server->sin = &server;
-#endif
+
+ request->server->sin = (struct sockaddr *)serverx;
}
@@ -156,34 +167,35 @@
* field is empty or unknown, use the address field to get the sockaddr
* and hostname. */
if (strlen(request->client->addr) &&
- HOSTNAME_KNOWN(request->client->addr) &&
- (!strlen(request->client->addr) ||
- !HOSTNAME_KNOWN(request->client->name)))
- host = request->client->addr;
+ HOSTNAME_KNOWN(request->client->addr) &&
+ (!strlen(request->client->addr) ||
+ !HOSTNAME_KNOWN(request->client->name)))
+ host = request->client->addr;
else
- return;
+ return;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET6;
+
+ hints.ai_family = ipv6() ? AF_INET6 : AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
ret = getaddrinfo(host, NULL, &hints, &res);
if (ret != 0) {
- hints.ai_family = AF_INET;
- ret = getaddrinfo(host, NULL, &hints, &res);
+ hints.ai_family = AF_INET;
+ ret = getaddrinfo(host, NULL, &hints, &res);
}
if (ret != 0) {
- tcpd_warn("can't resolve hostname (%s): %s", host, gai_strerror(ret));
+ tcpd_warn("can't resolve hostname (%s): %s", host, gai_strerror(ret));
} else {
- sock_methods(request);
+ sock_methods(request);
- memcpy(&client, res->ai_addr, res->ai_addrlen);
- request->client->sin = (struct sockaddr *)&client;
- freeaddrinfo(res);
+ memcpy(&client, res->ai_addr, res->ai_addrlen);
+ request->client->sin = (struct sockaddr *)&client;
+ freeaddrinfo(res);
- request->client->name[0] = 0;
+ request->client->name[0] = 0;
}
}
@@ -192,39 +204,37 @@
void sock_hostaddr(host)
struct host_info *host;
{
-#ifdef INET6
- struct sockaddr *sin = host->sin;
- char *ap;
- int alen;
+ if (ipv6()) {
+ struct sockaddr *sin = host->sin;
+ char *ap;
+ int alen;
- if (!sin)
- return;
- switch (sin->sa_family) {
- 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);
- break;
- default:
+ if (!sin)
return;
- }
- host->addr[0] = '\0';
- inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
-#else
- struct sockaddr_in *sin = host->sin;
+ switch (sin->sa_family) {
+ 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);
+ break;
+ default:
+ return;
+ }
+ host->addr[0] = '\0';
+ inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
+ } else {
+ struct sockaddr_in *sin = host->sin;
- if (sin != 0)
- STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
-#endif
+ if (sin != 0)
+ STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
+ }
}
-#ifdef INET6
/* sock_hostname - map endpoint address to host name */
-void
-sock_hostname(struct host_info *host)
+void sock_hostname6(struct host_info *host)
{
struct addrinfo hints, *res, *resbase;
struct sockaddr *sa = host->sin;
@@ -330,7 +340,7 @@
host->name,
inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr));
strncpy(host->name, paranoid, sizeof(host->name));
- freeaddrinfo (resbase);
+ freeaddrinfo (resbase);
return;
}
@@ -344,8 +354,8 @@
freeaddrinfo (resbase);
return;
}
-#else /* INET6 */
-void sock_hostname(host)
+
+void sock_hostname4(host)
struct host_info *host;
{
struct sockaddr_in *sin = host->sin;
@@ -428,7 +438,10 @@
strcpy(host->name, paranoid); /* name is bad, clobber it */
}
}
-#endif /* INET6 */
+
+void sock_hostname(struct host_info *host) {
+ ipv6()? sock_hostname6(host) :sock_hostname4(host);
+}
/* sock_sink - absorb unreceived IP datagram */
@@ -436,17 +449,18 @@
int fd;
{
char buf[BUFSIZ];
-#ifdef INET6
- struct sockaddr_storage sin;
-#else
+
+ struct sockaddr_storage sin6;
struct sockaddr_in sin;
-#endif
- int size = sizeof(sin);
+
+ void * sinx = ipv6() ? &sin6 : &sin;
+
+ int size = ipv6()? sizeof(sin6): sizeof(sin);
/*
* Eat up the not-yet received datagram. Some systems insist on a
* non-zero source address argument in the recvfrom() call below.
*/
- (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin,
&size);
+ (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) sinx, &size);
}
--
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.