| diff -ruNp tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c |
| --- tcp_wrappers_7.6.orig/hosts_access.c 2006-03-01 19:25:45.000000000 +0100 |
| +++ tcp_wrappers_7.6/hosts_access.c 2006-03-01 19:23:58.000000000 +0100 |
| @@ -82,6 +82,9 @@ int hosts_access_verbose = 0; |
| */ |
| |
| int resident = (-1); /* -1, 0: unknown; +1: yes */ |
| +#ifdef ACLEXEC |
| +int aclexec_matched = 0; |
| +#endif |
| |
| /* Forward declarations. */ |
| |
| @@ -185,6 +188,12 @@ struct request_info *request; |
| if (sh_cmd) { |
| #ifdef PROCESS_OPTIONS |
| process_options(sh_cmd, request); |
| +# ifdef ACLEXEC |
| + if (aclexec_matched) { |
| + syslog(LOG_INFO, "aclexec returned %d", aclexec_matched); |
| + match = NO; |
| + } |
| +# endif |
| #else |
| char cmd[BUFSIZ]; |
| shell_cmd(percent_x(cmd, sizeof(cmd), sh_cmd, request)); |
| diff -ruNp tcp_wrappers_7.6.orig/options.c tcp_wrappers_7.6/options.c |
| --- tcp_wrappers_7.6.orig/options.c 1996-02-11 17:01:32.000000000 +0100 |
| +++ tcp_wrappers_7.6/options.c 2006-03-01 19:24:25.000000000 +0100 |
| @@ -47,6 +47,7 @@ static char sccsid[] = "@(#) options.c 1 |
| #include <ctype.h> |
| #include <setjmp.h> |
| #include <string.h> |
| +#include <sys/wait.h> |
| |
| #ifndef MAXPATHNAMELEN |
| #define MAXPATHNAMELEN BUFSIZ |
| @@ -76,6 +77,7 @@ static void group_option(); /* execute |
| static void umask_option(); /* execute "umask mask" option */ |
| static void linger_option(); /* execute "linger time" option */ |
| static void keepalive_option(); /* execute "keepalive" option */ |
| +static void aclexec_option(); /* execute "aclexec command" option */ |
| static void spawn_option(); /* execute "spawn command" option */ |
| static void twist_option(); /* execute "twist command" option */ |
| static void rfc931_option(); /* execute "rfc931" option */ |
| @@ -113,6 +115,9 @@ static struct option option_table[] = { |
| "umask", umask_option, NEED_ARG, |
| "linger", linger_option, NEED_ARG, |
| "keepalive", keepalive_option, 0, |
| +#ifdef ACLEXEC |
| + "aclexec", aclexec_option, NEED_ARG | EXPAND_ARG, |
| +#endif |
| "spawn", spawn_option, NEED_ARG | EXPAND_ARG, |
| "twist", twist_option, NEED_ARG | EXPAND_ARG | USE_LAST, |
| "rfc931", rfc931_option, OPT_ARG, |
| @@ -310,6 +315,54 @@ struct request_info *request; |
| shell_cmd(value); |
| } |
| |
| +#ifdef ACLEXEC |
| +/* aclexec_option - spawn a shell command and check status */ |
| + |
| +/* ARGSUSED */ |
| + |
| +static void aclexec_option(value, request) |
| +char *value; |
| +struct request_info *request; |
| +{ |
| + int status, child_pid, wait_pid; |
| + extern int aclexec_matched; |
| + |
| + if (dry_run != 0) |
| + return; |
| + |
| + child_pid = fork(); |
| + |
| + /* Something went wrong: we MUST terminate the process. */ |
| + if (child_pid < 0) { |
| + tcpd_warn("aclexec_option: /bin/sh: %m"); |
| + clean_exit(request); |
| + } |
| + |
| + if (child_pid == 0) { |
| + execl("/bin/sh", "sh", "-c", value, (char *) 0); |
| + |
| + /* Something went wrong. We MUST terminate the child process. */ |
| + tcpd_warn("execl /bin/sh: %m"); |
| + _exit(0); |
| + } |
| + |
| + while ((wait_pid = wait(&status)) != -1 && wait_pid != child_pid) |
| + /* void */ ; |
| + |
| + aclexec_matched = 1; |
| + |
| + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { |
| + aclexec_matched = 0; |
| + } |
| + |
| + if (WIFSIGNALED(status)) |
| + tcpd_warn("process %d exited with signal %d", child_pid, |
| + WTERMSIG(status)); |
| + |
| + return; |
| +} |
| +#endif |
| + |
| /* linger_option - set the socket linger time (Marc Boucher <marc@cam.org>) */ |
| |
| /* ARGSUSED */ |
| diff -ruNp tcp_wrappers_7.6.orig/hosts_options.5 tcp_wrappers_7.6/hosts_options.5 |
| --- tcp_wrappers_7.6.orig/hosts_options.5 2006-03-01 21:48:43.000000000 +0100 |
| +++ tcp_wrappers_7.6/hosts_options.5 2006-03-01 21:47:39.000000000 +0100 |
| @@ -52,6 +52,23 @@ ALL: ALL: ALLOW |
| .sp |
| Notice the leading dot on the domain name patterns. |
| .SH RUNNING OTHER COMMANDS |
| +.IP "aclexec shell_command" |
| +Execute, in a child process, the specified shell command, after |
| +performing the %<letter> expansions described in the hosts_access(5) |
| +manual page. The command is executed with stdin, stdout and stderr |
| +connected to the null device, so that it won't mess up the |
| +conversation with the client host. Example: |
| +.sp |
| +.nf |
| +.ti +3 |
| +smtp : ALL : aclexec checkdnsbl %a |
| +.fi |
| +.sp |
| +executes, in a background child process, the shell command "checkdnsbl %a" |
| +after replacing %a by the address of the remote host. |
| +.sp |
| +The connection will be allowed or refused depending on whether the |
| +command returns a true or false exit status. |
| .IP "spawn shell_command" |
| Execute, in a child process, the specified shell command, after |
| performing the %<letter> expansions described in the hosts_access(5) |