Compare commits

..

24 Commits

Author SHA1 Message Date
Nirmal Khanal
01f85cf755 Fix parent negotiation after sending PROXY protocol header
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
After 'parent ha' sends the PROXY v1 header, continue negotiating the
real parent protocol (SOCKS5/CONNECT/etc.) instead of returning early.
'ha' used alone still sends the header and relays plain TCP.
2026-07-23 10:55:07 +03:00
Vladimir Dubrovin
305f9932ac Update docs
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-07-22 18:47:11 +03:00
Vladimir Dubrovin
c94766dff7 Fix: dnspr was broken since udppm rewrite. -F (fake resolve to redirect traffic) option added to dnspr 2026-07-22 17:34:51 +03:00
Vladimir Dubrovin
87fc8ae4ee Fix cmake build 2026-07-22 16:23:11 +03:00
Vladimir Dubrovin
9ab2e820b5 Added imapp, starttls support for smtpp, pop3p, tlspr 2026-07-22 16:15:50 +03:00
Vladimir Dubrovin
7798f78137 support chunked TE from client
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-07-21 16:05:12 +03:00
Vladimir Dubrovin
d60ac723a5 Multiple fixes, including security-related ones (in smtpp and LDAP plugin)
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-07-20 19:52:10 +03:00
Vladimir Dubrovin
afb2ec0696 IPV6_BOUND_IF also in second place
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Has been cancelled
2026-07-17 15:12:49 +03:00
Vladimir Dubrovin
f18a751f89 define IPV6_BOUND_IF if not defined (for legacy MacOS 10.x) 2026-07-17 15:07:11 +03:00
Vladimir Dubrovin
8de071aa87 fix wolfSSL build
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Has been cancelled
2026-07-13 20:50:27 +03:00
Vladimir Dubrovin
f173f8860d wolfSSL support added 2026-07-13 20:24:51 +03:00
Vladimir Dubrovin
3a66c0a4c0 Use half sha256 for cert cache
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-07-13 17:14:46 +03:00
Vladimir Dubrovin
66ee250e5c Fix: hashstable item is added with wrong index on table grow 2026-07-13 15:30:49 +03:00
Vladimir Dubrovin
c893e866bd Use Solar Designer's md4/md5 on non-Windows
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-07-10 14:01:29 +03:00
Vladimir Dubrovin
fbc0953d5c Use native Windows crypto for MD4/MD5 2026-07-10 13:04:43 +03:00
Vladimir Dubrovin
37b1ab8169 Update Makefile.win 2026-07-10 12:15:45 +03:00
Vladimir Dubrovin
b7769d05af Support static libraries in Makefile.win 2026-07-10 12:10:01 +03:00
Vladimir Dubrovin
fdda69c1f4 fux ucrt workflow 2026-07-10 11:41:27 +03:00
Vladimir Dubrovin
a757fae617 Fix Makefile.win for UCRT bug 2026-07-10 11:35:56 +03:00
Vladimir Dubrovin
1c9577b9a9 Add ucrt64 build support 2026-07-10 11:25:45 +03:00
Vladimir Dubrovin
b59c044663 Update CMakeLists.txt 2026-07-10 10:53:58 +03:00
Vladimir Dubrovin
de5acb2abd Do not use getrandom for glibc < 2.25
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-07-06 11:41:12 +03:00
Vladimir Dubrovin
d6dea13a6f Fix zip name in win32 build action
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-07-04 14:37:24 +03:00
Vladimir Dubrovin
a04cd67eaa Fix release artefact uploads in Windows workflows 2026-07-04 14:15:01 +03:00
64 changed files with 3081 additions and 463 deletions

View File

@ -88,6 +88,7 @@ jobs:
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}

View File

@ -0,0 +1,72 @@
name: Build 3proxy with MSYS2 UCRT64
on:
workflow_dispatch:
permissions:
contents: read
jobs:
ci:
name: "msys2-ucrt64"
runs-on: windows-2022
steps:
- uses: actions/checkout@v7
- name: Setup MSYS2 (UCRT64)
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: >-
make
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-pcre2
mingw-w64-ucrt-x86_64-openssl
mingw-w64-ucrt-x86_64-zlib
- name: set date
shell: pwsh
run: |
$NOW = Get-Date -Format "yyMMddHHmmss"
$RELEASE = Get-Content -Path "RELEASE" -Raw
echo "NOW=$NOW" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "RELEASE=$RELEASE" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: make Windows (Makefile.win)
shell: msys2 {0}
env:
LIBSTATIC: 'true'
run: make -f Makefile.win
- name: make dist dir
shell: cmd
run: |
mkdir dist
mkdir dist\3proxy
mkdir dist\3proxy\bin
mkdir dist\3proxy\cfg
mkdir dist\3proxy\cfg\sql
mkdir dist\3proxy\doc
mkdir dist\3proxy\doc\ru
mkdir dist\3proxy\doc\html
mkdir dist\3proxy\doc\html\plugins
mkdir dist\3proxy\doc\html\man5
mkdir dist\3proxy\doc\html\man8
mkdir dist\3proxy\doc\html\devel
copy bin\3proxy.exe dist\3proxy\bin\
copy bin\*.dll dist\3proxy\bin\
copy bin\3proxy_crypt.exe dist\3proxy\bin\
copy cfg\*.* dist\3proxy\cfg\
copy cfg\sql\*.* dist\3proxy\cfg\sql\
copy doc\ru\*.* dist\3proxy\doc\ru\
copy doc\html\*.* dist\3proxy\doc\html\
copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\
copy doc\html\man8\*.* dist\3proxy\doc\html\man8\
copy doc\html\man5\*.* dist\3proxy\doc\html\man5\
copy doc\html\devel\*.* dist\3proxy\doc\html\devel\
copy copying dist\3proxy\
copy authors dist\3proxy\
copy README.md dist\3proxy\
copy rus.3ps dist\3proxy\
- name: Get artifact
uses: actions/upload-artifact@v7
with:
name: "3proxy-${{ env.RELEASE }}-msys2-ucrt64"
path: dist/

View File

@ -28,7 +28,7 @@ jobs:
echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: install packages - name: install packages
run: vcpkg install pcre2:x86-windows-static openssl:x86-windows-static run: vcpkg install pcre2:x86-windows-static wolfssl:x86-windows-static
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v3 uses: microsoft/setup-msbuild@v3
- name: make Windows MSVC - name: make Windows MSVC
@ -41,7 +41,7 @@ jobs:
set "LIB=%LIB%;c:/vcpkg/installed/x86-windows-static/lib" set "LIB=%LIB%;c:/vcpkg/installed/x86-windows-static/lib"
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x86-windows-static/include" set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x86-windows-static/include"
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
nmake /F Makefile.msvc nmake /F Makefile.msvc WOLFSSL=1
- name: Decode Certificate - name: Decode Certificate
shell: pwsh shell: pwsh
run: | run: |
@ -95,7 +95,7 @@ jobs:
- name: Get artifact - name: Get artifact
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}" name: "3proxy-${{ env.RELEASE }}-x86"
path: dist/ path: dist/
- name: Create zip - name: Create zip
if: github.event_name == 'release' if: github.event_name == 'release'
@ -103,6 +103,7 @@ jobs:
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}

View File

@ -29,7 +29,7 @@ jobs:
echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: install packages - name: install packages
run: vcpkg install pcre2:x64-windows-static openssl:x64-windows-static run: vcpkg install pcre2:x64-windows-static wolfssl:x64-windows-static
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v3 uses: microsoft/setup-msbuild@v3
- name: make Windows MSVC - name: make Windows MSVC
@ -42,7 +42,7 @@ jobs:
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x64-windows-static/include" set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x64-windows-static/include"
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION% echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION%
nmake /F Makefile.msvc nmake /F Makefile.msvc WOLFSSL=1
- name: Decode Certificate - name: Decode Certificate
shell: pwsh shell: pwsh
run: | run: |
@ -104,6 +104,7 @@ jobs:
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}

View File

@ -28,7 +28,7 @@ jobs:
echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "VERSION=/D `"VERSION=\`"3proxy-$RELEASE\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append echo "BUILDDATE=/D `"BUILDDATE=\`"$NOW\`"`"" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: install packages - name: install packages
run: vcpkg install pcre2:arm64-windows-static openssl:arm64-windows-static run: vcpkg install pcre2:arm64-windows-static wolfssl:arm64-windows-static
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v3 uses: microsoft/setup-msbuild@v3
- name: make Windows MSVC - name: make Windows MSVC
@ -41,7 +41,7 @@ jobs:
set "LIB=%LIB%;c:/vcpkg/installed/arm64-windows-static/lib" set "LIB=%LIB%;c:/vcpkg/installed/arm64-windows-static/lib"
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/arm64-windows-static/include" set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/arm64-windows-static/include"
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
nmake /F Makefile.msvc nmake /F Makefile.msvc WOLFSSL=1
- name: Decode Certificate - name: Decode Certificate
shell: pwsh shell: pwsh
run: | run: |
@ -103,6 +103,7 @@ jobs:
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}

View File

@ -21,7 +21,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- name: install Windows libraries - name: install Windows libraries
run: vcpkg install pcre2:x64-windows && c:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-x86_64-pcre2 mingw-w64-x86_64-openssl run: vcpkg install pcre2:x64-windows wolfssl:x64-windows-static && c:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-x86_64-pcre2 mingw-w64-x86_64-wolfssl
- name: make Windows - name: make Windows
run: make -f Makefile.win run: make -f Makefile.win
env: env:
@ -37,7 +37,7 @@ jobs:
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
D: D:
cd "D:/a/3proxy/3proxy" cd "D:/a/3proxy/3proxy"
set "LIB=%LIB%;c:/program files/openssl/lib/VC/x64/MT;c:/vcpkg/installed/x64-windows/lib" set "LIB=%LIB%;c:/vcpkg/installed/x64-windows-static/lib;c:/vcpkg/installed/x64-windows/lib"
set "INCLUDE=%INCLUDE%;c:/program files/openssl/include;c:/vcpkg/installed/x64-windows/include" set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x64-windows-static/include;c:/vcpkg/installed/x64-windows/include"
nmake /F Makefile.msvc nmake /F Makefile.msvc WOLFSSL=1
nmake /F Makefile.msvc clean nmake /F Makefile.msvc clean

View File

@ -57,3 +57,18 @@ jobs:
cmake --build . cmake --build .
cd .. cd ..
rmdir /s /q build rmdir /s /q build
wolfssl:
name: "ubuntu-latest (wolfSSL)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install wolfSSL
run: sudo apt install -y libwolfssl-dev
- name: make with CMake (wolfSSL preferred)
run: |
mkdir build
cd build
cmake ..
cmake --build .
cd .. && rm -rf build/

3
.gitignore vendored
View File

@ -18,6 +18,7 @@ bin/socks
bin/tcppm bin/tcppm
bin/udppm bin/udppm
bin/pop3p bin/pop3p
bin/imapp
bin/smtpp bin/smtpp
bin/ftppr bin/ftppr
bin/mycrypt bin/mycrypt
@ -45,6 +46,7 @@ src/socks
src/tcppm src/tcppm
src/udppm src/udppm
src/pop3p src/pop3p
src/imapp
src/smtpp src/smtpp
src/ftppr src/ftppr
src/icqpr src/icqpr
@ -261,6 +263,7 @@ CLAUDE.md
bin/3proxy_crypt bin/3proxy_crypt
bin/3proxy_ftppr bin/3proxy_ftppr
bin/3proxy_pop3p bin/3proxy_pop3p
bin/3proxy_imapp
bin/3proxy_proxy bin/3proxy_proxy
bin/3proxy_smtpp bin/3proxy_smtpp
bin/3proxy_socks bin/3proxy_socks

View File

@ -46,7 +46,8 @@ endif()
# Options # Options
option(3PROXY_BUILD_SHARED "Build shared libraries for plugins" ON) option(3PROXY_BUILD_SHARED "Build shared libraries for plugins" ON)
option(3PROXY_USE_OPENSSL "Enable TLS/SSL support (requires OpenSSL)" ON) option(3PROXY_USE_WOLFSSL "Enable TLS/SSL support via wolfSSL (preferred when detected)" ON)
option(3PROXY_USE_OPENSSL "Enable TLS/SSL support via OpenSSL (fallback when wolfSSL unavailable)" ON)
option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" ON) option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" ON)
option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON) option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON)
option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF) option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF)
@ -69,6 +70,7 @@ option(3PROXY_BUILD_NONE "Do not build standalone binaries" OFF)
option(3PROXY_BUILD_PROXY "Build standalone proxy binary" ON) option(3PROXY_BUILD_PROXY "Build standalone proxy binary" ON)
option(3PROXY_BUILD_SOCKS "Build standalone socks binary" ON) option(3PROXY_BUILD_SOCKS "Build standalone socks binary" ON)
option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" ON) option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" ON)
option(3PROXY_BUILD_IMAPP "Build standalone imapp binary" ON)
option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" ON) option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" ON)
option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" ON) option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" ON)
option(3PROXY_BUILD_TCPPM "Build standalone tcppm binary" ON) option(3PROXY_BUILD_TCPPM "Build standalone tcppm binary" ON)
@ -76,7 +78,7 @@ option(3PROXY_BUILD_UDPPM "Build standalone udppm binary" ON)
option(3PROXY_BUILD_TLSPR "Build standalone tlspr binary" ON) option(3PROXY_BUILD_TLSPR "Build standalone tlspr binary" ON)
if(3PROXY_BUILD_NONE) if(3PROXY_BUILD_NONE)
foreach(_M PROXY SOCKS POP3P SMTPP FTPPR TCPPM UDPPM TLSPR) foreach(_M PROXY SOCKS POP3P IMAPP SMTPP FTPPR TCPPM UDPPM TLSPR)
set(3PROXY_BUILD_${_M} OFF) set(3PROXY_BUILD_${_M} OFF)
endforeach() endforeach()
endif() endif()
@ -253,17 +255,38 @@ endif()
# Find dependencies # Find dependencies
# OpenSSL # TLS/SSL backend: prefer wolfSSL when detected, fall back to OpenSSL.
set(3PROXY_SSL_ENABLED FALSE)
set(3PROXY_SSL_WOLFSSL FALSE)
set(OPENSSL_FOUND FALSE) set(OPENSSL_FOUND FALSE)
if(3PROXY_USE_OPENSSL) set(WOLFSSL_FOUND FALSE)
if(3PROXY_USE_WOLFSSL)
find_path(WOLFSSL_INCLUDE_DIR NAMES wolfssl/options.h wolfssl/ssl.h)
find_library(WOLFSSL_LIBRARIES NAMES wolfssl)
if(WOLFSSL_INCLUDE_DIR AND WOLFSSL_LIBRARIES)
set(WOLFSSL_FOUND TRUE)
set(3PROXY_SSL_ENABLED TRUE)
set(3PROXY_SSL_WOLFSSL TRUE)
add_compile_definitions(WITH_SSL WITH_WOLFSSL)
message(STATUS "wolfSSL found: ${WOLFSSL_LIBRARIES} (preferred backend)")
else()
message(STATUS "wolfSSL not found, falling back to OpenSSL if enabled")
endif()
endif()
if(NOT 3PROXY_SSL_ENABLED AND 3PROXY_USE_OPENSSL)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
if(OpenSSL_FOUND) if(OpenSSL_FOUND)
set(OPENSSL_FOUND TRUE) set(OPENSSL_FOUND TRUE)
set(3PROXY_SSL_ENABLED TRUE)
add_compile_definitions(WITH_SSL) add_compile_definitions(WITH_SSL)
message(STATUS "OpenSSL found: ${OPENSSL_VERSION}") message(STATUS "OpenSSL found: ${OPENSSL_VERSION}")
endif() endif()
else() elseif(NOT 3PROXY_SSL_ENABLED)
message(STATUS "OpenSSL disabled by user request") message(STATUS "SSL disabled (neither wolfSSL nor OpenSSL enabled/found)")
elseif(3PROXY_SSL_WOLFSSL)
message(STATUS "OpenSSL skipped (wolfSSL in use)")
endif() endif()
# PCRE2 # PCRE2
@ -305,8 +328,9 @@ if(ODBC_FOUND)
add_compile_definitions(WITH_ODBC) add_compile_definitions(WITH_ODBC)
endif() endif()
# Set NORADIUS if OpenSSL is not available (RADIUS requires MD5 from OpenSSL) # Set NORADIUS if no SSL backend is available (RADIUS MD5 uses bundled md5, but
if(NOT OPENSSL_FOUND) # keep the historical gate tied to SSL availability).
if(NOT 3PROXY_SSL_ENABLED)
add_compile_definitions(NORADIUS) add_compile_definitions(NORADIUS)
endif() endif()
@ -328,10 +352,8 @@ set(3PROXY_CORE_SOURCES
src/stringtable.c src/stringtable.c
) )
# BLAKE2 source for 3proxy_crypt # Bundled hash implementations (md4.c, md5.c, blake2b-ref.c) self-disable
set(MD_SOURCES # via preprocessor guards when wolfSSL provides them natively.
src/libs/blake2b-ref.c
)
# ============================================================================ # ============================================================================
# Object libraries for common sources (shared between executables) # Object libraries for common sources (shared between executables)
@ -350,6 +372,14 @@ target_include_directories(common_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_library(base64_obj OBJECT src/base64.c) add_library(base64_obj OBJECT src/base64.c)
target_include_directories(base64_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(base64_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# mdhash object library. md4.c/md5.c self-disable via NO_MD4/NO_MD5 guards
# when wolfSSL provides them; always compiled for fallback.
add_library(mdhash_obj OBJECT src/mdhash.c src/libs/md4.c src/libs/md5.c src/libs/blake2b-ref.c)
target_include_directories(mdhash_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
if(3PROXY_SSL_WOLFSSL)
target_include_directories(mdhash_obj PRIVATE ${WOLFSSL_INCLUDE_DIR})
endif()
# ============================================================================ # ============================================================================
# Object libraries for 3proxy (compiled WITHOUT WITHMAIN) # Object libraries for 3proxy (compiled WITHOUT WITHMAIN)
# These are used by the main 3proxy executable # These are used by the main 3proxy executable
@ -359,6 +389,7 @@ target_include_directories(base64_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_library(srv_modules OBJECT add_library(srv_modules OBJECT
src/proxy.c src/proxy.c
src/pop3p.c src/pop3p.c
src/imapp.c
src/smtpp.c src/smtpp.c
src/ftppr.c src/ftppr.c
src/tcppm.c src/tcppm.c
@ -394,9 +425,13 @@ target_include_directories(ftp_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# 3proxy_crypt object for 3proxy (without WITHMAIN) # 3proxy_crypt object for 3proxy (without WITHMAIN)
add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c) add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c)
target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
if(3PROXY_SSL_WOLFSSL)
target_include_directories(3proxy_crypt_obj PRIVATE ${WOLFSSL_INCLUDE_DIR})
else()
target_include_directories(3proxy_crypt_obj PRIVATE ${OPENSSL_INCLUDE_DIR}) target_include_directories(3proxy_crypt_obj PRIVATE ${OPENSSL_INCLUDE_DIR})
endif() endif()
endif()
# ============================================================================ # ============================================================================
# Main 3proxy executable # Main 3proxy executable
@ -411,12 +446,12 @@ add_executable(3proxy
$<TARGET_OBJECTS:common_obj> $<TARGET_OBJECTS:common_obj>
$<TARGET_OBJECTS:udpsockmap_obj> $<TARGET_OBJECTS:udpsockmap_obj>
$<TARGET_OBJECTS:base64_obj> $<TARGET_OBJECTS:base64_obj>
$<TARGET_OBJECTS:mdhash_obj>
$<TARGET_OBJECTS:ftp_obj> $<TARGET_OBJECTS:ftp_obj>
$<TARGET_OBJECTS:3proxy_crypt_obj> $<TARGET_OBJECTS:3proxy_crypt_obj>
) )
target_sources(3proxy PRIVATE ${MD_SOURCES})
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
target_sources(3proxy PRIVATE src/ssllib.c src/ssl.c) target_sources(3proxy PRIVATE src/ssllib.c src/ssl.c)
endif() endif()
@ -428,9 +463,13 @@ target_include_directories(3proxy PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/libs ${CMAKE_CURRENT_SOURCE_DIR}/src/libs
) )
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
if(3PROXY_SSL_WOLFSSL)
target_include_directories(3proxy PRIVATE ${WOLFSSL_INCLUDE_DIR})
else()
target_include_directories(3proxy PRIVATE ${OPENSSL_INCLUDE_DIR}) target_include_directories(3proxy PRIVATE ${OPENSSL_INCLUDE_DIR})
endif() endif()
endif()
if(PCRE2_FOUND) if(PCRE2_FOUND)
target_include_directories(3proxy PRIVATE ${PCRE2_INCLUDE_DIRS}) target_include_directories(3proxy PRIVATE ${PCRE2_INCLUDE_DIRS})
endif() endif()
@ -445,10 +484,16 @@ if(ODBC_FOUND)
endif() endif()
endif() endif()
# OpenSSL linking # SSL linking
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
if(3PROXY_SSL_WOLFSSL)
if(3PROXY_STATIC_LINK) if(3PROXY_STATIC_LINK)
# Will be linked statically below (if static libraries are found) # Will be linked statically below (if static library is found)
else()
target_link_libraries(3proxy PRIVATE ${WOLFSSL_LIBRARIES})
endif()
elseif(3PROXY_STATIC_LINK)
# OpenSSL static linking handled below
else() else()
target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif() endif()
@ -465,14 +510,19 @@ if(PCRE2_FOUND)
endif() endif()
endif() endif()
# Static linking of OpenSSL and PCRE2 (when option is enabled) # Static linking of SSL backend and PCRE2 (when option is enabled)
if(3PROXY_STATIC_LINK AND (OpenSSL_FOUND OR PCRE2_FOUND)) if(3PROXY_STATIC_LINK AND ((3PROXY_SSL_ENABLED AND NOT 3PROXY_SSL_WOLFSSL) OR (3PROXY_SSL_WOLFSSL) OR PCRE2_FOUND))
set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(_static_libs "") set(_static_libs "")
if(OpenSSL_FOUND) if(3PROXY_SSL_WOLFSSL)
find_library(_wolfssl_static_lib NAMES wolfssl)
if(_wolfssl_static_lib)
list(APPEND _static_libs ${_wolfssl_static_lib})
endif()
elseif(OpenSSL_FOUND)
find_library(_ssl_static_lib ssl) find_library(_ssl_static_lib ssl)
find_library(_crypto_static_lib crypto) find_library(_crypto_static_lib crypto)
if(_ssl_static_lib AND _crypto_static_lib) if(_ssl_static_lib AND _crypto_static_lib)
@ -491,10 +541,12 @@ if(3PROXY_STATIC_LINK AND (OpenSSL_FOUND OR PCRE2_FOUND))
if(_static_libs) if(_static_libs)
target_link_libraries(3proxy PRIVATE -Wl,-Bstatic ${_static_libs} -Wl,-Bdynamic) target_link_libraries(3proxy PRIVATE -Wl,-Bstatic ${_static_libs} -Wl,-Bdynamic)
message(STATUS "Static linking enabled for OpenSSL/PCRE2") message(STATUS "Static linking enabled for SSL backend/PCRE2")
else() else()
message(WARNING "3PROXY_STATIC_LINK is ON but static libraries not found, falling back to dynamic") message(WARNING "3PROXY_STATIC_LINK is ON but static libraries not found, falling back to dynamic")
if(OpenSSL_FOUND) if(3PROXY_SSL_WOLFSSL)
target_link_libraries(3proxy PRIVATE ${WOLFSSL_LIBRARIES})
elseif(OpenSSL_FOUND)
target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif() endif()
if(PCRE2_FOUND) if(PCRE2_FOUND)
@ -520,18 +572,39 @@ endif()
add_executable(3proxy_crypt add_executable(3proxy_crypt
src/3proxy_crypt.c src/3proxy_crypt.c
$<TARGET_OBJECTS:base64_obj> $<TARGET_OBJECTS:base64_obj>
$<TARGET_OBJECTS:mdhash_obj>
) )
target_sources(3proxy_crypt PRIVATE ${MD_SOURCES})
target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN) target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN)
target_include_directories(3proxy_crypt PRIVATE target_include_directories(3proxy_crypt PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/libs ${CMAKE_CURRENT_SOURCE_DIR}/src/libs
) )
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
if(3PROXY_SSL_WOLFSSL)
target_include_directories(3proxy_crypt PRIVATE ${WOLFSSL_INCLUDE_DIR})
else()
target_include_directories(3proxy_crypt PRIVATE ${OPENSSL_INCLUDE_DIR}) target_include_directories(3proxy_crypt PRIVATE ${OPENSSL_INCLUDE_DIR})
endif() endif()
endif()
target_link_libraries(3proxy_crypt PRIVATE Threads::Threads) target_link_libraries(3proxy_crypt PRIVATE Threads::Threads)
if(OpenSSL_FOUND) if(3PROXY_SSL_ENABLED)
if(3PROXY_SSL_WOLFSSL)
if(3PROXY_STATIC_LINK)
set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
find_library(_wolfssl_static_lib_c NAMES wolfssl)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_saved_cmake_find_library_suffixes})
if(_wolfssl_static_lib_c)
target_link_libraries(3proxy_crypt PRIVATE -Wl,-Bstatic ${_wolfssl_static_lib_c} -Wl,-Bdynamic)
message(STATUS "3proxy_crypt: static wolfSSL")
else()
message(WARNING "3PROXY_STATIC_LINK is ON but static wolfSSL not found, using dynamic")
target_link_libraries(3proxy_crypt PRIVATE ${WOLFSSL_LIBRARIES})
endif()
else()
target_link_libraries(3proxy_crypt PRIVATE ${WOLFSSL_LIBRARIES})
endif()
else()
if(3PROXY_STATIC_LINK) if(3PROXY_STATIC_LINK)
set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
@ -549,6 +622,7 @@ if(OpenSSL_FOUND)
target_link_libraries(3proxy_crypt PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(3proxy_crypt PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif() endif()
endif() endif()
endif()
if("${3PROXY_BINARY_PREFIX}" STREQUAL "") if("${3PROXY_BINARY_PREFIX}" STREQUAL "")
set_target_properties(3proxy_crypt PROPERTIES OUTPUT_NAME "mycrypt") set_target_properties(3proxy_crypt PROPERTIES OUTPUT_NAME "mycrypt")
else() else()
@ -556,7 +630,7 @@ else()
endif() endif()
# Build standalone proxy executables # Build standalone proxy executables
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr) foreach(PROXY_NAME proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT) string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(NOT 3PROXY_BUILD_${_MODULE_OPT}) if(NOT 3PROXY_BUILD_${_MODULE_OPT})
continue() continue()
@ -607,7 +681,7 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
target_link_libraries(${PROXY_NAME} PRIVATE ${WINDOWS_LIBS}) target_link_libraries(${PROXY_NAME} PRIVATE ${WINDOWS_LIBS})
endif() endif()
if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp") if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp" OR PROXY_NAME STREQUAL "imapp")
target_sources(${PROXY_NAME} PRIVATE $<TARGET_OBJECTS:base64_obj>) target_sources(${PROXY_NAME} PRIVATE $<TARGET_OBJECTS:base64_obj>)
endif() endif()
@ -651,7 +725,7 @@ install(TARGETS 3proxy 3proxy_crypt
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) )
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr) foreach(PROXY_NAME proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT) string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(3PROXY_BUILD_${_MODULE_OPT}) if(3PROXY_BUILD_${_MODULE_OPT})
install(TARGETS ${PROXY_NAME} install(TARGETS ${PROXY_NAME}
@ -661,16 +735,18 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
endforeach() endforeach()
# Install plugins # Install plugins
file(GLOB PLUGINFILES "${PLUGIN_OUTPUT_DIR}/*${PLUGIN_SUFFIX}") # Use install(DIRECTORY ... FILES_MATCHING) so the glob resolves at install
# time, after plugin targets have been built. A configure-time file(GLOB)
# would run before any plugin exists and install nothing.
if(WIN32) if(WIN32)
install(FILES install(DIRECTORY ${PLUGIN_OUTPUT_DIR}/
${PLUGINFILES}
DESTINATION ${CMAKE_INSTALL_BINDIR} DESTINATION ${CMAKE_INSTALL_BINDIR}
FILES_MATCHING PATTERN "*${PLUGIN_SUFFIX}"
) )
else() else()
install(FILES install(DIRECTORY ${PLUGIN_OUTPUT_DIR}/
${PLUGINFILES}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/3proxy DESTINATION ${CMAKE_INSTALL_LIBDIR}/3proxy
FILES_MATCHING PATTERN "*${PLUGIN_SUFFIX}"
) )
endif() endif()
@ -812,7 +888,7 @@ if(NOT WIN32)
) )
endif() endif()
# Module man pages installed with binary prefix only if module is built # Module man pages installed with binary prefix only if module is built
foreach(_MAN proxy socks pop3p smtpp ftppr tcppm udppm tlspr) foreach(_MAN proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${_MAN}" _MODULE_OPT) string(TOUPPER "${_MAN}" _MODULE_OPT)
if(3PROXY_BUILD_${_MODULE_OPT}) if(3PROXY_BUILD_${_MODULE_OPT})
set(_MAN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/man/${_MAN}.8") set(_MAN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/man/${_MAN}.8")
@ -836,6 +912,7 @@ message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "") message(STATUS "")
message(STATUS " Options:") message(STATUS " Options:")
message(STATUS " BUILD_SHARED: ${3PROXY_BUILD_SHARED}") message(STATUS " BUILD_SHARED: ${3PROXY_BUILD_SHARED}")
message(STATUS " USE_WOLFSSL: ${3PROXY_USE_WOLFSSL}")
message(STATUS " USE_OPENSSL: ${3PROXY_USE_OPENSSL}") message(STATUS " USE_OPENSSL: ${3PROXY_USE_OPENSSL}")
message(STATUS " USE_PCRE2: ${3PROXY_USE_PCRE2}") message(STATUS " USE_PCRE2: ${3PROXY_USE_PCRE2}")
message(STATUS " USE_PAM: ${3PROXY_USE_PAM}") message(STATUS " USE_PAM: ${3PROXY_USE_PAM}")
@ -853,6 +930,7 @@ if(WIN32)
endif() endif()
message(STATUS "") message(STATUS "")
message(STATUS " Libraries found:") message(STATUS " Libraries found:")
message(STATUS " wolfSSL: ${WOLFSSL_FOUND}")
message(STATUS " OpenSSL: ${OPENSSL_FOUND}") message(STATUS " OpenSSL: ${OPENSSL_FOUND}")
message(STATUS " PCRE2: ${PCRE2_FOUND}") message(STATUS " PCRE2: ${PCRE2_FOUND}")
message(STATUS " PAM: ${PAM_FOUND}") message(STATUS " PAM: ${PAM_FOUND}")
@ -862,7 +940,7 @@ message(STATUS " Plugins to build: ${ALL_PLUGINS}")
message(STATUS "") message(STATUS "")
message(STATUS " Standalone modules:") message(STATUS " Standalone modules:")
message(STATUS " Binary prefix: \"${3PROXY_BINARY_PREFIX}\"") message(STATUS " Binary prefix: \"${3PROXY_BINARY_PREFIX}\"")
foreach(_M proxy socks pop3p smtpp ftppr tcppm udppm tlspr) foreach(_M proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${_M}" _MO) string(TOUPPER "${_M}" _MO)
message(STATUS " BUILD_${_MO}: ${3PROXY_BUILD_${_MO}}") message(STATUS " BUILD_${_MO}: ${3PROXY_BUILD_${_MO}}")
endforeach() endforeach()

View File

@ -47,6 +47,13 @@ ifeq ($(LIBSTATIC), true)
STATIC_SUFFIX = -Wl,-Bdynamic STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB :=
else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX)
@ -55,6 +62,7 @@ ifeq ($(OPENSSL_CHECK), true)
else else
ZLIB := ZLIB :=
endif endif
endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\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 <pcre2.h>\\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) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
@ -76,7 +84,7 @@ install: all
if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi
install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy
install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \ for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \ if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \
done done
install -d $(DESTDIR)$(prefix)/etc/3proxy/conf install -d $(DESTDIR)$(prefix)/etc/3proxy/conf
@ -93,7 +101,7 @@ install: all
touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters
install -d $(DESTDIR)$(MANDIR)/man8 install -d $(DESTDIR)$(MANDIR)/man8
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8 install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \ for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \ if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done done
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8 install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8

View File

@ -51,6 +51,13 @@ ifeq ($(LIBSTATIC), true)
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB :=
else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
@ -59,6 +66,7 @@ ifeq ($(OPENSSL_CHECK), true)
else else
ZLIB := ZLIB :=
endif endif
endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
@ -86,6 +94,7 @@ INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = bin/3proxy \ INSTALL_OBJS = bin/3proxy \
bin/$(CRYPT_PREFIX)crypt \ bin/$(CRYPT_PREFIX)crypt \
bin/$(PREFIX)ftppr \ bin/$(PREFIX)ftppr \
bin/$(PREFIX)imapp \
bin/$(PREFIX)pop3p \ bin/$(PREFIX)pop3p \
bin/$(PREFIX)proxy \ bin/$(PREFIX)proxy \
bin/$(PREFIX)smtpp \ bin/$(PREFIX)smtpp \
@ -149,7 +158,7 @@ install-man:
$(INSTALL_BIN) -d $(MANDIR8) $(INSTALL_BIN) -d $(MANDIR8)
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5) $(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8) $(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \ for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \ if [ -f man/$$f.8 ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \
done done
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8 $(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8

View File

@ -31,12 +31,19 @@ COMPATLIBS =
MAKEFILE = Makefile.Solaris MAKEFILE = Makefile.Solaris
PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testwssl testwssl.o -lwolfssl 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true)
LIBS += -lwolfssl
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\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) OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\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) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += -l crypto -l ssl
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
endif endif
endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\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) PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\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) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE

View File

@ -11,13 +11,20 @@ CRYPT_PREFIX = 3proxy_
CC = cl CC = cl
VERSION = $(VERSION) VERSION = $(VERSION)
BUILDDATE = $(BUILDDATE) BUILDDATE = $(BUILDDATE)
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 "WITH_ODBC" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION) !IFDEF WOLFSSL
SSL_DEFS = /D "WITH_SSL" /D "WITH_WOLFSSL"
SSL_LIBS = wolfssl.lib
!ELSE
SSL_DEFS = /D "WITH_SSL"
SSL_LIBS = libcrypto.lib libssl.lib
!ENDIF
CFLAGS = /nologo /MT /W3 /Ox /GS /EHs- /GA /GF /D "MSVC" /D "WITH_WSAPOLL" /D "NDEBUG" /D "WIN32" $(SSL_DEFS) /D "WITH_PCRE" /D "WITH_ODBC" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION)
COUT = /Fo COUT = /Fo
LN = link LN = link
LDFLAGS = /nologo /subsystem:console /incremental:no LDFLAGS = /nologo /subsystem:console /incremental:no
DLFLAGS = /DLL DLFLAGS = /DLL
DLSUFFICS = .dll DLSUFFICS = .dll
LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib libcrypto.lib libssl.lib pcre2-8.lib LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib $(SSL_LIBS) pcre2-8.lib
LIBSPREFIX = LIBSPREFIX =
LIBSSUFFIX = .lib LIBSSUFFIX = .lib
LIBEXT = .lib LIBEXT = .lib

View File

@ -49,6 +49,13 @@ ifeq ($(LIBSTATIC), true)
STATIC_SUFFIX = -Wl,-Bdynamic STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB :=
else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
@ -57,6 +64,7 @@ ifeq ($(OPENSSL_CHECK), true)
else else
ZLIB := ZLIB :=
endif endif
endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
@ -78,7 +86,7 @@ install: all
if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi
install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy
install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \ for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \ if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \
done done
install -d $(DESTDIR)$(prefix)/etc/3proxy/conf install -d $(DESTDIR)$(prefix)/etc/3proxy/conf
@ -95,7 +103,7 @@ install: all
touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters
install -d $(DESTDIR)$(MANDIR)/man8 install -d $(DESTDIR)$(MANDIR)/man8
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8 install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \ for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \ if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done done
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8 install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8

View File

@ -37,21 +37,36 @@ BUILDDATE := $(BUILDDATE)
AFTERCLEAN = (find . -type f -name "*.o" -delete && find . -type f -name "*.res" -delete && find src/ -type f -name "Makefile.var" -delete && find bin/ -type f -executable -delete) || true AFTERCLEAN = (find . -type f -name "*.o" -delete && find . -type f -name "*.res" -delete && find src/ -type f -name "Makefile.var" -delete && find bin/ -type f -executable -delete) || true
ifndef OPENSSL_CHECK ifndef OPENSSL_CHECK
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\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 ($(LIBSTATIC), true)
STATIC_PREFIX = -Wl,-Bstatic
STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz
endif
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -o testwssl - 2>/dev/null && rm testwssl && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -lws2_32
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB :=
else
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -lcrypt32
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else
ZLIB :=
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\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) endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\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) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\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) PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = -lpcre2-8 PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
endif endif

View File

@ -33,6 +33,7 @@
<li><a href="#NAMES">How to resolve names through a parent proxy</a></li> <li><a href="#NAMES">How to resolve names through a parent proxy</a></li>
<li><a href="#ISFTP">How to set up an FTP proxy</a></li> <li><a href="#ISFTP">How to set up an FTP proxy</a></li>
<li><a href="#TLSPR">How to set up an SNI proxy (tlspr)</a></li> <li><a href="#TLSPR">How to set up an SNI proxy (tlspr)</a></li>
<li><a href="#DNSPR">How to set up a DNS proxy (dnspr)</a></li>
<li><a href="#SSLPLUGIN">How to set up TLS/SSL (https proxy, mTLS)</a></li> <li><a href="#SSLPLUGIN">How to set up TLS/SSL (https proxy, mTLS)</a></li>
<li><a href="#CERTIFICATES">How to create CA and certificates for SSL</a></li> <li><a href="#CERTIFICATES">How to create CA and certificates for SSL</a></li>
<li><a href="#PCRE">How to use PCRE filtering (regular expressions)</a></li> <li><a href="#PCRE">How to use PCRE filtering (regular expressions)</a></li>
@ -582,6 +583,7 @@ proxy -p8080 -i192.168.2.1
An SNI proxy can be used to transparently redirect any TLS traffic with an external router or via local redirection rules. It can also be used An SNI proxy can be used to transparently redirect any TLS traffic with an external router or via local redirection rules. It can also be used
to extract hostnames from TLS to use in ACLs in combination with SOCKS or HTTP(s) proxy and/or the Transparent plugin. It can also be used to require TLS or mTLS between services. The TLS handshake contains no to extract hostnames from TLS to use in ACLs in combination with SOCKS or HTTP(s) proxy and/or the Transparent plugin. It can also be used to require TLS or mTLS between services. The TLS handshake contains no
port information; if tlspr is used as a standalone service, the destination port may be either detected with the Transparent plugin or configured with the -P option (default 443). port information; if tlspr is used as a standalone service, the destination port may be either detected with the Transparent plugin or configured with the -P option (default 443).
Note: tlspr does not support user authentication (there are no credentials in the TLS handshake to authenticate against); use ACLs by IP or a parent proxy with authentication if access control is required.
</p><p> </p><p>
<b>Options:</b> <b>Options:</b>
</p><pre> </p><pre>
@ -592,8 +594,54 @@ proxy -p8080 -i192.168.2.1
2 - require TLS, check both client and server HELLO 2 - require TLS, check both client and server HELLO
3 - require TLS, check that the server sends a certificate (not compatible with TLS 1.3) 3 - require TLS, check that the server sends a certificate (not compatible with TLS 1.3)
4 - require mutual TLS, check that the server sends a certificate request and the client sends a certificate (not compatible with TLS 1.3) 4 - require mutual TLS, check that the server sends a certificate request and the client sends a certificate (not compatible with TLS 1.3)
-Ximap | -Xpop3 | -Xsmtp - explicit TLS (STARTTLS) mode: tlspr speaks the plaintext
protocol with the client (greeting, STARTTLS command), then upgrades both sides to TLS
</pre> </pre>
<p> <p>
<b>Implicit vs explicit TLS:</b>
</p><p>
Implicit TLS means TLS from the first byte of the connection: https (443), imaps (993), SMTP submission secure (submissions) (465).
Explicit TLS means the connection starts in plaintext and is upgraded with a STARTTLS/STLS command: imap (143), SMTP submission (587), pop3 (110).
tlspr supports both: for implicit TLS the destination host is taken from SNI and the port from -P; for explicit TLS
the -X option makes tlspr speak the plaintext protocol phase with the client (greeting, STARTTLS command) before
upgrading both sides to TLS. Example:
</p><pre>
# https (implicit)
tlspr -p443 -P443 -c1
# imaps (implicit)
tlspr -p993 -P993 -c1
# submissions (implicit)
tlspr -p465 -P465 -c1
# imap STARTTLS (explicit)
tlspr -p143 -P143 -Ximap
# submission STARTTLS (explicit)
tlspr -p587 -P587 -Xsmtp
# pop3 STLS (explicit)
tlspr -p110 -P110 -Xpop3
</pre>
<p>
Note: for explicit TLS the protocol services smtpp, imapp and pop3p can be used instead of tlspr -X; they also
support STARTTLS.
</p><p>
<b>Recommended setup - traffic redirection:</b> the most universal configuration is to redirect TLS traffic
(ports 443, 993, 465, 143, 587, 110) to tlspr with external router rules or local redirection (Transparent plugin).
The original destination address and port are preserved, no -P or per-port services are required, and both implicit
and explicit TLS work with the same installation.
</p><pre>
auth iponly
allow *
tlspr -p1443 -c1
</pre>
<p>
with, for example, iptables:
</p><pre>
iptables -t nat -A PREROUTING -p tcp -m multiport --dports 443,993,465 -j REDIRECT --to-port 1443
</pre>
<p>
Alternatively, if clients use dnspr as their DNS resolver, traffic can be redirected via DNS —
see <a href="#DNSPR">How to set up a DNS proxy (dnspr)</a>.
</p>
<p>
<b>SNI Break (DPI Bypass):</b> <b>SNI Break (DPI Bypass):</b>
<br>tlspr can be used as a parent with the "tls" type to implement SNI splitting for DPI bypass (similar to NoDPI/GoodByeDPI). <br>tlspr can be used as a parent with the "tls" type to implement SNI splitting for DPI bypass (similar to NoDPI/GoodByeDPI).
The client sends the first part of the TLS ClientHello, tlspr splits it at the SNI extension and sends it in two TCP packets, The client sends the first part of the TLS ClientHello, tlspr splits it at the SNI extension and sends it in two TCP packets,
@ -638,6 +686,47 @@ parent 1000 tls 0.0.0.0 0
deny * * blocked.example.com deny * * blocked.example.com
allow * allow *
proxy proxy
</pre>
</p>
<li><a name="DNSPR"><i>How to set up a DNS proxy (dnspr)</i></a></li>
<p>
dnspr is a DNS forwarding service. It answers queries from the 3proxy name cache (including static nsrecord
entries), forwards other queries to the resolvers configured with nserver, and caches the results if
nscache/nscache6 are configured. Options:
</p><pre>
-s - simple DNS forwarding: do not use 3proxy resolver / name cache
-F&lt;ip&gt; - fake: answer all A (or AAAA) queries with the given IP address.
May be given twice - once with an IPv4 and once with an IPv6 address.
</pre>
<p>
dnspr can be used to redirect traffic by hostname, e.g. to point mail clients to a
<a href="#TLSPR">tlspr</a> installation, by adding nsrecord entries for the service hostnames
(nscache/nscache6 keep the answers for all other names intact):
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53
# google
nsrecord smtp.gmail.com 10.0.0.1
nsrecord imap.gmail.com 10.0.0.1
nsrecord pop.gmail.com 10.0.0.1
# mail.ru
nsrecord smtp.mail.ru 10.0.0.1
nsrecord imap.mail.ru 10.0.0.1
nsrecord pop.mail.ru 10.0.0.1
# yandex.ru
nsrecord smtp.yandex.ru 10.0.0.1
nsrecord imap.yandex.ru 10.0.0.1
nsrecord pop.yandex.ru 10.0.0.1
</pre>
<p>
where 10.0.0.1 is the address tlspr listens on. If every hostname must be redirected, a single fake
address can be used instead of individual nsrecords:
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53 -F10.0.0.1
</pre> </pre>
</p> </p>
<li><a name="SSLPLUGIN"><i>How to set up TLS/SSL (https proxy, mTLS)</i></a> <li><a name="SSLPLUGIN"><i>How to set up TLS/SSL (https proxy, mTLS)</i></a>
@ -1383,16 +1472,19 @@ socks -H -p1080
<p> <p>
<b>Sending PROXY protocol header to parent proxy:</b> <b>Sending PROXY protocol header to parent proxy:</b>
<br>Use the <code>ha</code> parent type to send a PROXY protocol v1 header to <br>Use the <code>ha</code> parent type to send a PROXY protocol v1 header to
the parent proxy. This must be the last parent in the chain: the parent proxy. Place <code>ha</code> before the parent that should receive
the header; after the header is sent, parent protocol negotiation continues:
</p><pre> </p><pre>
allow * allow *
parent 1000 ha parent 1000 ha 0.0.0.0 0
parent 1000 socks5 parent.example.com 1080 parent 1000 socks5 parent.example.com 1080
socks proxy
</pre> </pre>
<p> <p>
This configuration sends the client IP information to the SOCKS5 parent proxy This configuration connects to the SOCKS5 parent, sends the PROXY protocol
via the PROXY protocol. header with the original client IP, then performs SOCKS5 negotiation before
relaying the client payload. The parent should use <code>-H</code> to accept
the header (for example <code>socks -H</code>).
</p> </p>
<li><a name="MAXSEG"><i>How to set TCP maximum segment size (MSS)</i></a> <li><a name="MAXSEG"><i>How to set TCP maximum segment size (MSS)</i></a>
<p> <p>

View File

@ -33,6 +33,7 @@
<li><a href="#NAMES">Как разрешать имена на родительском прокси?</a></li> <li><a href="#NAMES">Как разрешать имена на родительском прокси?</a></li>
<li><a href="#ISFTP">Как настроить FTP прокси?</a></li> <li><a href="#ISFTP">Как настроить FTP прокси?</a></li>
<li><a href="#TLSPR">Как настроить SNI proxy (tlspr)</a></li> <li><a href="#TLSPR">Как настроить SNI proxy (tlspr)</a></li>
<li><a href="#DNSPR">Как настроить DNS proxy (dnspr)</a></li>
<li><a href="#SSLPLUGIN">Как настроить TLS/SSL (https прокси, mTLS)</a></li> <li><a href="#SSLPLUGIN">Как настроить TLS/SSL (https прокси, mTLS)</a></li>
<li><a href="#CERTIFICATES">Как создать CA и сертификаты для SSL</a></li> <li><a href="#CERTIFICATES">Как создать CA и сертификаты для SSL</a></li>
<li><a href="#PCRE">Как использовать PCRE-фильтрацию (регулярные выражения)</a></li> <li><a href="#PCRE">Как использовать PCRE-фильтрацию (регулярные выражения)</a></li>
@ -590,6 +591,7 @@
Еще одна задача которую может решать модуль - требование наличия TLS или mTLS (mutual TLS). Еще одна задача которую может решать модуль - требование наличия TLS или mTLS (mutual TLS).
Если tlspr используется как отдельный сервис без использования плагина Transparent, то необходимо задать порт назначения через опцию -P (по умолчанию 443), Если tlspr используется как отдельный сервис без использования плагина Transparent, то необходимо задать порт назначения через опцию -P (по умолчанию 443),
т.к. TLS хендшейк не содержит информации о порте назначения. т.к. TLS хендшейк не содержит информации о порте назначения.
Примечание: tlspr не поддерживает аутентификацию пользователей (в TLS-хендшейке нет учетных данных); используйте ACL по IP или родительский прокси с аутентификацией, если требуется контроль доступа.
</p><p> </p><p>
<b>Опции:</b> <b>Опции:</b>
</p><pre> </p><pre>
@ -600,8 +602,54 @@
2 - требовать TLS, проверять наличие client и server HELLO 2 - требовать TLS, проверять наличие client и server HELLO
3 - требовать TLS, проверять наличие серверного сертификата (не совместим с TLS 1.3+) 3 - требовать TLS, проверять наличие серверного сертификата (не совместим с TLS 1.3+)
4 - требовать взаимный (mutual) TLS, проверять что сервер запрашивает сертификат и клиент его отправляет (не совместим с TLS 1.3+) 4 - требовать взаимный (mutual) TLS, проверять что сервер запрашивает сертификат и клиент его отправляет (не совместим с TLS 1.3+)
-Ximap | -Xpop3 | -Xsmtp - режим explicit TLS (STARTTLS): tlspr говорит с клиентом
на plaintext-протоколе (приветствие, команда STARTTLS), затем поднимает TLS с обеих сторон
</pre> </pre>
<p> <p>
<b>Implicit и explicit TLS:</b>
</p><p>
Implicit TLS означает TLS с первого байта соединения: https (443), imaps (993), SMTP submission secure (submissions) (465).
Explicit TLS означает, что соединение начинается в plaintext и поднимается до TLS командой STARTTLS/STLS: imap (143), SMTP submission (587), pop3 (110).
tlspr поддерживает оба варианта: для implicit TLS хост назначения берется из SNI, а порт из -P; для explicit TLS
опция -X заставляет tlspr говорить с клиентом на plaintext-фазе протокола (приветствие, команда STARTTLS) перед
поднятием TLS с обеих сторон. Пример:
</p><pre>
# https (implicit)
tlspr -p443 -P443 -c1
# imaps (implicit)
tlspr -p993 -P993 -c1
# submissions (implicit)
tlspr -p465 -P465 -c1
# imap STARTTLS (explicit)
tlspr -p143 -P143 -Ximap
# submission STARTTLS (explicit)
tlspr -p587 -P587 -Xsmtp
# pop3 STLS (explicit)
tlspr -p110 -P110 -Xpop3
</pre>
<p>
Примечание: для explicit TLS вместо tlspr -X можно использовать протокольные сервисы smtpp, imapp и pop3p; они
также поддерживают STARTTLS.
</p><p>
<b>Рекомендуемая конфигурация - перенаправление трафика:</b> наиболее универсальная конфигурация - перенаправлять
TLS-трафик (порты 443, 993, 465, 143, 587, 110) на tlspr правилами внешнего маршрутизатора или локальными
правилами (плагин Transparent). Исходные адрес и порт назначения сохраняются, -P и отдельные сервисы для каждого
порта не требуются, implicit и explicit TLS работают в рамках одной установки.
</p><pre>
auth iponly
allow *
tlspr -p1443 -c1
</pre>
<p>
например, с iptables:
</p><pre>
iptables -t nat -A PREROUTING -p tcp -m multiport --dports 443,993,465 -j REDIRECT --to-port 1443
</pre>
<p>
Также, если клиенты используют dnspr в качестве DNS-резолвера, трафик можно перенаправлять через DNS —
см. <a href="#DNSPR">Как настроить DNS proxy (dnspr)</a>.
</p>
<p>
<b>SNI Break (обход DPI):</b> <b>SNI Break (обход DPI):</b>
<br>tlspr может использоваться как родительский прокси типа "tls" для реализации SNI-фрагментации (аналог NoDPI/GoodByeDPI). <br>tlspr может использоваться как родительский прокси типа "tls" для реализации SNI-фрагментации (аналог NoDPI/GoodByeDPI).
Клиент отправляет первую часть TLS ClientHello, tlspr разбивает его на расширении SNI и отправляет двумя TCP-пакетами, Клиент отправляет первую часть TLS ClientHello, tlspr разбивает его на расширении SNI и отправляет двумя TCP-пакетами,
@ -649,6 +697,48 @@ proxy
</pre> </pre>
</p> </p>
<li><a name="DNSPR"><i>Как настроить DNS proxy (dnspr)</i></a></li>
<p>
dnspr - сервис пересылки DNS-запросов. Он отвечает на запросы из кэша имен 3proxy (включая статические записи
nsrecord), пересылает остальные запросы на резолверы, заданные командой nserver, и кэширует результаты, если
настроены nscache/nscache6. Опции:
</p><pre>
-s - простая пересылка DNS: не использовать резолвер / кэш имен 3proxy
-F&lt;ip&gt; - fake: отвечать на все A (или AAAA) запросы заданным IP-адресом.
Может быть указана дважды - один раз с IPv4 и один раз с IPv6 адресом.
</pre>
<p>
dnspr можно использовать для перенаправления трафика по имени хоста, например, чтобы направить почтовых
клиентов на установку <a href="#TLSPR">tlspr</a>, добавив записи nsrecord для имен почтовых сервисов
(nscache/nscache6 сохраняют ответы для всех остальных имен):
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53
# google
nsrecord smtp.gmail.com 10.0.0.1
nsrecord imap.gmail.com 10.0.0.1
nsrecord pop.gmail.com 10.0.0.1
# mail.ru
nsrecord smtp.mail.ru 10.0.0.1
nsrecord imap.mail.ru 10.0.0.1
nsrecord pop.mail.ru 10.0.0.1
# yandex.ru
nsrecord smtp.yandex.ru 10.0.0.1
nsrecord imap.yandex.ru 10.0.0.1
nsrecord pop.yandex.ru 10.0.0.1
</pre>
<p>
где 10.0.0.1 - адрес, на котором слушает tlspr. Если перенаправлять нужно все имена, вместо отдельных
записей nsrecord можно использовать один fake-адрес:
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53 -F10.0.0.1
</pre>
</p>
<li><a name="SSLPLUGIN"><i>Как настроить TLS/SSL (https прокси, mTLS)</i></a> <li><a name="SSLPLUGIN"><i>Как настроить TLS/SSL (https прокси, mTLS)</i></a>
<p> <p>
Начиная с версии 0.9.7 поддержка TLS/SSL встроена в 3proxy при компиляции с OpenSSL Начиная с версии 0.9.7 поддержка TLS/SSL встроена в 3proxy при компиляции с OpenSSL
@ -1441,16 +1531,20 @@ socks -H -p1080
<p> <p>
<b>Отправка заголовка PROXY протокола родительскому прокси:</b> <b>Отправка заголовка PROXY протокола родительскому прокси:</b>
<br>Используйте тип родительского прокси <code>ha</code> для отправки заголовка <br>Используйте тип родительского прокси <code>ha</code> для отправки заголовка
PROXY протокола v1 родительскому прокси. Это должен быть последний родитель в цепочке: PROXY протокола v1 родительскому прокси. Укажите <code>ha</code> перед родителем,
который должен получить заголовок; после отправки заголовка продолжается
хендшейк протокола родителя:
</p><pre> </p><pre>
allow * allow *
parent 1000 ha parent 1000 ha 0.0.0.0 0
parent 1000 socks5 parent.example.com 1080 parent 1000 socks5 parent.example.com 1080
socks proxy
</pre> </pre>
<p> <p>
Эта конфигурация отправляет информацию об IP-адресе клиента SOCKS5 родительскому Эта конфигурация подключается к SOCKS5 родителю, отправляет PROXY заголовок
прокси через PROXY протокол. с исходным IP клиента, затем выполняет SOCKS5-хендшейк и только после этого
передаёт полезную нагрузку. Родитель должен использовать <code>-H</code>
(например <code>socks -H</code>).
</p> </p>
<li><a name="MAXSEG"><i>Как установить максимальный размер сегмента TCP (MSS)</i></a> <li><a name="MAXSEG"><i>Как установить максимальный размер сегмента TCP (MSS)</i></a>
<p> <p>

View File

@ -8,6 +8,7 @@
<br><A HREF="man8/3proxy_crypt.8.html">3proxy_crypt.8</A> <br><A HREF="man8/3proxy_crypt.8.html">3proxy_crypt.8</A>
<br><A HREF="man8/3proxy.8.html">3proxy.8</A> <br><A HREF="man8/3proxy.8.html">3proxy.8</A>
<br><A HREF="man8/ftppr.8.html">ftppr.8</A> <br><A HREF="man8/ftppr.8.html">ftppr.8</A>
<br><A HREF="man8/imapp.8.html">imapp.8</A>
<br><A HREF="man8/pop3p.8.html">pop3p.8</A> <br><A HREF="man8/pop3p.8.html">pop3p.8</A>
<br><A HREF="man8/proxy.8.html">proxy.8</A> <br><A HREF="man8/proxy.8.html">proxy.8</A>
<br><A HREF="man8/smtpp.8.html">smtpp.8</A> <br><A HREF="man8/smtpp.8.html">smtpp.8</A>

View File

@ -87,6 +87,7 @@ start gateway services:</p>
[options] <b><br> [options] <b><br>
socks</b> [options] <b><br> socks</b> [options] <b><br>
pop3p</b> [options] <b><br> pop3p</b> [options] <b><br>
imapp</b> [options] <b><br>
smtpp</b> [options] <b><br> smtpp</b> [options] <b><br>
ftppr</b> [options] <b><br> ftppr</b> [options] <b><br>
admin</b> [options] <b><br> admin</b> [options] <b><br>
@ -104,6 +105,7 @@ handshake), may be used to redirect any TLS-based traffic
auto</b> Proxy with protocol autoselection between proxy / auto</b> Proxy with protocol autoselection between proxy /
socks / tlspr <b><br> socks / tlspr <b><br>
pop3p</b> POP3 proxy (default port 110) <b><br> pop3p</b> POP3 proxy (default port 110) <b><br>
imapp</b> IMAPv4 proxy (default port 143) <b><br>
smtpp</b> SMTP proxy (default port 25) <b><br> smtpp</b> SMTP proxy (default port 25) <b><br>
ftppr</b> FTP proxy (default port 21) <b><br> ftppr</b> FTP proxy (default port 21) <b><br>
admin</b> Web interface (default port 80) <b><br> admin</b> Web interface (default port 80) <b><br>
@ -220,8 +222,8 @@ information reported) <b><br>
-a2</b> (for proxy) generate Via: and X-Forwarded-For: -a2</b> (for proxy) generate Via: and X-Forwarded-For:
instead of Forwarded: <br> instead of Forwarded: <br>
Also, all options mentioned for <b>proxy</b>(8) Also, all options mentioned for <b>proxy</b>(8)
<b>socks</b>(8) <b>pop3p</b>(8) <b>tcppm</b>(8) <b>socks</b>(8) <b>pop3p</b>(8) <b>imapp</b>(8)
<b>udppm</b>(8) <b>ftppr</b>(8) <br> <b>tcppm</b>(8) <b>udppm</b>(8) <b>ftppr</b>(8) <br>
are also supported. <br> are also supported. <br>
Portmapping services listen at SRCPORT and connect to Portmapping services listen at SRCPORT and connect to
DSTADDR:DSTPORT HTTP and SOCKS proxies are standard. <br> DSTADDR:DSTPORT HTTP and SOCKS proxies are standard. <br>
@ -757,10 +759,15 @@ useful). Never use this option unless you know exactly you
need it. <b><br> need it. <b><br>
admin</b> redirect request to local &acute;admin&acute; admin</b> redirect request to local &acute;admin&acute;
service (with -s parameter). <b><br> service (with -s parameter). <b><br>
ha</b> send HAProxy PROXY protocol v1 header to parent ha</b> send HAProxy PROXY protocol v1 header to the next
proxy. Must be the last in the proxy chain. Useful for parent proxy (or to the destination if <b>ha</b> is used
passing client IP information to the parent proxy. Example: alone). Place <b>ha</b> before the parent that should
parent 1000 ha <br> receive the header; after the header is sent, negotiation
of that parent protocol continues (SOCKS, CONNECT, etc.).
Useful for passing client IP information to the parent
proxy. Example: <br>
parent 1000 ha 0.0.0.0 0 <br>
parent 1000 socks5 parent.example.com 1080 <br>
Use &quot;+&quot; proxy only with <b>fakeresolve</b> option Use &quot;+&quot; proxy only with <b>fakeresolve</b> option
<br> <br>
Any parent type above can be suffixed with <b>s</b> (e.g. Any parent type above can be suffixed with <b>s</b> (e.g.
@ -779,8 +786,9 @@ special case of local redirection, it works only with
<b>socks</b> proxy. In case of local redirection request is <b>socks</b> proxy. In case of local redirection request is
redirected to different service, <b>ftp</b> locally redirected to different service, <b>ftp</b> locally
redirects to <b>ftppr pop3</b> locally redirects to <b>pop3p redirects to <b>ftppr pop3</b> locally redirects to <b>pop3p
http</b> locally redirects to <b>proxy admin</b> locally imap</b> locally redirects to <b>imapp http</b> locally
redirects to the admin -s service. <br> redirects to <b>proxy admin</b> locally redirects to the
admin -s service. <br>
Unix domain sockets can be used instead of IP address with Unix domain sockets can be used instead of IP address with
the syntax <i>unix:/path/to/socket</i> (e.g., parent 1000 the syntax <i>unix:/path/to/socket</i> (e.g., parent 1000
socks5 unix:/var/run/parent.sock 1080). On Linux, abstract socks5 unix:/var/run/parent.sock 1080). On Linux, abstract
@ -1294,7 +1302,8 @@ to <b>3proxy@3proxy.org</b></p>
<p style="margin-left:6%; margin-top: 1em">3proxy(8), <p style="margin-left:6%; margin-top: 1em">3proxy(8),
3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8), 3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8),
smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8), <br> imapp(8), smtpp(8), tlspr(8), tcppm(8), udppm(8),
syslogd(8), <br>
https://3proxy.org/</p> https://3proxy.org/</p>
<h2>AUTHORS <h2>AUTHORS

View File

@ -58,11 +58,11 @@ multiple gateways with HTTP and HTTPS proxy with FTP over
HTTP support, SOCKS v4, v4.5 and v5, POP3 proxy, UDP and TCP HTTP support, SOCKS v4, v4.5 and v5, POP3 proxy, UDP and TCP
portmappers. Each gateway is started from the configuration portmappers. Each gateway is started from the configuration
file like an independent service <b>proxy</b>(8) file like an independent service <b>proxy</b>(8)
<b>socks</b>(8) <b>pop3p</b>(8) <b>tcppm</b>(8) <b>socks</b>(8) <b>pop3p</b>(8) <b>imapp</b>(8)
<b>udppm</b>(8) <b>ftppr</b>(8) <b>dnspr</b> but <b>tcppm</b>(8) <b>udppm</b>(8) <b>ftppr</b>(8) <b>dnspr</b>
<b>3proxy</b> is not a kind of wrapper or superserver for but <b>3proxy</b> is not a kind of wrapper or superserver
these daemons. It just has the same code compiled in, but for these daemons. It just has the same code compiled in,
provides much more functionality. SOCKSv5 implementation but provides much more functionality. SOCKSv5 implementation
allows you to use 3proxy with any UDP or TCP based client allows you to use 3proxy with any UDP or TCP based client
applications designed without proxy support (with applications designed without proxy support (with
<i>SocksCAP</i>, <i>FreeCAP</i> or another client-side <i>SocksCAP</i>, <i>FreeCAP</i> or another client-side
@ -195,8 +195,8 @@ to <b>3proxy@3proxy.org</b></p>
<p style="margin-left:6%; margin-top: 1em">3proxy.cfg(5), <p style="margin-left:6%; margin-top: 1em">3proxy.cfg(5),
proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8), proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), tcppm(8),
kill(1), syslogd(8), <br> udppm(8), kill(1), syslogd(8), <br>
https://3proxy.org/</p> https://3proxy.org/</p>
<h2>AUTHORS <h2>AUTHORS

287
doc/html/man8/imapp.8.html Normal file
View File

@ -0,0 +1,287 @@
<!-- Creator : groff version 1.24.1 -->
<html>
<head>
</head>
<body>
<h1 align="center">imapp</h1>
<a href="#NAME">NAME</a><br>
<a href="#SYNOPSIS">SYNOPSIS</a><br>
<a href="#DESCRIPTION">DESCRIPTION</a><br>
<a href="#OPTIONS">OPTIONS</a><br>
<a href="#CLIENTS">CLIENTS</a><br>
<a href="#BUGS">BUGS</a><br>
<a href="#SEE ALSO">SEE ALSO</a><br>
<a href="#AUTHORS">AUTHORS</a><br>
<hr>
<h2>NAME
<a name="NAME"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>imapp</b> -
IMAPv4 proxy gateway service</p>
<h2>SYNOPSIS
<a name="SYNOPSIS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>imapp</b>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION
<a name="DESCRIPTION"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><i><b>imapp</b></i>
is IMAPv4 (IMAP4rev1) gateway service to allow internal
users to access external IMAP servers.</p>
<h2>OPTIONS
<a name="OPTIONS"></a>
</h2>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-I</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Inetd mode. Standalone service
only.</p> </td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-d</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Daemonize. Detach service from
console and run in the background.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-t</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Be silenT. Do not log
start/stop/accept error records.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-u</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Never look for username
authentication.</p> </td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-e</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">External address. IP address of
the interface the proxy should initiate connections from. By
default, the system will decide which address to use in
accordance with the routing table.</p></td></tr>
</table>
<p style="margin-left:6%;"><b>-ni</b><i>PATH</i></p>
<p style="margin-left:15%;">(Linux only) Switch to the
network namespace identified by <i>PATH</i> before opening
the listening socket. The current namespace is saved and
restored immediately after binding, so outgoing connections
run in the original namespace unless <b>-ne</b> is also
given.</p>
<p style="margin-left:6%;"><b>-ne</b><i>PATH</i></p>
<p style="margin-left:15%;">(Linux only) Switch to the
network namespace identified by <i>PATH</i> after the
listening socket has been bound (and after restoring from
<b>-ni</b> if applicable). Both options accept any namespace
file path (e.g. <i>/var/run/netns/myns</i> or
<i>/proc/PID/ns/net</i>) and require
<b>CAP_SYS_ADMIN</b>.</p>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p><b>-i</b></p></td>
<td width="6%"></td>
<td width="85%">
<p>Internal address. IP address the proxy accepts
connections to. By default, connections to any interface are
accepted. It&acute;s usually unsafe. Unix domain sockets can
be specified with <i>-iunix:/path/to/socket</i> syntax
(e.g., -iunix:/var/run/imapp.sock). On Linux, abstract
sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-p</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Port. Port proxy listens for
incoming connections. Default is 143.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-h</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Default destination. It&rsquo;s
used if the target address is not specified by the user.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS support.
STARTTLS is not announced in the CAPABILITY response and the
STARTTLS command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Log. By default logging is to
stdout. If <i>logfile</i> is specified logging is to file.
Under Unix, if &acute;<i>@</i>&acute; precedes
<i>logfile</i>, syslog is used for logging.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-S</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Increase or decrease stack size.
You may want to try something like -S8192 if you experience
3proxy crashes.</p></td></tr>
</table>
<h2>CLIENTS
<a name="CLIENTS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">You can use any
MUA (Mail User Agent) with IMAPv4 support. Set the client to
use <i>internal_ip</i> and <i>port</i> as an IMAP server.
The address of the real IMAP server must be configured as a
part of the IMAP username. The format for the username is
<i>username</i>@<i>server</i>, where <i>server</i> is the
address of the IMAP server and <i>username</i> is the
user&acute;s login on this IMAP server. The login itself may
contain an &acute;@&acute; sign. Supported client
authentication methods are the LOGIN command, AUTHENTICATE
PLAIN and AUTHENTICATE LOGIN. With the server, the proxy
authenticates using the method chosen by the client if the
server supports it (as advertised in the CAPABILITY
response); otherwise it falls back to AUTHENTICATE LOGIN,
AUTHENTICATE PLAIN or the LOGIN command, in this order of
preference. Challenge-response authentication (CRAM-MD5,
etc.) is not supported, because it requires a challenge from
the server before we know which server to connect to. When
running as a 3proxy service (not as a standalone binary),
STARTTLS is supported and announced in the CAPABILITY
response unless disabled with <b>-x</b>. After the client
issues STARTTLS, the connection is handled by
<b>tlspr</b>(8): the destination host is taken from the SNI
of the client TLS handshake (or from the -h option), the
proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between
the client and the server. If the destination server does
not support STARTTLS, the TLS handshake with the client
fails.</p>
<h2>BUGS
<a name="BUGS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">Report all bugs
to <b>3proxy@3proxy.org</b></p>
<h2>SEE ALSO
<a name="SEE ALSO"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">3proxy(8),
ftppr(8), pop3p(8), proxy(8), smtpp(8), socks(8), tcppm(8),
tlspr(8), udppm(8), syslogd(8), <br>
https://3proxy.org/</p>
<h2>AUTHORS
<a name="AUTHORS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
<hr>
</body>
</html>

View File

@ -36,15 +36,16 @@ POP3 proxy gateway service</p>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]] [<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>] [<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>] [<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>]</p> [<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION <h2>DESCRIPTION
<a name="DESCRIPTION"></a> <a name="DESCRIPTION"></a>
</h2> </h2>
<p style="margin-left:6%; margin-top: 1em"><b>pop3p</b> is
POP3 gateway service to allow internal users to access <p style="margin-left:6%; margin-top: 1em"><i><b>pop3p</b></i>
is POP3 gateway service to allow internal users to access
external POP3 servers.</p> external POP3 servers.</p>
<h2>OPTIONS <h2>OPTIONS
@ -184,6 +185,19 @@ used if the target address is not specified by the user.</p></td></tr>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS (STLS) support.
STLS is not announced in the CAPA response and the STLS
command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td> <p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -224,8 +238,17 @@ user&acute;s login on this POP3 server. The login itself may
contain an &acute;@&acute; sign. Only cleartext contain an &acute;@&acute; sign. Only cleartext
authentication is supported, because challenge-response authentication is supported, because challenge-response
authentication (APOP, CRAM-MD5, etc.) requires a challenge authentication (APOP, CRAM-MD5, etc.) requires a challenge
from the server before we know which server to connect from the server before we know which server to connect to.
to.</p> When running as a 3proxy service (not as a standalone
binary), STLS is supported and announced in the CAPA
response unless disabled with <b>-x</b>. After the client
issues STLS, the connection is handled by <b>tlspr</b>(8):
the destination host is taken from the SNI of the client TLS
handshake (or from the -h option), the proxy performs STLS
negotiation with the destination server, and then
transparently passes TLS traffic between the client and the
server. If the destination server does not support STLS, the
TLS handshake with the client fails.</p>
<h2>BUGS <h2>BUGS
<a name="BUGS"></a> <a name="BUGS"></a>

View File

@ -36,15 +36,16 @@ SMTP proxy gateway service</p>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]] [<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>] [<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>] [<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>]</p> [<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION <h2>DESCRIPTION
<a name="DESCRIPTION"></a> <a name="DESCRIPTION"></a>
</h2> </h2>
<p style="margin-left:6%; margin-top: 1em"><b>smtpp</b> is
SMTP gateway service to allow internal users to access <p style="margin-left:6%; margin-top: 1em"><i><b>smtpp</b></i>
is SMTP gateway service to allow internal users to access
external SMTP servers.</p> external SMTP servers.</p>
<h2>OPTIONS <h2>OPTIONS
@ -166,7 +167,7 @@ sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<p style="margin-top: 1em">Port. Port proxy listens for <p style="margin-top: 1em">Port. Port proxy listens for
incoming connections. Default is 25.</p></td></tr> incoming connections. Default is 587.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -184,6 +185,19 @@ used if the target address is not specified by the user.</p></td></tr>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS support.
STARTTLS is not announced in the EHLO response and the
STARTTLS command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td> <p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -225,7 +239,17 @@ server. The login itself may contain an &acute;@&acute;
sign. Only cleartext authentication is supported, because sign. Only cleartext authentication is supported, because
challenge-response authentication (CRAM-MD5, SPA, etc.) challenge-response authentication (CRAM-MD5, SPA, etc.)
requires a challenge from the server before we know which requires a challenge from the server before we know which
server to connect to.</p> server to connect to. When running as a 3proxy service (not
as a standalone binary), STARTTLS is supported and announced
in the EHLO response unless disabled with <b>-x</b>. After
the client issues STARTTLS, the connection is handled by
<b>tlspr</b>(8): the destination host is taken from the SNI
of the client TLS handshake (or from the -h option), the
proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between
the client and the server. If the destination server does
not support STARTTLS, the TLS handshake with the client
fails.</p>
<h2>BUGS <h2>BUGS
<a name="BUGS"></a> <a name="BUGS"></a>

View File

@ -49,7 +49,9 @@ SNI proxy gateway service</p>
an SNI gateway service (destination host is taken from TLS an SNI gateway service (destination host is taken from TLS
handshake). The destination port must be specified via the handshake). The destination port must be specified via the
-P option (or it may be detected with the Transparent -P option (or it may be detected with the Transparent
plugin).</p> plugin). tlspr does not support user authentication; use
ACLs by client IP or a parent proxy with authentication if
access control is required.</p>
<h2>OPTIONS <h2>OPTIONS
<a name="OPTIONS"></a> <a name="OPTIONS"></a>
@ -241,27 +243,45 @@ with TLS 1.3)</p></td></tr>
packet across multiple TCP segments to make SNI-based DPI packet across multiple TCP segments to make SNI-based DPI
detection harder. An optional numeric value can follow (e.g. detection harder. An optional numeric value can follow (e.g.
<b>-s1</b>) to control the splitting behaviour.</p></td></tr> <b>-s1</b>) to control the splitting behaviour.</p></td></tr>
</table>
<p style="margin-left:6%;"><b>-Ximap | -Xpop3 |
-Xsmtp</b></p>
<p style="margin-left:15%;">STARTTLS mode for the given
protocol. The proxy speaks the plaintext protocol with the
client (greeting, capability advertisement with STARTTLS
only, STARTTLS command), then, after the client issues
STARTTLS and sends a TLS Client HELLO, connects to the
destination taken from SNI (default port 143/110/587),
performs STARTTLS negotiation with the destination server
and transparently passes TLS traffic. If the destination
server does not support STARTTLS, the TLS handshake with the
client fails.</p>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td> <p><b>-l</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Log. By default logging is to <p>Log. By default logging is to stdout. If <i>logfile</i>
stdout. If <i>logfile</i> is specified logging is to file. is specified logging is to file. Under Unix, if
Under Unix, if &acute;<i>@</i>&acute; precedes &acute;<i>@</i>&acute; precedes <i>logfile</i>, syslog is
<i>logfile</i>, syslog is used for logging.</p></td></tr> used for logging.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-S</b></p></td> <p style="margin-top: 1em"><b>-S</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">

View File

@ -29,6 +29,7 @@ from the configuration file like an independent service
.BR proxy (8) .BR proxy (8)
.BR socks (8) .BR socks (8)
.BR pop3p (8) .BR pop3p (8)
.BR imapp (8)
.BR tcppm (8) .BR tcppm (8)
.BR udppm (8) .BR udppm (8)
.BR ftppr (8) .BR ftppr (8)
@ -140,7 +141,7 @@ configuration file
Report all bugs to Report all bugs to
.BR 3proxy@3proxy.org .BR 3proxy@3proxy.org
.SH SEE ALSO .SH SEE ALSO
3proxy.cfg(5), proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8), 3proxy.cfg(5), proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), tcppm(8), udppm(8),
kill(1), syslogd(8), kill(1), syslogd(8),
.br .br
https://3proxy.org/ https://3proxy.org/

View File

@ -55,6 +55,9 @@ Recursion is not allowed.
.B pop3p .B pop3p
[options] [options]
.br .br
.B imapp
[options]
.br
.B smtpp .B smtpp
[options] [options]
.br .br
@ -92,6 +95,9 @@ Proxy with protocol autoselection between proxy / socks / tlspr
.B pop3p .B pop3p
POP3 proxy (default port 110) POP3 proxy (default port 110)
.br .br
.B imapp
IMAPv4 proxy (default port 143)
.br
.B smtpp .B smtpp
SMTP proxy (default port 25) SMTP proxy (default port 25)
.br .br
@ -209,6 +215,7 @@ Never ask for username/password
.BR proxy (8) .BR proxy (8)
.BR socks (8) .BR socks (8)
.BR pop3p (8) .BR pop3p (8)
.BR imapp (8)
.BR tcppm (8) .BR tcppm (8)
.BR udppm (8) .BR udppm (8)
.BR ftppr (8) .BR ftppr (8)
@ -821,9 +828,16 @@ unless you know exactly you need it.
.br .br
\fBadmin\fR redirect request to local \'admin\' service (with -s parameter). \fBadmin\fR redirect request to local \'admin\' service (with -s parameter).
.br .br
\fBha\fR send HAProxy PROXY protocol v1 header to parent proxy. Must be the last \fBha\fR send HAProxy PROXY protocol v1 header to the next parent proxy (or to
in the proxy chain. Useful for passing client IP information to the parent proxy. the destination if \fBha\fR is used alone). Place \fBha\fR before the parent
Example: parent 1000 ha that should receive the header; after the header is sent, negotiation of that
parent protocol continues (SOCKS, CONNECT, etc.). Useful for passing client IP
information to the parent proxy.
Example:
.br
parent 1000 ha 0.0.0.0 0
.br
parent 1000 socks5 parent.example.com 1080
.br .br
Use "+" proxy only with \fBfakeresolve\fR option Use "+" proxy only with \fBfakeresolve\fR option
.br .br
@ -847,6 +861,9 @@ locally redirects to
.B pop3 .B pop3
locally redirects to locally redirects to
.B pop3p .B pop3p
.B imap
locally redirects to
.B imapp
.B http .B http
locally redirects to locally redirects to
.B proxy .B proxy
@ -1384,7 +1401,7 @@ authentication and/or allow/deny ACLs.
Report all bugs to Report all bugs to
.BR 3proxy@3proxy.org .BR 3proxy@3proxy.org
.SH SEE ALSO .SH SEE ALSO
3proxy(8), 3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8), smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8), 3proxy(8), 3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8),
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS

124
man/imapp.8 Normal file
View File

@ -0,0 +1,124 @@
.TH imapp "8" "July 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME
.B imapp
\- IMAPv4 proxy gateway service
.SH SYNOPSIS
.BR "imapp " [ -d ]
.IB \fR[ -l \fR[ \fR[ @ \fR] logfile \fR]]
.IB \fR[ -p port\fR]
.IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION
.B imapp
is IMAPv4 (IMAP4rev1) gateway service to allow internal users to access external
IMAP servers.
.SH OPTIONS
.TP
.B -I
Inetd mode. Standalone service only.
.TP
.B -d
Daemonize. Detach service from console and run in the background.
.TP
.B -t
Be silenT. Do not log start/stop/accept error records.
.TP
.B -u
Never look for username authentication.
.TP
.B -e
External address. IP address of the interface the proxy should initiate connections
from.
By default, the system will decide which address to use in accordance
with the routing table.
.TP
.B \-ni\fIPATH\fR
(Linux only) Switch to the network namespace identified by
.I PATH
before opening the listening socket. The current namespace is saved and restored
immediately after binding, so outgoing connections run in the original namespace
unless
.B \-ne
is also given.
.TP
.B \-ne\fIPATH\fR
(Linux only) Switch to the network namespace identified by
.I PATH
after the listening socket has been bound (and after restoring from
.B \-ni
if applicable). Both options accept any namespace file path
(e.g.\& \fI/var/run/netns/myns\fR or \fI/proc/PID/ns/net\fR)
and require \fBCAP_SYS_ADMIN\fR.
.TP
.B -i
Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe.
Unix domain sockets can be specified with
.I -iunix:/path/to/socket
syntax (e.g., -iunix:/var/run/imapp.sock). On Linux, abstract sockets use
.I -iunix:@socketname
syntax.
.TP
.B -p
Port. Port proxy listens for incoming connections. Default is 143.
.TP
.B -h
Default destination. It's used if the target address is not specified by the user.
.TP
.B -x
Disable STARTTLS support. STARTTLS is not announced in the CAPABILITY
response and the STARTTLS command is not accepted.
.TP
.B -l
Log. By default logging is to stdout. If
.I logfile
is specified logging is to file. Under Unix, if
.RI \' @ \'
precedes
.IR logfile ,
syslog is used for logging.
.TP
.B -S
Increase or decrease stack size. You may want to try something like -S8192 if you experience 3proxy
crashes.
.SH CLIENTS
You can use any MUA (Mail User Agent) with IMAPv4 support. Set the client to use
.I internal_ip
and
.IR port
as an IMAP server. The address of the real IMAP server must be configured as a part of
the IMAP username. The format for the username is
.IR username @ server ,
where
.I server
is the address of the IMAP server and
.I username
is the user\'s login on this IMAP server. The login itself may contain an \'@\' sign.
Supported client authentication methods are the LOGIN command, AUTHENTICATE PLAIN
and AUTHENTICATE LOGIN. With the server, the proxy authenticates using the method
chosen by the client if the server supports it (as advertised in the CAPABILITY
response); otherwise it falls back to AUTHENTICATE LOGIN, AUTHENTICATE PLAIN or
the LOGIN command, in this order of preference. Challenge-response authentication
(CRAM-MD5, etc.) is not supported, because it requires a challenge from the server
before we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STARTTLS is
supported and announced in the CAPABILITY response unless disabled with
.BR -x .
After the client issues STARTTLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.SH BUGS
Report all bugs to
.BR 3proxy@3proxy.org
.SH SEE ALSO
3proxy(8), ftppr(8), pop3p(8), proxy(8), smtpp(8), socks(8), tcppm(8), tlspr(8), udppm(8), syslogd(8),
.br
https://3proxy.org/
.SH AUTHORS
3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>

View File

@ -9,6 +9,7 @@
.IB \fR[ -i internal_ip\fR] .IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR] .IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR] .IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION .SH DESCRIPTION
.B pop3p .B pop3p
is POP3 gateway service to allow internal users to access external POP3 is POP3 gateway service to allow internal users to access external POP3
@ -66,6 +67,10 @@ Port. Port proxy listens for incoming connections. Default is 110.
.B -h .B -h
Default destination. It's used if the target address is not specified by the user. Default destination. It's used if the target address is not specified by the user.
.TP .TP
.B -x
Disable STARTTLS (STLS) support. STLS is not announced in the CAPA response
and the STLS command is not accepted.
.TP
.B -l .B -l
Log. By default logging is to stdout. If Log. By default logging is to stdout. If
.I logfile .I logfile
@ -94,6 +99,16 @@ is the user\'s login on this POP3 server. The login itself may contain an \'@\'
Only cleartext authentication is supported, because challenge-response Only cleartext authentication is supported, because challenge-response
authentication (APOP, CRAM-MD5, etc.) requires a challenge from the server before authentication (APOP, CRAM-MD5, etc.) requires a challenge from the server before
we know which server to connect to. we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STLS is
supported and announced in the CAPA response unless disabled with
.BR -x .
After the client issues STLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STLS, the TLS handshake
with the client fails.
.SH BUGS .SH BUGS
Report all bugs to Report all bugs to
.BR 3proxy@3proxy.org .BR 3proxy@3proxy.org

View File

@ -9,6 +9,7 @@
.IB \fR[ -i internal_ip\fR] .IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR] .IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR] .IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION .SH DESCRIPTION
.B smtpp .B smtpp
is SMTP gateway service to allow internal users to access external SMTP is SMTP gateway service to allow internal users to access external SMTP
@ -61,11 +62,15 @@ syntax (e.g., -iunix:/var/run/smtpp.sock). On Linux, abstract sockets use
syntax. syntax.
.TP .TP
.B -p .B -p
Port. Port proxy listens for incoming connections. Default is 25. Port. Port proxy listens for incoming connections. Default is 587.
.TP .TP
.B -h .B -h
Default destination. It's used if the target address is not specified by the user. Default destination. It's used if the target address is not specified by the user.
.TP .TP
.B -x
Disable STARTTLS support. STARTTLS is not announced in the EHLO response
and the STARTTLS command is not accepted.
.TP
.B -l .B -l
Log. By default logging is to stdout. If Log. By default logging is to stdout. If
.I logfile .I logfile
@ -95,6 +100,16 @@ is the user\'s login on this SMTP server. The login itself may contain an \'@\'
Only cleartext authentication is supported, because challenge-response Only cleartext authentication is supported, because challenge-response
authentication (CRAM-MD5, SPA, etc.) requires a challenge from the server before authentication (CRAM-MD5, SPA, etc.) requires a challenge from the server before
we know which server to connect to. we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STARTTLS is
supported and announced in the EHLO response unless disabled with
.BR -x .
After the client issues STARTTLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.SH BUGS .SH BUGS
Report all bugs to Report all bugs to
.BR 3proxy@3proxy.org .BR 3proxy@3proxy.org

View File

@ -13,6 +13,7 @@
.SH DESCRIPTION .SH DESCRIPTION
.B tlspr .B tlspr
is an SNI gateway service (destination host is taken from TLS handshake). The destination port must be specified via the -P option (or it may be detected with the Transparent plugin). is an SNI gateway service (destination host is taken from TLS handshake). The destination port must be specified via the -P option (or it may be detected with the Transparent plugin).
tlspr does not support user authentication; use ACLs by client IP or a parent proxy with authentication if access control is required.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B -I .B -I
@ -78,6 +79,15 @@ TLS_CHECK_LEVEL. 0 (default) - allow non-TLS traffic to pass, 1 - require TLS, o
.B -s .B -s
Split the TLS Client HELLO packet across multiple TCP segments to make SNI-based DPI detection harder. An optional numeric value can follow (e.g. \fB-s1\fR) to control the splitting behaviour. Split the TLS Client HELLO packet across multiple TCP segments to make SNI-based DPI detection harder. An optional numeric value can follow (e.g. \fB-s1\fR) to control the splitting behaviour.
.TP .TP
.B -Ximap | -Xpop3 | -Xsmtp
STARTTLS mode for the given protocol. The proxy speaks the plaintext protocol
with the client (greeting, capability advertisement with STARTTLS only, STARTTLS
command), then, after the client issues STARTTLS and sends a TLS Client HELLO,
connects to the destination taken from SNI (default port 143/110/587), performs
STARTTLS negotiation with the destination server and transparently passes TLS
traffic. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.TP
.B -l .B -l
Log. By default logging is to stdout. If Log. By default logging is to stdout. If
.I logfile .I logfile

View File

@ -537,6 +537,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
#endif #endif
freeconf(&conf); freeconf(&conf);
initcommands();
res = readconfig(fp); res = readconfig(fp);
conf.version++; conf.version++;

View File

@ -5,14 +5,7 @@
please read License Agreement please read License Agreement
*/ */
#include "libs/blake2.h" #include "mdhash.h"
#ifdef WITH_SSL
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/params.h>
#include <openssl/core_names.h>
#endif
#endif
#include <string.h> #include <string.h>
#define MD5_SIZE 16 #define MD5_SIZE 16
@ -28,11 +21,6 @@ static unsigned char itoa64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MD *md4_hash = NULL;
EVP_MD *md5_hash = NULL;
#endif
void void
_crypt_to64(unsigned char *s, unsigned long v, int n) _crypt_to64(unsigned char *s, unsigned long v, int n)
{ {
@ -43,21 +31,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 * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex)
{ {
unsigned char szUnicodePass[513]; unsigned char szUnicodePass[513];
unsigned int nPasswordLen; unsigned int nPasswordLen;
EVP_MD_CTX *ctx; unsigned int len = 16;
unsigned int len=sizeof(szUnicodePass);
unsigned int i; unsigned int i;
mdh_ctx *ctx;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const EVP_MD *md4 = md4_hash;
#else
const EVP_MD *md4 = EVP_md4();
#endif
if(md4 == NULL) return NULL;
/* /*
* NT passwords are unicode. Convert plain text password * NT passwords are unicode. Convert plain text password
@ -71,15 +51,14 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor
} }
/* Encrypt Unicode password to a 16-byte MD4 hash */ /* Encrypt Unicode password to a 16-byte MD4 hash */
ctx = EVP_MD_CTX_new(); ctx = mdh_init(MDH_MD4, 16);
if(!ctx) return NULL; if(!ctx) return NULL;
if(!EVP_DigestInit_ex(ctx, md4, NULL)){ mdh_update(ctx, szUnicodePass, (nPasswordLen<<1));
EVP_MD_CTX_free(ctx); if(!mdh_final(ctx, szUnicodePass, &len)) {
mdh_free(ctx);
return NULL; return NULL;
} }
EVP_DigestUpdate(ctx, szUnicodePass, (nPasswordLen<<1)); mdh_free(ctx);
EVP_DigestFinal_ex(ctx, szUnicodePass, &len);
EVP_MD_CTX_free(ctx);
if (ctohex){ if (ctohex){
tohex(szUnicodePass, szHash, 16); tohex(szUnicodePass, szHash, 16);
} }
@ -87,7 +66,6 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor
memset(szUnicodePass, 0, sizeof szUnicodePass); memset(szUnicodePass, 0, sizeof szUnicodePass);
return szHash; return szHash;
} }
#endif
unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){
@ -100,57 +78,44 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
int sl; int sl;
unsigned long l; unsigned long l;
#if defined(WITH_SSL)
#ifndef WITHMAIN #ifndef WITHMAIN
if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) { if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
EVP_MD_CTX *ctx, *ctx1; mdh_ctx *ctx, *ctx1;
unsigned int len; unsigned int len = MD5_SIZE;
int pl, i; int pl, i;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const EVP_MD *md5 = md5_hash;
#else
const EVP_MD *md5 = EVP_md5();
#endif
if(md5 == NULL) {
*passwd = 0;
return NULL;
}
sp = salt +3; sp = salt +3;
sl = (int)(ep - sp); sl = (int)(ep - sp);
magic = (unsigned char *)"$1$"; magic = (unsigned char *)"$1$";
ctx = EVP_MD_CTX_new(); ctx = mdh_init(MDH_MD5, 16);
if(!ctx) { if(!ctx) {
*passwd = 0; *passwd = 0;
return NULL; return NULL;
} }
EVP_DigestInit_ex(ctx, md5, NULL);
/* The password first, since that is what is most unknown */ /* The password first, since that is what is most unknown */
EVP_DigestUpdate(ctx,pw,strlen((char *)pw)); mdh_update(ctx, pw, (unsigned int)strlen((char *)pw));
/* Then our magic string */ /* Then our magic string */
EVP_DigestUpdate(ctx,magic,strlen((char *)magic)); mdh_update(ctx, magic, (unsigned int)strlen((char *)magic));
/* Then the raw salt */ /* Then the raw salt */
EVP_DigestUpdate(ctx,sp,sl); mdh_update(ctx, sp, (unsigned int)sl);
/* Then just as many unsigned characters of the MD5(pw,salt,pw) */ /* Then just as many unsigned characters of the MD5(pw,salt,pw) */
ctx1 = EVP_MD_CTX_new(); ctx1 = mdh_init(MDH_MD5, 16);
if(!ctx1) { if(!ctx1) {
EVP_MD_CTX_free(ctx); mdh_free(ctx);
*passwd = 0; *passwd = 0;
return NULL; return NULL;
} }
EVP_DigestInit_ex(ctx1, md5, NULL); mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw));
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); mdh_update(ctx1, sp, (unsigned int)sl);
EVP_DigestUpdate(ctx1,sp,sl); mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw));
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); mdh_final(ctx1, final, &len);
EVP_DigestFinal_ex(ctx1,final,&len);
for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE) for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE)
EVP_DigestUpdate(ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl); mdh_update(ctx, final, (unsigned int)(pl>MD5_SIZE ? MD5_SIZE : pl));
/* Don't leave anything around in vm they could use. */ /* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final); memset(final,0,sizeof final);
@ -158,13 +123,13 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
/* Then something really weird... */ /* Then something really weird... */
for (i = (int)strlen((char *)pw); i ; i >>= 1) for (i = (int)strlen((char *)pw); i ; i >>= 1)
if(i&1) if(i&1)
EVP_DigestUpdate(ctx, final, 1); mdh_update(ctx, final, 1);
else else
EVP_DigestUpdate(ctx, pw, 1); mdh_update(ctx, pw, 1);
EVP_DigestFinal_ex(ctx,final,&len); mdh_final(ctx, final, &len);
EVP_MD_CTX_free(ctx); mdh_free(ctx);
/* /*
* and now, just to make sure things don't run too fast * and now, just to make sure things don't run too fast
@ -172,43 +137,46 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
* need 30 seconds to build a 1000 entry dictionary... * need 30 seconds to build a 1000 entry dictionary...
*/ */
for(i=0;i<1000;i++) { for(i=0;i<1000;i++) {
EVP_MD_CTX_reset(ctx1); mdh_free(ctx1);
EVP_DigestInit_ex(ctx1, md5, NULL); ctx1 = mdh_init(MDH_MD5, 16);
if(!ctx1) { *passwd = 0; return NULL; }
if(i & 1) if(i & 1)
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw));
else else
EVP_DigestUpdate(ctx1,final,MD5_SIZE); mdh_update(ctx1, final, MD5_SIZE);
if(i % 3) if(i % 3)
EVP_DigestUpdate(ctx1,sp,sl); mdh_update(ctx1, sp, (unsigned int)sl);
if(i % 7) if(i % 7)
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw));
if(i & 1) if(i & 1)
EVP_DigestUpdate(ctx1,final,MD5_SIZE); mdh_update(ctx1, final, MD5_SIZE);
else else
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw));
EVP_DigestFinal_ex(ctx1,final,&len); mdh_final(ctx1, final, &len);
} }
EVP_MD_CTX_free(ctx1); mdh_free(ctx1);
} }
else else
#endif
#endif #endif
if(salt[0] == '$' && salt[1] == '3' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) { if(salt[0] == '$' && salt[1] == '3' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
sp = salt +3; sp = salt +3;
sl = (int)(ep - sp); sl = (int)(ep - sp);
magic = (unsigned char *)"$3$"; magic = (unsigned char *)"$3$";
{ {
blake2b_state S; mdh_ctx *bctx = mdh_init(MDH_BLAKE2, MD5_SIZE);
if(blake2b_init(&S, MD5_SIZE) != 0 || unsigned int blen = MD5_SIZE;
blake2b_update(&S, pw, strlen((char *)pw) + 1) != 0 || if(!bctx ||
blake2b_update(&S, sp, sl) != 0 || !mdh_update(bctx, pw, (unsigned int)(strlen((char *)pw) + 1)) ||
blake2b_final(&S, final, MD5_SIZE) != 0) { !mdh_update(bctx, sp, (unsigned int)sl) ||
!mdh_final(bctx, final, &blen)) {
mdh_free(bctx);
*passwd = 0; *passwd = 0;
return NULL; return NULL;
} }
mdh_free(bctx);
} }
} }
else { else {
@ -238,9 +206,6 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
} }
#ifdef WITHMAIN #ifdef WITHMAIN
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
#endif
#include <stdio.h> #include <stdio.h>
int main(int argc, char* argv[]){ int main(int argc, char* argv[]){
unsigned char buf1[128]; unsigned char buf1[128];
@ -248,37 +213,17 @@ int main(int argc, char* argv[]){
unsigned i; unsigned i;
if(argc < 2 || argc > 3) { if(argc < 2 || argc > 3) {
fprintf(stderr, "usage: \n" fprintf(stderr, "usage: \n"
#ifdef WITH_SSL
"\t%s <password>\n" "\t%s <password>\n"
#endif
"\t%s <salt> <password>\n" "\t%s <salt> <password>\n"
#ifdef WITH_SSL
"Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n" "Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n"
#else
"Performs BLAKE2 crypt with salt\n"
#endif
, ,
#ifdef WITH_SSL
argv[0], argv[0],
#endif
argv[0]); argv[0]);
return 1; return 1;
} }
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER_load(NULL, "default");
md4_hash = EVP_MD_fetch(NULL, "MD4", NULL);
if (md4_hash == NULL) {
fprintf(stderr, "Error fetching MD4\n");
}
#endif
if(argc == 2) { if(argc == 2) {
#ifdef WITH_SSL
{ unsigned char *nt = ntpwdhash(buf1, (unsigned char *)argv[1], 1); { unsigned char *nt = ntpwdhash(buf1, (unsigned char *)argv[1], 1);
if(nt) printf("NT:%s\n", nt); } if(nt) printf("NT:%s\n", nt); }
#else
fprintf(stderr, "NT crypt not available (compiled without OpenSSL)\n");
#endif
} }
else { else {
unsigned char *cr; unsigned char *cr;

View File

@ -2,7 +2,7 @@
# 3 proxy common Makefile # 3 proxy common Makefile
# #
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins
sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h
$(CC) $(CFLAGS) sockmap.c $(CC) $(CFLAGS) sockmap.c
@ -31,6 +31,9 @@ proxy$(OBJSUFFICS): proxy.c proxy.h structures.h proxymain.c
pop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h proxymain.c pop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN pop3p.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN pop3p.c
imapp$(OBJSUFFICS): imapp.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN imapp.c
smtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h proxymain.c smtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN smtpp.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN smtpp.c
@ -59,6 +62,9 @@ $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS)
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
@ -86,6 +92,9 @@ srvproxy$(OBJSUFFICS): proxy.c proxy.h structures.h
srvpop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h srvpop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h
$(CC) $(COUT)srvpop3p$(OBJSUFFICS) $(CFLAGS) pop3p.c $(CC) $(COUT)srvpop3p$(OBJSUFFICS) $(CFLAGS) pop3p.c
srvimapp$(OBJSUFFICS): imapp.c proxy.h structures.h
$(CC) $(COUT)srvimapp$(OBJSUFFICS) $(CFLAGS) imapp.c
srvsmtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h srvsmtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h
$(CC) $(COUT)srvsmtpp$(OBJSUFFICS) $(CFLAGS) smtpp.c $(CC) $(COUT)srvsmtpp$(OBJSUFFICS) $(CFLAGS) smtpp.c
@ -134,7 +143,7 @@ hashtables$(OBJSUFFICS): hashtables.c proxy.h structures.h libs/blake2.h
resolve$(OBJSUFFICS): resolve.c proxy.h structures.h resolve$(OBJSUFFICS): resolve.c proxy.h structures.h
$(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c $(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c
authradius$(OBJSUFFICS): authradius.c proxy.h structures.h authradius$(OBJSUFFICS): authradius.c proxy.h structures.h mdhash.h
$(CC) $(COUT)authradius$(OBJSUFFICS) $(CFLAGS) authradius.c $(CC) $(COUT)authradius$(OBJSUFFICS) $(CFLAGS) authradius.c
conf$(OBJSUFFICS): conf.c proxy.h structures.h conf$(OBJSUFFICS): conf.c proxy.h structures.h
@ -146,17 +155,26 @@ log$(OBJSUFFICS): log.c proxy.h structures.h
datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h
$(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c $(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c
3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h 3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h mdhash.h
$(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c $(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c
3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h 3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h mdhash.h
$(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c $(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c
blake2$(OBJSUFFICS): libs/blake2b-ref.c blake2$(OBJSUFFICS): libs/blake2b-ref.c
$(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c $(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c
$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS) mdhash$(OBJSUFFICS): mdhash.c mdhash.h proxy.h structures.h
$(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS) $(CC) $(COUT)mdhash$(OBJSUFFICS) $(CFLAGS) mdhash.c
md4$(OBJSUFFICS): libs/md4.c libs/md4.h
$(CC) $(COUT)md4$(OBJSUFFICS) $(CFLAGS) libs/md4.c
md5$(OBJSUFFICS): libs/md5.c libs/md5.h
$(CC) $(COUT)md5$(OBJSUFFICS) $(CFLAGS) libs/md5.c
$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS) mdhash$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) mdhash$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS)
stringtable$(OBJSUFFICS): stringtable.c stringtable$(OBJSUFFICS): stringtable.c
$(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c $(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c
@ -170,6 +188,6 @@ ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h
pcre$(OBJSUFFICS): pcre.c structures.h pcre$(OBJSUFFICS): pcre.c structures.h
$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE 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) $(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(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) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(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) $(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) srvimapp$(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) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)

View File

@ -7,7 +7,7 @@
*/ */
#include "proxy.h" #include "proxy.h"
#include "libs/blake2.h" #include "mdhash.h"
void initbandlims(struct clientparam *param); void initbandlims(struct clientparam *param);
@ -216,6 +216,24 @@ int dnsauth(struct clientparam * param){
return param->username? 0:3; return param->username? 0:3;
} }
static int ctmemcmp(const void *a, const void *b, size_t len){
const unsigned char *pa = (const unsigned char *)a, *pb = (const unsigned char *)b;
unsigned char diff = 0;
size_t i;
for(i = 0; i < len; i++) diff |= (unsigned char)(pa[i] ^ pb[i]);
return diff;
}
static int ctstrcmp(const char *a, const char *b, size_t maxlen){
unsigned char diff = 0;
size_t i;
for(i = 0; i < maxlen; i++){
diff |= (unsigned char)((unsigned char)a[i] ^ (unsigned char)b[i]);
if(!a[i] && !b[i]) break;
}
return diff;
}
int strongauth(struct clientparam * param){ int strongauth(struct clientparam * param){
static char dummy; static char dummy;
unsigned char buf[256]; unsigned char buf[256];
@ -229,27 +247,31 @@ int strongauth(struct clientparam * param){
int pwlen = strlen((char *)param->password); int pwlen = strlen((char *)param->password);
if(pwlen > 255) pwlen = 255; if(pwlen > 255) pwlen = 255;
if((unsigned)pwlen < pwl_table.recsize) { if((unsigned)pwlen < pwl_table.recsize) {
if(!strncmp(pass + 1, (char *)param->password, pwl_table.recsize - 1)) return 0; if(strlen(pass + 1) == strlen((char *)param->password) && !ctmemcmp(pass + 1, param->password, pwl_table.recsize - 1)) return 0;
} else { } else {
blake2b_state S; mdh_ctx *bctx;
unsigned hashsz; unsigned hashsz;
unsigned int blen;
hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64; hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64;
memset(buf, 0, pwl_table.recsize - 1); memset(buf, 0, pwl_table.recsize - 1);
blake2b_init(&S, hashsz); bctx = mdh_init(MDH_BLAKE2, hashsz);
blake2b_update(&S, param->password, pwlen + 1); if(!bctx) return 6;
blake2b_final(&S, buf, hashsz); mdh_update(bctx, param->password, pwlen + 1);
if(!memcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0; blen = hashsz;
mdh_final(bctx, buf, &blen);
mdh_free(bctx);
if(!ctmemcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0;
} }
return 6; return 6;
} }
case CR: case CR:
if (mycrypt(param->password, (unsigned char *)pass + 1, buf) && if (mycrypt(param->password, (unsigned char *)pass + 1, buf) &&
!strcmp(pass + 1, (char *)buf)) !ctstrcmp(pass + 1, (char *)buf, sizeof(pass) - 1))
return 0; return 0;
else return 7; else return 7;
#ifdef WITH_SSL #ifdef WITH_SSL
case NT: case NT:
if(ntpwdhash(buf, param->password, 1) && !strcmp(pass + 1, (char *)buf)) return 0; if(ntpwdhash(buf, param->password, 1) && !ctstrcmp(pass + 1, (char *)buf, sizeof(pass) - 1)) return 0;
else return 8; else return 8;
#endif #endif
default: default:

View File

@ -8,7 +8,7 @@
#ifndef NORADIUS #ifndef NORADIUS
#include "proxy.h" #include "proxy.h"
#include <openssl/evp.h> #include "mdhash.h"
#define AUTH_VECTOR_LEN 16 #define AUTH_VECTOR_LEN 16
#define MAX_STRING_LEN 254 #define MAX_STRING_LEN 254
@ -185,25 +185,15 @@ char *strNcpy(char *dest, const char *src, int n)
return dest; return dest;
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
extern EVP_MD *md4_hash;
extern EVP_MD *md5_hash;
#endif
void md5_calc(unsigned char *output, unsigned char *input, void md5_calc(unsigned char *output, unsigned char *input,
unsigned int inlen) unsigned int inlen)
{ {
EVP_MD_CTX *ctx = EVP_MD_CTX_new(); mdh_ctx *ctx = mdh_init(MDH_MD5, 16);
unsigned int len = 0; unsigned int len = 16;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L if(!ctx) return;
EVP_DigestInit_ex(ctx, md5_hash, NULL); mdh_update(ctx, input, inlen);
#else mdh_final(ctx, output, &len);
EVP_DigestInit_ex(ctx, EVP_md5(), NULL); mdh_free(ctx);
#endif
EVP_DigestUpdate(ctx, input, inlen);
EVP_DigestFinal_ex(ctx, output, &len);
EVP_MD_CTX_free(ctx);
} }

View File

@ -17,6 +17,8 @@ char * copyright = COPYRIGHT;
# define MYRAND_ARC4RANDOM 1 # define MYRAND_ARC4RANDOM 1
#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 36))) #elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 36)))
# define MYRAND_ARC4RANDOM 1 # define MYRAND_ARC4RANDOM 1
#elif defined(__GLIBC__) && ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 25)))
# define MYRAND_FALLBACK 1
#elif defined(__linux__) #elif defined(__linux__)
# define MYRAND_GETRANDOM 1 # define MYRAND_GETRANDOM 1
# include <sys/random.h> # include <sys/random.h>
@ -497,6 +499,14 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
if(se){ if(se){
*se = 0; *se = 0;
} }
if(!*hostname){
if(sp){
port = atoi(sp+1);
*sp = ':';
}
*SAPORT(&param->req) = htons(port);
return 0;
}
if(hostname != (char *)param->hostname){ if(hostname != (char *)param->hostname){
if(param->hostname) free(param->hostname); if(param->hostname) free(param->hostname);
param->hostname = (unsigned char *)strdup(hostname + (se!=0)); param->hostname = (unsigned char *)strdup(hostname + (se!=0));
@ -551,14 +561,14 @@ int parseconnusername(char *username, struct clientparam *param, int extpasswd,
if(!username || !*username) return 1; if(!username || !*username) return 1;
if ((sb=strchr(username, conf.delimchar)) == NULL){ if ((sb=strchr(username, conf.delimchar)) == NULL){
if(!param->hostname && param->remsock == INVALID_SOCKET) return 2; if(!param->hostname && param->remsock == INVALID_SOCKET) return 2;
if(param->hostname)parsehostname((char *)param->hostname, param, port); if(param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(&param->req)? ntohs(*SAPORT(&param->req)) : port);
return parseusername(username, param, extpasswd); return parseusername(username, param, extpasswd);
} }
while ((se=strchr(sb+1, conf.delimchar)))sb=se; while ((se=strchr(sb+1, conf.delimchar)))sb=se;
*(sb) = 0; *(sb) = 0;
if(parseusername(username, param, extpasswd)) return 3; if(parseusername(username, param, extpasswd)) return 3;
*(sb) = conf.delimchar; *(sb) = conf.delimchar;
if(parsehostname(sb+1, param, port)) return 4; if(parsehostname(sb+1, param, *SAPORT(&param->req)? ntohs(*SAPORT(&param->req)) : port)) return 4;
return 0; return 0;
} }
@ -657,6 +667,9 @@ int doconnect(struct clientparam * param){
if(!idx || (*SAFAMILY(&param->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) if(!idx || (*SAFAMILY(&param->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
return 12; return 12;
#ifndef NOIPV6 #ifndef NOIPV6
#ifndef IPV6_BOUND_IF
#define IPV6_BOUND_IF 125
#endif
if(*SAFAMILY(&param->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12; if(*SAFAMILY(&param->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12;
#endif #endif
} }
@ -867,3 +880,21 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
return 0; return 0;
#endif #endif
} }
int hascap(const unsigned char *line, const char *cap){
int len = (int)strlen(cap);
for(; *line; line++) if(!strncasecmp((char *)line, cap, len)) return 1;
return 0;
}
int getmultiline(struct clientparam *param, DIRECTION which, unsigned char *buf, int bufsize, const char *cap, int *found){
int i;
do {
i = sockgetlinebuf(param, which, buf, bufsize, '\n', conf.timeouts[STRING_L]);
if(i > 0 && cap && found && !*found){
buf[i] = 0;
if(hascap(buf, cap)) *found = 1;
}
} while (i > 3 && buf[3] == '-');
return i;
}

View File

@ -7,7 +7,7 @@
*/ */
#include "proxy.h" #include "proxy.h"
#include "libs/blake2.h" #include "mdhash.h"
#ifdef WITH_SSL #ifdef WITH_SSL
void ssl_install(void); void ssl_install(void);
#endif #endif
@ -191,14 +191,21 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 110; childdef.port = 110;
childdef.isudp = 0; childdef.isudp = 0;
childdef.service = S_POP3P; childdef.service = S_POP3P;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n"; childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
}
else if(!strcmp((char *)argv[0], "imapp")) {
childdef.pf = imappchild;
childdef.port = 143;
childdef.isudp = 0;
childdef.service = S_IMAPP;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
} }
else if(!strcmp((char *)argv[0], "smtpp")) { else if(!strcmp((char *)argv[0], "smtpp")) {
childdef.pf = smtppchild; childdef.pf = smtppchild;
childdef.port = 25; childdef.port = 587;
childdef.isudp = 0; childdef.isudp = 0;
childdef.service = S_SMTPP; childdef.service = S_SMTPP;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n"; childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
} }
else if(!strcmp((char *)argv[0], "ftppr")) { else if(!strcmp((char *)argv[0], "ftppr")) {
childdef.pf = ftpprchild; childdef.pf = ftpprchild;
@ -257,7 +264,7 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 53; childdef.port = 53;
childdef.isudp = 1; childdef.isudp = 1;
childdef.service = S_DNSPR; childdef.service = S_DNSPR;
childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n"; childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n -Fip - fake: answer all A queries with this IP\n";
#ifndef NOIPV6 #ifndef NOIPV6
if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize) || resolvfunc == fakeresolver){ if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize) || resolvfunc == fakeresolver){
fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum); fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
@ -543,13 +550,17 @@ static int h_users(int argc, unsigned char **argv){
l = strlen(pw[1]); l = strlen(pw[1]);
if(l > 255) l = 255; if(l > 255) l = 255;
if((unsigned)l >= pwl_table.recsize) { if((unsigned)l >= pwl_table.recsize) {
blake2b_state S; mdh_ctx *bctx;
unsigned hashsz; unsigned hashsz;
unsigned int blen;
if(*pass != CL) continue; if(*pass != CL) continue;
hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64; hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64;
blake2b_init(&S, hashsz); bctx = mdh_init(MDH_BLAKE2, hashsz);
blake2b_update(&S, pw[1], l + 1); if(!bctx) continue;
blake2b_final(&S, pass+1, hashsz); mdh_update(bctx, pw[1], l + 1);
blen = hashsz;
mdh_final(bctx, (unsigned char *)pass+1, &blen);
mdh_free(bctx);
} else { } else {
memcpy(pass + 1, pw[1], l); memcpy(pass + 1, pw[1], l);
} }
@ -739,6 +750,7 @@ struct redirdesc redirs[] = {
{R_SOCKS5, "socks5", sockschild}, {R_SOCKS5, "socks5", sockschild},
{R_HTTP, "http", proxychild}, {R_HTTP, "http", proxychild},
{R_POP3, "pop3", pop3pchild}, {R_POP3, "pop3", pop3pchild},
{R_IMAP, "imap", imappchild},
{R_SMTP, "smtp", smtppchild}, {R_SMTP, "smtp", smtppchild},
{R_FTP, "ftp", ftpprchild}, {R_FTP, "ftp", ftpprchild},
{R_CONNECTP, "connect+", proxychild}, {R_CONNECTP, "connect+", proxychild},
@ -1599,88 +1611,94 @@ static int h_chroot(int argc, unsigned char **argv){
#endif #endif
struct commands specificcommands[]={ struct commands commandhandlers[]={
{NULL, "", h_noop, 1, 0},
{NULL, "proxy", h_proxy, 1, 0},
{NULL, "pop3p", h_proxy, 1, 0},
{NULL, "imapp", h_proxy, 1, 0},
{NULL, "ftppr", h_proxy, 1, 0},
{NULL, "socks", h_proxy, 1, 0},
{NULL, "tcppm", h_proxy, 4, 0},
{NULL, "udppm", h_proxy, 4, 0},
{NULL, "admin", h_proxy, 1, 0},
{NULL, "dnspr", h_proxy, 1, 0},
{NULL, "internal", h_internal, 2, 2},
{NULL, "external", h_external, 2, 2},
{NULL, "log", h_log, 1, 0},
{NULL, "service", h_service, 1, 1},
{NULL, "daemon", h_daemon, 1, 1},
{NULL, "config", h_config, 2, 2},
{NULL, "include", h_include, 2, 2},
{NULL, "archiver", h_archiver, 3, 0},
{NULL, "counter", h_counter, 2, 4},
{NULL, "rotate", h_rotate, 2, 2},
{NULL, "logformat", h_logformat, 2, 2},
{NULL, "timeouts", h_timeouts, 2, 0},
{NULL, "auth", h_auth, 2, 0},
{NULL, "users", h_users, 1, 0},
{NULL, "maxconn", h_maxconn, 2, 2},
{NULL, "flush", h_flush, 1, 1},
{NULL, "nserver", h_nserver, 2, 2},
{NULL, "fakeresolve", h_fakeresolve, 1, 1},
{NULL, "nscache", h_nscache, 2, 2},
{NULL, "nscache6", h_nscache6, 2, 2},
{NULL, "nsrecord", h_nsrecord, 3, 3},
{NULL, "dialer", h_dialer, 2, 2},
{NULL, "system", h_system, 2, 2},
{NULL, "pidfile", h_pidfile, 2, 2},
{NULL, "monitor", h_monitor, 2, 2},
{NULL, "parent", h_parent, 5, 0},
{NULL, "allow", h_ace, 1, 0},
{NULL, "deny", h_ace, 1, 0},
{NULL, "redirect", h_ace, 3, 0},
{NULL, "bandlimin", h_ace, 2, 0},
{NULL, "bandlimout", h_ace, 2, 0},
{NULL, "nobandlimin", h_ace, 1, 0},
{NULL, "nobandlimout", h_ace, 1, 0},
{NULL, "countin", h_ace, 4, 0},
{NULL, "nocountin", h_ace, 1, 0},
{NULL, "countout", h_ace, 4, 0},
{NULL, "nocountout", h_ace, 1, 0},
{NULL, "countall", h_ace, 4, 0},
{NULL, "nocountall", h_ace, 1, 0},
{NULL, "connlim", h_ace, 4, 0},
{NULL, "noconnlim", h_ace, 1, 0},
{NULL, "plugin", h_plugin, 3, 0},
{NULL, "logdump", h_logdump, 2, 3},
{NULL, "filtermaxsize", h_filtermaxsize, 2, 2},
{NULL, "nolog", h_nolog, 1, 1},
{NULL, "weight", h_nolog, 2, 2},
{NULL, "authcache", h_authcache, 2, 4},
{NULL, "smtpp", h_proxy, 1, 0},
{NULL, "delimchar",h_delimchar, 2, 2},
{NULL, "authnserver", h_authnserver, 2, 2},
{NULL, "stacksize", h_stacksize, 2, 2},
{NULL, "force", h_force, 1, 1},
{NULL, "noforce", h_noforce, 1, 1},
{NULL, "parentretries", h_parentretries, 2, 2},
{NULL, "auto", h_proxy, 1, 0},
{NULL, "backlog", h_backlog, 2, 2},
{NULL, "tlspr", h_proxy, 1, 0},
{NULL, "maxseg", h_maxseg, 2, 2},
#ifndef NORADIUS
{NULL, "radius", h_radius, 3, 0},
#endif
#ifndef _WIN32 #ifndef _WIN32
{specificcommands+1, "setuid", h_setuid, 2, 2}, {NULL, "setuid", h_setuid, 2, 2},
{specificcommands+2, "setgid", h_setgid, 2, 2}, {NULL, "setgid", h_setgid, 2, 2},
{specificcommands+3, "chroot", h_chroot, 2, 4}, {NULL, "chroot", h_chroot, 2, 4},
#endif #endif
{NULL, "", h_noop, 1, 0} {NULL, "", h_noop, 1, 0}
}; };
struct commands commandhandlers[]={ void initcommands(void){
{commandhandlers+1, "", h_noop, 1, 0}, static int initialized = 0;
{commandhandlers+2, "proxy", h_proxy, 1, 0}, unsigned i;
{commandhandlers+3, "pop3p", h_proxy, 1, 0}, if(initialized) return;
{commandhandlers+4, "ftppr", h_proxy, 1, 0}, initialized = 1;
{commandhandlers+5, "socks", h_proxy, 1, 0}, for(i = 0; i + 1 < sizeof(commandhandlers)/sizeof(commandhandlers[0]); i++)
{commandhandlers+6, "tcppm", h_proxy, 4, 0}, commandhandlers[i].next = commandhandlers + i + 1;
{commandhandlers+7, "udppm", h_proxy, 4, 0}, }
{commandhandlers+8, "admin", h_proxy, 1, 0},
{commandhandlers+9, "dnspr", h_proxy, 1, 0},
{commandhandlers+10, "internal", h_internal, 2, 2},
{commandhandlers+11, "external", h_external, 2, 2},
{commandhandlers+12, "log", h_log, 1, 0},
{commandhandlers+13, "service", h_service, 1, 1},
{commandhandlers+14, "daemon", h_daemon, 1, 1},
{commandhandlers+15, "config", h_config, 2, 2},
{commandhandlers+16, "include", h_include, 2, 2},
{commandhandlers+17, "archiver", h_archiver, 3, 0},
{commandhandlers+18, "counter", h_counter, 2, 4},
{commandhandlers+19, "rotate", h_rotate, 2, 2},
{commandhandlers+20, "logformat", h_logformat, 2, 2},
{commandhandlers+21, "timeouts", h_timeouts, 2, 0},
{commandhandlers+22, "auth", h_auth, 2, 0},
{commandhandlers+23, "users", h_users, 1, 0},
{commandhandlers+24, "maxconn", h_maxconn, 2, 2},
{commandhandlers+25, "flush", h_flush, 1, 1},
{commandhandlers+26, "nserver", h_nserver, 2, 2},
{commandhandlers+27, "fakeresolve", h_fakeresolve, 1, 1},
{commandhandlers+28, "nscache", h_nscache, 2, 2},
{commandhandlers+29, "nscache6", h_nscache6, 2, 2},
{commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
{commandhandlers+31, "dialer", h_dialer, 2, 2},
{commandhandlers+32, "system", h_system, 2, 2},
{commandhandlers+33, "pidfile", h_pidfile, 2, 2},
{commandhandlers+34, "monitor", h_monitor, 2, 2},
{commandhandlers+35, "parent", h_parent, 5, 0},
{commandhandlers+36, "allow", h_ace, 1, 0},
{commandhandlers+37, "deny", h_ace, 1, 0},
{commandhandlers+38, "redirect", h_ace, 3, 0},
{commandhandlers+39, "bandlimin", h_ace, 2, 0},
{commandhandlers+40, "bandlimout", h_ace, 2, 0},
{commandhandlers+41, "nobandlimin", h_ace, 1, 0},
{commandhandlers+42, "nobandlimout", h_ace, 1, 0},
{commandhandlers+43, "countin", h_ace, 4, 0},
{commandhandlers+44, "nocountin", h_ace, 1, 0},
{commandhandlers+45, "countout", h_ace, 4, 0},
{commandhandlers+46, "nocountout", h_ace, 1, 0},
{commandhandlers+47, "countall", h_ace, 4, 0},
{commandhandlers+48, "nocountall", h_ace, 1, 0},
{commandhandlers+49, "connlim", h_ace, 4, 0},
{commandhandlers+50, "noconnlim", h_ace, 1, 0},
{commandhandlers+51, "plugin", h_plugin, 3, 0},
{commandhandlers+52, "logdump", h_logdump, 2, 3},
{commandhandlers+53, "filtermaxsize", h_filtermaxsize, 2, 2},
{commandhandlers+54, "nolog", h_nolog, 1, 1},
{commandhandlers+55, "weight", h_nolog, 2, 2},
{commandhandlers+56, "authcache", h_authcache, 2, 4},
{commandhandlers+57, "smtpp", h_proxy, 1, 0},
{commandhandlers+58, "delimchar",h_delimchar, 2, 2},
{commandhandlers+59, "authnserver", h_authnserver, 2, 2},
{commandhandlers+60, "stacksize", h_stacksize, 2, 2},
{commandhandlers+61, "force", h_force, 1, 1},
{commandhandlers+62, "noforce", h_noforce, 1, 1},
{commandhandlers+63, "parentretries", h_parentretries, 2, 2},
{commandhandlers+64, "auto", h_proxy, 1, 0},
{commandhandlers+65, "backlog", h_backlog, 2, 2},
{commandhandlers+66, "tlspr", h_proxy, 1, 0},
{commandhandlers+67, "maxseg", h_maxseg, 2, 2},
#ifndef NORADIUS
{commandhandlers+68, "radius", h_radius, 3, 0},
#endif
{specificcommands, "", h_noop, 1, 0}
};
int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){ int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){
#define buf (*buff) #define buf (*buff)

View File

@ -523,7 +523,7 @@ static void * ef_server_next(struct node * node){
static void * ef_server_type(struct node * node){ static void * ef_server_type(struct node * node){
int service = ((struct srvparam *)node->value) -> service; int service = ((struct srvparam *)node->value) -> service;
return (service>=0 && service < 15)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown"; return (service>=0 && service < MAX_SERVICE)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
} }
static void * ef_server_child(struct node * node){ static void * ef_server_child(struct node * node){
@ -682,7 +682,7 @@ static void * ef_client_next(struct node * node){
static void * ef_client_type(struct node * node){ static void * ef_client_type(struct node * node){
int service = ((struct clientparam *)node->value) -> service; int service = ((struct clientparam *)node->value) -> service;
return (service>=0 && service < 15)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown"; return (service>=0 && service < MAX_SERVICE)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
} }
static void * ef_client_operation(struct node * node){ static void * ef_client_operation(struct node * node){

View File

@ -25,6 +25,7 @@ void * dnsprchild(struct clientparam* param) {
SASIZETYPE size; SASIZETYPE size;
int res, i; int res, i;
int len; int len;
int semlocked = 1;
unsigned type=0; unsigned type=0;
uint32_t ttl; uint32_t ttl;
unsigned char addr[16]; unsigned char addr[16];
@ -38,10 +39,13 @@ void * dnsprchild(struct clientparam* param) {
RETURN (21); RETURN (21);
} }
buf = bbuf+2; buf = bbuf+2;
size = sizeof(param->sincr);
i = param->srv->so._recvfrom(param->sostate, param->srv->srvsock, (char *)buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size);
size = sizeof(param->sinsl); size = sizeof(param->sinsl);
getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size); getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size);
i = param->srv->udplen;
if(i > BUFSIZE) i = BUFSIZE;
memcpy(buf, param->srv->udpbuf, i);
_3proxy_sem_unlock(udpinit);
semlocked = 0;
#ifdef _WIN32 #ifdef _WIN32
if((param->clisock=param->srv->so._socket(param->sostate, AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { if((param->clisock=param->srv->so._socket(param->sostate, AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818); RETURN(818);
@ -82,7 +86,19 @@ void * dnsprchild(struct clientparam* param) {
*s2 = (len - (int)(s2 - buf)) - 1; *s2 = (len - (int)(s2 - buf)) - 1;
type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2]; type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
if((type==0x01 || type==0x1c) && !param->srv->s_option){ if(type==0x01 && param->srv->fakeip){
ip = 1;
ttl = 3600;
*(uint32_t *)addr = param->srv->fakeip;
}
#ifndef NOIPV6
else if(type==0x1c && *(uint32_t *)param->srv->fakeip6){
ip = 1;
ttl = 3600;
memcpy(addr, param->srv->fakeip6, 16);
}
#endif
else if((type==0x01 || type==0x1c) && !param->srv->s_option){
ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0); ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
} }
@ -191,6 +207,7 @@ void * dnsprchild(struct clientparam* param) {
CLEANRET: CLEANRET:
if(semlocked) _3proxy_sem_unlock(udpinit);
if(param->res!=813){ if(param->res!=813){
sprintf((char *)buf, "%04x/%s/", sprintf((char *)buf, "%04x/%s/",
(unsigned)type, (unsigned)type,

View File

@ -197,6 +197,7 @@ void hashadd(struct hashtable *ht, void* name, void* value, time_t expires){
if(!ht->ihashempty){ if(!ht->ihashempty){
hashgrow(ht); hashgrow(ht);
index = hashindex(ht, ht->tablesize, hash);
} }
if(ht->ihashempty){ if(ht->ihashempty){

View File

@ -1,18 +1,21 @@
#include "proxy.h" #include "proxy.h"
#include "libs/blake2.h" #include "mdhash.h"
static void char_index2hash(const struct hashtable *ht, void *index, uint8_t *hash){ static void char_index2hash(const struct hashtable *ht, void *index, uint8_t *hash){
blake2b_state S;
int len; int len;
unsigned int blen;
len = strlen((const char*)index); len = strlen((const char*)index);
memset(hash, 0, ht->hash_size); memset(hash, 0, ht->hash_size);
if(len <= ht->hash_size) memcpy(hash, index, len); if(len <= ht->hash_size) memcpy(hash, index, len);
else { else {
blake2b_init(&S, ht->hash_size); mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
blake2b_update(&S, index, strlen((const char*)index) + 1); if(!bctx) return;
blake2b_final(&S, hash, ht->hash_size); mdh_update(bctx, index, (unsigned int)(strlen((const char*)index) + 1));
blen = ht->hash_size;
mdh_final(bctx, hash, &blen);
mdh_free(bctx);
} }
} }
@ -23,7 +26,6 @@ static void param2hash_add(const struct hashtable *ht, void *index, uint8_t *has
} }
void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
blake2b_state S;
struct clientparam *param = (struct clientparam *)index; struct clientparam *param = (struct clientparam *)index;
unsigned type = param->srv->authcachetype; unsigned type = param->srv->authcachetype;
int len = 0, oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0; int len = 0, oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0;
@ -55,31 +57,36 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
if((type & 2048)){ memcpy(hash + offset, SAPORT(&param->srv->intsa), p2len); offset += 2; } if((type & 2048)){ memcpy(hash + offset, SAPORT(&param->srv->intsa), p2len); offset += 2; }
} }
else { else {
blake2b_init(&S, ht->hash_size); mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
if((type & 2) && param->username)blake2b_update(&S, param->username, ulen); unsigned int blen = ht->hash_size;
if((type & 4) && param->password)blake2b_update(&S, param->password, plen); if(!bctx) { memcpy(param->hash, hash, ht->hash_size); return; }
if((type & 1) && !(type & 8))blake2b_update(&S, SAADDR(&param->sincr), a1len); if((type & 2) && param->username)mdh_update(bctx, param->username, ulen);
if((type & 16))blake2b_update(&S, &param->srv->acl, acllen); if((type & 4) && param->password)mdh_update(bctx, param->password, plen);
if((type & 64))blake2b_update(&S, SAADDR(&param->req), a2len); if((type & 1) && !(type & 8))mdh_update(bctx, SAADDR(&param->sincr), a1len);
if((type & 128))blake2b_update(&S, SAPORT(&param->req), 2); if((type & 16))mdh_update(bctx, &param->srv->acl, acllen);
if((type & 256) && param->hostname)blake2b_update(&S, param->hostname, hlen); if((type & 64))mdh_update(bctx, SAADDR(&param->req), a2len);
if((type & 512))blake2b_update(&S, &param->operation, sizeof(param->operation)); if((type & 128))mdh_update(bctx, SAPORT(&param->req), 2);
if((type & 1024))blake2b_update(&S, SAADDR(&param->srv->intsa), a3len); if((type & 256) && param->hostname)mdh_update(bctx, param->hostname, hlen);
if((type & 2048))blake2b_update(&S, SAPORT(&param->srv->intsa), 2); if((type & 512))mdh_update(bctx, &param->operation, sizeof(param->operation));
blake2b_final(&S, hash, ht->hash_size); if((type & 1024))mdh_update(bctx, SAADDR(&param->srv->intsa), a3len);
if((type & 2048))mdh_update(bctx, SAPORT(&param->srv->intsa), 2);
mdh_final(bctx, hash, &blen);
mdh_free(bctx);
} }
memcpy(param->hash, hash, ht->hash_size); memcpy(param->hash, hash, ht->hash_size);
} }
static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash){ static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash){
struct clientparam *param = (struct clientparam *)index; struct clientparam *param = (struct clientparam *)index;
blake2b_state S; mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
blake2b_init(&S, ht->hash_size); unsigned int blen = ht->hash_size;
blake2b_update(&S, SAADDR(&param->srv->intsa), SAADDRLEN(&param->srv->intsa)); if(!bctx) return;
blake2b_update(&S, SAPORT(&param->srv->intsa), 2); mdh_update(bctx, SAADDR(&param->srv->intsa), SAADDRLEN(&param->srv->intsa));
blake2b_update(&S, SAADDR(&param->sincr), SAADDRLEN(&param->sincr)); mdh_update(bctx, SAPORT(&param->srv->intsa), 2);
blake2b_update(&S, SAPORT(&param->sincr), 2); mdh_update(bctx, SAADDR(&param->sincr), SAADDRLEN(&param->sincr));
blake2b_final(&S, hash, ht->hash_size); mdh_update(bctx, SAPORT(&param->sincr), 2);
mdh_final(bctx, hash, &blen);
mdh_free(bctx);
} }
struct hashtable dns_table = {char_index2hash, char_index2hash, 4, 32}; struct hashtable dns_table = {char_index2hash, char_index2hash, 4, 32};

255
src/imapp.c Normal file
View File

@ -0,0 +1,255 @@
/*
3APA3A simplest proxy server
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement
*/
#include "proxy.h"
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#define CL_LOGINCMD 0
#define CL_PLAIN 1
#define CL_LOGIN 2
#define CAP_PLAIN 1
#define CAP_LOGIN 2
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
void * imappchild(struct clientparam* param) {
int i=0, res, method=CL_LOGINCMD, caps=0;
unsigned char buf[2048];
unsigned char srvbuf[1024];
unsigned char ibuf[2048];
unsigned char tag[64];
unsigned char ub[320];
unsigned char pb[320];
unsigned char *se, *cmd, *user, *pass, *p1, *p2;
*tag = 0;
i = sprintf((char *)buf, "* OK [CAPABILITY IMAP4rev1%s AUTH=PLAIN AUTH=LOGIN] IMAP4rev1 Proxy Ready\r\n", NOSTARTTLS?"":" STARTTLS");
if(socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (691);}
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) {RETURN(692);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
if (!(se=(unsigned char *)strchr((char *)buf, ' ')) || (se - buf) >= (int)(sizeof(tag) - 1)) {RETURN(692);}
memcpy(tag, buf, se - buf);
tag[se - buf] = 0;
cmd = se + 1;
if(!strncasecmp((char *)cmd, "LOGOUT", 6)){
socksend(param, param->clisock, (unsigned char *)"* BYE\r\n", 7, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK LOGOUT completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
RETURN(0);
}
if(!strncasecmp((char *)cmd, "CAPABILITY", 10)){
i = sprintf((char *)buf, "* CAPABILITY IMAP4rev1%s AUTH=PLAIN AUTH=LOGIN\r\n", NOSTARTTLS?"":" STARTTLS");
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK CAPABILITY completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
continue;
}
#ifndef WITHMAIN
if(!strncasecmp((char *)cmd, "STARTTLS", 8) && !param->srv->nostarttls){
sprintf((char *)buf, "%.60s OK Begin TLS negotiation\r\n", (char *)tag);
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) {RETURN(698);}
param->clientstarttls = S_IMAPP;
if(!param->srv->targetport) param->srv->targetport = htons(143);
return tlsprchild(param);
}
#endif
if(!strncasecmp((char *)cmd, "LOGIN ", 6)){
user = cmd + 6;
if(*user == '"') {
user++;
if (!(se=(unsigned char *)strchr((char *)user, '"'))) {RETURN(693);}
*se = 0;
pass = se + 1;
if(*pass == ' ') pass++;
}
else {
if (!(se=(unsigned char *)strchr((char *)user, ' '))) {RETURN(693);}
*se = 0;
pass = se + 1;
}
if(strlen((char *)user) >= sizeof(ub) || strlen((char *)pass) >= sizeof(pb)) {RETURN(693);}
strcpy((char *)ub, (char *)user);
strcpy((char *)pb, (char *)pass);
break;
}
if(!strncasecmp((char *)cmd, "AUTHENTICATE PLAIN", 18)){
method = CL_PLAIN;
se = cmd + 18;
if(*se == ' ') se++; else se = NULL;
if(!se || !*se){
if(socksend(param, param->clisock, (unsigned char *)"+ \r\n", 4, conf.timeouts[STRING_S])!=4) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
se = buf;
}
i = de64(se, ibuf, (int)sizeof(ibuf) - 1);
if(i < 3) {RETURN(693);}
ibuf[i] = 0;
p1 = (unsigned char *)memchr(ibuf, 0, i);
if(!p1 || p1 == ibuf + i - 1) {RETURN(693);}
p2 = (unsigned char *)memchr(p1 + 1, 0, i - (int)(p1 + 1 - ibuf));
if(p2){
user = p1 + 1;
pass = p2 + 1;
}
else {
user = ibuf;
pass = p1 + 1;
}
if(strlen((char *)user) >= sizeof(ub) || strlen((char *)pass) >= sizeof(pb)) {RETURN(693);}
strcpy((char *)ub, (char *)user);
strcpy((char *)pb, (char *)pass);
break;
}
if(!strncasecmp((char *)cmd, "AUTHENTICATE LOGIN", 18)){
method = CL_LOGIN;
se = cmd + 18;
if(*se == ' ') se++; else se = NULL;
if(se && *se){
i = de64(se, ub, (int)sizeof(ub) - 1);
if(i < 0) {RETURN(693);}
ub[i] = 0;
}
else {
if(socksend(param, param->clisock, (unsigned char *)"+ VXNlcm5hbWU6\r\n", 16, conf.timeouts[STRING_S])!=16) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
i = de64(buf, ub, (int)sizeof(ub) - 1);
if(i < 0) {RETURN(693);}
ub[i] = 0;
}
if(socksend(param, param->clisock, (unsigned char *)"+ UGFzc3dvcmQ6\r\n", 16, conf.timeouts[STRING_S])!=16) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
i = de64(buf, pb, (int)sizeof(pb) - 1);
if(i < 0) {RETURN(693);}
pb[i] = 0;
break;
}
sprintf((char *)buf, "%.60s BAD need LOGIN first\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
}
if(parseconnusername((char *)ub, param, 0, 143)){RETURN(694);}
if(*pb && !param->password) param->password = (unsigned char *)strdup((char *)pb);
param->operation = CONNECT;
res = (*param->srv->authfunc)(param);
if(res) {RETURN(res);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if( i < 4 ) {RETURN(695);}
srvbuf[i] = 0;
if(strncasecmp((char *)srvbuf, "* OK", 4)||strstr((char *)srvbuf, "IMAP4rev1 Proxy Ready")){RETURN(696);}
if((se = (unsigned char *)strstr((char *)srvbuf, "[CAPABILITY "))){
if(hascap(se, "AUTH=PLAIN")) caps |= CAP_PLAIN;
if(hascap(se, "AUTH=LOGIN")) caps |= CAP_LOGIN;
}
else {
if(socksend(param, param->remsock, (unsigned char *)"zz CAPABILITY\r\n", 15, conf.timeouts[STRING_S])!=15) {RETURN(697);}
for(;;){
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) {RETURN(697);}
srvbuf[i] = 0;
if(!strncasecmp((char *)srvbuf, "* CAPABILITY", 12)){
if(hascap(srvbuf, "AUTH=PLAIN")) caps |= CAP_PLAIN;
if(hascap(srvbuf, "AUTH=LOGIN")) caps |= CAP_LOGIN;
continue;
}
if(!strncasecmp((char *)srvbuf, "zz ", 3)) break;
}
}
if(method == CL_PLAIN && !(caps & CAP_PLAIN)) method = (caps & CAP_LOGIN)? CL_LOGIN : CL_LOGINCMD;
else if(method == CL_LOGIN && !(caps & CAP_LOGIN)) method = (caps & CAP_PLAIN)? CL_PLAIN : CL_LOGINCMD;
else if(method == CL_LOGINCMD && caps) method = (caps & CAP_PLAIN)? CL_PLAIN : CL_LOGIN;
if(method == CL_PLAIN){
i = (int)strlen((char *)param->extusername);
res = (int)strlen((char *)pb);
if(((i + res + 4) / 3) * 4 + 1 > (int)sizeof(srvbuf)) {RETURN(693);}
ibuf[0] = 0;
memcpy(ibuf + 1, param->extusername, i);
ibuf[i + 1] = 0;
memcpy(ibuf + i + 2, pb, res);
en64(ibuf, srvbuf, i + res + 2);
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE PLAIN ", 20, conf.timeouts[STRING_S])!= 20 ||
socksend(param, param->remsock, srvbuf, (int)strlen((char *)srvbuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
else if(method == CL_LOGIN){
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE LOGIN\r\n", 21, conf.timeouts[STRING_S])!= 21)
{RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)param->extusername) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);}
en64(param->extusername, ibuf, (int)strlen((char *)param->extusername));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)pb) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);}
en64(pb, ibuf, (int)strlen((char *)pb));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
else {
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" LOGIN ", 7, conf.timeouts[STRING_S])!= 7 ||
socksend(param, param->remsock, param->extusername, (int)strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" ", 1, conf.timeouts[STRING_S])!= 1 ||
socksend(param, param->remsock, pb, (int)strlen((char *)pb), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
param->statscli64 += (uint64_t)(strlen((char *)tag) + strlen((char *)param->extusername) + strlen((char *)pb) + 11);
param->nwrites++;
RETURN (mapsocket(param, 180));
CLEANRET:
if(param->hostname&&param->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(&param->sinsr)==143)?0:':', ntohs(*SAPORT(&param->sinsr)));
dolog(param, buf);
}
else dolog(param, NULL);
if(param->clisock != INVALID_SOCKET) {
if ((param->res > 0 && param->res < 100) || (param->res > 691 && param->res <700)) {
sprintf((char *)buf, "%.60s NO proxy error\r\n", *tag? (char *)tag : "*");
socksend(param, param->clisock, buf, (int)strlen((char *)buf),conf.timeouts[STRING_S]);
}
}
freeparam(param);
return (NULL);
}
#ifdef WITHMAIN
struct proxydef childdef = {
imappchild,
143,
0,
S_IMAPP,
" -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
};
#include "proxymain.c"
#endif

View File

@ -13,6 +13,12 @@
https://blake2.net. https://blake2.net.
*/ */
#if defined(WITH_WOLFSSL)
#include <wolfssl/options.h>
#endif
#ifndef HAVE_BLAKE2B
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -377,3 +383,5 @@ fail:
return -1; return -1;
} }
#endif #endif
#endif /* !HAVE_BLAKE2B */

276
src/libs/md4.c Normal file
View File

@ -0,0 +1,276 @@
/*
* This is an OpenSSL API compatible (but not ABI compatible) implementation
* of the RSA Data Security, Inc. MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
* https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#if defined(WITH_WOLFSSL)
#include <wolfssl/options.h>
#endif
#if !defined(WITH_WOLFSSL) || defined(NO_MD4)
#include <string.h>
#include "md4.h"
/*
* The basic MD4 functions.
*
* F and G are optimized compared to their RFC 1320 definitions, with the
* optimization for F borrowed from Colin Plumb's MD5 implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
* The MD4 transformation for all three rounds.
*/
#define STEP(f, a, b, c, d, x, s) \
(a) += f((b), (c), (d)) + (x); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD4_u32plus. In practice, this problem may occur if these MD4 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD4 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD4_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD4_u32plus)ptr[(n) * 4] | \
((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void *body(MD4_CTX *ctx, const void *data, size_t size)
{
const unsigned char *ptr;
MD4_u32plus a, b, c, d;
MD4_u32plus saved_a, saved_b, saved_c, saved_d;
const MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 3)
STEP(F, d, a, b, c, SET(1), 7)
STEP(F, c, d, a, b, SET(2), 11)
STEP(F, b, c, d, a, SET(3), 19)
STEP(F, a, b, c, d, SET(4), 3)
STEP(F, d, a, b, c, SET(5), 7)
STEP(F, c, d, a, b, SET(6), 11)
STEP(F, b, c, d, a, SET(7), 19)
STEP(F, a, b, c, d, SET(8), 3)
STEP(F, d, a, b, c, SET(9), 7)
STEP(F, c, d, a, b, SET(10), 11)
STEP(F, b, c, d, a, SET(11), 19)
STEP(F, a, b, c, d, SET(12), 3)
STEP(F, d, a, b, c, SET(13), 7)
STEP(F, c, d, a, b, SET(14), 11)
STEP(F, b, c, d, a, SET(15), 19)
/* Round 2 */
STEP(G, a, b, c, d, GET(0) + ac1, 3)
STEP(G, d, a, b, c, GET(4) + ac1, 5)
STEP(G, c, d, a, b, GET(8) + ac1, 9)
STEP(G, b, c, d, a, GET(12) + ac1, 13)
STEP(G, a, b, c, d, GET(1) + ac1, 3)
STEP(G, d, a, b, c, GET(5) + ac1, 5)
STEP(G, c, d, a, b, GET(9) + ac1, 9)
STEP(G, b, c, d, a, GET(13) + ac1, 13)
STEP(G, a, b, c, d, GET(2) + ac1, 3)
STEP(G, d, a, b, c, GET(6) + ac1, 5)
STEP(G, c, d, a, b, GET(10) + ac1, 9)
STEP(G, b, c, d, a, GET(14) + ac1, 13)
STEP(G, a, b, c, d, GET(3) + ac1, 3)
STEP(G, d, a, b, c, GET(7) + ac1, 5)
STEP(G, c, d, a, b, GET(11) + ac1, 9)
STEP(G, b, c, d, a, GET(15) + ac1, 13)
/* Round 3 */
STEP(H, a, b, c, d, GET(0) + ac2, 3)
STEP(H, d, a, b, c, GET(8) + ac2, 9)
STEP(H, c, d, a, b, GET(4) + ac2, 11)
STEP(H, b, c, d, a, GET(12) + ac2, 15)
STEP(H, a, b, c, d, GET(2) + ac2, 3)
STEP(H, d, a, b, c, GET(10) + ac2, 9)
STEP(H, c, d, a, b, GET(6) + ac2, 11)
STEP(H, b, c, d, a, GET(14) + ac2, 15)
STEP(H, a, b, c, d, GET(1) + ac2, 3)
STEP(H, d, a, b, c, GET(9) + ac2, 9)
STEP(H, c, d, a, b, GET(5) + ac2, 11)
STEP(H, b, c, d, a, GET(13) + ac2, 15)
STEP(H, a, b, c, d, GET(3) + ac2, 3)
STEP(H, d, a, b, c, GET(11) + ac2, 9)
STEP(H, c, d, a, b, GET(7) + ac2, 11)
STEP(H, b, c, d, a, GET(15) + ac2, 15)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void MD4_Init(MD4_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void MD4_Update(MD4_CTX *ctx, const void *data, size_t size)
{
MD4_u32plus saved_lo;
size_t used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += (MD4_u32plus)(size >> 29);
used = saved_lo & 0x3f;
if (used) {
available = 64 - used;
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64) {
data = body(ctx, data, size & ~(size_t)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void MD4_Final(unsigned char *result, MD4_CTX *ctx)
{
size_t used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
#if 0
memset(ctx, 0, sizeof(*ctx));
#endif
}
#endif /* !WITH_WOLFSSL || NO_MD4 */

57
src/libs/md4.h Normal file
View File

@ -0,0 +1,57 @@
/*
* This is an OpenSSL API compatible (but not ABI compatible) implementation
* of the RSA Data Security, Inc. MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
* https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md4.c for more information.
*/
#ifndef _MD4_H
#define _MD4_H
#ifdef WITH_WOLFSSL
#include <wolfssl/options.h>
#endif
#if defined(WITH_WOLFSSL) && !defined(NO_MD4)
#include <wolfssl/openssl/md4.h>
#else
#include <stddef.h> /* for size_t */
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD4_u32plus;
typedef struct {
MD4_u32plus lo, hi;
MD4_u32plus a, b, c, d;
unsigned char buffer[64];
#if !(defined(__i386__) || defined(__x86_64__) || defined(__vax__))
MD4_u32plus block[16];
#endif
} MD4_CTX;
extern void MD4_Init(MD4_CTX *ctx);
extern void MD4_Update(MD4_CTX *ctx, const void *data, size_t size);
extern void MD4_Final(unsigned char *result, MD4_CTX *ctx);
#endif /* !WITH_WOLFSSL */
#endif

295
src/libs/md5.c Normal file
View File

@ -0,0 +1,295 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#if defined(WITH_WOLFSSL)
#include <wolfssl/options.h>
#endif
#if !defined(WITH_WOLFSSL) || defined(NO_MD5)
#include <string.h>
#include "md5.h"
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void MD5_Init(MD5_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used) {
available = 64 - used;
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}
#endif /* !WITH_WOLFSSL || NO_MD5 */

53
src/libs/md5.h Normal file
View File

@ -0,0 +1,53 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifndef _MD5_H
#define _MD5_H
#ifdef WITH_WOLFSSL
#include <wolfssl/options.h>
#endif
#if defined(WITH_WOLFSSL) && !defined(NO_MD5)
#include <wolfssl/openssl/md5.h>
#else
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif /* !WITH_WOLFSSL */
#endif

211
src/mdhash.c Normal file
View File

@ -0,0 +1,211 @@
/*
3APA3A simplest proxy server
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement
MD4/MD5/BLAKE2 hash implementation.
- Windows (no wolfSSL): CryptoAPI (CAPI) for MD4/MD5; bundled BLAKE2.
- wolfSSL: wolfCrypt for MD4/MD5 (OpenSSL compat) and BLAKE2 (native wc_*).
- Other: bundled public-domain MD4/MD5 + bundled BLAKE2 reference.
*/
#include "mdhash.h"
#include <stdlib.h>
#include <string.h>
/* ----- BLAKE2 backend selection ----- */
/* wolfSSL may provide BLAKE2 natively (HAVE_BLAKE2B). If not enabled
(e.g. vcpkg port), fall back to the bundled reference implementation. */
#ifdef WITH_WOLFSSL
#include <wolfssl/options.h>
#ifdef HAVE_BLAKE2B
#include <wolfssl/wolfcrypt/blake2.h>
#define MDH_BLAKE2_BACKEND_WOLFSSL
#else
#include "libs/blake2.h"
#endif
#else
#include "libs/blake2.h"
#endif
/* ----- MD4/MD5 backend selection ----- */
#if defined(_WIN32) && !defined(WITH_WOLFSSL)
#define MDH_MD_BACKEND_CAPI
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
#else
#include "libs/md4.h"
#include "libs/md5.h"
#endif
struct mdh_ctx {
mdh_alg alg;
unsigned int outlen;
#ifdef MDH_MD_BACKEND_CAPI
HCRYPTPROV hProv;
HCRYPTHASH hHash;
#else
union {
MD4_CTX md4;
MD5_CTX md5;
} u;
#endif
#ifdef MDH_BLAKE2_BACKEND_WOLFSSL
Blake2b blake2;
#else
blake2b_state blake2;
#endif
};
mdh_ctx *mdh_init(mdh_alg alg, unsigned int outlen)
{
mdh_ctx *c = (mdh_ctx *)malloc(sizeof(mdh_ctx));
if(!c) return NULL;
memset(c, 0, sizeof(*c));
c->alg = alg;
c->outlen = outlen;
switch(alg) {
case MDH_MD4:
#ifdef MDH_MD_BACKEND_CAPI
if(!CryptAcquireContext(&c->hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
free(c);
return NULL;
}
if(!CryptCreateHash(c->hProv, CALG_MD4, 0, 0, &c->hHash)) {
CryptReleaseContext(c->hProv, 0);
free(c);
return NULL;
}
#else
MD4_Init(&c->u.md4);
#endif
break;
case MDH_MD5:
#ifdef MDH_MD_BACKEND_CAPI
if(!CryptAcquireContext(&c->hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
free(c);
return NULL;
}
if(!CryptCreateHash(c->hProv, CALG_MD5, 0, 0, &c->hHash)) {
CryptReleaseContext(c->hProv, 0);
free(c);
return NULL;
}
#else
MD5_Init(&c->u.md5);
#endif
break;
case MDH_BLAKE2:
if(!outlen || outlen > 64) {
free(c);
return NULL;
}
#ifdef MDH_BLAKE2_BACKEND_WOLFSSL
if(wc_InitBlake2b(&c->blake2, outlen) != 0) {
free(c);
return NULL;
}
#else
if(blake2b_init(&c->blake2, outlen) != 0) {
free(c);
return NULL;
}
#endif
break;
default:
free(c);
return NULL;
}
return c;
}
int mdh_update(mdh_ctx *c, const void *data, unsigned int len)
{
if(!c) return 0;
if(len == 0) return 1;
switch(c->alg) {
case MDH_MD4:
#ifdef MDH_MD_BACKEND_CAPI
return CryptHashData(c->hHash, (BYTE *)data, len, 0) ? 1 : 0;
#else
MD4_Update(&c->u.md4, data, (size_t)len);
return 1;
#endif
case MDH_MD5:
#ifdef MDH_MD_BACKEND_CAPI
return CryptHashData(c->hHash, (BYTE *)data, len, 0) ? 1 : 0;
#else
MD5_Update(&c->u.md5, data, (unsigned long)len);
return 1;
#endif
case MDH_BLAKE2:
#ifdef MDH_BLAKE2_BACKEND_WOLFSSL
return wc_Blake2bUpdate(&c->blake2, (const byte *)data, len) == 0;
#else
return blake2b_update(&c->blake2, data, len) == 0;
#endif
}
return 0;
}
int mdh_final(mdh_ctx *c, unsigned char *out, unsigned int *outlen)
{
if(!c || !outlen) return 0;
switch(c->alg) {
case MDH_MD4:
#ifdef MDH_MD_BACKEND_CAPI
{
DWORD l = (DWORD)*outlen;
if(!CryptGetHashParam(c->hHash, HP_HASHVAL, out, &l, 0))
return 0;
*outlen = (unsigned int)l;
return 1;
}
#else
MD4_Final(out, &c->u.md4);
*outlen = 16;
return 1;
#endif
case MDH_MD5:
#ifdef MDH_MD_BACKEND_CAPI
{
DWORD l = (DWORD)*outlen;
if(!CryptGetHashParam(c->hHash, HP_HASHVAL, out, &l, 0))
return 0;
*outlen = (unsigned int)l;
return 1;
}
#else
MD5_Final(out, &c->u.md5);
*outlen = 16;
return 1;
#endif
case MDH_BLAKE2:
if(*outlen < c->outlen) return 0;
#ifdef MDH_BLAKE2_BACKEND_WOLFSSL
if(wc_Blake2bFinal(&c->blake2, out, c->outlen) != 0)
return 0;
#else
if(blake2b_final(&c->blake2, out, c->outlen) != 0)
return 0;
#endif
*outlen = c->outlen;
return 1;
}
return 0;
}
void mdh_free(mdh_ctx *c)
{
if(!c) return;
#ifdef MDH_MD_BACKEND_CAPI
if(c->hHash) CryptDestroyHash(c->hHash);
if(c->hProv) CryptReleaseContext(c->hProv, 0);
#endif
memset(c, 0, sizeof(*c));
free(c);
}

35
src/mdhash.h Normal file
View File

@ -0,0 +1,35 @@
/*
3APA3A simplest proxy server
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement
Internal MD4/MD5/BLAKE2 hash abstraction.
- Windows (no wolfSSL): CryptoAPI (CAPI) for MD4/MD5; bundled BLAKE2.
- wolfSSL: wolfCrypt for MD4/MD5 (OpenSSL compat) and BLAKE2 (native).
- Other: bundled public-domain MD4/MD5 + bundled BLAKE2 reference.
*/
#ifndef _MDHASH_H
#define _MDHASH_H
typedef enum { MDH_MD4, MDH_MD5, MDH_BLAKE2 } mdh_alg;
typedef struct mdh_ctx mdh_ctx;
/* alg selects the hash. outlen selects digest size:
- MD4/MD5: outlen ignored (fixed 16 bytes).
- BLAKE2: outlen is the requested digest length (1..64).
Returns NULL on failure. */
mdh_ctx *mdh_init(mdh_alg alg, unsigned int outlen);
/* Returns 1 on success, 0 on failure. */
int mdh_update(mdh_ctx *c, const void *data, unsigned int len);
/* outlen is in/out: caller passes buffer size, receives hash length.
Returns 1 on success, 0 on failure. */
int mdh_final(mdh_ctx *c, unsigned char *out, unsigned int *outlen);
/* Safe to call with NULL. */
void mdh_free(mdh_ctx *c);
#endif /* _MDHASH_H */

View File

@ -214,6 +214,7 @@ struct pcre_filter_data {
int users; int users;
pcre2_code * re; pcre2_code * re;
pcre2_match_data * match_data; pcre2_match_data * match_data;
pcre2_match_context * match_context;
int action; int action;
char * replace; char * replace;
struct ace *acl; struct ace *acl;
@ -223,6 +224,7 @@ static void pcre_data_free(struct pcre_filter_data *pcrefd){
_3proxy_mutex_lock(&pcre_mutex); _3proxy_mutex_lock(&pcre_mutex);
pcrefd->users--; pcrefd->users--;
if(!pcrefd->users){ if(!pcrefd->users){
if(pcrefd->match_context) pcre2_match_context_free(pcrefd->match_context);
if(pcrefd->match_data) pcre2_match_data_free(pcrefd->match_data); if(pcrefd->match_data) pcre2_match_data_free(pcrefd->match_data);
if(pcrefd->re) pcre2_code_free(pcrefd->re); if(pcrefd->re) pcre2_code_free(pcrefd->re);
if(pcrefd->acl) pl->freeacl(pcrefd->acl); if(pcrefd->acl) pl->freeacl(pcrefd->acl);
@ -283,10 +285,12 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
if(!match) return CONTINUE; if(!match) return CONTINUE;
if(!pcrefd->re) return pcrefd->action; if(!pcrefd->re) return pcrefd->action;
for(; offset < *length_p; nreplaces++){ for(; offset < *length_p; nreplaces++){
int repsz;
count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcrefd->match_data, NULL); count = pcre2_match(pcrefd->re, (PCRE2_SPTR)*buf_p, *length_p, offset, 0, pcrefd->match_data, pcrefd->match_context);
if(count <= 0) break; if(count <= 0) break;
ovector = pcre2_get_ovector_pointer(pcrefd->match_data); ovector = pcre2_get_ovector_pointer(pcrefd->match_data);
if(ovector[0] > (PCRE2_SIZE)*length_p || ovector[1] > (PCRE2_SIZE)*length_p || ovector[1] < ovector[0]) break;
if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action; if(!(replace = pcrefd->replace) || param->nooverwritefilter) return pcrefd->action;
replen = *length_p - ovector[1]; replen = *length_p - ovector[1];
@ -300,6 +304,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
num = atoi(replace); num = atoi(replace);
while(isnumber(*replace)) replace++; while(isnumber(*replace)) replace++;
if(num > (count - 1)) continue; if(num > (count - 1)) continue;
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
replen += (ovector[(num<<1) + 1] - ovector[(num<<1)]); replen += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
} }
else { else {
@ -319,6 +325,8 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
replace ++; replace ++;
num = atoi(replace); num = atoi(replace);
if(num > (count - 1)) continue; if(num > (count - 1)) continue;
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]); memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]);
target += (ovector[(num<<1) + 1] - ovector[(num<<1)]); target += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
while(isnumber(*replace)) replace++; while(isnumber(*replace)) replace++;
@ -327,6 +335,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
*target++ = *replace++; *target++ = *replace++;
} }
} }
repsz = (int)(target - tmpbuf);
memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]); memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]);
if((ovector[0] + replen + 1) > *bufsize_p){ if((ovector[0] + replen + 1) > *bufsize_p){
newbuf = pl->mallocfunc(ovector[0] + replen + 1); newbuf = pl->mallocfunc(ovector[0] + replen + 1);
@ -343,10 +352,11 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
pl->freefunc(tmpbuf); pl->freefunc(tmpbuf);
(*buf_p)[ovector[0] + replen] = 0; (*buf_p)[ovector[0] + replen] = 0;
*length_p = ovector[0] + replen; *length_p = ovector[0] + replen;
if(ovector[0] + replen <= offset){ offset = ovector[0] + repsz;
break; if(ovector[1] == ovector[0] && offset <= (int)ovector[0]){
/* zero-width match with empty replacement: force progress */
offset = ovector[1] + 1;
} }
offset = ovector[0] + (int)strlen(pcrefd->replace);
} }
return nreplaces? pcrefd->action : CONTINUE; return nreplaces? pcrefd->action : CONTINUE;
#undef pcrefd #undef pcrefd
@ -442,6 +452,13 @@ static int h_pcre(int argc, unsigned char **argv){
flt->acl = acl; flt->acl = acl;
flt->replace = replace; flt->replace = replace;
flt->users = 1; flt->users = 1;
if(re){
flt->match_context = pcre2_match_context_create(NULL);
if(flt->match_context){
pcre2_set_match_limit(flt->match_context, 1000000);
pcre2_set_depth_limit(flt->match_context, 10000);
}
}
newf->instance = "pcre"; newf->instance = "pcre";
newf->data = flt; newf->data = flt;
newf->filter_open = pcre_filter_open; newf->filter_open = pcre_filter_open;
@ -549,6 +566,13 @@ static int h_pcre_rewrite(int argc, unsigned char **argv){
flt->acl = acl; flt->acl = acl;
flt->replace = replace; flt->replace = replace;
flt->users = 1; flt->users = 1;
if(re){
flt->match_context = pcre2_match_context_create(NULL);
if(flt->match_context){
pcre2_set_match_limit(flt->match_context, 1000000);
pcre2_set_depth_limit(flt->match_context, 10000);
}
}
newf->instance = "pcre"; newf->instance = "pcre";
newf->data = flt; newf->data = flt;
newf->filter_open = pcre_filter_open; newf->filter_open = pcre_filter_open;

View File

@ -71,6 +71,7 @@ struct symbol symbols[] = {
{symbols+46, "make_ace", (void *) make_ace}, {symbols+46, "make_ace", (void *) make_ace},
{symbols+47, "freeacl", (void *) freeacl}, {symbols+47, "freeacl", (void *) freeacl},
{symbols+48, "handleredirect", (void *) handleredirect}, {symbols+48, "handleredirect", (void *) handleredirect},
{symbols+49, "imapp", (void *) imappchild},
{NULL, "", NULL} {NULL, "", NULL}
}; };

View File

@ -51,8 +51,56 @@ void lower (char *string)
} }
#endif #endif
/* RFC 4514 escaping for DN attribute values. Returns dst, NULL on overflow. */
static char * ldap_escape_dn(const char *src, char *dst, int dstlen)
{
int j = 0;
unsigned char c;
for (; *src; src++){
c = (unsigned char)*src;
if(c == ',' || c == '+' || c == '"' || c == '\\' || c == '<' || c == '>' || c == ';' || c == '=' || c < 0x20 || c == 0x7f){
if(j + 3 >= dstlen) return NULL;
sprintf(dst + j, "\\%02X", c);
j += 3;
}
else {
if(j + 1 >= dstlen) return NULL;
dst[j++] = (char)c;
}
}
dst[j] = 0;
return dst;
}
/* RFC 4515 escaping for search filter values. Returns dst, NULL on overflow. */
static char * ldap_escape_filter(const char *src, char *dst, int dstlen)
{
int j = 0;
unsigned char c;
for (; *src; src++){
c = (unsigned char)*src;
if(c == '*' || c == '(' || c == ')' || c == '\\' || c == 0 || c < 0x20 || c >= 0x7f){
if(j + 3 >= dstlen) return NULL;
sprintf(dst + j, "\\%02X", c);
j += 3;
}
else {
if(j + 1 >= dstlen) return NULL;
dst[j++] = (char)c;
}
}
dst[j] = 0;
return dst;
}
/* reject names unsafe for use in filesystem paths */
static int unsafe_filename(const char *name)
{
return (strchr(name, '/') || strchr(name, '\\') || strstr(name, "..") || !*name);
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
int savecounters(void) int savecounters(void *v)
{ {
struct trafcount *tc=mypluginlink->conf->trafcounter; struct trafcount *tc=mypluginlink->conf->trafcounter;
struct trafcount *tcd; struct trafcount *tcd;
@ -67,8 +115,8 @@ int savecounters(void)
tcd = tc; tcd = tc;
tc = tc->next; tc = tc->next;
f=NULL; f=NULL;
if(strcmp(tcd->comment,"ldapcounters")==0) { if(strcmp(tcd->comment,"ldapcounters")==0 && !unsafe_filename(tcd->ace->users->user)) {
tmpbuf=malloc(strlen(pat_file)+strlen(ldap_dircount)+strlen(tcd->ace->users->user)); tmpbuf=malloc(strlen(ldap_dircount)+strlen(tcd->ace->users->user)+sizeof(".lc"));
sprintf(tmpbuf,pat_file,ldap_dircount,tcd->ace->users->user); sprintf(tmpbuf,pat_file,ldap_dircount,tcd->ace->users->user);
f=fopen(tmpbuf,"w+b"); f=fopen(tmpbuf,"w+b");
fseek(f,0,SEEK_SET); fseek(f,0,SEEK_SET);
@ -100,6 +148,7 @@ static int ldapfunc(struct clientparam *param)
LDAPMessage *res = NULL; LDAPMessage *res = NULL;
int rc = -1; int rc = -1;
char tmpbuf[1024]; char tmpbuf[1024];
char escuser[512];
/* test proxy user auth ------------------------*/ /* test proxy user auth ------------------------*/
if(!param->username || !param->password) return 4; if(!param->username || !param->password) return 4;
@ -126,7 +175,12 @@ static int ldapfunc(struct clientparam *param)
/* create user for test auth */ /* create user for test auth */
sprintf(tmpbuf,"%.200s=%.200s,%.200s",attrs[0],param->username,ldap_userenv); if(!ldap_escape_dn(param->username, escuser, sizeof(escuser)))
{
ldap_unbind_s(ld);
return 5;
}
snprintf(tmpbuf, sizeof(tmpbuf), "%.200s=%.510s,%.200s",attrs[0],escuser,ldap_userenv);
rc = ldap_bind_s( ld, tmpbuf, param->password, LDAP_AUTH_SIMPLE ); rc = ldap_bind_s( ld, tmpbuf, param->password, LDAP_AUTH_SIMPLE );
@ -162,7 +216,12 @@ static int ldapfunc(struct clientparam *param)
/* test enter user in filter ------------------------------ /* test enter user in filter ------------------------------
create filter for search*/ create filter for search*/
sprintf(tmpbuf,"(&(%.200s=%.200s)(%.200s=%.200s))",attrs[0],param->username, if(!ldap_escape_filter(param->username, escuser, sizeof(escuser)))
{
ldap_unbind_s(ld);
return 5;
}
snprintf(tmpbuf, sizeof(tmpbuf), "(&(%.200s=%.510s)(%.200s=%.200s))",attrs[0],escuser,
ldap_group_attr,ldap_access); ldap_group_attr,ldap_access);
@ -326,7 +385,7 @@ int h_trafgroup(int argc, unsigned char ** argv)
while (rc > 0) while (rc > 0)
{ {
vals=ldap_get_values(ld, msg, getattr); vals=ldap_get_values(ld, msg, getattr);
if (vals != NULL && vals[0] != NULL ) if (vals != NULL && vals[0] != NULL && !unsafe_filename(vals[0]) )
{ {
/* -------------bandlim---------- /* -------------bandlim----------
@ -378,7 +437,7 @@ int h_trafgroup(int argc, unsigned char ** argv)
newtrafcount->traflim64 = traflimit; newtrafcount->traflim64 = traflimit;
newtrafcount->comment=(*mypluginlink->strdupfunc)("ldapcounters"); newtrafcount->comment=(*mypluginlink->strdupfunc)("ldapcounters");
newtrafcount->number=0; newtrafcount->number=0;
tmpbuf=malloc(strlen(pat_file)+strlen(ldap_dircount)+strlen(vals[0])); tmpbuf=malloc(strlen(ldap_dircount)+strlen(vals[0])+sizeof(".lc"));
sprintf(tmpbuf,pat_file,ldap_dircount,vals[0]); sprintf(tmpbuf,pat_file,ldap_dircount,vals[0]);
f=NULL; f=NULL;
f=fopen(tmpbuf,"rb"); f=fopen(tmpbuf,"rb");

View File

@ -49,9 +49,13 @@ char **load_string(FILE *f,int max_count_str, int *countloadstr,
/*load from file new strings */ /*load from file new strings */
i=0; i=0;
while ( !feof(f) || i< max_count_str) while ( !feof(f) && i < max_count_str)
{ {
if(!fgets(tmpbuf1, 1023,f)) return NULL; if(!fgets(tmpbuf1, 1023,f)){
if(pt) free(pt);
free(old_table);
return NULL;
}
if ((strstr(tmpbuf1,stop))!=NULL) { break; } if ((strstr(tmpbuf1,stop))!=NULL) { break; }

View File

@ -10,6 +10,12 @@
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
void * pop3pchild(struct clientparam* param) { void * pop3pchild(struct clientparam* param) {
int i=0, res; int i=0, res;
unsigned char buf[320]; unsigned char buf[320];
@ -22,6 +28,19 @@ void * pop3pchild(struct clientparam* param) {
socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]); socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]);
RETURN(0); RETURN(0);
} }
if(!strncasecmp((char *)buf, "CAPA", 4) && !NOSTARTTLS){
socksend(param, param->clisock, (unsigned char *)"+OK Capability list follows\r\nSTLS\r\n.\r\n", 38, conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
continue;
}
#ifndef WITHMAIN
if(!strncasecmp((char *)buf, "STLS", 4) && !param->srv->nostarttls){
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) {RETURN(623);}
param->clientstarttls = S_POP3P;
if(!param->srv->targetport) param->srv->targetport = htons(110);
return tlsprchild(param);
}
#endif
socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]); socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
} }
@ -65,7 +84,7 @@ struct proxydef childdef = {
110, 110,
0, 0,
S_POP3P, S_POP3P,
" -hdefault_host[:port] - use this host and port as default if no host specified\n" " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
}; };
#include "proxymain.c" #include "proxymain.c"

View File

@ -240,6 +240,9 @@ void * proxychild(struct clientparam* param) {
int keepalive = 0; int keepalive = 0;
uint64_t contentlength64 = 0; uint64_t contentlength64 = 0;
int hascontent =0; int hascontent =0;
int clhdrofs = -1;
int chunkedcli = 0;
int clhdrofs_req = -1;
int isconnect = 0; int isconnect = 0;
int redirect = 0; int redirect = 0;
int prefix = 0, ckeepalive=0; int prefix = 0, ckeepalive=0;
@ -266,6 +269,9 @@ void * proxychild(struct clientparam* param) {
for(;;){ for(;;){
memset(buf, 0, bufsize); memset(buf, 0, bufsize);
inbuf = 0; inbuf = 0;
chunkedcli = 0;
clhdrofs_req = -1;
param->nolongdatfilter = 0;
if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){ if(keepalive && (param->cliinbuf == param->clioffset) && (param->remsock != INVALID_SOCKET)){
@ -413,6 +419,10 @@ for(;;){
param->password = (unsigned char *)strdup((char *)sb+1); param->password = (unsigned char *)strdup((char *)sb+1);
param->pwtype = 0; param->pwtype = 0;
} }
else if(param->password){
free(param->password);
param->password = NULL;
}
if(param->username)free(param->username); if(param->username)free(param->username);
param->username = (unsigned char *)strdup((char *)username); param->username = (unsigned char *)strdup((char *)username);
continue; continue;
@ -458,13 +468,14 @@ for(;;){
if(parsehostname((char *)sb, param, 80)) RETURN(100); if(parsehostname((char *)sb, param, 80)) RETURN(100);
} }
newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8); newbuf = malloc(strlen((char *)req) + strlen((char *)(buf+inbuf)) + 8);
if(newbuf){
sp = (unsigned char *)strchr((char *)req+1, '/'); sp = (unsigned char *)strchr((char *)req+1, '/');
if(newbuf && sp){
memcpy(newbuf, req, (sp - req)); memcpy(newbuf, req, (sp - req));
sprintf((char*)newbuf + (sp - req), "http://%s%s",sb,sp); sprintf((char*)newbuf + (sp - req), "http://%s%s",sb,sp);
free(req); free(req);
req = newbuf; req = newbuf;
} }
else if(newbuf) free(newbuf);
if(se)*se = c; if(se)*se = c;
} }
if(ftp && i > 13 && (!strncasecmp((char *)(buf+inbuf), "authorization", 13))){ if(ftp && i > 13 && (!strncasecmp((char *)(buf+inbuf), "authorization", 13))){
@ -485,12 +496,17 @@ for(;;){
if(param->extpassword)free(param->extpassword); if(param->extpassword)free(param->extpassword);
param->extpassword = (unsigned char *)strdup((char *)sb+1); param->extpassword = (unsigned char *)strdup((char *)sb+1);
} }
else if(param->extpassword){
free(param->extpassword);
param->extpassword = NULL;
}
if(param->extusername)free(param->extusername); if(param->extusername)free(param->extusername);
param->extusername = (unsigned char *)strdup((char *)username); param->extusername = (unsigned char *)strdup((char *)username);
continue; continue;
} }
} }
if(i> 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){ if(i> 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){
if(chunkedcli) continue;
sb = (unsigned char *)strchr((char *)(buf+inbuf), ':'); sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
if(!sb)continue; if(!sb)continue;
++sb; ++sb;
@ -500,6 +516,23 @@ for(;;){
RETURN(10); RETURN(10);
} }
if(param->ndatfilterscli > 0 && contentlength64 > 0) continue; if(param->ndatfilterscli > 0 && contentlength64 > 0) continue;
clhdrofs_req = inbuf;
}
else if(i>25 && (!strncasecmp((char *)(buf+inbuf), "transfer-encoding", 17))){
sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
if(sb){
++sb;
while(isspace(*sb))sb++;
if(!strncasecmp((char *)sb, "chunked", 7)){
chunkedcli = 1;
if(clhdrofs_req >= 0){
buf[clhdrofs_req] = 'X';
clhdrofs_req = -1;
}
contentlength64 = 0;
param->nolongdatfilter = 1;
}
}
} }
inbuf += i; inbuf += i;
if((bufsize - inbuf) < LINESIZE){ if((bufsize - inbuf) < LINESIZE){
@ -565,7 +598,7 @@ for(;;){
if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) { if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) {
param->nolongdatfilter = 1; param->nolongdatfilter = 1;
} }
else if(param->ndatfilterscli > 0 && contentlength64 > 0){ else if(param->ndatfilterscli > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64){
uint64_t newlen64; uint64_t newlen64;
newlen64 = (uint64_t) sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S); newlen64 = (uint64_t) sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S);
if(newlen64 == contentlength64) { if(newlen64 == contentlength64) {
@ -906,7 +939,35 @@ for(;;){
if(param->bandlimfunc) { if(param->bandlimfunc) {
sleeptime = param->bandlimfunc(param, 0, (int)strlen((char *)buf)); sleeptime = param->bandlimfunc(param, 0, (int)strlen((char *)buf));
} }
if(contentlength64 > 0){ if(chunkedcli || contentlength64 > 0){
if(chunkedcli){
do {
unsigned char smallbuf[32];
while ((i = sockgetlinebuf(param, CLIENT, smallbuf, 30, '\n', conf.timeouts[STRING_S])) == 2) {
if (socksend(param, param->remsock, smallbuf, i, conf.timeouts[STRING_S]) != i) RETURN(536);
if(chunkedcli == 2) break;
}
if(i<3) break;
if (socksend(param, param->remsock, smallbuf, i, conf.timeouts[STRING_S]) != i) RETURN(536);
if(chunkedcli == 2) {
if((i = sockgetlinebuf(param, CLIENT, smallbuf, 30, '\n', conf.timeouts[STRING_S])) != 2) RETURN(537);
if (socksend(param, param->remsock, smallbuf, i, conf.timeouts[STRING_S]) != i) RETURN(536);
break;
}
smallbuf[i] = 0;
contentlength64 = 0;
sscanf((char *)smallbuf, "%"SCNx64"", &contentlength64);
if(contentlength64 == 0) chunkedcli = 2;
else {
param->waitclient64 = contentlength64;
res = mapsocket(param, conf.timeouts[CONNECTION_S]);
param->waitclient64 = 0;
if(res != 99) RETURN(res);
}
} while(chunkedcli);
res = 99;
}
else {
param->waitclient64 = contentlength64; param->waitclient64 = contentlength64;
res = mapsocket(param, conf.timeouts[CONNECTION_S]); res = mapsocket(param, conf.timeouts[CONNECTION_S]);
param->waitclient64 = 0; param->waitclient64 = 0;
@ -914,6 +975,7 @@ for(;;){
RETURN(res); RETURN(res);
} }
} }
}
contentlength64 = 0; contentlength64 = 0;
inbuf = 0; inbuf = 0;
ckeepalive = keepalive; ckeepalive = keepalive;
@ -921,6 +983,7 @@ for(;;){
authenticate = 0; authenticate = 0;
param->chunked = 0; param->chunked = 0;
hascontent = 0; hascontent = 0;
clhdrofs = -1;
while( (i = sockgetlinebuf(param, SERVER, buf + inbuf, LINESIZE - 1, '\n', conf.timeouts[(res)?STRING_S:STRING_L])) > 2) { while( (i = sockgetlinebuf(param, SERVER, buf + inbuf, LINESIZE - 1, '\n', conf.timeouts[(res)?STRING_S:STRING_L])) > 2) {
if(!res && i>9)param->status = res = atoi((char *)buf + inbuf + 9); if(!res && i>9)param->status = res = atoi((char *)buf + inbuf + 9);
@ -942,6 +1005,7 @@ for(;;){
authenticate = 1; authenticate = 1;
} }
else if(i > 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){ else if(i > 15 && (!strncasecmp((char *)(buf+inbuf), "content-length", 14))){
if(param->chunked) continue;
buf[inbuf+i]=0; buf[inbuf+i]=0;
sb = (unsigned char *)strchr((char *)(buf+inbuf), ':'); sb = (unsigned char *)strchr((char *)(buf+inbuf), ':');
if(!sb)continue; if(!sb)continue;
@ -949,6 +1013,7 @@ for(;;){
while(isspace(*sb))sb++; while(isspace(*sb))sb++;
sscanf((char *)sb, "%"SCNu64"", &contentlength64); sscanf((char *)sb, "%"SCNu64"", &contentlength64);
hascontent = 1; hascontent = 1;
clhdrofs = inbuf;
if(param->unsafefilter && param->ndatfilterssrv > 0) { if(param->unsafefilter && param->ndatfilterssrv > 0) {
hascontent = 2; hascontent = 2;
continue; continue;
@ -965,6 +1030,12 @@ for(;;){
while(isspace(*sb))sb++; while(isspace(*sb))sb++;
if(!strncasecmp((char *)sb, "chunked", 7)){ if(!strncasecmp((char *)sb, "chunked", 7)){
param->chunked = 1; param->chunked = 1;
if(clhdrofs >= 0){
buf[clhdrofs] = 'X';
clhdrofs = -1;
contentlength64 = 0;
hascontent = 0;
}
} }
} }
inbuf += i; inbuf += i;
@ -1009,7 +1080,7 @@ for(;;){
if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) { if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) {
param->nolongdatfilter = 1; param->nolongdatfilter = 1;
} }
else if(param->ndatfilterssrv > 0 && contentlength64 > 0 && param->operation != HTTP_HEAD && res != 204 && res != 304){ else if(param->ndatfilterssrv > 0 && contentlength64 > 0 && contentlength64 == (uint64_t)(unsigned long)contentlength64 && param->operation != HTTP_HEAD && res != 204 && res != 304){
uint64_t newlen; uint64_t newlen;
newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S); newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S);
if(newlen == contentlength64) { if(newlen == contentlength64) {

View File

@ -188,6 +188,8 @@ unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, in
unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec); unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec);
int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to); int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
int getmultiline(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, const char *cap, int *found);
int hascap(const unsigned char *line, const char *cap);
@ -240,9 +242,7 @@ extern int paused;
extern int demon; extern int demon;
unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf); 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); unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int tohex);
#endif
int de64 (const unsigned char *in, unsigned char *out, int maxlen); int de64 (const unsigned char *in, unsigned char *out, int maxlen);
unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen); unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen);
void tohex(unsigned char *in, unsigned char *out, int len); void tohex(unsigned char *in, unsigned char *out, int len);
@ -314,6 +314,7 @@ void srvinit2(struct srvparam * srv, struct clientparam *param);
void srvfree(struct srvparam * srv); void srvfree(struct srvparam * srv);
unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t); unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
int readconfig(FILE * fp); int readconfig(FILE * fp);
void initcommands(void);
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to); int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
@ -327,6 +328,7 @@ extern char *copyright;
void * dnsprchild(struct clientparam * param); void * dnsprchild(struct clientparam * param);
void * pop3pchild(struct clientparam * param); void * pop3pchild(struct clientparam * param);
void * imappchild(struct clientparam * param);
void * smtppchild(struct clientparam * param); void * smtppchild(struct clientparam * param);
void * proxychild(struct clientparam * param); void * proxychild(struct clientparam * param);
void * sockschild(struct clientparam * param); void * sockschild(struct clientparam * param);

View File

@ -528,6 +528,27 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.needuser = 0; srv.needuser = 0;
if(*(argv[i] + 2)) srv.needuser = atoi(argv[i] + 2); if(*(argv[i] + 2)) srv.needuser = atoi(argv[i] + 2);
break; break;
case 'x':
srv.nostarttls = 1;
break;
case 'X':
if(!strncasecmp(argv[i]+2, "imap", 4)) srv.srvstarttls = S_IMAPP;
else if(!strncasecmp(argv[i]+2, "pop3", 4)) srv.srvstarttls = S_POP3P;
else if(!strncasecmp(argv[i]+2, "smtp", 4)) srv.srvstarttls = S_SMTPP;
else error = 1;
break;
case 'F':
{
PROXYSOCKADDRTYPE fsa;
memset(&fsa, 0, sizeof(fsa));
if(!getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&fsa)) error = 1;
else if(*SAFAMILY(&fsa) == AF_INET) srv.fakeip = *(uint32_t *)SAADDR(&fsa);
#ifndef NOIPV6
else if(*SAFAMILY(&fsa) == AF_INET6) memcpy(srv.fakeip6, SAADDR(&fsa), 16);
#endif
else error = 1;
}
break;
case 'T': case 'T':
srv.transparent = 1; srv.transparent = 1;
break; break;
@ -772,6 +793,9 @@ int MODULEMAINFUNC (int argc, char** argv){
return -12; return -12;
} }
#ifndef NOIPV6 #ifndef NOIPV6
#ifndef IPV6_BOUND_IF
#define IPV6_BOUND_IF 125
#endif
if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) { if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) {
dolog(&defparam, (unsigned char *)"failed to bind device"); dolog(&defparam, (unsigned char *)"failed to bind device");
return -12; return -12;

View File

@ -47,6 +47,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
switch(redir->type){ switch(redir->type){
case R_TCP: case R_TCP:
case R_HTTP: case R_HTTP:
case R_IMAP:
return 0; return 0;
case R_CONNECT: case R_CONNECT:
case R_CONNECTP: case R_CONNECTP:
@ -374,7 +375,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
ntohs(*SAPORT(&param->sincl)) ntohs(*SAPORT(&param->sincl))
); );
if(socksend(param, param->remsock, (unsigned char *)buf, len, conf.timeouts[CHAIN_TO])!=len) return 39; if(socksend(param, param->remsock, (unsigned char *)buf, len, conf.timeouts[CHAIN_TO])!=len) return 39;
return 0; if(cur->type == R_HA) return 0;
} }
} }
else { else {

View File

@ -10,11 +10,23 @@
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
char ehlo[] = "250-Proxy\r\n" char ehlo[] = "250-Proxy\r\n"
"250-AUTH PLAIN LOGIN\r\n" "250-AUTH PLAIN LOGIN\r\n"
"250-8BITMIME\r\n" "250-8BITMIME\r\n"
"250 DSN\r\n"; "250 DSN\r\n";
char ehlotls[] = "250-Proxy\r\n"
"250-AUTH PLAIN LOGIN\r\n"
"250-8BITMIME\r\n"
"250-STARTTLS\r\n"
"250 DSN\r\n";
int readreply (struct clientparam* param) { int readreply (struct clientparam* param) {
unsigned char * buf; unsigned char * buf;
int res, i, bufsize = 640; int res, i, bufsize = 640;
@ -112,8 +124,17 @@ void * smtppchild(struct clientparam* param) {
socksend(param, param->clisock, (unsigned char *)"250 Proxy\r\n", 11,conf.timeouts[STRING_S]); socksend(param, param->clisock, (unsigned char *)"250 Proxy\r\n", 11,conf.timeouts[STRING_S]);
} }
else if(!strncasecmp((char *)buf, "EHLO ", 5)){ else if(!strncasecmp((char *)buf, "EHLO ", 5)){
socksend(param, param->clisock, (unsigned char *)ehlo, sizeof(ehlo) - 1,conf.timeouts[STRING_S]); if(!NOSTARTTLS) socksend(param, param->clisock, (unsigned char *)ehlotls, sizeof(ehlotls) - 1,conf.timeouts[STRING_S]);
else socksend(param, param->clisock, (unsigned char *)ehlo, sizeof(ehlo) - 1,conf.timeouts[STRING_S]);
} }
#ifndef WITHMAIN
else if(!strncasecmp((char *)buf, "STARTTLS", 8) && !param->srv->nostarttls){
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) {RETURN(673);}
param->clientstarttls = S_SMTPP;
if(!param->srv->targetport) param->srv->targetport = htons(587);
return tlsprchild(param);
}
#endif
else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]); else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
else { else {
login = -1; login = -1;
@ -132,7 +153,7 @@ void * smtppchild(struct clientparam* param) {
i = de64(buf,username,255); i = de64(buf,username,255);
if(i < 1) {RETURN(664);} if(i < 1) {RETURN(664);}
username[i] = 0; username[i] = 0;
parseconnusername((char *)username, param, 0, 25); parseconnusername((char *)username, param, 0, 587);
socksend(param, param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]); socksend(param, param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 2) {RETURN(665);} if(i < 2) {RETURN(665);}
@ -157,7 +178,7 @@ void * smtppchild(struct clientparam* param) {
} }
if(i < 3 || *username) {RETURN(668);} if(i < 3 || *username) {RETURN(668);}
username[i] = 0; username[i] = 0;
parseconnusername((char *)username+1, param, 0, 25); parseconnusername((char *)username+1, param, 0, 587);
res = (int)strlen((char *)username+1) + 2; res = (int)strlen((char *)username+1) + 2;
if(res < i){ if(res < i){
if(param->extpassword) free(param->extpassword); if(param->extpassword) free(param->extpassword);
@ -180,9 +201,7 @@ void * smtppchild(struct clientparam* param) {
param->operation = CONNECT; param->operation = CONNECT;
res = (*param->srv->authfunc)(param); res = (*param->srv->authfunc)(param);
if(res) {RETURN(res);} if(res) {RETURN(res);}
do { i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, NULL, NULL);
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
} while (i > 3 && buf[3] == '-');
if( i < 3 ) {RETURN(671);} if( i < 3 ) {RETURN(671);}
buf[i] = 0; buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(672);} if(strncasecmp((char *)buf, "220", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(672);}
@ -233,9 +252,10 @@ void * smtppchild(struct clientparam* param) {
if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(682);} if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(682);}
*username = 0; *username = 0;
i = (int)strlen((char *)param->extusername) + 1; i = (int)strlen((char *)param->extusername) + 1;
res = (int)strlen((char *)param->extpassword);
if(i + 1 + res >= (int)sizeof(username) || ((i + 1 + res + 2) / 3) * 4 + 1 > (int)sizeof(buf)) {RETURN(683);}
memcpy(username+1, param->extusername, i); memcpy(username+1, param->extusername, i);
i++; i++;
res = (int)strlen((char *)param->extpassword);
memcpy(username + i, param->extpassword, res); memcpy(username + i, param->extpassword, res);
i+=res; i+=res;
en64(username, buf, i); en64(username, buf, i);
@ -291,7 +311,7 @@ void * smtppchild(struct clientparam* param) {
CLEANRET: CLEANRET:
if(param->hostname&&param->extusername) { if(param->hostname&&param->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==25?0:':',ntohs(*SAPORT(&param->sinsr))); sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==587?0:':',ntohs(*SAPORT(&param->sinsr)));
dolog(param, buf); dolog(param, buf);
} }
else dolog(param, NULL); else dolog(param, NULL);
@ -306,10 +326,10 @@ CLEANRET:
#ifdef WITHMAIN #ifdef WITHMAIN
struct proxydef childdef = { struct proxydef childdef = {
smtppchild, smtppchild,
25, 587,
0, 0,
S_SMTPP, S_SMTPP,
" -hdefault_host[:port] - use this host and port as default if no host specified\n" " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
}; };
#include "proxymain.c" #include "proxymain.c"

View File

@ -6,11 +6,20 @@
*/ */
#include "structures.h" #include "structures.h"
#ifdef WITH_WOLFSSL
#include <wolfssl/options.h>
#include <wolfssl/openssl/crypto.h>
#include <wolfssl/openssl/x509.h>
#include <wolfssl/openssl/pem.h>
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/openssl/err.h>
#else
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#endif
#include "proxy.h" #include "proxy.h"
#include "ssl.h" #include "ssl.h"
@ -487,7 +496,7 @@ SSL_CTX * ssl_cli_ctx(SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_ke
int err = 0; int err = 0;
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
ctx = SSL_CTX_new(SSLv23_server_method()); ctx = SSL_CTX_new(SSLv23_server_method());
#else #else
ctx = SSL_CTX_new(TLS_server_method()); ctx = SSL_CTX_new(TLS_server_method());
@ -517,14 +526,17 @@ SSL_CTX * ssl_cli_ctx(SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_ke
if(config->server_min_proto_version)SSL_CTX_set_min_proto_version(ctx, config->server_min_proto_version); if(config->server_min_proto_version)SSL_CTX_set_min_proto_version(ctx, config->server_min_proto_version);
if(config->server_max_proto_version)SSL_CTX_set_max_proto_version(ctx, config->server_max_proto_version); if(config->server_max_proto_version)SSL_CTX_set_max_proto_version(ctx, config->server_max_proto_version);
if(config->server_cipher_list)SSL_CTX_set_cipher_list(ctx, config->server_cipher_list); if(config->server_cipher_list)SSL_CTX_set_cipher_list(ctx, config->server_cipher_list);
#if OPENSSL_VERSION_NUMBER >= 0x10101000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x10101000L
if(config->server_ciphersuites)SSL_CTX_set_ciphersuites(ctx, config->server_ciphersuites); if(config->server_ciphersuites)SSL_CTX_set_ciphersuites(ctx, config->server_ciphersuites);
#elif defined(WITH_WOLFSSL)
/* wolfSSL has no separate TLS1.3 ciphersuites API; route to cipher list. */
if(config->server_ciphersuites)wolfSSL_CTX_set_cipher_list(ctx, config->server_ciphersuites);
#endif #endif
if(config->server_verify){ if(config->server_verify){
if(config->server_ca_file || config->server_ca_dir){ if(config->server_ca_file || config->server_ca_dir){
SSL_CTX_load_verify_locations(ctx, config->server_ca_file, config->server_ca_dir); SSL_CTX_load_verify_locations(ctx, config->server_ca_file, config->server_ca_dir);
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
else if(config->server_ca_store){ else if(config->server_ca_store){
SSL_CTX_load_verify_store(ctx, config->server_ca_store); SSL_CTX_load_verify_store(ctx, config->server_ca_store);
} }
@ -655,7 +667,7 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
srv->so._poll = ssl_poll; srv->so._poll = ssl_poll;
} }
if(sc && (sc->mitm || sc->cli)){ if(sc && (sc->mitm || sc->cli)){
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
sc->srv_ctx = SSL_CTX_new(SSLv23_client_method()); sc->srv_ctx = SSL_CTX_new(SSLv23_client_method());
#else #else
sc->srv_ctx = SSL_CTX_new(TLS_client_method()); sc->srv_ctx = SSL_CTX_new(TLS_client_method());
@ -671,17 +683,20 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
if(sc->client_min_proto_version)SSL_CTX_set_min_proto_version(sc->srv_ctx, sc->client_min_proto_version); if(sc->client_min_proto_version)SSL_CTX_set_min_proto_version(sc->srv_ctx, sc->client_min_proto_version);
if(sc->client_max_proto_version)SSL_CTX_set_max_proto_version(sc->srv_ctx, sc->client_max_proto_version); if(sc->client_max_proto_version)SSL_CTX_set_max_proto_version(sc->srv_ctx, sc->client_max_proto_version);
if(sc->client_cipher_list)SSL_CTX_set_cipher_list(sc->srv_ctx, sc->client_cipher_list); if(sc->client_cipher_list)SSL_CTX_set_cipher_list(sc->srv_ctx, sc->client_cipher_list);
#if OPENSSL_VERSION_NUMBER >= 0x10101000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x10101000L
if(sc->client_ciphersuites)SSL_CTX_set_ciphersuites(sc->srv_ctx, sc->client_ciphersuites); if(sc->client_ciphersuites)SSL_CTX_set_ciphersuites(sc->srv_ctx, sc->client_ciphersuites);
#elif defined(WITH_WOLFSSL)
/* wolfSSL has no separate TLS1.3 ciphersuites API; route to cipher list. */
if(sc->client_ciphersuites)wolfSSL_CTX_set_cipher_list(sc->srv_ctx, sc->client_ciphersuites);
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x10200000L #if (defined(WITH_WOLFSSL) && defined(HAVE_ALPN) && LIBWOLFSSL_VERSION_HEX >= 0x03007000) || (!defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x10200000L)
if(sc->client_alpn_protos.protos_len)SSL_CTX_set_alpn_protos(sc->srv_ctx, sc->client_alpn_protos.protos, sc->client_alpn_protos.protos_len); if(sc->client_alpn_protos.protos_len)SSL_CTX_set_alpn_protos(sc->srv_ctx, sc->client_alpn_protos.protos, sc->client_alpn_protos.protos_len);
#endif #endif
if(sc->client_verify){ if(sc->client_verify){
if(sc->client_ca_file || sc->client_ca_dir){ if(sc->client_ca_file || sc->client_ca_dir){
SSL_CTX_load_verify_locations(sc->srv_ctx, sc->client_ca_file, sc->client_ca_dir); SSL_CTX_load_verify_locations(sc->srv_ctx, sc->client_ca_file, sc->client_ca_dir);
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
else if(sc->client_ca_store){ else if(sc->client_ca_store){
SSL_CTX_load_verify_store(sc->srv_ctx, sc->client_ca_store); SSL_CTX_load_verify_store(sc->srv_ctx, sc->client_ca_store);
} }

View File

@ -14,14 +14,21 @@
#include <sys/file.h> #include <sys/file.h>
#endif #endif
#ifdef WITH_WOLFSSL
#include <wolfssl/options.h>
#include <wolfssl/openssl/crypto.h>
#include <wolfssl/openssl/x509.h>
#include <wolfssl/openssl/x509v3.h>
#include <wolfssl/openssl/pem.h>
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/openssl/err.h>
#else
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
#endif #endif
#include "proxy.h" #include "proxy.h"
@ -106,21 +113,19 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
X509 *dst_cert = NULL; X509 *dst_cert = NULL;
EVP_PKEY *pk = NULL; EVP_PKEY *pk = NULL;
RSA *rsa = NULL;
int hash_size = 20; unsigned char hash_sha256[32];
unsigned char hash_sha1[20]; char hash_name_sha256[(16*2) + 1];
char hash_name_sha1[(20*2) + 1];
char cache_name[256]; char cache_name[256];
err = X509_digest(src_cert, EVP_sha1(), hash_sha1, NULL); err = X509_digest(src_cert, EVP_sha256(), hash_sha256, NULL);
if(!err){ if(!err){
return NULL; return NULL;
} }
if(config->certcache){ if(config->certcache){
bin2hex(hash_sha1, 20, hash_name_sha1, sizeof(hash_name_sha1)); bin2hex(hash_sha256, 16, hash_name_sha256, sizeof(hash_name_sha256));
sprintf(cache_name, "%s%s.pem", config->certcache, hash_name_sha1); sprintf(cache_name, "%s%s.pem", config->certcache, hash_name_sha256);
/* check if certificate is already cached */ /* check if certificate is already cached */
fcache = BIO_new_file(cache_name, "rb"); fcache = BIO_new_file(cache_name, "rb");
if ( fcache != NULL ) { if ( fcache != NULL ) {
@ -280,12 +285,6 @@ int ssl_file_init = 0;
int ssl_init_done = 0; int ssl_init_done = 0;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
extern EVP_MD *md4_hash;
extern EVP_MD *md5_hash;
#endif
void ssl_init() void ssl_init()
{ {
if(!ssl_init_done){ if(!ssl_init_done){
@ -296,17 +295,5 @@ void ssl_init()
SSL_load_error_strings(); SSL_load_error_strings();
_3proxy_mutex_init(&ssl_file_mutex); _3proxy_mutex_init(&ssl_file_mutex);
bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER_load(NULL, "default");
md4_hash = EVP_MD_fetch(NULL, "MD4", NULL);
if (md4_hash == NULL) {
fprintf(stderr, "Error fetching MD4\n");
}
md5_hash = EVP_MD_fetch(NULL, "MD5", NULL);
if (md5_hash == NULL) {
fprintf(stderr, "Error fetching MD5\n");
}
#endif
} }
} }

View File

@ -30,8 +30,8 @@ unsigned char * strings[] = {
/* 17 */ (unsigned char *)"SMTPP", /* 17 */ (unsigned char *)"SMTPP",
/* 18 */ (unsigned char *)"AUTO", /* 18 */ (unsigned char *)"AUTO",
/* 19 */ (unsigned char *)"TLSPR", /* 19 */ (unsigned char *)"TLSPR",
/* 20 */ (unsigned char *)"ZOMBIE", /* 20 */ (unsigned char *)"IMAPP",
/* 21 */ NULL, /* 21 */ (unsigned char *)"ZOMBIE",
/* 22 */ NULL, /* 22 */ NULL,
/* 23 */ NULL, /* 23 */ NULL,
/* 24 */ NULL, /* 24 */ NULL,

View File

@ -208,6 +208,7 @@ typedef enum {
S_SMTPP, S_SMTPP,
S_AUTO, S_AUTO,
S_TLSPR, S_TLSPR,
S_IMAPP,
S_ZOMBIE S_ZOMBIE
}PROXYSERVICE; }PROXYSERVICE;
@ -304,7 +305,8 @@ typedef enum {
R_EXTIP, R_EXTIP,
R_TLS, R_TLS,
R_HA, R_HA,
R_DNS R_DNS,
R_IMAP
} REDIRTYPE; } REDIRTYPE;
struct redirdesc { struct redirdesc {
@ -535,6 +537,10 @@ struct srvparam {
int gracetraf, gracenum, gracedelay; int gracetraf, gracenum, gracedelay;
int requirecert; int requirecert;
int haproxy; int haproxy;
int nostarttls;
PROXYSERVICE srvstarttls;
uint32_t fakeip;
unsigned char fakeip6[16];
#ifdef WITHSPLICE #ifdef WITHSPLICE
int usesplice; int usesplice;
#endif #endif
@ -594,6 +600,8 @@ struct clientparam {
PROXYSERVICE service; PROXYSERVICE service;
PROXYSERVICE clientstarttls;
SOCKET clisock, SOCKET clisock,
remsock, remsock,
ctrlsock, ctrlsock,

View File

@ -37,6 +37,176 @@ int readtls(struct clientparam *param, int direction, unsigned char *buf, int bu
#define SNILEN (256) #define SNILEN (256)
#define PROTOLEN (32) #define PROTOLEN (32)
int srvstarttls(struct clientparam *param, PROXYSERVICE proto){
unsigned char buf[1024];
int i, found = 0;
switch(proto){
case S_IMAPP:
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 4) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "* OK", 4)) return 1;
found = hascap(buf, "STARTTLS");
if(!found){
if(socksend(param, param->remsock, (unsigned char *)"zz CAPABILITY\r\n", 15, conf.timeouts[STRING_S])!=15) return 2;
for(;;){
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(!strncasecmp((char *)buf, "* CAPABILITY", 12) && hascap(buf, "STARTTLS")) found = 1;
if(!strncasecmp((char *)buf, "zz ", 3)) break;
}
if(!found) return 3;
}
if(socksend(param, param->remsock, (unsigned char *)"zz STARTTLS\r\n", 13, conf.timeouts[STRING_S])!=13) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 5) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "zz OK", 5)) return 3;
break;
case S_POP3P:
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "+OK", 3)) return 1;
if(socksend(param, param->remsock, (unsigned char *)"CAPA\r\n", 6, conf.timeouts[STRING_S])!=6) return 2;
for(;;){
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1) return 2;
buf[i] = 0;
if(buf[0] == '.') break;
if(!strncasecmp((char *)buf, "-ERR", 4)) return 2;
if(hascap(buf, "STLS")) found = 1;
}
if(!found) return 3;
if(socksend(param, param->remsock, (unsigned char *)"STLS\r\n", 6, conf.timeouts[STRING_S])!=6) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "+OK", 3)) return 3;
break;
case S_SMTPP:
i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, NULL, NULL);
if(i < 3) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)) return 1;
i = sprintf((char *)buf, "EHLO [");
i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf+strlen((char *)buf), 64);
i += sprintf((char *)buf+strlen((char *)buf), "]\r\n");
if(socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S])!= i) return 2;
i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, "STARTTLS", &found);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "250", 3)) return 2;
if(!found) return 3;
if(socksend(param, param->remsock, (unsigned char *)"STARTTLS\r\n", 10, conf.timeouts[STRING_S])!= 10) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)) return 3;
break;
default:
return 1;
}
return 0;
}
uint16_t starttlsport(PROXYSERVICE proto){
switch(proto){
case S_IMAPP: return 143;
case S_POP3P: return 110;
case S_SMTPP: return 587;
default: return 443;
}
}
int clistarttls(struct clientparam *param, PROXYSERVICE proto){
unsigned char buf[1024];
unsigned char tag[64];
unsigned char *se, *cmd;
int i;
switch(proto){
case S_IMAPP:
i = sprintf((char *)buf, "* OK [CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED] IMAP4rev1 Proxy Ready\r\n");
if(socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S])!=i) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
if (!(se=(unsigned char *)strchr((char *)buf, ' ')) || (se - buf) >= (int)(sizeof(tag) - 1)) return 1;
memcpy(tag, buf, se - buf);
tag[se - buf] = 0;
cmd = se + 1;
if(!strncasecmp((char *)cmd, "LOGOUT", 6)){
socksend(param, param->clisock, (unsigned char *)"* BYE\r\n", 7, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK LOGOUT completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
return -1;
}
if(!strncasecmp((char *)cmd, "CAPABILITY", 10)){
i = sprintf((char *)buf, "* CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED\r\n");
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK CAPABILITY completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)cmd, "STARTTLS", 8)){
sprintf((char *)buf, "%.60s OK Begin TLS negotiation\r\n", (char *)tag);
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) return 1;
return 0;
}
sprintf((char *)buf, "%.60s BAD need STARTTLS first\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
}
case S_POP3P:
if(socksend(param, param->clisock, (unsigned char *)"+OK Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
if(!strncasecmp((char *)buf, "STLS", 4)){
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) return 1;
return 0;
}
if(!strncasecmp((char *)buf, "CAPA", 4)){
socksend(param, param->clisock, (unsigned char *)"+OK Capability list follows\r\nSTLS\r\n.\r\n", 38, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "QUIT", 4)){
socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5, conf.timeouts[STRING_S]);
return -1;
}
socksend(param, param->clisock, (unsigned char *)"-ERR need STLS first\r\n", 22, conf.timeouts[STRING_S]);
}
case S_SMTPP:
if(socksend(param, param->clisock, (unsigned char *)"220 Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
if(!strncasecmp((char *)buf, "STARTTLS", 8)){
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) return 1;
return 0;
}
if(!strncasecmp((char *)buf, "EHLO ", 5)){
socksend(param, param->clisock, (unsigned char *)"250-Proxy\r\n250 STARTTLS\r\n", 24, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "HELO ", 5)){
socksend(param, param->clisock, (unsigned char *)"250 Proxy\r\n", 11, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "QUIT", 4)){
socksend(param, param->clisock, (unsigned char *)"221 Proxy\r\n", 11, conf.timeouts[STRING_S]);
return -1;
}
socksend(param, param->clisock, (unsigned char *)"530 5.7.0 Must issue a STARTTLS command first\r\n", 45, conf.timeouts[STRING_S]);
}
}
return 1;
}
int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * snipos, int *lv, char * proto){ int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * snipos, int *lv, char * proto){
unsigned offset; unsigned offset;
@ -69,7 +239,7 @@ int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * sn
elen = size16(hello+offset); elen = size16(hello+offset);
offset += 2; offset += 2;
if(elen+offset != len) return -9; if(elen+offset != len) return -9;
while(elen > 1){ while(elen > 3){
unsigned xlen; unsigned xlen;
xlen = size16(hello+offset+2); xlen = size16(hello+offset+2);
if(xlen+4 > elen) return -10; if(xlen+4 > elen) return -10;
@ -176,6 +346,13 @@ void * tlsprchild(struct clientparam* param) {
int lv=-1; int lv=-1;
char proto[PROTOLEN]="-"; char proto[PROTOLEN]="-";
int snipos = 0; int snipos = 0;
PROXYSERVICE stlsproto = param->clientstarttls? param->clientstarttls : param->srv->srvstarttls;
if(!param->clientstarttls && stlsproto){
res = clistarttls(param, stlsproto);
if(res > 0) RETURN(364);
if(res < 0) RETURN(0);
}
res = tlstobufcli(param); res = tlstobufcli(param);
if(res <= 0 || param->clibuf[0] != 22){ if(res <= 0 || param->clibuf[0] != 22){
@ -189,7 +366,7 @@ void * tlsprchild(struct clientparam* param) {
free(param->hostname); free(param->hostname);
param->hostname = NULL; param->hostname = NULL;
} }
else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):443)) RETURN (100); else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):starttlsport(stlsproto))) RETURN (100);
if (!param->hostname)param->hostname = (unsigned char *)strdup(sni); if (!param->hostname)param->hostname = (unsigned char *)strdup(sni);
if(param->srv->s_option && snipos && res > 1){ if(param->srv->s_option && snipos && res > 1){
int len; int len;
@ -220,6 +397,14 @@ void * tlsprchild(struct clientparam* param) {
return (*param->redirectfunc)(param); return (*param->redirectfunc)(param);
} }
if(stlsproto){
res = srvstarttls(param, stlsproto);
if(res){
socksend(param, param->clisock, (unsigned char *)"\x15\x03\x01\x00\x02\x02\x28", 7, conf.timeouts[STRING_S]);
RETURN(360+res);
}
}
if(param->srv->requirecert > 1){ if(param->srv->requirecert > 1){
res = tlstobufsrv(param); res = tlstobufsrv(param);
if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res); if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res);