diff --git a/.github/workflows/c-cpp-Linux.yml b/.github/workflows/c-cpp-Linux.yml index 1551944..c906317 100644 --- a/.github/workflows/c-cpp-Linux.yml +++ b/.github/workflows/c-cpp-Linux.yml @@ -27,7 +27,7 @@ jobs: if: ${{ startsWith(matrix.target, 'ubuntu') }} run: sudo apt-get update && sudo apt-get install -y libssl-dev libpam-dev libpcre2-dev - name: make - run: make -f Makefile.Linux + run: make -f Makefile.Linux MAILPROXY=true FTP=true - name: regression tests run: python3 tests/run.py - name: mkdir diff --git a/CMakeLists.txt b/CMakeLists.txt index fed8642..f7d969c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,8 @@ option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON) option(3PROXY_USE_TRANSPARENT "Build transparent proxying support (Linux and BSD only)" ON) option(3PROXY_USE_UNIX_SOCKETS "Enable Unix domain socket support (Unix only)" ON) option(3PROXY_USE_HTTPSRV "Build the HTTP server and the admin interface on top of it" ON) +option(3PROXY_USE_MAILPROXY "Build the pop3p, imapp and smtpp proxies" OFF) +option(3PROXY_USE_FTP "Build FTP support: the ftppr service and ftp:// in the HTTP proxy" OFF) if(NOT WIN32 AND NOT APPLE) option(3PROXY_STATIC_LINK "Statically link libraries using -Wl,-Bstatic (Linux/Unix only)" OFF) @@ -83,10 +85,13 @@ set(3PROXY_BINARY_PREFIX "3proxy_" CACHE STRING "Prefix for standalone module an option(3PROXY_BUILD_NONE "Do not build standalone binaries" OFF) option(3PROXY_BUILD_PROXY "Build standalone proxy binary" ON) option(3PROXY_BUILD_SOCKS "Build standalone socks binary" ON) -option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" ON) -option(3PROXY_BUILD_IMAPP "Build standalone imapp binary" ON) -option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" ON) -option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" ON) +# The mail proxies and FTP are asked for rather than assumed: without them +# pop3p, imapp and smtpp are the STARTTLS proxy under those names, and ftp +# is not spoken at all. A standalone binary needs the support it is made of. +option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" OFF) +option(3PROXY_BUILD_IMAPP "Build standalone imapp binary" OFF) +option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" OFF) +option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" OFF) option(3PROXY_BUILD_TCPPM "Build standalone tcppm binary" ON) option(3PROXY_BUILD_UDPPM "Build standalone udppm binary" ON) option(3PROXY_BUILD_TLSPR "Build standalone tlspr binary" ON) @@ -250,6 +255,14 @@ else() ) endif() +if(3PROXY_USE_MAILPROXY) + add_compile_definitions(WITH_POP3P WITH_IMAPP WITH_SMTPP) +endif() + +if(3PROXY_USE_FTP) + add_compile_definitions(WITH_FTP) +endif() + if(3PROXY_USE_HTTPSRV) add_compile_definitions(WITH_HTTPSRV) endif() @@ -684,6 +697,15 @@ foreach(PROXY_NAME proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr) continue() endif() + # A binary of nothing: without the support built, these files hold the + # stand-in the main binary uses and no service of their own. + if(NOT 3PROXY_USE_MAILPROXY AND PROXY_NAME MATCHES "^(pop3p|imapp|smtpp)$") + continue() + endif() + if(NOT 3PROXY_USE_FTP AND PROXY_NAME STREQUAL "ftppr") + continue() + endif() + if(PROXY_NAME STREQUAL "ftppr" OR PROXY_NAME STREQUAL "proxy") # ftppr and proxy use ftp_obj add_executable(${PROXY_NAME} diff --git a/Makefile.FreeBSD b/Makefile.FreeBSD index 7865d04..eddce71 100644 --- a/Makefile.FreeBSD +++ b/Makefile.FreeBSD @@ -24,6 +24,16 @@ LDFLAGS += $(EXTRA_LDFLAGS) # -lpthreads may be reuiured on some platforms instead of -pthreads # -ldl or -lld may be required for some platforms DCFLAGS ?= -fPIC +MAILPROXY ?= false +ifeq ($(MAILPROXY),true) + CFLAGS += -DWITH_POP3P -DWITH_IMAPP -DWITH_SMTPP + MAIL_EXES = $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) +endif +FTP ?= false +ifeq ($(FTP),true) + CFLAGS += -DWITH_FTP + FTP_EXES = $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) +endif HTTPSRV ?= true ifeq ($(HTTPSRV),true) CFLAGS += -DWITH_HTTPSRV diff --git a/Makefile.Linux b/Makefile.Linux index 48b48d8..94479e5 100644 --- a/Makefile.Linux +++ b/Makefile.Linux @@ -27,6 +27,16 @@ CFLAGS += $(EXTRA_CFLAGS) LDFLAGS += $(EXTRA_LDFLAGS) # The HTTP server serves the endpoints declared by http lines. The admin # interface is built on top of it, so turning it off removes both. +MAILPROXY ?= false +ifeq ($(MAILPROXY),true) + CFLAGS += -DWITH_POP3P -DWITH_IMAPP -DWITH_SMTPP + MAIL_EXES = $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) +endif +FTP ?= false +ifeq ($(FTP),true) + CFLAGS += -DWITH_FTP + FTP_EXES = $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) +endif HTTPSRV ?= true ifeq ($(HTTPSRV),true) CFLAGS += -DWITH_HTTPSRV diff --git a/Makefile.Solaris b/Makefile.Solaris index f5c2537..8595400 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -14,6 +14,16 @@ COUT = -o ./ LN = $(CC) LDFLAGS = -xO3 DCFLAGS = -fPIC +MAILPROXY ?= false +ifeq ($(MAILPROXY),true) + CFLAGS += -DWITH_POP3P -DWITH_IMAPP -DWITH_SMTPP + MAIL_EXES = $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) +endif +FTP ?= false +ifeq ($(FTP),true) + CFLAGS += -DWITH_FTP + FTP_EXES = $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) +endif HTTPSRV ?= true ifeq ($(HTTPSRV),true) CFLAGS += -DWITH_HTTPSRV diff --git a/Makefile.unix b/Makefile.unix index ec71ad5..96ffe0e 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -26,6 +26,16 @@ LDFLAGS += $(EXTRA_LDFLAGS) # -lpthreads may be reuqired on some platforms instead of -pthreads # -ldl or -lld may be required for some platforms DCFLAGS ?= -fPIC +MAILPROXY ?= false +ifeq ($(MAILPROXY),true) + CFLAGS += -DWITH_POP3P -DWITH_IMAPP -DWITH_SMTPP + MAIL_EXES = $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) +endif +FTP ?= false +ifeq ($(FTP),true) + CFLAGS += -DWITH_FTP + FTP_EXES = $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) +endif HTTPSRV ?= true ifeq ($(HTTPSRV),true) CFLAGS += -DWITH_HTTPSRV diff --git a/Makefile.win b/Makefile.win index 9d7a2dd..77304bf 100644 --- a/Makefile.win +++ b/Makefile.win @@ -23,6 +23,16 @@ LDFLAGS += -fno-strict-aliasing -mthreads # makefile, including the += above and the STATIC/LIBSTATIC handling below. CFLAGS += $(EXTRA_CFLAGS) LDFLAGS += $(EXTRA_LDFLAGS) +MAILPROXY ?= false +ifeq ($(MAILPROXY),true) + CFLAGS += -DWITH_POP3P -DWITH_IMAPP -DWITH_SMTPP + MAIL_EXES = $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) +endif +FTP ?= false +ifeq ($(FTP),true) + CFLAGS += -DWITH_FTP + FTP_EXES = $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) +endif HTTPSRV ?= true ifeq ($(HTTPSRV),true) CFLAGS += -DWITH_HTTPSRV diff --git a/man/3proxy.cfg.5 b/man/3proxy.cfg.5 index 2b22cb7..950ba4c 100644 --- a/man/3proxy.cfg.5 +++ b/man/3proxy.cfg.5 @@ -95,16 +95,19 @@ SNI proxy (destination address is taken from TLS handshake), may be used to redi Proxy with protocol autoselection between proxy / socks / tlspr .br .B pop3p -POP3 proxy (default port 110) +POP3 proxy (default port 110), in a build which has one: otherwise the +service is \fBtlspr\fR speaking POP3 to negotiate STARTTLS, under this name. .br .B imapp -IMAPv4 proxy (default port 143) +IMAPv4 proxy (default port 143), or \fBtlspr\fR speaking IMAP, as above. .br .B smtpp -SMTP proxy (default port 25) +SMTP proxy (default port 25), or \fBtlspr\fR speaking SMTP, as above. .br .B ftppr -FTP proxy (default port 21) +FTP proxy (default port 21), in a build with FTP support. Without it the +service is known but answers nothing, and \fBftp://\fR is not a URL the HTTP +proxy fetches. .br .B admin Web interface (default port 80) @@ -1573,6 +1576,21 @@ matched if the ACL matches the connection data. Warning: Regular expressions don't require authentication and cannot replace authentication and/or allow/deny ACLs. +.SH OPTIONAL SERVICES +The mail proxies and FTP are built when they are asked for, and are not in a +default build. \fBMAILPROXY=true\fR builds \fBpop3p\fR, \fBimapp\fR and +\fBsmtpp\fR, and \fBFTP=true\fR builds \fBftppr\fR and the \fBftp://\fR +scheme of the HTTP proxy; with CMake the switches are +\fB-D3PROXY_USE_MAILPROXY=ON\fR and \fB-D3PROXY_USE_FTP=ON\fR. The standalone +binaries of those services are built with them and not without. +.br + A configuration naming a service which was not built is still read. The three +mail proxies become \fBtlspr\fR negotiating STARTTLS in that protocol, which +is what most of their use amounts to now that the mail protocols are used over +TLS, and a \fBparent\fR chain naming \fBpop3\fR, \fBimap\fR or \fBsmtp\fR +does the same. \fBftppr\fR is answered by nothing: a client reaching it is +turned away and the refusal logged, since there is no protocol to fall back on. + .SH BUILT IN HTTP SERVER The \fBhttpsrv\fR service answers requests itself instead of forwarding them. What it does with a request is decided by \fBhttp\fR rules, which are taken in diff --git a/src/Makefile.inc b/src/Makefile.inc index b2c04ce..1cb5a40 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -2,7 +2,7 @@ # 3 proxy common Makefile # -all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins +all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(MAIL_EXES) $(FTP_EXES) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h $(CC) $(CFLAGS) sockmap.c diff --git a/src/ftp.c b/src/ftp.c index a2c71a2..94cda64 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -7,6 +7,8 @@ #include "proxy.h" +#ifdef WITH_FTP + /* * Read one FTP server response, skipping continuation lines (lines whose * 4th character is '-' per RFC 959). Returns the line length on success, @@ -249,3 +251,5 @@ SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned c } return s; } + +#endif diff --git a/src/ftppr.c b/src/ftppr.c index 049bc93..abe1006 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -8,6 +8,8 @@ #include "proxy.h" +#ifdef WITH_FTP + #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define BUFSIZE 2048 @@ -345,3 +347,16 @@ struct proxydef childdef = { }; #include "proxymain.c" #endif + +#else + +/* Built without FTP support. The service and the redirect naming it are + still known, so a configuration carrying them is read rather than + refused, and a client reaching one is turned away. */ +void * ftpprchild(struct clientparam * param){ + param->res = 878; + dolog(param, (unsigned char *)"ftp support is not built in"); + return NULL; +} + +#endif diff --git a/src/imapp.c b/src/imapp.c index 2d1e0db..c3f3b0d 100644 --- a/src/imapp.c +++ b/src/imapp.c @@ -8,6 +8,8 @@ #include "proxy.h" +#ifdef WITH_IMAPP + #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define CL_LOGINCMD 0 @@ -250,3 +252,15 @@ struct proxydef childdef = { }; #include "proxymain.c" #endif +#else + +/* Built without this proxy of its own. The command and the redirect + naming it are the STARTTLS proxy speaking that protocol, which + negotiates the same way and passes the session on: what "tlspr -Ximap" + does, under the name a configuration already uses. */ +void * imappchild(struct clientparam * param){ + param->starttls = S_IMAPP; + return (void *)tlsprchild; +} + +#endif diff --git a/src/pop3p.c b/src/pop3p.c index 9bc1333..ccd3a08 100644 --- a/src/pop3p.c +++ b/src/pop3p.c @@ -8,6 +8,8 @@ #include "proxy.h" +#ifdef WITH_POP3P + #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #ifdef WITHMAIN @@ -88,3 +90,15 @@ struct proxydef childdef = { }; #include "proxymain.c" #endif +#else + +/* Built without this proxy of its own. The command and the redirect + naming it are the STARTTLS proxy speaking that protocol, which + negotiates the same way and passes the session on: what "tlspr -Xpop3" + does, under the name a configuration already uses. */ +void * pop3pchild(struct clientparam * param){ + param->starttls = S_POP3P; + return (void *)tlsprchild; +} + +#endif diff --git a/src/proxy.c b/src/proxy.c index a52d972..811f0af 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -385,10 +385,12 @@ for(;;){ if (!strncasecmp((char *)sb, "http://", 7)) { sb += 7; } +#ifdef WITH_FTP else if (!strncasecmp((char *)sb, "ftp://", 6)) { ftp = 1; sb += 6; } +#endif else if(*sb == '/') { param->transparent = 1; } @@ -712,6 +714,7 @@ for(;;){ #endif +#ifdef WITH_FTP if(ftp && param->redirtype != R_HTTP){ SOCKET s; int mode = 0; @@ -963,6 +966,7 @@ for(;;){ } RETURN(res); } +#endif if(isconnect && param->redirtype != R_HTTP) { if(param->redirectfunc) { diff --git a/src/smtpp.c b/src/smtpp.c index 3905bf0..6bde921 100644 --- a/src/smtpp.c +++ b/src/smtpp.c @@ -8,6 +8,8 @@ #include "proxy.h" +#ifdef WITH_SMTPP + #define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #ifdef WITHMAIN @@ -342,3 +344,15 @@ struct proxydef childdef = { }; #include "proxymain.c" #endif +#else + +/* Built without this proxy of its own. The command and the redirect + naming it are the STARTTLS proxy speaking that protocol, which + negotiates the same way and passes the session on: what "tlspr -Xsmtp" + does, under the name a configuration already uses. */ +void * smtppchild(struct clientparam * param){ + param->starttls = S_SMTPP; + return (void *)tlsprchild; +} + +#endif diff --git a/src/structures.h b/src/structures.h index f7a9d42..459a6a5 100644 --- a/src/structures.h +++ b/src/structures.h @@ -759,6 +759,10 @@ struct clientparam { that a plugin built against an older header still finds the fields it knows where they were. */ int onerequest; + /* A STARTTLS protocol to speak before the session is wrapped, set for + one connection rather than for the service, which is how a redirect + and a service name standing in for a mail proxy reach tlspr. */ + PROXYSERVICE starttls; }; struct filemon { diff --git a/src/tlspr.c b/src/tlspr.c index 44f51c7..c6c343e 100644 --- a/src/tlspr.c +++ b/src/tlspr.c @@ -334,7 +334,8 @@ void * tlsprchild(struct clientparam* param) { int lv=-1; char proto[PROTOLEN]="-"; int snipos = 0; - PROXYSERVICE stlsproto = param->clientstarttls? param->clientstarttls : param->srv->srvstarttls; + PROXYSERVICE stlsproto = param->clientstarttls? param->clientstarttls : + (param->starttls? param->starttls : param->srv->srvstarttls); if(!param->clientstarttls && stlsproto){ res = clistarttls(param, stlsproto);