2 ===================================================================
3 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/Makefile,v
4 retrieving revision 1.1.1.1
5 retrieving revision 1.2
6 diff -u -r1.1.1.1 -r1.2
7 --- Makefile 2001/03/02 09:26:27 1.1.1.1
8 +++ Makefile 2001/03/02 09:30:19 1.2
10 @echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix"
11 @echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
12 @echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4"
13 - @echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
14 + @echo " sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
17 @echo "If none of these match your environment, edit the system"
19 NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all
21 # Freebsd and linux by default have no NIS.
24 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
25 LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
26 EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
29 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
30 + LIBS="-L/usr/local/v6/lib -linet6" \
31 LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
32 - EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
33 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" \
37 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
38 + LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
39 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all
42 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
43 LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
44 - NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
45 + NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER -DINET6=1 -Dss_family=__ss_family -Dss_len=__ss_len" all
48 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
49 + LIBS="/usr/inet6/lib/libinet6.a -lresolv" \
50 + RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP= TLI= \
51 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DBROKEN_SO_LINGER -DINET6=1 -Dss_family=sin6_family -Dsockaddr_storage=sockaddr_in6 -I/usr/inet6/include" all
53 # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
54 hpux hpux8 hpux9 hpux10:
56 NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
57 BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all
59 +# SunOS 5.8 is another SYSV4 variant, but has IPv6 support
61 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
62 + LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \
63 + NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
64 + EXTRA_CFLAGS="-DINET6 -DNO_CLONE_DEVICE -DINT32_T" all
68 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
70 # the ones provided with this source distribution. The environ.c module
71 # implements setenv(), getenv(), and putenv().
76 #AUX_OBJ= environ.o strcasecmp.o
79 # host name aliases. Compile with -DSOLARIS_24_GETHOSTBYNAME_BUG to work
80 # around this. The workaround does no harm on other Solaris versions.
82 -BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
83 +#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
84 #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DINET_ADDR_BUG
85 #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DSOLARIS_24_GETHOSTBYNAME_BUG
88 # If your system supports vsyslog(), comment out the following definition.
89 # If in doubt leave it in, it won't harm.
91 -VSYSLOG = -Dvsyslog=myvsyslog
92 +#VSYSLOG = -Dvsyslog=myvsyslog
94 # End of the system dependencies.
95 #################################
97 ===================================================================
98 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/fix_options.c,v
99 retrieving revision 1.1.1.1
100 retrieving revision 1.2
101 diff -u -r1.1.1.1 -r1.2
102 --- fix_options.c 2001/03/02 09:26:27 1.1.1.1
103 +++ fix_options.c 2001/03/02 09:30:19 1.2
106 #include <sys/types.h>
107 #include <sys/param.h>
109 +#include <sys/socket.h>
111 #include <netinet/in.h>
112 #include <netinet/in_systm.h>
113 #include <netinet/ip.h>
117 struct in_addr dummy;
119 + struct sockaddr_storage ss;
123 + * check if this is AF_INET socket
124 + * XXX IPv6 support?
126 + sslen = sizeof(ss);
127 + if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
128 + syslog(LOG_ERR, "getpeername: %m");
129 + clean_exit(request);
131 + if (ss.ss_family != AF_INET)
135 if ((ip = getprotobyname("ip")) != 0)
136 ipproto = ip->p_proto;
137 Index: hosts_access.5
138 ===================================================================
139 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/hosts_access.5,v
140 retrieving revision 1.1.1.1
141 retrieving revision 1.2
142 diff -u -r1.1.1.1 -r1.2
143 --- hosts_access.5 2001/03/02 09:26:27 1.1.1.1
144 +++ hosts_access.5 2001/03/02 09:30:19 1.2
146 for daemon process names or for client user names.
148 An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
149 -`net/mask\' pair. A host address is matched if `net\' is equal to the
150 +`net/mask\' pair. An IPv4 host address is matched if `net\' is equal to the
151 bitwise AND of the address and the `mask\'. For example, the net/mask
152 pattern `131.155.72.0/255.255.254.0\' matches every address in the
153 range `131.155.72.0\' through `131.155.73.255\'.
155 +An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
156 +`[net]/prefixlen\' pair. An IPv6 host address is matched if
157 +`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
158 +address. For example, the [net]/prefixlen pattern
159 +`[3ffe:505:2:1::]/64\' matches every address in the range
160 +`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
162 The access control language supports explicit wildcards:
164 Index: hosts_access.c
165 ===================================================================
166 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/hosts_access.c,v
167 retrieving revision 1.1.1.1
168 retrieving revision 1.2
169 diff -u -r1.1.1.1 -r1.2
170 --- hosts_access.c 2001/03/02 09:26:27 1.1.1.1
171 +++ hosts_access.c 2001/03/02 09:30:19 1.2
173 /* System libraries. */
175 #include <sys/types.h>
177 + typedef uint32_t u_int32_t;
179 #include <sys/param.h>
181 +#include <sys/socket.h>
183 #include <netinet/in.h>
184 #include <arpa/inet.h>
194 extern char *fgets();
197 static int host_match();
198 static int string_match();
199 static int masked_match();
201 +static int masked_match4();
202 +static int masked_match6();
205 /* Size of logical line buffer. */
212 + /* convert IPv4 mapped IPv6 address to IPv4 address */
213 + if (STRN_EQ(string, "::ffff:", 7)
214 + && dot_quad_addr(string + 7) != INADDR_NONE) {
218 if (tok[0] == '.') { /* suffix */
219 n = strlen(string) - strlen(tok);
220 return (n > 0 && STR_EQ(tok, string + n));
221 @@ -299,20 +319,72 @@
222 } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
223 return (STRN_EQ(tok, string, n));
224 } else { /* exact match */
226 + struct addrinfo hints, *res;
227 + struct sockaddr_in6 pat, addr;
232 + if (*tok == '[' && tok[len - 1] == ']') {
234 + tok[len - 1] = '\0';
235 + memset(&hints, 0, sizeof(hints));
236 + hints.ai_family = AF_INET6;
237 + hints.ai_socktype = SOCK_STREAM;
238 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
239 + if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) {
240 + memcpy(&pat, res->ai_addr, sizeof(pat));
244 + if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
246 + memcpy(&addr, res->ai_addr, sizeof(addr));
248 +#ifdef NI_WITHSCOPEID
249 + if (pat.sin6_scope_id != 0 &&
250 + addr.sin6_scope_id != pat.sin6_scope_id)
253 + return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
254 + sizeof(struct in6_addr)));
258 return (STR_EQ(tok, string));
262 /* masked_match - match address against netnumber/netmask */
265 static int masked_match(net_tok, mask_tok, string)
270 + return (masked_match4(net_tok, mask_tok, string) ||
271 + masked_match6(net_tok, mask_tok, string));
274 +static int masked_match4(net_tok, mask_tok, string)
276 +static int masked_match(net_tok, mask_tok, string)
293 * Disallow forms other than dotted quad: the treatment that inet_addr()
296 if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
297 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
299 tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
301 return (NO); /* not tcpd_jump() */
303 return ((addr & mask) == net);
307 +static int masked_match6(net_tok, mask_tok, string)
312 + struct addrinfo hints, *res;
313 + struct sockaddr_in6 net, addr;
315 + int len, mask_len, i = 0;
319 + * Behavior of getaddrinfo() against IPv4-mapped IPv6 address is
320 + * different between KAME and Solaris8. While KAME returns
321 + * AF_INET6, Solaris8 returns AF_INET. So, we avoid this here.
323 + if (STRN_EQ(string, "::ffff:", 7)
324 + && dot_quad_addr(string + 7) != INADDR_NONE)
325 + return (masked_match4(net_tok, mask_tok, string + 7));
327 + memset(&hints, 0, sizeof(hints));
328 + hints.ai_family = AF_INET6;
329 + hints.ai_socktype = SOCK_STREAM;
330 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
331 + if (getaddrinfo(string, NULL, &hints, &res) != 0)
333 + memcpy(&addr, res->ai_addr, sizeof(addr));
336 + /* match IPv6 address against netnumber/prefixlen */
337 + len = strlen(net_tok);
338 + if (*net_tok != '[' || net_tok[len - 1] != ']')
340 + ch = net_tok[len - 1];
341 + net_tok[len - 1] = '\0';
342 + if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) {
343 + net_tok[len - 1] = ch;
346 + memcpy(&net, res->ai_addr, sizeof(net));
348 + net_tok[len - 1] = ch;
349 + if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
352 +#ifdef NI_WITHSCOPEID
353 + if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
356 + while (mask_len > 0) {
357 + if (mask_len < 32) {
358 + mask = htonl(~(0xffffffff >> mask_len));
359 + if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask))
363 + if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
372 ===================================================================
373 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/inetcf.c,v
374 retrieving revision 1.1.1.1
375 retrieving revision 1.2
376 diff -u -r1.1.1.1 -r1.2
377 --- inetcf.c 2001/03/02 09:26:27 1.1.1.1
378 +++ inetcf.c 2001/03/02 09:30:19 1.2
380 * guesses. Shorter names follow longer ones.
382 char *inet_files[] = {
384 + "/usr/local/v6/etc/inet6d.conf", /* KAME */
386 "/private/etc/inetd.conf", /* NEXT */
387 "/etc/inet/inetd.conf", /* SYSV4 */
388 "/usr/etc/inetd.conf", /* IRIX?? */
390 ===================================================================
391 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/misc.c,v
392 retrieving revision 1.1.1.1
393 retrieving revision 1.2
394 diff -u -r1.1.1.1 -r1.2
395 --- misc.c 2001/03/02 09:26:27 1.1.1.1
396 +++ misc.c 2001/03/02 09:30:19 1.2
404 + for (cp = string; cp && *cp; cp++) {
413 + if (bracket == 0 && *cp == delimiter) {
422 if ((cp = strchr(string, delimiter)) != 0)
428 /* dot_quad_addr - convert dotted quad to internal form */
430 ===================================================================
431 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/refuse.c,v
432 retrieving revision 1.1.1.1
433 retrieving revision 1.2
434 diff -u -r1.1.1.1 -r1.2
435 --- refuse.c 2001/03/02 09:26:27 1.1.1.1
436 +++ refuse.c 2001/03/02 09:30:19 1.2
439 struct request_info *request;
442 + syslog(deny_severity, "refused connect from %s (%s)",
443 + eval_client(request), eval_hostaddr(request->client));
445 syslog(deny_severity, "refused connect from %s", eval_client(request));
451 ===================================================================
452 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/rfc931.c,v
453 retrieving revision 1.1.1.1
454 retrieving revision 1.2
455 diff -u -r1.1.1.1 -r1.2
456 --- rfc931.c 2001/03/02 09:26:26 1.1.1.1
457 +++ rfc931.c 2001/03/02 09:30:19 1.2
459 /* rfc931 - return remote user name, given socket structures */
461 void rfc931(rmt_sin, our_sin, dest)
463 +struct sockaddr *rmt_sin;
464 +struct sockaddr *our_sin;
466 struct sockaddr_in *rmt_sin;
467 struct sockaddr_in *our_sin;
474 + struct sockaddr_storage rmt_query_sin;
475 + struct sockaddr_storage our_query_sin;
478 struct sockaddr_in rmt_query_sin;
479 struct sockaddr_in our_query_sin;
481 char user[256]; /* XXX */
482 char buffer[512]; /* XXX */
484 char *result = unknown;
488 + /* address family must be the same */
489 + if (rmt_sin->sa_family != our_sin->sa_family) {
490 + STRN_CPY(dest, result, STRING_LENGTH);
493 + switch (our_sin->sa_family) {
495 + alen = sizeof(struct sockaddr_in);
498 + alen = sizeof(struct sockaddr_in6);
501 + STRN_CPY(dest, result, STRING_LENGTH);
507 * Use one unbuffered stdio stream for writing to and for reading from
508 * the RFC931 etc. server. This is done because of a bug in the SunOS
514 + if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
516 if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
518 setbuf(fp, (char *) 0);
522 * addresses from the query socket.
526 + memcpy(&our_query_sin, our_sin, alen);
527 + memcpy(&rmt_query_sin, rmt_sin, alen);
528 + switch (our_sin->sa_family) {
530 + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
531 + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
534 + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
535 + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
539 + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
541 + connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
544 our_query_sin = *our_sin;
545 our_query_sin.sin_port = htons(ANY_PORT);
546 rmt_query_sin = *rmt_sin;
548 sizeof(our_query_sin)) >= 0 &&
549 connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
550 sizeof(rmt_query_sin)) >= 0) {
554 * Send query to server. Neglect the risk that a 13-byte
558 fprintf(fp, "%u,%u\r\n",
560 + ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
561 + ntohs(((struct sockaddr_in *)our_sin)->sin_port));
563 ntohs(rmt_sin->sin_port),
564 ntohs(our_sin->sin_port));
570 && ferror(fp) == 0 && feof(fp) == 0
571 && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
572 &rmt_port, &our_port, user) == 3
574 + && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
575 + && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
577 && ntohs(rmt_sin->sin_port) == rmt_port
578 && ntohs(our_sin->sin_port) == our_port) {
582 * Strip trailing carriage return. It is part of the
584 ===================================================================
585 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/scaffold.c,v
586 retrieving revision 1.1.1.1
587 retrieving revision 1.2
588 diff -u -r1.1.1.1 -r1.2
589 --- scaffold.c 2001/03/02 09:26:27 1.1.1.1
590 +++ scaffold.c 2001/03/02 09:30:19 1.2
592 #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
596 extern char *malloc();
599 /* Application-specific. */
602 int deny_severity = LOG_WARNING;
603 int rfc931_timeout = RFC931_TIMEOUT;
606 /* dup_hostent - create hostent in one memory block */
608 static struct hostent *dup_hostent(hp)
615 /* find_inet_addr - find all addresses for this host, result to free() */
618 +struct addrinfo *find_inet_addr(host)
621 + struct addrinfo hints, *res;
623 + memset(&hints, 0, sizeof(hints));
624 + hints.ai_family = PF_UNSPEC;
625 + hints.ai_socktype = SOCK_STREAM;
626 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
627 + if (getaddrinfo(host, NULL, &hints, &res) == 0)
630 + memset(&hints, 0, sizeof(hints));
631 + hints.ai_family = PF_UNSPEC;
632 + hints.ai_socktype = SOCK_STREAM;
633 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
634 + if (getaddrinfo(host, NULL, &hints, &res) != 0) {
635 + tcpd_warn("%s: host not found", host);
638 + if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
639 + tcpd_warn("%d: not an internet host", res->ai_family);
643 + if (!res->ai_canonname) {
644 + tcpd_warn("%s: hostname alias", host);
645 + tcpd_warn("(cannot obtain official name)", res->ai_canonname);
646 + } else if (STR_NE(host, res->ai_canonname)) {
647 + tcpd_warn("%s: hostname alias", host);
648 + tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
653 struct hostent *find_inet_addr(host)
658 return (dup_hostent(hp));
662 /* check_dns - give each address thorough workout, return address count */
667 struct request_info request;
669 + struct sockaddr_storage sin;
670 + struct addrinfo *hp, *res;
672 struct sockaddr_in sin;
678 @@ -134,11 +180,18 @@
680 request_init(&request, RQ_CLIENT_SIN, &sin, 0);
681 sock_methods(&request);
683 memset((char *) &sin, 0, sizeof(sin));
684 sin.sin_family = AF_INET;
688 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
689 + memcpy(&sin, res->ai_addr, res->ai_addrlen);
691 for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
692 memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
696 * Force host name and address conversions. Use the request structure
698 tcpd_warn("host address %s->name lookup failed",
699 eval_hostaddr(request.client));
710 ===================================================================
711 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/scaffold.h,v
712 retrieving revision 1.1.1.1
713 retrieving revision 1.2
714 diff -u -r1.1.1.1 -r1.2
715 --- scaffold.h 2001/03/02 09:26:27 1.1.1.1
716 +++ scaffold.h 2001/03/02 09:30:19 1.2
718 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
722 +extern struct addrinfo *find_inet_addr();
724 extern struct hostent *find_inet_addr();
726 extern int check_dns();
727 extern int check_path();
729 ===================================================================
730 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/socket.c,v
731 retrieving revision 1.1.1.1
732 retrieving revision 1.2
733 diff -u -r1.1.1.1 -r1.2
734 --- socket.c 2001/03/02 09:26:27 1.1.1.1
735 +++ socket.c 2001/03/02 09:30:19 1.2
737 #include <sys/types.h>
738 #include <sys/param.h>
739 #include <sys/socket.h>
741 +typedef uint32_t u_int32_t;
743 #include <netinet/in.h>
750 +#ifndef NI_WITHSCOPEID
751 +#define NI_WITHSCOPEID 0
754 extern char *inet_ntoa();
760 void sock_host(request)
761 struct request_info *request;
764 + static struct sockaddr_storage client;
765 + static struct sockaddr_storage server;
767 static struct sockaddr_in client;
768 static struct sockaddr_in server;
772 int fd = request->fd;
774 memset(buf, 0 sizeof(buf));
778 + request->client->sin = (struct sockaddr *)&client;
780 request->client->sin = &client;
784 * Determine the server binding. This is used for client username
786 tcpd_warn("getsockname: %m");
790 + request->server->sin = (struct sockaddr *)&server;
792 request->server->sin = &server;
796 /* sock_hostaddr - map endpoint address to printable form */
797 @@ -125,10 +147,26 @@
798 void sock_hostaddr(host)
799 struct host_info *host;
802 + struct sockaddr *sin = host->sin;
808 + salen = sin->sa_len;
810 + salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
811 + : sizeof(struct sockaddr_in6);
813 + getnameinfo(sin, salen, host->addr, sizeof(host->addr),
814 + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
816 struct sockaddr_in *sin = host->sin;
819 STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
823 /* sock_hostname - map endpoint address to host name */
824 @@ -136,6 +174,160 @@
825 void sock_hostname(host)
826 struct host_info *host;
829 + struct sockaddr *sin = host->sin;
830 + struct sockaddr_in sin4;
831 + struct addrinfo hints, *res, *res0 = NULL;
832 + int salen, alen, err = 1;
833 + char *ap = NULL, *rap, hname[NI_MAXHOST];
836 + if (sin->sa_family == AF_INET6) {
837 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
839 + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
840 + memset(&sin4, 0, sizeof(sin4));
842 + sin4.sin_len = sizeof(sin4);
844 + sin4.sin_family = AF_INET;
845 + sin4.sin_port = sin6->sin6_port;
846 + sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
847 + sin = (struct sockaddr *)&sin4;
850 + switch (sin->sa_family) {
852 + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
853 + alen = sizeof(struct in_addr);
854 + salen = sizeof(struct sockaddr_in);
857 + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
858 + alen = sizeof(struct in6_addr);
859 + salen = sizeof(struct sockaddr_in6);
865 + err = getnameinfo(sin, salen, hname, sizeof(hname),
866 + NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
870 + STRN_CPY(host->name, hname, sizeof(host->name));
872 + /* reject numeric addresses */
873 + memset(&hints, 0, sizeof(hints));
874 + hints.ai_family = sin->sa_family;
875 + hints.ai_socktype = SOCK_STREAM;
876 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
877 + if ((err = getaddrinfo(host->name, NULL, &hints, &res0)) == 0) {
878 + freeaddrinfo(res0);
880 + tcpd_warn("host name/name mismatch: "
881 + "reverse lookup results in non-FQDN %s",
883 + strcpy(host->name, paranoid); /* name is bad, clobber it */
888 + /* we are now sure that this is non-numeric */
891 + * Verify that the address is a member of the address list returned
892 + * by gethostbyname(hostname).
894 + * Verify also that gethostbyaddr() and gethostbyname() return the same
895 + * hostname, or rshd and rlogind may still end up being spoofed.
897 + * On some sites, gethostbyname("localhost") returns "localhost.domain".
898 + * This is a DNS artefact. We treat it as a special case. When we
899 + * can't believe the address list from gethostbyname("localhost")
900 + * we're in big trouble anyway.
903 + memset(&hints, 0, sizeof(hints));
904 + hints.ai_family = sin->sa_family;
905 + hints.ai_socktype = SOCK_STREAM;
906 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
907 + if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) {
910 + * Unable to verify that the host name matches the address. This
911 + * may be a transient problem or a botched name server setup.
914 + tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed",
916 + (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
918 + } else if ((res0->ai_canonname == NULL
919 + || STR_NE(host->name, res0->ai_canonname))
920 + && STR_NE(host->name, "localhost")) {
923 + * The gethostbyaddr() and gethostbyname() calls did not return
924 + * the same hostname. This could be a nameserver configuration
925 + * problem. It could also be that someone is trying to spoof us.
928 + tcpd_warn("host name/name mismatch: %s != %.*s",
929 + host->name, STRING_LENGTH,
930 + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
935 + * The address should be a member of the address list returned by
936 + * gethostbyname(). We should first verify that the h_addrtype
937 + * field is AF_INET, but this program has already caused too much
938 + * grief on systems with broken library code.
941 + for (res = res0; res; res = res->ai_next) {
942 + if (res->ai_family != sin->sa_family)
944 + switch (res->ai_family) {
946 + rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
949 + /* need to check scope_id */
950 + if (((struct sockaddr_in6 *)sin)->sin6_scope_id !=
951 + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) {
954 + rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
959 + if (memcmp(rap, ap, alen) == 0) {
960 + freeaddrinfo(res0);
961 + return; /* name is good, keep it */
966 + * The host name does not map to the initial address. Perhaps
967 + * someone has messed up. Perhaps someone compromised a name
971 + getnameinfo(sin, salen, hname, sizeof(hname),
972 + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
973 + tcpd_warn("host name/address mismatch: %s != %.*s",
974 + hname, STRING_LENGTH,
975 + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
977 + strcpy(host->name, paranoid); /* name is bad, clobber it */
979 + freeaddrinfo(res0);
982 struct sockaddr_in *sin = host->sin;
987 strcpy(host->name, paranoid); /* name is bad, clobber it */
992 /* sock_sink - absorb unreceived IP datagram */
998 + struct sockaddr_storage sin;
1000 struct sockaddr_in sin;
1002 int size = sizeof(sin);
1006 ===================================================================
1007 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/tcpd.c,v
1008 retrieving revision 1.1.1.1
1009 retrieving revision 1.2
1010 diff -u -r1.1.1.1 -r1.2
1011 --- tcpd.c 2001/03/02 09:26:27 1.1.1.1
1012 +++ tcpd.c 2001/03/02 09:30:19 1.2
1013 @@ -120,7 +120,12 @@
1015 /* Report request and invoke the real daemon program. */
1018 + syslog(allow_severity, "connect from %s (%s)",
1019 + eval_client(&request), eval_hostaddr(request.client));
1021 syslog(allow_severity, "connect from %s", eval_client(&request));
1024 (void) execv(path, argv);
1025 syslog(LOG_ERR, "error: cannot execute %s: %m", path);
1027 ===================================================================
1028 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/tcpd.h,v
1029 retrieving revision 1.1.1.1
1030 retrieving revision 1.2
1031 diff -u -r1.1.1.1 -r1.2
1032 --- tcpd.h 2001/03/02 09:26:27 1.1.1.1
1033 +++ tcpd.h 2001/03/02 09:30:19 1.2
1036 char name[STRING_LENGTH]; /* access via eval_hostname(host) */
1037 char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */
1039 + struct sockaddr *sin; /* socket address or 0 */
1041 struct sockaddr_in *sin; /* socket address or 0 */
1043 struct t_unitdata *unit; /* TLI transport address or 0 */
1044 struct request_info *request; /* for shared information */
1047 ===================================================================
1048 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/tcpdchk.c,v
1049 retrieving revision 1.1.1.1
1050 retrieving revision 1.2
1051 diff -u -r1.1.1.1 -r1.2
1052 --- tcpdchk.c 2001/03/02 09:26:27 1.1.1.1
1053 +++ tcpdchk.c 2001/03/02 09:30:19 1.2
1056 #include <sys/types.h>
1057 #include <sys/stat.h>
1059 +#include <sys/socket.h>
1061 #include <netinet/in.h>
1062 #include <arpa/inet.h>
1064 @@ -397,6 +400,31 @@
1069 +static int is_inet6_addr(pat)
1072 + struct addrinfo hints, *res;
1078 + len = strlen(pat);
1079 + if ((ch = pat[len - 1]) != ']')
1081 + pat[len - 1] = '\0';
1082 + memset(&hints, 0, sizeof(hints));
1083 + hints.ai_family = AF_INET6;
1084 + hints.ai_socktype = SOCK_STREAM;
1085 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1086 + if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0)
1087 + freeaddrinfo(res);
1088 + pat[len - 1] = ch;
1089 + return (ret == 0);
1093 /* check_host - criticize host pattern */
1095 static int check_host(pat)
1096 @@ -423,14 +451,27 @@
1099 } else if (mask = split_at(pat, '/')) { /* network/netmask */
1103 + if ((dot_quad_addr(pat) == INADDR_NONE
1104 + || dot_quad_addr(mask) == INADDR_NONE)
1105 + && (!is_inet6_addr(pat)
1106 + || ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
1108 if (dot_quad_addr(pat) == INADDR_NONE
1109 || dot_quad_addr(mask) == INADDR_NONE)
1111 tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
1112 } else if (STR_EQ(pat, "FAIL")) { /* obsolete */
1113 tcpd_warn("FAIL is no longer recognized");
1114 tcpd_warn("(use EXCEPT or DENY instead)");
1115 } else if (reserved_name(pat)) { /* other reserved */
1118 + } else if (is_inet6_addr(pat)) { /* IPv6 address */
1121 } else if (NOT_INADDR(pat)) { /* internet name */
1122 if (pat[strlen(pat) - 1] == '.') {
1123 tcpd_warn("%s: domain or host name ends in dot", pat);
1125 ===================================================================
1126 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/tcpdmatch.c,v
1127 retrieving revision 1.1.1.1
1128 retrieving revision 1.2
1129 diff -u -r1.1.1.1 -r1.2
1130 --- tcpdmatch.c 2001/03/02 09:26:27 1.1.1.1
1131 +++ tcpdmatch.c 2001/03/02 09:30:19 1.2
1137 + struct addrinfo hints, *hp, *res;
1141 char *myname = argv[0];
1149 + struct sockaddr_storage server_sin;
1150 + struct sockaddr_storage client_sin;
1152 struct sockaddr_in server_sin;
1153 struct sockaddr_in client_sin;
1158 @@ -172,13 +181,20 @@
1159 if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
1160 if ((hp = find_inet_addr(server)) == 0)
1163 memset((char *) &server_sin, 0, sizeof(server_sin));
1164 server_sin.sin_family = AF_INET;
1166 request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
1169 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
1170 + memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
1172 for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
1173 memcpy((char *) &server_sin.sin_addr, addr,
1174 sizeof(server_sin.sin_addr));
1178 * Force evaluation of server host name and address. Host name
1179 @@ -194,7 +210,11 @@
1180 fprintf(stderr, "Please specify an address instead\n");
1189 request_set(&request, RQ_SERVER_NAME, server, 0);
1191 @@ -208,6 +228,18 @@
1192 tcpdmatch(&request);
1196 + memset(&hints, 0, sizeof(hints));
1197 + hints.ai_family = AF_INET6;
1198 + hints.ai_socktype = SOCK_STREAM;
1199 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1200 + if (getaddrinfo(client, NULL, &hints, &res) == 0) {
1201 + freeaddrinfo(res);
1202 + request_set(&request, RQ_CLIENT_ADDR, client, 0);
1203 + tcpdmatch(&request);
1209 * Perhaps they are testing special client hostname patterns that aren't
1210 @@ -229,6 +261,34 @@
1212 if ((hp = find_inet_addr(client)) == 0)
1215 + request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1217 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
1218 + memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
1221 + * getnameinfo() doesn't do reverse lookup against link-local
1222 + * address. So, we pass through host name evaluation against
1225 + if (res->ai_family != AF_INET6 ||
1226 + !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
1228 + * Force evaluation of client host name and address. Host name
1229 + * conflicts will be reported while eval_hostname() does its job.
1231 + request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
1232 + if (STR_EQ(eval_hostname(request.client), unknown))
1233 + tcpd_warn("host address %s->name lookup failed",
1234 + eval_hostaddr(request.client));
1236 + tcpdmatch(&request);
1242 memset((char *) &client_sin, 0, sizeof(client_sin));
1243 client_sin.sin_family = AF_INET;
1244 request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1254 ===================================================================
1255 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/tli.c,v
1256 retrieving revision 1.1.1.1
1257 retrieving revision 1.2
1258 diff -u -r1.1.1.1 -r1.2
1259 --- tli.c 2001/03/02 09:26:27 1.1.1.1
1260 +++ tli.c 2001/03/02 09:30:19 1.2
1262 void tli_host(request)
1263 struct request_info *request;
1266 + static struct sockaddr_storage client;
1267 + static struct sockaddr_storage server;
1269 static struct sockaddr_in client;
1270 static struct sockaddr_in server;
1274 * If we discover that we are using an IP transport, pretend we never
1277 tli_endpoints(request);
1278 if ((request->config = tli_transport(request->fd)) != 0
1280 + && (STR_EQ(request->config->nc_protofmly, "inet") ||
1281 + STR_EQ(request->config->nc_protofmly, "inet6"))) {
1283 && STR_EQ(request->config->nc_protofmly, "inet")) {
1285 if (request->client->unit != 0) {
1287 + client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
1288 + request->client->sin = (struct sockaddr *) &client;
1290 client = *(struct sockaddr_in *) request->client->unit->addr.buf;
1291 request->client->sin = &client;
1294 if (request->server->unit != 0) {
1296 + server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
1297 + request->server->sin = (struct sockaddr *) &server;
1299 server = *(struct sockaddr_in *) request->server->unit->addr.buf;
1300 request->server->sin = &server;
1303 tli_cleanup(request);
1304 sock_methods(request);
1305 @@ -187,7 +207,15 @@
1307 while (config = getnetconfig(handlep)) {
1308 if (stat(config->nc_device, &from_config) == 0) {
1309 +#ifdef NO_CLONE_DEVICE
1311 + * If the network devices are not cloned (as is the case for
1312 + * Solaris 8 Beta), we must compare the major device numbers.
1314 + if (major(from_config.st_rdev) == major(from_client.st_rdev))
1316 if (minor(from_config.st_rdev) == major(from_client.st_rdev))
1322 ===================================================================
1323 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/update.c,v
1324 retrieving revision 1.1.1.1
1325 retrieving revision 1.2
1326 diff -u -r1.1.1.1 -r1.2
1327 --- update.c 2001/03/02 09:26:27 1.1.1.1
1328 +++ update.c 2001/03/02 09:30:19 1.2
1330 request->fd = va_arg(ap, int);
1334 + request->client->sin = va_arg(ap, struct sockaddr *);
1336 request->client->sin = va_arg(ap, struct sockaddr_in *);
1341 + request->server->sin = va_arg(ap, struct sockaddr *);
1343 request->server->sin = va_arg(ap, struct sockaddr_in *);
1348 Index: workarounds.c
1349 ===================================================================
1350 RCS file: /cvsroot/usagi/usagi/src/tcp_wrappers/workarounds.c,v
1351 retrieving revision 1.1.1.1
1352 retrieving revision 1.2
1353 diff -u -r1.1.1.1 -r1.2
1354 --- workarounds.c 2001/03/02 09:26:27 1.1.1.1
1355 +++ workarounds.c 2001/03/02 09:30:19 1.2
1356 @@ -166,11 +166,22 @@
1361 + struct sockaddr *sin = sa;
1363 struct sockaddr_in *sin = (struct sockaddr_in *) sa;
1366 if ((ret = getpeername(sock, sa, len)) >= 0
1368 + && ((sin->su_si.si_family == AF_INET6
1369 + && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr))
1370 + || (sin->su_si.si_family == AF_INET
1371 + && sin->su_sin.sin_addr.s_addr == 0))) {
1373 && sa->sa_family == AF_INET
1374 && sin->sin_addr.s_addr == 0) {