diff -urN ftpd.ORI/Makefile ftpd/Makefile --- ftpd.ORI/Makefile Sun Jan 26 22:02:56 2003 +++ ftpd/Makefile Wed Nov 26 02:04:56 2003 @@ -5,14 +5,14 @@ MAN= ftpd.8 ftpchroot.5 SRCS= ftpd.c ftpcmd.y logwtmp.c popen.c -CFLAGS+=-DSETPROCTITLE -DLOGIN_CAP -DVIRTUAL_HOSTING +CFLAGS+=-DSETPROCTITLE -DLOGIN_CAP -DVIRTUAL_HOSTING -DTCPWRAPPERS CFLAGS+=-DINET6 CFLAGS+=-I${.CURDIR} YFLAGS= WFORMAT=0 -DPADD= ${LIBMD} ${LIBCRYPT} ${LIBUTIL} -LDADD= -lmd -lcrypt -lutil +DPADD= ${LIBMD} ${LIBCRYPT} ${LIBUTIL} ${LIBWRAP} +LDADD= -lmd -lcrypt -lutil -lwrap # XXX Kluge! Conversation mechanism needs to be fixed. DPADD+= ${LIBOPIE} diff -urN ftpd.ORI/ftpcmd.y ftpd/ftpcmd.y --- ftpd.ORI/ftpcmd.y Sun Oct 26 07:30:05 2003 +++ ftpd/ftpcmd.y Wed Nov 26 02:07:25 2003 @@ -80,7 +80,7 @@ extern struct passwd *pw; extern int guest; extern char *homedir; -extern int paranoid; +extern int ftpdparanoid; extern int logging; extern int type; extern int form; @@ -1630,7 +1630,7 @@ reply(500, "Invalid address rejected."); return 1; } - if (paranoid && + if (ftpdparanoid && ((ntohs(data_dest.su_port) < IPPORT_RESERVED) || memcmp(&data_dest.su_sin.sin_addr, &his_addr.su_sin.sin_addr, @@ -1757,7 +1757,7 @@ reply(500, "Invalid address rejected."); return 1; } - if (paranoid && + if (ftpdparanoid && ((ntohs(data_dest.su_port) < IPPORT_RESERVED) || memcmp(&data_dest.su_sin6.sin6_addr, &his_addr.su_sin6.sin6_addr, diff -urN ftpd.ORI/ftpd.c ftpd/ftpd.c --- ftpd.ORI/ftpd.c Sat Nov 15 14:08:26 2003 +++ ftpd/ftpd.c Wed Nov 26 02:09:43 2003 @@ -95,6 +95,10 @@ #include #endif +#ifdef TCPWRAPPERS +#include +#endif /* TCPWRAPPERS */ + #include "pathnames.h" #include "extern.h" @@ -124,7 +128,7 @@ int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ int logging; int restricted_data_ports = 1; -int paranoid = 1; /* be extra careful about security */ +int ftpdparanoid = 1; /* be extra careful about security */ int anon_only = 0; /* Only anonymous ftp allowed */ int guest; int dochroot; @@ -186,6 +190,12 @@ static char opieprompt[OPIE_CHALLENGE_MAX+1]; static int pwok; +#ifdef TCPWRAPPERS +static int check_host(struct sockaddr *); +int allow_severity = LOG_INFO; +int deny_severity = LOG_NOTICE; +#endif /* TCPWRAPPERS */ + char *pid_file = NULL; /* @@ -367,7 +377,7 @@ break; case 'R': - paranoid = 0; + ftpdparanoid = 0; break; case 'S': @@ -580,6 +590,16 @@ syslog(LOG_ERR, "fcntl F_SETOWN: %m"); #endif dolog((struct sockaddr *)&his_addr); +#ifdef TCPWRAPPERS + /* If ftpd runs in daemon mode, this code is reachable only in the + * child process */ + if (daemon_mode) { + /* Use tcp_wrappers to filter incoming requests */ + if (!check_host((struct sockaddr *)&his_addr)) + exit(1); + } +#endif /* TCPWRAPPERS */ + /* * Set up default state */ @@ -3212,3 +3232,40 @@ } return(socks); } + +#ifdef TCPWRAPPERS +static int +check_host(struct sockaddr *sa) +{ + struct request_info req; + + int error_name, error_addr; + char sa_name[MAXHOSTNAMELEN], sa_addr[NI_MAXHOST]; + + error_name = getnameinfo(sa, sa->sa_len, + sa_name, sizeof(sa_name) - 1, NULL, 0, NI_NAMEREQD); + error_addr = getnameinfo(sa, sa->sa_len, + sa_addr, sizeof(sa_addr) - 1, NULL, 0, NI_NUMERICHOST); + + /* fill req struct with port name and fd number */ + if (!error_name) { + request_init(&req, RQ_DAEMON, "ftpd", RQ_CLIENT_NAME, sa_name, + RQ_CLIENT_ADDR, error_addr == 0 ? sa_addr : "", RQ_USER, + STRING_UNKNOWN, NULL); + } else { + request_init(&req, RQ_DAEMON, "ftpd", RQ_CLIENT_NAME, STRING_UNKNOWN, + RQ_CLIENT_ADDR, error_addr == 0 ? sa_addr : "", RQ_USER, + STRING_UNKNOWN, NULL); + } + + if (!hosts_access(&req)) { + syslog(LOG_NOTICE, "connection from %.256s rejected by tcp_wrappers", + eval_client(&req)); + return (0); + } + + syslog(LOG_INFO, "connection from %.256s granted by tcp_wrappers", + eval_client(&req)); + return (1); +} +#endif /* TCPWRAPPERS */