From 8107f03062651dfea260ce2888fda2671e6652a2 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Fri, 1 May 2026 15:11:08 +0300 Subject: [PATCH] Move PCRE/SSL to main code --- .gitignore | 1 + CMakeLists.txt | 111 ++++-- Makefile.FreeBSD | 7 +- Makefile.Linux | 9 +- Makefile.Solaris | 15 +- Makefile.msvc | 14 +- Makefile.unix | 9 +- Makefile.watcom | 2 + Makefile.win | 7 +- doc/html/howtoe.html | 78 ++++- doc/html/howtor.html | 79 ++++- doc/html/man5/3proxy.cfg.5.html | 222 ++++++++++++ doc/html/plugins/PCREPlugin.html | 17 +- doc/html/plugins/PCREPlugin.ru.html | 21 +- doc/html/plugins/SSLPlugin.html | 14 +- doc/html/plugins/SSLPlugin.ru.html | 13 +- man/3proxy.cfg.5 | 199 ++++++++++- src/3proxy.c | 13 + src/3proxy_crypt.c | 126 +++++-- src/Makefile.inc | 34 +- src/auth.c | 2 + src/authradius.c | 17 +- src/blake2_compat.h | 76 ++++ src/conf.c | 26 ++ src/hashtables.c | 20 +- src/libs/md4.c | 290 ---------------- src/libs/md4.h | 83 ----- src/libs/md5.c | 325 ------------------ src/libs/md5.h | 94 ----- .../PCREPlugin/pcre_plugin.c => pcre.c} | 19 +- src/pcre.h | 6 + src/plugins/PCREPlugin/CMakeLists.txt | 20 -- src/plugins/PCREPlugin/Makefile | 1 - src/plugins/PCREPlugin/Makefile.inc | 8 - src/plugins/SSLPlugin/CMakeLists.txt | 17 - src/plugins/SSLPlugin/Makefile | 1 - src/plugins/SSLPlugin/Makefile.inc | 14 - src/proxy.h | 9 + src/{plugins/SSLPlugin/ssl_plugin.c => ssl.c} | 84 ++--- src/{plugins/SSLPlugin/my_ssl.h => ssl.h} | 18 +- src/{plugins/SSLPlugin/my_ssl.c => ssllib.c} | 84 +++-- src/structures.h | 4 + 42 files changed, 1088 insertions(+), 1121 deletions(-) create mode 100644 src/blake2_compat.h delete mode 100644 src/libs/md4.c delete mode 100644 src/libs/md4.h delete mode 100644 src/libs/md5.c delete mode 100644 src/libs/md5.h rename src/{plugins/PCREPlugin/pcre_plugin.c => pcre.c} (97%) create mode 100644 src/pcre.h delete mode 100644 src/plugins/PCREPlugin/CMakeLists.txt delete mode 100644 src/plugins/PCREPlugin/Makefile delete mode 100644 src/plugins/PCREPlugin/Makefile.inc delete mode 100644 src/plugins/SSLPlugin/CMakeLists.txt delete mode 100644 src/plugins/SSLPlugin/Makefile delete mode 100644 src/plugins/SSLPlugin/Makefile.inc rename src/{plugins/SSLPlugin/ssl_plugin.c => ssl.c} (96%) rename src/{plugins/SSLPlugin/my_ssl.h => ssl.h} (89%) rename src/{plugins/SSLPlugin/my_ssl.c => ssllib.c} (86%) diff --git a/.gitignore b/.gitignore index 1bc2154..5f4b1c0 100644 --- a/.gitignore +++ b/.gitignore @@ -267,3 +267,4 @@ bin/3proxy_socks bin/3proxy_tcppm bin/3proxy_tlspr bin/3proxy_udppm +build*/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9428120..f8150be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,6 @@ if(WIN32) # MSVC-specific settings add_compile_definitions( MSVC - WITH_SSL ) # Use static runtime library set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") @@ -123,7 +122,6 @@ if(WIN32) # clang-cl (Clang with MSVC frontend) add_compile_definitions( MSVC - WITH_SSL ) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") add_compile_options( @@ -254,14 +252,14 @@ endif() # OpenSSL set(OPENSSL_FOUND FALSE) if(3PROXY_USE_OPENSSL) - find_package(OpenSSL QUIET) + find_package(OpenSSL REQUIRED) if(OpenSSL_FOUND) set(OPENSSL_FOUND TRUE) add_compile_definitions(WITH_SSL) message(STATUS "OpenSSL found: ${OPENSSL_VERSION}") - else() - message(STATUS "OpenSSL not found, SSLPlugin will not be built") endif() +else() + message(STATUS "OpenSSL disabled by user request") endif() # PCRE2 @@ -269,9 +267,10 @@ set(PCRE2_FOUND FALSE) if(3PROXY_USE_PCRE2) find_package(PCRE2 QUIET) if(PCRE2_FOUND) + add_compile_definitions(WITH_PCRE) message(STATUS "PCRE2 found: ${PCRE2_VERSION}") else() - message(STATUS "PCRE2 not found, PCREPlugin will not be built") + message(STATUS "PCRE2 not found, PCRE support will not be built") endif() endif() @@ -302,6 +301,11 @@ if(NOT ODBC_FOUND) add_compile_definitions(NOODBC) endif() +# Set NORADIUS if OpenSSL is not available (RADIUS requires MD5 from OpenSSL) +if(NOT OPENSSL_FOUND) + add_compile_definitions(NORADIUS) +endif() + # Source files for 3proxy core set(3PROXY_CORE_SOURCES src/3proxy.c @@ -320,10 +324,8 @@ set(3PROXY_CORE_SOURCES src/stringtable.c ) -# MD4/MD5/BLAKE2 sources for 3proxy_crypt +# BLAKE2 source for 3proxy_crypt set(MD_SOURCES - src/libs/md4.c - src/libs/md5.c src/libs/blake2b-ref.c ) @@ -372,6 +374,10 @@ target_include_directories(srvudppm_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# UDP socket relay (used by 3proxy, socks, udppm) +add_library(udpsockmap_obj OBJECT src/udpsockmap.c) +target_include_directories(udpsockmap_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) + # mainfunc object (proxymain.c compiled with MODULEMAINFUNC=mainfunc for 3proxy) add_library(mainfunc OBJECT src/proxymain.c) target_include_directories(mainfunc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) @@ -384,6 +390,9 @@ target_include_directories(ftp_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # 3proxy_crypt object for 3proxy (without WITHMAIN) add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c) target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +if(OpenSSL_FOUND) + target_include_directories(3proxy_crypt_obj PRIVATE ${OPENSSL_INCLUDE_DIR}) +endif() # ============================================================================ # Main 3proxy executable @@ -397,15 +406,30 @@ add_executable(3proxy $ $ $ + $ $ $ $ ) +if(OpenSSL_FOUND) + target_sources(3proxy PRIVATE src/ssllib.c src/ssl.c) +endif() + +if(PCRE2_FOUND) + target_sources(3proxy PRIVATE src/pcre.c) +endif() + target_include_directories(3proxy PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/libs ) +if(OpenSSL_FOUND) + target_include_directories(3proxy PRIVATE ${OPENSSL_INCLUDE_DIR}) +endif() +if(PCRE2_FOUND) + target_include_directories(3proxy PRIVATE ${PCRE2_INCLUDE_DIRS}) +endif() target_link_libraries(3proxy PRIVATE Threads::Threads) @@ -417,19 +441,52 @@ if(ODBC_FOUND) endif() endif() +if(OpenSSL_FOUND) + target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) +endif() + +# PCRE2 linking (try static first on Linux/FreeBSD, fallback to dynamic) +if(PCRE2_FOUND) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR + CMAKE_SYSTEM_NAME MATCHES "FreeBSD|OpenBSD|NetBSD" OR + CMAKE_SYSTEM_NAME STREQUAL "Unix") + # Try static linking for Linux/BSD + find_library(PCRE2_STATIC_LIB + NAMES pcre2-8-static libpcre2-8.a pcre2-8.a + PATHS ${PC_PCRE2_LIBRARY_DIRS} + /usr/lib/x86_64-linux-gnu + /usr/lib + /usr/local/lib + /lib + ) + if(PCRE2_STATIC_LIB AND PCRE2_STATIC_LIB MATCHES "\\.a$") + target_link_libraries(3proxy PRIVATE + -Wl,-Bstatic + ${PCRE2_STATIC_LIB} + -Wl,-Bdynamic + ) + message(STATUS "Using static PCRE2: ${PCRE2_STATIC_LIB}") + elseif(TARGET PCRE2::PCRE2) + target_link_libraries(3proxy PRIVATE PCRE2::PCRE2) + message(STATUS "Using dynamic PCRE2 (PCRE2::PCRE2)") + else() + target_link_libraries(3proxy PRIVATE ${PCRE2_LIBRARIES}) + message(STATUS "Using dynamic PCRE2: ${PCRE2_LIBRARIES}") + endif() + elseif(TARGET PCRE2::PCRE2) + target_link_libraries(3proxy PRIVATE PCRE2::PCRE2) + else() + target_link_libraries(3proxy PRIVATE ${PCRE2_LIBRARIES}) + endif() +endif() + if(WIN32) target_link_libraries(3proxy PRIVATE ${WINDOWS_LIBS}) - if(OpenSSL_FOUND) - target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) - endif() if(COMPILER_IS_MSVC AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3proxy.rc) target_sources(3proxy PRIVATE 3proxy.rc) endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(3proxy PRIVATE dl) - if(OpenSSL_FOUND) - target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) - endif() endif() # Build 3proxy_crypt utility @@ -443,7 +500,13 @@ target_include_directories(3proxy_crypt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/libs ) +if(OpenSSL_FOUND) + target_include_directories(3proxy_crypt PRIVATE ${OPENSSL_INCLUDE_DIR}) +endif() target_link_libraries(3proxy_crypt PRIVATE Threads::Threads) +if(OpenSSL_FOUND) + target_link_libraries(3proxy_crypt PRIVATE OpenSSL::SSL OpenSSL::Crypto) +endif() if("${3PROXY_BINARY_PREFIX}" STREQUAL "") set_target_properties(3proxy_crypt PROPERTIES OUTPUT_NAME "mycrypt") else() @@ -509,6 +572,10 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr) if(PROXY_NAME STREQUAL "udppm") target_sources(${PROXY_NAME} PRIVATE src/hash.c) endif() + + if(PROXY_NAME STREQUAL "socks" OR PROXY_NAME STREQUAL "udppm") + target_sources(${PROXY_NAME} PRIVATE src/udpsockmap.c) + endif() endforeach() # Plugin output directory @@ -527,26 +594,12 @@ foreach(PLUGIN ${DEFAULT_PLUGINS}) add_subdirectory(src/plugins/${PLUGIN}) endforeach() -if(OPENSSL_FOUND) - add_subdirectory(src/plugins/SSLPlugin) -endif() - -if(PCRE2_FOUND) - add_subdirectory(src/plugins/PCREPlugin) -endif() - if(PAM_FOUND) add_subdirectory(src/plugins/PamAuth) endif() # Build full list of plugins to be built set(ALL_PLUGINS ${DEFAULT_PLUGINS}) -if(OPENSSL_FOUND) - list(APPEND ALL_PLUGINS SSLPlugin) -endif() -if(PCRE2_FOUND) - list(APPEND ALL_PLUGINS PCREPlugin) -endif() if(PAM_FOUND) list(APPEND ALL_PLUGINS PamAuth) endif() diff --git a/Makefile.FreeBSD b/Makefile.FreeBSD index ce07b2f..fa122c0 100644 --- a/Makefile.FreeBSD +++ b/Makefile.FreeBSD @@ -36,11 +36,14 @@ PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin OPENSSL_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(OPENSSL_CHECK), true) LIBS += -l crypto -l ssl - PLUGINS += SSLPlugin + CFLAGS += -DWITH_SSL + SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) endif PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) ifeq ($(PCRE_CHECK), true) - PLUGINS += PCREPlugin + CFLAGS += -DWITH_PCRE + PCRE_OBJS = pcre$(OBJSUFFICS) + PCRE_LIBS = -lpcre2-8 endif PAM_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) ifeq ($(PAM_CHECK), true) diff --git a/Makefile.Linux b/Makefile.Linux index 713830a..64e976a 100644 --- a/Makefile.Linux +++ b/Makefile.Linux @@ -38,11 +38,14 @@ PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin OPENSSL_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(OPENSSL_CHECK), true) LIBS += -l crypto -l ssl - PLUGINS += SSLPlugin + CFLAGS += -DWITH_SSL + SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) endif -PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) +PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) ifeq ($(PCRE_CHECK), true) - PLUGINS += PCREPlugin + CFLAGS += -DWITH_PCRE + PCRE_OBJS = pcre$(OBJSUFFICS) + PCRE_LIBS = -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic endif PAM_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) ifeq ($(PAM_CHECK), true) diff --git a/Makefile.Solaris b/Makefile.Solaris index e75658c..c58b072 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -27,7 +27,20 @@ AFTERCLEAN = (find . -type f -name "*.o" -delete && find src/ -type f -name "Mak TYPECOMMAND = cat COMPATLIBS = MAKEFILE = Makefile.Solaris -PLUGINS = StringsPlugin TrafficPlugin +PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin + +OPENSSL_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) +ifeq ($(OPENSSL_CHECK), true) + LIBS += -l crypto -l ssl + CFLAGS += -DWITH_SSL + SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) +endif +PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) +ifeq ($(PCRE_CHECK), true) + CFLAGS += -DWITH_PCRE + PCRE_OBJS = pcre$(OBJSUFFICS) + PCRE_LIBS = -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic +endif include Makefile.inc diff --git a/Makefile.msvc b/Makefile.msvc index 9651bb5..031af74 100644 --- a/Makefile.msvc +++ b/Makefile.msvc @@ -8,26 +8,28 @@ BUILDDIR = ../bin/ CC = cl VERSION = $(VERSION) BUILDDATE = $(BUILDDATE) -CFLAGS = /nologo /MT /W3 /Ox /GS /EHs- /GA /GF /D "MSVC" /D "WITH_WSAPOLL" /D "NDEBUG" /D "WIN32" /D "WITH_SSL" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION) +CFLAGS = /nologo /MT /W3 /Ox /GS /EHs- /GA /GF /D "MSVC" /D "WITH_WSAPOLL" /D "NDEBUG" /D "WIN32" /D "WITH_SSL" /D "WITH_PCRE" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION) COUT = /Fo LN = link LDFLAGS = /nologo /subsystem:console /incremental:no DLFLAGS = /DLL DLSUFFICS = .dll -LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib libcrypto.lib libssl.lib -LIBSPREFIX = +LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib libcrypto.lib libssl.lib pcre2-8.lib +LIBSPREFIX = LIBSSUFFIX = .lib -LIBEXT = .lib +LIBEXT = .lib LNOUT = /out: EXESUFFICS = .exe OBJSUFFICS = .obj -DEFINEOPTION = /D +DEFINEOPTION = /D COMPFILES = *.pch *.idb REMOVECOMMAND = del TYPECOMMAND = type COMPATLIBS = MAKEFILE = Makefile.msvc -PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin FilePlugin SSLPlugin PCREPlugin +PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin FilePlugin +SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) +PCRE_OBJS = pcre$(OBJSUFFICS) VERFILE = 3proxy.res $(VERFILE) VERSIONDEP = 3proxy.res $(VERSIONDEP) AFTERCLEAN = if exist src\*.res (del src\*.res) && if exist src\*.err (del src\*.err) diff --git a/Makefile.unix b/Makefile.unix index f386a5d..9a9c664 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -38,11 +38,14 @@ PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin OPENSSL_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(OPENSSL_CHECK), true) LIBS += -l crypto -l ssl - PLUGINS += SSLPlugin + CFLAGS += -DWITH_SSL + SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) endif -PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) +PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) ifeq ($(PCRE_CHECK), true) - PLUGINS += PCREPlugin + CFLAGS += -DWITH_PCRE + PCRE_OBJS = pcre$(OBJSUFFICS) + PCRE_LIBS = -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic endif PAM_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) ifeq ($(PAM_CHECK), true) diff --git a/Makefile.watcom b/Makefile.watcom index 5df122e..ee6908c 100644 --- a/Makefile.watcom +++ b/Makefile.watcom @@ -27,6 +27,8 @@ TYPECOMMAND = type COMPATLIBS = MAKEFILE = Makefile.watcom PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin +SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) +PCRE_OBJS = pcre$(OBJSUFFICS) VERFILE = $(VERFILE) VERSION = $(VERSION) VERSIONDEP = 3proxy.res $(VERSIONDEP) diff --git a/Makefile.win b/Makefile.win index 835d4bc..486e41d 100644 --- a/Makefile.win +++ b/Makefile.win @@ -37,7 +37,8 @@ ifndef OPENSSL_CHECK OPENSSL_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l crypto -l ssl -o testssl - 2>/dev/null && rm testssl && echo true||echo false) ifeq ($(OPENSSL_CHECK), true) LIBS += -l crypto -l ssl - PLUGINS += SSLPlugin + CFLAGS += -DWITH_SSL + SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) endif PAM_CHECK = $(shell echo "\#include \\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false) ifeq ($(PAM_CHECK), true) @@ -45,7 +46,9 @@ ifeq ($(PAM_CHECK), true) endif PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include \\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -lpcre2-8 -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false) ifeq ($(PCRE_CHECK), true) - PLUGINS += PCREPlugin + CFLAGS += -DWITH_PCRE + PCRE_OBJS = pcre$(OBJSUFFICS) + PCRE_LIBS = -lpcre2-8 endif endif diff --git a/doc/html/howtoe.html b/doc/html/howtoe.html index de6d6c3..dc7f585 100644 --- a/doc/html/howtoe.html +++ b/doc/html/howtoe.html @@ -33,8 +33,9 @@
  • How to resolve names through a parent proxy
  • How to set up an FTP proxy
  • How to set up an SNI proxy (tlspr)
  • -
  • How to set up TLS/SSL with SSLPlugin (https proxy, mTLS)
  • -
  • How to create CA and certificates for SSLPlugin
  • +
  • How to set up TLS/SSL (https proxy, mTLS)
  • +
  • How to create CA and certificates for SSL
  • +
  • How to use PCRE filtering (regular expressions)
  • How to limit service access
  • How to create a user list
  • How to limit user access to resources @@ -639,9 +640,12 @@ allow * proxy

    -
  • How to set up TLS/SSL with SSLPlugin (https proxy, mTLS) +
  • How to set up TLS/SSL (https proxy, mTLS)

    -SSLPlugin provides TLS/SSL support for 3proxy. It can be used to: +Since version 0.9.7, SSL/TLS support is built into 3proxy when compiled with OpenSSL +(WITH_SSL). Previously available as SSLPlugin, the functionality is now integrated +into the main binary. The plugin line is no longer required. +SSL/TLS support can be used to:

    • Create an https:// proxy (TLS-encrypted connection between client and proxy)
    • Implement MITM for TLS traffic inspection
    • @@ -654,7 +658,6 @@ SSLPlugin provides TLS/SSL support for 3proxy. It can be used to:
      To create an https:// proxy, you need a server certificate and key. The certificate must not be self-signed and should contain Subject Alternative Names (SAN) for the proxy hostname/IP.

      -plugin /path/to/SSLPlugin.ld.so ssl_plugin
       ssl_server_cert /etc/3proxy/certs/server.crt
       ssl_server_key /etc/3proxy/certs/server.key
       ssl_serv
      @@ -670,7 +673,6 @@ Configure clients to use https://proxy-host:3129/ as the proxy URL.
       Client certificate authentication (mTLS):
       
      To require clients to authenticate with a certificate, use ssl_server_verify and provide the CA certificate:

      -plugin /path/to/SSLPlugin.ld.so ssl_plugin
       ssl_server_cert /etc/3proxy/certs/server.crt
       ssl_server_key /etc/3proxy/certs/server.key
       ssl_server_ca_file /etc/3proxy/certs/ca.crt
      @@ -685,7 +687,6 @@ Only clients with a valid certificate signed by the CA can connect.
       MITM for TLS traffic inspection:
       
      To intercept and decrypt TLS traffic, you need a CA certificate to generate spoofed server certificates:

      -plugin /path/to/SSLPlugin.ld.so ssl_plugin
       ssl_server_ca_file /etc/3proxy/certs/ca.crt
       ssl_server_ca_key /etc/3proxy/certs/ca.key
       ssl_client_verify
      @@ -703,7 +704,6 @@ Without ssl_client_verify, the proxy is vulnerable to MITM attacks.
       TLS client (connect to upstream via TLS):
       
      To connect to upstream servers via TLS with client certificate authentication:

      -plugin /path/to/SSLPlugin.ld.so ssl_plugin
       ssl_client_cert /etc/3proxy/certs/client.crt
       ssl_client_key /etc/3proxy/certs/client.key
       ssl_client_verify
      @@ -715,7 +715,6 @@ proxy -p3128
       Conditional TLS for parent proxy (ssl_client_mode 3):
       
      With ssl_client_mode 3, TLS handshake to parent proxy is performed only if the parent type ends with 's' (secure types). This allows mixing secure and non-secure parent proxies in the same configuration:

      -plugin /path/to/SSLPlugin.ld.so ssl_plugin
       ssl_server_cert /etc/3proxy/certs/server.crt
       ssl_server_key /etc/3proxy/certs/server.key
       ssl_client_mode 3
      @@ -734,7 +733,7 @@ ssl_nocli
       

      This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients. For parent proxy connections, user1's traffic goes through an https parent with TLS encryption (secure type), while user2's traffic goes through a regular socks5 parent without TLS. Secure parent types include: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.

      -
    • How to create CA and certificates for SSLPlugin +
    • How to create CA and certificates for SSL

      Creating a Certificate Authority (CA):
      For MITM or mTLS, you need a CA. Generate a CA private key and certificate: @@ -849,6 +848,65 @@ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \ openssl pkcs12 -export -out client.p12 -passout pass: \ -inkey client.key -in client.crt -certfile ca.crt

    • +
    • How to use PCRE filtering (regular expressions) +

      +Since version 0.9.7, PCRE (Perl Compatible Regular Expressions) filtering is built into +3proxy when compiled with PCRE2 support (WITH_PCRE). Previously available as PCREPlugin, +the functionality is now integrated into the main binary. The plugin line is no longer required. +

      +

      +PCRE filtering can be used to create matching and replacement rules with regular expressions +for client requests, client and server headers, and client and server data. +

      +

      +Commands: +

      +pcre TYPE FILTER_ACTION REGEXP [ACE]
      +pcre_rewrite TYPE FILTER_ACTION REGEXP REWRITE_EXPRESSION [ACE]
      +pcre_extend FILTER_ACTION [ACE]
      +pcre_options OPTION1 [...]
      +
      +

      +

        +
      • TYPE - type of filtered data (comma-delimited list): +
          +
        • request - content of the client's request (e.g., HTTP GET request string) +
        • cliheader - content of the client request headers +
        • srvheader - content of the server's reply headers +
        • clidata - data received from the client (e.g., HTTP POST data) +
        • srvdata - data received from the server (e.g., HTML page) +
        +
      • FILTER_ACTION - action on match: +
          +
        • allow - allow this request without checking the rest of the rules +
        • deny - deny this request without checking the rest of the rules +
        • dunno - continue with the rest of the rules (useful with pcre_rewrite) +
        +
      • REGEXP - PCRE (Perl) regular expression. Use * if no regexp matching is required. +
      • REWRITE_EXPRESSION - substitution string. May contain Perl-style substrings +$1, $2, etc. $0 means the whole matched string. \r and \n may be used to insert new lines. +
      • ACE - access control entry (user names, source IPs, destination IPs, ports, etc.), +identical to allow/deny/bandlimin commands. The regular expression is only matched if the ACL +matches the connection data. +
      +

      +

      +Examples: +

      +# Block requests containing specific keywords for certain users
      +pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
      +
      +# Block responses with specific content type
      +pcre srvheader deny "Content-type: application"
      +
      +# Replace content in both directions (censorship)
      +pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
      +pcre_extend deny * 192.168.0.1/16
      +
      +

      +Note: Regular expressions don't require authentication and cannot replace +authentication and/or allow/deny ACLs. +

    • How to limit service access

      First, always specify the internal interface to accept incoming connections with the diff --git a/doc/html/howtor.html b/doc/html/howtor.html index b72935d..c2df08d 100644 --- a/doc/html/howtor.html +++ b/doc/html/howtor.html @@ -33,8 +33,9 @@

    • Как разрешать имена на родительском прокси?
    • Как настроить FTP прокси?
    • Как настроить SNI proxy (tlspr)
    • -
    • Как настроить TLS/SSL с помощью SSLPlugin (https прокси, mTLS)
    • -
    • Как создать CA и сертификаты для SSLPlugin
    • +
    • Как настроить TLS/SSL (https прокси, mTLS)
    • +
    • Как создать CA и сертификаты для SSL
    • +
    • Как использовать PCRE-фильтрацию (регулярные выражения)
    • Как ограничить доступ к службе
    • Как создать список пользователей
    • Как ограничить доступ пользователей к ресурсам @@ -648,9 +649,12 @@ proxy
    • -
    • Как настроить TLS/SSL с помощью SSLPlugin (https прокси, mTLS) +
    • Как настроить TLS/SSL (https прокси, mTLS)

      -SSLPlugin обеспечивает поддержку TLS/SSL для 3proxy. Он может использоваться для: +Начиная с версии 0.9.7 поддержка TLS/SSL встроена в 3proxy при компиляции с OpenSSL +(WITH_SSL). Ранее доступная как SSLPlugin, функциональность теперь интегрирована +в основной бинарный файл. Строка plugin больше не нужна. +TLS/SSL может использоваться для:

      • Создания https:// прокси (TLS-шифрованное соединение между клиентом и прокси)
      • Реализации MITM для инспекции TLS-трафика
      • @@ -663,7 +667,6 @@ SSLPlugin обеспечивает поддержку TLS/SSL для 3proxy. О
        Для создания https:// прокси требуется сертификат и ключ сервера. Сертификат не должен быть самоподписанным и должен содержать альтернативные имена (SAN) для имени хоста/IP прокси.

        -plugin /path/to/SSLPlugin.ld.so ssl_plugin
         ssl_server_cert /etc/3proxy/certs/server.crt
         ssl_server_key /etc/3proxy/certs/server.key
         ssl_serv
        @@ -679,7 +682,6 @@ proxy -p3128
         Аутентификация по клиентскому сертификату (mTLS):
         
        Чтобы требовать от клиентов аутентификацию по сертификату, используйте ssl_server_verify и укажите CA-сертификат:

        -plugin /path/to/SSLPlugin.ld.so ssl_plugin
         ssl_server_cert /etc/3proxy/certs/server.crt
         ssl_server_key /etc/3proxy/certs/server.key
         ssl_server_ca_file /etc/3proxy/certs/ca.crt
        @@ -694,7 +696,6 @@ proxy -p3129
         MITM для инспекции TLS-трафика:
         
        Для перехвата и расшифровки TLS-трафика требуется CA-сертификат для генерации подделанных серверных сертификатов:

        -plugin /path/to/SSLPlugin.ld.so ssl_plugin
         ssl_server_ca_file /etc/3proxy/certs/ca.crt
         ssl_server_ca_key /etc/3proxy/certs/ca.key
         ssl_client_verify
        @@ -712,7 +713,6 @@ CA-сертификат должен быть доверенным для кли
         TLS-клиент (соединение с вышестоящим сервером через TLS):
         
        Для соединения с вышестоящими серверами через TLS с аутентификацией по клиентскому сертификату:

        -plugin /path/to/SSLPlugin.ld.so ssl_plugin
         ssl_client_cert /etc/3proxy/certs/client.crt
         ssl_client_key /etc/3proxy/certs/client.key
         ssl_client_verify
        @@ -724,7 +724,6 @@ proxy -p3128
         Условное TLS для parent прокси (ssl_client_mode 3):
         
        При ssl_client_mode 3 TLS-рукопожатие с родительским прокси выполняется только если тип parent прокси заканчивается на 's' (защищённые типы). Это позволяет смешивать защищённые и незащищённые родительские прокси в одной конфигурации:

        -plugin /path/to/SSLPlugin.ld.so ssl_plugin
         ssl_server_cert /etc/3proxy/certs/server.crt
         ssl_server_key /etc/3proxy/certs/server.key
         ssl_client_mode 3
        @@ -743,7 +742,7 @@ ssl_nocli
         

        Создаётся HTTPS-прокси (ssl_serv), принимающий TLS-соединения от клиентов. Для соединений с родительским прокси трафик user1 идёт через https родитель с TLS-шифрованием (защищённый тип), а трафик user2 — через обычный socks5 родитель без TLS. Защищённые типы parent прокси: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.

        -
      • Как создать CA и сертификаты для SSLPlugin +
      • Как создать CA и сертификаты для SSL

        Создание удостоверяющего центра (CA):
        Для MITM или mTLS требуется CA. Сгенерируйте закрытый ключ CA и сертификат: @@ -859,6 +858,66 @@ openssl pkcs12 -export -out client.p12 -passout pass: \ -inkey client.key -in client.crt -certfile ca.crt

      • +
      • Как использовать PCRE-фильтрацию (регулярные выражения) +

        +Начиная с версии 0.9.7 фильтрация PCRE встроена в 3proxy при компиляции с поддержкой +PCRE2 (WITH_PCRE). Ранее доступная как PCREPlugin, функциональность теперь интегрирована +в основной бинарный файл. Строка plugin больше не нужна. +

        +

        +PCRE-фильтрация может использоваться для создания правил поиска и замены с регулярными +выражениями для запросов клиентов, заголовков клиента и сервера, а также данных. +

        +

        +Команды: +

        +pcre TYPE FILTER_ACTION REGEXP [ACE]
        +pcre_rewrite TYPE FILTER_ACTION REGEXP REWRITE_EXPRESSION [ACE]
        +pcre_extend FILTER_ACTION [ACE]
        +pcre_options OPTION1 [...]
        +
        +

        +

          +
        • TYPE - тип фильтруемых данных (список через запятую): +
            +
          • request - содержимое запроса клиента (например, строка HTTP GET-запроса) +
          • cliheader - содержимое заголовков запроса клиента +
          • srvheader - содержимое заголовков ответа сервера +
          • clidata - данные полученные от клиента (например, данные POST-запроса) +
          • srvdata - данные полученные от сервера (например, HTML-страница) +
          +
        • FILTER_ACTION - действие при совпадении: +
            +
          • allow - разрешить запрос без проверки остальных правил +
          • deny - запретить запрос без проверки остальных правил +
          • dunno - продолжить проверку правил (полезно для pcre_rewrite) +
          +
        • REGEXP - регулярное выражение PCRE (Perl). Используйте * если проверка не требуется. +
        • REWRITE_EXPRESSION - строка замены. Может содержать Perl-подстановки +$1, $2 и т.д. $0 - вся найденная подстрока. \r и \n для вставки новых строк. +
        • ACE - элемент списка контроля доступа (имена пользователей, IP источника, +IP назначения, порты и т.д.), аналогичный командам allow/deny/bandlimin. +Регулярное выражение проверяется только при совпадении ACL с данными соединения. +
        +

        +

        +Примеры: +

        +# Блокировать запросы с определёнными ключевыми словами для некоторых пользователей
        +pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
        +
        +# Блокировать ответы с определённым content-type
        +pcre srvheader deny "Content-type: application"
        +
        +# Замена содержимого в обоих направлениях (цензура)
        +pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
        +pcre_extend deny * 192.168.0.1/16
        +
        +

        +Примечание: Регулярные выражения не требуют авторизации и не могут заменить +авторизацию и/или ACL allow/deny. +

        +
      • Как ограничить доступ к службе

        Во-первых, для ограничения доступа необходимо указать внутренний интерфейс, diff --git a/doc/html/man5/3proxy.cfg.5.html b/doc/html/man5/3proxy.cfg.5.html index 0a52129..4ffe168 100644 --- a/doc/html/man5/3proxy.cfg.5.html +++ b/doc/html/man5/3proxy.cfg.5.html @@ -10,6 +10,14 @@ NAME
        DESCRIPTION
        PLUGINS
        +SSL/TLS SUPPORT
        +MITM Commands
        +Server TLS Commands
        +Client TLS Commands
        +SSL Parameters
        +PCRE FILTERING
        +PCRE Commands
        +PCRE Parameters
        BUGS
        SEE ALSO
        TRIVIA
        @@ -1017,6 +1025,220 @@ the given value, no data filtering will be performed through filtering plugins to avoid data corruption and/or Content-Length changing. Default is 1MB (1048576).

        +

        SSL/TLS SUPPORT + +

        + + +

        SSL/TLS support +is built into 3proxy (since 0.9.7) when compiled with +OpenSSL (WITH_SSL). Previously available as SSLPlugin, the +functionality is now integrated into the main binary. The +plugin line is no longer required.

        + +

        SSL/TLS can be +used for: - transparent MITM (Man-in-the-Middle) for TLS +traffic inspection - https:// proxy (TLS-encrypted +connection between client and proxy) - TLS client +connections to upstream servers with certificate +authentication - mTLS (mutual TLS) requiring client +certificates

        + +

        MITM Commands + +

        + + +

        ssl_mitm +- spoof certificates for services started below. Usage +without ssl_client_verify is insecure.
        +ssl_nomitm
        - do not spoof certificates for services +started below

        + +

        Server TLS Commands + +

        + + +

        ssl_serv +(or ssl_server) - require TLS connection from clients for +services below
        +ssl_noserv
        (or ssl_noserver) - do not require TLS +connection from clients for services below

        + +

        Client TLS Commands + +

        + + +

        ssl_cli +(or ssl_client) - establish TLS connection to upstream +server for services below
        +ssl_nocli
        (or ssl_noclient) - do not establish TLS +connection to upstream server for services below

        + +

        SSL Parameters + +

        + + + +

        ssl_server_cert +/path/to/cert - Server certificate (should not be +self-signed, must contain SAN) for ssl_serv
        +ssl_server_key
        /path/to/key - Server certificate +key for ssl_server_cert or generated MITM certificate +
        +ssl_client_cert
        /path/to/cert - Client +certificate for authentication on upstream server (used with +ssl_cli)
        +ssl_client_key
        /path/to/key - Client certificate +key for ssl_client_cert
        +ssl_client_ciphersuites
        ciphersuites_list - TLS +client ciphers for TLS 1.3
        +ssl_server_ciphersuites
        ciphersuites_list - TLS +server ciphers for TLS 1.3
        +ssl_client_cipher_list
        ciphers_list - TLS client +ciphers for TLS 1.2 and below
        +ssl_server_cipher_list
        ciphers_list - TLS server +ciphers for TLS 1.2 and below
        +ssl_client_min_proto_version
        tls_version - TLS +client minimum TLS version (e.g., TLSv1.2)
        +ssl_server_min_proto_version
        tls_version - TLS +server minimum TLS version
        +ssl_client_max_proto_version
        tls_version - TLS +client maximum TLS version
        +ssl_server_max_proto_version
        tls_version - TLS +server maximum TLS version
        +ssl_client_verify
        - verify the certificate for the +upstream server (used with ssl_mitm or ssl_cli)
        +ssl_client_no_verify
        - do not verify the certificate for +the upstream server (default)
        +ssl_server_verify
        - require client certificate +authentication (mTLS) for ssl_serv
        +ssl_server_no_verify
        - do not require client certificate +(default)
        +ssl_server_ca_file
        /path/to/cafile - CA +certificate file for MITM
        +ssl_server_ca_key
        /path/to/cakey - key for +ssl_server_ca_file MITM CA
        +ssl_server_ca_dir
        /path/to/cadir - CA directory +for ssl_server_verify
        +ssl_server_ca_store
        /path/to/castore - CA store +for ssl_server_verify (OpenSSL 3.0+)
        +ssl_client_ca_file
        /path/to/cafile - CA file for +ssl_client_verify
        +ssl_client_ca_dir
        /path/to/cadir - CA directory +for ssl_client_verify
        +ssl_client_ca_store
        /path/to/castore - CA store +for ssl_client_verify (OpenSSL 3.0+)
        +ssl_client_sni
        hostname - SNI hostname to send to +upstream server
        +ssl_client_alpn
        protocol1 protocol2 ... - ALPN +protocols to negotiate with upstream server
        +ssl_client_mode
        mode - when to establish TLS +connection: 0 - on connect (default), 1 - after +authentication, 2 - before data, 3 - only for secure parent +types (ending with ’s’)
        +ssl_certcache
        /path/to/cache/ - location for the +generated MITM certificates cache

        + +

        PCRE FILTERING + +

        + + +

        PCRE (Perl +Compatible Regular Expressions) filtering is built into +3proxy (since 0.9.7) when compiled with PCRE2 support +(WITH_PCRE). Previously available as PCREPlugin, the +functionality is now integrated into the main binary. The +plugin line is no longer required.

        + +

        PCRE filtering +allows creating matching and replacement rules with regular +expressions for client requests, headers, and data.

        + +

        PCRE Commands + +

        + + +

        pcre +TYPE FILTER_ACTION REGEXP [ACE]
        +Apply a rule for matching regular expression.
        +pcre_rewrite
        TYPE FILTER_ACTION REGEXP +REWRITE_EXPRESSION [ACE]
        +Match and replace with rewrite expression.
        +pcre_extend
        FILTER_ACTION [ACE]
        +Extend the ACL of the last pcre or pcre_rewrite command by +adding an additional ACE.
        +pcre_options
        OPTION1 [OPTION2 ...]
        +Set matching options. Both PCRE2 native options and PCRE +compatibility options are supported. PCRE options are mapped +to their PCRE2 equivalents for backward compatibility.
        +PCRE2 options: PCRE2_CASELESS, PCRE2_MULTILINE, +PCRE2_DOTALL, PCRE2_EXTENDED, PCRE2_DOLLAR_ENDONLY, +PCRE2_UNGREEDY, PCRE2_UTF, PCRE2_UCP, PCRE2_NO_AUTO_CAPTURE, +PCRE2_FIRSTLINE, PCRE2_DUPNAMES, PCRE2_MATCH_UNSET_BACKREF, +PCRE2_ALT_BSUX, PCRE2_ALT_CIRCUMFLEX, PCRE2_ALT_VERBNAMES, +PCRE2_USE_OFFSET_LIMIT, PCRE2_EXTENDED_MORE, PCRE2_LITERAL, +PCRE2_MATCH_INVALID_UTF.
        +PCRE compatibility options: PCRE_CASELESS, PCRE_MULTILINE, +PCRE_DOTALL, PCRE_EXTENDED, PCRE_ANCHORED, +PCRE_DOLLAR_ENDONLY, PCRE_EXTRA, PCRE_NOTBOL, PCRE_NOTEOL, +PCRE_UNGREEDY, PCRE_NOTEMPTY, PCRE_UTF8, +PCRE_NO_AUTO_CAPTURE, PCRE_NO_UTF8_CHECK, PCRE_AUTO_CALLOUT, +PCRE_PARTIAL, PCRE_DFA_SHORTEST, PCRE_DFA_RESTART, +PCRE_FIRSTLINE, PCRE_DUPNAMES, PCRE_NEWLINE_CR, +PCRE_NEWLINE_LF, PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANY, +PCRE_NEWLINE_ANYCRLF, PCRE_BSR_ANYCRLF, +PCRE_BSR_UNICODE.

        + +

        PCRE Parameters + +

        + + +

        TYPE - type of +filtered data (comma-delimited list):
        +request - content of the client’s request (e.g., HTTP +GET request string)
        +cliheader - content of the client request headers
        +srvheader - content of the server’s reply headers
        +clidata - data received from the client (e.g., HTTP POST +data)
        +srvdata - data received from the server (e.g., HTML +page)

        + +

        FILTER_ACTION - +action on match:
        +allow - allow this request without checking the rest of the +rules
        +deny - deny this request without checking the rest of the +rules
        +dunno - continue with the rest of the rules (useful with +pcre_rewrite)

        + +

        REGEXP - PCRE +(Perl) regular expression. Use * if no regexp matching is +required.

        + + +

        REWRITE_EXPRESSION +- substitution string. May contain Perl-style substrings $1, +$2, etc. $0 means the whole matched string. \r and \n may be +used to insert new lines; the string may be empty +("").

        + +

        ACE - access +control entry (user names, source IPs, destination IPs, +ports, etc.), identical to allow/deny/bandlimin commands. +The regular expression is only matched if the ACL matches +the connection data. Warning: Regular expressions +don’t require authentication and cannot replace +authentication and/or allow/deny ACLs.

        +

        BUGS

        diff --git a/doc/html/plugins/PCREPlugin.html b/doc/html/plugins/PCREPlugin.html index acca2af..64297c6 100644 --- a/doc/html/plugins/PCREPlugin.html +++ b/doc/html/plugins/PCREPlugin.html @@ -1,10 +1,13 @@ +

        3proxy PCRE (Perl Compatible Regular Expressions) Filtering

        -

        3proxy Perl Compatible Regular Expressions (PCRE) Plugin

        +

        Note: Since version 0.9.7, PCRE filtering is built into 3proxy and does not require +a separate plugin. All pcre_* commands are available directly when 3proxy is compiled with +PCRE2 support (WITH_PCRE). The plugin line is no longer needed.

        -This filtering plugin can be used to create matching and replacement +

        This filtering functionality can be used to create matching and replacement rules with regular expressions for client requests, client and server headers, and client and server data. It adds 3 additional -configuration commands: +configuration commands:

         pcre TYPE FILTER_ACTION REGEXP [ACE]
        @@ -78,16 +81,10 @@ authentication and/or allow/deny ACLs.
         
         

        Example:

        -plugin PCREPlugin.dll pcre_plugin
         pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
         pcre srvheader deny "Content-type: application"
         pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
         pcre_extend deny * 192.168.0.1/16
         
        -

        Download:

        -
          -
        • Plugin is included in the 3proxy 0.6 binary and source distribution -
        • Example configuration (by Dennis Garber): NoPornLitest.cfg -
        - +© Vladimir Dubrovin, License: BSD style diff --git a/doc/html/plugins/PCREPlugin.ru.html b/doc/html/plugins/PCREPlugin.ru.html index 5835dd8..cff579e 100644 --- a/doc/html/plugins/PCREPlugin.ru.html +++ b/doc/html/plugins/PCREPlugin.ru.html @@ -1,8 +1,12 @@ -

        Плагин регулярных выражений совместимых с Perl (PCRE) для 3proxy

        +

        Фильтрация PCRE (Perl Compatible Regular Expressions) в 3proxy

        -Фильтрующий плагин используется для создания правил поиска и замены +

        Примечание: Начиная с версии 0.9.7 фильтрация PCRE встроена в 3proxy и не требует +отдельного плагина. Все команды pcre_* доступны напрямую при компиляции 3proxy с поддержкой +PCRE2 (WITH_PCRE). Строка plugin больше не нужна.

        + +

        Фильтрующий плагин используется для создания правил поиска и замены регулярных выражений в запросе, заголовков запроса и ответа и данных. -Добавляет поддержку 3х новых команд в файле конфигурации: +Добавляет поддержку 3х новых команд в файле конфигурации:

         pcre TYPE FILTER_ACTION REGEXP [ACE]
        @@ -30,7 +34,7 @@ PCRE_UTF8,
         PCRE_NO_AUTO_CAPTURE,
         PCRE_NO_UTF8_CHECK,
         PCRE_AUTO_CALLOUT,
        -PCRE_PARTIAL,     
        +PCRE_PARTIAL,
         PCRE_DFA_SHORTEST,
         PCRE_DFA_RESTART,
         PCRE_FIRSTLINE,
        @@ -58,7 +62,7 @@ PCRE_BSR_UNICODE
         
      • FILTER_ACTION - действие при совпадении. Может принимать значение
        • allow - разрешить данный запрос без просмотра дальнейших правил
        • deny - запретить данный запрос без просмотра дальнейших правил -
        • dunno - продолжить анализ правил (полезно для pcre_rewrite) +
        • dunno - продолжить анализ правил (полезно для pcre_rewrite)
      • REGEXP - регулярное выражение в формате PCRE (perl). Используйте * если не требуется проерка регулярного выражения. @@ -76,15 +80,10 @@ PCRE_BSR_UNICODE

        Пример:

        -plugin PCREPlugin.dll pcre_plugin
         pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
         pcre srvheader deny "Content-type: application"
         pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
         pcre_extend deny * 192.168.0.1/16
         
        -

        Загрузить:

        -
          -
        • Плагин включен в дистрибутив 3proxy 0.6 -
        • Пример конфигурации (by Dennis Garber): NoPornLitest.cfg -
        +© Vladimir Dubrovin, License: BSD style diff --git a/doc/html/plugins/SSLPlugin.html b/doc/html/plugins/SSLPlugin.html index 89e5582..b33c070 100644 --- a/doc/html/plugins/SSLPlugin.html +++ b/doc/html/plugins/SSLPlugin.html @@ -1,6 +1,11 @@ -

        3proxy SSL/TLS Plugin

        +

        3proxy SSL/TLS Support

        -This plugin can be used to transparently decrypt SSL/TLS data, provide TLS encryption for proxy traffic, and authenticate using client certificates. +

        Note: Since version 0.9.7, SSL/TLS support is built into 3proxy and does not require +a separate plugin. All ssl_* commands are available directly when 3proxy is compiled with +OpenSSL support (WITH_SSL). The plugin line is no longer needed.

        + +

        SSL/TLS support can be used to transparently decrypt SSL/TLS data, provide TLS encryption +for proxy traffic, and authenticate using client certificates.

        For transparent certificate spoofing (MITM):

        @@ -55,7 +60,6 @@ Generated certificates are placed in the same path.

        MITM example:

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_ca_file /path/to/cafile
         ssl_server_ca_key /path/to/cakey
         ssl_mitm
        @@ -67,7 +71,6 @@ MITM's traffic with a spoofed certificate for the port 3128 proxy.
         
         

        https:// proxy example:

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert path_to_cert
         ssl_server_key path_to_key
         ssl_serv
        @@ -79,7 +82,6 @@ Creates an https:// proxy on port 33128 and an http:// proxy on port 3128
         
         

        TLS client example (connect to upstream via TLS):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_client_cert /path/to/client.crt
         ssl_client_key /path/to/client.key
         ssl_client_verify
        @@ -91,7 +93,6 @@ Creates an HTTP proxy that connects to upstream servers via TLS with client cert
         
         

        Conditional TLS for parent proxy (ssl_client_mode 3):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert /path/to/server.crt
         ssl_server_key /path/to/key
         ssl_client_mode 3
        @@ -111,7 +112,6 @@ Creates an HTTP proxy on port 3128 that uses TLS for client connections (ssl_ser
         
         

        mTLS example (require client certificate):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert /path/to/server.crt
         ssl_server_key /path/to/server.key
         ssl_server_ca_file /path/to/ca.crt
        diff --git a/doc/html/plugins/SSLPlugin.ru.html b/doc/html/plugins/SSLPlugin.ru.html
        index 7c6bf6b..dc9238b 100644
        --- a/doc/html/plugins/SSLPlugin.ru.html
        +++ b/doc/html/plugins/SSLPlugin.ru.html
        @@ -1,6 +1,10 @@
        -

        3proxy SSL/TLS плагин

        +

        3proxy SSL/TLS поддержка

        -Плагин можно использовать для перехвата и дешифровки SSL/TLS трафика, для шифрования трафика прокси-сервера и аутентификации с помощью клиентских сертификатов. +

        Примечание: Начиная с версии 0.9.7 поддержка SSL/TLS встроена в 3proxy и не требует +отдельного плагина. Все команды ssl_* доступны напрямую при компиляции 3proxy с поддержкой +OpenSSL (WITH_SSL). Строка plugin больше не нужна.

        + +

        Плагин можно использовать для перехвата и дешифровки SSL/TLS трафика, для шифрования трафика прокси-сервера и аутентификации с помощью клиентских сертификатов.

        Для прозрачного перехвата трафика (MITM):

        @@ -52,7 +56,6 @@ ssl_server_ca_key и ssl_server_key соответственно, если он

        Пример MITM:

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_ca_file /path/to/cafile
         ssl_server_ca_key /path/to/cakey
         ssl_mitm
        @@ -64,7 +67,6 @@ proxy -p3129
         
         

        Пример конфигурации https:// прокси:

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert path_to_cert
         ssl_server_key path_to_key
         ssl_serv
        @@ -76,7 +78,6 @@ proxy -p3128
         
         

        Пример TLS-клиента (соединение к вышестоящему серверу через TLS):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_client_cert /path/to/client.crt
         ssl_client_key /path/to/client.key
         ssl_client_verify
        @@ -88,7 +89,6 @@ proxy -p3128
         
         

        Условное TLS для parent прокси (ssl_client_mode 3):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert /path/to/server.crt
         ssl_server_key /path/to/key
         ssl_client_mode 3
        @@ -108,7 +108,6 @@ ssl_nocli
         
         

        Пример mTLS (требование клиентского сертификата):

        -plugin /path/to/SSLPlugin.so ssl_plugin
         ssl_server_cert /path/to/server.crt
         ssl_server_key /path/to/server.key
         ssl_server_ca_file /path/to/ca.crt
        diff --git a/man/3proxy.cfg.5 b/man/3proxy.cfg.5
        index 7812e57..3b4029f 100644
        --- a/man/3proxy.cfg.5
        +++ b/man/3proxy.cfg.5
        @@ -1135,7 +1135,7 @@ memory shortage, you can try to experiment with negative values.
         \fI\fR \fI\fR [\fI\fR ...]
         .br
          Loads specified library and calls given export function with given arguments,
        -as 
        +as
         .br
          int functions_to_call(struct pluginlink * pl, int argc, char * argv[]);
         .br
        @@ -1149,6 +1149,203 @@ as
         data filtering will be performed through filtering plugins to avoid data
         corruption and/or Content-Length changing. Default is 1MB (1048576).
         
        +.SH SSL/TLS SUPPORT
        +SSL/TLS support is built into 3proxy (since 0.9.7) when compiled with OpenSSL
        +(WITH_SSL). Previously available as SSLPlugin, the functionality is now integrated
        +into the main binary. The plugin line is no longer required.
        +
        +SSL/TLS can be used for:
        +- transparent MITM (Man-in-the-Middle) for TLS traffic inspection
        +- https:// proxy (TLS-encrypted connection between client and proxy)
        +- TLS client connections to upstream servers with certificate authentication
        +- mTLS (mutual TLS) requiring client certificates
        +
        +.SS MITM Commands
        +.br
        +.BR ssl_mitm
        +- spoof certificates for services started below. Usage without ssl_client_verify is insecure.
        +.br
        +.BR ssl_nomitm
        +- do not spoof certificates for services started below
        +
        +.SS Server TLS Commands
        +.br
        +.BR ssl_serv
        +(or ssl_server) - require TLS connection from clients for services below
        +.br
        +.BR ssl_noserv
        +(or ssl_noserver) - do not require TLS connection from clients for services below
        +
        +.SS Client TLS Commands
        +.br
        +.BR ssl_cli
        +(or ssl_client) - establish TLS connection to upstream server for services below
        +.br
        +.BR ssl_nocli
        +(or ssl_noclient) - do not establish TLS connection to upstream server for services below
        +
        +.SS SSL Parameters
        +.br
        +.BR ssl_server_cert
        +\fI/path/to/cert\fR - Server certificate (should not be self-signed, must contain SAN) for ssl_serv
        +.br
        +.BR ssl_server_key
        +\fI/path/to/key\fR - Server certificate key for ssl_server_cert or generated MITM certificate
        +.br
        +.BR ssl_client_cert
        +\fI/path/to/cert\fR - Client certificate for authentication on upstream server (used with ssl_cli)
        +.br
        +.BR ssl_client_key
        +\fI/path/to/key\fR - Client certificate key for ssl_client_cert
        +.br
        +.BR ssl_client_ciphersuites
        +\fIciphersuites_list\fR - TLS client ciphers for TLS 1.3
        +.br
        +.BR ssl_server_ciphersuites
        +\fIciphersuites_list\fR - TLS server ciphers for TLS 1.3
        +.br
        +.BR ssl_client_cipher_list
        +\fIciphers_list\fR - TLS client ciphers for TLS 1.2 and below
        +.br
        +.BR ssl_server_cipher_list
        +\fIciphers_list\fR - TLS server ciphers for TLS 1.2 and below
        +.br
        +.BR ssl_client_min_proto_version
        +\fItls_version\fR - TLS client minimum TLS version (e.g., TLSv1.2)
        +.br
        +.BR ssl_server_min_proto_version
        +\fItls_version\fR - TLS server minimum TLS version
        +.br
        +.BR ssl_client_max_proto_version
        +\fItls_version\fR - TLS client maximum TLS version
        +.br
        +.BR ssl_server_max_proto_version
        +\fItls_version\fR - TLS server maximum TLS version
        +.br
        +.BR ssl_client_verify
        +- verify the certificate for the upstream server (used with ssl_mitm or ssl_cli)
        +.br
        +.BR ssl_client_no_verify
        +- do not verify the certificate for the upstream server (default)
        +.br
        +.BR ssl_server_verify
        +- require client certificate authentication (mTLS) for ssl_serv
        +.br
        +.BR ssl_server_no_verify
        +- do not require client certificate (default)
        +.br
        +.BR ssl_server_ca_file
        +\fI/path/to/cafile\fR - CA certificate file for MITM
        +.br
        +.BR ssl_server_ca_key
        +\fI/path/to/cakey\fR - key for ssl_server_ca_file MITM CA
        +.br
        +.BR ssl_server_ca_dir
        +\fI/path/to/cadir\fR - CA directory for ssl_server_verify
        +.br
        +.BR ssl_server_ca_store
        +\fI/path/to/castore\fR - CA store for ssl_server_verify (OpenSSL 3.0+)
        +.br
        +.BR ssl_client_ca_file
        +\fI/path/to/cafile\fR - CA file for ssl_client_verify
        +.br
        +.BR ssl_client_ca_dir
        +\fI/path/to/cadir\fR - CA directory for ssl_client_verify
        +.br
        +.BR ssl_client_ca_store
        +\fI/path/to/castore\fR - CA store for ssl_client_verify (OpenSSL 3.0+)
        +.br
        +.BR ssl_client_sni
        +\fIhostname\fR - SNI hostname to send to upstream server
        +.br
        +.BR ssl_client_alpn
        +\fIprotocol1 protocol2 ...\fR - ALPN protocols to negotiate with upstream server
        +.br
        +.BR ssl_client_mode
        +\fImode\fR - when to establish TLS connection: 0 - on connect (default), 1 - after authentication, 2 - before data, 3 - only for secure parent types (ending with 's')
        +.br
        +.BR ssl_certcache
        +\fI/path/to/cache/\fR - location for the generated MITM certificates cache
        +
        +.SH PCRE FILTERING
        +PCRE (Perl Compatible Regular Expressions) filtering is built into 3proxy
        +(since 0.9.7) when compiled with PCRE2 support (WITH_PCRE). Previously
        +available as PCREPlugin, the functionality is now integrated into the main
        +binary. The plugin line is no longer required.
        +
        +PCRE filtering allows creating matching and replacement rules with regular
        +expressions for client requests, headers, and data.
        +
        +.SS PCRE Commands
        +.br
        +.BR pcre
        +\fITYPE FILTER_ACTION REGEXP [ACE]\fR
        +.br
        +Apply a rule for matching regular expression.
        +.br
        +.BR pcre_rewrite
        +\fITYPE FILTER_ACTION REGEXP REWRITE_EXPRESSION [ACE]\fR
        +.br
        +Match and replace with rewrite expression.
        +.br
        +.BR pcre_extend
        +\fIFILTER_ACTION [ACE]\fR
        +.br
        +Extend the ACL of the last pcre or pcre_rewrite command by adding an additional ACE.
        +.br
        +.BR pcre_options
        +\fIOPTION1 [OPTION2 ...]\fR
        +.br
        +Set matching options. Both PCRE2 native options and PCRE compatibility options
        +are supported. PCRE options are mapped to their PCRE2 equivalents for backward
        +compatibility.
        +.br
        +PCRE2 options: PCRE2_CASELESS, PCRE2_MULTILINE, PCRE2_DOTALL, PCRE2_EXTENDED,
        +PCRE2_DOLLAR_ENDONLY, PCRE2_UNGREEDY, PCRE2_UTF, PCRE2_UCP, PCRE2_NO_AUTO_CAPTURE,
        +PCRE2_FIRSTLINE, PCRE2_DUPNAMES, PCRE2_MATCH_UNSET_BACKREF, PCRE2_ALT_BSUX,
        +PCRE2_ALT_CIRCUMFLEX, PCRE2_ALT_VERBNAMES, PCRE2_USE_OFFSET_LIMIT, PCRE2_EXTENDED_MORE,
        +PCRE2_LITERAL, PCRE2_MATCH_INVALID_UTF.
        +.br
        +PCRE compatibility options: PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, PCRE_EXTENDED,
        +PCRE_ANCHORED, PCRE_DOLLAR_ENDONLY, PCRE_EXTRA, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_UNGREEDY,
        +PCRE_NOTEMPTY, PCRE_UTF8, PCRE_NO_AUTO_CAPTURE, PCRE_NO_UTF8_CHECK, PCRE_AUTO_CALLOUT,
        +PCRE_PARTIAL, PCRE_DFA_SHORTEST, PCRE_DFA_RESTART, PCRE_FIRSTLINE, PCRE_DUPNAMES,
        +PCRE_NEWLINE_CR, PCRE_NEWLINE_LF, PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANY, PCRE_NEWLINE_ANYCRLF,
        +PCRE_BSR_ANYCRLF, PCRE_BSR_UNICODE.
        +
        +.SS PCRE Parameters
        +TYPE - type of filtered data (comma-delimited list):
        +.br
        + request - content of the client's request (e.g., HTTP GET request string)
        +.br
        + cliheader - content of the client request headers
        +.br
        + srvheader - content of the server's reply headers
        +.br
        + clidata - data received from the client (e.g., HTTP POST data)
        +.br
        + srvdata - data received from the server (e.g., HTML page)
        +
        +FILTER_ACTION - action on match:
        +.br
        + allow - allow this request without checking the rest of the rules
        +.br
        + deny - deny this request without checking the rest of the rules
        +.br
        + dunno - continue with the rest of the rules (useful with pcre_rewrite)
        +
        +REGEXP - PCRE (Perl) regular expression. Use * if no regexp matching is required.
        +
        +REWRITE_EXPRESSION - substitution string. May contain Perl-style substrings
        +$1, $2, etc. $0 means the whole matched string. \er and \en may be used
        +to insert new lines; the string may be empty ("").
        +
        +ACE - access control entry (user names, source IPs, destination IPs, ports, etc.),
        +identical to allow/deny/bandlimin commands. The regular expression is only
        +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 BUGS
         Report all bugs to
         .BR 3proxy@3proxy.org
        diff --git a/src/3proxy.c b/src/3proxy.c
        index f24d5ab..8270b86 100644
        --- a/src/3proxy.c
        +++ b/src/3proxy.c
        @@ -7,6 +7,12 @@
         */
         
         #include "proxy.h"
        +#ifdef WITH_SSL
        +void ssl_install(void);
        +#endif
        +#ifdef WITH_PCRE
        +void pcre_install(void);
        +#endif
         #ifndef _WIN32
         #include 
         #ifndef NOPLUGINS
        @@ -523,6 +529,13 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
           _3proxy_mutex_init(&conf.threadinit);
         #endif
         
        +#ifdef WITH_SSL
        +  ssl_install();
        +#endif
        +#ifdef WITH_PCRE
        +  pcre_install();
        +#endif
        +
           freeconf(&conf);
           res = readconfig(fp);
           conf.version++;
        diff --git a/src/3proxy_crypt.c b/src/3proxy_crypt.c
        index a4c0eb5..7ddf28e 100644
        --- a/src/3proxy_crypt.c
        +++ b/src/3proxy_crypt.c
        @@ -5,11 +5,13 @@
            please read License Agreement
         
         */
        +#include "blake2_compat.h"
        +#ifdef WITH_SSL
        +#include 
         #ifndef WITHMAIN
        -#include "libs/md5.h"
        +/* MD5 needed for $1$ crypt */
        +#endif
         #endif
        -#include "libs/md4.h"
        -#include "libs/blake2.h"
         #include 
         
         #define MD5_SIZE 16
        @@ -24,6 +26,12 @@ void tohex(unsigned char *in, unsigned char *out, int len);
         static unsigned char itoa64[] =
                 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
         
        +
        +#if defined(WITH_SSL)
        +EVP_MD *md4 = NULL;
        +EVP_MD *md5 = NULL;
        +#endif
        +
         void
         _crypt_to64(unsigned char *s, unsigned long v, int n)
         {
        @@ -34,11 +42,13 @@ _crypt_to64(unsigned char *s, unsigned long v, int n)
         }
         
         
        +#ifdef WITH_SSL
         unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex)
         {
         	unsigned char szUnicodePass[513];
         	unsigned int nPasswordLen;
        -	MD4_CTX ctx;
        +	EVP_MD_CTX *ctx;
        +	unsigned int len=sizeof(szUnicodePass);
         	unsigned int i;
         
         	/*
        @@ -53,15 +63,20 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor
         	}
         
         	/* Encrypt Unicode password to a 16-byte MD4 hash */
        -	MD4Init(&ctx);
        -	MD4Update(&ctx, szUnicodePass, (nPasswordLen<<1));
        -	MD4Final(szUnicodePass, &ctx);
        +	ctx = EVP_MD_CTX_new();
        +	if(!EVP_DigestInit_ex(ctx, md4, NULL)){
        +	    fprintf(stderr, "Failed to init MD4 digest\n");
        +	}
        +	EVP_DigestUpdate(ctx, szUnicodePass, (nPasswordLen<<1));
        +	EVP_DigestFinal_ex(ctx, szUnicodePass, &len);
        +	EVP_MD_CTX_free(ctx);
         	if (ctohex){
         		tohex(szUnicodePass, szHash, 16);
         	}
         	else memcpy(szHash, szUnicodePass, 16);
         	return szHash;
         }
        +#endif
         
         
         unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){
        @@ -74,34 +89,38 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
          int sl;
          unsigned long l;
         
        -#ifndef WITHMAIN
        +#if defined(WITH_SSL)
          if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
        -	MD5_CTX	ctx,ctx1;
        +	EVP_MD_CTX	*ctx, *ctx1;
        +	unsigned int len;
         	int pl, i;
         
         	sp = salt +3;
         	sl = (int)(ep - sp);
         	magic = (unsigned char *)"$1$";
         
        -	MD5Init(&ctx);
        +	ctx = EVP_MD_CTX_new();
        +	EVP_DigestInit_ex(ctx, md5, NULL);
         
         	/* The password first, since that is what is most unknown */
        -	MD5Update(&ctx,pw,strlen((char *)pw));
        +	EVP_DigestUpdate(ctx,pw,strlen((char *)pw));
         
         	/* Then our magic string */
        -	MD5Update(&ctx,magic,strlen((char *)magic));
        +	EVP_DigestUpdate(ctx,magic,strlen((char *)magic));
         
         	/* Then the raw salt */
        -	MD5Update(&ctx,sp,sl);
        +	EVP_DigestUpdate(ctx,sp,sl);
         
         	/* Then just as many unsigned characters of the MD5(pw,salt,pw) */
        -	MD5Init(&ctx1);
        -	MD5Update(&ctx1,pw,strlen((char *)pw));
        -	MD5Update(&ctx1,sp,sl);
        -	MD5Update(&ctx1,pw,strlen((char *)pw));
        -	MD5Final(final,&ctx1);
        +	ctx1 = EVP_MD_CTX_new();
        +	EVP_DigestInit_ex(ctx1, EVP_md5(), NULL);
        +	EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
        +	EVP_DigestUpdate(ctx1,sp,sl);
        +	EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
        +	EVP_DigestFinal_ex(ctx1,final,&len);
        +	EVP_MD_CTX_free(ctx1);
         	for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE)
        -		MD5Update(&ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl);
        +		EVP_DigestUpdate(ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl);
         
         	/* Don't leave anything around in vm they could use. */
         	memset(final,0,sizeof final);
        @@ -109,12 +128,13 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
         	/* Then something really weird... */
         	for (i = (int)strlen((char *)pw); i ; i >>= 1)
         		if(i&1)
        -		    MD5Update(&ctx, final, 1);
        +		    EVP_DigestUpdate(ctx, final, 1);
         		else
        -		    MD5Update(&ctx, pw, 1);
        +		    EVP_DigestUpdate(ctx, pw, 1);
         
         
        -	MD5Final(final,&ctx);
        +	EVP_DigestFinal_ex(ctx,final,&len);
        +	EVP_MD_CTX_free(ctx);
         
         	/*
         	 * and now, just to make sure things don't run too fast
        @@ -122,23 +142,25 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
         	 * need 30 seconds to build a 1000 entry dictionary...
         	 */
         	for(i=0;i<1000;i++) {
        -		MD5Init(&ctx1);
        +		ctx1 = EVP_MD_CTX_new();
        +		EVP_DigestInit_ex(ctx1, md5, NULL);
         		if(i & 1)
        -			MD5Update(&ctx1,pw,strlen((char *)pw));
        +			EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
         		else
        -			MD5Update(&ctx1,final,MD5_SIZE);
        +			EVP_DigestUpdate(ctx1,final,MD5_SIZE);
         
         		if(i % 3)
        -			MD5Update(&ctx1,sp,sl);
        +			EVP_DigestUpdate(ctx1,sp,sl);
         
         		if(i % 7)
        -			MD5Update(&ctx1,pw,strlen((char *)pw));
        +			EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
         
         		if(i & 1)
        -			MD5Update(&ctx1,final,MD5_SIZE);
        +			EVP_DigestUpdate(ctx1,final,MD5_SIZE);
         		else
        -			MD5Update(&ctx1,pw,strlen((char *)pw));
        -		MD5Final(final,&ctx1);
        +			EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
        +		EVP_DigestFinal_ex(ctx1,final,&len);
        +		EVP_MD_CTX_free(ctx1);
         	}
         
         
        @@ -151,7 +173,13 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
             sp = salt +3;
             sl = (int)(ep - sp);
             magic = (unsigned char *)"$3$";
        -    blake2b(final, MD5_SIZE, pw, strlen((char *)pw), sp, sl);
        +    {
        +        blake2b_state S;
        +        blake2b_init(&S, MD5_SIZE);
        +        blake2b_update(&S, pw, strlen((char *)pw) + 1);
        +        blake2b_update(&S, sp, sl);
        +        blake2b_final(&S, final, MD5_SIZE);
        +    }
          }
          else {
         	*passwd = 0;
        @@ -180,25 +208,55 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
         }
         
         #ifdef WITHMAIN
        -
        +#ifdef WITH_SSL
        +OSSL_LIB_CTX *library_ctx = NULL;
        +#include 
        +#endif
         #include 
         int main(int argc, char* argv[]){
         	unsigned char buf[1024];
         	unsigned i;
         	if(argc < 2 || argc > 3) {
         		fprintf(stderr, "usage: \n"
        +#ifdef WITH_SSL
         			"\t%s \n"
        +#endif
         			"\t%s  \n"
        +#ifdef WITH_SSL
         			"Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n"
        +#else
        +			"Performs BLAKE2 crypt with salt\n"
        +#endif
         			"This software uses:\n"
        -			"  RSA Data Security, Inc. MD4 Message-Digest Algorithm\n"
        -			"  RSA Data Security, Inc. MD5 Message-Digest Algorithm\n",
        +#ifdef WITH_SSL
        +			"  OpenSSL EVP (MD4, MD5, BLAKE2b)\n"
        +#else
        +			"  BLAKE2 reference implementation\n"
        +#endif
        +			,
         			argv[0],
         			argv[0]);
         			return 1;
         	}
        +#ifdef WITH_SSL
        +        library_ctx = OSSL_LIB_CTX_new();
        +        OSSL_PROVIDER_load(library_ctx, "legacy");
        +        OSSL_PROVIDER_load(library_ctx, "default");
        +        md4 = EVP_MD_fetch(library_ctx, "MD4", NULL);
        +        if (md4 == NULL) {
        +	    fprintf(stderr, "Error fetching MD4\n");
        +        }
        +        md5 = EVP_MD_fetch(library_ctx, "MD5", NULL);
        +        if (md5 == NULL) {
        +	    fprintf(stderr, "Error fetching MD5\n");
        +        }
        +#endif
         	if(argc == 2) {
        +#ifdef WITH_SSL
         		printf("NT:%s\n", ntpwdhash(buf, (unsigned char *)argv[1], 1));
        +#else
        +		fprintf(stderr, "NT crypt not available (compiled without OpenSSL)\n");
        +#endif
         	}
         	else {
         		i = (int)strlen((char *)argv[1]);
        diff --git a/src/Makefile.inc b/src/Makefile.inc
        index 272b7dd..2c2ed0c 100644
        --- a/src/Makefile.inc
        +++ b/src/Makefile.inc
        @@ -7,6 +7,9 @@ all:	$(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS)
         sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h
         	$(CC) $(CFLAGS) sockmap.c
         
        +udpsockmap$(OBJSUFFICS): udpsockmap.c proxy.h structures.h
        +	$(CC) $(COUT)udpsockmap$(OBJSUFFICS) $(CFLAGS) udpsockmap.c
        +
         common$(OBJSUFFICS): common.c proxy.h structures.h
         	$(CC) $(CFLAGS) common.c
         
        @@ -65,14 +68,14 @@ $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS)
         $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
         	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
         
        -$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
        -	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
        +$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
        +	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
         
         $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
         	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
         
        -$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
        -	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
        +$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
        +	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
         
         $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
         	$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
        @@ -152,21 +155,24 @@ datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h
         3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c
         	$(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c
         
        -md4$(OBJSUFFICS):  libs/md4.h libs/md4.c
        -	$(CC) $(COUT)md4$(OBJSUFFICS) $(CFLAGS) libs/md4.c
        -
        -md5$(OBJSUFFICS):  libs/md5.h libs/md5.c
        -	$(CC) $(COUT)md5$(OBJSUFFICS) $(CFLAGS) libs/md5.c
        -
         blake2$(OBJSUFFICS):  libs/blake2.h libs/blake2-impl.h libs/blake2b-ref.c
         	$(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c
         
        -$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): md4$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS)
        -	$(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) md4$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS)
        +$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS)
        +	$(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS)
         
         stringtable$(OBJSUFFICS):  stringtable.c
         	$(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c
         
        -$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(VERSIONDEP)
        -	$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE)  3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
        +ssllib$(OBJSUFFICS): ssllib.c
        +	$(CC) $(COUT)ssllib$(OBJSUFFICS) $(CFLAGS) ssllib.c
        +
        +ssl$(OBJSUFFICS): ssl.c
        +	$(CC) $(COUT)ssl$(OBJSUFFICS) $(CFLAGS) ssl.c
        +
        +pcre$(OBJSUFFICS): pcre.c
        +	$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c
        +
        +$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(VERSIONDEP)
        +	$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE)  3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
         
        diff --git a/src/auth.c b/src/auth.c
        index 0727cb3..85ea0e4 100644
        --- a/src/auth.c
        +++ b/src/auth.c
        @@ -223,8 +223,10 @@ int strongauth(struct clientparam * param){
         	if (!param->pwtype && param->password) {
         		if (pw_table.ihashtable && hashresolv(&pw_table, param, &dummy, NULL))
         			return 0;
        +#ifdef WITH_SSL
         		if (pwnt_table.ihashtable && hashresolv(&pwnt_table, param, &dummy, NULL))
         			return 0;
        +#endif
         #ifndef NOCRYPT
         		if (pwcr_table.ihashtable && hashresolv(&pwcr_table, param, cryptpw, NULL)) {
         			if (!strcmp(cryptpw, (char *)mycrypt(param->password, (unsigned char *)cryptpw, buf)))
        diff --git a/src/authradius.c b/src/authradius.c
        index 2ff0c4a..fc3fdae 100644
        --- a/src/authradius.c
        +++ b/src/authradius.c
        @@ -8,7 +8,7 @@
         
         #ifndef NORADIUS
         #include "proxy.h"
        -#include "libs/md5.h"
        +#include 
         
         #define AUTH_VECTOR_LEN         16
         #define MAX_STRING_LEN          254
        @@ -183,14 +183,19 @@ char *strNcpy(char *dest, const char *src, int n)
         	return dest;
         }
         
        +extern EVP_MD *md4;
        +extern EVP_MD *md5;
        +
        +
         void md5_calc(unsigned char *output, unsigned char *input,
         		     unsigned int inlen)
         {
        -	MD5_CTX	context;
        -
        -	MD5Init(&context);
        -	MD5Update(&context, input, inlen);
        -	MD5Final(output, &context);
        +	EVP_MD_CTX *ctx = EVP_MD_CTX_new();
        +	unsigned int len = 0;
        +	EVP_DigestInit_ex(ctx, md5, NULL);
        +	EVP_DigestUpdate(ctx, input, inlen);
        +	EVP_DigestFinal_ex(ctx, output, &len);
        +	EVP_MD_CTX_free(ctx);
         }
         
         
        diff --git a/src/blake2_compat.h b/src/blake2_compat.h
        new file mode 100644
        index 0000000..63b5d92
        --- /dev/null
        +++ b/src/blake2_compat.h
        @@ -0,0 +1,76 @@
        +#ifndef BLAKE2_COMPAT_H
        +#define BLAKE2_COMPAT_H
        +
        +#if defined(WITH_SSL)
        +#include 
        +#endif
        +
        +#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L
        +
        +#include 
        +#include 
        +
        +#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        +#include 
        +#include 
        +#endif
        +
        +/*
        + * OpenSSL 1.1.0+ BLAKE2b implementation.
        + * Provides the same streaming API as libs/blake2.h but uses EVP internally.
        + *
        + * OpenSSL 3.0+: uses OSSL_DIGEST_PARAM_SIZE for proper custom output sizes.
        + * OpenSSL 1.1.x: computes full 64-byte output and truncates in blake2b_final.
        + */
        +
        +typedef EVP_MD_CTX *blake2b_state;
        +
        +static int blake2b_init(blake2b_state *S, size_t outlen) {
        +    *S = EVP_MD_CTX_new();
        +    if (!*S) return -1;
        +
        +#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        +    size_t sz = outlen;
        +    OSSL_PARAM params[2];
        +    params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &sz);
        +    params[1] = OSSL_PARAM_construct_end();
        +
        +    if (!EVP_DigestInit_ex2(*S, EVP_blake2b512(), params)) {
        +#else
        +    (void)outlen;
        +    if (!EVP_DigestInit_ex(*S, EVP_blake2b512(), NULL)) {
        +#endif
        +        EVP_MD_CTX_free(*S);
        +        *S = NULL;
        +        return -1;
        +    }
        +    return 0;
        +}
        +
        +static int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
        +    if (inlen == 0) return 0;
        +    return EVP_DigestUpdate(*S, in, inlen) ? 0 : -1;
        +}
        +
        +static int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
        +#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        +    unsigned int len = 0;
        +    int ret = EVP_DigestFinal_ex(*S, out, &len) ? 0 : -1;
        +#else
        +    unsigned char tmp[64];
        +    unsigned int len = 0;
        +    int ret = EVP_DigestFinal_ex(*S, tmp, &len) ? 0 : -1;
        +    if (ret == 0) memcpy(out, tmp, outlen);
        +#endif
        +    EVP_MD_CTX_free(*S);
        +    *S = NULL;
        +    return ret;
        +}
        +
        +#else
        +
        +#include "libs/blake2.h"
        +
        +#endif
        +
        +#endif /* BLAKE2_COMPAT_H */
        diff --git a/src/conf.c b/src/conf.c
        index bad0d2e..5455b46 100644
        --- a/src/conf.c
        +++ b/src/conf.c
        @@ -7,6 +7,12 @@
         */
         
         #include "proxy.h"
        +#ifdef WITH_SSL
        +void ssl_install(void);
        +#endif
        +#ifdef WITH_PCRE
        +void pcre_install(void);
        +#endif
         #ifndef _WIN32
         #include 
         #include 
        @@ -526,9 +532,11 @@ static int h_users(int argc, unsigned char **argv){
                 if (arg[1] && arg[2] && arg[3] == ':') {
                     pw[1] = (char *)(arg + 4);
                     if (arg[1] == 'N' && arg[2] == 'T') {
        +#ifdef WITH_SSL
                         if (!pwnt_table.ihashtable && inithashtable(&pwnt_table, 16, 32, 1048576))
                             return 3;
                         hashadd(&pwnt_table, pw, &dummy, MAX_COUNTER_TIME);
        +#endif
                         continue;
                     }
                     if (arg[1] == 'C' && arg[2] == 'R') {
        @@ -1447,6 +1455,16 @@ static int h_authcache(int argc, unsigned char **argv){
         }
         
         static int h_plugin(int argc, unsigned char **argv){
        +#ifdef WITH_SSL
        +	if(argc >= 3 && !strcmp((char *)argv[2], "ssl_plugin")){
        +		return 0;
        +	}
        +#endif
        +#ifdef WITH_PCRE
        +	if(argc >= 3 && !strcmp((char *)argv[2], "pcre_plugin")){
        +		return 0;
        +	}
        +#endif
         #ifdef NOPLUGINS
         	return 999;
         #else
        @@ -1875,7 +1893,9 @@ void freeconf(struct extparam *confp){
          _3proxy_mutex_unlock(&connlim_mutex);
         
          destroyhashtable(&pw_table);
        +#ifdef WITH_SSL
          destroyhashtable(&pwnt_table);
        +#endif
          destroyhashtable(&pwcr_table);
         
          confp->logfunc = lognone;
        @@ -1946,6 +1966,12 @@ int reload (void){
         	int error = -2;
         
         	_3proxy_mutex_lock(&config_mutex);
        +#ifdef WITH_SSL
        +	ssl_install();
        +#endif
        +#ifdef WITH_PCRE
        +	pcre_install();
        +#endif
         	conf.paused++;
         	freeconf(&conf);
         	conf.paused++;
        diff --git a/src/hashtables.c b/src/hashtables.c
        index df8c5d9..1d2acd4 100644
        --- a/src/hashtables.c
        +++ b/src/hashtables.c
        @@ -1,11 +1,13 @@
         #include "proxy.h"
        -#include "libs/blake2.h"
        +#include "blake2_compat.h"
         
         
         static void char_index2hash(const struct hashtable *ht, void *index, uint8_t *hash){
        -    char* name = index;
        +    blake2b_state S;
         
        -    blake2b(hash, ht->hash_size, index, strlen((const char*)index), NULL, 0);
        +    blake2b_init(&S, ht->hash_size);
        +    blake2b_update(&S, index, strlen((const char*)index) + 1);
        +    blake2b_final(&S, hash, ht->hash_size);
         }
         
         static void param2hash_add(const struct hashtable *ht, void *index, uint8_t *hash){
        @@ -36,7 +38,11 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
         
         static void user2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
             struct clientparam *param = (struct clientparam *)index;
        -    blake2b(hash, ht->hash_size, param->username, strlen((const char *)param->username), NULL, 0);
        +    blake2b_state S;
        +
        +    blake2b_init(&S, ht->hash_size);
        +    blake2b_update(&S, param->username, strlen((const char *)param->username) + 1);
        +    blake2b_final(&S, hash, ht->hash_size);
         }
         
         static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash){
        @@ -80,14 +86,16 @@ static void pwnt2hash_add(const struct hashtable *ht, void *index, uint8_t *hash
         }
         
         
        +#ifdef WITH_SSL
         static void pwnt2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
             struct clientparam *param  = (struct clientparam *)index;
        -    unsigned char pass[40];    
        +    unsigned char pass[40];
             char *pw[2] = {(char *)param->username, (char *)pass};
         
             ntpwdhash(pass, param->password, 1);
             pwnt2hash_add(ht, pw, hash);
         }
        +#endif
         
         
         
        @@ -95,5 +103,7 @@ struct hashtable dns_table = {char_index2hash, char_index2hash, 4, 12};
         struct hashtable dns6_table = {char_index2hash, char_index2hash, 16, 12};
         struct hashtable auth_table = {param2hash_add, param2hash_search, sizeof(struct authcache), 12};
         struct hashtable pw_table = {pw2hash_add, pw2hash_search, 0, 12};
        +#ifdef WITH_SSL
         struct hashtable pwnt_table = {pwnt2hash_add, pwnt2hash_search, 0, 12};
        +#endif
         struct hashtable pwcr_table = {char_index2hash, user2hash_search, 64, 12};
        diff --git a/src/libs/md4.c b/src/libs/md4.c
        deleted file mode 100644
        index e09d340..0000000
        --- a/src/libs/md4.c
        +++ /dev/null
        @@ -1,290 +0,0 @@
        -/*
        - * md4c.c	MD4 message-digest algorithm
        - *
        - *   License to copy and use this software is granted provided that it
        - *   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
        - *   Algorithm" in all material mentioning or referencing this software
        - *   or this function.
        - *
        - *   License is also granted to make and use derivative works provided
        - *   that such works are identified as "derived from the RSA Data
        - *   Security, Inc. MD4 Message-Digest Algorithm" in all material
        - *   mentioning or referencing the derived work.
        - *
        - *   RSA Data Security, Inc. makes no representations concerning either
        - *   the merchantability of this software or the suitability of this
        - *   software for any particular purpose. It is provided "as is"
        - *   without express or implied warranty of any kind.
        - *
        - *   These notices must be retained in any copies of any part of this
        - *   documentation and/or software.
        - *
        - * Copyright 1990,1991,1992  RSA Data Security, Inc.
        - */
        -
        -
        -#include "md4.h"
        -
        -/* Constants for MD4Transform routine.
        - */
        -#define S11 3
        -#define S12 7
        -#define S13 11
        -#define S14 19
        -#define S21 3
        -#define S22 5
        -#define S23 9
        -#define S24 13
        -#define S31 3
        -#define S32 9
        -#define S33 11
        -#define S34 15
        -
        -static void MD4Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
        -static void Encode PROTO_LIST
        -  ((unsigned char *, UINT4 *, unsigned int));
        -static void Decode PROTO_LIST
        -  ((UINT4 *, unsigned char *, unsigned int));
        -static void MD4_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
        -static void MD4_memset PROTO_LIST ((POINTER, int, unsigned int));
        -
        -static unsigned char PADDING[64] = {
        -  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        -  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        -  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        -};
        -
        -/* F, G and H are basic MD4 functions.
        - */
        -#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
        -#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
        -#define H(x, y, z) ((x) ^ (y) ^ (z))
        -
        -/* ROTATE_LEFT rotates x left n bits.
        - */
        -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
        -
        -/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
        -/* Rotation is separate from addition to prevent recomputation */
        -
        -#define FF(a, b, c, d, x, s) { \
        -    (a) += F ((b), (c), (d)) + (x); \
        -    (a) = ROTATE_LEFT ((a), (s)); \
        -  }
        -#define GG(a, b, c, d, x, s) { \
        -    (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
        -    (a) = ROTATE_LEFT ((a), (s)); \
        -  }
        -#define HH(a, b, c, d, x, s) { \
        -    (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
        -    (a) = ROTATE_LEFT ((a), (s)); \
        -  }
        -
        -void md4_calc(unsigned char *output, unsigned char *input, unsigned inlen)
        -{
        -	MD4_CTX	context;
        -
        -	MD4Init(&context);
        -	MD4Update(&context, input, inlen);
        -	MD4Final(output, &context);
        -}
        -
        -/* MD4 initialization. Begins an MD4 operation, writing a new context.
        - */
        -void MD4Init ( MD4_CTX *context)
        -{
        -  context->count[0] = context->count[1] = 0;
        -
        -  /* Load magic initialization constants.
        -   */
        -  context->state[0] = 0x67452301;
        -  context->state[1] = 0xefcdab89;
        -  context->state[2] = 0x98badcfe;
        -  context->state[3] = 0x10325476;
        -}
        -
        -/* MD4 block update operation. Continues an MD4 message-digest
        -     operation, processing another message block, and updating the
        -     context.
        - */
        -void MD4Update (MD4_CTX *context, unsigned char *input, unsigned inputLen)
        -{
        -  unsigned int i, index, partLen;
        -
        -  /* Compute number of bytes mod 64 */
        -  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
        -  /* Update number of bits */
        -  if ((context->count[0] += ((UINT4)inputLen << 3))
        -      < ((UINT4)inputLen << 3))
        -    context->count[1]++;
        -  context->count[1] += ((UINT4)inputLen >> 29);
        -
        -  partLen = 64 - index;
        -
        -  /* Transform as many times as possible.
        -   */
        -  if (inputLen >= partLen) {
        -    MD4_memcpy
        -      ((POINTER)&context->buffer[index], (POINTER)input, partLen);
        -    MD4Transform (context->state, context->buffer);
        -
        -    for (i = partLen; i + 63 < inputLen; i += 64)
        -      MD4Transform (context->state, &input[i]);
        -
        -    index = 0;
        -  }
        -  else
        -    i = 0;
        -
        -  /* Buffer remaining input */
        -  MD4_memcpy
        -    ((POINTER)&context->buffer[index], (POINTER)&input[i],
        -     inputLen-i);
        -}
        -
        -/* MD4 finalization. Ends an MD4 message-digest operation, writing the
        -     the message digest and zeroizing the context.
        - */
        -void MD4Final (unsigned char digest[16],  MD4_CTX *context)
        -{
        -  unsigned char bits[8];
        -  unsigned int index, padLen;
        -
        -  /* Save number of bits */
        -  Encode (bits, context->count, 8);
        -
        -  /* Pad out to 56 mod 64.
        -   */
        -  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
        -  padLen = (index < 56) ? (56 - index) : (120 - index);
        -  MD4Update (context, PADDING, padLen);
        -
        -  /* Append length (before padding) */
        -  MD4Update (context, bits, 8);
        -  /* Store state in digest */
        -  Encode (digest, context->state, 16);
        -
        -  /* Zeroize sensitive information.
        -   */
        -  MD4_memset ((POINTER)context, 0, sizeof (*context));
        -}
        -
        -/* MD4 basic transformation. Transforms state based on block.
        - */
        -static void MD4Transform (UINT4 state[4], unsigned char block[64])
        -{
        -  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
        -
        -  Decode (x, block, 64);
        -
        -  /* Round 1 */
        -  FF (a, b, c, d, x[ 0], S11); /* 1 */
        -  FF (d, a, b, c, x[ 1], S12); /* 2 */
        -  FF (c, d, a, b, x[ 2], S13); /* 3 */
        -  FF (b, c, d, a, x[ 3], S14); /* 4 */
        -  FF (a, b, c, d, x[ 4], S11); /* 5 */
        -  FF (d, a, b, c, x[ 5], S12); /* 6 */
        -  FF (c, d, a, b, x[ 6], S13); /* 7 */
        -  FF (b, c, d, a, x[ 7], S14); /* 8 */
        -  FF (a, b, c, d, x[ 8], S11); /* 9 */
        -  FF (d, a, b, c, x[ 9], S12); /* 10 */
        -  FF (c, d, a, b, x[10], S13); /* 11 */
        -  FF (b, c, d, a, x[11], S14); /* 12 */
        -  FF (a, b, c, d, x[12], S11); /* 13 */
        -  FF (d, a, b, c, x[13], S12); /* 14 */
        -  FF (c, d, a, b, x[14], S13); /* 15 */
        -  FF (b, c, d, a, x[15], S14); /* 16 */
        -
        -  /* Round 2 */
        -  GG (a, b, c, d, x[ 0], S21); /* 17 */
        -  GG (d, a, b, c, x[ 4], S22); /* 18 */
        -  GG (c, d, a, b, x[ 8], S23); /* 19 */
        -  GG (b, c, d, a, x[12], S24); /* 20 */
        -  GG (a, b, c, d, x[ 1], S21); /* 21 */
        -  GG (d, a, b, c, x[ 5], S22); /* 22 */
        -  GG (c, d, a, b, x[ 9], S23); /* 23 */
        -  GG (b, c, d, a, x[13], S24); /* 24 */
        -  GG (a, b, c, d, x[ 2], S21); /* 25 */
        -  GG (d, a, b, c, x[ 6], S22); /* 26 */
        -  GG (c, d, a, b, x[10], S23); /* 27 */
        -  GG (b, c, d, a, x[14], S24); /* 28 */
        -  GG (a, b, c, d, x[ 3], S21); /* 29 */
        -  GG (d, a, b, c, x[ 7], S22); /* 30 */
        -  GG (c, d, a, b, x[11], S23); /* 31 */
        -  GG (b, c, d, a, x[15], S24); /* 32 */
        -
        -  /* Round 3 */
        -  HH (a, b, c, d, x[ 0], S31); /* 33 */
        -  HH (d, a, b, c, x[ 8], S32); /* 34 */
        -  HH (c, d, a, b, x[ 4], S33); /* 35 */
        -  HH (b, c, d, a, x[12], S34); /* 36 */
        -  HH (a, b, c, d, x[ 2], S31); /* 37 */
        -  HH (d, a, b, c, x[10], S32); /* 38 */
        -  HH (c, d, a, b, x[ 6], S33); /* 39 */
        -  HH (b, c, d, a, x[14], S34); /* 40 */
        -  HH (a, b, c, d, x[ 1], S31); /* 41 */
        -  HH (d, a, b, c, x[ 9], S32); /* 42 */
        -  HH (c, d, a, b, x[ 5], S33); /* 43 */
        -  HH (b, c, d, a, x[13], S34); /* 44 */
        -  HH (a, b, c, d, x[ 3], S31); /* 45 */
        -  HH (d, a, b, c, x[11], S32); /* 46 */
        -  HH (c, d, a, b, x[ 7], S33); /* 47 */
        -  HH (b, c, d, a, x[15], S34); /* 48 */
        -
        -  state[0] += a;
        -  state[1] += b;
        -  state[2] += c;
        -  state[3] += d;
        -
        -  /* Zeroize sensitive information.
        -   */
        -  MD4_memset ((POINTER)x, 0, sizeof (x));
        -}
        -
        -/* Encodes input (UINT4) into output (unsigned char). Assumes len is
        -     a multiple of 4.
        - */
        -static void Encode (unsigned char *output, UINT4 *input, unsigned len)
        -{
        -  unsigned int i, j;
        -
        -  for (i = 0, j = 0; j < len; i++, j += 4) {
        -    output[j] = (unsigned char)(input[i] & 0xff);
        -    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
        -    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
        -    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
        -  }
        -}
        -
        -/* Decodes input (unsigned char) into output (UINT4). Assumes len is
        -     a multiple of 4.
        - */
        -static void Decode (UINT4 *output, unsigned char *input, unsigned len)
        -
        -{
        -  unsigned int i, j;
        -
        -  for (i = 0, j = 0; j < len; i++, j += 4)
        -    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
        -      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
        -}
        -
        -/* Note: Replace "for loop" with standard memcpy if possible.
        - */
        -static void MD4_memcpy (POINTER output, POINTER input, unsigned len)
        -{
        -  unsigned int i;
        -
        -  for (i = 0; i < len; i++)
        -    output[i] = input[i];
        -}
        -
        -/* Note: Replace "for loop" with standard memset if possible.
        - */
        -static void MD4_memset (POINTER output, int value, unsigned len)
        -{
        -  unsigned int i;
        -
        -  for (i = 0; i < len; i++)
        -    ((char *)output)[i] = (char)value;
        -}
        diff --git a/src/libs/md4.h b/src/libs/md4.h
        deleted file mode 100644
        index de07d79..0000000
        --- a/src/libs/md4.h
        +++ /dev/null
        @@ -1,83 +0,0 @@
        -#ifndef _LRAD_MD4_H
        -#define _LRAD_MD4_H
        -
        -#ifndef _LRAD_PROTO_H
        -#define _LRAD_PROTO_H
        -/* GLOBAL.H - RSAREF types and constants
        - */
        -
        -/* PROTOTYPES should be set to one if and only if the compiler supports
        -  function argument prototyping.
        -  The following makes PROTOTYPES default to 0 if it has not already
        -  been defined with C compiler flags.
        - */
        -#ifndef PROTOTYPES
        -#  if __STDC__
        -#    define PROTOTYPES 1
        -#  else
        -#    define PROTOTYPES 0
        -#  endif
        -#endif
        -
        -/* POINTER defines a generic pointer type */
        -typedef unsigned char *POINTER;
        -#define _POINTER_T
        -
        -/* UINT2 defines a two byte word */
        -typedef unsigned short int UINT2;
        -#define _UINT2_T
        -
        -/* UINT4 defines a four byte word */
        -typedef unsigned int UINT4;
        -#define _UINT4_T
        -
        -/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
        -   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
        -  returns an empty list.
        - */
        -#if PROTOTYPES
        -#define PROTO_LIST(list) list
        -#else
        -#define PROTO_LIST(list) ()
        -#endif
        -#endif /* _LRAD_PROTO_H */
        -
        -/* MD4.H - header file for MD4C.C
        - */
        -
        -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
        -   rights reserved.
        -
        -   License to copy and use this software is granted provided that it
        -   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
        -   Algorithm" in all material mentioning or referencing this software
        -   or this function.
        -
        -   License is also granted to make and use derivative works provided
        -   that such works are identified as "derived from the RSA Data
        -   Security, Inc. MD4 Message-Digest Algorithm" in all material
        -   mentioning or referencing the derived work.
        -
        -   RSA Data Security, Inc. makes no representations concerning either
        -   the merchantability of this software or the suitability of this
        -   software for any particular purpose. It is provided "as is"
        -   without express or implied warranty of any kind.
        -
        -   These notices must be retained in any copies of any part of this
        -   documentation and/or software.
        - */
        -
        -/* MD4 context. */
        -typedef struct {
        -  UINT4 state[4];                                   /* state (ABCD) */
        -  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
        -  unsigned char buffer[64];                         /* input buffer */
        -} MD4_CTX;
        -
        -void md4_calc (unsigned char *, unsigned char *, unsigned int);
        -void MD4Init PROTO_LIST ((MD4_CTX *));
        -void MD4Update PROTO_LIST
        -  ((MD4_CTX *, unsigned char *, unsigned int));
        -void MD4Final PROTO_LIST ((unsigned char [16], MD4_CTX *));
        -
        -#endif /* _LRAD_MD4_H */
        diff --git a/src/libs/md5.c b/src/libs/md5.c
        deleted file mode 100644
        index 09d8559..0000000
        --- a/src/libs/md5.c
        +++ /dev/null
        @@ -1,325 +0,0 @@
        -/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
        - */
        -
        -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
        -rights reserved.
        -
        -License to copy and use this software is granted provided that it
        -is identified as the "RSA Data Security, Inc. MD5 Message-Digest
        -Algorithm" in all material mentioning or referencing this software
        -or this function.
        -
        -License is also granted to make and use derivative works provided
        -that such works are identified as "derived from the RSA Data
        -Security, Inc. MD5 Message-Digest Algorithm" in all material
        -mentioning or referencing the derived work.
        -
        -RSA Data Security, Inc. makes no representations concerning either
        -the merchantability of this software or the suitability of this
        -software for any particular purpose. It is provided "as is"
        -without express or implied warranty of any kind.
        -
        -These notices must be retained in any copies of any part of this
        -documentation and/or software.
        - */
        -
        -#include "md5.h"
        -
        -/* Constants for MD5Transform routine.
        - */
        -#define S11 7
        -#define S12 12
        -#define S13 17
        -#define S14 22
        -#define S21 5
        -#define S22 9
        -#define S23 14
        -#define S24 20
        -#define S31 4
        -#define S32 11
        -#define S33 16
        -#define S34 23
        -#define S41 6
        -#define S42 10
        -#define S43 15
        -#define S44 21
        -
        -void librad_md5_calc(unsigned char *output, unsigned char *input,
        -		     unsigned int inputlen);
        -static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
        -static void Encode PROTO_LIST
        -  ((unsigned char *, UINT4 *, unsigned int));
        -static void Decode PROTO_LIST
        -  ((UINT4 *, const unsigned char *, unsigned int));
        -static void MD5_memcpy PROTO_LIST ((POINTER, CONSTPOINTER, unsigned int));
        -static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
        -
        -static const unsigned char PADDING[64] = {
        -  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        -  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        -  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        -};
        -
        -/* F, G, H and I are basic MD5 functions.
        - */
        -#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
        -#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
        -#define H(x, y, z) ((x) ^ (y) ^ (z))
        -#define I(x, y, z) ((y) ^ ((x) | (~z)))
        -
        -/* ROTATE_LEFT rotates x left n bits.
        - */
        -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
        -
        -/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
        -Rotation is separate from addition to prevent recomputation.
        - */
        -#define FF(a, b, c, d, x, s, ac) { \
        - (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
        - (a) = ROTATE_LEFT ((a), (s)); \
        - (a) += (b); \
        -  }
        -#define GG(a, b, c, d, x, s, ac) { \
        - (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
        - (a) = ROTATE_LEFT ((a), (s)); \
        - (a) += (b); \
        -  }
        -#define HH(a, b, c, d, x, s, ac) { \
        - (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
        - (a) = ROTATE_LEFT ((a), (s)); \
        - (a) += (b); \
        -  }
        -#define II(a, b, c, d, x, s, ac) { \
        - (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
        - (a) = ROTATE_LEFT ((a), (s)); \
        - (a) += (b); \
        -  }
        -
        -void librad_md5_calc(unsigned char *output, unsigned char *input,
        -		     unsigned int inlen)
        -{
        -	MD5_CTX	context;
        -
        -	MD5Init(&context);
        -	MD5Update(&context, input, inlen);
        -	MD5Final(output, &context);
        -}
        -
        -/* MD5 initialization. Begins an MD5 operation, writing a new context.
        - */
        -void MD5Init (MD5_CTX *context)
        -{
        -  context->count[0] = context->count[1] = 0;
        -  /* Load magic initialization constants.
        -*/
        -  context->state[0] = 0x67452301;
        -  context->state[1] = 0xefcdab89;
        -  context->state[2] = 0x98badcfe;
        -  context->state[3] = 0x10325476;
        -}
        -
        -/* MD5 block update operation. Continues an MD5 message-digest
        -  operation, processing another message block, and updating the
        -  context.
        - */
        -void MD5Update (MD5_CTX *context, const unsigned char *input, unsigned inputLen)
        -{
        -  unsigned int i, index, partLen;
        -
        -  /* Compute number of bytes mod 64 */
        -  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
        -
        -  /* Update number of bits */
        -  if ((context->count[0] += ((UINT4)inputLen << 3))
        -   < ((UINT4)inputLen << 3))
        - context->count[1]++;
        -  context->count[1] += ((UINT4)inputLen >> 29);
        -
        -  partLen = 64 - index;
        -
        -  /* Transform as many times as possible.
        -*/
        -  if (inputLen >= partLen) {
        - MD5_memcpy
        -   ((POINTER)&context->buffer[index], (CONSTPOINTER)input, partLen);
        - MD5Transform (context->state, context->buffer);
        -
        - for (i = partLen; i + 63 < inputLen; i += 64)
        -   MD5Transform (context->state, &input[i]);
        -
        - index = 0;
        -  }
        -  else
        - i = 0;
        -
        -  /* Buffer remaining input */
        -  MD5_memcpy
        - ((POINTER)&context->buffer[index], (CONSTPOINTER)&input[i],
        -  inputLen-i);
        -}
        -
        -/* MD5 finalization. Ends an MD5 message-digest operation, writing the
        -  the message digest and zeroizing the context.
        - */
        -void MD5Final (unsigned char digest[16], MD5_CTX *context)
        -{
        -  unsigned char bits[8];
        -  unsigned int index, padLen;
        -
        -  /* Save number of bits */
        -  Encode (bits, context->count, 8);
        -
        -  /* Pad out to 56 mod 64.
        -*/
        -  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
        -  padLen = (index < 56) ? (56 - index) : (120 - index);
        -  MD5Update (context, PADDING, padLen);
        -
        -  /* Append length (before padding) */
        -  MD5Update (context, bits, 8);
        -
        -  /* Store state in digest */
        -  Encode (digest, context->state, 16);
        -
        -  /* Zeroize sensitive information.
        -*/
        -  MD5_memset ((POINTER)context, 0, sizeof (*context));
        -}
        -
        -/* MD5 basic transformation. Transforms state based on block.
        - */
        -static void MD5Transform (UINT4 state[4], const unsigned char block[64])
        -{
        -  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
        -
        -  Decode (x, block, 64);
        -
        -  /* Round 1 */
        -  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
        -  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
        -  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
        -  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
        -  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
        -  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
        -  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
        -  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
        -  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
        -  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
        -  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
        -  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
        -  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
        -  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
        -  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
        -  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
        -
        - /* Round 2 */
        -  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
        -  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
        -  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
        -  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
        -  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
        -  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
        -  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
        -  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
        -  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
        -  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
        -  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
        -  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
        -  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
        -  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
        -  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
        -  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
        -
        -  /* Round 3 */
        -  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
        -  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
        -  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
        -  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
        -  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
        -  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
        -  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
        -  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
        -  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
        -  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
        -  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
        -  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
        -  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
        -  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
        -  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
        -  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
        -
        -  /* Round 4 */
        -  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
        -  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
        -  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
        -  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
        -  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
        -  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
        -  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
        -  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
        -  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
        -  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
        -  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
        -  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
        -  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
        -  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
        -  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
        -  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
        -
        -  state[0] += a;
        -  state[1] += b;
        -  state[2] += c;
        -  state[3] += d;
        -
        -  /* Zeroize sensitive information.
        -*/
        -  MD5_memset ((POINTER)x, 0, sizeof (x));
        -}
        -
        -/* Encodes input (UINT4) into output (unsigned char). Assumes len is
        -  a multiple of 4.
        - */
        -static void Encode (unsigned char *output, UINT4 *input, unsigned len)
        -{
        -  unsigned int i, j;
        -
        -  for (i = 0, j = 0; j < len; i++, j += 4) {
        - output[j] = (unsigned char)(input[i] & 0xff);
        - output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
        - output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
        - output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
        -  }
        -}
        -
        -/* Decodes input (unsigned char) into output (UINT4). Assumes len is
        -  a multiple of 4.
        - */
        -static void Decode (UINT4 *output, const unsigned char *input, unsigned len)
        -{
        -  unsigned int i, j;
        -
        -  for (i = 0, j = 0; j < len; i++, j += 4)
        - output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
        -   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
        -}
        -
        -/* Note: Replace "for loop" with standard memcpy if possible.
        - */
        -
        -static void MD5_memcpy (POINTER output, CONSTPOINTER input, unsigned len)
        -{
        -  unsigned int i;
        -
        -  for (i = 0; i < len; i++)
        - output[i] = input[i];
        -}
        -
        -/* Note: Replace "for loop" with standard memset if possible.
        - */
        -static void MD5_memset (POINTER output, int value, unsigned len)
        -{
        -  unsigned int i;
        -
        -  for (i = 0; i < len; i++)
        - ((char *)output)[i] = (char)value;
        -}
        diff --git a/src/libs/md5.h b/src/libs/md5.h
        deleted file mode 100644
        index 9209cde..0000000
        --- a/src/libs/md5.h
        +++ /dev/null
        @@ -1,94 +0,0 @@
        -#ifndef _LRAD_MD5_H
        -#define _LRAD_MD5_H
        -
        -#ifndef _LRAD_PROTO_H
        -#define _LRAD_PROTO_H
        -/* GLOBAL.H - RSAREF types and constants
        - */
        -
        -/* PROTOTYPES should be set to one if and only if the compiler supports
        -  function argument prototyping.
        -  The following makes PROTOTYPES default to 0 if it has not already
        -  been defined with C compiler flags.
        - */
        -#ifndef PROTOTYPES
        -#  if __STDC__
        -#    define PROTOTYPES 1
        -#  else
        -#    define PROTOTYPES 0
        -#  endif
        -#endif
        -
        -/* POINTER defines a generic pointer type */
        -#ifndef _POINTER_T
        -typedef unsigned char *POINTER;
        -#endif
        -typedef const unsigned char *CONSTPOINTER;
        -
        -/* UINT2 defines a two byte word */
        -#ifndef _UINT2_T
        -typedef unsigned short int UINT2;
        -#endif
        -
        -/* UINT4 defines a four byte word */
        -#ifndef _UINT4_T
        -typedef unsigned int UINT4;
        -#endif
        -
        -/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
        -   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
        -  returns an empty list.
        - */
        -#if PROTOTYPES
        -#define PROTO_LIST(list) list
        -#else
        -#define PROTO_LIST(list) ()
        -#endif
        -#endif /* _LRAD_PROTO_H */
        -
        -/*
        - *  FreeRADIUS defines to ensure globally unique MD5 function names,
        - *  so that we don't pick up vendor-specific broken MD5 libraries.
        - */
        -#define MD5_CTX		librad_MD5_CTX
        -#define MD5Init		librad_MD5Init
        -#define MD5Update	librad_MD5Update
        -#define MD5Final       	librad_MD5Final
        -
        -/* MD5.H - header file for MD5C.C
        - */
        -
        -/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
        -rights reserved.
        -
        -License to copy and use this software is granted provided that it
        -is identified as the "RSA Data Security, Inc. MD5 Message-Digest
        -Algorithm" in all material mentioning or referencing this software
        -or this function.
        -
        -License is also granted to make and use derivative works provided
        -that such works are identified as "derived from the RSA Data
        -Security, Inc. MD5 Message-Digest Algorithm" in all material
        -mentioning or referencing the derived work.
        -
        -RSA Data Security, Inc. makes no representations concerning either
        -the merchantability of this software or the suitability of this
        -software for any particular purpose. It is provided "as is"
        -without express or implied warranty of any kind.
        -
        -These notices must be retained in any copies of any part of this
        -documentation and/or software.
        - */
        -
        -/* MD5 context. */
        -typedef struct {
        -  UINT4 state[4];                                   /* state (ABCD) */
        -  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
        -  unsigned char buffer[64];                         /* input buffer */
        -} MD5_CTX;
        -
        -void MD5Init PROTO_LIST ((MD5_CTX *));
        -void MD5Update PROTO_LIST
        -  ((MD5_CTX *, const unsigned char *, unsigned int));
        -void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
        -#endif /* _LRAD_MD5_H */
        diff --git a/src/plugins/PCREPlugin/pcre_plugin.c b/src/pcre.c
        similarity index 97%
        rename from src/plugins/PCREPlugin/pcre_plugin.c
        rename to src/pcre.c
        index fa6438c..dfaf921 100644
        --- a/src/plugins/PCREPlugin/pcre_plugin.c
        +++ b/src/pcre.c
        @@ -5,7 +5,7 @@
         
         */
         
        -#include "../../structures.h"
        +#include "structures.h"
         #include 
         #define PCRE2_CODE_UNIT_WIDTH 8
         #define PCRE2_STATIC
        @@ -261,7 +261,7 @@ static int h_pcre(int argc, unsigned char **argv){
         	PCRE2_SIZE erroffset;
         	struct pcre_filter_data *flt;
         	struct filter *newf;
        -	char *replace = NULL;
        +	char * replace = NULL;
         
         	if(!strncmp((char *)argv[2], "allow",5)) action = PASS;
         	else if(!strncmp((char *)argv[2], "deny",4)) action = REJECT;
        @@ -368,7 +368,7 @@ static int h_pcre_rewrite(int argc, unsigned char **argv){
         	PCRE2_SIZE erroffset;
         	struct pcre_filter_data *flt;
         	struct filter *newf;
        -	char *replace = NULL;
        +	char * replace = NULL;
         
         	if(!strncmp((char *)argv[2], "allow",5)) action = PASS;
         	else if(!strncmp((char *)argv[2], "deny",4)) action = REJECT;
        @@ -503,17 +503,11 @@ static struct symbol regexp_symbols[] = {
         	{NULL, "pcre_options", (void *)&pcre_options},
         };
         
        -#ifdef WATCOM
        -#pragma aux pcre_plugin "*" parm caller [ ] value struct float struct routine [eax] modify [eax ecx edx]
        -#undef PLUGINCALL
        -#define PLUGINCALL
        -#endif
         
        -PLUGINAPI int PLUGINCALL pcre_plugin (struct pluginlink * pluginlink,
        -					 int argc, char** argv){
        +void pcre_install(void){
         
         	struct filter *flt, *tmpflt;
        -	pl = pluginlink;
        +	pl = &pluginlink;
         	pcre_options = 0;
         	if(!pcre_loaded){
         		pcre_loaded = 1;
        @@ -537,9 +531,8 @@ PLUGINAPI int PLUGINCALL pcre_plugin (struct pluginlink * pluginlink,
         		}
         	}
         	pcre_last_filter = NULL;
        -	return 0;
        -
          }
        +
         #ifdef  __cplusplus
         }
         #endif
        diff --git a/src/pcre.h b/src/pcre.h
        new file mode 100644
        index 0000000..539b7f6
        --- /dev/null
        +++ b/src/pcre.h
        @@ -0,0 +1,6 @@
        +#ifndef __pcre_h__
        +#define __pcre_h__
        +
        +void pcre_install(void);
        +
        +#endif /* __pcre_h__ */
        diff --git a/src/plugins/PCREPlugin/CMakeLists.txt b/src/plugins/PCREPlugin/CMakeLists.txt
        deleted file mode 100644
        index f93725c..0000000
        --- a/src/plugins/PCREPlugin/CMakeLists.txt
        +++ /dev/null
        @@ -1,20 +0,0 @@
        -# PCREPlugin - requires PCRE2
        -
        -if(NOT PCRE2_FOUND)
        -    message(STATUS "PCREPlugin requires PCRE2, skipping")
        -    return()
        -endif()
        -
        -add_3proxy_plugin(PCREPlugin
        -    SOURCES pcre_plugin.c
        -    COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8
        -)
        -
        -if(TARGET PCRE2::PCRE2)
        -    target_link_libraries(PCREPlugin PRIVATE PCRE2::PCRE2)
        -else()
        -    target_link_libraries(PCREPlugin PRIVATE ${PCRE2_LIBRARIES})
        -    if(PCRE2_INCLUDE_DIRS)
        -        target_include_directories(PCREPlugin PRIVATE ${PCRE2_INCLUDE_DIRS})
        -    endif()
        -endif()
        diff --git a/src/plugins/PCREPlugin/Makefile b/src/plugins/PCREPlugin/Makefile
        deleted file mode 100644
        index e7c51ad..0000000
        --- a/src/plugins/PCREPlugin/Makefile
        +++ /dev/null
        @@ -1 +0,0 @@
        -include Makefile.var
        diff --git a/src/plugins/PCREPlugin/Makefile.inc b/src/plugins/PCREPlugin/Makefile.inc
        deleted file mode 100644
        index 455ee34..0000000
        --- a/src/plugins/PCREPlugin/Makefile.inc
        +++ /dev/null
        @@ -1,8 +0,0 @@
        -all: $(BUILDDIR)PCREPlugin$(DLSUFFICS)
        -
        -pcre_plugin$(OBJSUFFICS): pcre_plugin.c
        -	$(CC) $(DCFLAGS) $(CFLAGS) pcre_plugin.c
        -
        -$(BUILDDIR)PCREPlugin$(DLSUFFICS): pcre_plugin$(OBJSUFFICS)
        -	$(LN) $(LNOUT)../../$(BUILDDIR)PCREPlugin$(DLSUFFICS) $(LDFLAGS) $(DLFLAGS) pcre_plugin$(OBJSUFFICS) $(LIBSPREFIX)pcre2-8$(LIBSSUFFIX)
        -
        diff --git a/src/plugins/SSLPlugin/CMakeLists.txt b/src/plugins/SSLPlugin/CMakeLists.txt
        deleted file mode 100644
        index 30b4e13..0000000
        --- a/src/plugins/SSLPlugin/CMakeLists.txt
        +++ /dev/null
        @@ -1,17 +0,0 @@
        -# SSLPlugin - requires OpenSSL
        -
        -if(NOT TARGET OpenSSL::SSL)
        -    message(STATUS "SSLPlugin requires OpenSSL, skipping")
        -    return()
        -endif()
        -
        -add_3proxy_plugin(SSLPlugin
        -    SOURCES
        -        ssl_plugin.c
        -        my_ssl.c
        -    LIBRARIES
        -        OpenSSL::SSL
        -        OpenSSL::Crypto
        -    COMPILE_DEFINITIONS
        -        WITH_SSL
        -)
        diff --git a/src/plugins/SSLPlugin/Makefile b/src/plugins/SSLPlugin/Makefile
        deleted file mode 100644
        index e7c51ad..0000000
        --- a/src/plugins/SSLPlugin/Makefile
        +++ /dev/null
        @@ -1 +0,0 @@
        -include Makefile.var
        diff --git a/src/plugins/SSLPlugin/Makefile.inc b/src/plugins/SSLPlugin/Makefile.inc
        deleted file mode 100644
        index 1afc984..0000000
        --- a/src/plugins/SSLPlugin/Makefile.inc
        +++ /dev/null
        @@ -1,14 +0,0 @@
        -all: $(BUILDDIR)SSLPlugin$(DLSUFFICS)
        -
        -
        -
        -ssl_plugin$(OBJSUFFICS): ssl_plugin.c
        -	$(CC) $(DCFLAGS) $(CFLAGS) ssl_plugin.c
        -
        -my_ssl$(OBJSUFFICS): my_ssl.c
        -	$(CC) $(DCFLAGS) $(CFLAGS) my_ssl.c
        -
        -
        -$(BUILDDIR)SSLPlugin$(DLSUFFICS): ssl_plugin$(OBJSUFFICS) my_ssl$(OBJSUFFICS)
        -	$(LN) $(LNOUT)../../$(BUILDDIR)SSLPlugin$(DLSUFFICS) $(LDFLAGS) $(DLFLAGS) ssl_plugin$(OBJSUFFICS) my_ssl$(OBJSUFFICS) $(LIBS) 
        -	
        \ No newline at end of file
        diff --git a/src/proxy.h b/src/proxy.h
        index a692a57..2a67daa 100644
        --- a/src/proxy.h
        +++ b/src/proxy.h
        @@ -15,6 +15,12 @@
         #ifndef _3PROXY_H_
         #define _3PROXY_H_
         #include "version.h"
        +
        +#ifndef WITH_SSL
        +#ifndef NORADIUS
        +#define NORADIUS
        +#endif
        +#endif
         #include 
         #include 
         #include 
        @@ -169,6 +175,7 @@ extern struct extparam conf;
         extern int timeouts[12];
         
         int sockmap(struct clientparam * param, int timeo, int usesplice);
        +int udpsockmap(struct clientparam * param, int timeo);
         int socksend(struct clientparam *param, SOCKET sock, unsigned char * buf, int bufsize, int to);
         int socksendto(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
         int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
        @@ -232,7 +239,9 @@ extern int paused;
         extern int demon;
         
         unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf);
        +#ifdef WITH_SSL
         unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int tohex);
        +#endif
         int de64 (const unsigned char *in, unsigned char *out, int maxlen);
         unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen);
         void tohex(unsigned char *in, unsigned char *out, int len);
        diff --git a/src/plugins/SSLPlugin/ssl_plugin.c b/src/ssl.c
        similarity index 96%
        rename from src/plugins/SSLPlugin/ssl_plugin.c
        rename to src/ssl.c
        index 8d5a4ed..d2a1bd6 100644
        --- a/src/plugins/SSLPlugin/ssl_plugin.c
        +++ b/src/ssl.c
        @@ -5,23 +5,19 @@
         
         */
         
        -#include "../../structures.h"
        +#include "structures.h"
         #include 
         #include 
         #include 
         #include 
         #include 
        -#include "../../proxy.h"
        -#include "my_ssl.h"
        +#include "proxy.h"
        +#include "ssl.h"
         
         #ifndef _WIN32
         #define WINAPI
         #endif
         
        -#ifdef  __cplusplus
        -extern "C" {
        -#endif
        -
         #ifndef isnumber
         #define isnumber(i_n_arg) ((i_n_arg>='0')&&(i_n_arg<='9'))
         #endif
        @@ -62,11 +58,6 @@ static char * server_cipher_list = NULL;
         static char * client_sni = NULL;
         static int client_mode = 0;
         
        -typedef struct _ssl_conn {
        -	SSL_CTX *ctx;
        -	SSL *ssl;
        -} ssl_conn;
        -
         
         struct SSLsock {
         	SOCKET s;
        @@ -92,8 +83,8 @@ static struct SSLsock *searchSSL(void* state, SOCKET s){
         #define SOSTATE ((struct SSLstate *)(param->sostate))
         
         static void addSSL(
        -    SOCKET cli_s, SSL_CONN cli_conn, 
        -    SOCKET srv_s, SSL_CONN srv_conn, 
        +    SOCKET cli_s, SSL_CONN cli_conn,
        +    SOCKET srv_s, SSL_CONN srv_conn,
             struct clientparam* param){
         	if(!param->sostate) return;
         	if (cli_s != INVALID_SOCKET){
        @@ -264,7 +255,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config,
             }
             if(hostname && *hostname && config->client_verify){
                 X509_VERIFY_PARAM *param;
        -        
        +
                 param = SSL_get0_param(conn->ssl);
                 X509_VERIFY_PARAM_set1_host(param, hostname, strlen(hostname));
             }
        @@ -305,7 +296,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config,
         
             if(server_cert){
                 X509 *cert;
        -        cert = SSL_get_peer_certificate(conn->ssl);     
        +        cert = SSL_get_peer_certificate(conn->ssl);
                 if(!cert) {
         	ssl_conn_free(conn);
         	return NULL;
        @@ -375,7 +366,7 @@ SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CONFIG *config, X509 *server_cert
         	return NULL;
             }
         
        -    cert = SSL_get_peer_certificate(conn->ssl);     
        +    cert = SSL_get_peer_certificate(conn->ssl);
         
             if ( cert != NULL )
         	X509_free(cert);
        @@ -424,7 +415,7 @@ int domitm(struct clientparam* param){
          }
         
          ClientConn = ssl_handshake_to_client(param->clisock, PCONF, FakeCert, PCONF->server_key?PCONF->server_key:PCONF->CA_key, &errSSL);
        - 
        +
          _ssl_cert_free(FakeCert);
          if ( ClientConn == NULL ) {
         	param->res = 8012;
        @@ -462,7 +453,7 @@ int docli(struct clientparam* param){
         X509 * getCert (const char *fname){
             BIO *f;
             X509 *CA_cert;
        -    
        +
             f = BIO_new_file(fname, "r");
             if(!f) return NULL;
             CA_cert=PEM_read_bio_X509(f, NULL, NULL, NULL);
        @@ -478,7 +469,7 @@ EVP_PKEY * getKey(const char *fname){
             if(!f) return NULL;
             key = PEM_read_bio_PrivateKey(f, NULL, NULL, NULL);
             BIO_free(f);
        -    
        +
             return key;
         }
         
        @@ -532,8 +523,8 @@ SSL_CTX * ssl_cli_ctx(SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_ke
                         else if(config->server_ca_store){
                             SSL_CTX_load_verify_store(ctx, config->server_ca_store);
                         }
        -#endif          
        -                else 
        +#endif
        +                else
                             SSL_CTX_set_default_verify_paths(ctx);
                         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_CLIENT_ONCE, NULL);
             }
        @@ -545,7 +536,7 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
         	char fname[256];
         	char *errSSL;
         	struct ssl_config *sc;
        -	
        +
         	sc = malloc(sizeof(struct ssl_config));
         	if(!sc) return NULL;
         	memset(sc, 0, sizeof(struct ssl_config));
        @@ -689,8 +680,8 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
         		else if(sc->client_ca_store){
         		    SSL_CTX_load_verify_store(sc->srv_ctx, sc->client_ca_store);
         		}
        -#endif		
        -		else 
        +#endif
        +		else
         		    SSL_CTX_set_default_verify_paths(sc->srv_ctx);
         		    SSL_CTX_set_verify(sc->srv_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
         	    }
        @@ -777,7 +768,7 @@ static FILTER_ACTION ssl_parent(struct clientparam * param){
         
         static void ssl_filter_clear(void *state){
             struct clientparam *param;
        -    
        +
             if(!state) return;
             param = STATE->param;
             free(state);
        @@ -834,13 +825,13 @@ static struct filter ssl_filter = {
         	"ssl_filter",
         	ssl_filter_open,
         	ssl_filter_client,
        -	NULL, 
        -	ssl_filter_connect, 
        -	ssl_filter_afterauth, 
        -	NULL, NULL, 
        +	NULL,
        +	ssl_filter_connect,
        +	ssl_filter_afterauth,
        +	NULL, NULL,
         	ssl_filter_predata,
         	NULL, NULL,
        -	ssl_filter_clear, 
        +	ssl_filter_clear,
         	ssl_filter_close
         };
         
        @@ -1027,7 +1018,7 @@ static int h_client_alpn(int argc, unsigned char **argv){
         
             for(len = 0, i = 1; i < argc; i++){
         	int l;
        -	
        +
         	l = strlen((char *)argv[i]);
         	if(l >= 255) return 2;
         	client_alpn_protos.protos[len++] = l;
        @@ -1084,7 +1075,7 @@ int string_to_version(unsigned char *ver){
         	if(!strcasecmp(versions[i].sver, (char *)ver)) return versions[i].iver;
             }
             return 0;
        -} 
        +}
         
         static int h_client_min_proto_version(int argc, unsigned char **argv){
         	client_min_proto_version = argc>1? string_to_version(argv[1]) : 0;
        @@ -1178,21 +1169,13 @@ static struct symbol ssl_symbols[] = {
         };
         
         
        -#ifdef WATCOM
        -#pragma aux ssl_plugin "*" parm caller [ ] value struct float struct routine [eax] modify [eax ecx edx]
        -#undef PLUGINCALL
        -#define PLUGINCALL
        -#endif
        -
        -PLUGINAPI int PLUGINCALL ssl_plugin (struct pluginlink * pluginlink, 
        -					 int argc, char** argv){
        -
        +void ssl_install(void){
         
         	h_nomitm(0, NULL);
         	h_noserv(0, NULL);
         	h_nocli(0, NULL);
         
        -	pl = pluginlink;
        +	pl = &pluginlink;
         
         	free(certcache);
         	certcache = NULL;
        @@ -1244,18 +1227,13 @@ PLUGINAPI int PLUGINCALL ssl_plugin (struct pluginlink * pluginlink,
         		pl->symbols.next = ssl_symbols;
         	}
         
        -	tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");	
        -	if(!tcppmfunc){return 13;}
        -	proxyfunc = (PROXYFUNC)pl->findbyname("proxy");	
        +	tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");
        +	if(!tcppmfunc) return;
        +	proxyfunc = (PROXYFUNC)pl->findbyname("proxy");
         	if(!proxyfunc)proxyfunc = tcppmfunc;
        -	smtppfunc = (PROXYFUNC)pl->findbyname("smtpp");	
        +	smtppfunc = (PROXYFUNC)pl->findbyname("smtpp");
         	if(!smtppfunc)smtppfunc = tcppmfunc;
        -	ftpprfunc = (PROXYFUNC)pl->findbyname("ftppr");	
        +	ftpprfunc = (PROXYFUNC)pl->findbyname("ftppr");
         	if(!ftpprfunc)ftpprfunc = tcppmfunc;
         
        -	return 0;
        -		
          }
        -#ifdef  __cplusplus
        -}
        -#endif
        diff --git a/src/plugins/SSLPlugin/my_ssl.h b/src/ssl.h
        similarity index 89%
        rename from src/plugins/SSLPlugin/my_ssl.h
        rename to src/ssl.h
        index 3f2cc51..ff7468a 100644
        --- a/src/plugins/SSLPlugin/my_ssl.h
        +++ b/src/ssl.h
        @@ -1,5 +1,5 @@
        -#ifndef __my_ssl_h__
        -#define __my_ssl_h__
        +#ifndef __ssl_h__
        +#define __ssl_h__
         
         //
         // opaque connection structure
        @@ -10,6 +10,11 @@ typedef void *SSL_CONN;
         //
         typedef void *SSL_CERT;
         
        +typedef struct _ssl_conn {
        +	SSL_CTX *ctx;
        +	SSL *ssl;
        +} ssl_conn;
        +
         struct alpn {
             unsigned char *protos;
             unsigned int protos_len;
        @@ -65,7 +70,7 @@ SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CONFIG *config, X509 *server_cert
         SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config, SSL_CERT *server_cert, char **errSSL);
         
         //
        -// SSL/TLS Read/Write       
        +// SSL/TLS Read/Write
         //
         int ssl_read(SSL_CONN connection, void * buf, int bufsize);
         int ssl_write(SSL_CONN connection, void * buf, int bufsize);
        @@ -83,5 +88,10 @@ void _ssl_cert_free(SSL_CERT cert);
         void ssl_init(void);
         char * getSSLErr(void);
         
        +//
        +// Built-in SSL installation (called from 3proxy.c)
        +//
        +void ssl_install(void);
        +
         extern struct sockfuncs sso;
        -#endif // __my_ssl_h__
        \ No newline at end of file
        +#endif // __ssl_h__
        diff --git a/src/plugins/SSLPlugin/my_ssl.c b/src/ssllib.c
        similarity index 86%
        rename from src/plugins/SSLPlugin/my_ssl.c
        rename to src/ssllib.c
        index f76bd52..8f08e83 100644
        --- a/src/plugins/SSLPlugin/my_ssl.c
        +++ b/src/ssllib.c
        @@ -7,7 +7,7 @@
         
         #define _CRT_SECURE_NO_WARNINGS
         
        -#include "../../structures.h"
        +#include "structures.h"
         #include 
         #include 
         #ifndef _WIN32
        @@ -20,27 +20,21 @@
         #include 
         #include 
         #include 
        +#include 
         
        -#include "../../proxy.h"
        -#include "my_ssl.h"
        +#include "proxy.h"
        +#include "ssl.h"
         
         
        -
        -
        -typedef struct _ssl_conn {
        -	SSL_CTX *ctx;
        -	SSL *ssl;
        -} ssl_conn;
        -
         _3proxy_mutex_t ssl_file_mutex;
         
         
         static char errbuf[256];
         
        -static char hexMap[] = { 
        -                          '0', '1', '2', '3', '4', '5', '6', '7', 
        +static char hexMap[] = {
        +                          '0', '1', '2', '3', '4', '5', '6', '7',
                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        -                        }; 
        +                        };
         
         static BIO *bio_err=NULL;
         
        @@ -50,25 +44,25 @@ char * getSSLErr(){
             return ERR_error_string(ERR_get_error(), errbuf);
         }
         
        -static size_t bin2hex (const unsigned char* bin, size_t bin_length, char* str, size_t str_length) 
        +static size_t bin2hex (const unsigned char* bin, size_t bin_length, char* str, size_t str_length)
         {
         	char *p;
         	size_t i;
        -	
        -	if ( str_length < ( (bin_length*2)+1) ) 
        -		return 0; 
         
        -	p = str; 
        -	for ( i=0; i < bin_length; ++i )  
        -	{ 
        -		*p++ = hexMap[(*(unsigned char *)bin) >> 4];  
        -		*p++ = hexMap[(*(unsigned char *)bin) & 0xf]; 
        +	if ( str_length < ( (bin_length*2)+1) )
        +		return 0;
        +
        +	p = str;
        +	for ( i=0; i < bin_length; ++i )
        +	{
        +		*p++ = hexMap[(*(unsigned char *)bin) >> 4];
        +		*p++ = hexMap[(*(unsigned char *)bin) & 0xf];
         		++bin;
        -	} 
        -	
        -	*p = 0; 
        +	}
         
        -	return p - str; 
        +	*p = 0;
        +
        +	return p - str;
         }
         
         static int add_ext(X509 *cert, int nid, char *value)
        @@ -227,11 +221,11 @@ void _ssl_cert_free(SSL_CERT cert)
         }
         
         
        - 
        -/* This array will store all of the mutexes available to OpenSSL. */ 
        +
        +/* This array will store all of the mutexes available to OpenSSL. */
         static _3proxy_mutex_t *mutex_buf= NULL;
        - 
        - 
        +
        +
         static void locking_function(int mode, int n, const char * file, int line)
         {
           if (mode & CRYPTO_LOCK)
        @@ -239,7 +233,7 @@ static void locking_function(int mode, int n, const char * file, int line)
           else
             _3proxy_mutex_unlock(mutex_buf + n);
         }
        - 
        +
         static unsigned long id_function(void)
         {
         #ifdef _WIN32
        @@ -248,11 +242,11 @@ static unsigned long id_function(void)
           return ((unsigned long)pthread_self());
         #endif
         }
        - 
        +
         int thread_setup(void)
         {
           int i;
        - 
        +
           mutex_buf = malloc(CRYPTO_num_locks(  ) * sizeof(_3proxy_mutex_t));
           if (!mutex_buf)
             return 0;
        @@ -262,11 +256,11 @@ int thread_setup(void)
           CRYPTO_set_locking_callback(locking_function);
           return 1;
         }
        - 
        +
         int thread_cleanup(void)
         {
           int i;
        - 
        +
           if (!mutex_buf)
             return 0;
           CRYPTO_set_id_callback(NULL);
        @@ -284,15 +278,31 @@ int ssl_file_init = 0;
         
         int ssl_init_done = 0;
         
        +OSSL_LIB_CTX *library_ctx = NULL;
        +extern EVP_MD *md4;
        +extern EVP_MD *md5;
        +
        +
         void ssl_init()
         {
         	if(!ssl_init_done){
        +	    
         	    ssl_init_done = 1;
         	    thread_setup();
         	    SSLeay_add_ssl_algorithms();
         	    SSL_load_error_strings();
         	    _3proxy_mutex_init(&ssl_file_mutex);
         	    bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
        -	}
        +	    library_ctx = OSSL_LIB_CTX_new();
        +	    OSSL_PROVIDER_load(library_ctx, "legacy");
        +	    OSSL_PROVIDER_load(library_ctx, "default");
        +	    md4 = EVP_MD_fetch(library_ctx, "MD4", NULL);
        +	    if (md4 == NULL) {
        +    		printf("Error fetching MD4\n");
        +	    }
        +	    md5 = EVP_MD_fetch(library_ctx, "MD5", NULL);
        +	    if (md5 == NULL) {
        +    		printf("Error fetching MD5\n");
        +	    }
        +    	}
         }
        -
        diff --git a/src/structures.h b/src/structures.h
        index 225c1f2..1f49b9c 100644
        --- a/src/structures.h
        +++ b/src/structures.h
        @@ -651,6 +651,8 @@ struct clientparam {
         	struct bandlim	*bandlims[MAXBANDLIMS],
         			*bandlimsout[MAXBANDLIMS];
         
        +	PROXYSOCKADDRTYPE udp_relay[3];
        +	int udp_nhops;
         	time_t time_start;
         };
         
        @@ -771,7 +773,9 @@ extern struct hashtable dns_table;
         extern struct hashtable dns6_table;
         extern struct hashtable auth_table;
         extern struct hashtable pw_table;
        +#ifdef WITH_SSL
         extern struct hashtable pwnt_table;
        +#endif
         extern struct hashtable pwcr_table;
         extern struct hashtable udp_table;