commit 627830b59e064f7780a683ab3a8c3d3c922fa00e63cde37c340748ac3a2a23d7 Author: Adrian Schröter Date: Sat May 4 01:05:40 2024 +0200 Sync from SUSE:SLFO:Main tcpd revision 0f722b78d9a61615383b78c04269863b diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/baselibs.conf b/baselibs.conf new file mode 100644 index 0000000..ccabd0b --- /dev/null +++ b/baselibs.conf @@ -0,0 +1,4 @@ +libwrap0 + obsoletes "tcpd- <= " + provides "tcpd- = " +arch ppc package tcpd-devel diff --git a/hosts.allow b/hosts.allow new file mode 100644 index 0000000..df4e910 --- /dev/null +++ b/hosts.allow @@ -0,0 +1,64 @@ +# /etc/hosts.allow +# Make sure package tcpd is installed on your system for this to work. +# See 'man tcpd' and 'man 5 hosts_access' for a detailed description +# of /etc/hosts.allow and /etc/hosts.deny. +# +# short overview about daemons and servers that are built with +# tcp_wrappers support: +# +# package name | daemon path | token +# ---------------------------------------------------------------------------- +# ssh, openssh | /usr/sbin/sshd | sshd, sshd-fwd-x11, sshd-fwd- +# quota | /usr/sbin/rpc.rquotad | rquotad +# tftpd | /usr/sbin/in.tftpd | in.tftpd +# portmap | /sbin/portmap | portmap +# The portmapper does not verify against hostnames +# to prevent hangs. It only checks non-local addresses. +# +# (kernel nfs server) +# nfs-utils | /usr/sbin/rpc.mountd | mountd +# nfs-utils | /sbin/rpc.statd | statd +# +# (unfsd, userspace nfs server) +# nfs-server | /usr/sbin/rpc.mountd | rpc.mountd +# nfs-server | /usr/sbin/rpc.ugidd | rpc.ugidd +# +# (printing services) +# lprng | /usr/sbin/lpd | lpd +# cups | /usr/sbin/cupsd | cupsd +# The cupsd server daemon reports to the cups +# error logs, not to the syslog(3) facility. +# +# (Uniterrupted Power Supply Software) +# apcupsd | /sbin/apcupsd | apcupsd +# apcupsd | /sbin/apcnisd | apcnisd +# +# All of the other network servers such as samba, apache or X, have their own +# access control scheme that should be used instead. +# +# In addition to the services above, the services that are started on request +# by inetd or xinetd use tcpd to "wrap" the network connection. tcpd uses +# the last component of the server pathname as a token to match a service in +# /etc/hosts.{allow,deny}. See the file /etc/inetd.conf for the token names. +# The following examples work when uncommented: +# +# +# Example 1: Fire up a mail to the admin if a connection to the printer daemon +# has been made from host foo.bar.com, but simply deny all others: +# lpd : foo.bar.com : spawn /bin/echo "%h printer access" | \ +# mail -s "tcp_wrappers on %H" root +# +# +# Example 2: grant access from local net, reject with message from elsewhere. +# in.telnetd : ALL EXCEPT LOCAL : ALLOW +# in.telnetd : ALL : \ +# twist /bin/echo -e "\n\raccess from %h declined.\n\rGo away.";sleep 2 +# +# +# Example 3: run a different instance of rsyncd if the connection comes +# from network 172.20.0.0/24, but regular for others: +# rsyncd : 172.20.0.0/255.255.255.0 : twist /usr/local/sbin/my_rsyncd-script +# rsyncd : ALL : ALLOW +# + + diff --git a/hosts.deny b/hosts.deny new file mode 100644 index 0000000..f8e28d7 --- /dev/null +++ b/hosts.deny @@ -0,0 +1,7 @@ +# /etc/hosts.deny +# Make sure package tcpd is installed on your system for this to work. +# See 'man tcpd' and 'man 5 hosts_access' as well as /etc/hosts.allow +# for a detailed description. + +http-rman : ALL EXCEPT LOCAL + diff --git a/tcp_wrappers_7.6-builtin.diff b/tcp_wrappers_7.6-builtin.diff new file mode 100644 index 0000000..b2f6459 --- /dev/null +++ b/tcp_wrappers_7.6-builtin.diff @@ -0,0 +1,19 @@ +--- scaffold.c.orig ++++ scaffold.c +@@ -20,6 +20,8 @@ static char sccs_id[] = "@(#) scaffold.c + #include + #include + #include ++#include ++ + #if defined(INET6) && !defined(USE_GETIPNODEBY) + #include + #endif +@@ -28,7 +30,6 @@ static char sccs_id[] = "@(#) scaffold.c + #define INADDR_NONE (-1) /* XXX should be 0xffffffff */ + #endif + +-extern char *malloc(); + + /* Application-specific. */ + diff --git a/tcp_wrappers_7.6-fedora-bug11881.diff b/tcp_wrappers_7.6-fedora-bug11881.diff new file mode 100644 index 0000000..d209b00 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-bug11881.diff @@ -0,0 +1,35 @@ +--- eval.c.orig ++++ eval.c +@@ -111,7 +111,7 @@ struct request_info *request; + return (hostinfo); + #endif + if (STR_NE(eval_user(request), unknown)) { +- sprintf(both, "%s@%s", request->user, hostinfo); ++ snprintf(both, sizeof(both), "%s@%s", request->user, hostinfo); + return (both); + } else { + return (hostinfo); +@@ -128,7 +128,7 @@ struct request_info *request; + char *daemon = eval_daemon(request); + + if (STR_NE(host, unknown)) { +- sprintf(both, "%s@%s", daemon, host); ++ snprintf(both, sizeof(both), "%s@%s", daemon, host); + return (both); + } else { + return (daemon); +--- tcpd.c.orig ++++ tcpd.c +@@ -61,10 +61,10 @@ char **argv; + */ + + if (argv[0][0] == '/') { +- strcpy(path, argv[0]); ++ strncpy(path, argv[0], sizeof(path)); + argv[0] = strrchr(argv[0], '/') + 1; + } else { +- sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]); ++ snprintf(path, sizeof(path), "%s/%s", REAL_DAEMON_DIR, argv[0]); + } + + /* diff --git a/tcp_wrappers_7.6-fedora-bug141110.diff b/tcp_wrappers_7.6-fedora-bug141110.diff new file mode 100644 index 0000000..0edba1b --- /dev/null +++ b/tcp_wrappers_7.6-fedora-bug141110.diff @@ -0,0 +1,20 @@ +--- hosts_access.c.orig ++++ hosts_access.c +@@ -146,7 +146,7 @@ struct request_info *request; + verdict = setjmp(tcpd_buf); + if (verdict != 0) + return (verdict == AC_PERMIT); +- if (table_match(hosts_allow_table, request)) ++ if (table_match(hosts_allow_table, request) == YES) + return (YES); + if (table_match(hosts_deny_table, request)) + return (NO); +@@ -195,7 +195,7 @@ struct request_info *request; + } else if (errno != ENOENT) { + tcpd_warn("cannot open %s: %m", table); + } +- if (match) { ++ if (match == YES) { + if (hosts_access_verbose > 1) + syslog(LOG_DEBUG, "matched: %s line %d", + tcpd_context.file, tcpd_context.line); diff --git a/tcp_wrappers_7.6-fedora-bug17795.diff b/tcp_wrappers_7.6-fedora-bug17795.diff new file mode 100644 index 0000000..bff18f3 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-bug17795.diff @@ -0,0 +1,54 @@ +--- hosts_access.5.orig ++++ hosts_access.5 +@@ -90,6 +90,13 @@ bitwise AND of the address and the `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 ++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 ++zero or more lines with zero or more host name or address patterns ++separated by whitespace. A file name pattern can be used anywhere ++a host name or address pattern can be used. ++.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 +--- hosts_access.c.orig ++++ hosts_access.c +@@ -273,6 +273,26 @@ struct request_info *request; + } + } + ++/* hostfile_match - look up host patterns from file */ ++ ++static int hostfile_match(path, host) ++char *path; ++struct hosts_info *host; ++{ ++ char tok[BUFSIZ]; ++ int match = NO; ++ FILE *fp; ++ ++ if ((fp = fopen(path, "r")) != 0) { ++ while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host))) ++ /* void */ ; ++ fclose(fp); ++ } else if (errno != ENOENT) { ++ tcpd_warn("open %s: %m", path); ++ } ++ return (match); ++} ++ + /* host_match - match host name and/or address against pattern */ + + static int host_match(tok, host) +@@ -300,6 +320,8 @@ struct host_info *host; + tcpd_warn("netgroup support is disabled"); /* not tcpd_jump() */ + return (NO); + #endif ++ } else if (tok[0] == '/') { /* /file hack */ ++ return (hostfile_match(tok, host)); + } else if (STR_EQ(tok, "KNOWN")) { /* check address and name */ + char *name = eval_hostname(host); + return (STR_NE(eval_hostaddr(host), unknown) && HOSTNAME_KNOWN(name)); diff --git a/tcp_wrappers_7.6-fedora-bug17847.diff b/tcp_wrappers_7.6-fedora-bug17847.diff new file mode 100644 index 0000000..41c5109 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-bug17847.diff @@ -0,0 +1,100 @@ +--- hosts_access.5.orig ++++ hosts_access.5 +@@ -103,6 +103,10 @@ An expression of the form `[n:n:n:n:n:n: + 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 ++Wildcards `*\' and `?\' can be used to match hostnames or IP addresses. This ++method of matching cannot be used in conjunction with `net/mask\' matching, ++hostname matching beginning with `.\' or IP address matching ending with `.\'. + .SH WILDCARDS + The access control language supports explicit wildcards: + .IP ALL +--- hosts_access.c.orig ++++ hosts_access.c +@@ -346,6 +346,12 @@ char *string; + { + int n; + ++#ifndef DISABLE_WILDCARD_MATCHING ++ if (strchr(tok, '*') || strchr(tok,'?')) { /* contains '*' or '?' */ ++ return (match_pattern_ylo(string,tok)); ++ } else ++#endif ++ + if (tok[0] == '.') { /* suffix */ + n = strlen(string) - strlen(tok); + return (n > 0 && STR_EQ(tok, string + n)); +@@ -454,3 +460,71 @@ char *string; + } + #endif + } ++ ++#ifndef DISABLE_WILDCARD_MATCHING ++/* Note: this feature has been adapted in a pretty straightforward way ++ from Tatu Ylonen's last SSH version under free license by ++ Pekka Savola . ++ ++ Copyright (c) 1995 Tatu Ylonen , Espoo, Finland ++*/ ++ ++/* Returns true if the given string matches the pattern (which may contain ++ ? and * as wildcards), and zero if it does not match. */ ++ ++int match_pattern_ylo(const char *s, const char *pattern) ++{ ++ while (1) ++ { ++ /* If at end of pattern, accept if also at end of string. */ ++ if (!*pattern) ++ return !*s; ++ ++ /* Process '*'. */ ++ if (*pattern == '*') ++ { ++ /* Skip the asterisk. */ ++ pattern++; ++ ++ /* If at end of pattern, accept immediately. */ ++ if (!*pattern) ++ return 1; ++ ++ /* If next character in pattern is known, optimize. */ ++ if (*pattern != '?' && *pattern != '*') ++ { ++ /* Look instances of the next character in pattern, and try ++ to match starting from those. */ ++ for (; *s; s++) ++ if (*s == *pattern && ++ match_pattern_ylo(s + 1, pattern + 1)) ++ return 1; ++ /* Failed. */ ++ return 0; ++ } ++ ++ /* Move ahead one character at a time and try to match at each ++ position. */ ++ for (; *s; s++) ++ if (match_pattern_ylo(s, pattern)) ++ return 1; ++ /* Failed. */ ++ return 0; ++ } ++ ++ /* There must be at least one more character in the string. If we are ++ at the end, fail. */ ++ if (!*s) ++ return 0; ++ ++ /* Check if the next character of the string is acceptable. */ ++ if (*pattern != '?' && *pattern != *s) ++ return 0; ++ ++ /* Move to the next character, both in string and in pattern. */ ++ s++; ++ pattern++; ++ } ++ /*NOTREACHED*/ ++} ++#endif /* DISABLE_WILDCARD_MATCHING */ diff --git a/tcp_wrappers_7.6-fedora-bug220015.diff b/tcp_wrappers_7.6-fedora-bug220015.diff new file mode 100644 index 0000000..c3b33fe --- /dev/null +++ b/tcp_wrappers_7.6-fedora-bug220015.diff @@ -0,0 +1,92 @@ +--- hosts_ctl.c.orig ++++ hosts_ctl.c +@@ -29,10 +29,12 @@ char *user; + { + struct request_info request; + +- return (hosts_access(request_init(&request, +- RQ_DAEMON, daemon, +- RQ_CLIENT_NAME, name, +- RQ_CLIENT_ADDR, addr, +- RQ_USER, user, +- 0))); ++ request_init(&request, RQ_DAEMON, daemon, ++ RQ_CLIENT_NAME, name, ++ RQ_CLIENT_ADDR, addr, ++ RQ_USER, user, ++ 0); ++ sock_hostnofd(&request); ++ ++ return (hosts_access(&request)); + } +--- socket.c.orig ++++ socket.c +@@ -140,6 +140,53 @@ struct request_info *request; + #endif + } + ++ ++ ++/* sock_hostnofd - look up endpoint addresses and install conversion methods */ ++ ++void sock_hostnofd(request) ++struct request_info *request; ++{ ++ static struct sockaddr_storage client; ++ struct addrinfo hints, *res; ++ int ret; ++ char *host; ++ ++ /* If the address field is non-empty and non-unknown and if the hostname ++ * field is empty or unknown, use the address field to get the sockaddr ++ * and hostname. */ ++ if (strlen(request->client->addr) && ++ HOSTNAME_KNOWN(request->client->addr) && ++ (!strlen(request->client->addr) || ++ !HOSTNAME_KNOWN(request->client->name))) ++ host = request->client->addr; ++ else ++ return; ++ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = AF_INET6; ++ hints.ai_socktype = SOCK_STREAM; ++ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; ++ ++ ret = getaddrinfo(host, NULL, &hints, &res); ++ if (ret != 0) { ++ hints.ai_family = AF_INET; ++ ret = getaddrinfo(host, NULL, &hints, &res); ++ } ++ ++ if (ret != 0) { ++ tcpd_warn("can't resolve hostname (%s): %s", host, gai_strerror(ret)); ++ } else { ++ sock_methods(request); ++ ++ memcpy(&client, res->ai_addr, res->ai_addrlen); ++ request->client->sin = (struct sockaddr *)&client; ++ freeaddrinfo(res); ++ ++ request->client->name[0] = 0; ++ } ++} ++ + /* sock_hostaddr - map endpoint address to printable form */ + + void sock_hostaddr(host) +--- tcpd.h.orig ++++ tcpd.h +@@ -174,10 +174,12 @@ extern char *eval_server(); /* whatever + + #ifdef __STDC__ + extern void sock_host(struct request_info *); ++extern void sock_hostnofd(struct request_info *); + extern void sock_hostname(struct host_info *); + extern void sock_hostaddr(struct host_info *); + #else + extern void sock_host(); /* look up endpoint addresses */ ++extern void sock_hostnofd(); + extern void sock_hostname(); /* translate address to hostname */ + extern void sock_hostaddr(); /* address to printable address */ + #endif diff --git a/tcp_wrappers_7.6-fedora-docu.diff b/tcp_wrappers_7.6-fedora-docu.diff new file mode 100644 index 0000000..302c904 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-docu.diff @@ -0,0 +1,11 @@ +--- hosts_access.5.orig ++++ hosts_access.5 +@@ -329,7 +329,7 @@ in.tftpd: LOCAL, .my.domain + /etc/hosts.deny: + .in +3 + .nf +-in.tftpd: ALL: (/some/where/safe_finger -l @%h | \\ ++in.tftpd: ALL: spawn (/some/where/safe_finger -l @%h | \\ + /usr/ucb/mail -s %d-%h root) & + .fi + .PP diff --git a/tcp_wrappers_7.6-fedora-fixgethostbyname.diff b/tcp_wrappers_7.6-fedora-fixgethostbyname.diff new file mode 100644 index 0000000..9941b53 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-fixgethostbyname.diff @@ -0,0 +1,25 @@ +--- socket.c.orig ++++ socket.c +@@ -54,6 +54,7 @@ static struct hostent *gethostbyname_dot + char *name; + { + char dot_name[MAXHOSTNAMELEN + 1]; ++ struct hostent *hp; + + /* + * Don't append dots to unqualified names. Such names are likely to come +@@ -63,8 +64,12 @@ char *name; + if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) { + return (gethostbyname(name)); + } else { +- sprintf(dot_name, "%s.", name); +- return (gethostbyname(dot_name)); ++ sprintf(dot_name, "%s.", name); ++ hp = gethostbyname(dot_name); ++ if (hp) ++ return hp; ++ else ++ return (gethostbyname(name)); + } + } + diff --git a/tcp_wrappers_7.6-fedora-sig.diff b/tcp_wrappers_7.6-fedora-sig.diff new file mode 100644 index 0000000..a51dc05 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-sig.diff @@ -0,0 +1,39 @@ +--- hosts_access.c.orig ++++ hosts_access.c +@@ -63,6 +63,7 @@ static char sep[] = ", \t\r\n"; + + #define YES 1 + #define NO 0 ++#define ERR -1 + + /* + * These variables are globally visible so that they can be redirected in +@@ -125,7 +126,6 @@ int hosts_access(request) + struct request_info *request; + { + int verdict; +- + /* + * If the (daemon, client) pair is matched by an entry in the file + * /etc/hosts.allow, access is granted. Otherwise, if the (daemon, +@@ -148,9 +148,9 @@ struct request_info *request; + return (verdict == AC_PERMIT); + if (table_match(hosts_allow_table, request) == YES) + return (YES); +- if (table_match(hosts_deny_table, request)) +- return (NO); +- return (YES); ++ if (table_match(hosts_deny_table, request) == NO) ++ return (YES); ++ return (NO); + } + + /* table_match - match table entries with (daemon, client) pair */ +@@ -194,6 +194,7 @@ struct request_info *request; + (void) fclose(fp); + } else if (errno != ENOENT) { + tcpd_warn("cannot open %s: %m", table); ++ match = ERR; + } + if (match == YES) { + if (hosts_access_verbose > 1) diff --git a/tcp_wrappers_7.6-fedora-sigalarm.diff b/tcp_wrappers_7.6-fedora-sigalarm.diff new file mode 100644 index 0000000..69f2112 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-sigalarm.diff @@ -0,0 +1,36 @@ +--- rfc931.c.orig ++++ rfc931.c +@@ -92,6 +92,8 @@ char *dest; + char *cp; + char *result = unknown; + FILE *fp; ++ unsigned saved_timeout; ++ struct sigaction nact, oact; + + #ifdef INET6 + /* address family must be the same */ +@@ -134,7 +136,12 @@ char *dest; + */ + + if (sigsetjmp(timebuf, 1) == 0) { +- signal(SIGALRM, timeout); ++ /* Save SIGALRM timer and handler. Sudheer Abdul-Salam, SUN. */ ++ saved_timeout = alarm(0); ++ nact.sa_handler = timeout; ++ nact.sa_flags = 0; ++ (void) sigemptyset(&nact.sa_mask); ++ (void) sigaction(SIGALRM, &nact, &oact); + alarm(rfc931_timeout); + + /* +@@ -223,6 +230,10 @@ char *dest; + } + alarm(0); + } ++ /* Restore SIGALRM timer and handler. Sudheer Abdul-Salam, SUN. */ ++ (void) sigaction(SIGALRM, &oact, NULL); ++ if (saved_timeout > 0) ++ alarm(saved_timeout); + fclose(fp); + } + STRN_CPY(dest, result, STRING_LENGTH); diff --git a/tcp_wrappers_7.6-fedora-sigchld.diff b/tcp_wrappers_7.6-fedora-sigchld.diff new file mode 100644 index 0000000..170497a --- /dev/null +++ b/tcp_wrappers_7.6-fedora-sigchld.diff @@ -0,0 +1,87 @@ +--- shell_cmd.c.orig ++++ shell_cmd.c +@@ -24,6 +24,11 @@ static char sccsid[] = "@(#) shell_cmd.c + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + + extern void exit(); + +@@ -35,13 +40,42 @@ extern void exit(); + + static void do_child(); + ++/* ++ * The sigchld handler. If there is a SIGCHLD caused by a child other than ++ * ours, we set a flag and raise the signal later. ++ */ ++volatile static int foreign_sigchld; ++volatile static int our_child_pid; ++static void sigchld(int sig, siginfo_t *si, void *unused) ++{ ++ if (si && si->si_pid != our_child_pid) ++ foreign_sigchld = 1; ++} ++ + /* shell_cmd - execute shell command */ + + void shell_cmd(command) + char *command; + { + int child_pid; +- int wait_pid; ++ ++ struct sigaction new_action, old_action; ++ sigset_t new_mask, old_mask, empty_mask; ++ ++ new_action.sa_sigaction = &sigchld; ++ new_action.sa_flags = SA_SIGINFO; ++ sigemptyset(&new_action.sa_mask); ++ sigemptyset(&new_mask); ++ sigemptyset(&empty_mask); ++ sigaddset(&new_mask, SIGCHLD); ++ ++ /* ++ * Set the variables for handler, set the handler and block the signal ++ * until we have the pid. ++ */ ++ foreign_sigchld = 0; our_child_pid = 0; ++ sigprocmask(SIG_BLOCK, &new_mask, &old_mask); ++ sigaction(SIGCHLD, &new_action, &old_action); + + /* + * Most of the work is done within the child process, to minimize the +@@ -53,12 +87,26 @@ char *command; + tcpd_warn("cannot fork: %m"); + break; + case 00: /* child */ ++ /* Clear the blocked mask for the child not to be surprised. */ ++ sigprocmask(SIG_SETMASK, &empty_mask, 0); + do_child(command); + /* NOTREACHED */ + default: /* parent */ +- while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid) +- /* void */ ; ++ our_child_pid = child_pid; ++ sigprocmask(SIG_UNBLOCK, &new_mask, 0); ++ while (waitpid(child_pid, (int *) 0, 0) == -1 && errno == EINTR); + } ++ ++ /* ++ * Revert the signal mask and the SIGCHLD handler. ++ */ ++ sigprocmask(SIG_SETMASK, &old_mask, 0); ++ sigaction(SIGCHLD, &old_action, 0); ++ ++ /* If there was a foreign SIGCHLD, raise it after we have restored the old ++ * mask and handler. */ ++ if (foreign_sigchld) ++ raise(SIGCHLD); + } + + /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */ diff --git a/tcp_wrappers_7.6-fedora-sigjmp.diff b/tcp_wrappers_7.6-fedora-sigjmp.diff new file mode 100644 index 0000000..44c0943 --- /dev/null +++ b/tcp_wrappers_7.6-fedora-sigjmp.diff @@ -0,0 +1,29 @@ +--- rfc931.c.orig ++++ rfc931.c +@@ -33,7 +33,7 @@ static char sccsid[] = "@(#) rfc931.c 1. + + int rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */ + +-static jmp_buf timebuf; ++static sigjmp_buf timebuf; + + /* fsocket - open stdio stream on top of socket */ + +@@ -62,7 +62,7 @@ int protocol; + static void timeout(sig) + int sig; + { +- longjmp(timebuf, sig); ++ siglongjmp(timebuf, sig); + } + + /* rfc931 - return remote user name, given socket structures */ +@@ -133,7 +133,7 @@ char *dest; + * Set up a timer so we won't get stuck while waiting for the server. + */ + +- if (setjmp(timebuf) == 0) { ++ if (sigsetjmp(timebuf, 1) == 0) { + signal(SIGALRM, timeout); + alarm(rfc931_timeout); + diff --git a/tcp_wrappers_7.6-fedora-strerror.diff b/tcp_wrappers_7.6-fedora-strerror.diff new file mode 100644 index 0000000..e3e765e --- /dev/null +++ b/tcp_wrappers_7.6-fedora-strerror.diff @@ -0,0 +1,27 @@ +--- percent_m.c.orig ++++ percent_m.c +@@ -13,7 +13,7 @@ static char sccsid[] = "@(#) percent_m.c + #include + + extern int errno; +-#ifndef SYS_ERRLIST_DEFINED ++#if !defined(SYS_ERRLIST_DEFINED) && !defined(HAVE_STRERROR) + extern char *sys_errlist[]; + extern int sys_nerr; + #endif +@@ -29,11 +29,15 @@ char *ibuf; + + while (*bp = *cp) + if (*cp == '%' && cp[1] == 'm') { ++#ifdef HAVE_STRERROR ++ strcpy(bp, strerror(errno)); ++#else + if (errno < sys_nerr && errno > 0) { + strcpy(bp, sys_errlist[errno]); + } else { + sprintf(bp, "Unknown error %d", errno); + } ++#endif + bp += strlen(bp); + cp += 2; + } else { diff --git a/tcp_wrappers_7.6-fix_options-fix.diff b/tcp_wrappers_7.6-fix_options-fix.diff new file mode 100644 index 0000000..05aa0ec --- /dev/null +++ b/tcp_wrappers_7.6-fix_options-fix.diff @@ -0,0 +1,11 @@ +--- fix_options.c.orig ++++ fix_options.c +@@ -53,7 +53,7 @@ struct request_info *request; + * XXX IPv6 support? + */ + sslen = sizeof(ss); +- if (getsockname(fd, (struct sockaddr *)&ss, &sslen < 0)) { ++ if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + clean_exit(request); + } diff --git a/tcp_wrappers_7.6-host_name_mapping-fix.diff b/tcp_wrappers_7.6-host_name_mapping-fix.diff new file mode 100644 index 0000000..d3f4555 --- /dev/null +++ b/tcp_wrappers_7.6-host_name_mapping-fix.diff @@ -0,0 +1,27 @@ +--- socket.c.orig ++++ socket.c +@@ -270,7 +270,6 @@ sock_hostname(struct host_info *host) + res = res->ai_next; + } + +- freeaddrinfo (resbase); + + if (res == NULL) + { +@@ -279,6 +278,7 @@ sock_hostname(struct host_info *host) + host->name, + inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr)); + strncpy(host->name, paranoid, sizeof(host->name)); ++ freeaddrinfo (resbase); + return; + } + +@@ -289,7 +289,7 @@ sock_hostname(struct host_info *host) + host->name, res->ai_canonname, + inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr)); + } +- ++ freeaddrinfo (resbase); + return; + } + #else /* INET6 */ diff --git a/tcp_wrappers_7.6-hosts_ctl.diff b/tcp_wrappers_7.6-hosts_ctl.diff new file mode 100644 index 0000000..337840a --- /dev/null +++ b/tcp_wrappers_7.6-hosts_ctl.diff @@ -0,0 +1,10 @@ +--- tcpd.h.orig ++++ tcpd.h +@@ -128,6 +128,7 @@ extern int resident; /* > 0 if residen + #ifdef __STDC__ + extern struct request_info *request_init(struct request_info *,...); + extern struct request_info *request_set(struct request_info *,...); ++extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user); + #else + extern struct request_info *request_init(); /* initialize request */ + extern struct request_info *request_set(); /* update request structure */ diff --git a/tcp_wrappers_7.6-implicit-decl.patch b/tcp_wrappers_7.6-implicit-decl.patch new file mode 100644 index 0000000..c1dd08c --- /dev/null +++ b/tcp_wrappers_7.6-implicit-decl.patch @@ -0,0 +1,67 @@ +--- rfc931.c.orig ++++ rfc931.c +@@ -23,7 +23,7 @@ static char sccsid[] = "@(#) rfc931.c 1. + #include + #include + #include +- ++#include + /* Local stuff. */ + + #include "tcpd.h" +--- safe_finger.c.orig ++++ safe_finger.c +@@ -19,13 +19,16 @@ static char sccsid[] = "@(#) safe_finger + #endif + + /* System libraries */ +- ++#include ++#include + #include + #include ++#include + #include + #include + #include + #include ++#include + + extern void exit(); + +--- tcpdchk.c.orig ++++ tcpdchk.c +@@ -20,6 +20,7 @@ static char sccsid[] = "@(#) tcpdchk.c 1 + + /* System libraries. */ + ++#include + #include + #include + #ifdef INET6 +@@ -33,6 +34,7 @@ static char sccsid[] = "@(#) tcpdchk.c 1 + #include + #include + #include ++#include + + extern int errno; + extern void exit(); +--- tcpdmatch.c.orig ++++ tcpdmatch.c +@@ -19,6 +19,7 @@ static char sccsid[] = "@(#) tcpdmatch.c + + /* System libraries. */ + ++#include + #include + #include + #include +@@ -29,6 +30,7 @@ static char sccsid[] = "@(#) tcpdmatch.c + #include + #include + #include ++#include + + extern void exit(); + extern int optind; diff --git a/tcp_wrappers_7.6-ipv6-1.6.diff b/tcp_wrappers_7.6-ipv6-1.6.diff new file mode 100644 index 0000000..4c3d222 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-1.6.diff @@ -0,0 +1,1146 @@ +;; IPv6 patch for tcp_wrappers_7.6 1.6 +;; Aug 23, 1999 by Hajimu UMEMOTO +;; +;; This patch supports IPv4/IPv6 dual stack and IPv4-mapped IPv6 address. +;; You can replace stock tcpd or libwrap.a with this. +;; IPv6 address pattern is as a `[net]/prefixlen' pair. +;; This patch was tested on KAME/FreeBSD, KAME/FreeBSD3, KAME/NetBSD, +;; RedHat 5.1 with kernel 2.1.126, and RedHat 6.0 with kernel 2.2.10. +;; +;; CAUTION: +;; Back out change for field separater. Now, field separater is `:' +;; not `|'. To specify IPv6 address, enclose IPv6 address with `[' +;; and `]'. +;; +;; For Linux users: +;; If your libc doesn't have sockaddr_storage, try target `linux-old'. + +================================================================================ +--- fix_options.c.orig ++++ fix_options.c +@@ -11,6 +11,9 @@ static char sccsid[] = "@(#) fix_options + + #include + #include ++#ifdef INET6 ++#include ++#endif + #include + #include + #include +@@ -41,6 +44,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; +--- hosts_access.5.orig ++++ hosts_access.5 +@@ -85,10 +85,17 @@ member of the specified netgroup. Netgro + for daemon process names or for client user names. + .IP \(bu + An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a +-`net/mask\' pair. A host address is matched if `net\' is equal to the ++`net/mask\' pair. A IPv4 host address is matched if `net\' is equal to the + 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\'. + .SH WILDCARDS + The access control language supports explicit wildcards: + .IP ALL +--- hosts_access.c.orig ++++ hosts_access.c +@@ -25,6 +25,9 @@ static char sccsid[] = "@(#) hosts_acces + + #include + #include ++#ifdef INET6 ++#include ++#endif + #include + #include + #include +@@ -83,6 +86,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. */ + +@@ -317,6 +324,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)); +@@ -327,20 +341,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() +@@ -352,8 +401,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 */ +--- inetcf.c.orig ++++ inetcf.c +@@ -26,6 +26,9 @@ extern void exit(); + * guesses. Shorter names follow longer ones. + */ + char *inet_files[] = { ++#ifdef INET6 ++ "/usr/local/v6/etc/inet6d.conf", /* KAME */ ++#endif + "/private/etc/inetd.conf", /* NEXT */ + "/etc/inet/inetd.conf", /* SYSV4 */ + "/usr/etc/inetd.conf", /* IRIX?? */ +--- misc.c.orig ++++ misc.c +@@ -58,9 +58,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 */ +--- refuse.c.orig ++++ refuse.c +@@ -25,7 +25,12 @@ static char sccsid[] = "@(#) refuse.c 1. + 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 */ + } +--- rfc931.c.orig ++++ rfc931.c +@@ -68,20 +68,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 +122,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 +146,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 +174,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 +183,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 +203,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 +--- scaffold.c.orig ++++ scaffold.c +@@ -20,6 +20,9 @@ static char sccs_id[] = "@(#) scaffold.c + #include + #include + #include ++#if defined(INET6) && !defined(USE_GETIPNODEBY) ++#include ++#endif + + #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,100 @@ 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, *hp2; ++#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; ++ _res.options |= RES_USE_INET6; ++ if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL) ++ hp1 = dup_hostent(hp1); ++ if ((hp2 = gethostbyname2(host, AF_INET)) != NULL) ++ hp2 = dup_hostent(hp2); ++ _res.options = res_options; ++ if (hp1 && hp2) { ++ hp = merge_hostent(hp1, hp2); ++ free((char *) hp1); ++ free((char *) hp2); ++ return (hp); ++ } ++ if (hp1) ++ return (hp1); ++ 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) +@@ -91,6 +196,15 @@ 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 = (char *) malloc(strlen(host)+1); ++ if (! h.h_name){ ++ fprintf(stderr, "Sorry, out of memory\n"); ++ exit(1); ++ } ++ strncpy(h.h_name, host, strlen(host)+1); ++#endif + return (dup_hostent(&h)); + } + +@@ -104,19 +218,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 +253,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 +269,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 +--- socket.c.orig ++++ socket.c +@@ -30,6 +30,12 @@ static char sccsid[] = "@(#) socket.c 1. + #include + #include + ++#ifdef INET6 ++#ifndef USE_GETIPNODEBY ++#include ++#endif ++#endif ++ + extern char *inet_ntoa(); + + /* Local stuff. */ +@@ -74,8 +80,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 +115,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 +132,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 +144,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 +178,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 +202,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 +252,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 +322,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 +343,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 +366,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); + + /* +--- tcpd.c.orig ++++ tcpd.c +@@ -24,6 +24,7 @@ static char sccsid[] = "@(#) tcpd.c 1.10 + #include + #include + #include ++#include + + #ifndef MAXPATHNAMELEN + #define MAXPATHNAMELEN BUFSIZ +@@ -120,7 +121,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); +--- tcpd.h.orig ++++ tcpd.h +@@ -17,7 +17,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 */ + }; +--- tcpdchk.c.orig ++++ tcpdchk.c +@@ -22,6 +22,9 @@ static char sccsid[] = "@(#) tcpdchk.c 1 + + #include + #include ++#ifdef INET6 ++#include ++#endif + #include + #include + #include +@@ -397,6 +400,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) +@@ -423,14 +446,27 @@ char *pat; + #endif + #endif + } 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); +--- tcpdmatch.c.orig ++++ tcpdmatch.c +@@ -68,8 +68,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 +180,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 +260,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 +--- update.c.orig ++++ update.c +@@ -46,10 +46,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; + + /* +--- workarounds.c.orig ++++ workarounds.c +@@ -166,11 +166,22 @@ struct sockaddr *sa; + int *len; + { + int ret; ++#ifdef INET6 ++ struct sockaddr_storage *sin = (struct sockaddr_storage *) sa; ++#else + struct sockaddr_in *sin = (struct sockaddr_in *) sa; ++#endif + + if ((ret = getpeername(sock, sa, len)) >= 0 ++#ifdef INET6 ++ && ((sin->__ss_family == AF_INET6 ++ && IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sin)->sin6_addr)) ++ || (sin->ss_family == AF_INET ++ && ((struct sockaddr_in *)sin)->sin_addr.s_addr == 0))) { ++#else + && sa->sa_family == AF_INET + && sin->sin_addr.s_addr == 0) { ++#endif + errno = ENOTCONN; + return (-1); + } else { diff --git a/tcp_wrappers_7.6-ipv6-fix.diff b/tcp_wrappers_7.6-ipv6-fix.diff new file mode 100644 index 0000000..238609e --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-fix.diff @@ -0,0 +1,956 @@ +# +# This patch makes tcpd/libwrap work with IPv6, IPv4 and +# mapped IPv4 addresses. +# +# The approach is "convert everything to IPv6". It means that +# any IPv4 address I ever met either in /etc/hosts.* or that I get from +# the socket is first converted to v4-mapped and then handled as if it was +# IPv6. This simplifies the logic very much and makes the code much +# cleaner. Prefixes are also supported in the form [3ffe:ffff::/48] as +# well as for IPv4 addresses. +# +# Made by Michal Ludvig , +# November , 2002 +# +================================================================================ +--- Makefile.orig ++++ Makefile +@@ -1,5 +1,7 @@ + # @(#) Makefile 1.23 97/03/21 19:27:20 + ++really-all: linux ++ + what: + @echo + @echo "Usage: edit the REAL_DAEMON_DIR definition in the Makefile then:" +@@ -670,7 +672,7 @@ CFLAGS = -O2 -pipe -DFACILITY=$(FACILITY + LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \ + hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \ + $(FROM_OBJ) fix_options.o socket.o tli.o workarounds.o \ +- update.o misc.o diag.o percent_m.o myvsyslog.o ++ update.o misc.o diag.o percent_m.o myvsyslog.o ip6utils.o + + FROM_OBJ= fromhost.o + +@@ -683,6 +685,7 @@ KIT = README miscd.c tcpd.c fromhost.c h + tli-sequent.h misc.c diag.c ncr.c tcpdchk.c percent_m.c \ + myvsyslog.c mystdarg.h printf.ck README.IRIX Banners.Makefile \ + refuse.c tcpdchk.8 setenv.c inetcf.c inetcf.h scaffold.c \ ++ ip6utils.c ip6utils.h \ + scaffold.h tcpdmatch.8 README.NIS + + LIB = libwrap.a +@@ -812,6 +815,7 @@ printfck: + + # Internal compilation dependencies. + ++tcpd.h: ip6utils.h + clean_exit.o: cflags + clean_exit.o: tcpd.h + diag.o: cflags +--- hosts_access.c.orig ++++ hosts_access.c +@@ -85,11 +85,6 @@ static int server_match(); + 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. */ + +@@ -308,15 +303,17 @@ struct host_info *host; + } else if (STR_EQ(tok, "LOCAL")) { /* local: no dots in name */ + char *name = eval_hostname(host); + return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name)); +- } else if ((mask = split_at(tok, '/')) != 0) { /* net/mask */ +- return (masked_match(tok, mask, eval_hostaddr(host))); + } else { /* anything else */ + return (string_match(tok, eval_hostaddr(host)) + || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); + } + } + +-/* string_match - match string against pattern */ ++/* string_match - match string against pattern ++ * ++ * tok = data read from /etc/hosts.* ++ * string = textual data of actual client ++ */ + + static int string_match(tok, string) + char *tok; +@@ -324,13 +321,6 @@ 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)); +@@ -340,122 +330,65 @@ char *string; + return (STR_NE(string, unknown)); + } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ + return (STRN_EQ(tok, string, n)); +- } else { /* exact match */ ++ } else if (STR_EQ(tok, string)) /* exact match */ ++ return (YES); + #ifdef INET6 ++ else /* IP addresses match - not needed for IPv4 */ ++ { ++ /* For simplicity we convert everything to IPv6 (or v4 mapped) */ + struct in6_addr pat, addr; +- int len, ret; +- char ch; +- ++ int len, ret, prefixlen=128; ++ char ch, token[INET6_ADDRSTRLEN+1], *mask; ++ + 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))); ++ if (*tok == '[' && tok[len - 1] == ']') ++ { ++ ch = tok[len - 1]; ++ tok[len - 1] = '\0'; ++ snprintf(token, sizeof(token), "%s", tok+1); ++ tok[len - 1] = ch; ++ } ++ else ++ snprintf(token, sizeof(token), "%s", tok); ++ ++ /* If prefix was given, handle it */ ++ if ((mask = split_at(token, '/')) != 0) ++ { ++ if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0) ++ { ++ tcpd_warn ("Wrong prefix length in %s", tok); ++ return (NO); ++ } ++ ++ if (is_v4_string (token)) ++ prefixlen += 96; /* extend to v4mapped */ ++ ++ if (prefixlen > 128) ++ { ++ tcpd_warn ("Prefix too long in %s", tok); ++ return (NO); ++ } ++ } ++ ++ memset (&pat, 0, sizeof(pat)); ++ memset (&addr, 0, sizeof(addr)); ++ ++ if (inet_pton_mapped(AF_INET6, token, &pat) != 1) ++ return (NO); ++ ++ if (inet_pton_mapped(AF_INET6, string, &addr) != 1) ++ { ++ tcpd_warn("Unable to handle client address: %s", string); ++ return (NO); + } +-#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() +- * gives to forms with less than four components is inconsistent with the +- * access control language. John P. Rouillard . +- */ +- +- if ((addr = dot_quad_addr(string)) == INADDR_NONE) +- 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 (prefixlen < 128) ++ { ++ apply_v6_prefix (&pat, prefixlen); ++ apply_v6_prefix (&addr, prefixlen); + } +- if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i]) +- return NO; +- i += 4; +- mask_len -= 32; ++ ++ return (!memcmp(&pat, &addr, sizeof(struct in6_addr))); + } +- return YES; ++#endif + } +-#endif /* INET6 */ +--- /dev/null ++++ ip6utils.c +@@ -0,0 +1,152 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "ip6utils.h" ++ ++/* inet_pton_mapped() ++ - works like inet_pton(3) but always returns IPv6 address ++ in dst - either "real" or v4mapped (::ffff:1.2.3.4) in ++ the case, when src points to IPv4 address (eg. to 1.2.3.4). */ ++int ++inet_pton_mapped (int af, const char *src, void *dst) ++{ ++ int ret; ++ ++ /* Mapped address is v6. */ ++ if (af != AF_INET6) ++ { ++ errno = EAFNOSUPPORT; ++ return -1; ++ } ++ ++ /* We must put the result somewhere. */ ++ if (!dst) ++ { ++ errno = EFAULT; ++ return -1; ++ } ++ ++ /* First try whether the address IPv6. */ ++ ret = inet_pton (AF_INET6, src, dst); ++ if (ret > 0) ++ return ret; ++ ++ /* Because we're here, it apparently wasn't IPv6. Try IPv4 now. */ ++ ret = inet_pton (AF_INET, src, &((struct in6_addr *)dst)->s6_addr32[3]); ++ if (ret > 0) ++ { ++ /* Good, it was IPv4, map it now. */ ++ ((struct in6_addr *)dst)->s6_addr32[0] = 0; ++ ((struct in6_addr *)dst)->s6_addr32[1] = 0; ++ ((struct in6_addr *)dst)->s6_addr32[2] = htonl(0x0000ffffL); ++ } ++ return ret; ++} ++ ++/* inet_ntop2() ++ - works like inet_ntop(3) but doesn't need an external ++ buffer. Usefull eg. for printing addresses via printf(). */ ++const char * ++inet_ntop2 (int af, const void *src) ++{ ++ static char address[INET6_ADDRSTRLEN]; ++ ++ return inet_ntop(af, src, address, sizeof(address)); ++} ++ ++/* sa_map_v4_to_v6() ++ - Take an IPv4 address in first argument and map it to ++ IPv4-mapped (::ffff:1.2.3.4) IPv6 address. */ ++struct sockaddr_in6 * ++sa_map_v4_to_v6 (struct sockaddr_in *sin, struct sockaddr_in6 *sin6) ++{ ++ /* Both pointers must be not-NULL or we'll segfault. */ ++ if (!sin || !sin6) ++ { ++ errno = EFAULT; ++ return NULL; ++ } ++ ++ /* We can map only IPv4 addresses. */ ++ if (sin->sin_family != AF_INET) ++ return NULL; ++ ++ /* Map it now... */ ++ memset(sin6, 0, sizeof(*sin6)); ++ ++ sin6->sin6_family = AF_INET6; ++ sin6->sin6_port = sin->sin_port; ++ sin6->sin6_addr.s6_addr16[5] = 0xffff; ++ sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr; ++ ++ return sin6; ++} ++ ++/* is_v4_string(), is_v6_string() ++ - Return 1 when src is a string representing a valid ++ IPv4, resp. IPv6 address. Return 0 otherwise. */ ++int ++is_v4_string (const char *src) ++{ ++ struct in_addr result; ++ ++ return (inet_pton (AF_INET, src, &result) > 0); ++} ++ ++int ++is_v6_string (const char *src) ++{ ++ struct in6_addr result; ++ ++ return (inet_pton (AF_INET6, src, &result) > 0); ++} ++ ++/* apply_v6_prefix() ++ - mask the address given in 'src' with 'prefixlen' netmask. Clear ++ all bits not covered by prefixlen. */ ++int ++apply_v6_prefix (struct in6_addr *src, int prefixlen) ++{ ++ int i; ++ ++ /* Check prefix for a valid length. */ ++ if (prefixlen < 0 || prefixlen > 128) ++ return -1; ++ ++ /* Prefixes will quite often end up on 16b boundary, ++ so we'll walk thorugh 16b blocks and possibly avoid ++ creating bitmasks. */ ++ for (i=0; i<8; i++) ++ { ++ /* Prefix fully covers this block -> leave as is. */ ++ if (prefixlen >= (i+1)*16) ++ continue; ++ /* Prefix doesn't cover this block -> zero it. */ ++ if (prefixlen <= i*16) ++ { ++ src->s6_addr16[i] = 0; ++ continue; ++ } ++ /* Prefix ends somewhere inside in this block. Let's ++ build and apply a bitmask for this block. */ ++ { ++ uint16_t mask=0; ++ int bits; ++ ++ bits = prefixlen - i*16; ++ ++ while (bits) ++ { ++ mask |= (1 << (16-bits)); ++ bits --; ++ } ++ ++ src->s6_addr16[i] &= htons(mask); ++ } ++ } ++ ++ return 0; ++} +--- /dev/null ++++ ip6utils.h +@@ -0,0 +1,33 @@ ++#ifndef IP6UTILS_H ++#define IP6UTILS_H ++ ++/* inet_pton_mapped() ++ - works like inet_pton(3) but always returns IPv6 address ++ in dst - either "real" or v4mapped (::ffff:1.2.3.4) in ++ the case, when src points to IPv4 address (eg. to 1.2.3.4). ++ Return value is as with inet_pton(), dst remains untouched on ++ an address translation failure. */ ++int inet_pton_mapped (int af, const char *src, void *dst); ++ ++/* inet_ntop2() ++ - works like inet_ntop(3) but doesn't need an external ++ buffer. Usefull eg. for printing addresses via printf(). */ ++const char *inet_ntop2 (int af, const void *src); ++ ++/* sa_map_v4_to_v6() ++ - Take an IPv4 address in form 1.2.3.4 and map it to ++ IPv4-mapped form ::ffff:1.2.3.4 */ ++struct sockaddr_in6 *sa_map_v4_to_v6 (struct sockaddr_in *sin, struct sockaddr_in6 *sin6); ++ ++/* is_v4_string(), is_v6_string() ++ - Return 1 when src is a string representing a valid ++ IPv4, resp. IPv6 address. Return 0 otherwise. */ ++int is_v4_string (const char *src); ++int is_v6_string (const char *src); ++ ++/* apply_v6_prefix() ++ - mask the address given in 'src' with 'prefixlen' netmask. Clear ++ all bits not covered by prefixlen. Return -1 on a failure, else 0. */ ++int apply_v6_prefix (struct in6_addr *src, int prefixlen); ++ ++#endif /* IP6UTILS_H */ +--- socket.c.orig ++++ socket.c +@@ -25,16 +25,12 @@ static char sccsid[] = "@(#) socket.c 1. + #include + #include + #include ++#include + #include + #include + #include + #include +- +-#ifdef INET6 +-#ifndef USE_GETIPNODEBY +-#include +-#endif +-#endif ++#include + + extern char *inet_ntoa(); + +@@ -65,10 +61,10 @@ char *name; + */ + + if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) { +- return (gethostbyname(name)); ++ return (gethostbyname(name)); + } else { +- sprintf(dot_name, "%s.", name); +- return (gethostbyname(dot_name)); ++ sprintf(dot_name, "%s.", name); ++ return (gethostbyname(dot_name)); + } + } + +@@ -104,15 +100,15 @@ struct request_info *request; + + len = sizeof(client); + if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) { +- request->sink = sock_sink; +- len = sizeof(client); +- if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK, +- (struct sockaddr *) & client, &len) < 0) { +- tcpd_warn("can't get client address: %m"); +- return; /* give up */ +- } ++ request->sink = sock_sink; ++ len = sizeof(client); ++ if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK, ++ (struct sockaddr *) & client, &len) < 0) { ++ tcpd_warn("can't get client address: %m"); ++ return; /* give up */ ++ } + #ifdef really_paranoid +- memset(buf, 0 sizeof(buf)); ++ memset(buf, 0 sizeof(buf)); + #endif + } + #ifdef INET6 +@@ -129,8 +125,8 @@ struct request_info *request; + + len = sizeof(server); + if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) { +- tcpd_warn("getsockname: %m"); +- return; ++ tcpd_warn("getsockname: %m"); ++ return; + } + #ifdef INET6 + request->server->sin = (struct sockaddr *)&server; +@@ -150,18 +146,18 @@ struct host_info *host; + int alen; + + if (!sin) +- return; ++ 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; ++ 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)); +@@ -169,30 +165,139 @@ struct host_info *host; + struct sockaddr_in *sin = host->sin; + + if (sin != 0) +- STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); ++ STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); + #endif + } + ++#ifdef INET6 + /* sock_hostname - map endpoint address to host name */ ++void ++sock_hostname(struct host_info *host) ++{ ++ struct addrinfo hints, *res, *resbase; ++ struct sockaddr *sa = host->sin; ++ struct sockaddr_in6 *sin6, sin6buf; ++ int errcode; ++ ++ if (!sa) ++ { ++ /* Unknown sockaddr => unable to verify */ ++ tcpd_warn ("can't verify hostname: sockaddr == NULL"); ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } ++ ++ switch (sa->sa_family) ++ { ++ case AF_INET: ++ if (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0) ++ { ++ /* Address 0.0.0.0 is invalid. */ ++ tcpd_warn ("can't verify hostname of address %s", ++ inet_ntop2(sa->sa_family, ++ &((struct sockaddr_in *)sa)->sin_addr)); ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } ++ sin6 = sa_map_v4_to_v6 ((struct sockaddr_in *)sa, ++ &sin6buf); ++ break; ++ case AF_INET6: ++ sin6 = (struct sockaddr_in6 *)sa; ++ break; ++ default: ++ /* Unknown protocol family. */ ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } ++ ++ /* First resolve address to name... */ ++ if (getnameinfo ((struct sockaddr *)sin6, sizeof(*sin6), ++ host->name, sizeof(host->name), ++ NULL, 0, 0) < 0) ++ { ++ tcpd_warn ("can't verify hostname: getnameinfo(%s): %s", ++ inet_ntop2(sin6->sin6_family, &sin6->sin6_addr), ++ strerror(errno)); ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } ++ ++ /* Now resolve the name back to the address. Hopefully we'll ++ get the same one... */ ++ ++ memset (&hints, 0, sizeof(hints)); ++ ++ hints.ai_family = PF_UNSPEC; ++ hints.ai_socktype = SOCK_STREAM; ++ hints.ai_flags |= AI_CANONNAME; ++ ++ errcode = getaddrinfo(host->name, NULL, &hints, &resbase); ++ if(errcode) ++ { ++ tcpd_warn ("can't verify hostname: getaddrinfo(%s): %s", ++ host->name, ++ gai_strerror(errcode)); ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } ++ ++ res = resbase; ++ ++ /* Now walk through all reutrned addresses and see if at least one ++ is the same (or mmapped-same) as the incoming one. */ ++ while(res) ++ { ++ struct sockaddr_in6 *sin6res, sin6resbuf; ++ ++ switch (res->ai_family) ++ { ++ case AF_INET: ++ sin6res = sa_map_v4_to_v6 ((struct sockaddr_in *)res->ai_addr, &sin6resbuf); ++ break; ++ case AF_INET6: ++ sin6res = (struct sockaddr_in6 *)res->ai_addr; ++ break; ++ default: ++ res = res->ai_next; ++ continue; ++ } ++ ++ if (memcmp (&sin6->sin6_addr, &sin6res->sin6_addr, ++ sizeof(sin6->sin6_addr)) == 0) ++ break; ++ ++ res = res->ai_next; ++ } ++ ++ freeaddrinfo (resbase); ++ ++ if (res == NULL) ++ { ++ /* We walked through the list but didn't find a matching address. */ ++ tcpd_warn ("can't verify hostname: getaddrinfo(%s) didn't return %s", ++ host->name, ++ inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr)); ++ strncpy(host->name, paranoid, sizeof(host->name)); ++ return; ++ } + +-void sock_hostname(host) ++ if (STR_NE (host->name, res->ai_canonname) && STR_NE(host->name, "localhost")) ++ { ++ /* We don't treat this as an error, though... */ ++ tcpd_warn("host name mismatch: %s != %s (%s)", ++ host->name, res->ai_canonname, ++ inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr)); ++ } ++ ++ return; ++} ++#else /* INET6 */ ++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; + + /* +@@ -202,163 +307,76 @@ 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 ++ && (hp = gethostbyaddr((char *) &(sin->sin_addr), ++ sizeof(sin->sin_addr), AF_INET)) != 0) { + +- /* +- * Verify that the address is a member of the address list returned +- * by gethostbyname(hostname). +- * +- * Verify also that gethostbyaddr() and gethostbyname() return the same +- * hostname, or rshd and rlogind may still end up being spoofed. +- * +- * On some sites, gethostbyname("localhost") returns "localhost.domain". +- * This is a DNS artefact. We treat it as a special case. When we +- * can't believe the address list from gethostbyname("localhost") +- * we're in big trouble anyway. +- */ ++ STRN_CPY(host->name, hp->h_name, sizeof(host->name)); + +-#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. +- */ ++ /* ++ * Verify that the address is a member of the address list returned ++ * by gethostbyname(hostname). ++ * ++ * Verify also that gethostbyaddr() and gethostbyname() return the same ++ * hostname, or rshd and rlogind may still end up being spoofed. ++ * ++ * On some sites, gethostbyname("localhost") returns "localhost.domain". ++ * This is a DNS artefact. We treat it as a special case. When we ++ * can't believe the address list from gethostbyname("localhost") ++ * we're in big trouble anyway. ++ */ + +-#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 ++ if ((hp = gethostbyname(host->name)) == 0) { + +- } else if (STR_NE(host->name, hp->h_name) +- && STR_NE(host->name, "localhost")) { ++ /* ++ * Unable to verify that the host name matches the address. This ++ * may be a transient problem or a botched name server setup. ++ */ ++ ++ tcpd_warn("can't verify hostname: gethostbyname(%s) failed", ++ host->name); ++ ++ } else if (STR_NE(host->name, hp->h_name) ++ && STR_NE(host->name, "localhost")) { ++ ++ /* ++ * The gethostbyaddr() and gethostbyname() calls did not return ++ * the same hostname. This could be a nameserver configuration ++ * problem. It could also be that someone is trying to spoof us. ++ */ + +- /* +- * The gethostbyaddr() and gethostbyname() calls did not return +- * the same hostname. This could be a nameserver configuration +- * problem. It could also be that someone is trying to spoof us. +- */ +- +- tcpd_warn("host name/name mismatch: %s != %.*s", +- host->name, STRING_LENGTH, hp->h_name); +- +- } else { +- +- /* +- * The address should be a member of the address list returned by +- * gethostbyname(). We should first verify that the h_addrtype +- * field is AF_INET, but this program has already caused too much +- * grief on systems with broken library code. +- */ ++ tcpd_warn("host name/name mismatch: %s != %.*s", ++ host->name, STRING_LENGTH, hp->h_name); + +- 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 +- } ++ } else { + +- /* +- * The host name does not map to the initial address. Perhaps +- * someone has messed up. Perhaps someone compromised a name +- * server. +- */ ++ /* ++ * The address should be a member of the address list returned by ++ * gethostbyname(). We should first verify that the h_addrtype ++ * field is AF_INET, but this program has already caused too much ++ * grief on systems with broken library code. ++ */ ++ ++ for (i = 0; hp->h_addr_list[i]; i++) { ++ if (memcmp(hp->h_addr_list[i], ++ (char *) &sin->sin_addr, ++ sizeof(sin->sin_addr)) == 0) ++ return; /* name is good, keep it */ ++ } ++ ++ /* ++ * The host name does not map to the initial address. Perhaps ++ * someone has messed up. Perhaps someone compromised a name ++ * 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 ++ tcpd_warn("host name/address mismatch: %s != %.*s", ++ inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name); ++ } ++ strcpy(host->name, paranoid); /* name is bad, clobber it */ + } + } ++#endif /* INET6 */ + + /* sock_sink - absorb unreceived IP datagram */ + +--- tcpd.h.orig ++++ tcpd.h +@@ -10,6 +10,8 @@ + #include + #endif + ++#include "ip6utils.h" ++ + /* Structure to describe one communications endpoint. */ + + #define STRING_LENGTH 128 /* hosts, users, processes */ diff --git a/tcp_wrappers_7.6-ipv6-host-match.patch b/tcp_wrappers_7.6-ipv6-host-match.patch new file mode 100644 index 0000000..51a6411 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-host-match.patch @@ -0,0 +1,364 @@ +--- + hosts_access.c | 271 ++++++++++++++++++++++++++++++++++----------------------- + misc.c | 18 +++ + tcpd.h | 2 + 3 files changed, 183 insertions(+), 108 deletions(-) + +Index: tcp_wrappers_7.6/hosts_access.c +=================================================================== +--- tcp_wrappers_7.6.orig/hosts_access.c ++++ tcp_wrappers_7.6/hosts_access.c +@@ -88,6 +88,10 @@ static int server_match(); + static int client_match(); + static int host_match(); + static int string_match(); ++static int masked_match(); ++#ifdef INET6 ++static void ipv6_mask(); ++#endif + + /* Size of logical line buffer. */ + +@@ -293,6 +297,74 @@ struct hosts_info *host; + return (match); + } + ++static inline int ++host_info_ipv6addr(const struct host_info *host, struct in6_addr *addrbuf) ++{ ++ /* ++ * In some cases we don't get the sockaddr, only the addr. ++ * We use inet_pton to convert it to its binary representation ++ * and match against that. ++ */ ++ if (host->sin == NULL) { ++ if (host->addr == NULL || inet_pton(AF_INET6, host->addr, addrbuf) != 1) ++ return 0; ++ ++ return 1; ++ } else ++ if (host->sin->ss_family == AF_INET6) { ++ *addrbuf = ((struct sockaddr_in6 *) host->sin)->sin6_addr; ++ return 1; ++ } ++ return 0; ++} ++ ++static inline int ++token_ipv6addr_and_mask(char *tok, struct in6_addr *addrbuf, unsigned int *maskbits) ++{ ++ char *cbr; ++ char *slash; ++ ++ if (*tok != '[') ++ return 0; ++ ++ *maskbits = 128; ++ ++ ++tok; /* now points to the beginning of the IPv6 addr string */ ++ if ((cbr = strchr(tok, ']')) == NULL) { ++ tcpd_warn("bad IP6 address specification"); ++ return 0; ++ } ++ *cbr++ = '\0'; ++ ++ /* ++ * A /nnn prefix specifies how many bits of the address we ++ * need to check. ++ * Note, we support both [x::y/64] and [x::y]/64 ++ */ ++ if ((slash = strchr(tok, '/')) == NULL && *cbr == '/') ++ slash = cbr; ++ ++ if (slash != NULL) { ++ int mask; ++ ++ *slash++ = '\0'; ++ mask = atoi(slash); ++ if (mask < 0 || mask > 128) { ++ tcpd_warn("bad IP6 prefix specification"); ++ return 0; ++ } ++ ++ *maskbits = mask; ++ } ++ ++ if (inet_pton(AF_INET6, tok, addrbuf) != 1) { ++ tcpd_warn("bad IP6 address specification"); ++ return 0; ++ } ++ ++ return 1; ++} ++ + /* host_match - match host name and/or address against pattern */ + + static int host_match(tok, host) +@@ -328,12 +400,68 @@ struct host_info *host; + } else if (STR_EQ(tok, "LOCAL")) { /* local: no dots in name */ + char *name = eval_hostname(host); + return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name)); ++ } else if (tok[0] == '[') { /* IPv6 address */ ++#ifdef INET6 ++ struct in6_addr match_addr, host_addr; ++ unsigned int mask = 128; ++ ++ if (!host_info_ipv6addr(host, &host_addr)) ++ return (NO); ++ ++ if (!token_ipv6addr_and_mask(tok, &match_addr, &mask)) ++ return (NO); ++ ++ /* ++ * Zero the bits we're not interested in in both addresses ++ * then compare. Note that we take a copy of the host info ++ * in that case. ++ */ ++ if (mask != 128) { ++ ipv6_mask(&match_addr, mask); ++ ipv6_mask(&host_addr, mask); ++ } ++ if (memcmp(&match_addr, &host_addr, sizeof(struct in6_addr)) == 0) ++ return (YES); ++#endif ++ return (NO); ++ } else if ((mask = split_at(tok, '/')) != 0) { /* net/mask */ ++ return (masked_match(tok, mask, eval_hostaddr(host))); + } else { /* anything else */ +- return (string_match(tok, eval_hostaddr(host)) +- || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); ++ return (string_match(tok, eval_hostaddr(host)) ++ || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); + } + } + ++static int masked_match(net_tok, mask_tok, string) ++char *net_tok; ++char *mask_tok; ++char *string; ++{ ++ unsigned long net; ++ unsigned long mask; ++ unsigned long addr; ++ ++ /* ++ * Disallow forms other than dotted quad: the treatment that inet_addr() ++ * gives to forms with less than four components is inconsistent with the ++ * access control language. John P. Rouillard . ++ */ ++ ++ if ((addr = dot_quad_addr(string)) == INADDR_NONE) ++ return (NO); ++ if ((net = dot_quad_addr(net_tok)) == INADDR_NONE ++ || ((mask = dot_quad_addr(mask_tok)) == INADDR_NONE ++ && strcmp(mask_tok, "255.255.255.255") ++ && (mask = prefix_to_netmask(mask_tok)) == INADDR_NONE ++ && strcmp(mask_tok, "32"))) { ++ /* 255.255.255.255 == INADDR_NONE, separate check needed. TJ. */ ++ /* 32 == INADDR_NONE, separate check needed. philipp */ ++ tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); ++ return (NO); /* not tcpd_jump() */ ++ } ++ return ((addr & mask) == net); ++} ++ + /* string_match - match string against pattern + * + * tok = data read from /etc/hosts.* +@@ -359,113 +487,14 @@ char *string; + return (YES); + } else if (STR_EQ(tok, "KNOWN")) { /* not unknown */ + return (STR_NE(string, unknown)); +- } else if (STR_EQ(tok, string)) /* exact match */ +- return (YES); +-#ifdef INET6 +- else /* IP addresses match - not needed for IPv4 */ +- { +- /* For simplicity we convert everything to IPv6 (or v4 mapped) */ +- struct in6_addr pat, addr; +- int len, ret, prefixlen=128, nof_periods = 0; +- char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition; +- +- /* If prefix was given, handle it */ +- if ((mask = split_at(tok, '/')) != 0) +- { +- if (strchr(mask, '.') != NULL) /* We have something +- like 255.255.0.0 */ +- { +- int b1, b2, b3, b4; +- uint32_t netmask; +- +- if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) +- { +- tcpd_warn ("Wrong netmask in %s", tok); +- return (NO); +- } +- netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4; +- prefixlen = 0; +- while (netmask > 0) +- { +- ++prefixlen; +- netmask <<= 1; +- } +- } +- else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0) +- { +- tcpd_warn ("Wrong prefix length in %s", tok); +- return (NO); +- } +- +- if (is_v4_string (tok)) +- prefixlen += 96; /* extend to v4mapped */ +- +- if (prefixlen > 128) +- { +- tcpd_warn ("Prefix too long in %s", tok); +- return (NO); +- } +- } +- +- len = strlen(tok); +- if (tok[len - 1] == '.') { /* prefix */ +- char *ptok = tok; +- +- while ((ptok = strchr(ptok, '.')) != NULL){ +- nof_periods++; +- ptok++; +- } +- switch(nof_periods){ +- case 1: +- addition = "0.0.0"; +- prefixlen = 8; +- break; +- case 2: +- addition = "0.0"; +- prefixlen = 16; +- break; +- case 3: +- addition = "0"; +- prefixlen = 24; +- break; +- default: +- tcpd_warn ("Wrong prefix %s", tok); +- return (NO); +- } +- snprintf(token, sizeof(token), "%s%s", tok, addition); +- prefixlen += 96; /* extend to v4mapped */ +- } +- else if (*tok == '[' && tok[len - 1] == ']') +- { +- ch = tok[len - 1]; +- tok[len - 1] = '\0'; +- snprintf(token, sizeof(token), "%s", tok+1); +- tok[len - 1] = ch; +- } +- else +- snprintf(token, sizeof(token), "%s", tok); +- +- memset (&pat, 0, sizeof(pat)); +- memset (&addr, 0, sizeof(addr)); +- +- if (inet_pton_mapped(AF_INET6, token, &pat) != 1) +- return (NO); +- +- if (inet_pton_mapped(AF_INET6, string, &addr) != 1) +- { +- tcpd_warn("Unable to handle client address: %s", string); +- return (NO); +- } +- +- if (prefixlen < 128) +- { +- apply_v6_prefix (&pat, prefixlen); +- apply_v6_prefix (&addr, prefixlen); +- } +- +- return (!memcmp(&pat, &addr, sizeof(struct in6_addr))); ++ } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ ++ return (STRN_EQ(tok, string, n)); ++ } else if ((STR_EQ(tok, "localhost") || STR_EQ(tok, "localhost.localdomain")) ++ && (STR_EQ(string, "localhost") || STR_EQ(string, "localhost.localdomain"))) { ++ return (YES); /* these localhosts are equivalent */ ++ } else { /* exact match */ ++ return (STR_EQ(tok, string)); + } +-#endif + } + + #ifndef DISABLE_WILDCARD_MATCHING +@@ -535,3 +564,29 @@ int match_pattern_ylo(const char *s, con + /*NOTREACHED*/ + } + #endif /* DISABLE_WILDCARD_MATCHING */ ++ ++#ifdef INET6 ++/* ++ * Function that zeros all but the first "maskbits" bits of the IPV6 address ++ * This function can be made generic by specifying an address length as ++ * extra parameter. (So Wietse can implement 1.2.3.4/16) ++ */ ++static void ipv6_mask(in6p, maskbits) ++struct in6_addr *in6p; ++int maskbits; ++{ ++ unsigned char *p = (unsigned char*) in6p; ++ ++ if (maskbits < 0 || maskbits >= 128) ++ return; ++ ++ p += maskbits / 8; ++ maskbits %= 8; ++ ++ if (maskbits != 0) ++ *p++ &= 0xff << (8 - maskbits); ++ ++ while (p < (((unsigned char*) in6p)) + sizeof(*in6p)) ++ *p++ = 0; ++} ++#endif +Index: tcp_wrappers_7.6/misc.c +=================================================================== +--- tcp_wrappers_7.6.orig/misc.c ++++ tcp_wrappers_7.6/misc.c +@@ -107,3 +107,21 @@ char *str; + } + return (runs == 4 ? inet_addr(str) : INADDR_NONE); + } ++ ++/* prefix_to_netmask - convert prefix (0-32) to netmask */ ++ ++unsigned long prefix_to_netmask(str) ++char *str; ++{ ++ unsigned long prefix; ++ char *endptr; ++ ++ if (!isdigit(str[0])) ++ return INADDR_NONE; ++ ++ prefix = strtoul(str, &endptr, 10); ++ if ((endptr == str) || (*endptr != '\0') || (prefix > 32)) ++ return INADDR_NONE; ++ ++ return htonl(~0UL << (32 - prefix)); ++} +Index: tcp_wrappers_7.6/tcpd.h +=================================================================== +--- tcp_wrappers_7.6.orig/tcpd.h ++++ tcp_wrappers_7.6/tcpd.h +@@ -88,6 +88,7 @@ extern void refuse(struct request_info * + extern char *xgets(char *, int, FILE *); + extern char *split_at(char *, int); + extern unsigned long dot_quad_addr(char *); ++extern char *skip_ipv6_addrs(char *); + #else + extern int hosts_access(); /* access control */ + extern void shell_cmd(); /* execute shell command */ +@@ -98,6 +99,7 @@ extern void refuse(); /* clean up and + extern char *xgets(); /* fgets() on steroids */ + extern char *split_at(); /* strchr() and split */ + extern unsigned long dot_quad_addr(); /* restricted inet_addr() */ ++extern char *skip_ipv6_addrs(); + #endif + + /* Global variables. */ diff --git a/tcp_wrappers_7.6-ipv6-mapped-v4.patch b/tcp_wrappers_7.6-ipv6-mapped-v4.patch new file mode 100644 index 0000000..e053ea6 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-mapped-v4.patch @@ -0,0 +1,56 @@ +--- + hosts_access.c | 2 +- + socket.c | 14 +++++++++----- + 2 files changed, 10 insertions(+), 6 deletions(-) + +Index: tcp_wrappers_7.6/hosts_access.c +=================================================================== +--- tcp_wrappers_7.6.orig/hosts_access.c ++++ tcp_wrappers_7.6/hosts_access.c +@@ -461,7 +461,7 @@ char *string; + } + return ((addr & mask) == net); + } +- ++ + /* string_match - match string against pattern + * + * tok = data read from /etc/hosts.* +Index: tcp_wrappers_7.6/socket.c +=================================================================== +--- tcp_wrappers_7.6.orig/socket.c ++++ tcp_wrappers_7.6/socket.c +@@ -187,24 +187,28 @@ struct host_info *host; + #ifdef INET6 + struct sockaddr *sin = (struct sockaddr *) host->sin; + char *ap; +- int alen; ++ int af; + + if (!sin) + return; +- switch (sin->sa_family) { ++ ++ af = sin->sa_family; ++ switch (af) { + 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); ++ if (IN6_IS_ADDR_V4MAPPED(ap)) { ++ ap = &((struct in6_addr *) ap)->s6_addr32[3]; ++ af = AF_INET; ++ } + break; + default: + return; + } + host->addr[0] = '\0'; +- inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr)); ++ inet_ntop(af, ap, host->addr, sizeof(host->addr)); + #else + struct sockaddr_in *sin = host->sin; + diff --git a/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch b/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch new file mode 100644 index 0000000..309da68 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch @@ -0,0 +1,297 @@ +--- + ip6utils.h | 2 + + rfc931.c | 101 +++++++++++++++++++++++++++++++++++++++---------------------- + scaffold.c | 9 +---- + socket.c | 14 +------- + tcpd.h | 8 +--- + update.c | 4 +- + 6 files changed, 76 insertions(+), 62 deletions(-) + +Index: tcp_wrappers_7.6/ip6utils.h +=================================================================== +--- tcp_wrappers_7.6.orig/ip6utils.h ++++ tcp_wrappers_7.6/ip6utils.h +@@ -1,6 +1,8 @@ + #ifndef IP6UTILS_H + #define IP6UTILS_H + ++#include ++ + /* inet_pton_mapped() + - works like inet_pton(3) but always returns IPv6 address + in dst - either "real" or v4mapped (::ffff:1.2.3.4) in +Index: tcp_wrappers_7.6/rfc931.c +=================================================================== +--- tcp_wrappers_7.6.orig/rfc931.c ++++ tcp_wrappers_7.6/rfc931.c +@@ -65,28 +65,69 @@ int sig; + siglongjmp(timebuf, sig); + } + ++static inline unsigned int ++sockaddr_len(const struct sockaddr_storage *ap) ++{ ++ switch (ap->ss_family) { ++ case AF_INET: ++ return sizeof(struct sockaddr_in); ++ ++ case AF_INET6: ++ return sizeof(struct sockaddr_in6); ++ ++ } ++ ++ return 0; ++} ++ ++static inline unsigned short ++sockaddr_port(const struct sockaddr_storage *ap) ++{ ++ unsigned short num; ++ ++ switch (ap->ss_family) { ++ case AF_INET: ++ num = ((const struct sockaddr_in *) ap)->sin_port; ++ break; ++ case AF_INET6: ++ num = ((const struct sockaddr_in6 *) ap)->sin6_port; ++ break; ++ default: ++ num = 0; ++ break; ++ } ++ ++ return ntohs(num); ++} ++ ++static inline void ++sockaddr_set_port(struct sockaddr_storage *ap, unsigned short port) ++{ ++ unsigned short num = htons(port); ++ ++ switch (ap->ss_family) { ++ case AF_INET: ++ ((struct sockaddr_in *) ap)->sin_port = num; ++ break; ++ case AF_INET6: ++ ((struct sockaddr_in6 *) ap)->sin6_port = num; ++ break; ++ } ++} ++ ++ + /* 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 ++struct sockaddr_storage *rmt_sin; ++struct sockaddr_storage *our_sin; + 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; +@@ -97,18 +138,13 @@ char *dest; + + #ifdef INET6 + /* address family must be the same */ +- if (rmt_sin->sa_family != our_sin->sa_family) { ++ if (rmt_sin->ss_family != our_sin->ss_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: ++ ++ alen = sockaddr_len(our_sin); ++ if (alen == 0) { + STRN_CPY(dest, result, STRING_LENGTH); + return; + } +@@ -125,7 +161,7 @@ char *dest; + */ + + #ifdef INET6 +- if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) { ++ if ((fp = fsocket(our_sin->ss_family, SOCK_STREAM, 0)) != 0) { + #else + if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) { + #endif +@@ -154,18 +190,11 @@ char *dest; + */ + + #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; +- } ++ our_query_sin = *our_sin; ++ sockaddr_set_port(&our_query_sin, ANY_PORT); ++ ++ rmt_query_sin = *rmt_sin; ++ sockaddr_set_port(&rmt_query_sin, RFC931_PORT); + + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin, + alen) >= 0 && +@@ -191,8 +220,8 @@ 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)); ++ sockaddr_port(rmt_sin), ++ sockaddr_port(our_sin)); + #else + ntohs(rmt_sin->sin_port), + ntohs(our_sin->sin_port)); +Index: tcp_wrappers_7.6/scaffold.c +=================================================================== +--- tcp_wrappers_7.6.orig/scaffold.c ++++ tcp_wrappers_7.6/scaffold.c +@@ -336,13 +336,8 @@ struct request_info *request; + /* ARGSUSED */ + + void rfc931(rmt_sin, our_sin, dest) +-#ifndef INET6 +-struct sockaddr_in *rmt_sin; +-struct sockaddr_in *our_sin; +-#else +-struct sockaddr *rmt_sin; +-struct sockaddr *our_sin; +-#endif ++struct sockaddr_storage *rmt_sin; ++struct sockaddr_storage *our_sin; + char *dest; + { + strcpy(dest, unknown); +Index: tcp_wrappers_7.6/tcpd.h +=================================================================== +--- tcp_wrappers_7.6.orig/tcpd.h ++++ tcp_wrappers_7.6/tcpd.h +@@ -19,11 +19,7 @@ + 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 sockaddr_storage *sin; /* socket address or 0 */ + struct t_unitdata *unit; /* TLI transport address or 0 */ + struct request_info *request; /* for shared information */ + }; +@@ -86,7 +82,7 @@ extern void fromhost(); /* get/validat + extern int hosts_access(struct request_info *); + extern void shell_cmd(char *); + extern char *percent_x(char *, int, char *, struct request_info *); +-extern void rfc931(struct sockaddr *, struct sockaddr *, char *); ++extern void rfc931(struct sockaddr_storage *, struct sockaddr_storage *, char *); + extern void clean_exit(struct request_info *); + extern void refuse(struct request_info *); + extern char *xgets(char *, int, FILE *); +Index: tcp_wrappers_7.6/socket.c +=================================================================== +--- tcp_wrappers_7.6.orig/socket.c ++++ tcp_wrappers_7.6/socket.c +@@ -116,11 +116,7 @@ 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 +@@ -133,11 +129,7 @@ struct request_info *request; + tcpd_warn("getsockname: %m"); + return; + } +-#ifdef INET6 +- request->server->sin = (struct sockaddr *)&server; +-#else + request->server->sin = &server; +-#endif + } + + +@@ -180,7 +172,7 @@ struct request_info *request; + sock_methods(request); + + memcpy(&client, res->ai_addr, res->ai_addrlen); +- request->client->sin = (struct sockaddr *)&client; ++ request->client->sin = &client; + freeaddrinfo(res); + + request->client->name[0] = 0; +@@ -193,7 +185,7 @@ void sock_hostaddr(host) + struct host_info *host; + { + #ifdef INET6 +- struct sockaddr *sin = host->sin; ++ struct sockaddr *sin = (struct sockaddr *) host->sin; + char *ap; + int alen; + +@@ -227,7 +219,7 @@ void + sock_hostname(struct host_info *host) + { + struct addrinfo hints, *res, *resbase; +- struct sockaddr *sa = host->sin; ++ struct sockaddr *sa = (struct sockaddr *) host->sin; + struct sockaddr_in6 *sin6, sin6buf; + int errcode; + +Index: tcp_wrappers_7.6/update.c +=================================================================== +--- tcp_wrappers_7.6.orig/update.c ++++ tcp_wrappers_7.6/update.c +@@ -48,14 +48,14 @@ va_list ap; + continue; + case RQ_CLIENT_SIN: + #ifdef INET6 +- request->client->sin = va_arg(ap, struct sockaddr *); ++ request->client->sin = va_arg(ap, struct sockaddr_storage *); + #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 *); ++ request->server->sin = va_arg(ap, struct sockaddr_storage *); + #else + request->server->sin = va_arg(ap, struct sockaddr_in *); + #endif diff --git a/tcp_wrappers_7.6-ipv6-subnet.diff b/tcp_wrappers_7.6-ipv6-subnet.diff new file mode 100644 index 0000000..5ed6c4a --- /dev/null +++ b/tcp_wrappers_7.6-ipv6-subnet.diff @@ -0,0 +1,101 @@ +--- hosts_access.c 2014/10/11 17:16:13 1.57 ++++ hosts_access.c 2014/10/12 16:11:45 +@@ -367,41 +367,10 @@ + /* For simplicity we convert everything to IPv6 (or v4 mapped) */ + struct in6_addr pat, addr; + int len, ret, prefixlen=128, nof_periods = 0; +- char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition; +- len = strlen(tok); +- if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ +- while ((ptok = strchr(ptok, '.')) != NULL){ +- nof_periods++; +- ptok++; +- } +- switch(nof_periods){ +- case 1: +- addition = "0.0.0/8"; +- break; +- case 2: +- addition = "0.0/16"; +- break; +- case 3: +- addition = "0/24"; +- break; +- default: +- tcpd_warn ("Wrong prefix %s", tok); +- return (NO); +- } +- snprintf(token, sizeof(token), "%s%s", tok, addition); +- } +- else if (*tok == '[' && tok[len - 1] == ']') +- { +- ch = tok[len - 1]; +- tok[len - 1] = '\0'; +- snprintf(token, sizeof(token), "%s", tok+1); +- tok[len - 1] = ch; +- } +- else +- snprintf(token, sizeof(token), "%s", tok); +- ++ char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition; ++ + /* If prefix was given, handle it */ +- if ((mask = split_at(token, '/')) != 0) ++ if ((mask = split_at(tok, '/')) != 0) + { + if (strchr(mask, '.') != NULL) /* We have something + like 255.255.0.0 */ +@@ -428,7 +397,7 @@ + return (NO); + } + +- if (is_v4_string (token)) ++ if (is_v4_string (tok)) + prefixlen += 96; /* extend to v4mapped */ + + if (prefixlen > 128) +@@ -437,6 +406,44 @@ + return (NO); + } + } ++ ++ len = strlen(tok); ++ if (tok[len - 1] == '.') { /* prefix */ ++ char *ptok = tok; ++ ++ while ((ptok = strchr(ptok, '.')) != NULL){ ++ nof_periods++; ++ ptok++; ++ } ++ switch(nof_periods){ ++ case 1: ++ addition = "0.0.0"; ++ prefixlen = 8; ++ break; ++ case 2: ++ addition = "0.0"; ++ prefixlen = 16; ++ break; ++ case 3: ++ addition = "0"; ++ prefixlen = 24; ++ break; ++ default: ++ tcpd_warn ("Wrong prefix %s", tok); ++ return (NO); ++ } ++ snprintf(token, sizeof(token), "%s%s", tok, addition); ++ prefixlen += 96; /* extend to v4mapped */ ++ } ++ else if (*tok == '[' && tok[len - 1] == ']') ++ { ++ ch = tok[len - 1]; ++ tok[len - 1] = '\0'; ++ snprintf(token, sizeof(token), "%s", tok+1); ++ tok[len - 1] = ch; ++ } ++ else ++ snprintf(token, sizeof(token), "%s", tok); + + memset (&pat, 0, sizeof(pat)); + memset (&addr, 0, sizeof(addr)); diff --git a/tcp_wrappers_7.6-ipv6.fix.fix.diff b/tcp_wrappers_7.6-ipv6.fix.fix.diff new file mode 100644 index 0000000..09455c8 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6.fix.fix.diff @@ -0,0 +1,30 @@ +--- hosts_access.c.orig ++++ hosts_access.c +@@ -354,7 +354,26 @@ char *string; + /* If prefix was given, handle it */ + if ((mask = split_at(token, '/')) != 0) + { +- if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0) ++ if (strchr(mask, '.') != NULL) /* We have something ++ like 255.255.0.0 */ ++ { ++ int b1, b2, b3, b4; ++ uint32_t netmask; ++ ++ if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4) ++ { ++ tcpd_warn ("Wrong netmask in %s", tok); ++ return (NO); ++ } ++ netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4; ++ prefixlen = 0; ++ while (netmask > 0) ++ { ++ ++prefixlen; ++ netmask <<= 1; ++ } ++ } ++ else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0) + { + tcpd_warn ("Wrong prefix length in %s", tok); + return (NO); diff --git a/tcp_wrappers_7.6-ipv6.fix.fix2.diff b/tcp_wrappers_7.6-ipv6.fix.fix2.diff new file mode 100644 index 0000000..f218fff --- /dev/null +++ b/tcp_wrappers_7.6-ipv6.fix.fix2.diff @@ -0,0 +1,47 @@ +--- hosts_access.c.orig ++++ hosts_access.c +@@ -328,8 +328,6 @@ char *string; + return (YES); + } else if (STR_EQ(tok, "KNOWN")) { /* not unknown */ + return (STR_NE(string, unknown)); +- } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ +- return (STRN_EQ(tok, string, n)); + } else if (STR_EQ(tok, string)) /* exact match */ + return (YES); + #ifdef INET6 +@@ -337,11 +335,31 @@ char *string; + { + /* For simplicity we convert everything to IPv6 (or v4 mapped) */ + struct in6_addr pat, addr; +- int len, ret, prefixlen=128; +- char ch, token[INET6_ADDRSTRLEN+1], *mask; +- ++ int len, ret, prefixlen=128, nof_periods = 0; ++ char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition; + len = strlen(tok); +- if (*tok == '[' && tok[len - 1] == ']') ++ if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */ ++ while ((ptok = strchr(ptok, '.')) != NULL){ ++ nof_periods++; ++ ptok++; ++ } ++ switch(nof_periods){ ++ case 1: ++ addition = "0.0.0/8"; ++ break; ++ case 2: ++ addition = "0.0/16"; ++ break; ++ case 3: ++ addition = "0/24"; ++ break; ++ default: ++ tcpd_warn ("Wrong prefix %s", tok); ++ return (NO); ++ } ++ snprintf(token, sizeof(token), "%s%s", tok, addition); ++ } ++ else if (*tok == '[' && tok[len - 1] == ']') + { + ch = tok[len - 1]; + tok[len - 1] = '\0'; diff --git a/tcp_wrappers_7.6-ipv6.fix.fix3.diff b/tcp_wrappers_7.6-ipv6.fix.fix3.diff new file mode 100644 index 0000000..77a7df7 --- /dev/null +++ b/tcp_wrappers_7.6-ipv6.fix.fix3.diff @@ -0,0 +1,10 @@ +--- scaffold.c 2019-09-24 10:22:50.334175241 +0200 ++++ scaffold.c 2019-09-24 10:23:16.773896312 +0200 +@@ -160,7 +160,6 @@ + } + } + res_options = _res.options; +- _res.options |= RES_USE_INET6; + if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL) + hp1 = dup_hostent(hp1); + if ((hp2 = gethostbyname2(host, AF_INET)) != NULL) diff --git a/tcp_wrappers_7.6-multi_local_interfaces-fix.diff b/tcp_wrappers_7.6-multi_local_interfaces-fix.diff new file mode 100644 index 0000000..a8a33c6 --- /dev/null +++ b/tcp_wrappers_7.6-multi_local_interfaces-fix.diff @@ -0,0 +1,11 @@ +--- socket.c.orig ++++ socket.c +@@ -282,7 +282,7 @@ sock_hostname(struct host_info *host) + return; + } + +- if (STR_NE (host->name, res->ai_canonname) && STR_NE(host->name, "localhost")) ++ if ((!res->ai_canonname || STR_NE (host->name, res->ai_canonname)) && STR_NE(host->name, "localhost")) + { + /* We don't treat this as an error, though... */ + tcpd_warn("host name mismatch: %s != %s (%s)", diff --git a/tcp_wrappers_7.6-nonvoid.diff b/tcp_wrappers_7.6-nonvoid.diff new file mode 100644 index 0000000..0530b88 --- /dev/null +++ b/tcp_wrappers_7.6-nonvoid.diff @@ -0,0 +1,67 @@ +--- fakelog.c.orig ++++ fakelog.c +@@ -16,7 +16,7 @@ static char sccsid[] = "@(#) fakelog.c 1 + /* openlog - dummy */ + + /* ARGSUSED */ +- ++void + openlog(name, logopt, facility) + char *name; + int logopt; +@@ -26,7 +26,7 @@ int facility; + } + + /* vsyslog - format one record */ +- ++void + vsyslog(severity, fmt, ap) + int severity; + char *fmt; +@@ -42,7 +42,7 @@ va_list ap; + /* syslog - format one record */ + + /* VARARGS */ +- ++void + VARARGS(syslog, int, severity) + { + va_list ap; +@@ -55,7 +55,7 @@ VARARGS(syslog, int, severity) + } + + /* closelog - dummy */ +- ++void + closelog() + { + /* void */ +--- fix_options.c.orig ++++ fix_options.c +@@ -31,7 +31,7 @@ static char sccsid[] = "@(#) fix_options + #define BUFFER_SIZE 512 /* Was: BUFSIZ */ + + /* fix_options - get rid of IP-level socket options */ +- ++void + fix_options(request) + struct request_info *request; + { +--- options.c.orig ++++ options.c +@@ -541,6 +541,7 @@ char *name; + return (t->value); + tcpd_jump("bad syslog facility or severity: \"%s\"", name); + /* NOTREACHED */ ++ return 0; + } + + /* severity_option - change logging severity for this event (Dave Mitchell) */ +--- tcpd.c.orig ++++ tcpd.c +@@ -132,4 +132,5 @@ char **argv; + syslog(LOG_ERR, "error: cannot execute %s: %m", path); + clean_exit(&request); + /* NOTREACHED */ ++ return 0; + } diff --git a/tcp_wrappers_7.6-optflags.diff b/tcp_wrappers_7.6-optflags.diff new file mode 100644 index 0000000..9ff578a --- /dev/null +++ b/tcp_wrappers_7.6-optflags.diff @@ -0,0 +1,46 @@ +Index: Makefile +=================================================================== +--- Makefile.orig ++++ Makefile +@@ -673,7 +673,7 @@ SHLIBFLAGS = -Lshared -lwrap + shared/%.o: %.c + $(CC) $(CFLAGS) $(SHCFLAGS) -c $< -o $@ + +-CFLAGS = -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \ ++CFLAGS = $(RPM_OPT_FLAGS) $(shell getconf LFS_CFLAGS) -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \ + $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \ + -DREAL_DAEMON_DIR=\"$(REAL_DAEMON_DIR)\" $(STYLE) $(KILL_OPT) \ + -DSEVERITY=$(SEVERITY) -DRFC931_TIMEOUT=$(RFC931_TIMEOUT) \ +@@ -730,26 +730,26 @@ $(SHLIB): $(SHLIB_OBJ) + ln -s $(notdir $(SHLIBSOMAJ)) $(SHLIBSO) + + tcpd: tcpd.o $(SHLIB) +- $(CC) $(CFLAGS) -o $@ tcpd.o $(SHLIBFLAGS) ++ $(CC) -pie -o $@ tcpd.o $(SHLIBFLAGS) + + miscd: miscd.o $(SHLIB) +- $(CC) $(CFLAGS) -o $@ miscd.o $(SHLIBFLAGS) ++ $(CC) -pie -o $@ miscd.o $(SHLIBFLAGS) + + safe_finger: safe_finger.o $(SHLIB) +- $(CC) $(CFLAGS) -o $@ safe_finger.o $(SHLIBFLAGS) ++ $(CC) -pie -o $@ safe_finger.o $(SHLIBFLAGS) + + TCPDMATCH_OBJ = tcpdmatch.o fakelog.o inetcf.o scaffold.o + + tcpdmatch: $(TCPDMATCH_OBJ) $(SHLIB) +- $(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS) ++ $(CC) -pie -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS) + + try-from: try-from.o fakelog.o $(SHLIB) +- $(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(SHLIBFLAGS) ++ $(CC) -pie -o $@ try-from.o fakelog.o $(SHLIBFLAGS) + + TCPDCHK_OBJ = tcpdchk.o fakelog.o inetcf.o scaffold.o + + tcpdchk: $(TCPDCHK_OBJ) $(SHLIB) +- $(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS) ++ $(CC) -pie -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS) + + shar: $(KIT) + @shar $(KIT) diff --git a/tcp_wrappers_7.6-prototypes.diff b/tcp_wrappers_7.6-prototypes.diff new file mode 100644 index 0000000..ad04855 --- /dev/null +++ b/tcp_wrappers_7.6-prototypes.diff @@ -0,0 +1,91 @@ +--- clean_exit.c.orig ++++ clean_exit.c +@@ -13,6 +13,8 @@ static char sccsid[] = "@(#) clean_exit. + #endif + + #include ++#include ++#include + + extern void exit(); + +--- hosts_access.c.orig ++++ hosts_access.c +@@ -31,6 +31,8 @@ static char sccsid[] = "@(#) hosts_acces + #include + #include + #include ++#include ++#include + #include + #include + #include +--- inetcf.c.orig ++++ inetcf.c +@@ -88,7 +88,7 @@ char *conf; + } else { + for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "r")) == 0; i++) + /* void */ ; +- if (fp == 0) { ++ if (!fp) { + fprintf(stderr, "Cannot find your inetd.conf or tlid.conf file.\n"); + fprintf(stderr, "Please specify its location.\n"); + exit(1); +--- ip6utils.c.orig ++++ ip6utils.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include + + #include "ip6utils.h" +--- options.c.orig ++++ options.c +@@ -41,6 +41,8 @@ static char sccsid[] = "@(#) options.c 1 + #include + #include + #include ++#include ++#include + #include + #include + #include +--- percent_x.c.orig ++++ percent_x.c +@@ -18,6 +18,8 @@ static char sccsid[] = "@(#) percent_x.c + + #include + #include ++#include ++#include + #include + + extern void exit(); +--- shell_cmd.c.orig ++++ shell_cmd.c +@@ -15,9 +15,13 @@ static char sccsid[] = "@(#) shell_cmd.c + /* System libraries. */ + + #include ++#include + #include + #include + #include ++#include ++#include ++#include + #include + #include + +--- update.c.orig ++++ update.c +@@ -21,6 +21,7 @@ static char sccsid[] = "@(#) update.c 1. + + #include + #include ++#include + #include + + /* Local stuff. */ diff --git a/tcp_wrappers_7.6-shared-lib.diff b/tcp_wrappers_7.6-shared-lib.diff new file mode 100644 index 0000000..b520533 --- /dev/null +++ b/tcp_wrappers_7.6-shared-lib.diff @@ -0,0 +1,163 @@ +--- Makefile.orig ++++ Makefile +@@ -145,9 +145,9 @@ freebsd: + + linux: + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \ +- LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \ ++ LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=weak_symbols.o \ + NETGROUP=-DNETGROUP TLI= \ +- EXTRA_CFLAGS="-fPIC -DSYS_ERRLIST_DEFINED -DINET6=1 -Dss_family=__ss_family" all ++ EXTRA_CFLAGS="-fPIC -DHAVE_STRERROR -DINET6=1 -Dss_family=__ss_family -DHAVE_WEAKSYMS -D_REENTRANT" all + + # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x. + hpux hpux8 hpux9 hpux10: +@@ -660,7 +660,18 @@ HOSTNAME= -DALWAYS_HOSTNAME + # Protection against weird shells or weird make programs. + + SHELL = /bin/sh +-.c.o:; $(CC) $(CFLAGS) -c $*.c ++.c.o:; $(CC) $(CFLAGS) -o $*.o -c $*.c ++ ++SOMAJOR = 0 ++SOMINOR = 7.6 ++LIB = libwrap.a ++SHLIB = shared/libwrap.so.$(SOMAJOR).$(SOMINOR) ++SHLIBSOMAJ = shared/libwrap.so.$(SOMAJOR) ++SHLIBSO = shared/libwrap.so ++SHLIBFLAGS = -Lshared -lwrap ++ ++shared/%.o: %.c ++ $(CC) $(CFLAGS) $(SHCFLAGS) -c $< -o $@ + + CFLAGS = -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \ + $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \ +@@ -669,11 +680,16 @@ CFLAGS = -O2 -pipe -DFACILITY=$(FACILITY + $(UCHAR) $(TABLES) $(STRINGS) $(TLI) $(EXTRA_CFLAGS) $(DOT) \ + $(VSYSLOG) + ++SHLINKFLAGS = -shared -Xlinker -soname -Xlinker libwrap.so.$(SOMAJOR) -lc $(LIBS) ++SHCFLAGS = -fPIC -shared -D_REENTRANT ++ + LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \ + hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \ + $(FROM_OBJ) fix_options.o socket.o tli.o workarounds.o \ + update.o misc.o diag.o percent_m.o myvsyslog.o ip6utils.o + ++SHLIB_OBJ= $(addprefix shared/, $(LIB_OBJ)); ++ + FROM_OBJ= fromhost.o + + KIT = README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \ +@@ -688,9 +704,8 @@ KIT = README miscd.c tcpd.c fromhost.c h + ip6utils.c ip6utils.h \ + scaffold.h tcpdmatch.8 README.NIS + +-LIB = libwrap.a ++all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk $(LIB) + +-all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk + + # Invalidate all object files when the compiler options (CFLAGS) have changed. + +@@ -701,33 +716,40 @@ config-check: + then rm /tmp/cflags.$$$$ ; \ + else mv /tmp/cflags.$$$$ cflags ; \ + fi >/dev/null 2>/dev/null ++ @if [ ! -d shared ]; then mkdir shared; fi + + $(LIB): $(LIB_OBJ) + rm -f $(LIB) + $(AR) $(ARFLAGS) $(LIB) $(LIB_OBJ) + -$(RANLIB) $(LIB) + +-tcpd: tcpd.o $(LIB) +- $(CC) $(CFLAGS) -o $@ tcpd.o $(LIB) $(LIBS) ++$(SHLIB): $(SHLIB_OBJ) ++ rm -f $(SHLIB) ++ $(CC) -o $(SHLIB) $(SHLINKFLAGS) $(SHLIB_OBJ) ++ ln -s $(notdir $(SHLIB)) $(SHLIBSOMAJ) ++ ln -s $(notdir $(SHLIBSOMAJ)) $(SHLIBSO) ++ ++tcpd: tcpd.o $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ tcpd.o $(SHLIBFLAGS) + +-miscd: miscd.o $(LIB) +- $(CC) $(CFLAGS) -o $@ miscd.o $(LIB) $(LIBS) ++miscd: miscd.o $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ miscd.o $(SHLIBFLAGS) + +-safe_finger: safe_finger.o $(LIB) +- $(CC) $(CFLAGS) -o $@ safe_finger.o $(LIB) $(LIBS) ++safe_finger: safe_finger.o $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ safe_finger.o $(SHLIBFLAGS) + + TCPDMATCH_OBJ = tcpdmatch.o fakelog.o inetcf.o scaffold.o + +-tcpdmatch: $(TCPDMATCH_OBJ) $(LIB) +- $(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(LIB) $(LIBS) ++tcpdmatch: $(TCPDMATCH_OBJ) $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS) + +-try-from: try-from.o fakelog.o $(LIB) +- $(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(LIB) $(LIBS) ++try-from: try-from.o fakelog.o $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(SHLIBFLAGS) + + TCPDCHK_OBJ = tcpdchk.o fakelog.o inetcf.o scaffold.o + +-tcpdchk: $(TCPDCHK_OBJ) $(LIB) +- $(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(LIB) $(LIBS) ++tcpdchk: $(TCPDCHK_OBJ) $(SHLIB) ++ $(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS) + + shar: $(KIT) + @shar $(KIT) +@@ -743,7 +765,8 @@ archive: + + clean: + rm -f tcpd miscd safe_finger tcpdmatch tcpdchk try-from *.[oa] core \ +- cflags ++ cflags libwrap*.so* ++ rm -rf shared + + tidy: clean + chmod -R a+r . +@@ -890,5 +913,6 @@ update.o: cflags + update.o: mystdarg.h + update.o: tcpd.h + vfprintf.o: cflags ++weak_symbols.o: tcpd.h + workarounds.o: cflags + workarounds.o: tcpd.h +--- tcpd.h.orig ++++ tcpd.h +@@ -106,8 +106,14 @@ extern unsigned long dot_quad_addr(); /* + + /* Global variables. */ + ++#ifdef HAVE_WEAKSYMS ++extern int allow_severity __attribute__ ((weak)); /* for connection logging */ ++extern int deny_severity __attribute__ ((weak)); /* for connection logging */ ++#else + extern int allow_severity; /* for connection logging */ + extern int deny_severity; /* for connection logging */ ++#endif ++ + extern char *hosts_allow_table; /* for verification mode redirection */ + extern char *hosts_deny_table; /* for verification mode redirection */ + extern int hosts_access_verbose; /* for verbose matching mode */ +--- /dev/null ++++ weak_symbols.c +@@ -0,0 +1,11 @@ ++/* ++ * @(#) weak_symbols.h 1.5 99/12/29 23:50 ++ * ++ * Author: Anthony Towns ++ */ ++ ++#ifdef HAVE_WEAKSYMS ++#include ++int deny_severity = LOG_WARNING; ++int allow_severity = SEVERITY; ++#endif diff --git a/tcp_wrappers_7.6-shared-lib2.diff b/tcp_wrappers_7.6-shared-lib2.diff new file mode 100644 index 0000000..d1fb29e --- /dev/null +++ b/tcp_wrappers_7.6-shared-lib2.diff @@ -0,0 +1,18 @@ +--- tcpd.h.orig ++++ tcpd.h +@@ -126,10 +126,15 @@ extern int resident; /* > 0 if residen + */ + + #ifdef __STDC__ ++extern int hosts_access(struct request_info *request); ++extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, ++ char *client_user); + extern struct request_info *request_init(struct request_info *,...); + extern struct request_info *request_set(struct request_info *,...); + extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user); + #else ++extern int hosts_access(); ++extern int hosts_ctl(); + extern struct request_info *request_init(); /* initialize request */ + extern struct request_info *request_set(); /* update request structure */ + #endif diff --git a/tcp_wrappers_7.6-uninitialized.diff b/tcp_wrappers_7.6-uninitialized.diff new file mode 100644 index 0000000..0ef926f --- /dev/null +++ b/tcp_wrappers_7.6-uninitialized.diff @@ -0,0 +1,11 @@ +--- inetcf.c.orig ++++ inetcf.c +@@ -61,7 +61,7 @@ char *inet_cfg(conf) + char *conf; + { + char buf[BUFSIZ]; +- FILE *fp; ++ FILE *fp = NULL; + char *service; + char *protocol; + char *user; diff --git a/tcp_wrappers_7.6.diff b/tcp_wrappers_7.6.diff new file mode 100644 index 0000000..9e98519 --- /dev/null +++ b/tcp_wrappers_7.6.diff @@ -0,0 +1,364 @@ +--- Makefile.orig ++++ Makefile +@@ -44,7 +44,7 @@ what: + #REAL_DAEMON_DIR=/usr/etc + # + # SysV.4 Solaris 2.x OSF AIX +-#REAL_DAEMON_DIR=/usr/sbin ++REAL_DAEMON_DIR=/usr/sbin + # + # BSD 4.4 + #REAL_DAEMON_DIR=/usr/libexec +@@ -143,8 +143,9 @@ freebsd: + + 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= \ ++ NETGROUP=-DNETGROUP TLI= \ ++ EXTRA_CFLAGS="-fPIC -DSYS_ERRLIST_DEFINED -DINET6=1 -Dss_family=__ss_family" all + + # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x. + hpux hpux8 hpux9 hpux10: +@@ -229,7 +230,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 + +@@ -472,7 +473,7 @@ BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS + # 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. + ################################# +@@ -491,7 +492,7 @@ VSYSLOG = -Dvsyslog=myvsyslog + # Uncomment the next definition to turn on the language extensions + # (examples: allow, deny, banners, twist and spawn). + # +-#STYLE = -DPROCESS_OPTIONS # Enable language extensions. ++STYLE = -DPROCESS_OPTIONS # Enable language extensions. + + ################################################################ + # Optional: Changing the default disposition of logfile records +@@ -514,7 +515,7 @@ VSYSLOG = -Dvsyslog=myvsyslog + # + # The LOG_XXX names below are taken from the /usr/include/syslog.h file. + +-FACILITY= LOG_MAIL # LOG_MAIL is what most sendmail daemons use ++FACILITY= LOG_AUTHPRIV # LOG_MAIL is what most sendmail daemons use + + # The syslog priority at which successful connections are logged. + +@@ -531,7 +532,7 @@ SEVERITY= LOG_INFO # LOG_INFO is normall + # and with Solaris < 2.4. APPEND_DOT will not work with hostnames taken + # from /etc/hosts or from NIS maps. It does work with DNS through NIS. + # +-# DOT= -DAPPEND_DOT ++DOT= -DAPPEND_DOT + + ################################################## + # Optional: Always attempt remote username lookups +@@ -610,7 +611,7 @@ TABLES = -DHOSTS_DENY=\"/etc/hosts.deny\ + # Paranoid mode implies hostname lookup. In order to disable hostname + # lookups altogether, see the next section. + +-PARANOID= -DPARANOID ++#PARANOID= -DPARANOID + + ######################################## + # Optional: turning off hostname lookups +@@ -649,7 +650,7 @@ HOSTNAME= -DALWAYS_HOSTNAME + # source-routed traffic in the kernel. Examples: 4.4BSD derivatives, + # Solaris 2.x, and Linux. See your system documentation for details. + # +-# KILL_OPT= -DKILL_IP_OPTIONS ++#KILL_OPT= -DKILL_IP_OPTIONS + + ## End configuration options + ############################ +@@ -659,12 +660,12 @@ HOSTNAME= -DALWAYS_HOSTNAME + SHELL = /bin/sh + .c.o:; $(CC) $(CFLAGS) -c $*.c + +-CFLAGS = -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \ ++CFLAGS = -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \ + $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \ + -DREAL_DAEMON_DIR=\"$(REAL_DAEMON_DIR)\" $(STYLE) $(KILL_OPT) \ + -DSEVERITY=$(SEVERITY) -DRFC931_TIMEOUT=$(RFC931_TIMEOUT) \ + $(UCHAR) $(TABLES) $(STRINGS) $(TLI) $(EXTRA_CFLAGS) $(DOT) \ +- $(VSYSLOG) $(HOSTNAME) ++ $(VSYSLOG) + + LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \ + hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \ +--- /dev/null ++++ README.ipv6 +@@ -0,0 +1,17 @@ ++;; IPv6 patch for tcp_wrappers_7.6 1.6 ++;; Aug 23, 1999 by Hajimu UMEMOTO ++;; ++;; This patch supports IPv4/IPv6 dual stack and IPv4-mapped IPv6 address. ++;; You can replace stock tcpd or libwrap.a with this. ++;; IPv6 address pattern is as a `[net]/prefixlen' pair. ++;; This patch was tested on KAME/FreeBSD, KAME/FreeBSD3, KAME/NetBSD, ++;; RedHat 5.1 with kernel 2.1.126, and RedHat 6.0 with kernel 2.2.10. ++;; ++;; CAUTION: ++;; Back out change for field separater. Now, field separater is `:' ++;; not `|'. To specify IPv6 address, enclose IPv6 address with `[' ++;; and `]'. ++;; ++;; For Linux users: ++;; If your libc doesn't have sockaddr_storage, try target `linux-old'. ++ +--- hosts_access.c.orig ++++ hosts_access.c +@@ -89,6 +90,33 @@ static int masked_match(); + + /* hosts_access - host access control facility */ + ++static int ++yp_get_default_domain (char **outdomain) ++{ ++ static char __ypdomainname[1025] = "\0"; ++ int result = 0; ++ *outdomain = NULL; ++ ++ if (__ypdomainname[0] == '\0') ++ { ++ if (getdomainname (__ypdomainname, 1024)) ++ result = 1; ++ else if (strcmp (__ypdomainname, "(none)") == 0) ++ { ++ /* If domainname is not set, some Systems will return "(none)" */ ++ __ypdomainname[0] = '\0'; ++ result = 1; ++ } ++ else ++ *outdomain = __ypdomainname; ++ } ++ else ++ *outdomain = __ypdomainname; ++ ++ return result; ++} ++ ++ + int hosts_access(request) + struct request_info *request; + { +--- safe_finger.c.orig ++++ safe_finger.c +@@ -31,7 +31,7 @@ extern void exit(); + + /* Local stuff */ + +-char path[] = "PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd:/etc:/usr/etc:/usr/sbin"; ++char path[] = "PATH=/bin:/usr/bin:/usr/sbin"; + + #define TIME_LIMIT 60 /* Do not keep listinging forever */ + #define INPUT_LENGTH 100000 /* Do not keep listinging forever */ +--- scaffold.c.orig ++++ scaffold.c +@@ -180,10 +180,17 @@ struct request_info *request; + + /* ARGSUSED */ + +-void rfc931(request) +-struct request_info *request; ++void rfc931(rmt_sin, our_sin, dest) ++#ifndef INET6 ++struct sockaddr_in *rmt_sin; ++struct sockaddr_in *our_sin; ++#else ++struct sockaddr *rmt_sin; ++struct sockaddr *our_sin; ++#endif ++char *dest; + { +- strcpy(request->user, unknown); ++ strcpy(dest, unknown); + } + + /* check_path - examine accessibility */ +--- tcpd.h.orig ++++ tcpd.h +@@ -4,6 +4,12 @@ + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + ++#ifdef __STDC__ ++#include ++#include ++#include ++#endif ++ + /* Structure to describe one communications endpoint. */ + + #define STRING_LENGTH 128 /* hosts, users, processes */ +@@ -61,11 +67,26 @@ extern char paranoid[]; + /* Global functions. */ + + #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT) ++#ifdef __STDC__ ++extern void fromhost(struct request_info *); ++#else + extern void fromhost(); /* get/validate client host info */ ++#endif + #else + #define fromhost sock_host /* no TLI support needed */ + #endif + ++#ifdef __STDC__ ++extern int hosts_access(struct request_info *); ++extern void shell_cmd(char *); ++extern char *percent_x(char *, int, char *, struct request_info *); ++extern void rfc931(struct sockaddr *, struct sockaddr *, char *); ++extern void clean_exit(struct request_info *); ++extern void refuse(struct request_info *); ++extern char *xgets(char *, int, FILE *); ++extern char *split_at(char *, int); ++extern unsigned long dot_quad_addr(char *); ++#else + extern int hosts_access(); /* access control */ + extern void shell_cmd(); /* execute shell command */ + extern char *percent_x(); /* do % expansion */ +@@ -75,6 +96,7 @@ extern void refuse(); /* clean up and + extern char *xgets(); /* fgets() on steroids */ + extern char *split_at(); /* strchr() and split */ + extern unsigned long dot_quad_addr(); /* restricted inet_addr() */ ++#endif + + /* Global variables. */ + +@@ -117,28 +139,47 @@ extern struct request_info *request_set( + * host_info structures serve as caches for the lookup results. + */ + ++#ifdef __STDC__ ++extern char *eval_user(struct request_info *); ++extern char *eval_hostname(struct host_info *); ++extern char *eval_hostaddr(struct host_info *); ++extern char *eval_hostinfo(struct host_info *); ++extern char *eval_client(struct request_info *); ++extern char *eval_server(struct request_info *); ++#else + extern char *eval_user(); /* client user */ + extern char *eval_hostname(); /* printable hostname */ + extern char *eval_hostaddr(); /* printable host address */ + extern char *eval_hostinfo(); /* host name or address */ + extern char *eval_client(); /* whatever is available */ + extern char *eval_server(); /* whatever is available */ ++#endif + #define eval_daemon(r) ((r)->daemon) /* daemon process name */ + #define eval_pid(r) ((r)->pid) /* process id */ + + /* Socket-specific methods, including DNS hostname lookups. */ + ++#ifdef __STDC__ ++extern void sock_host(struct request_info *); ++extern void sock_hostname(struct host_info *); ++extern void sock_hostaddr(struct host_info *); ++#else + extern void sock_host(); /* look up endpoint addresses */ + extern void sock_hostname(); /* translate address to hostname */ + extern void sock_hostaddr(); /* address to printable address */ ++#endif + #define sock_methods(r) \ + { (r)->hostname = sock_hostname; (r)->hostaddr = sock_hostaddr; } + + /* The System V Transport-Level Interface (TLI) interface. */ + + #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT) ++#ifdef __STDC__ ++extern void tli_host(struct request_info *); ++#else + extern void tli_host(); /* look up endpoint addresses etc. */ + #endif ++#endif + + /* + * Problem reporting interface. Additional file/line context is reported +@@ -178,42 +219,74 @@ extern struct tcpd_context tcpd_context; + * behavior. + */ + ++#ifdef __STDC__ ++extern void process_options(char *, struct request_info *); ++#else + extern void process_options(); /* execute options */ ++#endif + extern int dry_run; /* verification flag */ + + /* Bug workarounds. */ + + #ifdef INET_ADDR_BUG /* inet_addr() returns struct */ + #define inet_addr fix_inet_addr ++#ifdef __STDC__ ++extern long fix_inet_addr(char *); ++#else + extern long fix_inet_addr(); + #endif ++#endif + + #ifdef BROKEN_FGETS /* partial reads from sockets */ + #define fgets fix_fgets ++#ifdef __STDC__ ++extern char *fix_fgets(char *, int, FILE *); ++#else + extern char *fix_fgets(); + #endif ++#endif + + #ifdef RECVFROM_BUG /* no address family info */ + #define recvfrom fix_recvfrom ++#ifdef __STDC__ ++extern int fix_recvfrom(int, char *, int, int, struct sockaddr *, int *); ++#else + extern int fix_recvfrom(); + #endif ++#endif + + #ifdef GETPEERNAME_BUG /* claims success with UDP */ + #define getpeername fix_getpeername ++#ifdef __STDC__ ++extern int fix_getpeername(int, struct sockaddr *, int *); ++#else + extern int fix_getpeername(); + #endif ++#endif + + #ifdef SOLARIS_24_GETHOSTBYNAME_BUG /* lists addresses as aliases */ + #define gethostbyname fix_gethostbyname ++#ifdef __STDC__ ++extern struct hostent *fix_gethostbyname(char *); ++#else + extern struct hostent *fix_gethostbyname(); + #endif ++#endif + + #ifdef USE_STRSEP /* libc calls strtok() */ + #define strtok fix_strtok ++#ifdef __STDC__ ++extern char *fix_strtok(char *, char *); ++#else + extern char *fix_strtok(); + #endif ++#endif + + #ifdef LIBC_CALLS_STRTOK /* libc calls strtok() */ + #define strtok my_strtok ++#ifdef __STDC__ ++extern char *my_strtok(char *, char *); ++#else + extern char *my_strtok(); + #endif ++#endif diff --git a/tcp_wrappers_7.6.tar.gz b/tcp_wrappers_7.6.tar.gz new file mode 100644 index 0000000..1429775 --- /dev/null +++ b/tcp_wrappers_7.6.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9543d7adedf78a6de0b221ccbbd1952e08b5138717f4ade814039bb489a4315d +size 99438 diff --git a/tcpd-ocloexec.patch b/tcpd-ocloexec.patch new file mode 100644 index 0000000..3fd9b94 --- /dev/null +++ b/tcpd-ocloexec.patch @@ -0,0 +1,70 @@ +--- rfc931.c.orig ++++ rfc931.c +@@ -45,7 +45,7 @@ int protocol; + int s; + FILE *fp; + +- if ((s = socket(domain, type, protocol)) < 0) { ++ if ((s = socket(domain, type | SOCK_CLOEXEC, protocol)) < 0) { + tcpd_warn("socket: %m"); + return (0); + } else { +--- tcpdchk.c.orig ++++ tcpdchk.c +@@ -210,7 +210,7 @@ struct request_info *request; + + saved_context = tcpd_context; /* stupid compilers */ + +- if (fp = fopen(table, "r")) { ++ if (fp = fopen(table, "re")) { + tcpd_context.file = table; + tcpd_context.line = 0; + while (xgets(sv_list, sizeof(sv_list), fp)) { +--- inetcf.c.orig ++++ inetcf.c +@@ -81,12 +81,12 @@ char *conf; + * guesses. + */ + if (conf != 0) { +- if ((fp = fopen(conf, "r")) == 0) { ++ if ((fp = fopen(conf, "re")) == 0) { + fprintf(stderr, percent_m(buf, "open %s: %m\n"), conf); + exit(1); + } + } else { +- for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "r")) == 0; i++) ++ for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "re")) == 0; i++) + /* void */ ; + if (!fp) { + fprintf(stderr, "Cannot find your inetd.conf or tlid.conf file.\n"); +--- options.c.orig ++++ options.c +@@ -227,7 +227,7 @@ struct request_info *request; + FILE *fp; + + sprintf(path, "%s/%s", value, eval_daemon(request)); +- if ((fp = fopen(path, "r")) != 0) { ++ if ((fp = fopen(path, "re")) != 0) { + while ((ch = fgetc(fp)) == 0) + write(request->fd, "", 1); + ungetc(ch, fp); +--- hosts_access.c.orig ++++ hosts_access.c +@@ -173,7 +173,7 @@ struct request_info *request; + * file descriptor leaks. + */ + +- if ((fp = fopen(table, "r")) != 0) { ++ if ((fp = fopen(table, "re")) != 0) { + tcpd_context.file = table; + tcpd_context.line = 0; + while (match == NO && xgets(sv_list, sizeof(sv_list), fp) != 0) { +@@ -283,7 +283,7 @@ struct hosts_info *host; + int match = NO; + FILE *fp; + +- if ((fp = fopen(path, "r")) != 0) { ++ if ((fp = fopen(path, "re")) != 0) { + while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host))) + /* void */ ; + fclose(fp); diff --git a/tcpd.changes b/tcpd.changes new file mode 100644 index 0000000..7414b26 --- /dev/null +++ b/tcpd.changes @@ -0,0 +1,277 @@ +------------------------------------------------------------------- +Tue Oct 11 09:34:37 UTC 2022 - Danilo Spinella + +- Add hosts.allow and hosts.deny config files from the netcfg package, + as they are tcpd specific, bsc#1099755 + +------------------------------------------------------------------- +Mon Sep 5 14:42:10 UTC 2022 - Ludwig Nussel + +- use _libdir (boo#1191098) + +------------------------------------------------------------------- +Wed Aug 24 10:48:01 UTC 2022 - Andreas Schwab + +- Makefile is not parallel-safe + +------------------------------------------------------------------- +Fri Aug 14 12:47:44 UTC 2020 - Thorsten Kukuk + +- tcp_wrappers_7.6-shared-lib.diff: Linux has STRERROR not SYS_ERRLIST + [bsc#1175272] + +------------------------------------------------------------------- +Tue Sep 24 08:25:45 UTC 2019 - Martin Liška + +- Add tcp_wrappers_7.6-ipv6.fix.fix3.diff in order to fix + boo#1149708. + +------------------------------------------------------------------- +Fri Aug 2 08:23:22 UTC 2019 - Martin Liška + +- Use FAT LTO objects in order to provide proper static library. + +------------------------------------------------------------------- +Sat Jun 3 08:36:59 UTC 2017 - meissner@suse.com + +- tcp_wrappers_7.6-optflags.diff: enable PIE for all binaries + directly. + +------------------------------------------------------------------- +Wed Apr 6 10:35:38 CEST 2016 - kukuk@suse.de + +- tcp_wrappers_7.6.diff: don't use public headers for own + functions, make own yp_get_default_domain static. + +------------------------------------------------------------------- +Mon Jul 20 14:08:16 UTC 2015 - okir@suse.com + +- Fix breakage of IPv6 address handling [bsc#914527, bsc#899185] + Added patches: + tcp_wrappers_7.6-ipv6-sockaddr-storage.patch + tcp_wrappers_7.6-ipv6-subnet.diff + tcp_wrappers_7.6-ipv6-host-match.patch + tcp_wrappers_7.6-ipv6-mapped-v4.patch +- Re-added static library + +------------------------------------------------------------------- +Fri Nov 28 13:18:37 UTC 2014 - tchvatal@suse.com + +- Cleanup with spec-cleaner +- Remove obsolete sections of provides from 2k6 +- Remove static library + +------------------------------------------------------------------- +Mon Aug 18 16:39:30 UTC 2014 - fcrozat@suse.com + +- Add obsoletes/provides to baselibs.conf + +------------------------------------------------------------------- +Mon Jun 3 00:17:04 UTC 2013 - crrodriguez@opensuse.org + +- tcpd-ocloexec.patch: Use O_CLOEXEC whenever neccesary, + otherwise fd leaks will follow. + +------------------------------------------------------------------- +Fri Apr 5 10:39:36 UTC 2013 - idonmez@suse.com + +- Cleanup spec file +- Add Source URL, see https://en.opensuse.org/SourceUrls + +------------------------------------------------------------------- +Sun Jan 20 01:29:11 UTC 2013 - jengelh@inai.de + +- Implement shared library packaging guidelines (split libwrap0) +- Parallel build with %_smp_mflags instead of %jobs +- Remove redundant %clean sections + +------------------------------------------------------------------- +Sun Apr 22 01:18:07 UTC 2012 - crrodriguez@opensuse.org + +- Refresh all patches +- Also, pass getconf LFS_CFLAGS into CFLAGS + +------------------------------------------------------------------- +Wed Oct 5 15:03:33 UTC 2011 - uli@suse.com + +- cross-build fix: use %__cc macro + +------------------------------------------------------------------- +Mon Feb 1 12:34:48 UTC 2010 - jengelh@medozas.de + +- remove not-needed sparcv9 baselib exception + +------------------------------------------------------------------- +Sun Dec 13 15:48:21 CET 2009 - jengelh@medozas.de + +- add baselibs.conf as a source +- add baselibs for SPARC +- enable parallel building + +------------------------------------------------------------------- +Fri Oct 30 19:40:28 UTC 2009 - crrodriguez@opensuse.org + +- fix build + +------------------------------------------------------------------- +Wed Jan 7 12:34:56 CET 2009 - olh@suse.de + +- obsolete old -XXbit packages (bnc#437293) + +------------------------------------------------------------------- +Tue Nov 11 16:54:34 CET 2008 - ro@suse.de + +- SLE-11 uses PPC64 instead of PPC, adapt baselibs.conf + +------------------------------------------------------------------- +Mon Oct 13 18:29:57 CEST 2008 - prusnak@suse.cz + +- applied patches from Fedora package + * fedora-bug11881.diff - replace sprintf with snprintf + * fedora-bug17795.diff - add hostfile matching + * fedora-bug17847.diff - add wildcard matching + * fedora-bug141110.diff - fix table_match usage + * fedora-bug220015.diff - add sock_hostnofd function + * fedora-docu.diff - fix manpage + * fedora-fixgethostbyname.diff - fix gethostbyname usage + * fedora-sig.diff - fix signal usage + * fedora-sigalarm.diff - fix signal usage + * fedora-sigchld.diff - fix signal usage + * fedora-sigjmp.diff - fix signal usage + * fedora-strerror.diff - fix strerror usage + +------------------------------------------------------------------- +Thu Apr 10 12:54:45 CEST 2008 - ro@suse.de + +- added baselibs.conf file to build xxbit packages + for multilib support + +------------------------------------------------------------------- +Tue May 30 16:59:21 CEST 2006 - lmichnovic@suse.cz + +- fixed uninitilized filepointer (uninitialized.diff) [#178636] + +------------------------------------------------------------------- +Fri Mar 31 15:57:06 CEST 2006 - lmichnovic@suse.cz + +- fixed missing definition of hosts_ctl() in tcpd.h (hosts_ctl.diff) + [#162303] + +------------------------------------------------------------------- +Wed Jan 25 21:31:01 CET 2006 - mls@suse.de + +- converted neededforbuild to BuildRequires + +------------------------------------------------------------------- +Sun Jan 15 19:13:05 CET 2006 - schwab@suse.de + +- Don't strip binaries. + +------------------------------------------------------------------- +Fri Sep 16 22:16:47 CEST 2005 - meissner@suse.de + +- fixed all implicit warnings. + +------------------------------------------------------------------- +Fri Jun 24 02:34:37 CEST 2005 - ro@suse.de + +- build with fPIE/pie +- really use RPM_OPT_FLAGS +- fix some non-void-return warnings + +------------------------------------------------------------------- +Thu Jan 13 15:17:52 CET 2005 - postadal@suse.cz + +- fixed crashing on system with more than one network interface [#49368] + +------------------------------------------------------------------- +Wed Sep 15 20:56:57 CEST 2004 - aj@suse.de + +- Fix warnings about implicit functions to compile with GCC 4.0. + +------------------------------------------------------------------- +Mon Mar 22 15:36:12 CET 2004 - ro@suse.de + +- installed shared lib to /%_lib, not /usr/%_lib + and add symlinks (fix for part of #36514) + +------------------------------------------------------------------- +Thu Feb 12 16:28:45 CET 2004 - kukuk@suse.de + +- Create subpackage "tcpd-devel" + +------------------------------------------------------------------- +Mon Feb 09 13:05:26 CET 2004 - postadal@suse.cz + +- added support for compiling as shared library with soname of libwrap0 (version 7.6) + +------------------------------------------------------------------- +Sun Jan 11 11:59:00 CET 2004 - adrian@suse.de + +- build as user + +------------------------------------------------------------------- +Fri Oct 31 13:20:28 CET 2003 - postadal@suse.cz + +- fixed invalid warning about "host name mismatch" [#26519, #32772] + +------------------------------------------------------------------- +Wed Sep 10 15:03:34 CEST 2003 - postadal@suse.cz + +- fixed handling patterns ending with period [#27322] + +------------------------------------------------------------------- +Sat Mar 15 17:52:56 CET 2003 - kukuk@suse.de + +- Don't handle IPv4 netmask as Prefix length [#25409] + +------------------------------------------------------------------- +Mon Dec 16 13:18:04 CET 2002 - postadal@suse.cz + +- added ip6utils.h to filelist [#22487] + +------------------------------------------------------------------- +Fri Dec 13 14:07:13 CET 2002 - postadal@suse.cz + +- fixed fix_options function in libwrap.a [#22000] +- included patch ipv6-fix.diff of mludvig@suse.cz to make tcpd work + with IPv4 and mapped IPv4 addresses. [#16162] +- turned off remote username lookups (allways_rfc931) [#22013] + +------------------------------------------------------------------- +Thu Jan 10 08:47:15 CET 2002 - cihlar@suse.cz + +- use %{_libdir} + +------------------------------------------------------------------- +Tue Nov 20 15:35:07 CET 2001 - cihlar@suse.cz + +- fixed SEGFAULT in tcpdchk [#12135] + +------------------------------------------------------------------- +Thu Sep 6 17:55:44 CEST 2001 - schwab@suse.de + +- Compile with -fPIC so that it can be included in a shared library. + +------------------------------------------------------------------- +Wed Sep 5 15:34:35 CEST 2001 - schwab@suse.de + +- Add prototypes for C++. + +------------------------------------------------------------------- +Thu Mar 22 18:51:02 CET 2001 - ro@suse.de + +- added split-aliases as provides + +------------------------------------------------------------------- +Tue Feb 27 07:33:12 CET 2001 - cihlar@suse.cz + +- fixed %files +- clean up spec file +- bzipped sources + +------------------------------------------------------------------- +Tue Apr 11 17:15:20 CEST 2000 - kukuk@suse.de + +- Split from nkitb + diff --git a/tcpd.spec b/tcpd.spec new file mode 100644 index 0000000..122e093 --- /dev/null +++ b/tcpd.spec @@ -0,0 +1,189 @@ +# +# spec file for package tcpd +# +# Copyright (c) 2022 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%define lname libwrap0 + +Name: tcpd +Version: 7.6 +Release: 0 +Summary: A security wrapper for TCP daemons +License: BSD-3-Clause +Group: Productivity/Networking/System +URL: ftp://ftp.porcupine.org/pub/security/index.html +Source: ftp://ftp.porcupine.org/pub/security/tcp_wrappers_%{version}.tar.gz +Source2: baselibs.conf +Source3: hosts.allow +Source4: hosts.deny +Patch0: tcp_wrappers_%{version}.diff +Patch1: tcp_wrappers_%{version}-ipv6-1.6.diff +Patch2: tcp_wrappers_%{version}-ipv6-fix.diff +Patch3: tcp_wrappers_%{version}-ipv6.fix.fix.diff +Patch4: tcp_wrappers_%{version}-ipv6.fix.fix2.diff +Patch5: tcp_wrappers_%{version}-host_name_mapping-fix.diff +Patch6: tcp_wrappers_%{version}-fix_options-fix.diff +Patch7: tcp_wrappers_%{version}-shared-lib.diff +Patch8: tcp_wrappers_%{version}-builtin.diff +Patch9: tcp_wrappers_%{version}-multi_local_interfaces-fix.diff +Patch10: tcp_wrappers_%{version}-optflags.diff +Patch11: tcp_wrappers_%{version}-nonvoid.diff +Patch12: tcp_wrappers_%{version}-prototypes.diff +Patch13: tcp_wrappers_%{version}-hosts_ctl.diff +Patch14: tcp_wrappers_%{version}-uninitialized.diff +Patch15: tcp_wrappers_%{version}-fedora-bug11881.diff +Patch16: tcp_wrappers_%{version}-fedora-bug141110.diff +Patch17: tcp_wrappers_%{version}-fedora-docu.diff +Patch18: tcp_wrappers_%{version}-fedora-sig.diff +Patch19: tcp_wrappers_%{version}-fedora-sigchld.diff +Patch20: tcp_wrappers_%{version}-fedora-sigjmp.diff +Patch21: tcp_wrappers_%{version}-fedora-sigalarm.diff +Patch22: tcp_wrappers_%{version}-fedora-strerror.diff +Patch23: tcp_wrappers_%{version}-fedora-fixgethostbyname.diff +Patch24: tcp_wrappers_%{version}-fedora-bug220015.diff +Patch25: tcp_wrappers_%{version}-shared-lib2.diff +Patch26: tcp_wrappers_%{version}-fedora-bug17795.diff +Patch27: tcp_wrappers_%{version}-fedora-bug17847.diff +Patch28: tcp_wrappers_7.6-implicit-decl.patch +Patch29: tcpd-ocloexec.patch +Patch30: tcp_wrappers_%{version}-ipv6-sockaddr-storage.patch +Patch31: tcp_wrappers_%{version}-ipv6-subnet.diff +Patch32: tcp_wrappers_%{version}-ipv6-host-match.patch +Patch33: tcp_wrappers_%{version}-ipv6-mapped-v4.patch +Patch34: tcp_wrappers_%{version}-ipv6.fix.fix3.diff +BuildRequires: linux-kernel-headers +Provides: nkitb:%{_sbindir}/tcpd +# bug437293 +%ifarch ppc64 +Obsoletes: tcpd-64bit +%endif +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +This package contains a small daemon program that can monitor and +filter incoming requests for finger, ftp, telnet, rlogin, rsh, exec, +tftp, talk, and other network services. + +%package -n %{lname} +Summary: The TCP wrapper library +Group: System/Libraries + +%description -n %{lname} +This package contains a library which implements classifying incoming +requests (connections) based upon rule exclusion files (%{_sysconfdir}/hosts.*). + +%package devel +Summary: Include Files and Libraries for the TCP wrapper library +Group: Development/Languages/C and C++ +Requires: %{lname} = %{version} +Requires: glibc-devel +# bug437293 +%ifarch ppc64 +Obsoletes: tcpd-devel-64bit +%endif +# + +%description devel +This package contains the library and header files, which are necessary +to compile and link programs against the TCP wrapper library. + +%prep +%setup -q -n tcp_wrappers_%{version} +%patch0 +%patch1 +%patch2 +%patch3 +%patch4 +%patch5 +%patch6 +%patch7 +%patch8 +%patch9 +%patch10 +%patch11 +%patch12 +%patch13 +%patch14 +%patch15 +%patch16 +%patch17 +%patch18 +%patch19 +%patch20 +%patch21 +%patch22 +%patch23 +%patch24 +%patch25 +%patch26 +%patch27 +%patch28 +%patch29 +%patch30 -p1 +%patch31 +%patch32 -p1 +%patch33 -p1 +%patch34 + +%build +%global _lto_cflags %{_lto_cflags} -ffat-lto-objects +# Makefile is not parallel-safe +make linux CC="cc" + +%install +install -d -m 755 %{buildroot}%{_includedir} +install -d -m 755 %{buildroot}%{_libdir} +install -d -m 755 %{buildroot}%{_sbindir} +install -d -m 755 %{buildroot}%{_mandir}/man{1,3,5,8} +install -m 644 ip6utils.h tcpd.h %{buildroot}%{_includedir} +install -m 644 libwrap.a %{buildroot}/%{_libdir} +install -m 755 safe_finger tcpd tcpdchk tcpdmatch try-from %{buildroot}%{_sbindir} +install -m 644 hosts_access.3 %{buildroot}%{_mandir}/man3 +install -m 644 hosts_access.5 hosts_options.5 %{buildroot}%{_mandir}/man5 +install -m 644 tcpd.8 tcpdchk.8 tcpdmatch.8 %{buildroot}%{_mandir}/man8 +install -m 644 shared/libwrap.so.0.%{version} %{buildroot}/%{_libdir} +ln -sf libwrap.so.0.%{version} %{buildroot}/%{_libdir}/libwrap.so.0 +ln -sf libwrap.so.0.%{version} %{buildroot}/%{_libdir}/libwrap.so +mkdir -p %{buildroot}%{_sysconfdir} +for i in hosts.allow hosts.deny; do + install $RPM_SOURCE_DIR/$i %{buildroot}/%{_sysconfdir} +done + +%post -n %{lname} -p /sbin/ldconfig + +%postun -n %{lname} -p /sbin/ldconfig + +%files +%defattr(644,root,root,755) +%doc BLURB CHANGES DISCLAIMER README README.ipv6 README.NIS +%doc %{_mandir}/man?/* +%attr(755,root,root) %{_sbindir}/* + +%files -n %{lname} +%defattr(-,root,root) +%doc DISCLAIMER +%attr(755,root,root) %{_libdir}/libwrap.so.0* +%verify(not md5 size mtime) %config(noreplace) %{_sysconfdir}/hosts.allow +%verify(not md5 size mtime) %config(noreplace) %{_sysconfdir}/hosts.deny + +%files devel +%defattr(644,root,root,755) +%{_includedir}/tcpd.h +%{_includedir}/ip6utils.h +%{_libdir}/libwrap.a +%{_libdir}/libwrap.so + +%changelog