diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-10-14 00:56:17 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-10-14 00:56:17 +0000 |
commit | f6091bbe12538b3e722800dcd3e43cf014dc17e6 (patch) | |
tree | 0061ec9397b880b94546484b17273eac081d654d | |
parent | ea55ada60b971559c0cd36421576ee1f0502d9a3 (diff) |
tcp wrapper support for IPv6. from netbsd.
TODO: scoped address support may need more consideration (we are taking
safer side now - rejects too much).
-rw-r--r-- | lib/libwrap/Makefile | 3 | ||||
-rw-r--r-- | lib/libwrap/fix_options.c | 18 | ||||
-rw-r--r-- | lib/libwrap/hosts_access.5 | 27 | ||||
-rw-r--r-- | lib/libwrap/hosts_access.c | 100 | ||||
-rw-r--r-- | lib/libwrap/misc.c | 28 | ||||
-rw-r--r-- | lib/libwrap/rfc931.c | 98 | ||||
-rw-r--r-- | lib/libwrap/socket.c | 86 | ||||
-rw-r--r-- | lib/libwrap/tcpd.h | 6 | ||||
-rw-r--r-- | lib/libwrap/update.c | 8 | ||||
-rw-r--r-- | libexec/tcpd/Makefile.inc | 3 | ||||
-rw-r--r-- | libexec/tcpd/tcpdchk/scaffold.c | 63 | ||||
-rw-r--r-- | libexec/tcpd/tcpdchk/tcpdchk.c | 38 | ||||
-rw-r--r-- | libexec/tcpd/tcpdmatch/tcpdmatch.c | 58 |
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 |