summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libwrap/Makefile3
-rw-r--r--lib/libwrap/fix_options.c18
-rw-r--r--lib/libwrap/hosts_access.527
-rw-r--r--lib/libwrap/hosts_access.c100
-rw-r--r--lib/libwrap/misc.c28
-rw-r--r--lib/libwrap/rfc931.c98
-rw-r--r--lib/libwrap/socket.c86
-rw-r--r--lib/libwrap/tcpd.h6
-rw-r--r--lib/libwrap/update.c8
-rw-r--r--libexec/tcpd/Makefile.inc3
-rw-r--r--libexec/tcpd/tcpdchk/scaffold.c63
-rw-r--r--libexec/tcpd/tcpdchk/tcpdchk.c38
-rw-r--r--libexec/tcpd/tcpdmatch/tcpdmatch.c58
13 files changed, 460 insertions, 76 deletions
diff --git a/lib/libwrap/Makefile b/lib/libwrap/Makefile
index 2da18026bf6..99cba9a7137 100644
--- a/lib/libwrap/Makefile
+++ b/lib/libwrap/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.3 1997/04/27 20:56:19 millert Exp $
+# $OpenBSD: Makefile,v 1.4 2000/10/14 00:56:15 itojun Exp $
LIB= wrap
SRCS= hosts_access.c options.c shell_cmd.c rfc931.c eval.c \
@@ -12,6 +12,7 @@ CFLAGS+=-DPROCESS_OPTIONS -DFACILITY=LOG_AUTH -DSEVERITY=LOG_INFO \
-DRFC931_TIMEOUT=10 -DHOSTS_ACCESS -DALWAYS_HOSTNAME \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" \
-DNETGROUP -DSYS_ERRLIST_DEFINED -D_TCPD_PRIVATE
+CFLAGS+=-DINET6
MAN= hosts_access.3 hosts_access.5 hosts_options.5
MLINKS+=hosts_access.5 hosts.allow.5
diff --git a/lib/libwrap/fix_options.c b/lib/libwrap/fix_options.c
index 48e95972de4..a5de0f52e46 100644
--- a/lib/libwrap/fix_options.c
+++ b/lib/libwrap/fix_options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fix_options.c,v 1.2 1997/04/04 09:06:28 deraadt Exp $ */
+/* $OpenBSD: fix_options.c,v 1.3 2000/10/14 00:56:15 itojun Exp $ */
/*
* Routine to disable IP-level socket options. This code was taken from 4.4BSD
@@ -11,7 +11,7 @@
#if 0
static char sccsid[] = "@(#) fix_options.c 1.4 97/02/12 02:13:22";
#else
-static char rcsid[] = "$OpenBSD: fix_options.c,v 1.2 1997/04/04 09:06:28 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: fix_options.c,v 1.3 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -49,7 +49,21 @@ struct request_info *request;
int fd = request->fd;
unsigned int opt;
int optlen, i;
+ struct sockaddr_storage ss;
+ int sslen;
+ /*
+ * check if this is AF_INET socket
+ * XXX IPv6 support?
+ */
+ sslen = sizeof(ss);
+ if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
+ syslog(LOG_ERR, "getpeername: %m");
+ clean_exit(request);
+ }
+ if (ss.ss_family != AF_INET)
+ return;
+
if ((ip = getprotobyname("ip")) != 0)
ipproto = ip->p_proto;
else
diff --git a/lib/libwrap/hosts_access.5 b/lib/libwrap/hosts_access.5
index da3dbb54e20..7b59f26e366 100644
--- a/lib/libwrap/hosts_access.5
+++ b/lib/libwrap/hosts_access.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: hosts_access.5,v 1.8 2000/03/14 21:31:41 aaron Exp $
+.\" $OpenBSD: hosts_access.5,v 1.9 2000/10/14 00:56:15 itojun Exp $
.\"
.\" Copyright (c) 1997, Jason Downs. All rights reserved.
.\"
@@ -107,6 +107,8 @@ values) or wildcards (see below).
.Ar client_list
is a list of one or more host names, host addresses, patterns or wildcards (see
below) that will be matched against the client host name or address.
+When a client_list item needs to include colon character (for IPv6 addresses),
+the item needs to be wrapped with square bracket.
.Pp
The more complex forms
.Ar daemon@host
@@ -169,6 +171,26 @@ matches every address in the range
.Sq 131.155.72.0
through
.Sq 131.155.73.255 .
+Note that
+.Sq m.m.m.m
+portion must always be specified.
+.It
+An expression of the form
+.Sq ipv6-addr/ipv6-mask
+is interpreted as masked IPv6 address match,
+just like masked IPv4 address match (see above).
+Note that
+.Sq ipv6-mask
+portion must always be specified.
+.It
+An expression of the form
+.Sq ipv6-addr/prefixlen
+is interpreted as masked IPv6 address match
+(with mask specified by numeric prefixlen),
+just like masked IPv4 address match (see above).
+Note that
+.Sq prefixlen
+portion must always be specified.
.El
.Sh WILDCARDS
The access control language supports explicit wildcards:
@@ -486,6 +508,9 @@ to the access control software, even though the host is registered.
.Pp
Domain name server lookups are case insensitive; NIS (formerly YP)
netgroup lookups are case sensitive.
+.Pp
+The total length of an entry can be no more than 2047 characters long,
+including the final newline.
.Sh AUTHOR
.Bd -unfilled -offset indent
Wietse Venema (wietse@wzv.win.tue.nl)
diff --git a/lib/libwrap/hosts_access.c b/lib/libwrap/hosts_access.c
index a63a8deb90d..4b43e07b39f 100644
--- a/lib/libwrap/hosts_access.c
+++ b/lib/libwrap/hosts_access.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hosts_access.c,v 1.5 2000/02/01 03:23:17 deraadt Exp $ */
+/* $OpenBSD: hosts_access.c,v 1.6 2000/10/14 00:56:15 itojun Exp $ */
/*
* This module implements a simple access control language that is based on
@@ -23,7 +23,7 @@
#if 0
static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
#else
-static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.5 2000/02/01 03:23:17 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.6 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -31,6 +31,9 @@ static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.5 2000/02/01 03:23:17 deraad
#include <sys/types.h>
#include <sys/param.h>
+#ifdef INET6
+#include <sys/socket.h>
+#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
@@ -89,6 +92,10 @@ static int client_match();
static int host_match();
static int string_match();
static int masked_match();
+static int masked_match4();
+#ifdef INET6
+static int masked_match6();
+#endif
/* Size of logical line buffer. */
@@ -195,6 +202,7 @@ struct request_info *request;
int (*match_fn) ();
{
char *tok;
+ int l;
/*
* Process tokens one at a time. We have exhausted all possible matches
@@ -206,6 +214,11 @@ int (*match_fn) ();
for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
if (STR_EQ(tok, "EXCEPT")) /* EXCEPT: give up */
return (NO);
+ l = strlen(tok);
+ if (*tok == '[' && tok[l - 1] == ']') {
+ tok[l - 1] = '\0';
+ tok++;
+ }
if (match_fn(tok, request)) { /* YES: look for exceptions */
while ((tok = strtok((char *) 0, sep)) && STR_NE(tok, "EXCEPT"))
/* VOID */ ;
@@ -317,6 +330,23 @@ char *net_tok;
char *mask_tok;
char *string;
{
+#ifndef INET6
+ return masked_match4(net_tok, mask_tok, string);
+#else
+ if (dot_quad_addr_new(net_tok, NULL)
+ && dot_quad_addr_new(mask_tok, NULL)
+ && dot_quad_addr_new(string, NULL)) {
+ return masked_match4(net_tok, mask_tok, string);
+ } else
+ return masked_match6(net_tok, mask_tok, string);
+#endif
+}
+
+static int masked_match4(net_tok, mask_tok, string)
+char *net_tok;
+char *mask_tok;
+char *string;
+{
in_addr_t net;
in_addr_t mask;
in_addr_t addr;
@@ -336,3 +366,69 @@ char *string;
}
return ((addr & mask) == net);
}
+
+#ifdef INET6
+/* Ugly because it covers IPv4 mapped address. I hate mapped addresses. */
+static int masked_match6(net_tok, mask_tok, string)
+char *net_tok;
+char *mask_tok;
+char *string;
+{
+ struct in6_addr net;
+ struct in6_addr mask;
+ struct in6_addr addr;
+ int masklen;
+ int fail;
+ int i;
+ int maskoff;
+ int netaf;
+ const int sizoff64 = sizeof(struct in6_addr) - sizeof(struct in_addr);
+
+ memset(&addr, 0, sizeof(addr));
+ if (inet_pton(AF_INET6, string, &addr) == 1)
+ ; /* okay */
+ else if (inet_pton(AF_INET, string, &addr.s6_addr[sizoff64]) == 1)
+ addr.s6_addr[10] = addr.s6_addr[11] = 0xff;
+ else
+ return NO;
+
+ memset(&net, 0, sizeof(net));
+ if (inet_pton(AF_INET6, net_tok, &net) == 1) {
+ netaf = AF_INET6;
+ maskoff = 0;
+ } else if (inet_pton(AF_INET, net_tok, &net.s6_addr[sizoff64]) == 1) {
+ netaf = AF_INET;
+ maskoff = sizoff64;
+ net.s6_addr[10] = net.s6_addr[11] = 0xff;
+ } else
+ return NO;
+
+ fail = 0;
+ if (mask_tok[strspn(mask_tok, "0123456789")] == '\0') {
+ masklen = atoi(mask_tok) + maskoff * 8;
+ if (0 <= masklen && masklen <= 128) {
+ memset(&mask, 0, sizeof(mask));
+ memset(&mask, 0xff, masklen / 8);
+ if (masklen % 8) {
+ ((u_char *)&mask)[masklen / 8] =
+ (0xff00 >> (masklen % 8)) & 0xff;
+ }
+ } else
+ fail++;
+ } else if (netaf == AF_INET6 && inet_pton(AF_INET6, mask_tok, &mask) == 1)
+ ; /* okay */
+ else if (netaf == AF_INET
+ && inet_pton(AF_INET, mask_tok, &mask.s6_addr[12]) == 1) {
+ memset(&mask, 0xff, sizoff64);
+ } else
+ fail++;
+ if (fail) {
+ tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
+ return (NO); /* not tcpd_jump() */
+ }
+
+ for (i = 0; i < sizeof(addr); i++)
+ addr.s6_addr[i] &= mask.s6_addr[i];
+ return (memcmp(&addr, &net, sizeof(addr)) == 0);
+}
+#endif
diff --git a/lib/libwrap/misc.c b/lib/libwrap/misc.c
index 69e7ac1c086..3ba0caaf023 100644
--- a/lib/libwrap/misc.c
+++ b/lib/libwrap/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.3 1999/06/06 15:34:44 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.4 2000/10/14 00:56:15 itojun Exp $ */
/*
* Misc routines that are used by tcpd and by tcpdchk.
@@ -10,7 +10,7 @@
#if 0
static char sccsic[] = "@(#) misc.c 1.2 96/02/11 17:01:29";
#else
-static char rcsid[] = "$OpenBSD: misc.c,v 1.3 1999/06/06 15:34:44 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: misc.c,v 1.4 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -60,11 +60,35 @@ char *split_at(string, delimiter)
char *string;
int delimiter;
{
+#if 0
char *cp;
if ((cp = strchr(string, delimiter)) != 0)
*cp++ = 0;
return (cp);
+#else
+ char *cp;
+ int bracket;
+
+ bracket = 0;
+ for (cp = string; cp && *cp; cp++) {
+ switch (*cp) {
+ case '[':
+ bracket++;
+ break;
+ case ']':
+ bracket--;
+ break;
+ default:
+ if (bracket == 0 && *cp == delimiter) {
+ *cp++ = 0;
+ return cp;
+ }
+ break;
+ }
+ }
+ return NULL;
+#endif
}
/* dot_quad_addr_new - convert dotted quad to internal form */
diff --git a/lib/libwrap/rfc931.c b/lib/libwrap/rfc931.c
index 4bb94294e6c..8986d105a88 100644
--- a/lib/libwrap/rfc931.c
+++ b/lib/libwrap/rfc931.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rfc931.c,v 1.1 1997/02/26 03:06:56 downsj Exp $ */
+/* $OpenBSD: rfc931.c,v 1.2 2000/10/14 00:56:15 itojun Exp $ */
/*
* rfc931() speaks a common subset of the RFC 931, AUTH, TAP, IDENT and RFC
@@ -15,7 +15,7 @@
#if 0
static char sccsid[] = "@(#) rfc931.c 1.10 95/01/02 16:11:34";
#else
-static char rcsid[] = "$OpenBSD: rfc931.c,v 1.1 1997/02/26 03:06:56 downsj Exp $";
+static char rcsid[] = "$OpenBSD: rfc931.c,v 1.2 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -75,19 +75,61 @@ int sig;
/* rfc931 - return remote user name, given socket structures */
void rfc931(rmt_sin, our_sin, dest)
-struct sockaddr_in *rmt_sin;
-struct sockaddr_in *our_sin;
+struct sockaddr *rmt_sin;
+struct sockaddr *our_sin;
char *dest;
{
unsigned rmt_port;
unsigned our_port;
- struct sockaddr_in rmt_query_sin;
- struct sockaddr_in our_query_sin;
+ struct sockaddr_storage rmt_query_sin;
+ struct sockaddr_storage our_query_sin;
char user[256]; /* XXX */
char buffer[512]; /* XXX */
char *cp;
char *result = unknown;
FILE *fp;
+ int salen;
+ u_short *rmt_portp;
+ u_short *our_portp;
+
+ /* address family must be the same */
+ if (rmt_sin->sa_family != our_sin->sa_family) {
+ STRN_CPY(dest, result, STRING_LENGTH);
+ return;
+ }
+ switch (rmt_sin->sa_family) {
+ case AF_INET:
+ salen = sizeof(struct sockaddr_in);
+ rmt_portp = &((struct sockaddr_in *)&rmt_sin)->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ salen = sizeof(struct sockaddr_in6);
+ rmt_portp = &((struct sockaddr_in6 *)&rmt_sin)->sin6_port;
+ break;
+#endif
+ default:
+ STRN_CPY(dest, result, STRING_LENGTH);
+ return;
+ }
+ switch (our_sin->sa_family) {
+ case AF_INET:
+ our_portp = &((struct sockaddr_in *)&our_sin)->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ our_portp = &((struct sockaddr_in6 *)&our_sin)->sin6_port;
+ break;
+#endif
+ default:
+ STRN_CPY(dest, result, STRING_LENGTH);
+ return;
+ }
+
+#ifdef __GNUC__
+ (void)&result; /* Avoid longjmp clobbering */
+ (void)&fp; /* XXX gcc */
+#endif
/*
* Use one unbuffered stdio stream for writing to and for reading from
@@ -99,7 +141,7 @@ char *dest;
* sockets.
*/
- if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
+ if ((fp = fsocket(rmt_sin->sa_family, SOCK_STREAM, 0)) != 0) {
setbuf(fp, (char *) 0);
/*
@@ -119,15 +161,37 @@ char *dest;
* addresses from the query socket.
*/
- our_query_sin = *our_sin;
- our_query_sin.sin_port = htons(ANY_PORT);
- rmt_query_sin = *rmt_sin;
- rmt_query_sin.sin_port = htons(RFC931_PORT);
+ memcpy(&our_query_sin, our_sin, salen);
+ switch (our_query_sin.ss_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&our_query_sin)->sin_port =
+ htons(ANY_PORT);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&our_query_sin)->sin6_port =
+ htons(ANY_PORT);
+ break;
+#endif
+ }
+ memcpy(&rmt_query_sin, rmt_sin, salen);
+ switch (rmt_query_sin.ss_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&rmt_query_sin)->sin_port =
+ htons(RFC931_PORT);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port =
+ htons(RFC931_PORT);
+ break;
+#endif
+ }
if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
- sizeof(our_query_sin)) >= 0 &&
+ salen) >= 0 &&
connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
- sizeof(rmt_query_sin)) >= 0) {
+ salen) >= 0) {
/*
* Send query to server. Neglect the risk that a 13-byte
@@ -136,8 +200,8 @@ char *dest;
*/
fprintf(fp, "%u,%u\r\n",
- ntohs(rmt_sin->sin_port),
- ntohs(our_sin->sin_port));
+ ntohs(*rmt_portp),
+ ntohs(*our_portp));
fflush(fp);
/*
@@ -151,8 +215,8 @@ char *dest;
&& ferror(fp) == 0 && feof(fp) == 0
&& sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
&rmt_port, &our_port, user) == 3
- && ntohs(rmt_sin->sin_port) == rmt_port
- && ntohs(our_sin->sin_port) == our_port) {
+ && ntohs(*rmt_portp) == rmt_port
+ && ntohs(*our_portp) == our_port) {
/*
* Strip trailing carriage return. It is part of the
diff --git a/lib/libwrap/socket.c b/lib/libwrap/socket.c
index ac6e1367f26..46e24cec8a6 100644
--- a/lib/libwrap/socket.c
+++ b/lib/libwrap/socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: socket.c,v 1.2 1997/06/01 05:22:08 downsj Exp $ */
+/* $OpenBSD: socket.c,v 1.3 2000/10/14 00:56:15 itojun Exp $ */
/*
* This module determines the type of socket (datagram, stream), the client
@@ -21,7 +21,7 @@
#if 0
static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
#else
-static char rcsid[] = "$OpenBSD: socket.c,v 1.2 1997/06/01 05:22:08 downsj Exp $";
+static char rcsid[] = "$OpenBSD: socket.c,v 1.3 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -79,8 +79,8 @@ char *name;
void sock_host(request)
struct request_info *request;
{
- static struct sockaddr_in client;
- static struct sockaddr_in server;
+ static struct sockaddr_storage client;
+ static struct sockaddr_storage server;
int len;
char buf[BUFSIZ];
int fd = request->fd;
@@ -94,6 +94,8 @@ struct request_info *request;
* really should verify that client.sin_family gets the value AF_INET,
* but this program has already caused too much grief on systems with
* broken library code.
+ *
+ * XXX the last sentence is untrue as we support AF_INET6 as well :-)
*/
len = sizeof(client);
@@ -109,7 +111,7 @@ struct request_info *request;
memset(buf, 0 sizeof(buf));
#endif
}
- request->client->sin = &client;
+ request->client->sin = (struct sockaddr *)&client;
/*
* Determine the server binding. This is used for client username
@@ -122,7 +124,7 @@ struct request_info *request;
tcpd_warn("getsockname: %m");
return;
}
- request->server->sin = &server;
+ request->server->sin = (struct sockaddr *)&server;
}
/* sock_hostaddr - map endpoint address to printable form */
@@ -130,10 +132,28 @@ struct request_info *request;
void sock_hostaddr(host)
struct host_info *host;
{
- struct sockaddr_in *sin = host->sin;
+ struct sockaddr *sa = host->sin;
+ int alen, af;
+ char *ap;
- if (sin != 0)
- STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
+ if (!sa)
+ return;
+ switch (af = sa->sa_family) {
+ case AF_INET:
+ ap = (char *)&((struct sockaddr_in *)sa)->sin_addr;
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)sa)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ return;
+ }
+ host->addr[0] = '\0';
+ inet_ntop(af, ap, host->addr, sizeof(host->addr));
}
/* sock_hostname - map endpoint address to host name */
@@ -141,9 +161,12 @@ struct host_info *host;
void sock_hostname(host)
struct host_info *host;
{
- struct sockaddr_in *sin = host->sin;
+ struct sockaddr *sin = host->sin;
struct hostent *hp;
int i;
+ int af, alen;
+ char *ap;
+ char hbuf[MAXHOSTNAMELEN];
/*
* On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
@@ -152,9 +175,31 @@ struct host_info *host;
* have to special-case 0.0.0.0, in order to avoid false alerts from the
* host name/address checking code below.
*/
- if (sin != 0 && sin->sin_addr.s_addr != 0
- && (hp = gethostbyaddr((char *) &(sin->sin_addr),
- sizeof(sin->sin_addr), AF_INET)) != 0) {
+ if (!sin)
+ return;
+ switch (af = sin->sa_family) {
+ case AF_INET:
+ if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0)
+ return;
+ ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ /* special case on reverse lookup: mapped addr. I hate it */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ af = AF_INET;
+ ap += (sizeof(struct in6_addr) - sizeof(struct in_addr));
+ alen = sizeof(struct in_addr);
+ }
+ break;
+#endif
+ default:
+ return;
+ }
+ if ((hp = gethostbyaddr(ap, alen, af)) != 0) {
STRN_CPY(host->name, hp->h_name, sizeof(host->name));
@@ -171,15 +216,15 @@ struct host_info *host;
* we're in big trouble anyway.
*/
- if ((hp = gethostbyname(host->name)) == 0) {
+ if ((hp = gethostbyname2(host->name, af)) == 0) {
/*
* Unable to verify that the host name matches the address. This
* may be a transient problem or a botched name server setup.
*/
- tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
- host->name);
+ tcpd_warn("can't verify hostname: gethostbyname2(%s, %d) failed",
+ host->name, af);
} else if (STR_NE(host->name, hp->h_name)
&& STR_NE(host->name, "localhost")) {
@@ -203,9 +248,7 @@ struct host_info *host;
*/
for (i = 0; hp->h_addr_list[i]; i++) {
- if (memcmp(hp->h_addr_list[i],
- (char *) &sin->sin_addr,
- sizeof(sin->sin_addr)) == 0)
+ if (memcmp(hp->h_addr_list[i], (char *) ap, alen) == 0)
return; /* name is good, keep it */
}
@@ -216,7 +259,8 @@ struct host_info *host;
*/
tcpd_warn("host name/address mismatch: %s != %.*s",
- inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
+ inet_ntop(af, ap, hbuf, sizeof(hbuf)),
+ STRING_LENGTH, hp->h_name);
}
strcpy(host->name, paranoid); /* name is bad, clobber it */
}
@@ -228,7 +272,7 @@ static void sock_sink(fd)
int fd;
{
char buf[BUFSIZ];
- struct sockaddr_in sin;
+ struct sockaddr_storage sin;
int size = sizeof(sin);
/*
diff --git a/lib/libwrap/tcpd.h b/lib/libwrap/tcpd.h
index 3a12a3c92c2..9c524c8749f 100644
--- a/lib/libwrap/tcpd.h
+++ b/lib/libwrap/tcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpd.h,v 1.7 1999/07/21 18:27:41 form Exp $ */
+/* $OpenBSD: tcpd.h,v 1.8 2000/10/14 00:56:15 itojun Exp $ */
/*
* Copyright (c) 1997, Jason Downs. All rights reserved.
@@ -49,7 +49,7 @@
struct host_info {
char name[STRING_LENGTH]; /* access via eval_hostname(host) */
char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */
- struct sockaddr_in *sin; /* socket address or 0 */
+ struct sockaddr *sin; /* socket address or 0 */
struct t_unitdata *unit; /* TLI transport address or 0 */
struct request_info *request; /* for shared information */
};
@@ -108,7 +108,7 @@ extern int hosts_ctl __P((char *, char *, char *, char *));
extern void shell_cmd __P((char *));
extern char *percent_m __P((char *, char *));
extern char *percent_x __P((char *, int, char *, struct request_info *));
-extern void rfc931 __P((struct sockaddr_in *, struct sockaddr_in *, char *));
+extern void rfc931 __P((struct sockaddr *, struct sockaddr *, char *));
extern void clean_exit __P((struct request_info *));
extern void refuse __P((struct request_info *));
#ifdef _STDIO_H_
diff --git a/lib/libwrap/update.c b/lib/libwrap/update.c
index d8eca07d3e0..0cee40df295 100644
--- a/lib/libwrap/update.c
+++ b/lib/libwrap/update.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: update.c,v 1.1 1997/02/26 03:06:59 downsj Exp $ */
+/* $OpenBSD: update.c,v 1.2 2000/10/14 00:56:16 itojun Exp $ */
/*
* Routines for controlled update/initialization of request structures.
@@ -19,7 +19,7 @@
#if 0
static char sccsid[] = "@(#) update.c 1.1 94/12/28 17:42:56";
#else
-static char rcsid[] = "$OpenBSD: update.c,v 1.1 1997/02/26 03:06:59 downsj Exp $";
+static char rcsid[] = "$OpenBSD: update.c,v 1.2 2000/10/14 00:56:16 itojun Exp $";
#endif
#endif
@@ -53,10 +53,10 @@ va_list ap;
request->fd = va_arg(ap, int);
continue;
case RQ_CLIENT_SIN:
- request->client->sin = va_arg(ap, struct sockaddr_in *);
+ request->client->sin = va_arg(ap, struct sockaddr *);
continue;
case RQ_SERVER_SIN:
- request->server->sin = va_arg(ap, struct sockaddr_in *);
+ request->server->sin = va_arg(ap, struct sockaddr *);
continue;
/*
diff --git a/libexec/tcpd/Makefile.inc b/libexec/tcpd/Makefile.inc
index 21c317fe68d..8a62a4b245e 100644
--- a/libexec/tcpd/Makefile.inc
+++ b/libexec/tcpd/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.2 1997/03/04 09:01:39 downsj Exp $
+# $OpenBSD: Makefile.inc,v 1.3 2000/10/14 00:56:14 itojun Exp $
# Configuration options for libwrap. Keep in sync with libwrap/Makefile.
CFLAGS+=-DPROCESS_OPTIONS -DFACILITY=LOG_AUTH -DSEVERITY=LOG_INFO \
@@ -6,5 +6,6 @@ CFLAGS+=-DPROCESS_OPTIONS -DFACILITY=LOG_AUTH -DSEVERITY=LOG_INFO \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" \
-DNETGROUP -DSYS_ERRLIST_DEFINED -DREAL_DAEMON_DIR=\"/usr/libexec\" \
-D_TCPD_PRIVATE
+CFLAGS+=-DINET6
.include "../Makefile.inc"
diff --git a/libexec/tcpd/tcpdchk/scaffold.c b/libexec/tcpd/tcpdchk/scaffold.c
index 1d51f3eb6df..8ce6f7257e7 100644
--- a/libexec/tcpd/tcpdchk/scaffold.c
+++ b/libexec/tcpd/tcpdchk/scaffold.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scaffold.c,v 1.3 1999/06/06 18:58:54 deraadt Exp $ */
+/* $OpenBSD: scaffold.c,v 1.4 2000/10/14 00:56:14 itojun Exp $ */
/*
* Routines for testing only. Not really industrial strength.
@@ -10,7 +10,7 @@
#if 0
static char sccs_id[] = "@(#) scaffold.c 1.5 95/01/03 09:13:48";
#else
-static char rcsid[] = "$OpenBSD: scaffold.c,v 1.3 1999/06/06 18:58:54 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: scaffold.c,v 1.4 2000/10/14 00:56:14 itojun Exp $";
#endif
#endif
@@ -68,6 +68,7 @@ struct hostent *hp;
exit(1);
}
memset((char *) &hb->host, 0, sizeof(hb->host));
+ hb->host.h_addrtype = hp->h_addrtype;
hb->host.h_length = hp->h_length;
hb->host.h_addr_list = hb->addr_list;
hb->host.h_addr_list[count] = 0;
@@ -89,6 +90,9 @@ char *host;
struct hostent *hp;
static struct hostent h;
static char *addr_list[2];
+#ifdef INET6
+ static struct in6_addr in6;
+#endif
/*
* Host address: translate it to internal form.
@@ -97,8 +101,18 @@ char *host;
h.h_addr_list = addr_list;
h.h_addr_list[0] = (char *) &addr;
h.h_length = sizeof(addr);
+ h.h_addrtype = AF_INET;
return (dup_hostent(&h));
}
+#ifdef INET6
+ if (inet_pton(AF_INET6, host, &in6) == 1) {
+ h.h_addr_list = addr_list;
+ h.h_addr_list[0] = (char *) &in6;
+ h.h_length = sizeof(in6);
+ h.h_addrtype = AF_INET6;
+ return (dup_hostent(&h));
+ }
+#endif
/*
* Map host name to a series of addresses. Watch out for non-internet
@@ -106,10 +120,28 @@ char *host;
* been "enhanced" to accept numeric addresses. Make a copy of the
* address list so that later gethostbyXXX() calls will not clobber it.
*/
- if (NOT_INADDR(host) == 0) {
+#ifdef INET6
+ if (NOT_INADDR(host) == 0 && inet_pton(AF_INET6, host, &in6) == 1)
+#else
+ if (NOT_INADDR(host) == 0)
+#endif
+ {
tcpd_warn("%s: not an internet address", host);
return (0);
}
+#ifdef INET6
+ /*
+ * XXX this behavior may, or may not be desirable.
+ * - we may better use getipnodebyname() to addresses of get both AFs,
+ * however, getipnodebyname() is not widely implemented.
+ * - it may be better to have a way to specify the AF to use.
+ */
+ if ((hp = gethostbyname2(host, AF_INET)) == 0
+ && (hp = gethostbyname2(host, AF_INET6)) == 0) {
+ tcpd_warn("%s: host not found", host);
+ return (0);
+ }
+#else
if ((hp = gethostbyname(host)) == 0) {
tcpd_warn("%s: host not found", host);
return (0);
@@ -118,6 +150,7 @@ char *host;
tcpd_warn("%d: not an internet host", hp->h_addrtype);
return (0);
}
+#endif
if (STR_NE(host, hp->h_name)) {
tcpd_warn("%s: hostname alias", host);
tcpd_warn("(official name: %s)", hp->h_name);
@@ -131,20 +164,36 @@ int check_dns(host)
char *host;
{
struct request_info request;
- struct sockaddr_in sin;
+ struct sockaddr_storage sin;
struct hostent *hp;
int count;
char *addr;
+ char *ap;
+ int alen;
if ((hp = find_inet_addr(host)) == 0)
return (0);
request_init(&request, RQ_CLIENT_SIN, &sin, 0);
sock_methods(&request);
memset((char *) &sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
+ sin.ss_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
+ alen = sizeof(struct in6_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ return (0);
+ }
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
+ memcpy(ap, addr, alen);
/*
* Force host name and address conversions. Use the request structure
@@ -186,7 +235,7 @@ struct request_info *request;
/* ARGSUSED */
void rfc931(a1, a2, d1)
-struct sockaddr_in *a1, *a2;
+struct sockaddr *a1, *a2;
char *d1;
{
}
diff --git a/libexec/tcpd/tcpdchk/tcpdchk.c b/libexec/tcpd/tcpdchk/tcpdchk.c
index ff076901616..fc9c140d60b 100644
--- a/libexec/tcpd/tcpdchk/tcpdchk.c
+++ b/libexec/tcpd/tcpdchk/tcpdchk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpdchk.c,v 1.3 1999/06/06 15:34:57 deraadt Exp $ */
+/* $OpenBSD: tcpdchk.c,v 1.4 2000/10/14 00:56:14 itojun Exp $ */
/*
* tcpdchk - examine all tcpd access control rules and inetd.conf entries
@@ -20,7 +20,7 @@
#if 0
static char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25";
#else
-static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.3 1999/06/06 15:34:57 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.4 2000/10/14 00:56:14 itojun Exp $";
#endif
#endif
@@ -28,6 +28,9 @@ static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.3 1999/06/06 15:34:57 deraadt Exp
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef INET6
+#include <sys/socket.h>
+#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
@@ -331,15 +334,25 @@ char *list;
char *cp;
char *host;
int clients = 0;
+#ifdef INET6
+ int l;
+#endif
strcpy(buf, list);
for (cp = strtok(buf, sep); cp != 0; cp = strtok((char *) 0, sep)) {
+#ifdef INET6
+ l = strlen(cp);
+ if (cp[0] == '[' && cp[l - 1] == ']') {
+ cp[l - 1] = '\0';
+ cp++;
+ }
+#endif
if (STR_EQ(cp, "EXCEPT")) {
clients = 0;
} else {
clients++;
- if ((host = split_at(cp + 1, '@'))) { /* user@host */
+ if ((host = split_at(cp + 1, '@')) != NULL) { /* user@host */
check_user(cp);
check_host(host);
} else {
@@ -430,8 +443,23 @@ char *pat;
tcpd_warn("netgroup support disabled");
#endif
#endif
- } else if ((mask = split_at(pat, '/'))) { /* network/netmask */
- if (!dot_quad_addr_new(pat, NULL) || !dot_quad_addr_new(mask, NULL))
+ } else if ((mask = split_at(pat, '/')) != NULL) { /* network/netmask */
+#ifdef INET6
+ struct in6_addr in6;
+#endif
+ if (dot_quad_addr_new(pat, NULL)
+ && dot_quad_addr_new(mask, NULL))
+ ; /*okay*/
+#ifdef INET6
+ else if (inet_pton(AF_INET6, pat, &in6) == 1
+ && inet_pton(AF_INET6, mask, &in6) == 1)
+ ; /*okay*/
+ else if (inet_pton(AF_INET6, pat, &in6) == 1
+ && strchr(mask, ':') == NULL
+ && 0 <= atoi(mask) && atoi(mask) <= 128)
+ ; /*okay*/
+#endif
+ else
tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
} else if (STR_EQ(pat, "FAIL")) { /* obsolete */
tcpd_warn("FAIL is no longer recognized");
diff --git a/libexec/tcpd/tcpdmatch/tcpdmatch.c b/libexec/tcpd/tcpdmatch/tcpdmatch.c
index 2225e548546..f9de6575da6 100644
--- a/libexec/tcpd/tcpdmatch/tcpdmatch.c
+++ b/libexec/tcpd/tcpdmatch/tcpdmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpdmatch.c,v 1.4 1999/06/06 18:58:54 deraadt Exp $ */
+/* $OpenBSD: tcpdmatch.c,v 1.5 2000/10/14 00:56:15 itojun Exp $ */
/*
* tcpdmatch - explain what tcpd would do in a specific case
@@ -19,7 +19,7 @@
#if 0
static char sccsid[] = "@(#) tcpdmatch.c 1.5 96/02/11 17:01:36";
#else
-static char rcsid[] = "$OpenBSD: tcpdmatch.c,v 1.4 1999/06/06 18:58:54 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: tcpdmatch.c,v 1.5 2000/10/14 00:56:15 itojun Exp $";
#endif
#endif
@@ -73,9 +73,14 @@ char **argv;
int ch;
char *inetcf = 0;
int count;
- struct sockaddr_in server_sin;
- struct sockaddr_in client_sin;
+ struct sockaddr_storage server_sin;
+ struct sockaddr_storage client_sin;
struct stat st;
+ char *ap;
+ int alen;
+#ifdef INET6
+ struct sockaddr_in6 in6;
+#endif
/*
* Show what rule actually matched.
@@ -178,12 +183,25 @@ char **argv;
if ((hp = find_inet_addr(server)) == 0)
exit(1);
memset((char *) &server_sin, 0, sizeof(server_sin));
- server_sin.sin_family = AF_INET;
+ server_sin.ss_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ ap = (char *)&((struct sockaddr_in *)&server_sin)->sin_addr;
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ exit(1);
+ }
request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy((char *) &server_sin.sin_addr, addr,
- sizeof(server_sin.sin_addr));
+ memcpy(ap, addr, alen);
/*
* Force evaluation of server host name and address. Host name
@@ -213,6 +231,13 @@ char **argv;
tcpdmatch(&request);
exit(0);
}
+#ifdef INET6
+ if (inet_pton(AF_INET6, client, &in6) == 1) {
+ request_set(&request, RQ_CLIENT_ADDR, client, 0);
+ tcpdmatch(&request);
+ exit(0);
+ }
+#endif
/*
* Perhaps they are testing special client hostname patterns that aren't
@@ -235,12 +260,25 @@ char **argv;
if ((hp = find_inet_addr(client)) == 0)
exit(1);
memset((char *) &client_sin, 0, sizeof(client_sin));
- client_sin.sin_family = AF_INET;
+ client_sin.ss_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ ap = (char *)&((struct sockaddr_in *)&client_sin)->sin_addr;
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ exit(1);
+ }
request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy((char *) &client_sin.sin_addr, addr,
- sizeof(client_sin.sin_addr));
+ memcpy(ap, addr, alen);
/*
* Force evaluation of client host name and address. Host name