Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | Upstream-Status: Backport |
| 2 | |
| 3 | diff -ruN tcp_wrappers_7.6.orig/fix_options.c tcp_wrappers_7.6/fix_options.c |
| 4 | --- tcp_wrappers_7.6.orig/fix_options.c 1997-04-08 02:29:19.000000000 +0200 |
| 5 | +++ tcp_wrappers_7.6/fix_options.c 2004-04-10 19:07:43.000000000 +0200 |
| 6 | @@ -11,6 +11,9 @@ |
| 7 | |
| 8 | #include <sys/types.h> |
| 9 | #include <sys/param.h> |
| 10 | +#ifdef INET6 |
| 11 | +#include <sys/socket.h> |
| 12 | +#endif |
| 13 | #include <netinet/in.h> |
| 14 | #include <netinet/in_systm.h> |
| 15 | #include <netinet/ip.h> |
| 16 | @@ -41,6 +44,22 @@ |
| 17 | unsigned int opt; |
| 18 | int optlen; |
| 19 | struct in_addr dummy; |
| 20 | +#ifdef INET6 |
| 21 | + struct sockaddr_storage ss; |
| 22 | + int sslen; |
| 23 | + |
| 24 | + /* |
| 25 | + * check if this is AF_INET socket |
| 26 | + * XXX IPv6 support? |
| 27 | + */ |
| 28 | + sslen = sizeof(ss); |
| 29 | + if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { |
| 30 | + syslog(LOG_ERR, "getpeername: %m"); |
| 31 | + clean_exit(request); |
| 32 | + } |
| 33 | + if (ss.ss_family != AF_INET) |
| 34 | + return; |
| 35 | +#endif |
| 36 | |
| 37 | if ((ip = getprotobyname("ip")) != 0) |
| 38 | ipproto = ip->p_proto; |
| 39 | diff -ruN tcp_wrappers_7.6.orig/hosts_access.5 tcp_wrappers_7.6/hosts_access.5 |
| 40 | --- tcp_wrappers_7.6.orig/hosts_access.5 2004-04-10 19:22:58.000000000 +0200 |
| 41 | +++ tcp_wrappers_7.6/hosts_access.5 2004-04-10 19:07:43.000000000 +0200 |
| 42 | @@ -85,11 +85,18 @@ |
| 43 | for daemon process names or for client user names. |
| 44 | .IP \(bu |
| 45 | An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a |
| 46 | -`net/mask\' pair. A host address is matched if `net\' is equal to the |
| 47 | +`net/mask\' pair. An IPv4 host address is matched if `net\' is equal to the |
| 48 | bitwise AND of the address and the `mask\'. For example, the net/mask |
| 49 | pattern `131.155.72.0/255.255.254.0\' matches every address in the |
| 50 | range `131.155.72.0\' through `131.155.73.255\'. |
| 51 | .IP \(bu |
| 52 | +An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a |
| 53 | +`[net]/prefixlen\' pair. An IPv6 host address is matched if |
| 54 | +`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the |
| 55 | +address. For example, the [net]/prefixlen pattern |
| 56 | +`[3ffe:505:2:1::]/64\' matches every address in the range |
| 57 | +`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'. |
| 58 | +.IP \(bu |
| 59 | Wildcards `*\' and `?\' can be used to match hostnames or IP addresses. This |
| 60 | method of matching cannot be used in conjunction with `net/mask\' matching, |
| 61 | hostname matching beginning with `.\' or IP address matching ending with `.\'. |
| 62 | diff -ruN tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c |
| 63 | --- tcp_wrappers_7.6.orig/hosts_access.c 2004-04-10 19:22:58.000000000 +0200 |
| 64 | +++ tcp_wrappers_7.6/hosts_access.c 2004-04-10 19:07:43.000000000 +0200 |
| 65 | @@ -24,7 +24,13 @@ |
| 66 | /* System libraries. */ |
| 67 | |
| 68 | #include <sys/types.h> |
| 69 | +#ifdef INT32_T |
| 70 | + typedef uint32_t u_int32_t; |
| 71 | +#endif |
| 72 | #include <sys/param.h> |
| 73 | +#ifdef INET6 |
| 74 | +#include <sys/socket.h> |
| 75 | +#endif |
| 76 | #include <netinet/in.h> |
| 77 | #include <arpa/inet.h> |
| 78 | #include <stdio.h> |
| 79 | @@ -33,6 +39,9 @@ |
| 80 | #include <errno.h> |
| 81 | #include <setjmp.h> |
| 82 | #include <string.h> |
| 83 | +#ifdef INET6 |
| 84 | +#include <netdb.h> |
| 85 | +#endif |
| 86 | |
| 87 | extern char *fgets(); |
| 88 | extern int errno; |
| 89 | @@ -82,6 +91,10 @@ |
| 90 | static int host_match(); |
| 91 | static int string_match(); |
| 92 | static int masked_match(); |
| 93 | +#ifdef INET6 |
| 94 | +static int masked_match4(); |
| 95 | +static int masked_match6(); |
| 96 | +#endif |
| 97 | |
| 98 | /* Size of logical line buffer. */ |
| 99 | |
| 100 | @@ -289,6 +302,13 @@ |
| 101 | { |
| 102 | int n; |
| 103 | |
| 104 | +#ifdef INET6 |
| 105 | + /* convert IPv4 mapped IPv6 address to IPv4 address */ |
| 106 | + if (STRN_EQ(string, "::ffff:", 7) |
| 107 | + && dot_quad_addr(string + 7) != INADDR_NONE) { |
| 108 | + string += 7; |
| 109 | + } |
| 110 | +#endif |
| 111 | #ifndef DISABLE_WILDCARD_MATCHING |
| 112 | if (strchr(tok, '*') || strchr(tok,'?')) { /* contains '*' or '?' */ |
| 113 | return (match_pattern_ylo(string,tok)); |
| 114 | @@ -304,20 +324,72 @@ |
| 115 | } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ |
| 116 | return (STRN_EQ(tok, string, n)); |
| 117 | } else { /* exact match */ |
| 118 | +#ifdef INET6 |
| 119 | + struct addrinfo hints, *res; |
| 120 | + struct sockaddr_in6 pat, addr; |
| 121 | + int len, ret; |
| 122 | + char ch; |
| 123 | + |
| 124 | + len = strlen(tok); |
| 125 | + if (*tok == '[' && tok[len - 1] == ']') { |
| 126 | + ch = tok[len - 1]; |
| 127 | + tok[len - 1] = '\0'; |
| 128 | + memset(&hints, 0, sizeof(hints)); |
| 129 | + hints.ai_family = AF_INET6; |
| 130 | + hints.ai_socktype = SOCK_STREAM; |
| 131 | + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
| 132 | + if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) { |
| 133 | + memcpy(&pat, res->ai_addr, sizeof(pat)); |
| 134 | + freeaddrinfo(res); |
| 135 | + } |
| 136 | + tok[len - 1] = ch; |
| 137 | + if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0) |
| 138 | + return NO; |
| 139 | + memcpy(&addr, res->ai_addr, sizeof(addr)); |
| 140 | + freeaddrinfo(res); |
| 141 | +#ifdef NI_WITHSCOPEID |
| 142 | + if (pat.sin6_scope_id != 0 && |
| 143 | + addr.sin6_scope_id != pat.sin6_scope_id) |
| 144 | + return NO; |
| 145 | +#endif |
| 146 | + return (!memcmp(&pat.sin6_addr, &addr.sin6_addr, |
| 147 | + sizeof(struct in6_addr))); |
| 148 | + return (ret); |
| 149 | + } |
| 150 | +#endif |
| 151 | return (STR_EQ(tok, string)); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | /* masked_match - match address against netnumber/netmask */ |
| 156 | |
| 157 | +#ifdef INET6 |
| 158 | static int masked_match(net_tok, mask_tok, string) |
| 159 | char *net_tok; |
| 160 | char *mask_tok; |
| 161 | char *string; |
| 162 | { |
| 163 | + return (masked_match4(net_tok, mask_tok, string) || |
| 164 | + masked_match6(net_tok, mask_tok, string)); |
| 165 | +} |
| 166 | + |
| 167 | +static int masked_match4(net_tok, mask_tok, string) |
| 168 | +#else |
| 169 | +static int masked_match(net_tok, mask_tok, string) |
| 170 | +#endif |
| 171 | +char *net_tok; |
| 172 | +char *mask_tok; |
| 173 | +char *string; |
| 174 | +{ |
| 175 | +#ifdef INET6 |
| 176 | + u_int32_t net; |
| 177 | + u_int32_t mask; |
| 178 | + u_int32_t addr; |
| 179 | +#else |
| 180 | unsigned long net; |
| 181 | unsigned long mask; |
| 182 | unsigned long addr; |
| 183 | +#endif |
| 184 | |
| 185 | /* |
| 186 | * Disallow forms other than dotted quad: the treatment that inet_addr() |
| 187 | @@ -329,12 +401,78 @@ |
| 188 | return (NO); |
| 189 | if ((net = dot_quad_addr(net_tok)) == INADDR_NONE |
| 190 | || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) { |
| 191 | +#ifndef INET6 |
| 192 | tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); |
| 193 | +#endif |
| 194 | return (NO); /* not tcpd_jump() */ |
| 195 | } |
| 196 | return ((addr & mask) == net); |
| 197 | } |
| 198 | |
| 199 | +#ifdef INET6 |
| 200 | +static int masked_match6(net_tok, mask_tok, string) |
| 201 | +char *net_tok; |
| 202 | +char *mask_tok; |
| 203 | +char *string; |
| 204 | +{ |
| 205 | + struct addrinfo hints, *res; |
| 206 | + struct sockaddr_in6 net, addr; |
| 207 | + u_int32_t mask; |
| 208 | + int len, mask_len, i = 0; |
| 209 | + char ch; |
| 210 | + |
| 211 | + memset(&hints, 0, sizeof(hints)); |
| 212 | + hints.ai_family = AF_INET6; |
| 213 | + hints.ai_socktype = SOCK_STREAM; |
| 214 | + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
| 215 | + if (getaddrinfo(string, NULL, &hints, &res) != 0) |
| 216 | + return NO; |
| 217 | + memcpy(&addr, res->ai_addr, sizeof(addr)); |
| 218 | + freeaddrinfo(res); |
| 219 | + |
| 220 | + if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) { |
| 221 | + if ((*(u_int32_t *)&net.sin6_addr.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE |
| 222 | + || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) |
| 223 | + return (NO); |
| 224 | + return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]); |
| 225 | + } |
| 226 | + |
| 227 | + /* match IPv6 address against netnumber/prefixlen */ |
| 228 | + len = strlen(net_tok); |
| 229 | + if (*net_tok != '[' || net_tok[len - 1] != ']') |
| 230 | + return NO; |
| 231 | + ch = net_tok[len - 1]; |
| 232 | + net_tok[len - 1] = '\0'; |
| 233 | + if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) { |
| 234 | + net_tok[len - 1] = ch; |
| 235 | + return NO; |
| 236 | + } |
| 237 | + memcpy(&net, res->ai_addr, sizeof(net)); |
| 238 | + freeaddrinfo(res); |
| 239 | + net_tok[len - 1] = ch; |
| 240 | + if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128) |
| 241 | + return NO; |
| 242 | + |
| 243 | +#ifdef NI_WITHSCOPEID |
| 244 | + if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id) |
| 245 | + return NO; |
| 246 | +#endif |
| 247 | + while (mask_len > 0) { |
| 248 | + if (mask_len < 32) { |
| 249 | + mask = htonl(~(0xffffffff >> mask_len)); |
| 250 | + if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask)) |
| 251 | + return NO; |
| 252 | + break; |
| 253 | + } |
| 254 | + if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i]) |
| 255 | + return NO; |
| 256 | + i += 4; |
| 257 | + mask_len -= 32; |
| 258 | + } |
| 259 | + return YES; |
| 260 | +} |
| 261 | +#endif /* INET6 */ |
| 262 | + |
| 263 | #ifndef DISABLE_WILDCARD_MATCHING |
| 264 | /* Note: this feature has been adapted in a pretty straightforward way |
| 265 | from Tatu Ylonen's last SSH version under free license by |
| 266 | diff -ruN tcp_wrappers_7.6.orig/Makefile tcp_wrappers_7.6/Makefile |
| 267 | --- tcp_wrappers_7.6.orig/Makefile 1997-03-21 19:27:21.000000000 +0100 |
| 268 | +++ tcp_wrappers_7.6/Makefile 2004-04-10 19:22:44.000000000 +0200 |
| 269 | @@ -21,7 +21,7 @@ |
| 270 | @echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix" |
| 271 | @echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211" |
| 272 | @echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4" |
| 273 | - @echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2" |
| 274 | + @echo " sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2" |
| 275 | @echo " uts215 uxp" |
| 276 | @echo |
| 277 | @echo "If none of these match your environment, edit the system" |
| 278 | @@ -131,20 +131,34 @@ |
| 279 | NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all |
| 280 | |
| 281 | # Freebsd and linux by default have no NIS. |
| 282 | -386bsd netbsd bsdos: |
| 283 | +386bsd bsdos: |
| 284 | @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 285 | LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \ |
| 286 | EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all |
| 287 | |
| 288 | freebsd: |
| 289 | @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 290 | + LIBS="-L/usr/local/v6/lib -linet6" \ |
| 291 | LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \ |
| 292 | - EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all |
| 293 | + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" \ |
| 294 | + VSYSLOG= all |
| 295 | + |
| 296 | +netbsd: |
| 297 | + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 298 | + LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \ |
| 299 | + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all |
| 300 | |
| 301 | linux: |
| 302 | @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 303 | - LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \ |
| 304 | - NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all |
| 305 | + LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \ |
| 306 | + NETGROUP="-DNETGROUP" TLI= VSYSLOG= BUGS= \ |
| 307 | + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR -DINET6=1 -Dss_family=__ss_family -Dss_len=__ss_len" all |
| 308 | + |
| 309 | +gnu: |
| 310 | + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 311 | + LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \ |
| 312 | + NETGROUP=-DNETGROUP TLI= VSYSLOG= BUGS= \ |
| 313 | + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR" all |
| 314 | |
| 315 | # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x. |
| 316 | hpux hpux8 hpux9 hpux10: |
| 317 | @@ -196,6 +210,13 @@ |
| 318 | NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \ |
| 319 | BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all |
| 320 | |
| 321 | +# SunOS 5.8 is another SYSV4 variant, but has IPv6 support |
| 322 | +solaris8: |
| 323 | + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 324 | + LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \ |
| 325 | + NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \ |
| 326 | + EXTRA_CFLAGS="-DINET6 -DNO_CLONE_DEVICE -DINT32_T" all |
| 327 | + |
| 328 | # Generic SYSV40 |
| 329 | esix sysv4: |
| 330 | @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ |
| 331 | diff -ruN tcp_wrappers_7.6.orig/misc.c tcp_wrappers_7.6/misc.c |
| 332 | --- tcp_wrappers_7.6.orig/misc.c 1996-02-11 17:01:30.000000000 +0100 |
| 333 | +++ tcp_wrappers_7.6/misc.c 2004-04-10 19:07:43.000000000 +0200 |
| 334 | @@ -58,9 +58,31 @@ |
| 335 | { |
| 336 | char *cp; |
| 337 | |
| 338 | +#ifdef INET6 |
| 339 | + int bracket = 0; |
| 340 | + |
| 341 | + for (cp = string; cp && *cp; cp++) { |
| 342 | + switch (*cp) { |
| 343 | + case '[': |
| 344 | + bracket++; |
| 345 | + break; |
| 346 | + case ']': |
| 347 | + bracket--; |
| 348 | + break; |
| 349 | + default: |
| 350 | + if (bracket == 0 && *cp == delimiter) { |
| 351 | + *cp++ = 0; |
| 352 | + return cp; |
| 353 | + } |
| 354 | + break; |
| 355 | + } |
| 356 | + } |
| 357 | + return (NULL); |
| 358 | +#else |
| 359 | if ((cp = strchr(string, delimiter)) != 0) |
| 360 | *cp++ = 0; |
| 361 | return (cp); |
| 362 | +#endif |
| 363 | } |
| 364 | |
| 365 | /* dot_quad_addr - convert dotted quad to internal form */ |
| 366 | diff -ruN tcp_wrappers_7.6.orig/refuse.c tcp_wrappers_7.6/refuse.c |
| 367 | --- tcp_wrappers_7.6.orig/refuse.c 1994-12-28 17:42:40.000000000 +0100 |
| 368 | +++ tcp_wrappers_7.6/refuse.c 2004-04-10 19:07:43.000000000 +0200 |
| 369 | @@ -25,7 +25,12 @@ |
| 370 | void refuse(request) |
| 371 | struct request_info *request; |
| 372 | { |
| 373 | +#ifdef INET6 |
| 374 | + syslog(deny_severity, "refused connect from %s (%s)", |
| 375 | + eval_client(request), eval_hostaddr(request->client)); |
| 376 | +#else |
| 377 | syslog(deny_severity, "refused connect from %s", eval_client(request)); |
| 378 | +#endif |
| 379 | clean_exit(request); |
| 380 | /* NOTREACHED */ |
| 381 | } |
| 382 | diff -ruN tcp_wrappers_7.6.orig/rfc931.c tcp_wrappers_7.6/rfc931.c |
| 383 | --- tcp_wrappers_7.6.orig/rfc931.c 1995-01-02 16:11:34.000000000 +0100 |
| 384 | +++ tcp_wrappers_7.6/rfc931.c 2004-04-10 19:07:43.000000000 +0200 |
| 385 | @@ -68,20 +68,50 @@ |
| 386 | /* rfc931 - return remote user name, given socket structures */ |
| 387 | |
| 388 | void rfc931(rmt_sin, our_sin, dest) |
| 389 | +#ifdef INET6 |
| 390 | +struct sockaddr *rmt_sin; |
| 391 | +struct sockaddr *our_sin; |
| 392 | +#else |
| 393 | struct sockaddr_in *rmt_sin; |
| 394 | struct sockaddr_in *our_sin; |
| 395 | +#endif |
| 396 | char *dest; |
| 397 | { |
| 398 | unsigned rmt_port; |
| 399 | unsigned our_port; |
| 400 | +#ifdef INET6 |
| 401 | + struct sockaddr_storage rmt_query_sin; |
| 402 | + struct sockaddr_storage our_query_sin; |
| 403 | + int alen; |
| 404 | +#else |
| 405 | struct sockaddr_in rmt_query_sin; |
| 406 | struct sockaddr_in our_query_sin; |
| 407 | +#endif |
| 408 | char user[256]; /* XXX */ |
| 409 | char buffer[512]; /* XXX */ |
| 410 | char *cp; |
| 411 | char *result = unknown; |
| 412 | FILE *fp; |
| 413 | |
| 414 | +#ifdef INET6 |
| 415 | + /* address family must be the same */ |
| 416 | + if (rmt_sin->sa_family != our_sin->sa_family) { |
| 417 | + STRN_CPY(dest, result, STRING_LENGTH); |
| 418 | + return; |
| 419 | + } |
| 420 | + switch (our_sin->sa_family) { |
| 421 | + case AF_INET: |
| 422 | + alen = sizeof(struct sockaddr_in); |
| 423 | + break; |
| 424 | + case AF_INET6: |
| 425 | + alen = sizeof(struct sockaddr_in6); |
| 426 | + break; |
| 427 | + default: |
| 428 | + STRN_CPY(dest, result, STRING_LENGTH); |
| 429 | + return; |
| 430 | + } |
| 431 | +#endif |
| 432 | + |
| 433 | /* |
| 434 | * Use one unbuffered stdio stream for writing to and for reading from |
| 435 | * the RFC931 etc. server. This is done because of a bug in the SunOS |
| 436 | @@ -92,7 +122,11 @@ |
| 437 | * sockets. |
| 438 | */ |
| 439 | |
| 440 | +#ifdef INET6 |
| 441 | + if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) { |
| 442 | +#else |
| 443 | if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) { |
| 444 | +#endif |
| 445 | setbuf(fp, (char *) 0); |
| 446 | |
| 447 | /* |
| 448 | @@ -112,6 +146,25 @@ |
| 449 | * addresses from the query socket. |
| 450 | */ |
| 451 | |
| 452 | +#ifdef INET6 |
| 453 | + memcpy(&our_query_sin, our_sin, alen); |
| 454 | + memcpy(&rmt_query_sin, rmt_sin, alen); |
| 455 | + switch (our_sin->sa_family) { |
| 456 | + case AF_INET: |
| 457 | + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT); |
| 458 | + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT); |
| 459 | + break; |
| 460 | + case AF_INET6: |
| 461 | + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT); |
| 462 | + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT); |
| 463 | + break; |
| 464 | + } |
| 465 | + |
| 466 | + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin, |
| 467 | + alen) >= 0 && |
| 468 | + connect(fileno(fp), (struct sockaddr *) & rmt_query_sin, |
| 469 | + alen) >= 0) { |
| 470 | +#else |
| 471 | our_query_sin = *our_sin; |
| 472 | our_query_sin.sin_port = htons(ANY_PORT); |
| 473 | rmt_query_sin = *rmt_sin; |
| 474 | @@ -121,6 +174,7 @@ |
| 475 | sizeof(our_query_sin)) >= 0 && |
| 476 | connect(fileno(fp), (struct sockaddr *) & rmt_query_sin, |
| 477 | sizeof(rmt_query_sin)) >= 0) { |
| 478 | +#endif |
| 479 | |
| 480 | /* |
| 481 | * Send query to server. Neglect the risk that a 13-byte |
| 482 | @@ -129,8 +183,13 @@ |
| 483 | */ |
| 484 | |
| 485 | fprintf(fp, "%u,%u\r\n", |
| 486 | +#ifdef INET6 |
| 487 | + ntohs(((struct sockaddr_in *)rmt_sin)->sin_port), |
| 488 | + ntohs(((struct sockaddr_in *)our_sin)->sin_port)); |
| 489 | +#else |
| 490 | ntohs(rmt_sin->sin_port), |
| 491 | ntohs(our_sin->sin_port)); |
| 492 | +#endif |
| 493 | fflush(fp); |
| 494 | |
| 495 | /* |
| 496 | @@ -144,8 +203,13 @@ |
| 497 | && ferror(fp) == 0 && feof(fp) == 0 |
| 498 | && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s", |
| 499 | &rmt_port, &our_port, user) == 3 |
| 500 | +#ifdef INET6 |
| 501 | + && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port |
| 502 | + && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) { |
| 503 | +#else |
| 504 | && ntohs(rmt_sin->sin_port) == rmt_port |
| 505 | && ntohs(our_sin->sin_port) == our_port) { |
| 506 | +#endif |
| 507 | |
| 508 | /* |
| 509 | * Strip trailing carriage return. It is part of the |
| 510 | diff -ruN tcp_wrappers_7.6.orig/scaffold.c tcp_wrappers_7.6/scaffold.c |
| 511 | --- tcp_wrappers_7.6.orig/scaffold.c 1997-03-21 19:27:24.000000000 +0100 |
| 512 | +++ tcp_wrappers_7.6/scaffold.c 2004-04-10 19:07:43.000000000 +0200 |
| 513 | @@ -25,7 +25,9 @@ |
| 514 | #define INADDR_NONE (-1) /* XXX should be 0xffffffff */ |
| 515 | #endif |
| 516 | |
| 517 | +#ifndef INET6 |
| 518 | extern char *malloc(); |
| 519 | +#endif |
| 520 | |
| 521 | /* Application-specific. */ |
| 522 | |
| 523 | @@ -39,6 +41,7 @@ |
| 524 | int deny_severity = LOG_WARNING; |
| 525 | int rfc931_timeout = RFC931_TIMEOUT; |
| 526 | |
| 527 | +#ifndef INET6 |
| 528 | /* dup_hostent - create hostent in one memory block */ |
| 529 | |
| 530 | static struct hostent *dup_hostent(hp) |
| 531 | @@ -73,9 +76,46 @@ |
| 532 | } |
| 533 | return (&hb->host); |
| 534 | } |
| 535 | +#endif |
| 536 | |
| 537 | /* find_inet_addr - find all addresses for this host, result to free() */ |
| 538 | |
| 539 | +#ifdef INET6 |
| 540 | +struct addrinfo *find_inet_addr(host) |
| 541 | +char *host; |
| 542 | +{ |
| 543 | + struct addrinfo hints, *res; |
| 544 | + |
| 545 | + memset(&hints, 0, sizeof(hints)); |
| 546 | + hints.ai_family = PF_UNSPEC; |
| 547 | + hints.ai_socktype = SOCK_STREAM; |
| 548 | + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
| 549 | + if (getaddrinfo(host, NULL, &hints, &res) == 0) |
| 550 | + return (res); |
| 551 | + |
| 552 | + memset(&hints, 0, sizeof(hints)); |
| 553 | + hints.ai_family = PF_UNSPEC; |
| 554 | + hints.ai_socktype = SOCK_STREAM; |
| 555 | + hints.ai_flags = AI_PASSIVE | AI_CANONNAME; |
| 556 | + if (getaddrinfo(host, NULL, &hints, &res) != 0) { |
| 557 | + tcpd_warn("%s: host not found", host); |
| 558 | + return (0); |
| 559 | + } |
| 560 | + if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) { |
| 561 | + tcpd_warn("%d: not an internet host", res->ai_family); |
| 562 | + freeaddrinfo(res); |
| 563 | + return (0); |
| 564 | + } |
| 565 | + if (!res->ai_canonname) { |
| 566 | + tcpd_warn("%s: hostname alias", host); |
| 567 | + tcpd_warn("(cannot obtain official name)", res->ai_canonname); |
| 568 | + } else if (STR_NE(host, res->ai_canonname)) { |
| 569 | + tcpd_warn("%s: hostname alias", host); |
| 570 | + tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname); |
| 571 | + } |
| 572 | + return (res); |
| 573 | +} |
| 574 | +#else |
| 575 | struct hostent *find_inet_addr(host) |
| 576 | char *host; |
| 577 | { |
| 578 | @@ -118,6 +158,7 @@ |
| 579 | } |
| 580 | return (dup_hostent(hp)); |
| 581 | } |
| 582 | +#endif |
| 583 | |
| 584 | /* check_dns - give each address thorough workout, return address count */ |
| 585 | |
| 586 | @@ -125,8 +166,13 @@ |
| 587 | char *host; |
| 588 | { |
| 589 | struct request_info request; |
| 590 | +#ifdef INET6 |
| 591 | + struct sockaddr_storage sin; |
| 592 | + struct addrinfo *hp, *res; |
| 593 | +#else |
| 594 | struct sockaddr_in sin; |
| 595 | struct hostent *hp; |
| 596 | +#endif |
| 597 | int count; |
| 598 | char *addr; |
| 599 | |
| 600 | @@ -134,11 +180,18 @@ |
| 601 | return (0); |
| 602 | request_init(&request, RQ_CLIENT_SIN, &sin, 0); |
| 603 | sock_methods(&request); |
| 604 | +#ifndef INET6 |
| 605 | memset((char *) &sin, 0, sizeof(sin)); |
| 606 | sin.sin_family = AF_INET; |
| 607 | +#endif |
| 608 | |
| 609 | +#ifdef INET6 |
| 610 | + for (res = hp, count = 0; res; res = res->ai_next, count++) { |
| 611 | + memcpy(&sin, res->ai_addr, res->ai_addrlen); |
| 612 | +#else |
| 613 | for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { |
| 614 | memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr)); |
| 615 | +#endif |
| 616 | |
| 617 | /* |
| 618 | * Force host name and address conversions. Use the request structure |
| 619 | @@ -151,7 +204,11 @@ |
| 620 | tcpd_warn("host address %s->name lookup failed", |
| 621 | eval_hostaddr(request.client)); |
| 622 | } |
| 623 | +#ifdef INET6 |
| 624 | + freeaddrinfo(hp); |
| 625 | +#else |
| 626 | free((char *) hp); |
| 627 | +#endif |
| 628 | return (count); |
| 629 | } |
| 630 | |
| 631 | diff -ruN tcp_wrappers_7.6.orig/scaffold.h tcp_wrappers_7.6/scaffold.h |
| 632 | --- tcp_wrappers_7.6.orig/scaffold.h 1994-12-31 18:19:20.000000000 +0100 |
| 633 | +++ tcp_wrappers_7.6/scaffold.h 2004-04-10 19:07:43.000000000 +0200 |
| 634 | @@ -4,6 +4,10 @@ |
| 635 | * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. |
| 636 | */ |
| 637 | |
| 638 | +#ifdef INET6 |
| 639 | +extern struct addrinfo *find_inet_addr(); |
| 640 | +#else |
| 641 | extern struct hostent *find_inet_addr(); |
| 642 | +#endif |
| 643 | extern int check_dns(); |
| 644 | extern int check_path(); |
| 645 | diff -ruN tcp_wrappers_7.6.orig/socket.c tcp_wrappers_7.6/socket.c |
| 646 | --- tcp_wrappers_7.6.orig/socket.c 2004-04-10 19:22:58.000000000 +0200 |
| 647 | +++ tcp_wrappers_7.6/socket.c 2004-04-10 19:07:43.000000000 +0200 |
| 648 | @@ -24,13 +24,22 @@ |
| 649 | #include <sys/types.h> |
| 650 | #include <sys/param.h> |
| 651 | #include <sys/socket.h> |
| 652 | +#ifdef INT32_T |
| 653 | +typedef uint32_t u_int32_t; |
| 654 | +#endif |
| 655 | #include <netinet/in.h> |
| 656 | #include <netdb.h> |
| 657 | #include <stdio.h> |
| 658 | #include <syslog.h> |
| 659 | #include <string.h> |
| 660 | |
| 661 | +#ifdef INET6 |
| 662 | +#ifndef NI_WITHSCOPEID |
| 663 | +#define NI_WITHSCOPEID 0 |
| 664 | +#endif |
| 665 | +#else |
| 666 | extern char *inet_ntoa(); |
| 667 | +#endif |
| 668 | |
| 669 | /* Local stuff. */ |
| 670 | |
| 671 | @@ -79,8 +88,13 @@ |
| 672 | void sock_host(request) |
| 673 | struct request_info *request; |
| 674 | { |
| 675 | +#ifdef INET6 |
| 676 | + static struct sockaddr_storage client; |
| 677 | + static struct sockaddr_storage server; |
| 678 | +#else |
| 679 | static struct sockaddr_in client; |
| 680 | static struct sockaddr_in server; |
| 681 | +#endif |
| 682 | int len; |
| 683 | char buf[BUFSIZ]; |
| 684 | int fd = request->fd; |
| 685 | @@ -109,7 +123,11 @@ |
| 686 | memset(buf, 0 sizeof(buf)); |
| 687 | #endif |
| 688 | } |
| 689 | +#ifdef INET6 |
| 690 | + request->client->sin = (struct sockaddr *)&client; |
| 691 | +#else |
| 692 | request->client->sin = &client; |
| 693 | +#endif |
| 694 | |
| 695 | /* |
| 696 | * Determine the server binding. This is used for client username |
| 697 | @@ -122,7 +140,11 @@ |
| 698 | tcpd_warn("getsockname: %m"); |
| 699 | return; |
| 700 | } |
| 701 | +#ifdef INET6 |
| 702 | + request->server->sin = (struct sockaddr *)&server; |
| 703 | +#else |
| 704 | request->server->sin = &server; |
| 705 | +#endif |
| 706 | } |
| 707 | |
| 708 | /* sock_hostaddr - map endpoint address to printable form */ |
| 709 | @@ -130,10 +152,26 @@ |
| 710 | void sock_hostaddr(host) |
| 711 | struct host_info *host; |
| 712 | { |
| 713 | +#ifdef INET6 |
| 714 | + struct sockaddr *sin = host->sin; |
| 715 | + int salen; |
| 716 | + |
| 717 | + if (!sin) |
| 718 | + return; |
| 719 | +#ifdef SIN6_LEN |
| 720 | + salen = sin->sa_len; |
| 721 | +#else |
| 722 | + salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in) |
| 723 | + : sizeof(struct sockaddr_in6); |
| 724 | +#endif |
| 725 | + getnameinfo(sin, salen, host->addr, sizeof(host->addr), |
| 726 | + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); |
| 727 | +#else |
| 728 | struct sockaddr_in *sin = host->sin; |
| 729 | |
| 730 | if (sin != 0) |
| 731 | STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); |
| 732 | +#endif |
| 733 | } |
| 734 | |
| 735 | /* sock_hostname - map endpoint address to host name */ |
| 736 | @@ -141,6 +179,160 @@ |
| 737 | void sock_hostname(host) |
| 738 | struct host_info *host; |
| 739 | { |
| 740 | +#ifdef INET6 |
| 741 | + struct sockaddr *sin = host->sin; |
| 742 | + struct sockaddr_in sin4; |
| 743 | + struct addrinfo hints, *res, *res0 = NULL; |
| 744 | + int salen, alen, err = 1; |
| 745 | + char *ap = NULL, *rap, hname[NI_MAXHOST]; |
| 746 | + |
| 747 | + if (sin != NULL) { |
| 748 | + if (sin->sa_family == AF_INET6) { |
| 749 | + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin; |
| 750 | + |
| 751 | + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { |
| 752 | + memset(&sin4, 0, sizeof(sin4)); |
| 753 | +#ifdef SIN6_LEN |
| 754 | + sin4.sin_len = sizeof(sin4); |
| 755 | +#endif |
| 756 | + sin4.sin_family = AF_INET; |
| 757 | + sin4.sin_port = sin6->sin6_port; |
| 758 | + sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12]; |
| 759 | + sin = (struct sockaddr *)&sin4; |
| 760 | + } |
| 761 | + } |
| 762 | + switch (sin->sa_family) { |
| 763 | + case AF_INET: |
| 764 | + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr; |
| 765 | + alen = sizeof(struct in_addr); |
| 766 | + salen = sizeof(struct sockaddr_in); |
| 767 | + break; |
| 768 | + case AF_INET6: |
| 769 | + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr; |
| 770 | + alen = sizeof(struct in6_addr); |
| 771 | + salen = sizeof(struct sockaddr_in6); |
| 772 | + break; |
| 773 | + default: |
| 774 | + break; |
| 775 | + } |
| 776 | + if (ap) |
| 777 | + err = getnameinfo(sin, salen, hname, sizeof(hname), |
| 778 | + NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD); |
| 779 | + } |
| 780 | + if (!err) { |
| 781 | + |
| 782 | + STRN_CPY(host->name, hname, sizeof(host->name)); |
| 783 | + |
| 784 | + /* reject numeric addresses */ |
| 785 | + memset(&hints, 0, sizeof(hints)); |
| 786 | + hints.ai_family = sin->sa_family; |
| 787 | + hints.ai_socktype = SOCK_STREAM; |
| 788 | + hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST; |
| 789 | + if ((err = getaddrinfo(host->name, NULL, &hints, &res0) == 0)) { |
| 790 | + freeaddrinfo(res0); |
| 791 | + res0 = NULL; |
| 792 | + tcpd_warn("host name/name mismatch: " |
| 793 | + "reverse lookup results in non-FQDN %s", |
| 794 | + host->name); |
| 795 | + strcpy(host->name, paranoid); /* name is bad, clobber it */ |
| 796 | + } |
| 797 | + err = !err; |
| 798 | + } |
| 799 | + if (!err) { |
| 800 | + /* we are now sure that this is non-numeric */ |
| 801 | + |
| 802 | + /* |
| 803 | + * Verify that the address is a member of the address list returned |
| 804 | + * by gethostbyname(hostname). |
| 805 | + * |
| 806 | + * Verify also that gethostbyaddr() and gethostbyname() return the same |
| 807 | + * hostname, or rshd and rlogind may still end up being spoofed. |
| 808 | + * |
| 809 | + * On some sites, gethostbyname("localhost") returns "localhost.domain". |
| 810 | + * This is a DNS artefact. We treat it as a special case. When we |
| 811 | + * can't believe the address list from gethostbyname("localhost") |
| 812 | + * we're in big trouble anyway. |
| 813 | + */ |
| 814 | + |
| 815 | + memset(&hints, 0, sizeof(hints)); |
| 816 | + hints.ai_family = sin->sa_family; |
| 817 | + hints.ai_socktype = SOCK_STREAM; |
| 818 | + hints.ai_flags = AI_PASSIVE | AI_CANONNAME; |
| 819 | + if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) { |
| 820 | + |
| 821 | + /* |
| 822 | + * Unable to verify that the host name matches the address. This |
| 823 | + * may be a transient problem or a botched name server setup. |
| 824 | + */ |
| 825 | + |
| 826 | + tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed", |
| 827 | + host->name, |
| 828 | + (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6"); |
| 829 | + |
| 830 | + } else if ((res0->ai_canonname == NULL |
| 831 | + || STR_NE(host->name, res0->ai_canonname)) |
| 832 | + && STR_NE(host->name, "localhost")) { |
| 833 | + |
| 834 | + /* |
| 835 | + * The gethostbyaddr() and gethostbyname() calls did not return |
| 836 | + * the same hostname. This could be a nameserver configuration |
| 837 | + * problem. It could also be that someone is trying to spoof us. |
| 838 | + */ |
| 839 | + |
| 840 | + tcpd_warn("host name/name mismatch: %s != %.*s", |
| 841 | + host->name, STRING_LENGTH, |
| 842 | + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname); |
| 843 | + |
| 844 | + } else { |
| 845 | + |
| 846 | + /* |
| 847 | + * The address should be a member of the address list returned by |
| 848 | + * gethostbyname(). We should first verify that the h_addrtype |
| 849 | + * field is AF_INET, but this program has already caused too much |
| 850 | + * grief on systems with broken library code. |
| 851 | + */ |
| 852 | + |
| 853 | + for (res = res0; res; res = res->ai_next) { |
| 854 | + if (res->ai_family != sin->sa_family) |
| 855 | + continue; |
| 856 | + switch (res->ai_family) { |
| 857 | + case AF_INET: |
| 858 | + rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr; |
| 859 | + break; |
| 860 | + case AF_INET6: |
| 861 | + /* need to check scope_id */ |
| 862 | + if (((struct sockaddr_in6 *)sin)->sin6_scope_id != |
| 863 | + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) { |
| 864 | + continue; |
| 865 | + } |
| 866 | + rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; |
| 867 | + break; |
| 868 | + default: |
| 869 | + continue; |
| 870 | + } |
| 871 | + if (memcmp(rap, ap, alen) == 0) { |
| 872 | + freeaddrinfo(res0); |
| 873 | + return; /* name is good, keep it */ |
| 874 | + } |
| 875 | + } |
| 876 | + |
| 877 | + /* |
| 878 | + * The host name does not map to the initial address. Perhaps |
| 879 | + * someone has messed up. Perhaps someone compromised a name |
| 880 | + * server. |
| 881 | + */ |
| 882 | + |
| 883 | + getnameinfo(sin, salen, hname, sizeof(hname), |
| 884 | + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); |
| 885 | + tcpd_warn("host name/address mismatch: %s != %.*s", |
| 886 | + hname, STRING_LENGTH, |
| 887 | + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname); |
| 888 | + } |
| 889 | + strcpy(host->name, paranoid); /* name is bad, clobber it */ |
| 890 | + if (res0) |
| 891 | + freeaddrinfo(res0); |
| 892 | + } |
| 893 | +#else /* INET6 */ |
| 894 | struct sockaddr_in *sin = host->sin; |
| 895 | struct hostent *hp; |
| 896 | int i; |
| 897 | @@ -220,6 +412,7 @@ |
| 898 | } |
| 899 | strcpy(host->name, paranoid); /* name is bad, clobber it */ |
| 900 | } |
| 901 | +#endif /* INET6 */ |
| 902 | } |
| 903 | |
| 904 | /* sock_sink - absorb unreceived IP datagram */ |
| 905 | @@ -228,7 +421,11 @@ |
| 906 | int fd; |
| 907 | { |
| 908 | char buf[BUFSIZ]; |
| 909 | +#ifdef INET6 |
| 910 | + struct sockaddr_storage sin; |
| 911 | +#else |
| 912 | struct sockaddr_in sin; |
| 913 | +#endif |
| 914 | int size = sizeof(sin); |
| 915 | |
| 916 | /* |
| 917 | diff -ruN tcp_wrappers_7.6.orig/tcpd.c tcp_wrappers_7.6/tcpd.c |
| 918 | --- tcp_wrappers_7.6.orig/tcpd.c 1996-02-11 17:01:33.000000000 +0100 |
| 919 | +++ tcp_wrappers_7.6/tcpd.c 2004-04-10 19:07:43.000000000 +0200 |
| 920 | @@ -120,7 +120,12 @@ |
| 921 | |
| 922 | /* Report request and invoke the real daemon program. */ |
| 923 | |
| 924 | +#ifdef INET6 |
| 925 | + syslog(allow_severity, "connect from %s (%s)", |
| 926 | + eval_client(&request), eval_hostaddr(request.client)); |
| 927 | +#else |
| 928 | syslog(allow_severity, "connect from %s", eval_client(&request)); |
| 929 | +#endif |
| 930 | closelog(); |
| 931 | (void) execv(path, argv); |
| 932 | syslog(LOG_ERR, "error: cannot execute %s: %m", path); |
| 933 | diff -ruN tcp_wrappers_7.6.orig/tcpdchk.c tcp_wrappers_7.6/tcpdchk.c |
| 934 | --- tcp_wrappers_7.6.orig/tcpdchk.c 1997-02-12 02:13:25.000000000 +0100 |
| 935 | +++ tcp_wrappers_7.6/tcpdchk.c 2004-04-10 19:07:43.000000000 +0200 |
| 936 | @@ -22,6 +22,9 @@ |
| 937 | |
| 938 | #include <sys/types.h> |
| 939 | #include <sys/stat.h> |
| 940 | +#ifdef INET6 |
| 941 | +#include <sys/socket.h> |
| 942 | +#endif |
| 943 | #include <netinet/in.h> |
| 944 | #include <arpa/inet.h> |
| 945 | #include <stdio.h> |
| 946 | @@ -397,6 +400,31 @@ |
| 947 | } |
| 948 | } |
| 949 | |
| 950 | +#ifdef INET6 |
| 951 | +static int is_inet6_addr(pat) |
| 952 | + char *pat; |
| 953 | +{ |
| 954 | + struct addrinfo hints, *res; |
| 955 | + int len, ret; |
| 956 | + char ch; |
| 957 | + |
| 958 | + if (*pat != '[') |
| 959 | + return (0); |
| 960 | + len = strlen(pat); |
| 961 | + if ((ch = pat[len - 1]) != ']') |
| 962 | + return (0); |
| 963 | + pat[len - 1] = '\0'; |
| 964 | + memset(&hints, 0, sizeof(hints)); |
| 965 | + hints.ai_family = AF_INET6; |
| 966 | + hints.ai_socktype = SOCK_STREAM; |
| 967 | + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
| 968 | + if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0) |
| 969 | + freeaddrinfo(res); |
| 970 | + pat[len - 1] = ch; |
| 971 | + return (ret == 0); |
| 972 | +} |
| 973 | +#endif |
| 974 | + |
| 975 | /* check_host - criticize host pattern */ |
| 976 | |
| 977 | static int check_host(pat) |
| 978 | @@ -423,14 +451,27 @@ |
| 979 | #endif |
| 980 | #endif |
| 981 | } else if (mask = split_at(pat, '/')) { /* network/netmask */ |
| 982 | +#ifdef INET6 |
| 983 | + int mask_len; |
| 984 | + |
| 985 | + if ((dot_quad_addr(pat) == INADDR_NONE |
| 986 | + || dot_quad_addr(mask) == INADDR_NONE) |
| 987 | + && (!is_inet6_addr(pat) |
| 988 | + || ((mask_len = atoi(mask)) < 0 || mask_len > 128))) |
| 989 | +#else |
| 990 | if (dot_quad_addr(pat) == INADDR_NONE |
| 991 | || dot_quad_addr(mask) == INADDR_NONE) |
| 992 | +#endif |
| 993 | tcpd_warn("%s/%s: bad net/mask pattern", pat, mask); |
| 994 | } else if (STR_EQ(pat, "FAIL")) { /* obsolete */ |
| 995 | tcpd_warn("FAIL is no longer recognized"); |
| 996 | tcpd_warn("(use EXCEPT or DENY instead)"); |
| 997 | } else if (reserved_name(pat)) { /* other reserved */ |
| 998 | /* void */ ; |
| 999 | +#ifdef INET6 |
| 1000 | + } else if (is_inet6_addr(pat)) { /* IPv6 address */ |
| 1001 | + addr_count = 1; |
| 1002 | +#endif |
| 1003 | } else if (NOT_INADDR(pat)) { /* internet name */ |
| 1004 | if (pat[strlen(pat) - 1] == '.') { |
| 1005 | tcpd_warn("%s: domain or host name ends in dot", pat); |
| 1006 | diff -ruN tcp_wrappers_7.6.orig/tcpd.h tcp_wrappers_7.6/tcpd.h |
| 1007 | --- tcp_wrappers_7.6.orig/tcpd.h 1996-03-19 16:22:25.000000000 +0100 |
| 1008 | +++ tcp_wrappers_7.6/tcpd.h 2004-04-10 19:07:43.000000000 +0200 |
| 1009 | @@ -11,7 +11,11 @@ |
| 1010 | struct host_info { |
| 1011 | char name[STRING_LENGTH]; /* access via eval_hostname(host) */ |
| 1012 | char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */ |
| 1013 | +#ifdef INET6 |
| 1014 | + struct sockaddr *sin; /* socket address or 0 */ |
| 1015 | +#else |
| 1016 | struct sockaddr_in *sin; /* socket address or 0 */ |
| 1017 | +#endif |
| 1018 | struct t_unitdata *unit; /* TLI transport address or 0 */ |
| 1019 | struct request_info *request; /* for shared information */ |
| 1020 | }; |
| 1021 | diff -ruN tcp_wrappers_7.6.orig/tcpdmatch.c tcp_wrappers_7.6/tcpdmatch.c |
| 1022 | --- tcp_wrappers_7.6.orig/tcpdmatch.c 1996-02-11 17:01:36.000000000 +0100 |
| 1023 | +++ tcp_wrappers_7.6/tcpdmatch.c 2004-04-10 19:07:43.000000000 +0200 |
| 1024 | @@ -57,7 +57,11 @@ |
| 1025 | int argc; |
| 1026 | char **argv; |
| 1027 | { |
| 1028 | +#ifdef INET6 |
| 1029 | + struct addrinfo hints, *hp, *res; |
| 1030 | +#else |
| 1031 | struct hostent *hp; |
| 1032 | +#endif |
| 1033 | char *myname = argv[0]; |
| 1034 | char *client; |
| 1035 | char *server; |
| 1036 | @@ -68,8 +72,13 @@ |
| 1037 | int ch; |
| 1038 | char *inetcf = 0; |
| 1039 | int count; |
| 1040 | +#ifdef INET6 |
| 1041 | + struct sockaddr_storage server_sin; |
| 1042 | + struct sockaddr_storage client_sin; |
| 1043 | +#else |
| 1044 | struct sockaddr_in server_sin; |
| 1045 | struct sockaddr_in client_sin; |
| 1046 | +#endif |
| 1047 | struct stat st; |
| 1048 | |
| 1049 | /* |
| 1050 | @@ -172,13 +181,20 @@ |
| 1051 | if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) { |
| 1052 | if ((hp = find_inet_addr(server)) == 0) |
| 1053 | exit(1); |
| 1054 | +#ifndef INET6 |
| 1055 | memset((char *) &server_sin, 0, sizeof(server_sin)); |
| 1056 | server_sin.sin_family = AF_INET; |
| 1057 | +#endif |
| 1058 | request_set(&request, RQ_SERVER_SIN, &server_sin, 0); |
| 1059 | |
| 1060 | +#ifdef INET6 |
| 1061 | + for (res = hp, count = 0; res; res = res->ai_next, count++) { |
| 1062 | + memcpy(&server_sin, res->ai_addr, res->ai_addrlen); |
| 1063 | +#else |
| 1064 | for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) { |
| 1065 | memcpy((char *) &server_sin.sin_addr, addr, |
| 1066 | sizeof(server_sin.sin_addr)); |
| 1067 | +#endif |
| 1068 | |
| 1069 | /* |
| 1070 | * Force evaluation of server host name and address. Host name |
| 1071 | @@ -194,7 +210,11 @@ |
| 1072 | fprintf(stderr, "Please specify an address instead\n"); |
| 1073 | exit(1); |
| 1074 | } |
| 1075 | +#ifdef INET6 |
| 1076 | + freeaddrinfo(hp); |
| 1077 | +#else |
| 1078 | free((char *) hp); |
| 1079 | +#endif |
| 1080 | } else { |
| 1081 | request_set(&request, RQ_SERVER_NAME, server, 0); |
| 1082 | } |
| 1083 | @@ -208,6 +228,18 @@ |
| 1084 | tcpdmatch(&request); |
| 1085 | exit(0); |
| 1086 | } |
| 1087 | +#ifdef INET6 |
| 1088 | + memset(&hints, 0, sizeof(hints)); |
| 1089 | + hints.ai_family = AF_INET6; |
| 1090 | + hints.ai_socktype = SOCK_STREAM; |
| 1091 | + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; |
| 1092 | + if (getaddrinfo(client, NULL, &hints, &res) == 0) { |
| 1093 | + freeaddrinfo(res); |
| 1094 | + request_set(&request, RQ_CLIENT_ADDR, client, 0); |
| 1095 | + tcpdmatch(&request); |
| 1096 | + exit(0); |
| 1097 | + } |
| 1098 | +#endif |
| 1099 | |
| 1100 | /* |
| 1101 | * Perhaps they are testing special client hostname patterns that aren't |
| 1102 | @@ -229,6 +261,34 @@ |
| 1103 | */ |
| 1104 | if ((hp = find_inet_addr(client)) == 0) |
| 1105 | exit(1); |
| 1106 | +#ifdef INET6 |
| 1107 | + request_set(&request, RQ_CLIENT_SIN, &client_sin, 0); |
| 1108 | + |
| 1109 | + for (res = hp, count = 0; res; res = res->ai_next, count++) { |
| 1110 | + memcpy(&client_sin, res->ai_addr, res->ai_addrlen); |
| 1111 | + |
| 1112 | + /* |
| 1113 | + * getnameinfo() doesn't do reverse lookup against link-local |
| 1114 | + * address. So, we pass through host name evaluation against |
| 1115 | + * such addresses. |
| 1116 | + */ |
| 1117 | + if (res->ai_family != AF_INET6 || |
| 1118 | + !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) { |
| 1119 | + /* |
| 1120 | + * Force evaluation of client host name and address. Host name |
| 1121 | + * conflicts will be reported while eval_hostname() does its job. |
| 1122 | + */ |
| 1123 | + request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0); |
| 1124 | + if (STR_EQ(eval_hostname(request.client), unknown)) |
| 1125 | + tcpd_warn("host address %s->name lookup failed", |
| 1126 | + eval_hostaddr(request.client)); |
| 1127 | + } |
| 1128 | + tcpdmatch(&request); |
| 1129 | + if (res->ai_next) |
| 1130 | + printf("\n"); |
| 1131 | + } |
| 1132 | + freeaddrinfo(hp); |
| 1133 | +#else |
| 1134 | memset((char *) &client_sin, 0, sizeof(client_sin)); |
| 1135 | client_sin.sin_family = AF_INET; |
| 1136 | request_set(&request, RQ_CLIENT_SIN, &client_sin, 0); |
| 1137 | @@ -250,6 +310,7 @@ |
| 1138 | printf("\n"); |
| 1139 | } |
| 1140 | free((char *) hp); |
| 1141 | +#endif |
| 1142 | exit(0); |
| 1143 | } |
| 1144 | |
| 1145 | diff -ruN tcp_wrappers_7.6.orig/tli.c tcp_wrappers_7.6/tli.c |
| 1146 | --- tcp_wrappers_7.6.orig/tli.c 1997-03-21 19:27:26.000000000 +0100 |
| 1147 | +++ tcp_wrappers_7.6/tli.c 2004-04-10 19:07:43.000000000 +0200 |
| 1148 | @@ -65,8 +65,13 @@ |
| 1149 | void tli_host(request) |
| 1150 | struct request_info *request; |
| 1151 | { |
| 1152 | +#ifdef INET6 |
| 1153 | + static struct sockaddr_storage client; |
| 1154 | + static struct sockaddr_storage server; |
| 1155 | +#else |
| 1156 | static struct sockaddr_in client; |
| 1157 | static struct sockaddr_in server; |
| 1158 | +#endif |
| 1159 | |
| 1160 | /* |
| 1161 | * If we discover that we are using an IP transport, pretend we never |
| 1162 | @@ -76,14 +81,29 @@ |
| 1163 | |
| 1164 | tli_endpoints(request); |
| 1165 | if ((request->config = tli_transport(request->fd)) != 0 |
| 1166 | +#ifdef INET6 |
| 1167 | + && (STR_EQ(request->config->nc_protofmly, "inet") || |
| 1168 | + STR_EQ(request->config->nc_protofmly, "inet6"))) { |
| 1169 | +#else |
| 1170 | && STR_EQ(request->config->nc_protofmly, "inet")) { |
| 1171 | +#endif |
| 1172 | if (request->client->unit != 0) { |
| 1173 | +#ifdef INET6 |
| 1174 | + client = *(struct sockaddr_storage *) request->client->unit->addr.buf; |
| 1175 | + request->client->sin = (struct sockaddr *) &client; |
| 1176 | +#else |
| 1177 | client = *(struct sockaddr_in *) request->client->unit->addr.buf; |
| 1178 | request->client->sin = &client; |
| 1179 | +#endif |
| 1180 | } |
| 1181 | if (request->server->unit != 0) { |
| 1182 | +#ifdef INET6 |
| 1183 | + server = *(struct sockaddr_storage *) request->server->unit->addr.buf; |
| 1184 | + request->server->sin = (struct sockaddr *) &server; |
| 1185 | +#else |
| 1186 | server = *(struct sockaddr_in *) request->server->unit->addr.buf; |
| 1187 | request->server->sin = &server; |
| 1188 | +#endif |
| 1189 | } |
| 1190 | tli_cleanup(request); |
| 1191 | sock_methods(request); |
| 1192 | @@ -187,7 +207,15 @@ |
| 1193 | } |
| 1194 | while (config = getnetconfig(handlep)) { |
| 1195 | if (stat(config->nc_device, &from_config) == 0) { |
| 1196 | +#ifdef NO_CLONE_DEVICE |
| 1197 | + /* |
| 1198 | + * If the network devices are not cloned (as is the case for |
| 1199 | + * Solaris 8 Beta), we must compare the major device numbers. |
| 1200 | + */ |
| 1201 | + if (major(from_config.st_rdev) == major(from_client.st_rdev)) |
| 1202 | +#else |
| 1203 | if (minor(from_config.st_rdev) == major(from_client.st_rdev)) |
| 1204 | +#endif |
| 1205 | break; |
| 1206 | } |
| 1207 | } |
| 1208 | diff -ruN tcp_wrappers_7.6.orig/update.c tcp_wrappers_7.6/update.c |
| 1209 | --- tcp_wrappers_7.6.orig/update.c 1994-12-28 17:42:56.000000000 +0100 |
| 1210 | +++ tcp_wrappers_7.6/update.c 2004-04-10 19:07:43.000000000 +0200 |
| 1211 | @@ -46,10 +46,18 @@ |
| 1212 | request->fd = va_arg(ap, int); |
| 1213 | continue; |
| 1214 | case RQ_CLIENT_SIN: |
| 1215 | +#ifdef INET6 |
| 1216 | + request->client->sin = va_arg(ap, struct sockaddr *); |
| 1217 | +#else |
| 1218 | request->client->sin = va_arg(ap, struct sockaddr_in *); |
| 1219 | +#endif |
| 1220 | continue; |
| 1221 | case RQ_SERVER_SIN: |
| 1222 | +#ifdef INET6 |
| 1223 | + request->server->sin = va_arg(ap, struct sockaddr *); |
| 1224 | +#else |
| 1225 | request->server->sin = va_arg(ap, struct sockaddr_in *); |
| 1226 | +#endif |
| 1227 | continue; |
| 1228 | |
| 1229 | /* |
| 1230 | diff -ruN tcp_wrappers_7.6.orig/workarounds.c tcp_wrappers_7.6/workarounds.c |
| 1231 | --- tcp_wrappers_7.6.orig/workarounds.c 1996-03-19 16:22:26.000000000 +0100 |
| 1232 | +++ tcp_wrappers_7.6/workarounds.c 2004-04-10 19:07:43.000000000 +0200 |
| 1233 | @@ -166,11 +166,22 @@ |
| 1234 | int *len; |
| 1235 | { |
| 1236 | int ret; |
| 1237 | +#ifdef INET6 |
| 1238 | + struct sockaddr *sin = sa; |
| 1239 | +#else |
| 1240 | struct sockaddr_in *sin = (struct sockaddr_in *) sa; |
| 1241 | +#endif |
| 1242 | |
| 1243 | if ((ret = getpeername(sock, sa, len)) >= 0 |
| 1244 | +#ifdef INET6 |
| 1245 | + && ((sin->su_si.si_family == AF_INET6 |
| 1246 | + && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr)) |
| 1247 | + || (sin->su_si.si_family == AF_INET |
| 1248 | + && sin->su_sin.sin_addr.s_addr == 0))) { |
| 1249 | +#else |
| 1250 | && sa->sa_family == AF_INET |
| 1251 | && sin->sin_addr.s_addr == 0) { |
| 1252 | +#endif |
| 1253 | errno = ENOTCONN; |
| 1254 | return (-1); |
| 1255 | } else { |