Missing tcp_wrapper IPv6 support seemed to be a bug, so commit it.

Now when tcp_wrapper is enabled by inetd -wW,
  several accesses which should be permitted are refused only for IPv6,
  if hostname is used to decide the host to be allowed.
  IPv6 users will be just upset.

  About security related concern.
    -All extensions are wrapped by #ifdef INET6, so people can completely
     disable the extension by recompile libwrap without INET6 option.
    -Access via IPv6 is not enabled by default.
     People need to enable IPv6 access by changing /etc/inetd.conf at first,
     by adding tcp6 and/or tcp46 entries.
    -The base of patches are from KAME package and are actually daily used
     for more than a year in several Japanese IPv6 environments.
    -Patches are reviewed by markm.

Approved by: jkh

Submitted by: Hajimu UMEMOTO <ume@mahoroba.org>
Reviewed by: markm
Obtained from: KAME project
This commit is contained in:
Yoshinobu Inoue 2000-02-03 10:27:03 +00:00
parent ab08b2ee08
commit 8053080cbc
18 changed files with 729 additions and 12 deletions

View File

@ -1,4 +1,5 @@
# @(#) Makefile 1.23 97/03/21 19:27:20
# $FreeBSD$
what:
@echo
@ -21,7 +22,7 @@ what:
@echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix"
@echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
@echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4"
@echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
@echo " sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
@echo " uts215 uxp"
@echo
@echo "If none of these match your environment, edit the system"
@ -131,20 +132,34 @@ epix:
NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all
# Freebsd and linux by default have no NIS.
386bsd netbsd bsdos:
386bsd bsdos:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
freebsd:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP=-DNETGROUP TLI= \
EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -DUSE_GETIPNODEBY" \
VSYSLOG= all
netbsd:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 \
-Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all
linux:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP= TLI= \
EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DBROKEN_SO_LINGER -DINET6=1 \
-Dss_family=__ss_family -Dss_len=__ss_len" all
linux-old:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS="/usr/inet6/lib/libinet6.a -lresolv" \
RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP= TLI= \
EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DBROKEN_SO_LINGER -DINET6=1 -Dss_family=sin6_family -Dsockaddr_storage=sockaddr_in6 -I/usr/inet6/include" all
# This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
hpux hpux8 hpux9 hpux10:
@ -196,6 +211,14 @@ sunos5:
NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all
# SunOS 5.8 is another SYSV4 variant, but has IPv6 support
solaris8:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \
NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
EXTRA_CFLAGS="-DINET6 -DUSE_GETIPNODEBY -DNO_CLONE_DEVICE \
-DINT32_T" all
# Generic SYSV40
esix sysv4:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
@ -229,7 +252,7 @@ tandem:
# Amdahl UTS 2.1.5 (Richard.Richmond@bridge.bst.bls.com)
uts215:
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
LIBS="-lsocket" RANLIB=echo \
ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP=-DNO_NETGROUP TLI= all
@ -391,7 +414,7 @@ AR = ar
# the ones provided with this source distribution. The environ.c module
# implements setenv(), getenv(), and putenv().
AUX_OBJ= setenv.o
#AUX_OBJ= setenv.o
#AUX_OBJ= environ.o
#AUX_OBJ= environ.o strcasecmp.o
@ -454,7 +477,7 @@ AUX_OBJ= setenv.o
# host name aliases. Compile with -DSOLARIS_24_GETHOSTBYNAME_BUG to work
# around this. The workaround does no harm on other Solaris versions.
BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DINET_ADDR_BUG
#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DSOLARIS_24_GETHOSTBYNAME_BUG
@ -472,7 +495,7 @@ BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
# If your system supports vsyslog(), comment out the following definition.
# If in doubt leave it in, it won't harm.
VSYSLOG = -Dvsyslog=myvsyslog
#VSYSLOG = -Dvsyslog=myvsyslog
# End of the system dependencies.
#################################

View File

@ -3,6 +3,8 @@
* rlogind and kernel source, but all mistakes in it are my fault.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -11,6 +13,9 @@ static char sccsid[] = "@(#) fix_options.c 1.6 97/04/08 02:29:19";
#include <sys/types.h>
#include <sys/param.h>
#ifdef INET6
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@ -41,6 +46,22 @@ struct request_info *request;
unsigned int opt;
int optlen;
struct in_addr dummy;
#ifdef INET6
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;
#endif
if ((ip = getprotobyname("ip")) != 0)
ipproto = ip->p_proto;

View File

@ -90,6 +90,13 @@ bitwise AND of the address and the `mask\'. For example, the net/mask
pattern `131.155.72.0/255.255.254.0\' matches every address in the
range `131.155.72.0\' through `131.155.73.255\'.
.IP \(bu
An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
`[net]/prefixlen\' pair. A IPv6 host address is matched if
`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
address. For example, the [net]/prefixlen pattern
`[3ffe:505:2:1::]/64\' matches every address in the range
`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
.IP \(bu
A string that begins with a `/\' character is treated as a file
name. A host name or address is matched if it matches any host name
or address pattern listed in the named file. The file format is

View File

@ -26,7 +26,13 @@ static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
/* System libraries. */
#include <sys/types.h>
#ifdef INT32_T
typedef uint32_t u_int32_t;
#endif
#include <sys/param.h>
#ifdef INET6
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
@ -84,6 +90,10 @@ static int client_match();
static int host_match();
static int string_match();
static int masked_match();
#ifdef INET6
static int masked_match4();
static int masked_match6();
#endif
/* Size of logical line buffer. */
@ -313,6 +323,13 @@ char *string;
{
int n;
#ifdef INET6
/* convert IPv4 mapped IPv6 address to IPv4 address */
if (STRN_EQ(string, "::ffff:", 7)
&& dot_quad_addr(string + 7) != INADDR_NONE) {
string += 7;
}
#endif
if (tok[0] == '.') { /* suffix */
n = strlen(string) - strlen(tok);
return (n > 0 && STR_EQ(tok, string + n));
@ -323,20 +340,55 @@ char *string;
} else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
return (STRN_EQ(tok, string, n));
} else { /* exact match */
#ifdef INET6
struct in6_addr pat, addr;
int len, ret;
char ch;
len = strlen(tok);
if (*tok == '[' && tok[len - 1] == ']') {
ch = tok[len - 1];
tok[len - 1] = '\0';
ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
tok[len - 1] = ch;
if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
return NO;
return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
}
#endif
return (STR_EQ(tok, string));
}
}
/* masked_match - match address against netnumber/netmask */
#ifdef INET6
static int masked_match(net_tok, mask_tok, string)
char *net_tok;
char *mask_tok;
char *string;
{
return (masked_match4(net_tok, mask_tok, string) ||
masked_match6(net_tok, mask_tok, string));
}
static int masked_match4(net_tok, mask_tok, string)
#else
static int masked_match(net_tok, mask_tok, string)
#endif
char *net_tok;
char *mask_tok;
char *string;
{
#ifdef INET6
u_int32_t net;
u_int32_t mask;
u_int32_t addr;
#else
unsigned long net;
unsigned long mask;
unsigned long addr;
#endif
/*
* Disallow forms other than dotted quad: the treatment that inet_addr()
@ -348,8 +400,61 @@ char *string;
return (NO);
if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
#ifndef INET6
tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
#endif
return (NO); /* not tcpd_jump() */
}
return ((addr & mask) == net);
}
#ifdef INET6
static int masked_match6(net_tok, mask_tok, string)
char *net_tok;
char *mask_tok;
char *string;
{
struct in6_addr net, addr;
u_int32_t mask;
int len, mask_len, i = 0;
char ch;
if (inet_pton(AF_INET6, string, addr.s6_addr) != 1)
return NO;
if (IN6_IS_ADDR_V4MAPPED(&addr)) {
if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
return (NO);
return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]);
}
/* match IPv6 address against netnumber/prefixlen */
len = strlen(net_tok);
if (*net_tok != '[' || net_tok[len - 1] != ']')
return NO;
ch = net_tok[len - 1];
net_tok[len - 1] = '\0';
if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
net_tok[len - 1] = ch;
return NO;
}
net_tok[len - 1] = ch;
if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
return NO;
while (mask_len > 0) {
if (mask_len < 32) {
mask = htonl(~(0xffffffff >> mask_len));
if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask))
return NO;
break;
}
if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
return NO;
i += 4;
mask_len -= 32;
}
return YES;
}
#endif /* INET6 */

View File

@ -2,6 +2,8 @@
* Misc routines that are used by tcpd and by tcpdchk.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -58,9 +60,31 @@ int delimiter;
{
char *cp;
#ifdef INET6
int 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);
#else
if ((cp = strchr(string, delimiter)) != 0)
*cp++ = 0;
return (cp);
#endif
}
/* dot_quad_addr - convert dotted quad to internal form */

View File

@ -5,6 +5,8 @@
* the program is terminated.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -25,7 +27,12 @@ static char sccsid[] = "@(#) refuse.c 1.5 94/12/28 17:42:39";
void refuse(request)
struct request_info *request;
{
#ifdef INET6
syslog(deny_severity, "refused connect from %s (%s)",
eval_client(request), eval_hostaddr(request->client));
#else
syslog(deny_severity, "refused connect from %s", eval_client(request));
#endif
clean_exit(request);
/* NOTREACHED */
}

View File

@ -7,6 +7,8 @@
* Diagnostics are reported through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -68,20 +70,50 @@ int sig;
/* 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
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;
char *result = unknown;
FILE *fp;
#ifdef INET6
/* address family must be the same */
if (rmt_sin->sa_family != our_sin->sa_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:
STRN_CPY(dest, result, STRING_LENGTH);
return;
}
#endif
/*
* Use one unbuffered stdio stream for writing to and for reading from
* the RFC931 etc. server. This is done because of a bug in the SunOS
@ -92,7 +124,11 @@ char *dest;
* sockets.
*/
#ifdef INET6
if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
#else
if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
#endif
setbuf(fp, (char *) 0);
/*
@ -112,6 +148,25 @@ char *dest;
* addresses from the query socket.
*/
#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;
}
if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
alen) >= 0 &&
connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
alen) >= 0) {
#else
our_query_sin = *our_sin;
our_query_sin.sin_port = htons(ANY_PORT);
rmt_query_sin = *rmt_sin;
@ -121,6 +176,7 @@ char *dest;
sizeof(our_query_sin)) >= 0 &&
connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
sizeof(rmt_query_sin)) >= 0) {
#endif
/*
* Send query to server. Neglect the risk that a 13-byte
@ -129,8 +185,13 @@ 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));
#else
ntohs(rmt_sin->sin_port),
ntohs(our_sin->sin_port));
#endif
fflush(fp);
/*
@ -144,8 +205,13 @@ char *dest;
&& ferror(fp) == 0 && feof(fp) == 0
&& sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
&rmt_port, &our_port, user) == 3
#ifdef INET6
&& ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
&& ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
#else
&& ntohs(rmt_sin->sin_port) == rmt_port
&& ntohs(our_sin->sin_port) == our_port) {
#endif
/*
* Strip trailing carriage return. It is part of the

View File

@ -2,6 +2,8 @@
* Routines for testing only. Not really industrial strength.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -20,6 +22,7 @@ static char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24";
#include <syslog.h>
#include <setjmp.h>
#include <string.h>
#include <resolv.h>
#ifndef INADDR_NONE
#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
@ -57,6 +60,9 @@ struct hostent *hp;
/* void */ ;
if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
#ifdef INET6
+ strlen(hp->h_name) + 1
#endif
+ (hp->h_length + sizeof(char *)) * count)) == 0) {
fprintf(stderr, "Sorry, out of memory\n");
exit(1);
@ -66,6 +72,11 @@ struct hostent *hp;
hb->host.h_addr_list = hb->addr_list;
hb->host.h_addr_list[count] = 0;
data = (char *) (hb->host.h_addr_list + count + 1);
#ifdef INET6
hb->host.h_name = data + hp->h_length * count;
strcpy(hb->host.h_name, hp->h_name);
hb->host.h_addrtype = hp->h_addrtype;
#endif
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
hb->host.h_addr_list[count] = data + hp->h_length * count;
@ -74,6 +85,104 @@ struct hostent *hp;
return (&hb->host);
}
#if defined(INET6) && !defined(USE_GETIPNODEBY)
/* merge_hostent - merge hostent in one memory block */
static struct hostent *merge_hostent(hp1, hp2)
struct hostent *hp1, *hp2;
{
struct hostent_block {
struct hostent host;
char *addr_list[1];
};
struct hostent_block *hb;
int count, count2;
char *data;
char *addr;
for (count = 0; hp1->h_addr_list[count] != 0; count++)
/* void */ ;
for (count2 = 0; hp2->h_addr_list[count2] != 0; count2++)
/* void */ ;
count += count2;
if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
+ strlen(hp1->h_name) + 1
+ (hp1->h_length + sizeof(char *)) * count)) == 0) {
fprintf(stderr, "Sorry, out of memory\n");
exit(1);
}
memset((char *) &hb->host, 0, sizeof(hb->host));
hb->host.h_length = hp1->h_length;
hb->host.h_addr_list = hb->addr_list;
hb->host.h_addr_list[count] = 0;
data = (char *) (hb->host.h_addr_list + count + 1);
hb->host.h_name = data + hp1->h_length * count;
strcpy(hb->host.h_name, hp1->h_name);
hb->host.h_addrtype = hp1->h_addrtype;
for (count = 0; (addr = hp1->h_addr_list[count]) != 0; count++) {
hb->host.h_addr_list[count] = data + hp1->h_length * count;
memcpy(hb->host.h_addr_list[count], addr, hp1->h_length);
}
for (count2 = 0; (addr = hp2->h_addr_list[count2]) != 0; count2++) {
hb->host.h_addr_list[count] = data + hp1->h_length * count;
memcpy(hb->host.h_addr_list[count], addr, hp1->h_length);
++count;
}
return (&hb->host);
}
#endif
static struct hostent *gethostbyname64(host)
char *host;
{
struct hostent *hp = NULL, *hp2 = NULL;
#ifdef USE_GETIPNODEBY
int h_error;
if ((hp = getipnodebyname(host, AF_INET6,
AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL,
&h_error)) != 0) {
hp2 = dup_hostent(hp);
freehostent(hp);
return (hp2);
}
#else
struct hostent *hp1;
u_long res_options;
if ((_res.options & RES_INIT) == 0) {
if (res_init() < 0) {
tcpd_warn("%s: res_init() failed", host);
return (NULL);
}
}
res_options = _res.options;
#ifdef INET6
_res.options |= RES_USE_INET6;
if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL)
hp1 = dup_hostent(hp1);
#endif
if ((hp2 = gethostbyname2(host, AF_INET)) != NULL)
hp2 = dup_hostent(hp2);
_res.options = res_options;
#ifdef INET6
if (hp1 && hp2) {
hp = merge_hostent(hp1, hp2);
free((char *) hp1);
free((char *) hp2);
return (hp);
}
if (hp1)
return (hp1);
#endif
if (hp2)
return (hp2);
#endif
return (NULL);
}
/* find_inet_addr - find all addresses for this host, result to free() */
struct hostent *find_inet_addr(host)
@ -83,6 +192,7 @@ char *host;
struct hostent *hp;
static struct hostent h;
static char *addr_list[2];
static char hnamebuf[BUFSIZ];
/*
* Host address: translate it to internal form.
@ -91,6 +201,11 @@ char *host;
h.h_addr_list = addr_list;
h.h_addr_list[0] = (char *) &addr;
h.h_length = sizeof(addr);
#ifdef INET6
h.h_addrtype = AF_INET;
h.h_name = hnamebuf;
strcpy(h.h_name, host);
#endif
return (dup_hostent(&h));
}
@ -104,19 +219,33 @@ char *host;
tcpd_warn("%s: not an internet address", host);
return (0);
}
#ifdef INET6
if ((hp = gethostbyname64(host)) == 0) {
#else
if ((hp = gethostbyname(host)) == 0) {
#endif
tcpd_warn("%s: host not found", host);
return (0);
}
#ifdef INET6
if (hp->h_addrtype != AF_INET6) {
tcpd_warn("%d: not an internet host", hp->h_addrtype);
free((char *) hp);
#else
if (hp->h_addrtype != AF_INET) {
tcpd_warn("%d: not an internet host", hp->h_addrtype);
#endif
return (0);
}
if (STR_NE(host, hp->h_name)) {
tcpd_warn("%s: hostname alias", host);
tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name);
}
#ifdef INET6
return (hp);
#else
return (dup_hostent(hp));
#endif
}
/* check_dns - give each address thorough workout, return address count */
@ -125,7 +254,13 @@ int check_dns(host)
char *host;
{
struct request_info request;
#ifdef INET6
struct sockaddr_storage sin;
char *ap;
int alen;
#else
struct sockaddr_in sin;
#endif
struct hostent *hp;
int count;
char *addr;
@ -135,10 +270,30 @@ char *host;
request_init(&request, RQ_CLIENT_SIN, &sin, 0);
sock_methods(&request);
memset((char *) &sin, 0, sizeof(sin));
#ifdef INET6
sin.ss_family = hp->h_addrtype;
switch (hp->h_addrtype) {
case AF_INET:
ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
alen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
alen = sizeof(struct sockaddr_in6);
break;
default:
return (0);
}
#else
sin.sin_family = AF_INET;
#endif
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
#ifdef INET6
memcpy(ap, addr, alen);
#else
memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
#endif
/*
* Force host name and address conversions. Use the request structure

View File

@ -13,6 +13,8 @@
* Diagnostics are reported through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -30,6 +32,12 @@ static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
#include <syslog.h>
#include <string.h>
#ifdef INET6
#ifndef USE_GETIPNODEBY
#include <resolv.h>
#endif
#endif
extern char *inet_ntoa();
/* Local stuff. */
@ -74,8 +82,13 @@ char *name;
void sock_host(request)
struct request_info *request;
{
#ifdef INET6
static struct sockaddr_storage client;
static struct sockaddr_storage server;
#else
static struct sockaddr_in client;
static struct sockaddr_in server;
#endif
int len;
char buf[BUFSIZ];
int fd = request->fd;
@ -104,7 +117,11 @@ 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
@ -117,7 +134,11 @@ struct request_info *request;
tcpd_warn("getsockname: %m");
return;
}
#ifdef INET6
request->server->sin = (struct sockaddr *)&server;
#else
request->server->sin = &server;
#endif
}
/* sock_hostaddr - map endpoint address to printable form */
@ -125,10 +146,33 @@ struct request_info *request;
void sock_hostaddr(host)
struct host_info *host;
{
#ifdef INET6
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:
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
}
/* sock_hostname - map endpoint address to host name */
@ -136,8 +180,21 @@ struct host_info *host;
void sock_hostname(host)
struct host_info *host;
{
#ifdef INET6
struct sockaddr *sin = host->sin;
char addr[128];
#ifdef USE_GETIPNODEBY
int h_error;
#else
u_long res_options;
#endif
struct hostent *hp = NULL;
char *ap;
int alen;
#else
struct sockaddr_in *sin = host->sin;
struct hostent *hp;
#endif
int i;
/*
@ -147,11 +204,42 @@ 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.
*/
#ifdef INET6
if (sin != NULL) {
switch (sin->sa_family) {
case AF_INET:
if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0) {
strcpy(host->name, paranoid); /* name is bad, clobber it */
return;
}
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;
defalut:
strcpy(host->name, paranoid); /* name is bad, clobber it */
return;
}
#ifdef USE_GETIPNODEBY
hp = getipnodebyaddr(ap, alen, sin->sa_family, &h_error);
#else
hp = gethostbyaddr(ap, alen, sin->sa_family);
#endif
}
if (hp) {
#else
if (sin != 0 && sin->sin_addr.s_addr != 0
&& (hp = gethostbyaddr((char *) &(sin->sin_addr),
sizeof(sin->sin_addr), AF_INET)) != 0) {
#endif
STRN_CPY(host->name, hp->h_name, sizeof(host->name));
#if defined(INET6) && defined(USE_GETIPNODEBY)
freehostent(hp);
#endif
/*
* Verify that the address is a member of the address list returned
@ -166,15 +254,53 @@ struct host_info *host;
* we're in big trouble anyway.
*/
#ifdef INET6
#ifdef USE_GETIPNODEBY
hp = getipnodebyname(host->name, sin->sa_family,
AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, &h_error);
#else
if ((_res.options & RES_INIT) == 0) {
if (res_init() < 0) {
inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
tcpd_warn("can't verify hostname: res_init() for %s failed",
addr);
strcpy(host->name, paranoid); /* name is bad, clobber it */
return;
}
}
res_options = _res.options;
if (sin->sa_family == AF_INET6)
_res.options |= RES_USE_INET6;
else
_res.options &= ~RES_USE_INET6;
hp = gethostbyname2(host->name,
(sin->sa_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sin)->sin6_addr)) ?
AF_INET : sin->sa_family);
_res.options = res_options;
#endif
if (!hp) {
#else
if ((hp = gethostbyname(host->name)) == 0) {
#endif
/*
* Unable to verify that the host name matches the address. This
* may be a transient problem or a botched name server setup.
*/
#ifdef INET6
#ifdef USE_GETIPNODEBY
tcpd_warn("can't verify hostname: getipnodebyname(%s, %s) failed",
#else
tcpd_warn("can't verify hostname: gethostbyname2(%s, %s) failed",
#endif
host->name,
(sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
#else
tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
host->name);
#endif
} else if (STR_NE(host->name, hp->h_name)
&& STR_NE(host->name, "localhost")) {
@ -198,10 +324,19 @@ struct host_info *host;
*/
for (i = 0; hp->h_addr_list[i]; i++) {
#ifdef INET6
if (memcmp(hp->h_addr_list[i], ap, alen) == 0) {
#ifdef USE_GETIPNODEBY
freehostent(hp);
#endif
return; /* name is good, keep it */
}
#else
if (memcmp(hp->h_addr_list[i],
(char *) &sin->sin_addr,
sizeof(sin->sin_addr)) == 0)
return; /* name is good, keep it */
#endif
}
/*
@ -210,10 +345,20 @@ struct host_info *host;
* server.
*/
#ifdef INET6
inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
tcpd_warn("host name/address mismatch: %s != %.*s",
addr, STRING_LENGTH, hp->h_name);
#else
tcpd_warn("host name/address mismatch: %s != %.*s",
inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
#endif
}
strcpy(host->name, paranoid); /* name is bad, clobber it */
#if defined(INET6) && defined(USE_GETIPNODEBY)
if (hp)
freehostent(hp);
#endif
}
}
@ -223,7 +368,11 @@ static void sock_sink(fd)
int fd;
{
char buf[BUFSIZ];
#ifdef INET6
struct sockaddr_storage sin;
#else
struct sockaddr_in sin;
#endif
int size = sizeof(sin);
/*

View File

@ -8,6 +8,8 @@
* are logged through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -120,7 +122,12 @@ char **argv;
/* Report request and invoke the real daemon program. */
#ifdef INET6
syslog(allow_severity, "connect from %s (%s)",
eval_client(&request), eval_hostaddr(request.client));
#else
syslog(allow_severity, "connect from %s", eval_client(&request));
#endif
closelog();
(void) execv(path, argv);
syslog(LOG_ERR, "error: cannot execute %s: %m", path);

View File

@ -2,6 +2,8 @@
* @(#) tcpd.h 1.5 96/03/19 16:22:24
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
/* Structure to describe one communications endpoint. */
@ -11,7 +13,11 @@
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 t_unitdata *unit; /* TLI transport address or 0 */
struct request_info *request; /* for shared information */
};

View File

@ -24,6 +24,9 @@ static char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25";
#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>
@ -403,6 +406,26 @@ char *pat;
}
}
#ifdef INET6
static int is_inet6_addr(pat)
char *pat;
{
struct in6_addr addr;
int len, ret;
char ch;
if (*pat != '[')
return (0);
len = strlen(pat);
if ((ch = pat[len - 1]) != ']')
return (0);
pat[len - 1] = '\0';
ret = inet_pton(AF_INET6, pat + 1, &addr);
pat[len - 1] = ch;
return (ret == 1);
}
#endif
/* check_host - criticize host pattern */
static int check_host(pat)
@ -449,14 +472,27 @@ char *pat;
tcpd_warn("open %s: %m", pat);
}
} else if (mask = split_at(pat, '/')) { /* network/netmask */
#ifdef INET6
int mask_len;
if ((dot_quad_addr(pat) == INADDR_NONE
|| dot_quad_addr(mask) == INADDR_NONE)
&& (!is_inet6_addr(pat)
|| ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
#else
if (dot_quad_addr(pat) == INADDR_NONE
|| dot_quad_addr(mask) == INADDR_NONE)
#endif
tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
} else if (STR_EQ(pat, "FAIL")) { /* obsolete */
tcpd_warn("FAIL is no longer recognized");
tcpd_warn("(use EXCEPT or DENY instead)");
} else if (reserved_name(pat)) { /* other reserved */
/* void */ ;
#ifdef INET6
} else if (is_inet6_addr(pat)) { /* IPv6 address */
addr_count = 1;
#endif
} else if (NOT_INADDR(pat)) { /* internet name */
if (pat[strlen(pat) - 1] == '.') {
tcpd_warn("%s: domain or host name ends in dot", pat);

View File

@ -11,6 +11,8 @@
* that would normally be reported via the syslog daemon.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -68,8 +70,15 @@ char **argv;
int ch;
char *inetcf = 0;
int count;
#ifdef INET6
struct sockaddr_storage server_sin;
struct sockaddr_storage client_sin;
char *ap;
int alen;
#else
struct sockaddr_in server_sin;
struct sockaddr_in client_sin;
#endif
struct stat st;
/*
@ -173,12 +182,35 @@ char **argv;
if ((hp = find_inet_addr(server)) == 0)
exit(1);
memset((char *) &server_sin, 0, sizeof(server_sin));
#ifdef INET6
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 sockaddr_in);
break;
case AF_INET6:
ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr;
alen = sizeof(struct sockaddr_in6);
break;
default:
exit(1);
}
#ifdef SIN6_LEN
server_sin.ss_len = alen;
#endif
#else
server_sin.sin_family = AF_INET;
#endif
request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
#ifdef INET6
memcpy(ap, addr, alen);
#else
memcpy((char *) &server_sin.sin_addr, addr,
sizeof(server_sin.sin_addr));
#endif
/*
* Force evaluation of server host name and address. Host name
@ -230,12 +262,35 @@ char **argv;
if ((hp = find_inet_addr(client)) == 0)
exit(1);
memset((char *) &client_sin, 0, sizeof(client_sin));
#ifdef INET6
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 sockaddr_in);
break;
case AF_INET6:
ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr;
alen = sizeof(struct sockaddr_in6);
break;
default:
exit(1);
}
#ifdef SIN6_LEN
client_sin.ss_len = alen;
#endif
#else
client_sin.sin_family = AF_INET;
#endif
request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
#ifdef INET6
memcpy(ap, addr, alen);
#else
memcpy((char *) &client_sin.sin_addr, addr,
sizeof(client_sin.sin_addr));
#endif
/*
* Force evaluation of client host name and address. Host name

View File

@ -12,6 +12,8 @@
* Diagnostics are reported through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -65,8 +67,13 @@ static void tli_sink();
void tli_host(request)
struct request_info *request;
{
#ifdef INET6
static struct sockaddr_storage client;
static struct sockaddr_storage server;
#else
static struct sockaddr_in client;
static struct sockaddr_in server;
#endif
/*
* If we discover that we are using an IP transport, pretend we never
@ -75,15 +82,31 @@ struct request_info *request;
*/
tli_endpoints(request);
#ifdef INET6
if ((request->config = tli_transport(request->fd)) != 0
&& STR_EQ(request->config->nc_protofmly, "inet")) {
&& (STR_EQ(request->config->nc_protofmly, "inet") ||
STR_EQ(request->config->nc_protofmly, "inet6"))) {
#else
if ((request->config = tli_transport(request->fd)) != 0
&& STR_EQ(request->config->nc_protofmly, "inet")) {
#endif
if (request->client->unit != 0) {
#ifdef INET6
client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
request->client->sin = (struct sockaddr *) &client;
#else
client = *(struct sockaddr_in *) request->client->unit->addr.buf;
request->client->sin = &client;
#endif
}
if (request->server->unit != 0) {
server = *(struct sockaddr_in *) request->server->unit->addr.buf;
request->server->sin = &server;
#ifdef INET6
server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
request->server->sin = (struct sockaddr *) &server;
#else
server = *(struct sockaddr_in *) request->server->unit->addr.buf;
request->server->sin = &server;
#endif
}
tli_cleanup(request);
sock_methods(request);
@ -187,7 +210,15 @@ int fd;
}
while (config = getnetconfig(handlep)) {
if (stat(config->nc_device, &from_config) == 0) {
#ifdef NO_CLONE_DEVICE
/*
* If the network devices are not cloned (as is the case for
* Solaris 8 Beta), we must compare the major device numbers.
*/
if (major(from_config.st_rdev) == major(from_client.st_rdev))
#else
if (minor(from_config.st_rdev) == major(from_client.st_rdev))
#endif
break;
}
}

View File

@ -11,6 +11,8 @@
* Diagnostics are reported through syslog(3).
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -46,10 +48,18 @@ va_list ap;
request->fd = va_arg(ap, int);
continue;
case RQ_CLIENT_SIN:
#ifdef INET6
request->client->sin = va_arg(ap, struct sockaddr *);
#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 *);
#else
request->server->sin = va_arg(ap, struct sockaddr_in *);
#endif
continue;
/*

View File

@ -5,6 +5,8 @@
* systems.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*
* $FreeBSD$
*/
#ifndef lint
@ -166,11 +168,22 @@ struct sockaddr *sa;
int *len;
{
int ret;
#ifdef INET6
struct sockaddr *sin = sa;
#else
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
#endif
if ((ret = getpeername(sock, sa, len)) >= 0
#ifdef INET6
&& ((sin->su_si.si_family == AF_INET6
&& IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr))
|| (sin->su_si.si_family == AF_INET
&& sin->su_sin.sin_addr.s_addr == 0))) {
#else
&& sa->sa_family == AF_INET
&& sin->sin_addr.s_addr == 0) {
#endif
errno = ENOTCONN;
return (-1);
} else {

View File

@ -15,6 +15,7 @@ CFLAGS+=-DFACILITY=LOG_AUTH -DHOSTS_ACCESS -DNETGROUP -DDAEMON_UMASK=022 \
-DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" \
-DSYS_ERRLIST_DEFINED -DALWAYS_HOSTNAME
CFLAGS+=-DINET6 -DUSE_GETIPNODEBY
SRCS= clean_exit.c diag.c eval.c fix_options.c fromhost.c \
hosts_access.c hosts_ctl.c misc.c myvsyslog.c options.c \

View File

@ -11,6 +11,7 @@ SRCS= tcpdchk.c fakelog.c inetcf.c scaffold.c
CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \
-DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\"
CFLAGS+=-DINET6 -DUSE_GETIPNODEBY
DPADD= ${LIBWRAP}
LDADD= -lwrap