diff -Nru civetweb-1.13+dfsg/appveyor.yml civetweb-1.15+dfsg/appveyor.yml --- civetweb-1.13+dfsg/appveyor.yml 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/appveyor.yml 2021-09-01 08:46:33.000000000 +0000 @@ -267,33 +267,20 @@ platform: x64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 # Visual Studio 2019 -# - id: Full-VS2019-x86 -# compiler: msvc-21-seh -# build_shared: NO -# no_files: NO -# enable_ipv6: YES -# enable_ssl: YES -# enable_websockets: YES -# no_cgi: NO -# no_caching: NO -# enable_stats: YES -# configuration: Release -# platform: x86 -# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 -# - id: Full-VS2019-x64 -# compiler: msvc-21-seh -# build_shared: NO -# no_files: NO -# enable_ipv6: YES -# enable_ssl: YES -# enable_websockets: YES -# no_cgi: NO -# no_caching: NO -# enable_stats: YES -# configuration: Release -# platform: x64 -# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - # Experimental Ubuntu + - id: Full-VS2019-x64 + compiler: msvc-21-seh + build_shared: NO + no_files: NO + enable_ipv6: YES + enable_ssl: YES + enable_websockets: YES + no_cgi: NO + no_caching: NO + enable_stats: YES + configuration: Release + platform: x64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + # Ubuntu - id: Ubuntu1604-GCC-x64 compiler: gcc-5.1.0-posix build_shared: NO @@ -320,6 +307,19 @@ configuration: Release platform: x64 image: Ubuntu1804 + - id: Ubuntu2004-GCC-x64 + compiler: gcc-5.1.0-posix + build_shared: NO + no_files: NO + enable_ipv6: YES + enable_ssl: YES + enable_websockets: YES + no_cgi: NO + no_caching: NO + enable_stats: YES + configuration: Release + platform: x64 + image: Ubuntu2004 # Conan builds - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 CONAN_VISUAL_VERSIONS: 12 @@ -391,9 +391,17 @@ - if "%compiler_version%"=="20" (set "vs_version=15" & set "vs_year=2017") - if "%compiler_version%"=="21" (set "vs_version=16" & set "vs_year=2019") - if "%compiler_name%"=="msvc" (set "generator=Visual Studio %vs_version% %vs_year%") + - set "arch_arg= " - if "%compiler_name%"=="msvc" ( - if "%platform%"=="x64" ( - set "generator=%generator% Win64" + if "%compiler_version%"=="21" ( + set "arch_arg= -A x64 " + ) + ) + - if "%compiler_name%"=="msvc" ( + if not "%compiler_version%"=="21" ( + if "%platform%"=="x64" ( + set "generator=%generator% Win64" + ) ) ) - if %compiler_version% gtr 9 (set platform=%platform:x86=Win32%) @@ -419,9 +427,11 @@ - mkdir "%build_path%" - cd "%build_path%" - cmake --version + - echo %generator% + - echo %arch_arg% - appveyor AddMessage -Category Information "Generating '%generator%'" - - cmake - -G "%generator%" + - echo cmake + -G "%generator%" %arch_arg% -DCMAKE_BUILD_TYPE=%build_type% -DBUILD_SHARED_LIBS=%build_shared% -DCIVETWEB_SERVE_NO_FILES=%no_files% @@ -441,6 +451,27 @@ -DCIVETWEB_SSL_OPENSSL_API_1_0=NO -DCIVETWEB_SSL_OPENSSL_API_1_1=YES "%source_path%" + - cmake + -G "%generator%" %arch_arg% + -DCMAKE_BUILD_TYPE=%build_type% + -DBUILD_SHARED_LIBS=%build_shared% + -DCIVETWEB_SERVE_NO_FILES=%no_files% + "-DCIVETWEB_THIRD_PARTY_DIR=%third_party_dir:\=\\%" + -DCIVETWEB_ENABLE_THIRD_PARTY_OUTPUT=YES + -DCIVETWEB_ENABLE_SSL=%enable_ssl% + -DCIVETWEB_DISABLE_CGI=%no_cgi% + -DCIVETWEB_ENABLE_SSL_DYNAMIC_LOADING=%enable_ssl_dynamic_loading% + -DCIVETWEB_ENABLE_WEBSOCKETS=%enable_websockets% + -DCIVETWEB_ENABLE_CXX=%enable_cxx% + -DCIVETWEB_ENABLE_LUA=%enable_lua% + -DCIVETWEB_ENABLE_LUA_SHARED=%enable_lua_shared% + -DCIVETWEB_ENABLE_SERVER_STATS=%enable_stats% + -DCIVETWEB_DISABLE_CACHING=%no_caching% + -DCIVETWEB_C_STANDARD=%c_standard% + -DCIVETWEB_CXX_STANDARD=%cxx_standard% + -DCIVETWEB_SSL_OPENSSL_API_1_0=NO + -DCIVETWEB_SSL_OPENSSL_API_1_1=YES + "%source_path%" - powershell Push-AppveyorArtifact CMakeCache.txt - cd "%source_path%" @@ -511,35 +542,6 @@ only: - configuration: Release fast_finish: false - allow_failures: - # Experimental Ubuntu - - id: Ubuntu1604-GCC-x64 - compiler: gcc-5.1.0-posix - build_shared: NO - no_files: NO - enable_ipv6: YES - enable_ssl: YES - enable_websockets: YES - no_cgi: NO - no_caching: NO - enable_stats: YES - configuration: Release - platform: x64 - image: Ubuntu1604 - - id: Ubuntu1804-GCC-x64 - compiler: gcc-5.1.0-posix - build_shared: NO - no_files: NO - enable_ipv6: YES - enable_ssl: YES - enable_websockets: YES - no_cgi: NO - no_caching: NO - enable_stats: YES - configuration: Release - platform: x64 - image: Ubuntu1804 - - matrix: only: diff -Nru civetweb-1.13+dfsg/cmake/AddCCompilerFlag.cmake civetweb-1.15+dfsg/cmake/AddCCompilerFlag.cmake --- civetweb-1.13+dfsg/cmake/AddCCompilerFlag.cmake 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/cmake/AddCCompilerFlag.cmake 2021-09-01 08:46:33.000000000 +0000 @@ -24,9 +24,8 @@ string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - check_c_compiler_flag("" ${SANITIZED_FLAG}) - if(${SANITIZED_FLAG}) + check_c_compiler_flag(${SANITIZED_FLAG} NO_DIAGNOSTICS_PRODUCED) + if(${NO_DIAGNOSTICS_PRODUCED}) set(VARIANT ${ARGV1}) if(ARGV1) string(REGEX REPLACE "[^A-Za-z_0-9]" "_" VARIANT "${VARIANT}") diff -Nru civetweb-1.13+dfsg/cmake/AddCXXCompilerFlag.cmake civetweb-1.15+dfsg/cmake/AddCXXCompilerFlag.cmake --- civetweb-1.13+dfsg/cmake/AddCXXCompilerFlag.cmake 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/cmake/AddCXXCompilerFlag.cmake 2021-09-01 08:46:33.000000000 +0000 @@ -24,9 +24,8 @@ string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) - set(CMAKE_REQUIRED_FLAGS "${FLAG}") - check_cxx_compiler_flag("" ${SANITIZED_FLAG}) - if(${SANITIZED_FLAG}) + check_cxx_compiler_flag(${SANITIZED_FLAG} NO_DIAGNOSTICS_PRODUCED) + if(${NO_DIAGNOSTICS_PRODUCED}) set(VARIANT ${ARGV1}) if(ARGV1) string(REGEX REPLACE "[^A-Za-z_0-9]" "_" VARIANT "${VARIANT}") diff -Nru civetweb-1.13+dfsg/cmake/civetweb-config.cmake.in civetweb-1.15+dfsg/cmake/civetweb-config.cmake.in --- civetweb-1.13+dfsg/cmake/civetweb-config.cmake.in 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/cmake/civetweb-config.cmake.in 2021-09-01 08:46:33.000000000 +0000 @@ -3,4 +3,24 @@ set_and_check(civetweb_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +find_dependency(Threads) + +set(CIVETWEB_SAVED_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +if(@LOOKUP_LIBDL@) + find_dependency(LibDl) +endif() + +if(@LOOKUP_LIBRT@) + find_dependency(LibRt) +endif() + +if(@LOOKUP_WINSOCK@) + find_dependency(WinSock) +endif() + +set(CMAKE_MODULE_PATH ${CIVETWEB_SAVED_MODULE_PATH}) +unset(CIVETWEB_SAVED_MODULE_PATH) + include("${CMAKE_CURRENT_LIST_DIR}/civetweb-targets.cmake") diff -Nru civetweb-1.13+dfsg/cmake/FindWinSock.cmake civetweb-1.15+dfsg/cmake/FindWinSock.cmake --- civetweb-1.13+dfsg/cmake/FindWinSock.cmake 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/cmake/FindWinSock.cmake 2021-09-01 08:46:33.000000000 +0000 @@ -74,7 +74,7 @@ list(APPEND WINSOCK_LIBRARY_PATHS "${CMAKE_MATCH_1}") endif() endif() -if (${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "AMD64" AND "${CMAKE_SIZEOF_VOID_P}" EQUAL 4) +if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "AMD64" AND "${CMAKE_SIZEOF_VOID_P}" EQUAL 4) list(APPEND WINSOCK_LIBRARY_PATHS "C:/Windows/SysWOW64") endif() list(APPEND WINSOCK_LIBRARY_PATHS "C:/Windows/System32") diff -Nru civetweb-1.13+dfsg/CMakeLists.txt civetweb-1.15+dfsg/CMakeLists.txt --- civetweb-1.13+dfsg/CMakeLists.txt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/CMakeLists.txt 2021-09-01 08:46:33.000000000 +0000 @@ -1,12 +1,7 @@ -# Determines what CMake APIs we can rely on -cmake_minimum_required (VERSION 2.8.11) -if (${CMAKE_VERSION} VERSION_GREATER 3.2.2) - cmake_policy(VERSION 3.2.2) -endif() -if (${CMAKE_VERSION} VERSION_GREATER 3.1 OR - ${CMAKE_VERSION} VERSION_EQUAL 3.1) - cmake_policy(SET CMP0054 NEW) -endif() +# Use at least CMake 3.3 +cmake_minimum_required (VERSION 3.3.0) +cmake_policy(VERSION 3.2.2) +cmake_policy(SET CMP0054 NEW) # Set up the project project (civetweb) @@ -41,7 +36,7 @@ include(DetermineTargetArchitecture) include(CMakeDependentOption) -set(CIVETWEB_VERSION "1.13.0" CACHE STRING "The version of the civetweb library") +set(CIVETWEB_VERSION "1.15.0" CACHE STRING "The version of the civetweb library") string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CIVETWEB_VERSION_MATCH "${CIVETWEB_VERSION}") if ("${CIVETWEB_VERSION_MATCH}" STREQUAL "") message(FATAL_ERROR "Must specify a semantic version: major.minor.patch") @@ -112,6 +107,10 @@ option(CIVETWEB_ENABLE_LUA "Enable Lua CGIs" OFF) message(STATUS "Lua CGI support - ${CIVETWEB_ENABLE_LUA}") +# zlib compression support +option(CIVETWEB_ENABLE_ZLIB "Enables zlib compression support" OFF) +message(STATUS "zlib support - ${CIVETWEB_ENABLE_ZLIB}") + # Enable installing CivetWeb executables option(CIVETWEB_INSTALL_EXECUTABLE "Enable installing CivetWeb executable" ON) mark_as_advanced(FORCE CIVETWEB_INSTALL_EXECUTABLE) # Advanced users can disable @@ -476,8 +475,11 @@ # Set up the definitions +option(CIVETWEB_ENABLE_DEBUG_TOOLS "For Debug builds enable verbose logging and assertions" ON) if (${CMAKE_BUILD_TYPE} MATCHES "[Dd]ebug") - add_definitions(-DDEBUG) + if(CIVETWEB_ENABLE_DEBUG_TOOLS) + add_definitions(-DDEBUG) + endif() add_definitions(-O0) add_definitions(-g) endif() @@ -505,6 +507,9 @@ if (CIVETWEB_ENABLE_LUA) add_definitions(-DUSE_LUA) endif() +if (CIVETWEB_ENABLE_ZLIB) + add_definitions(-DUSE_ZLIB) +endif() if (CIVETWEB_ENABLE_DUKTAPE) add_definitions(-DUSE_DUKTAPE) endif() @@ -603,6 +608,9 @@ FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibDl.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindLibRt.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindWinSock.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" COMPONENT civetweb-cmake-config ) diff -Nru civetweb-1.13+dfsg/codecov.yml civetweb-1.15+dfsg/codecov.yml --- civetweb-1.13+dfsg/codecov.yml 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/codecov.yml 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,21 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: nearest + range: "70...100" + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "reach,diff,flags,files,footer" + behavior: default + require_changes: no + \ No newline at end of file diff -Nru civetweb-1.13+dfsg/CREDITS.md civetweb-1.15+dfsg/CREDITS.md --- civetweb-1.13+dfsg/CREDITS.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/CREDITS.md 2021-09-01 08:46:33.000000000 +0000 @@ -3,9 +3,11 @@ * Abhishek Lekshmanan * Abramo Bagnara * Adam Bailey +* Adam Hunyadi * Alan Somers * Alberto Bignotti * Alex Kozlov +* Alexander Kozhinov * AndreyArsov * Anton Te * beaver @@ -38,17 +40,21 @@ * daveelton * David Arnold * David Loffredo +* DavidKorczynski * Dialga +* dennis +* DL6ER * Domenico Di Iorio +* dprandle * Drew Wells * duong2179 * ehlertjd * Elan P. Kugelmass -* eugene * Eric Tsau * Erick Vieyra * Erik Beran * Erik Partridge +* eugene * extergnoto * F-Secure Corporation * Fabrice Fontaine @@ -56,6 +62,7 @@ * Fernando G. Aranda * Frank Hilliger * Gábor Csárdi +* Girish Joshi * goodmenzy * Grahack * Gregor Jasny @@ -63,6 +70,7 @@ * grunk * guangqing.chen * Guilherme Amadio +* Gustavo Romero * hansipie * HariKamath Kamath * Henry Chang @@ -71,11 +79,14 @@ * Iain Morton * ImgBotApp * Ivan Dlugos +* IZI * Jack * Jacob Repp * Jacob Skillin * Jan Kowalewski +* Jan Pohanka * Jan Willem Janssen +* Jens Wallgren * Jeremy Lin * Jesse Williamson * Jim Evans @@ -90,6 +101,7 @@ * Jordan Shelley * Joshua Boyd * Joshua D. Boyd +* Justin Standring * k-mds * kakwa * kalphamon @@ -101,12 +113,15 @@ * Kevin Wojniak * Khem Raj * Kimmo Mustonen +* Kjeld Flarup +* krpano * Krzysztof Kozlowski * Lammert Bies * Lars Immisch * Lawrence * Li Peng * Lianghui +* Lorenzo Canepa * Luka Rahne * Lukas Martanovic * Maarten Fremouw @@ -140,10 +155,12 @@ * Peter Foerster * Philipp Friedenberger * Philipp Hasper +* Pieter Cardoen * Piotr Zierhoffer * pkvamme * Ponnuvel Palaniyappan * qinch +* qinchao * Radoslaw Zarzynski * Red54 * Retallack Mark mark.retallack @@ -163,6 +180,7 @@ * shreyajaggi8 * Simon Hailes * slidertom +* SpaceIm * SpaceLord * Stefan Codrescu * sunfch @@ -175,6 +193,8 @@ * Thomas Davis * Thomas Klausner * Thorsten Horstmann +* Tim Gates +* Tim Hudson * tnoho * Tom Deblauwe * Tomas Andrle @@ -187,6 +207,7 @@ * wangli28 * webxer * William Greathouse +* Wolfram Rösler * xeoshow * xtne6f * Yehuda Sadeh diff -Nru civetweb-1.13+dfsg/debian/changelog civetweb-1.15+dfsg/debian/changelog --- civetweb-1.13+dfsg/debian/changelog 2021-01-21 14:30:38.000000000 +0000 +++ civetweb-1.15+dfsg/debian/changelog 2021-10-13 07:36:08.000000000 +0000 @@ -1,3 +1,12 @@ +civetweb (1.15+dfsg-1) unstable; urgency=medium + + * Fix watchfile to detect new versions on github + * New upstream version + * Standards-Version: 4.6.0 (routine-update) + * Remove Debian revision from symbols + + -- Andreas Tille Wed, 13 Oct 2021 09:36:08 +0200 + civetweb (1.13+dfsg-5) unstable; urgency=medium * Team Upload. diff -Nru civetweb-1.13+dfsg/debian/control civetweb-1.15+dfsg/debian/control --- civetweb-1.13+dfsg/debian/control 2021-01-21 14:30:38.000000000 +0000 +++ civetweb-1.15+dfsg/debian/control 2021-10-13 07:36:08.000000000 +0000 @@ -7,7 +7,7 @@ Build-Depends: debhelper-compat (= 13), cmake, libjs-jquery (>= 3.5.1+dfsg+~3.5.5-7) -Standards-Version: 4.5.1 +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/med-team/civetweb Vcs-Git: https://salsa.debian.org/med-team/civetweb.git Homepage: https://github.com/civetweb/civetweb/ @@ -35,6 +35,7 @@ Section: libs Depends: ${shlibs:Depends}, ${misc:Depends} +Multi-Arch: same Description: embeddable web server with optional CGI, SSL and Lua support (lib) CivetWeb is an easy to use, powerful, C (C/C++) embeddable web server with optional CGI, SSL and Lua support. CivetWeb has a MIT license so @@ -55,6 +56,7 @@ Depends: libcivetweb1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} +Multi-Arch: same Description: embeddable web server with optional CGI, SSL and Lua support (devel) CivetWeb is an easy to use, powerful, C (C/C++) embeddable web server with optional CGI, SSL and Lua support. CivetWeb has a MIT license so diff -Nru civetweb-1.13+dfsg/debian/libcivetweb1.symbols civetweb-1.15+dfsg/debian/libcivetweb1.symbols --- civetweb-1.13+dfsg/debian/libcivetweb1.symbols 2021-01-21 14:14:50.000000000 +0000 +++ civetweb-1.15+dfsg/debian/libcivetweb1.symbols 2021-10-13 07:36:08.000000000 +0000 @@ -1,79 +1,79 @@ libcivetweb-cpp.so.1 libcivetweb1 #MINVER# - _ZN11CivetServer10addHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP12CivetHandler@Base 1.13+dfsg-4~ - _ZN11CivetServer11authHandlerEP13mg_connectionPv@Base 1.13+dfsg-4~ - _ZN11CivetServer11getPostDataB5cxx11EP13mg_connection@Base 1.13+dfsg-4~ - _ZN11CivetServer12closeHandlerEPK13mg_connection@Base 1.13+dfsg-4~ - _ZN11CivetServer13removeHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13+dfsg-4~ - _ZN11CivetServer14addAuthHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP16CivetAuthHandler@Base 1.13+dfsg-4~ - _ZN11CivetServer14requestHandlerEP13mg_connectionPv@Base 1.13+dfsg-4~ - _ZN11CivetServer17getListeningPortsEv@Base 1.13+dfsg-4~ - _ZN11CivetServer17removeAuthHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13+dfsg-4~ - _ZN11CivetServer19addWebSocketHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP21CivetWebSocketHandler@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN11CivetServer20webSocketDataHandlerEP13mg_connectioniPcmPv@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN11CivetServer20webSocketDataHandlerEP13mg_connectioniPcjPv@Base 1.13+dfsg-4~ - _ZN11CivetServer21getListeningPortsFullEv@Base 1.13+dfsg-4~ - _ZN11CivetServer21webSocketCloseHandlerEPK13mg_connectionPv@Base 1.13+dfsg-4~ - _ZN11CivetServer21webSocketReadyHandlerEP13mg_connectionPv@Base 1.13+dfsg-4~ - _ZN11CivetServer22removeWebSocketHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13+dfsg-4~ - _ZN11CivetServer26webSocketConnectionHandlerEPK13mg_connectionPv@Base 1.13+dfsg-4~ - _ZN11CivetServer5closeEv@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN11CivetServer8getParamEP13mg_connectionPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEm@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN11CivetServer8getParamEP13mg_connectionPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEj@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN11CivetServer8getParamEPKcmS1_RNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEm@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN11CivetServer8getParamEPKcjS1_RNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEj@Base 1.13+dfsg-4~ - _ZN11CivetServer9getCookieEP13mg_connectionRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS7_@Base 1.13+dfsg-4~ - _ZN11CivetServer9getHeaderEP13mg_connectionRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13+dfsg-4~ - _ZN11CivetServer9urlDecodeEPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN11CivetServer9urlDecodeEPKcmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN11CivetServer9urlDecodeEPKcjRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - _ZN11CivetServer9urlEncodeEPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN11CivetServer9urlEncodeEPKcmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN11CivetServer9urlEncodeEPKcjRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13+dfsg-4~ - _ZN11CivetServerC1EPPKcPK14CivetCallbacksPKv@Base 1.13+dfsg-4~ - _ZN11CivetServerC1ERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EEPK14CivetCallbacksPKv@Base 1.13+dfsg-4~ - _ZN11CivetServerC2EPPKcPK14CivetCallbacksPKv@Base 1.13+dfsg-4~ - _ZN11CivetServerC2ERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EEPK14CivetCallbacksPKv@Base 1.13+dfsg-4~ - _ZN11CivetServerD0Ev@Base 1.13+dfsg-4~ - _ZN11CivetServerD1Ev@Base 1.13+dfsg-4~ - _ZN11CivetServerD2Ev@Base 1.13+dfsg-4~ - _ZN12CivetHandler10handleHeadEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler10handlePostEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler11handlePatchEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler12handleDeleteEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler13handleOptionsEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler9handleGetEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandler9handlePutEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN12CivetHandlerD0Ev@Base 1.13+dfsg-4~ - _ZN12CivetHandlerD1Ev@Base 1.13+dfsg-4~ - _ZN12CivetHandlerD2Ev@Base 1.13+dfsg-4~ - _ZN14CivetCallbacksC1Ev@Base 1.13+dfsg-4~ - _ZN14CivetCallbacksC2Ev@Base 1.13+dfsg-4~ - _ZN14CivetExceptionD0Ev@Base 1.13+dfsg-4~ - _ZN14CivetExceptionD1Ev@Base 1.13+dfsg-4~ - _ZN14CivetExceptionD2Ev@Base 1.13+dfsg-4~ - (arch-bits=64)_ZN21CivetWebSocketHandler10handleDataEP11CivetServerP13mg_connectioniPcm@Base 1.13+dfsg-4~ - (arch-bits=32)_ZN21CivetWebSocketHandler10handleDataEP11CivetServerP13mg_connectioniPcj@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandler11handleCloseEP11CivetServerPK13mg_connection@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandler16handleConnectionEP11CivetServerPK13mg_connection@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandler16handleReadyStateEP11CivetServerP13mg_connection@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandlerD0Ev@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandlerD1Ev@Base 1.13+dfsg-4~ - _ZN21CivetWebSocketHandlerD2Ev@Base 1.13+dfsg-4~ - (optional=templinst)_ZNSt12_Vector_baseIcSaIcEED1Ev@Base 1.13+dfsg-4~ - (optional=templinst)_ZNSt12_Vector_baseIcSaIcEED2Ev@Base 1.13+dfsg-4~ - (optional=templinst)_ZNSt6vectorIcSaIcEE17_M_realloc_insertIJcEEEvN9__gnu_cxx17__normal_iteratorIPcS1_EEDpOT_@Base 1.13+dfsg-4~ - _ZTI11CivetServer@Base 1.13+dfsg-4~ - _ZTI12CivetHandler@Base 1.13+dfsg-4~ - _ZTI14CivetException@Base 1.13+dfsg-4~ - _ZTI21CivetWebSocketHandler@Base 1.13+dfsg-4~ - _ZTS11CivetServer@Base 1.13+dfsg-4~ - _ZTS12CivetHandler@Base 1.13+dfsg-4~ - _ZTS14CivetException@Base 1.13+dfsg-4~ - _ZTS21CivetWebSocketHandler@Base 1.13+dfsg-4~ - _ZTV11CivetServer@Base 1.13+dfsg-4~ - _ZTV12CivetHandler@Base 1.13+dfsg-4~ - _ZTV14CivetException@Base 1.13+dfsg-4~ - _ZTV21CivetWebSocketHandler@Base 1.13+dfsg-4~ + _ZN11CivetServer10addHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP12CivetHandler@Base 1.13 + _ZN11CivetServer11authHandlerEP13mg_connectionPv@Base 1.13 + _ZN11CivetServer11getPostDataB5cxx11EP13mg_connection@Base 1.13 + _ZN11CivetServer12closeHandlerEPK13mg_connection@Base 1.13 + _ZN11CivetServer13removeHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13 + _ZN11CivetServer14addAuthHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP16CivetAuthHandler@Base 1.13 + _ZN11CivetServer14requestHandlerEP13mg_connectionPv@Base 1.13 + _ZN11CivetServer17getListeningPortsEv@Base 1.13 + _ZN11CivetServer17removeAuthHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13 + _ZN11CivetServer19addWebSocketHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEP21CivetWebSocketHandler@Base 1.13 + (arch-bits=64)_ZN11CivetServer20webSocketDataHandlerEP13mg_connectioniPcmPv@Base 1.13 + (arch-bits=32)_ZN11CivetServer20webSocketDataHandlerEP13mg_connectioniPcjPv@Base 1.13 + _ZN11CivetServer21getListeningPortsFullEv@Base 1.13 + _ZN11CivetServer21webSocketCloseHandlerEPK13mg_connectionPv@Base 1.13 + _ZN11CivetServer21webSocketReadyHandlerEP13mg_connectionPv@Base 1.13 + _ZN11CivetServer22removeWebSocketHandlerERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13 + _ZN11CivetServer26webSocketConnectionHandlerEPK13mg_connectionPv@Base 1.13 + _ZN11CivetServer5closeEv@Base 1.13 + (arch-bits=64)_ZN11CivetServer8getParamEP13mg_connectionPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEm@Base 1.13 + (arch-bits=32)_ZN11CivetServer8getParamEP13mg_connectionPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEj@Base 1.13 + (arch-bits=64)_ZN11CivetServer8getParamEPKcmS1_RNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEm@Base 1.13 + (arch-bits=32)_ZN11CivetServer8getParamEPKcjS1_RNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEj@Base 1.13 + _ZN11CivetServer9getCookieEP13mg_connectionRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS7_@Base 1.13 + _ZN11CivetServer9getHeaderEP13mg_connectionRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 1.13 + _ZN11CivetServer9urlDecodeEPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + (arch-bits=64)_ZN11CivetServer9urlDecodeEPKcmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + (arch-bits=32)_ZN11CivetServer9urlDecodeEPKcjRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + _ZN11CivetServer9urlEncodeEPKcRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + (arch-bits=64)_ZN11CivetServer9urlEncodeEPKcmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + (arch-bits=32)_ZN11CivetServer9urlEncodeEPKcjRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb@Base 1.13 + _ZN11CivetServerC1EPPKcPK14CivetCallbacksPKv@Base 1.13 + _ZN11CivetServerC1ERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EEPK14CivetCallbacksPKv@Base 1.13 + _ZN11CivetServerC2EPPKcPK14CivetCallbacksPKv@Base 1.13 + _ZN11CivetServerC2ERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS6_EEPK14CivetCallbacksPKv@Base 1.13 + _ZN11CivetServerD0Ev@Base 1.13 + _ZN11CivetServerD1Ev@Base 1.13 + _ZN11CivetServerD2Ev@Base 1.13 + _ZN12CivetHandler10handleHeadEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler10handlePostEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler11handlePatchEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler12handleDeleteEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler13handleOptionsEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler9handleGetEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandler9handlePutEP11CivetServerP13mg_connection@Base 1.13 + _ZN12CivetHandlerD0Ev@Base 1.13 + _ZN12CivetHandlerD1Ev@Base 1.13 + _ZN12CivetHandlerD2Ev@Base 1.13 + _ZN14CivetCallbacksC1Ev@Base 1.13 + _ZN14CivetCallbacksC2Ev@Base 1.13 + _ZN14CivetExceptionD0Ev@Base 1.13 + _ZN14CivetExceptionD1Ev@Base 1.13 + _ZN14CivetExceptionD2Ev@Base 1.13 + (arch-bits=64)_ZN21CivetWebSocketHandler10handleDataEP11CivetServerP13mg_connectioniPcm@Base 1.13 + (arch-bits=32)_ZN21CivetWebSocketHandler10handleDataEP11CivetServerP13mg_connectioniPcj@Base 1.13 + _ZN21CivetWebSocketHandler11handleCloseEP11CivetServerPK13mg_connection@Base 1.13 + _ZN21CivetWebSocketHandler16handleConnectionEP11CivetServerPK13mg_connection@Base 1.13 + _ZN21CivetWebSocketHandler16handleReadyStateEP11CivetServerP13mg_connection@Base 1.13 + _ZN21CivetWebSocketHandlerD0Ev@Base 1.13 + _ZN21CivetWebSocketHandlerD1Ev@Base 1.13 + _ZN21CivetWebSocketHandlerD2Ev@Base 1.13 + (optional=templinst)_ZNSt12_Vector_baseIcSaIcEED1Ev@Base 1.13 + (optional=templinst)_ZNSt12_Vector_baseIcSaIcEED2Ev@Base 1.13 + (optional=templinst)_ZNSt6vectorIcSaIcEE17_M_realloc_insertIJcEEEvN9__gnu_cxx17__normal_iteratorIPcS1_EEDpOT_@Base 1.13 + _ZTI11CivetServer@Base 1.13 + _ZTI12CivetHandler@Base 1.13 + _ZTI14CivetException@Base 1.13 + _ZTI21CivetWebSocketHandler@Base 1.13 + _ZTS11CivetServer@Base 1.13 + _ZTS12CivetHandler@Base 1.13 + _ZTS14CivetException@Base 1.13 + _ZTS21CivetWebSocketHandler@Base 1.13 + _ZTV11CivetServer@Base 1.13 + _ZTV12CivetHandler@Base 1.13 + _ZTV14CivetException@Base 1.13 + _ZTV21CivetWebSocketHandler@Base 1.13 libcivetweb.so.1 libcivetweb1 #MINVER# mg_check_digest_access_authentication@Base 1 mg_check_feature@Base 1 diff -Nru civetweb-1.13+dfsg/debian/patches/soversion civetweb-1.15+dfsg/debian/patches/soversion --- civetweb-1.13+dfsg/debian/patches/soversion 2021-01-21 14:14:50.000000000 +0000 +++ civetweb-1.15+dfsg/debian/patches/soversion 2021-10-13 07:36:08.000000000 +0000 @@ -2,22 +2,18 @@ Author: Sebastien Jodogne --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ -Index: civetweb-1.13/CMakeLists.txt -=================================================================== ---- civetweb-1.13.orig/CMakeLists.txt -+++ civetweb-1.13/CMakeLists.txt -@@ -42,6 +42,7 @@ include(DetermineTargetArchitecture) +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -37,6 +37,7 @@ include(DetermineTargetArchitecture) include(CMakeDependentOption) - set(CIVETWEB_VERSION "1.13.0" CACHE STRING "The version of the civetweb library") + set(CIVETWEB_VERSION "1.15.0" CACHE STRING "The version of the civetweb library") +set(CIVETWEB_SOVERSION "1" CACHE STRING "The SOVERSION of the civetweb library") string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CIVETWEB_VERSION_MATCH "${CIVETWEB_VERSION}") if ("${CIVETWEB_VERSION_MATCH}" STREQUAL "") message(FATAL_ERROR "Must specify a semantic version: major.minor.patch") -Index: civetweb-1.13/src/CMakeLists.txt -=================================================================== ---- civetweb-1.13.orig/src/CMakeLists.txt -+++ civetweb-1.13/src/CMakeLists.txt +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ set_target_properties(civetweb-c-library OUTPUT_NAME "civetweb" EXPORT_NAME "civetweb" @@ -27,7 +23,7 @@ ) if (BUILD_SHARED_LIBS) target_compile_definitions(civetweb-c-library PRIVATE CIVETWEB_DLL_EXPORTS INTERFACE CIVETWEB_DLL_IMPORTS) -@@ -298,7 +298,7 @@ if (CIVETWEB_ENABLE_CXX) +@@ -302,7 +302,7 @@ if (CIVETWEB_ENABLE_CXX) EXPORT_NAME "civetweb-cpp" OUTPUT_NAME "civetweb-cpp" VERSION ${CIVETWEB_VERSION} diff -Nru civetweb-1.13+dfsg/debian/patches/webdav-uploads civetweb-1.15+dfsg/debian/patches/webdav-uploads --- civetweb-1.13+dfsg/debian/patches/webdav-uploads 2021-01-21 14:14:50.000000000 +0000 +++ civetweb-1.15+dfsg/debian/patches/webdav-uploads 2021-10-13 07:36:08.000000000 +0000 @@ -2,13 +2,11 @@ Origin: https://hg.orthanc-server.com/orthanc/file/default/OrthancFramework/Resources/Patches/civetweb-1.13.patch --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ -Index: civetweb-1.13/include/civetweb.h -=================================================================== ---- civetweb-1.13.orig/include/civetweb.h -+++ civetweb-1.13/include/civetweb.h -@@ -1695,6 +1695,9 @@ CIVETWEB_API int mg_start_domain2(struct +--- a/include/civetweb.h ++++ b/include/civetweb.h +@@ -1705,6 +1705,9 @@ CIVETWEB_API int mg_start_domain2(struct struct mg_error_data *error); - #endif + +// Added by SJ +CIVETWEB_API void mg_disable_keep_alive(struct mg_connection *conn); @@ -16,11 +14,9 @@ #ifdef __cplusplus } #endif /* __cplusplus */ -Index: civetweb-1.13/src/civetweb.c -=================================================================== ---- civetweb-1.13.orig/src/civetweb.c -+++ civetweb-1.13/src/civetweb.c -@@ -10876,6 +10876,11 @@ static const struct mg_http_method_info +--- a/src/civetweb.c ++++ b/src/civetweb.c +@@ -10540,6 +10540,11 @@ static const struct mg_http_method_info /* + MicroSoft extensions * https://msdn.microsoft.com/en-us/library/aa142917.aspx */ @@ -32,7 +28,7 @@ /* REPORT method (RFC 3253) */ {"REPORT", 1, 1, 1, 1, 1}, /* REPORT method only allowed for CGI/Lua/LSP and callbacks. */ -@@ -21287,4 +21292,12 @@ mg_exit_library(void) +@@ -21472,4 +21477,12 @@ mg_exit_library(void) } diff -Nru civetweb-1.13+dfsg/debian/watch civetweb-1.15+dfsg/debian/watch --- civetweb-1.13+dfsg/debian/watch 2021-01-21 14:14:50.000000000 +0000 +++ civetweb-1.15+dfsg/debian/watch 2021-10-13 07:36:08.000000000 +0000 @@ -1,4 +1,4 @@ version=4 opts="repacksuffix=+dfsg,dversionmangle=auto,repack,compression=xz,filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%@PACKAGE@-$1.tar.gz%" \ -https://github.com/civetweb/civetweb/releases .*/archive/v?@ANY_VERSION@\.tar\.gz +https://github.com/civetweb/civetweb/releases .*/v?@ANY_VERSION@\.tar\.gz diff -Nru civetweb-1.13+dfsg/docs/api/mg_callbacks.md civetweb-1.15+dfsg/docs/api/mg_callbacks.md --- civetweb-1.13+dfsg/docs/api/mg_callbacks.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_callbacks.md 2021-09-01 08:46:33.000000000 +0000 @@ -9,7 +9,9 @@ |**`begin_request`**|**`int (*begin_request)( struct mg_connection *conn );`**| | |The `begin_request()` callback function is called when CivetWeb has received a new HTTP request. If the callback function does not process the request, it should return 0. In that case CivetWeb will handle the request with the default callback routine. If the callback function returns a value between 1 and 999, CivetWeb does nothing and the callback function should do all the processing, including sending the proper HTTP headers etc. Starting at CivetWeb version 1.7, the function `begin_request()` is called before any authorization is done. If an authorization check is required, `request_handler()` should be used instead. The return value of the callback function is not only used to signal CivetWeb to not further process the request. The returned value is also stored as HTTP status code in the access log. | |**`connection_close`**|**`void (*connection_close)( const struct mg_connection *conn );`**| -| |The callback function `connection_close()` is called when CivetWeb is closing a connection. The per-context mutex is locked when the callback function is invoked. The function is primarily useful for noting when a websocket is closing and removing it from any application-maintained list of clients. *Using this callback for websocket connections is deprecated. Use* `mg_set_websocket_handler()` *instead.*| +| |The callback function `connection_close()` is called before CivetWeb closes a connection. The per-context mutex is locked when the callback function is invoked. The function is primarily useful for noting when a websocket is closing and removing it from any application-maintained list of clients. *Using this callback for websocket connections is deprecated. Use* `mg_set_websocket_handler()` *instead.*| +|**`connection_closed`**|**`void (*connection_closed)( const struct mg_connection *conn );`**| +| |The callback function `connection_closed()` is called after CivetWeb has closed a connection (after SSL shutdown and after closing the socket). The per-context mutex is locked when the callback function is invoked.| |**`end_request`**|**`void (*end_request)(const struct mg_connection *conn, int reply_status_code);`**| | |The callback function `end_request()` is called by CivetWeb when a request has been completely processed. It sends the reply status code which was sent to the client to the application.| |**`exit_context`**|**`void (*exit_context)( const struct mg_context *ctx );`**| diff -Nru civetweb-1.13+dfsg/docs/api/mg_error_data.md civetweb-1.15+dfsg/docs/api/mg_error_data.md --- civetweb-1.13+dfsg/docs/api/mg_error_data.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_error_data.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,23 @@ +# Civetweb API Reference + +### `struct mg_error_data;` + +### Fields + +| Field | Type | Description | +| :--- | :--- | :--- | +|**`code`**|`unsigned *`| A pointer to an `unsigned` variable, to store the error code. | +|**`text`**|`char *`| A text buffer to store the error text. | +|**`text_buffer_size`**|`size_t`| Size of the text buffer. | + +### Description + +The structure `mg_error_data` is used in [`mg_start2()`](mg_start.md), [`mg_start_domain2();`](mg_start_domain2.md), [`mg_connect_client2();`](mg_connect_client2.md) and [`mg_get_response2();`](mg_get_response2.md) to return error information. + +### See Also + +* [`mg_start2();`](mg_start2.md) +* [`mg_start_domain2();`](mg_start_domain2.md) +* [`mg_connect_client2();`](mg_connect_client2.md) +* [`mg_get_response2();`](mg_get_response2.md) +* [`struct mg_init_data;`](mg_init_data.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_init_data.md civetweb-1.15+dfsg/docs/api/mg_init_data.md --- civetweb-1.13+dfsg/docs/api/mg_init_data.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_init_data.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,24 @@ +# Civetweb API Reference + +### `struct mg_init_data;` + +### Fields + +| Field | Type | Description | +| :--- | :--- | :--- | +|**`callbacks`**|`const struct mg_callbacks *`| A structure with optional callback functions to process requests from the web server | +|**`user_data`**|`void *`| A pointer to optional user data | +|**`configuration_options`**|`const char **`| A list of options used to initialize the web server. The list consists of an NULL terminated list of option-value string pairs. | + +### Description + +The structure `mg_init_data` is used in [`mg_start2()`](mg_start.md) and [`mg_connect_client2();`](mg_connect_client2.md). +It holds the same parameters supplied to [`mg_start();`](mg_start.md) as individual arguments in one structure. + +### See Also + +* [`struct mg_callbacks;`](mg_callbacks.md) +* [`mg_start();`](mg_start.md) +* [`mg_start2();`](mg_start2.md) +* [`mg_connect_client2();`](mg_connect_client2.md) +* [`struct mg_error_data;`](mg_error_data.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_modify_passwords_file_ha1.md civetweb-1.15+dfsg/docs/api/mg_modify_passwords_file_ha1.md --- civetweb-1.13+dfsg/docs/api/mg_modify_passwords_file_ha1.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_modify_passwords_file_ha1.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,37 @@ +# Civetweb API Reference + +### `mg_modify_passwords_file_ha1( passwords_file_name, domain, user, ha1 );` + +### Parameters + +| Parameter | Type | Description | +| :--- | :--- | :--- | +|**`passwords_file_name`**|`const char *`|The path to the passwords file| +|**`realm`**|`const char *`|The authentication realm (domain) of the user record| +|**`user`**|`const char *`|Username of the record to be added, changed or deleted| +|**`ha1`**|`const char *`|HA1 hash of "user:realm:password"| + +### Return Value + +| Type | Description | +| :--- | :--- | +|`int`|Success or error code| + +### Description + +The function `mg_modify_passwords_file_ha1()` is similar to `mg_modify_passwords_file()`, but the password is not specified in plain text and thus is not revealed to the civetweb library. Instead of the password, a hash ("HA1") is specified which is constructed by the caller as the MD5 checksum (in lower-case hex digits) of the string `user:realm:password`. + +For example, if the user name is `myuser`, the realm is `myrealm`, and the password is `secret`, then the HA1 is `e67fd3248b58975c3e89ff18ecb75e2f`: + +``` +$ echo -n "myuser:myrealm:secret" | md5sum +e67fd3248b58975c3e89ff18ecb75e2f - +``` + +The function returns 1 when successful and 0 if an error occurs. + +### See Also + +* [`mg_modify_passwords_file();`](mg_modify_passwords_file.md) + + diff -Nru civetweb-1.13+dfsg/docs/api/mg_modify_passwords_file.md civetweb-1.15+dfsg/docs/api/mg_modify_passwords_file.md --- civetweb-1.13+dfsg/docs/api/mg_modify_passwords_file.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_modify_passwords_file.md 2021-09-01 08:46:33.000000000 +0000 @@ -27,6 +27,7 @@ ### See Also +* [`mg_modify_passwords_file_ha1();`](mg_modify_passwords_file_ha1.md) * [`mg_check_digest_access_authentication();`](mg_check_digest_access_authentication.md) * [`mg_send_digest_access_authentication_request();`](mg_send_digest_access_authentication_request.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_request_info.md civetweb-1.15+dfsg/docs/api/mg_request_info.md --- civetweb-1.13+dfsg/docs/api/mg_request_info.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_request_info.md 2021-09-01 08:46:33.000000000 +0000 @@ -8,7 +8,8 @@ | :--- | :--- | :--- | |**`request_method`**|`const char *`| The request method used by the client for the connection this can be **GET**, **POST** or one of the other common HTTP request methods | |**`request_uri`**|`const char *`| The absolute, relative or URL-encoded URI as it was sent in the request. Example: "http://mydomain.com:8080/path/to/file.ext" or "/path/to/file.ext", depending on the client. | -|**`local_uri`**|`const char *`| The relative URL-encoded URI as it references the local resource. If the request URI does not reference a resource on the local server, this field is NULL. Example: "/path/to/file.ext" (even if the client used "http://mydomain.com:8080/path/to/file.ext" in the request) | +|**`local_uri_raw`**|`const char *`| The relative URL-encoded URI as it references the local resource. If the request URI does not reference a resource on the local server, this field is NULL. Example: "/path/to/file.ext" (even if the client used "http://mydomain.com:8080/path/to/file.ext" in the request) | +|**`local_uri`**|`const char *`| The `local_uri_raw` cleaned, so it does not allow a path like "allowed_dir/../forbidden_file". Files served by CivetWeb are selected based on this `local_uri`. | |~~`uri`~~|`const char *`| *Deprecated. Use* `local_uri` *instead* | |**`http_version`**|`const char *`| The HTTP version as mentioned in the client request. This can be "1.0", "1.1", etc. | |**`query_string`**|`const char *`| The HTTP query string, defined as URL part after the first '?' character, not including '?'. NULL if there is no '?'. | @@ -16,7 +17,8 @@ |**`remote addr`**|`char[48]`| The IP address of the remote client as a string. This can either represent an IPv4 or an IPv6 address. Example: "127.0.0.1" | |~~`remote_ip`~~|`long`| *Deprecated. Use* `remote_addr` *instead* | |**`content_length`**|`long long`| The content length of the request body. This value can be -1 if no content length was provided. The request may still have body data, but the server cannot determine the length until all data has arrived (e.g. when the client closes the connection, or the final chunk of a chunked request has been received). | -|**`remote_port`**|`int`| The port number at the client's side (an integer number between 1 and 65535). | +|**`remote_port`**|`int`| The port number at the client side (an integer number between 1 and 65535). | +|**`server_port`**|`int`| The port number at the server side (an integer number between 0 and 65535). | |**`is_ssl`**|`int`| 1 if the connection is over SSL (https), and 0 if it is a plain connection (http) | |**`user_data`**|`void *`| A pointer to the `user_data` information which was provided as a parameter to `mg_start()`. | |**`conn_data`**|`void *`| A pointer to connection specific user data | diff -Nru civetweb-1.13+dfsg/docs/api/mg_send_chunk.md civetweb-1.15+dfsg/docs/api/mg_send_chunk.md --- civetweb-1.13+dfsg/docs/api/mg_send_chunk.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_send_chunk.md 2021-09-01 08:46:33.000000000 +0000 @@ -25,7 +25,7 @@ ### See Also * [`mg_write();`](mg_write.md) -* [`mg_printf();`](mg_print.md) +* [`mg_printf();`](mg_printf.md) * [`mg_lock_connection();`](mg_lock_connection.md) * [`mg_unlock_connection();`](mg_unlock_connection.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_send_digest_access_authentication_request.md civetweb-1.15+dfsg/docs/api/mg_send_digest_access_authentication_request.md --- civetweb-1.13+dfsg/docs/api/mg_send_digest_access_authentication_request.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_send_digest_access_authentication_request.md 2021-09-01 08:46:33.000000000 +0000 @@ -31,5 +31,5 @@ * [`mg_modify_passwords_file();`](mg_modify_passwords_file.md) * [`mg_send_http_error();`](mg_send_http_error.md) * [`mg_write();`](mg_write.md) -* [`mg_printf();`](mg_print.md) +* [`mg_printf();`](mg_printf.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_set_websocket_handler.md civetweb-1.15+dfsg/docs/api/mg_set_websocket_handler.md --- civetweb-1.13+dfsg/docs/api/mg_set_websocket_handler.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_set_websocket_handler.md 2021-09-01 08:46:33.000000000 +0000 @@ -8,7 +8,7 @@ | :--- | :--- | :--- | |**`ctx`**|`mg_context *`|The context in which to add the handlers| |**`uri`**|`const char *`|The URI for which the handlers should be activated| -|**`connect_handler`**|`mg_websocket_connect_handler`|Handler called when a connect is signalled| +|**`connect_handler`**|`mg_websocket_connect_handler`|Handler called when a connect is signaled| |**`ready_handler`**|`mg_websocket_ready_handler`|Handler called when the connection is ready| |**`data_handler`**|`mg_websocket_data_handler`|Handler called when data is received| |**`close_handler`**|`mg_websocket_close_handler`|Handler called when the connection closes| @@ -28,3 +28,5 @@ The function `mg_set_websocket_handler()` connects callback functions to a websocket URI. The callback functions are called when a state change is detected on the URI like an incoming connection or data received from a remote peer. ### See Also + +* [`mg_set_websocket_handler_with_subprotocols();`](mg_set_websocket_handler_with_subprotocols.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_set_websocket_handler_with_subprotocols.md civetweb-1.15+dfsg/docs/api/mg_set_websocket_handler_with_subprotocols.md --- civetweb-1.13+dfsg/docs/api/mg_set_websocket_handler_with_subprotocols.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_set_websocket_handler_with_subprotocols.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,36 @@ +# Civetweb API Reference + +### `mg_set_websocket_handler_with_subprotocols( ctx, uri, subprotocols, connect_handler, ready_handler, data_handler, close_handler, cbdata );` + +### Parameters + +| Parameter | Type | Description | +| :--- | :--- | :--- | +|**`ctx`**|`mg_context *`|The context in which to add the handlers| +|**`uri`**|`const char *`|The URI for which the handlers should be activated| +|**`subprotocols`**|`struct mg_websocket_subprotocols *`|A list of supported sub-protocols| +|**`connect_handler`**|`mg_websocket_connect_handler`|Handler called when a connect is signaled| +|**`ready_handler`**|`mg_websocket_ready_handler`|Handler called when the connection is ready| +|**`data_handler`**|`mg_websocket_data_handler`|Handler called when data is received| +|**`close_handler`**|`mg_websocket_close_handler`|Handler called when the connection closes| +|**`cbdata`**|`void *`|User defined data| + +`int mg_websocket_connect_handler( const struct mg_connection *conn, void *cbdata );` +`int mg_websocket_ready_handler( struct mg_connection *conn, void *cbdata );` +`int mg_websocket_data_handler( struct mg_connection *conn, int opcode, char * buf, size_t buf_len, void *cbdata );` +`int mg_websocket_close_handler( const struct mg_connection *conn, void *cbdata );` + +### Return Value + +*none* + +### Description + +The function `mg_set_websocket_handler_with_subprotocols()` connects callback functions to a websocket URI, just like [`mg_set_websocket_handler();`](mg_set_websocket_handler.md). +In addition, it allows to specify websocket sub-protocols. +The callback functions are called when a state change is detected on the URI like an incoming connection or data received from a remote peer. + +### See Also + +* [`struct mg_websocket_subprotocols;`](api/mg_websocket_subprotocols.md) +* [`mg_set_websocket_handler();`](mg_set_websocket_handler.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_websocket_subprotocols.md civetweb-1.15+dfsg/docs/api/mg_websocket_subprotocols.md --- civetweb-1.13+dfsg/docs/api/mg_websocket_subprotocols.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_websocket_subprotocols.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,18 @@ +# Civetweb API Reference + +### `struct mg_websocket_subprotocols;` + +### Fields + +| Field | Type | Description | +| :--- | :--- | :--- | +|**`nb_subprotocols`**|`int`| Number of websocket sub-protocol names following (>=0). | +|**`subprotocols`**|`const char **`| Array of websocket sub-protocol names (nb_subprotocols elements). | + +### Description + +The structure `mg_websocket_subprotocols` is used to specify websocket sub-protocols supported by a websocket handler function. + +### See Also + +* [`mg_set_websocket_handler_with_subprotocols();`](mg_set_websocket_handler_with_subprotocols.md) diff -Nru civetweb-1.13+dfsg/docs/api/mg_write.md civetweb-1.15+dfsg/docs/api/mg_write.md --- civetweb-1.13+dfsg/docs/api/mg_write.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/api/mg_write.md 2021-09-01 08:46:33.000000000 +0000 @@ -23,7 +23,7 @@ ### See Also * [`mg_lock_connection();`](mg_lock_connection.md) -* [`mg_printf();`](mg_print.md) +* [`mg_printf();`](mg_printf.md) * [`mg_unlock_connection();`](mg_unlock_connection.md) * [`mg_websocket_client_write();`](mg_websocket_client_write.md) * [`mg_websocket_write();`](mg_websocket_write.md) diff -Nru civetweb-1.13+dfsg/docs/APIReference.md civetweb-1.15+dfsg/docs/APIReference.md --- civetweb-1.13+dfsg/docs/APIReference.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/APIReference.md 2021-09-01 08:46:33.000000000 +0000 @@ -37,16 +37,18 @@ ## Structures +* [`struct mg_callbacks;`](api/mg_callbacks.md) * [`struct mg_client_cert;`](api/mg_client_cert.md) * [`struct mg_client_options;`](api/mg_client_options.md) -* [`struct mg_callbacks;`](api/mg_callbacks.md) +* [`struct mg_error_data;`](api/mg_error_data.md) * [`struct mg_form_data_handler;`](api/mg_form_data_handler.md) * [`struct mg_header;`](api/mg_header.md) +* [`struct mg_init_data;`](api/mg_init_data.md) * [`struct mg_option;`](api/mg_option.md) * [`struct mg_request_info;`](api/mg_request_info.md) * [`struct mg_response_info;`](api/mg_response_info.md) * [`struct mg_server_port;`](api/mg_server_port.md) - +* [`struct mg_websocket_subprotocols;`](api/mg_websocket_subprotocols.md) ## Library API Functions @@ -60,6 +62,9 @@ ## Server API Functions * [`mg_start( callbacks, user_data, options );`](api/mg_start.md) +* [`mg_start2( init, error );`](api/mg_start2.md) +* [`mg_start_domain( ctx, configuration_options );`](api/mg_start_domain.md) +* [`mg_start_domain2( ctx, configuration_options, error );`](api/mg_start_domain2.md) * [`mg_stop( ctx );`](api/mg_stop.md) * [`mg_get_builtin_mime_type( file_name );`](api/mg_get_builtin_mime_type.md) @@ -69,6 +74,7 @@ * [`mg_set_auth_handler( ctx, uri, handler, cbdata );`](api/mg_set_auth_handler.md) * [`mg_set_request_handler( ctx, uri, handler, cbdata );`](api/mg_set_request_handler.md) * [`mg_set_websocket_handler( ctx, uri, connect_handler, ready_handler, data_handler, close_handler, cbdata );`](api/mg_set_websocket_handler.md) +* [`mg_set_websocket_handler_with_subprotocols( ctx, uri, subprotocols, connect_handler, ready_handler, data_handler, close_handler, cbdata );`](api/mg_set_websocket_handler_with_subprotocols.md) * [`mg_lock_context( ctx );`](api/mg_lock_context.md) * [`mg_unlock_context( ctx );`](api/mg_unlock_context.md) @@ -82,6 +88,7 @@ * [`mg_send_digest_access_authentication_request( conn, realm );`](api/mg_send_digest_access_authentication_request.md) * [`mg_check_digest_access_authentication( conn, realm, filename );`](api/mg_check_digest_access_authentication.md) * [`mg_modify_passwords_file( passwords_file_name, realm, user, password );`](api/mg_modify_passwords_file.md) +* [`mg_modify_passwords_file_ha1( passwords_file_name, realm, user, ha1 );`](api/mg_modify_passwords_file_ha1.md) * [`mg_get_request_info( conn );`](api/mg_get_request_info.md) * [`mg_get_request_link( conn, buf, buflen );`](api/mg_get_request_link.md) @@ -92,6 +99,8 @@ * [`mg_send_mime_file2( conn, path, mime_type, additional_headers );`](api/mg_send_mime_file2.md) * [`mg_websocket_write( conn, opcode, data, data_len );`](api/mg_websocket_write.md) +* [`mg_response_header_*();`](api/mg_response_header_X.md) + ## Client API Functions * [`mg_connect_client( host, port, use_ssl, error_buffer, error_buffer_size );`](api/mg_connect_client.md) @@ -104,6 +113,10 @@ * [`mg_get_response( conn, ebuf, ebuf_len, timeout );`](api/mg_get_response.md) * [`mg_get_response_info( conn );`](api/mg_get_response_info.md) +* [`mg_connect_client2( host, protocol, port, path, init, error );`](api/mg_connect_client2.md) +* [`mg_get_response2( conn, error, timeout );`](api/mg_get_response2.md) + + ## Common API Functions * [`mg_close_connection( conn );`](api/mg_close_connection.md) @@ -121,8 +134,9 @@ * [`mg_printf( conn, fmt, ... );`](api/mg_printf.md) * [`mg_read( conn, buf, len );`](api/mg_read.md) * [`mg_send_chunk( conn, buf, len );`](api/mg_send_chunk.md) -* [`mg_send_file( conn, path );`](api/mg_send_file_body.md) +* [`mg_send_file_body( conn, path );`](api/mg_send_file_body.md) * [`mg_set_user_connection_data( conn, data );`](api/mg_set_user_connection_data.md) +* [`mg_split_form_urlencoded( data, form_fields, num_form_fields);`](api/mg_split_form_urlencoded.md) * [`mg_start_thread( f, p );`](api/mg_start_thread.md) * [`mg_store_body( conn, path );`](api/mg_store_body.md) * [`mg_strcasecmp( s1, s2 );`](api/mg_strcasecmp.md) @@ -132,7 +146,6 @@ * [`mg_url_encode( src, dst, dst_len );`](api/mg_url_encode.md) * [`mg_write( conn, buf, len );`](api/mg_write.md) - ## Diagnosis Functions * [`mg_get_system_info( buffer, buf_len );`](api/mg_get_system_info.md) @@ -140,10 +153,8 @@ * [`mg_get_connection_info( ctx, idx, buffer, buf_len );`](api/mg_get_connection_info.md) -## Deprecated: +## Deprecated / removed: * [~~`mg_get_valid_option_names();`~~](api/mg_get_valid_option_names.md) * [~~`mg_upload( conn, destination_dir );`~~](api/mg_upload.md) * [~~`mg_get_ports( ctx, size, ports, ssl);`~~](api/mg_get_ports.md) - - diff -Nru civetweb-1.13+dfsg/docs/Building.md civetweb-1.15+dfsg/docs/Building.md --- civetweb-1.13+dfsg/docs/Building.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/Building.md 2021-09-01 08:46:33.000000000 +0000 @@ -49,8 +49,10 @@ ``` make build +make WITH_ALL=1 ``` -compile the code +Compile the code. +Using the option "WITH_ALL=1" enables all optional features. ``` make install @@ -58,11 +60,10 @@ Install on the system, Linux only. ``` -make lib WITH_CPP=1 WITH_IPV6=1 -make clean slib WITH_CPP=1 WITH_LUA=1 WITH_WEBSOCKET=1 +make lib WITH_IPV6=1 +make clean slib WITH_LUA=1 WITH_WEBSOCKET=1 ``` Build the static and shared libraries. -The *WITH_CPP* make option is to include the CivetServer class. The additional make options configure the library just as it would the application. The *slib* option should be done on a separate clean build as position @@ -89,6 +90,7 @@ | `WITH_DUKTAPE=1` | build with server-side JavaScript support | | `WITH_IPV6=1` | with IPV6 support | | `WITH_WEBSOCKET=1` | build with web socket support | +| `WITH_X_DOM_SOCKET=1` | build with unix domain socket support | | `WITH_SERVER_STATS=1` | build with support for server statistics | | `WITH_EXPERIMENTAL=1` | include experimental features (version depending) | | `WITH_ALL=1` | Include all of the above features | @@ -167,6 +169,7 @@ | `USE_SERVER_STATS` | enable server statistics support | | `USE_STACK_SIZE` | define stack size instead of using system default | | `USE_WEBSOCKET` | enable websocket support | +| `USE_X_DOM_SOCKET` | enable unix domain socket support | | `USE_ZLIB` | enable on-the-fly compression of files (using zlib) | | | | | `MG_EXPERIMENTAL_INTERFACES` | include experimental interfaces | @@ -176,6 +179,9 @@ | `SSL_ALREADY_INITIALIZED` | do not initialize libcrypto | | `OPENSSL_API_1_0` | Use OpenSSL V1.0.x interface | | `OPENSSL_API_1_1` | Use OpenSSL V1.1.x interface | +| | | +| `BUILD_DATE` | define as a string to be used as build id instead of __DATE__ | +| | | Note: If `make` is used (with this [Makefile](https://github.com/civetweb/civetweb/blob/master/Makefile)), you should not pass the `USE_` flags using `COPT`, but use the `WITH_` syntax above, since additional features may also use additional source code files. diff -Nru civetweb-1.13+dfsg/docs/Contribution.md civetweb-1.15+dfsg/docs/Contribution.md --- civetweb-1.13+dfsg/docs/Contribution.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/Contribution.md 2021-09-01 08:46:33.000000000 +0000 @@ -3,12 +3,13 @@ Contributions to CivetWeb are welcome, provided all contributions carry the MIT license. -- Please report issues on GitHub. If the issue you want to report is already reported there, add a note with your specific details to that issue. In case of doubt, please create a new issue. -- If you know how to fix the issue, please create a pull request on GitHub. Please take care your modifications pass the continuous integration checks. These checks are performed automatically when you create a pull request, but it may take some hours until all tests are completed. Please provide a description for every pull request. -- Alternatively, you can post a patch or describe the required modifications in a GitHub issue. -However, a pull request would be preferred. -- Contributor names are listed in CREDITS.md, unless you explicitly state you don't want your name to be listed there. This file is occasionally updated, adding new contributors, using author names from git commits and GitHub comments. +- Please report [issues](https://github.com/civetweb/civetweb/issues) on GitHub. If the issue you want to report is already reported there, add a comment with your specific details to that issue. In case of doubt, please create a new issue. +- If you know how to fix the issue, please create a pull request on GitHub. Please take care your modifications pass the continuous integration checks. These checks are performed automatically when you create a pull request, but it may take some hours until all tests are completed. Please provide a description for every pull request (see below). +- Alternatively, you can post a patch or describe the required modifications in a GitHub issue. However, a pull request would be preferred. +- Improvments to documentation, tests and examples are welcome as well. + +- Contributor names are listed in [CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md), unless you explicitly state you don't want your name to be listed there. This file is occasionally updated, adding new contributors, using author names from git commits and GitHub comments. - In case your modifications either 1. modify or extend the API, @@ -16,17 +17,31 @@ 3. imply structural changes, or 4. have significant influence on maintenance, - - please first create an issue on GitHub or create a thread on the CivetWeb discussion group, to discuss the planned changed. -- In case you think you found a security issue that should be evaluated and fixed before public disclosure, feel free to write an email. Although CivetWeb is a fork from Mongoose from 2013, the code bases are different now, so security vulnerabilities of Mongoose usually do not affect CivetWeb. Open an issue for Mongoose vulnerabilities you want to have checked if CivetWeb is affected. + please first create an issue on GitHub to discuss the planned changed. + +- In case you think you found a security issue that should be evaluated and fixed before public disclosure, feel free to write an email. Although CivetWeb is a fork from Mongoose from 2013, the code bases are different now, so security vulnerabilities of Mongoose usually do not affect CivetWeb. See also [SECURITY.md](https://github.com/civetweb/civetweb/blob/master/SECURITY.md). + + + +Closing Issues +--- + +Feel free to create a GitHub issue also for questions, discussions or support requests. +When your question is anwered, please close your issue again - so I know your request is handled. +In some cases I will have to query you for additional information. +If there is no acticity for a question/discussion/support issue for some weeks, I will close this issues. +Issues created for bugs or enhancement requests will not be closed only because some time has passed. + Why does a pull request need a description? --- -I'm asking for this, because I usually review all pull requests. +I'm asking for this, because I review most pull requests. The first thing I check is: "What is the intention of the fix **according to the description**?" and "Does the code really fix it?". Second: "Do I except side effects?". Third: "Is there a better way to fix the issue **explained in the description**?" -I don't like to "reverse engineer" the intention of the fix from the diff (although it may be obvious to the author of the PR, sometimes it's not for others). But you should also do it for yourself: You will get early feedback if your changes are not doing what you expect, or if there is a much more effective way to reach the same goal. Finally it will help all other users, since it helps writing better release notes. +I don't like to "reverse engineer" the intention of the fix from the diff (although it may be obvious to the author of the PR, sometimes it's not for others). +Writing a description will also help you to get early feedback if your changes are not doing what you expect, or if there is a much more effective way to reach the same goal. +Finally it will help all other users, since it allows to write better release notes. diff -Nru civetweb-1.13+dfsg/docs/Embedding.md civetweb-1.15+dfsg/docs/Embedding.md --- civetweb-1.13+dfsg/docs/Embedding.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/Embedding.md 2021-09-01 08:46:33.000000000 +0000 @@ -39,7 +39,9 @@ - src/mod\_*.inl (modules to access third party components from civetweb) -Note: The C++ wrapper uses the official C interface (civetweb.h) without adding any features to the server itself. Several features available in the C interface are missing in the C++ interface. While all features should be accessible using the C interface, this is not a design goal of the C++ interface. +Note: The C++ wrapper uses the official C interface (civetweb.h) without adding any features to the server itself. +Several features available in the C interface are missing in the C++ interface. +While all features should be accessible using the C interface, this is not a design goal of the C++ interface. New code is advised to use the C interface, since this is unit tested and new API functions are often only added there. @@ -179,7 +181,7 @@ - src/third\_party/lfs.c - src/third\_party/lfs.h -This build is valid for Lua version Lua 5.2. It is also possible to build with Lua 5.1 (including LuaJIT) or Lua 5.3. +This build is valid for Lua version Lua 5.2. It is also possible to build with Lua 5.1 (including LuaJIT), Lua 5.3 or Lua 5.4. JavaScript Support @@ -284,7 +286,23 @@ } ``` -A simple callback +A simple callback (HTTP/1.x and HTTP/2): +```C +static int +handler(struct mg_connection *conn, void *ignored) +{ + const char *msg = "Hello world"; + unsigned long len = (unsigned long)strlen(msg); + + mg_send_http_ok(conn, "text/plain", len); + + mg_write(conn, msg, len); + + return 200; /* HTTP state 200 = OK */ +} +``` + +A simple callback supporting HTTP/1.x only: ```C static int handler(struct mg_connection *conn, void *ignored) @@ -304,4 +322,3 @@ return 200; } ``` - diff -Nru civetweb-1.13+dfsg/docs/Installing.md civetweb-1.15+dfsg/docs/Installing.md --- civetweb-1.13+dfsg/docs/Installing.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/Installing.md 2021-09-01 08:46:33.000000000 +0000 @@ -1,7 +1,9 @@ -Civetweb Install Guide +CivetWeb Install Guide ==== -This guide covers the distributions for CivetWeb. The latest source code is available at [https://github.com/civetweb/civetweb](https://github.com/civetweb/civetweb). +This guide covers the pre-built binary distributions of CivetWeb. +The latest source code version is available at [https://github.com/civetweb/civetweb](https://github.com/civetweb/civetweb). + Windows --- @@ -10,17 +12,18 @@ however, users may add an SSL library themselves. Instructions for adding SSL support can be found in [https://github.com/civetweb/civetweb/tree/master/docs](https://github.com/civetweb/civetweb/tree/master/docs) -1. In case the Visual C++ Redistributable are not already installed: - 32 Bit Version: Install the [Redistributable for Visual Studio 2010](http://www.microsoft.com/en-us/download/details.aspx?id=8328) - 64 Bit Version: Install the [Redistributable for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145) - Note: The required version of the Redistributables may vary, depending on the CivetWeb version. +1. The "Visual C++ Redistributables" are already installed on most Windows PCs. + In case they are missing, you will see a "msvcr###.dll missing" error message when starting the server. + You need to download and install the [Redistributable for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145) + Note: The required version of the Redistributables may vary, depending on the CivetWeb version. 2. Download latest *civetweb-win.zip* from [SourceForge](https://sourceforge.net/projects/civetweb/files/) -3. When started, Civetweb puts itself into the tray. +3. When started, CivetWeb puts itself into the tray. + -Building civetweb - Using vcpkg +Building CivetWeb - Using vcpkg --- -You can download and install civetweb using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: +You can download and install CivetWeb using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: git clone https://github.com/Microsoft/vcpkg.git cd vcpkg @@ -28,17 +31,8 @@ ./vcpkg integrate install ./vcpkg install civetweb -The civetweb port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. - -OS X ---- - -This pre-built version comes with Lua, IPV6 and SSL support. +The CivetWeb port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. -1. Download the latest *Civetweb.dmg* from [SourceForge](https://sourceforge.net/projects/civetweb/files/) -2. Click on the it and look for the attachment in the finder. -4. Drag Civetweb to the Applications folder. -5. When started, Civetweb puts itself into top menu. Linux --- @@ -50,5 +44,5 @@ 5. make install 6. Run the program ```/usr/local/bin/civetweb```, it will use the configuration file */usr/local/etc/civetweb.conf*. -Most Linux systems support auto completion of command line arguments. To enable bash auto completion for the civetweb stand-alone executable, set *resources/complete.lua* as complete command. See comments in that file for further instructions. +Most Linux systems support auto completion of command line arguments. To enable bash auto completion for the CivetWeb stand-alone executable, set *resources/complete.lua* as complete command. See comments in that file for further instructions. diff -Nru civetweb-1.13+dfsg/docs/Interface_Changes_1.10.md civetweb-1.15+dfsg/docs/Interface_Changes_1.10.md --- civetweb-1.13+dfsg/docs/Interface_Changes_1.10.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/Interface_Changes_1.10.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -# Interface changes - -## Proposed interface changes for future versions - -Interface changes from 1.10 to 1.11 and/or later versions - -see also [this GitHub issue](https://github.com/civetweb/civetweb/issues/544). - - -### Server interface - -#### S1: mg\_start / mg\_init\_library - -Calling mg\_init\_library is recommended before calling mg\_start. - -**Compatibility considerations:** -Initially, mg\_init\_library will be called implicitly if it has -not been called before mg\_start. -If mg\_init\_library was not called, mg\_stop may leave memory leaks. - -**Required Actions:** -Call mg\_init\_library manually to avoid a small memory leak when -closing the server. - - -#### S2: mg\_websocket\_write functions - -Calling mg\_lock\_connection is no longer called implicitly -in mg\_websocket\_write functions. -If you use websocket write functions them from two threads, -you must call mg\_lock\_connection explicitly, just like for any -other connection. - -This is an API harmonization issue. - -**Compatibility considerations:** -If a websocket connection was used in only one thread, there is -no incompatibility. If a websocket connection was used in multiple -threads, the user has to add the mg\_lock\_connection before and -the mg\_unlock\_connection after the websocket write call. - -**Required Actions:** -Call mg\_lock\_connection and mg\_unlock\_connection manually -when using mg\_websocket\_write. - - -#### S3: open\_file member of mg\_callbacks - -Memory mapped files are a relic from before `mg_set_request_handler` -was introduced in CivetWeb 1.4 (September 2013). -Is "file in memory" still a useful feature or dead code? See this -[discussion](https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI). -Since it is not widely used, and a burden in maintenance, the -"file in memory" should be completely removed, including removing -the open\_file member of mg\_callbacks. - - -**Compatibility considerations:** -Removing "file in memory" will require code using open\_file to be changed. -A possible replacement by mg\_set\_request\_handler is sketched in -[this comment](https://github.com/civetweb/civetweb/issues/440#issuecomment-290531238). - -**Required Actions:** -Modify code using open\_file by using request handlers. - - -#### S4: Support multiple hostnames and SNI - -TLS [Server Name Identification (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) -allows to host different domains with different X.509 certificates -on the same physical server (same IP+port). In order to support this, -some configurations (like authentication\_domain, ssl\_certificate, -document\_root and may others) need to be specified multiple times - -once for each domain hosted -(see [535](https://github.com/civetweb/civetweb/issues/535)). - -The current configuration model does not account for SNI, so it needs -to be extended to support configuration of multiple instances. - -**Compatibility considerations:** -To be defined as soon as possible solutions are evaluated. - - -#### S5: IPv6 support for access\_control\_list and throttle - -The current configuration for access\_control\_list and throttle only -works for IPv4 addresses. If server and client support -[IPv6](https://en.wikipedia.org/wiki/IPv6_address) as well, -there is no way to add a client to the throttle or access list. -The current configuration syntax isn't really comfortable for IPv4 -either. -Combined with hosting multiple domains (and SNI), different domains -may have different block/throttle configurations as well - this has -to be considered in a new configuration as well. - -**Compatibility considerations:** -To be defined as soon as possible solutions are evaluated. - - -### Client interface - -#### C1: mg\_init\_library - -Calling mg\_init\_library is required before calling any client -function. In particular, the TLS initialization must be done -before using mg\_connect\_client\_secure. - -**Compatibility considerations:** -Some parts of the client interface did not work, if mg\_start -was not called before. Now it works after calling -mg\_init\_library - this is not an incompatibility. - - -#### C2: mg\_connect\_client (family) - -mg\_connect\_client needs several new parameters (options). - -Details are to be defined. - -mg\_connect\_client and mg\_download should return a different kind of -mg_connection than used in server callbacks. At least, there should -be a function mg\_get\_response\_info, instead of using -mg\_get\_request\_info, and getting the HTTP response code from the -server by looking into the uri member of struct mg\_request\_info. - - -### General interfaces - -#### G1: `size_t` in all interface - -Having `size_t` in interfaces while building for 32 and 64 bit -complicates maintenance in an unnecessary way -(see [498](https://github.com/civetweb/civetweb/issues/498)). - -Replace all data sizes by 64 bit integers. - - -#### G2: Pattern definition - -The current definition of pattern matching is problematic -(see [499](https://github.com/civetweb/civetweb/issues/499)). - -Find and implement a new definition. - - diff -Nru civetweb-1.13+dfsg/docs/mbedtls.md civetweb-1.15+dfsg/docs/mbedtls.md --- civetweb-1.13+dfsg/docs/mbedtls.md 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/docs/mbedtls.md 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,16 @@ +#### Use MbedTLS instead of OpenSSL +===== + +1 [Build mbedtls](https://github.com/ARMmbed/mbedtls) + + - 1.1 git clone https://github.com/ARMmbed/mbedtls.git -b mbedtls-2.24.0 + - 1.2 Use Arm Mbed TLS in threaded environments, enable `MBEDTLS_THREADING_C` and `MBEDTLS_THREADING_PTHREAD` in config.h, [more](https://tls.mbed.org/kb/development/thread-safety-and-multi-threading) + - 1.3 make SHARED=1 && make install + +2 Build civetweb + + - make build WITH_MBEDTLS=1 + +3 Run civetweb + - export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH + - ./civetweb -listening_ports 8443s -ssl_certificate resources/cert/server.pem -document_root ./test/htmldir/ diff -Nru civetweb-1.13+dfsg/docs/README.md civetweb-1.15+dfsg/docs/README.md --- civetweb-1.13+dfsg/docs/README.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/README.md 2021-09-01 08:46:33.000000000 +0000 @@ -8,7 +8,8 @@ It can also be used by end users as a stand-alone web server. It is available as single executable, no installation is required. -The current stable version is 1.13 - [release notes](https://github.com/civetweb/civetweb/blob/master/RELEASE_NOTES.md) +To find the latest stable release, visit [https://github.com/civetweb/civetweb/releases](https://github.com/civetweb/civetweb/releases). +A list of selected changes can be found in the [release notes](https://github.com/civetweb/civetweb/blob/master/RELEASE_NOTES.md). End users can download CivetWeb at SourceForge [https://sourceforge.net/projects/civetweb/](https://sourceforge.net/projects/civetweb/) @@ -19,14 +20,17 @@ Trouble tickets should be filed on GitHub [https://github.com/civetweb/civetweb/issues](https://github.com/civetweb/civetweb/issues) -Announcements are at Google Groups +New releases are announced at Google Groups [https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb) -While older support question and discussion threads have been at [Google groups](https://groups.google.com/d/forum/civetweb), most newer ones are [GitHub issues](https://github.com/civetweb/civetweb/issues). +Formerly some support question and discussion threads have been at [Google groups](https://groups.google.com/d/forum/civetweb). +Recent questions and discussions use [GitHub issues](https://github.com/civetweb/civetweb/issues). Source releases can be found on GitHub [https://github.com/civetweb/civetweb/releases](https://github.com/civetweb/civetweb/releases) +A security policy can be found in [SECURITY.md](https://github.com/civetweb/civetweb/blob/master/SECURITY.md). + CivetWeb is free of charge, however, donations for maintenance are welcome: [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=88ZLXZ6U77GJU) diff -Nru civetweb-1.13+dfsg/docs/UserManual.md civetweb-1.15+dfsg/docs/UserManual.md --- civetweb-1.13+dfsg/docs/UserManual.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/docs/UserManual.md 2021-09-01 08:46:33.000000000 +0000 @@ -242,22 +242,37 @@ ### cgi\_interpreter\_args Optional additional arguments passed to a Windows CGI interpreter program. -(Currently experimental - https://github.com/civetweb/civetweb/issues/854) - ### cgi\_pattern `**.cgi$|**.pl$|**.php$` All files that match `cgi_pattern` are treated as CGI files. The default pattern allows CGI files be anywhere. To restrict CGIs to a certain directory, use `/path/to/cgi-bin/**.cgi` as the pattern. Note that the full file path is matched against the pattern, not the URI. +Depending on the build configuration, additional patterns `cgi2_pattern`, +`cgi3_pattern` and `cgi4_pattern` may be available. +This allows to use different cgi interpreter programs (`cgi2_interpreter`, +...), environments (`cgi2_environment` ...) and interpreter arguments +(`cgi2_interpreter_argument`, ...). The default for all additional CGI file +patterns is empty - they are not used unless they are configured explicitly. + ### cgi\_timeout\_ms Maximum allowed runtime for CGI scripts. CGI processes are terminated by the server after this time. The default is "no timeout", so scripts may run or block for undefined time. +### decode\_query\_string `no` +URL decode all query strings in the server. +If you set this option to `yes`, all callbacks and scripts will only see the already +decoded query string. If this option is set to `no`, all callbacks and scripts have to decode +the query strings on their own, if they need to. Note that setting this option to `yes` is not +compatible with submitting form data using "GET" requests (but it is compatible with submitting +form data using the "POST" method; using "POST" is recommended for most use cases). + ### decode\_url `yes` -URL encoded request strings are decoded in the server, unless it is disabled -by setting this option to `no`. +The server should decode the URL, according to the HTTP standard. +This means, `http://mydomain.com/this%20file.txt` will be decoded to `this file.txt` +(%20 corresponds to the URL encoding of the space character). +Set this option to `no` only if you are using callbacks exclusively and need access to the encoded URLs. ### document\_root `.` A directory to serve. By default, the current working directory is served. @@ -274,6 +289,11 @@ ### enable\_directory\_listing `yes` Enable directory listing, either `yes` or `no`. +### enable\_http2 `no` +Enable HTTP2 protocol. Note: This option is only available, if the server has been +compiled with the `USE_HTTP2` define. The CivetWeb server supports only a subset of +all HTTP2 features. + ### enable\_keep\_alive `no` Enable connection keep alive, either `yes` or `no`. @@ -436,26 +456,41 @@ If you want to use an ephemeral port (i.e. let the operating system choose a port number), use `0` for the port number. This will make it necessary to communicate the port number to clients via other means, for example mDNS -(or Zeroconf, Bonjour or Avahi). +(Zeroconf, Bonjour, Avahi). + +In case the server has been built with the `USE_X_DOM_SOCKET` option set, +it can listen to unix domain sockets as well. They are specified by a +lower case `x` followed by the domain socket path, e.g. `x/tmp/sockname`. +Domain sockets do not require a port number, always use HTTP (not HTTPS) +and never redirect. Thus `:` is not allowed, while `r` or `s` at the end +of the configuration is interpreted as part of the domain socket path. +The domain sochet path must be a valid path to a non-existing file on a +Unix/Linux system. The CivetWeb process needs write/create access rights +to create the domain socket in the Unix/Linux file system. +Use only alphanumerical characters, underscore and `/` in a domain socket +path (in particular, `,;:` must be avoided). + +All socket/protocol types may be combined, separated by `,`. +E.g.: `127.0.0.1:80,[::1]:80,x/tmp/sockname` will listen to localhost +http connections using IPv4, IPv6 and the domain socket `/tmp/sockname`. ### lua\_background\_script -Experimental feature, and subject to change. Run a Lua script in the background, independent from any connection. The script is started before network access to the server is available. It can be used to prepare the document root (e.g., update files, compress files, ...), check for external resources, remove old log files, etc. +The script can define callbacks to be notified when the server starts +or stops. Furthermore, it can be used for log filtering or formatting. The Lua state remains open until the server is stopped. -In the future, some callback functions will be available to notify the -script on changes of the server state. See example lua script : -[background.lua](https://github.com/civetweb/civetweb/blob/master/test/background.lua). -Additional functions available in background script : -sleep, root path, script name, is terminated +For a detailed descriotion of available Lua callbacks see section +"Lua background script" below. -### lua\_background\_script\_params `param1=1,param2=2` +### lua\_background\_script\_params Can add dynamic parameters to background script. -Parameters mapped to global 'mg' table 'params' field. +Parameters mapped into 'mg.params' as table. +Example: `paramName1=paramValue1,paramName2=2` ### lua\_preload\_file This configuration option can be used to specify a Lua script file, which @@ -586,7 +621,7 @@ ### ssl\_cache\_timeout `-1` Allow caching of SSL/TLS sessions, so HTTPS connection from the same client to the same server can be established faster. A configuration value >0 activates -session caching. The configuration value is the maximum lifetime of a cached +session caching. The configuration value is the maximum lifetime of a cached session in seconds. The default is to deactivated session caching. @@ -610,23 +645,30 @@ See [this entry](https://www.openssl.org/docs/manmaster/apps/ciphers.html) in OpenSSL documentation for full list of options and additional examples. +The OpenSSL cipher string uses different cipher names than IANA +(see [this mapping](https://testssl.sh/openssl-iana.mapping.html)). + +In case CivetWeb is built with a TLS library other than OpenSSL +(e.g., [mbedTLS](https://tls.mbed.org/supported-ssl-ciphersuites)), +the cipher names may be different. ### ssl\_default\_verify\_paths `yes` Loads default trusted certificates locations set at openssl compile time. -### ssl\_protocol\_version `0` +### ssl\_protocol\_version `4` Sets the minimal accepted version of SSL/TLS protocol according to the table: Protocols | Value ------------ | ------------- -SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2 | 0 -SSL3+TLS1.0+TLS1.1+TLS1.2 | 1 -TLS1.0+TLS1.1+TLS1.2 | 2 -TLS1.1+TLS1.2 | 3 -TLS1.2 | 4 +SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2+TLS1.3 | 0 +SSL3+TLS1.0+TLS1.1+TLS1.2+TLS1.3 | 1 +TLS1.0+TLS1.1+TLS1.2+TLS1.3 | 2 +TLS1.1+TLS1.2+TLS1.3 | 3 +TLS1.2+TLS1.3 | 4 +TLS1.3 | 5 -More recent versions of OpenSSL include support for TLS version 1.3. -To use TLS1.3 only, set ssl\_protocol\_version to 5. +TLS version 1.3 is only available if you are using an up-to-date TLS libary. +The default setting has been changed from 0 to 4 in CivetWeb 1.14. ### ssl\_short\_trust `no` Enables the use of short lived certificates. This will allow for the certificates @@ -757,7 +799,7 @@ The following options are supported in `main.c`, the additional source file for the stand-alone executable. These options are not supported by other applications -embedding `civetweb.c`, unless they are added explicitly. +embedding `civetweb.c`, unless they are added to the embedding application. ### title Use the configured string as a server name. For Windows, this will be shown as @@ -771,15 +813,44 @@ For Windows, use this website as a link in the systray, replacing the default link for CivetWeb. +### hide\_tray `no` +For Windows: Do not show a tray icon. May be `yes` (hide) or `no` (show, default). + +### daemonize `no` +This option is only available for Linux, if the server has been build with the +`DAEMONIZE` compile options. Call (deprecated) `daemon()` BSD function to +detach the server process from the controlling terminal and run it in the +background as a system daemon. + ### add\_domain Option to load an additional configuration file, specifying an additional domain to host. To add multiple additional domains, use the add\_domain option multiple times with one configuration file for each domain. -A domain configuration file may have the same options as the main server, with -some exceptions. The options are passed to the `mg_start_domain` API function. +This option is available for Windows and Linux operating systems. -### hide\_tray `no` -Do not show a tray icon. May be `yes` (hide) or `no` (show, default). +Internally, the options are passed to the `mg_start_domain` API function. +If you are not using `main.c`, you need to call this API function to activate +and additional domain. + +Every domain configuration file may contain a subset of the options available for +the main server configuration files, with some exceptions. Some configurations +are per server while others are available for each domain. + +All port, socket, process and thread specific parameters are per server: +`allow_sendfile_call`, `case_sensitive`, `connection_queue`, `decode_url`, +`enable_http2`, `enable_keep_alive`, `enable_websocket_ping_pong`, +`keep_alive_timeout_ms`, `linger_timeout_ms`, `listen_backlog`, +`listening_ports`, `lua_background_script`, `lua_background_script_params`, +`max_request_size`, `num_threads`, `request_timeout_ms`, `run_as_user`, +`tcp_nodelay`, `throttle`, `websocket_timeout_ms` + all options from `main.c`. + +All other options can be set per domain. In particular +`authentication_domain`, `document_root` and (for HTTPS) `ssl_certificate` +must be set for each additional domain. + +While some options like `error_log_file` are per domain, the setting of the +initial (main) domain may be used if the server could not determine the +correct domain for a specific request. Scripting @@ -869,37 +940,73 @@ mg.read() -- reads a chunk from POST data, returns it as a string mg.write(str) -- writes string to the client + mg.cry(str) -- logs error string to stderr mg.include(filename, [pathtype]) -- include another Lua Page file (Lua Pages only) -- pathtype can be "abs", "rel"/"file" or "virt[ual]" -- like defined for SSI #include - mg.redirect(uri) -- internal redirect to a given URI + mg.redirect(uri) -- redirect to internal URI mg.onerror(msg) -- error handler, can be overridden - mg.version -- a string that holds CivetWeb version - mg.document_root -- a string that holds the document root directory mg.auth_domain -- a string that holds the HTTP authentication domain - mg.get_var(str, varname) -- extract variable from (query) string + mg.document_root -- a string that holds the document root directory + mg.lua_type -- a string that holds the lua script type + mg.system -- a string that holds the operating system name + mg.version -- a string that holds CivetWeb version mg.get_cookie(str, cookie) -- extract cookie from a string - mg.get_mime_type(filename) -- get MIME type of a file mg.get_info(infotype) -- get server status information + mg.get_mime_type(filename) -- get MIME type of a file + mg.get_option(name) -- get configuration option value from name + mg.get_response_code_text(n)-- get response code text for n, nil otherwise + mg.get_var(str, varname, [occurance]) -- extract the first occurance of variable from (query) string + -- otherwise the nth occurance if supplied, nil if not found mg.send_file(filename) -- send a file, including all required HTTP headers mg.send_file_body(filename) -- send a file, excluding HTTP headers + mg.send_http_error(n,str) -- send http error code n with string body + mg.send_http_ok(mime,body) -- send http 200 OK with content-type mime and string body + mg.send_http_ok(mime,length)-- send http 200 OK with content-type mime and integer content-length length + mg.send_http_redirect(url,n)-- redirect to url with status code n + mg.split_form_data(form) -- returns a table of the split form data mg.url_encode(str) -- URL encode a string mg.url_decode(str, [form]) -- URL decode a string. If form=true, replace + by space. mg.base64_encode(str) -- BASE64 encode a string mg.base64_decode(str) -- BASE64 decode a string mg.md5(str) -- return the MD5 hash of a string mg.keep_alive(bool) -- allow/forbid to use http keep-alive for this request + mg.time([bool]) -- get the current unix timestamp with milliseconds + -- if bool is true then it is the time since startup + mg.trace(n,message,...) -- trace level n messages into tracefile + mg.uuid() -- generate a uuid + mg.random() -- get a random floating point number mg.request_info -- a table with the following request information + .content_length -- Request content-length as a float + .content_type -- Request content-type, nil otherwise + .request_link -- Requested link + .request_uri -- Request URI + .uri -- Local request URI + .path_info -- Request URI, nil otherwise + .status -- Request status code, nil otherwise .remote_addr -- IP address of the client as string .remote_port -- remote port number .server_port -- server port number .request_method -- HTTP method (e.g.: GET, POST) .http_version -- HTTP protocol version (e.g.: 1.1) - .uri -- resource name + .http_headers -- Table of HTTP headers + .num_headers -- Number of headers .query_string -- query string if present, nil otherwise - .script_name -- name of the Lua script + .script_name -- name of the Lua script, nil otherwise .https -- true if accessed by https://, false otherwise .remote_user -- user name if authenticated, nil otherwise + .auth_type -- Digest + .client_cert -- Table with ssl certificate infomation + .subject -- Certificate subject + .issuer -- Certificate issuer + .serial -- Certificate serial number + .finger -- Certificate finger + +If websocket and timers support is enabled then the following is also available: + + mg.set_timeout(fn,delay,[interval]) -- call function after delay at an interval + mg.set_interval(fn,delay,[interval]) -- call function after delay at an interval + mg.websocket_root -- a string that holds the websocket root connect (function): @@ -953,7 +1060,7 @@ or Lua Server Pages generating HTML content MAY skip the HTTP header lines. In this case, CivetWeb automatically creates a "200 OK"/"Content-Type: text/html" -reply header. In this case, the document should start with "" +reply header. In this case, the document must start with "" or " 0) { + _snprintf(path, pathlen, "%s\\%s", temppath, fname); + } else { + _snprintf(path, pathlen, "C:\\tmp\\%s", fname); + } #else - snprintf(path, pathlen, "/tmp/%s", filename); + snprintf(path, pathlen, "/tmp/%s", fname); #endif - return MG_FORM_FIELD_STORAGE_STORE; + + /* According to https://datatracker.ietf.org/doc/html/rfc7578#section-7: + * Do not overwrite existing files. + */ + { + FILE *ftest = fopen(path, "r"); + if (!ftest) { + return MG_FORM_FIELD_STORAGE_STORE; + } + fclose(ftest); + /* This is just simple demo code. More sophisticated code could add + * numbers to the file name to make filenames unique. However, most + * likely file upload will not end up in the temporary path, but in + * a user directory - multiple directories for multiple users that + * are logged into the web service. In this case, users might want + * to overwrite their own code. You need to adapt this example to + * your needs. + */ + } + + return MG_FORM_FIELD_STORAGE_SKIP; } return MG_FORM_FIELD_STORAGE_GET; } diff -Nru civetweb-1.13+dfsg/examples/https/civetweb.conf civetweb-1.15+dfsg/examples/https/civetweb.conf --- civetweb-1.13+dfsg/examples/https/civetweb.conf 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/examples/https/civetweb.conf 2021-09-01 08:46:33.000000000 +0000 @@ -1,5 +1,5 @@ # Instructions to run (on Linux) to reproduce test results: -# +# # 1) copy civetweb executable here (examples/https directory) # 2) sudo ./civetweb # @@ -23,8 +23,8 @@ # proper certificate. Don't use it for your public home page, but # consider it for your private remote access server. # 7) run civetweb, like above - or better create your own start script -# You are welcome to share your thoughts and experience on GitHub -# (or Google groups) - see README.md in CivetWeb main directory +# You are welcome to share your thoughts and experience on GitHub +# (see README.md in CivetWeb main directory). # Don't run as super user, switch back to a regular user run_as_user user @@ -48,7 +48,7 @@ ssl_cipher_list ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS # Tell all browsers to access this site only as HTTPS for the next 180 days -strict_transport_security_max_age 15552000 +strict_transport_security_max_age 15552000 # Set some HTTP security header, see https://securityheaders.io additional_header Content-Security-Policy: script-src 'self' diff -Nru civetweb-1.13+dfsg/examples/README.md civetweb-1.15+dfsg/examples/README.md --- civetweb-1.13+dfsg/examples/README.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/examples/README.md 2021-09-01 08:46:33.000000000 +0000 @@ -2,16 +2,40 @@ Examples ===== -Two examples show how to embed civetweb into a C ([embedded_c](https://github.com/civetweb/civetweb/tree/master/examples/embedded_c)) or a C++ ([embedded_cpp](https://github.com/civetweb/civetweb/tree/master/examples/embedded_cpp)) application. -The C++ wrapper only offers a subset of the full C API, thus the C example is more complete than the C++ example. These examples were not designed with security in mind, but to show how the API can be used in principle. For more information, see the [documentation](https://github.com/civetweb/civetweb/tree/master/docs). Some examples can also be found in the [test](https://github.com/civetweb/civetweb/tree/master/test) folder (but they are less documented and adapted to the needs of the test framework). +The ([embedded_c](https://github.com/civetweb/civetweb/tree/master/examples/embedded_c)) example shows +how to embed civetweb into a C or C++ application. -In addition, there is one example how to configure a HTTPS server, to comply with modern security standards ([https](https://github.com/civetweb/civetweb/tree/master/examples/https)). It does not hold any source, but only a configuration file and some documentation how to use it. - -The [multidomain](https://github.com/civetweb/civetweb/tree/master/examples/multidomain) example demonstrates how to host multiple domains with different HTTPS certificates. It uses the standalone server (civetweb.c + main.c) and existing certificates. - -The [ws_client](https://github.com/civetweb/civetweb/tree/master/examples/ws_client) example shows how to use the websocket client interface to communicate with an (external) websocket server. It uses the "echo demo" of [websocket.org](http://websocket.org/echo.html), and only works if this server is reachable. - -Some no longer maintained examples can be found in the ["obsolete"](https://github.com/civetweb/civetweb/tree/master/examples/_obsolete) folder. It is not guaranteed that they work in the current version - they are kept for reference, but might be removed in the future. +The ([embedded_cpp](https://github.com/civetweb/civetweb/tree/master/examples/embedded_cpp)) example +demonstrates embedding in a C++ application. It uses the C++ wrapper of the full C interface `civetweb.h`. +The C++ wrapper only offers a limited subset of the full C API. +Thus, the C example is more complete than the C++ example. + +These examples were not designed with security in mind, but to show how the API can be used in principle. +For more information, see the [documentation](https://github.com/civetweb/civetweb/tree/master/docs). +Some examples can also be found in the [test](https://github.com/civetweb/civetweb/tree/master/test) folder, +but they are less documented and adapted to some special needs of the test frameworks. + +The ([https](https://github.com/civetweb/civetweb/tree/master/examples/https)) example shows how to configure +a HTTPS server with improved security settings. +It does not hold any source, but only a configuration file and some documentation how to use it. + +The [multidomain](https://github.com/civetweb/civetweb/tree/master/examples/multidomain) example demonstrates +how to host multiple domains with different HTTPS certificates. +It uses the standalone server (civetweb.c + main.c) and existing certificates. + +The [ws_client](https://github.com/civetweb/civetweb/tree/master/examples/ws_client) example shows +how to use the websocket client interface to communicate with an (external) websocket server. +It uses the "echo demo" of [websocket.org](http://websocket.org/echo.html) and will work only if this server is reachable. All examples are subject to the MIT license (unless noted otherwise) - they come without warranty of any kind. +Note that the examples are only meant as a demonstration how to use CivetWeb. +The example codes are omitting some error checking and input validation for better readability of the source. +They are not as actively maintained and continuously developed as main source of the project +(include/civetweb.h, src/civetweb.c, src/*.inl). +Example codes undergo less quality management than the main source files of this project. +Examples are not checked and updated with every new version. +There are no repeated security assessment for the example codes, settings are not updated on a regular basis. + +Contributions to examples code are welcome, under the same conditions as contributions to the +main source code ([Contribution.md](https://github.com/civetweb/civetweb/blob/master/Contribution.md)). diff -Nru civetweb-1.13+dfsg/fuzztest/build_and_run.sh civetweb-1.15+dfsg/fuzztest/build_and_run.sh --- civetweb-1.13+dfsg/fuzztest/build_and_run.sh 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/fuzztest/build_and_run.sh 2021-09-01 08:46:33.000000000 +0000 @@ -1,24 +1,9 @@ #!/bin/sh -make clean -rm civetweb_fuzz? - -make WITH_ALL=1 TEST_FUZZ=1 -mv civetweb civetweb_fuzz1 -make WITH_ALL=1 TEST_FUZZ=2 -mv civetweb civetweb_fuzz2 -make WITH_ALL=1 TEST_FUZZ=3 -mv civetweb civetweb_fuzz3 - -echo "" -echo "=====================" -echo "== Build completed ==" -echo "=====================" -echo "" - -ls -halt civetweb* -echo "" -md5sum civetweb_fuzz* +################# +# call build.sh +$(dirname $0)/build.sh +################# echo "" echo "=====================" @@ -26,7 +11,7 @@ echo "=====================" echo "" -./civetweb_fuzz1 -max_total_time=600 -max_len=2048 fuzztest/url/ +./civetweb_fuzz1 -max_total_time=60 -max_len=2048 fuzztest/url/ echo "" echo "=====================" @@ -34,7 +19,7 @@ echo "=====================" echo "" -./civetweb_fuzz2 -max_total_time=600 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1/ +./civetweb_fuzz2 -max_total_time=60 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1/ echo "" echo "=====================" @@ -42,7 +27,7 @@ echo "=====================" echo "" -./civetweb_fuzz3 -max_total_time=600 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1c/ +./civetweb_fuzz3 -max_total_time=60 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1c/ echo "" echo "=====================" diff -Nru civetweb-1.13+dfsg/fuzztest/build.sh civetweb-1.15+dfsg/fuzztest/build.sh --- civetweb-1.13+dfsg/fuzztest/build.sh 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/fuzztest/build.sh 2021-09-01 08:46:33.000000000 +0000 @@ -3,9 +3,22 @@ make clean rm civetweb_fuzz? -make WITH_ALL=1 TEST_FUZZ=1 +make TEST_FUZZ=1 mv civetweb civetweb_fuzz1 -make WITH_ALL=1 TEST_FUZZ=2 +make TEST_FUZZ=2 mv civetweb civetweb_fuzz2 -make WITH_ALL=1 TEST_FUZZ=3 +make TEST_FUZZ=3 mv civetweb civetweb_fuzz3 + +echo "" +echo "=====================" +echo "== Build completed ==" +echo "=====================" +echo "" + +ls -halt civetweb* +md5sum civetweb_fuzz* + +echo "" +echo "=====================" +echo "" diff -Nru civetweb-1.13+dfsg/fuzztest/build_with_all.sh civetweb-1.15+dfsg/fuzztest/build_with_all.sh --- civetweb-1.13+dfsg/fuzztest/build_with_all.sh 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/fuzztest/build_with_all.sh 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,24 @@ +#!/bin/sh + +make clean +rm civetweb_fuzz? + +make WITH_ALL=1 TEST_FUZZ=1 +mv civetweb civetweb_fuzz1 +make WITH_ALL=1 TEST_FUZZ=2 +mv civetweb civetweb_fuzz2 +make WITH_ALL=1 TEST_FUZZ=3 +mv civetweb civetweb_fuzz3 + +echo "" +echo "=====================" +echo "== Build completed ==" +echo "=====================" +echo "" + +ls -halt civetweb* +md5sum civetweb_fuzz* + +echo "" +echo "=====================" +echo "" diff -Nru civetweb-1.13+dfsg/fuzztest/fuzzmain.c civetweb-1.15+dfsg/fuzztest/fuzzmain.c --- civetweb-1.13+dfsg/fuzztest/fuzzmain.c 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/fuzztest/fuzzmain.c 2021-09-01 08:46:33.000000000 +0000 @@ -1,3 +1,14 @@ +/********************************************************/ +/* */ +/* FUZZ TEST for civetweb.c */ +/* */ +/* Copyright (c) 2015-2020 the CivetWeb developers */ +/* */ +/* This file contains test code for fuzz tests. */ +/* It should not be used in production code. */ +/* */ +/********************************************************/ + #include "civetweb.h" #include #include @@ -19,177 +30,93 @@ typedef int SOCKET; #define closesocket(a) (close(a)) -#endif +#endif // not _WIN32 + + +/* Port configuration */ +unsigned short PORT_NUM_HTTP = 0; /* set dynamically */ + + +#define TESTabort() \ + { \ + fprintf(stderr, "!!! Precondition in test environment not met !!!\n"); \ + fprintf(stderr, "!!! aborting fuzz test in line %u !!!", __LINE__); \ + abort(); \ + } static uint64_t call_count = 0; -static struct mg_context *ctx; + +/********************************************************/ +/* Init CivetWeb server ... test with mock client */ +/********************************************************/ +#if defined(TEST_FUZZ1) || defined(TEST_FUZZ2) + +static struct mg_context *ctx = 0; static const char *OPTIONS[] = {"listening_ports", - "8080,8443s", + "0", /* port: auto */ "document_root", "fuzztest/docroot", - "ssl_certificate", - "resources/cert/server.pem", NULL, NULL}; +static void +civetweb_exit(void) +{ + printf("CivetWeb server exit\n"); + mg_stop(ctx); + ctx = 0; + test_sleep(5); +} + static void -init_civetweb(void) +civetweb_init(void) { struct mg_callbacks callbacks; + struct mg_server_port ports[8]; memset(&callbacks, 0, sizeof(callbacks)); + memset(&ports, 0, sizeof(ports)); ctx = mg_start(&callbacks, 0, OPTIONS); if (!ctx) { fprintf(stderr, "\nCivetWeb test server failed to start\n"); - abort(); + TESTabort(); } - /* Give server 5 seconds to start, before flooding with requests. - * Don't know if this is required for fuzz-tests, but it was helpful - * when testing starting/stopping the server multiple times in test - * container environments. */ - test_sleep(5); -} - - -struct tcp_func_prm { - SOCKET sock; -}; - - -struct tRESPONSE { - char data[4096]; - size_t size; -} RESPONSE; - - -static void * -tcp_func(void *arg) -{ - char req[1024 * 16]; - struct tcp_func_prm *ptcp_func_prm = (struct tcp_func_prm *)arg; - SOCKET svr = ptcp_func_prm->sock; - printf("Server ready, sock %i\n", svr); - -next_request : { - struct sockaddr_in cliadr; - socklen_t adrlen = sizeof(cliadr); - int buf_filled = 0; - int req_ready = 0; - - memset(&cliadr, 0, sizeof(cliadr)); - - SOCKET cli = accept(svr, (struct sockaddr *)&cliadr, &adrlen); - - if (cli == -1) { - int er = errno; - fprintf(stderr, "Error: Accept failed [%s]\n", strerror(er)); - test_sleep(1); - goto next_request; - } - - /* Read request */ - do { - int r = recv(cli, req + buf_filled, sizeof(req) - buf_filled - 1, 0); - if (r > 0) { - buf_filled += r; - req[buf_filled] = 0; - if (strstr(req, "\r\n\r\n") != NULL) { - req_ready = 1; - } - } else { - /* some error */ - int er = errno; - fprintf(stderr, "Error: Recv failed [%s]\n", strerror(er)); - test_sleep(1); - goto next_request; - } - } while (!req_ready); - - /* Request is complete here. - * Now send response */ - send(cli, RESPONSE.data, RESPONSE.size, MSG_NOSIGNAL); - - /* Close connection. */ - shutdown(cli, SHUT_RDWR); - closesocket(cli); - - /* done */ - goto next_request; -} - - free(arg); -} - - -static void -init_tcp(void) -{ - int r; - SOCKET sock = socket(AF_INET, SOCK_STREAM, 6); - if (sock == -1) { - r = errno; - fprintf(stderr, "Error: Cannot create socket [%s]\n", strerror(r)); - abort(); - } - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr("127.0.0.1"); - sin.sin_port = htons(8080); - r = bind(sock, (struct sockaddr *)&sin, sizeof(sin)); - if (r != 0) { - r = errno; - fprintf(stderr, "Error: Cannot bind [%s]\n", strerror(r)); - closesocket(sock); - abort(); - } - - r = listen(sock, 128); - if (r != 0) { - r = errno; - fprintf(stderr, "Error: Cannot listen [%s]\n", strerror(r)); - closesocket(sock); - abort(); + int ret = mg_get_server_ports(ctx, 8, ports); + if (ret != 1) { + fprintf(stderr, + "\nCivetWeb test server: cannot determine port number\n"); + TESTabort(); } - - pthread_t thread_id; - pthread_attr_t attr; - int result; - struct tcp_func_prm *thread_prm; - - thread_prm = (struct tcp_func_prm *)malloc(sizeof(struct tcp_func_prm)); - if (!thread_prm) { - fprintf(stderr, "Error: Out of memory\n"); - closesocket(sock); - abort(); + if (ports[0].is_ssl != 0) { + fprintf(stderr, + "\nCivetWeb fuzz test works on HTTP, not HTTPS.\n" + "TLS library should be fuzzed separately.\n"); + TESTabort(); } - thread_prm->sock = sock; + PORT_NUM_HTTP = ports[0].port; - (void)pthread_attr_init(&attr); - (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - result = pthread_create(&thread_id, &attr, tcp_func, (void *)thread_prm); - (void)pthread_attr_destroy(&attr); - if (result != 0) { - r = errno; - fprintf(stderr, "Error: Cannot create thread [%s]\n", strerror(r)); - closesocket(sock); - abort(); - } + printf("CivetWeb server running on port %i\n", (int)PORT_NUM_HTTP); + /* Give server 5 seconds to start, before flooding with requests. + * Don't know if this is required for fuzz-tests, but it was helpful + * when testing starting/stopping the server multiple times in test + * container environments. */ test_sleep(5); + atexit(civetweb_exit); } +#if defined(TEST_FUZZ1) static int -test_http_request(const char *server, - uint16_t port, - int use_ssl, - const char *uri) +test_civetweb_client(const char *server, + uint16_t port, + int use_ssl, + const char *uri) { /* Client var */ struct mg_connection *client; @@ -283,7 +210,7 @@ if (call_count == 0) { memset(URI, 0, sizeof(URI)); - init_civetweb(); + civetweb_init(); } call_count++; @@ -294,15 +221,17 @@ return 1; } - return test_http_request("127.0.0.1", 8080, 0, URI); + return test_civetweb_client("127.0.0.1", PORT_NUM_HTTP, 0, URI); } +#endif +#if defined(TEST_FUZZ2) static int LLVMFuzzerTestOneInput_REQUEST(const uint8_t *data, size_t size) { if (call_count == 0) { - init_civetweb(); + civetweb_init(); } call_count++; @@ -317,7 +246,7 @@ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); - sin.sin_port = htons(8080); + sin.sin_port = htons(PORT_NUM_HTTP); r = connect(sock, (struct sockaddr *)&sin, sizeof(sin)); if (r != 0) { r = errno; @@ -328,7 +257,7 @@ char trash[1024]; r = send(sock, data, size, 0); - if (r != size) { + if (r != (int)size) { fprintf(stderr, "Warning: %i bytes sent (TODO: Repeat)\n", r); } @@ -345,6 +274,176 @@ max_data_read = data_read; printf("GOT data: %i\n", data_read); } + return 0; +} +#endif + +#endif // defined(TEST_FUZZ1) || defined(TEST_FUZZ2) + + +/********************************************************/ +/* Init mock server ... test with CivetWeb client */ +/********************************************************/ +#if defined(TEST_FUZZ3) + +struct tcp_func_prm { + SOCKET sock; +}; + +struct tRESPONSE { + char data[4096]; + size_t size; +} RESPONSE; + + +volatile int mock_server_stop_flag = 0; + +static void +mock_server_exit(void) +{ + printf("MOCK server exit\n"); + mock_server_stop_flag = 1; + test_sleep(5); +} + + +static void * +mock_server_thread(void *arg) +{ + char req[1024 * 16]; + SOCKET svr = (SOCKET)(-1); + + /* Get thread parameters and free arg */ + { + struct tcp_func_prm *ptcp_func_prm = (struct tcp_func_prm *)arg; + svr = ptcp_func_prm->sock; + free(arg); + } + + mock_server_stop_flag = 0; + printf("MOCK server ready, sock %i\n", svr); + +next_request: + while (!mock_server_stop_flag) { + struct sockaddr_in cliadr; + socklen_t adrlen = sizeof(cliadr); + int buf_filled = 0; + int req_ready = 0; + + memset(&cliadr, 0, sizeof(cliadr)); + + SOCKET cli = accept(svr, (struct sockaddr *)&cliadr, &adrlen); + + if (cli == -1) { + int er = errno; + fprintf(stderr, "Error: Accept failed [%s]\n", strerror(er)); + test_sleep(1); + goto next_request; + } + + /* Read request */ + do { + int r = + recv(cli, req + buf_filled, sizeof(req) - buf_filled - 1, 0); + if (r > 0) { + buf_filled += r; + req[buf_filled] = 0; + if (strstr(req, "\r\n\r\n") != NULL) { + req_ready = 1; + } + } else { + /* some error */ + int er = errno; + fprintf(stderr, "Error: Recv failed [%s]\n", strerror(er)); + test_sleep(1); + goto next_request; + } + } while (!req_ready); + + /* Request is complete here. + * Now send response */ + send(cli, RESPONSE.data, RESPONSE.size, MSG_NOSIGNAL); + + /* Close connection. */ + shutdown(cli, SHUT_RDWR); + closesocket(cli); + } + return 0; +} + + +static void +mock_server_init(void) +{ + int r; + int bind_success = 0; + SOCKET sock = socket(AF_INET, SOCK_STREAM, 6); + if (sock == -1) { + r = errno; + fprintf(stderr, "Error: Cannot create socket [%s]\n", strerror(r)); + TESTabort(); + } + + for (PORT_NUM_HTTP = 1024; PORT_NUM_HTTP != 0; PORT_NUM_HTTP++) { + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + sin.sin_port = htons(PORT_NUM_HTTP); + r = bind(sock, (struct sockaddr *)&sin, sizeof(sin)); + if (r == 0) { + bind_success = 1; + break; + } + r = errno; + fprintf(stderr, "Warning: Cannot bind [%s]\n", strerror(r)); + } + + if (!bind_success) { + fprintf(stderr, "Error: Cannot bind to any port\n"); + closesocket(sock); + TESTabort(); + } + + printf("MOCK server running on port %i\n", (int)PORT_NUM_HTTP); + + r = listen(sock, 128); + if (r != 0) { + r = errno; + fprintf(stderr, "Error: Cannot listen [%s]\n", strerror(r)); + closesocket(sock); + TESTabort(); + } + + pthread_t thread_id; + pthread_attr_t attr; + int result; + struct tcp_func_prm *thread_prm; + + thread_prm = (struct tcp_func_prm *)malloc(sizeof(struct tcp_func_prm)); + if (!thread_prm) { + fprintf(stderr, "Error: Out of memory\n"); + closesocket(sock); + TESTabort(); + } + thread_prm->sock = sock; + + (void)pthread_attr_init(&attr); + (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + result = pthread_create(&thread_id, + &attr, + mock_server_thread, + (void *)thread_prm); + (void)pthread_attr_destroy(&attr); + if (result != 0) { + r = errno; + fprintf(stderr, "Error: Cannot create thread [%s]\n", strerror(r)); + closesocket(sock); + TESTabort(); + } + + test_sleep(3); + atexit(mock_server_exit); } @@ -352,7 +451,7 @@ LLVMFuzzerTestOneInput_RESPONSE(const uint8_t *data, size_t size) { if (call_count == 0) { - init_tcp(); + mock_server_init(); } call_count++; @@ -365,8 +464,8 @@ char errbuf[256]; - struct mg_connection *conn = - mg_connect_client("127.0.0.1", 8080, 0, errbuf, sizeof(errbuf)); + struct mg_connection *conn = mg_connect_client( + "127.0.0.1", PORT_NUM_HTTP, 0, errbuf, sizeof(errbuf)); if (!conn) { printf("Connect error: %s\n", errbuf); test_sleep(1); @@ -377,13 +476,22 @@ int r = mg_get_response(conn, errbuf, sizeof(errbuf), 1000); const struct mg_response_info *ri = mg_get_response_info(conn); + (void)r; + (void)ri; + mg_close_connection(conn); return 0; } +#endif // defined(TEST_FUZZ3) + +/********************************************************/ +/* MAIN for fuzztest */ +/********************************************************/ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +// warning: no previous prototype for function 'LLVMFuzzerTestOneInput' -/* MAIN for fuzztest */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { diff -Nru civetweb-1.13+dfsg/fuzztest/README.txt civetweb-1.15+dfsg/fuzztest/README.txt --- civetweb-1.13+dfsg/fuzztest/README.txt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/fuzztest/README.txt 2021-09-01 08:46:33.000000000 +0000 @@ -24,7 +24,12 @@ * Need "sudo" for container? (ASAN seems to needs it on WSL test) * let "make" create "civetweb_fuzz#" instead of "mv" * useful initial corpus and directory - * Planned additional fuzz test: + * Planned additional fuzz test: * vary HTTP2 request for HTTP2 server (in HTTP2 feature branch) * use internal function to bypass socket (bottleneck) * where to put fuzz corpus? + +Note: +This test first starts a server, then launches an attack to this local server. +If you run this test on a system with endpoint protection software or some web traffic inspector installed, +this protection software may detect thousands of alarms during this test. diff -Nru civetweb-1.13+dfsg/include/CivetServer.h civetweb-1.15+dfsg/include/CivetServer.h --- civetweb-1.13+dfsg/include/CivetServer.h 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/include/CivetServer.h 2021-09-01 08:46:33.000000000 +0000 @@ -68,6 +68,18 @@ virtual bool handleGet(CivetServer *server, struct mg_connection *conn); /** + * Callback method for GET request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handleGet(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for POST request. * * @param server - the calling server @@ -77,6 +89,18 @@ virtual bool handlePost(CivetServer *server, struct mg_connection *conn); /** + * Callback method for POST request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handlePost(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for HEAD request. * * @param server - the calling server @@ -86,6 +110,18 @@ virtual bool handleHead(CivetServer *server, struct mg_connection *conn); /** + * Callback method for HEAD request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handleHead(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for PUT request. * * @param server - the calling server @@ -95,6 +131,18 @@ virtual bool handlePut(CivetServer *server, struct mg_connection *conn); /** + * Callback method for PUT request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handlePut(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for DELETE request. * * @param server - the calling server @@ -104,6 +152,18 @@ virtual bool handleDelete(CivetServer *server, struct mg_connection *conn); /** + * Callback method for DELETE request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handleDelete(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for OPTIONS request. * * @param server - the calling server @@ -113,6 +173,18 @@ virtual bool handleOptions(CivetServer *server, struct mg_connection *conn); /** + * Callback method for OPTIONS request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handleOptions(CivetServer *server, + struct mg_connection *conn, + int *status_code); + + /** * Callback method for PATCH request. * * @param server - the calling server @@ -120,6 +192,18 @@ * @returns true if implemented, false otherwise */ virtual bool handlePatch(CivetServer *server, struct mg_connection *conn); + + /** + * Callback method for PATCH request. + * + * @param server - the calling server + * @param conn - the connection information + * @param http - pointer to return status code + * @returns true if implemented, false otherwise + */ + virtual bool handlePatch(CivetServer *server, + struct mg_connection *conn, + int *status_code); }; /** @@ -404,6 +488,13 @@ const std::string &headerName); /** + * getMethod(struct mg_connection *conn) + * @param conn - the connection information + * @returns method of HTTP request + */ + static const char *getMethod(struct mg_connection *conn); + + /** * getParam(struct mg_connection *conn, const char *, std::string &, size_t) * * Returns a query which contained in the supplied buffer. The diff -Nru civetweb-1.13+dfsg/include/civetweb.h civetweb-1.15+dfsg/include/civetweb.h --- civetweb-1.13+dfsg/include/civetweb.h 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/include/civetweb.h 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2020 the Civetweb developers +/* Copyright (c) 2013-2021 the Civetweb developers * Copyright (c) 2004-2013 Sergey Lyubka * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,9 +23,9 @@ #ifndef CIVETWEB_HEADER_INCLUDED #define CIVETWEB_HEADER_INCLUDED -#define CIVETWEB_VERSION "1.13" +#define CIVETWEB_VERSION "1.15" #define CIVETWEB_VERSION_MAJOR (1) -#define CIVETWEB_VERSION_MINOR (13) +#define CIVETWEB_VERSION_MINOR (15) #define CIVETWEB_VERSION_PATCH (0) #ifndef CIVETWEB_API @@ -98,8 +98,13 @@ /* Will only work, if USE_ZLIB is set. */ MG_FEATURES_COMPRESSION = 0x200u, - /* Collect server status information. */ - /* Will only work, if USE_SERVER_STATS is set. */ + /* HTTP/2 support enabled. */ + MG_FEATURES_HTTP2 = 0x400u, + + /* Support unix domain sockets. */ + MG_FEATURES_X_DOMAIN_SOCKET = 0x800u, + + /* Bit mask for all feature defines. */ MG_FEATURES_ALL = 0xFFFFu }; @@ -143,26 +148,30 @@ /* This structure contains information about the HTTP request. */ struct mg_request_info { - const char *request_method; /* "GET", "POST", etc */ - const char *request_uri; /* URL-decoded URI (absolute or relative, - * as in the request) */ - const char *local_uri; /* URL-decoded URI (relative). Can be NULL - * if the request_uri does not address a - * resource at the server host. */ -#if defined(MG_LEGACY_INTERFACE) /* 2017-02-04, deprecated 2014-09-14 */ - const char *uri; /* Deprecated: use local_uri instead */ -#endif - const char *http_version; /* E.g. "1.0", "1.1" */ - const char *query_string; /* URL part after '?', not including '?', or - NULL */ - const char *remote_user; /* Authenticated user, or NULL if no auth - used */ - char remote_addr[48]; /* Client's IP address as a string. */ + const char *request_method; /* "GET", "POST", etc */ + const char *request_uri; /* URL-decoded URI (absolute or relative, + * as in the request) */ + const char *local_uri_raw; /* URL-decoded URI (relative). Can be NULL + * if the request_uri does not address a + * resource at the server host. */ + const char *local_uri; /* Same as local_uri_raw, however, cleaned + * so a path like + * allowed_dir/../forbidden_file + * is not possible. */ + const char *http_version; /* E.g. "1.0", "1.1" */ + const char *query_string; /* URL part after '?', not including '?', or + NULL */ + const char *remote_user; /* Authenticated user, or NULL if no auth + used */ + char remote_addr[48]; /* Client's IP address as a string. */ long long content_length; /* Length (in bytes) of the request body, can be -1 if no length was given. */ - int remote_port; /* Client's port */ - int is_ssl; /* 1 if SSL-ed, 0 if not */ + int remote_port; /* Port at client side */ + int server_port; /* Port at server side (one of the listening + ports) */ + int is_ssl; /* 1 if HTTPS or WS is used (SSL/TLS used), + 0 if not */ void *user_data; /* User data pointer passed to mg_start() */ void *conn_data; /* Connection-specific user data */ @@ -194,7 +203,6 @@ /* Client certificate information (part of mg_request_info) */ -/* New nomenclature. */ struct mg_client_cert { void *peer_cert; const char *subject; @@ -203,16 +211,6 @@ const char *finger; }; -#if defined(MG_LEGACY_INTERFACE) /* 2017-10-05 */ -/* Old nomenclature. */ -struct client_cert { - const char *subject; - const char *issuer; - const char *serial; - const char *finger; -}; -#endif - /* This structure needs to be passed to mg_start(), to let civetweb know which callbacks to invoke. For a detailed description, see @@ -318,14 +316,20 @@ application-maintained list of clients. Using this callback for websocket connections is deprecated: Use mg_set_websocket_handler instead. - - Connection specific data: - If memory has been allocated for the connection specific user data - (mg_request_info->conn_data, mg_get_user_connection_data), - this is the last chance to free it. */ void (*connection_close)(const struct mg_connection *); + /* Called after civetweb has closed a connection. The per-context mutex is + locked when this is invoked. + + Connection specific data: + If memory has been allocated for the connection specific user data + (mg_request_info->conn_data, mg_get_user_connection_data), + this is the last chance to free it. + */ + void (*connection_closed)(const struct mg_connection *); + + /* init_lua is called when civetweb is about to serve Lua server page. exit_lua is called when the Lua processing is complete. Both will work only if Lua support is enabled. @@ -452,7 +456,6 @@ CIVETWEB_API void mg_stop(struct mg_context *); -#if defined(MG_EXPERIMENTAL_INTERFACES) /* Add an additional domain to an already running web server. * * Parameters: @@ -472,7 +475,6 @@ */ CIVETWEB_API int mg_start_domain(struct mg_context *ctx, const char **configuration_options); -#endif /* mg_request_handler @@ -559,7 +561,7 @@ */ struct mg_websocket_subprotocols { int nb_subprotocols; - char **subprotocols; + const char **subprotocols; }; /* mg_set_websocket_handler @@ -643,7 +645,14 @@ /* Set user data for the current connection. */ -/* Note: This function is deprecated. Use the init_connection callback +/* Note: CivetWeb callbacks use "struct mg_connection *conn" as input + when mg_read/mg_write callbacks are allowed in the callback, + while "const struct mg_connection *conn" is used as input in case + calling mg_read/mg_write is not allowed. + Setting the user connection data will modify the connection + object represented by mg_connection *, but it will not read from + or write to the connection. */ +/* Note: An alternative is to use the init_connection callback instead to initialize the user connection data pointer. It is reccomended to supply a pointer to some user defined data structure as conn_data initializer in init_connection. In case it is required @@ -651,7 +660,7 @@ data pointer in the user defined data structure and modify that pointer. In either case, after the init_connection callback, only calls to mg_get_user_connection_data should be required. */ -CIVETWEB_API void mg_set_user_connection_data(struct mg_connection *conn, +CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn, void *data); @@ -679,22 +688,8 @@ const char *default_value; }; -/* Old nomenclature */ -#if defined(MG_LEGACY_INTERFACE) /* 2017-10-05 */ -enum { - CONFIG_TYPE_UNKNOWN = 0x0, - CONFIG_TYPE_NUMBER = 0x1, - CONFIG_TYPE_STRING = 0x2, - CONFIG_TYPE_FILE = 0x3, - CONFIG_TYPE_DIRECTORY = 0x4, - CONFIG_TYPE_BOOLEAN = 0x5, - CONFIG_TYPE_EXT_PATTERN = 0x6, - CONFIG_TYPE_STRING_LIST = 0x7, - CONFIG_TYPE_STRING_MULTILINE = 0x8 -}; -#endif -/* New nomenclature */ +/* Configuration types */ enum { MG_CONFIG_TYPE_UNKNOWN = 0x0, MG_CONFIG_TYPE_NUMBER = 0x1, @@ -739,15 +734,6 @@ struct mg_server_port *ports); -#if defined(MG_LEGACY_INTERFACE) /* 2017-04-02 */ -/* Deprecated: Use mg_get_server_ports instead. */ -CIVETWEB_API size_t mg_get_ports(const struct mg_context *ctx, - size_t size, - int *ports, - int *ssl); -#endif - - /* Add, edit or delete the entry in the passwords file. * * This function allows an application to manipulate .htpasswd files on the @@ -772,6 +758,21 @@ const char *password); +/* Same as mg_modify_passwords_file, but instead of the plain-text + * password, the HA1 hash is specified. The plain-text password is + * not made known to civetweb. + * + * The HA1 hash is the MD5 checksum of a "user:realm:password" string + * in lower-case hex format. For example, if the user name is "myuser", + * the realm is "myrealm", and the password is "secret", then the HA1 is + * e67fd3248b58975c3e89ff18ecb75e2f. + */ +CIVETWEB_API int mg_modify_passwords_file_ha1(const char *passwords_file_name, + const char *realm, + const char *user, + const char *ha1); + + /* Return information associated with the request. * Use this function to implement a server and get data about a request * from a HTTP/HTTPS client. @@ -852,19 +853,7 @@ CIVETWEB_API void mg_unlock_context(struct mg_context *ctx); -/* Opcodes, from http://tools.ietf.org/html/rfc6455 */ -#if defined(MG_LEGACY_INTERFACE) /* 2017-10-05 */ -enum { - WEBSOCKET_OPCODE_CONTINUATION = 0x0, - WEBSOCKET_OPCODE_TEXT = 0x1, - WEBSOCKET_OPCODE_BINARY = 0x2, - WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8, - WEBSOCKET_OPCODE_PING = 0x9, - WEBSOCKET_OPCODE_PONG = 0xa -}; -#endif - -/* New nomenclature */ +/* WebSocket OpcCodes, from http://tools.ietf.org/html/rfc6455 */ enum { MG_WEBSOCKET_OPCODE_CONTINUATION = 0x0, MG_WEBSOCKET_OPCODE_TEXT = 0x1, @@ -874,6 +863,7 @@ MG_WEBSOCKET_OPCODE_PONG = 0xa }; + /* Macros for enabling compiler-specific checks for printf-like arguments. */ #undef PRINTF_FORMAT_STRING #if defined(_MSC_VER) && _MSC_VER >= 1400 @@ -1277,20 +1267,6 @@ /* Return values definition for the "field_found" callback in * mg_form_data_handler. */ -#if defined(MG_LEGACY_INTERFACE) /* 2017-10-05 */ -enum { - /* Skip this field (neither get nor store it). Continue with the - * next field. */ - FORM_FIELD_STORAGE_SKIP = 0x0, - /* Get the field value. */ - FORM_FIELD_STORAGE_GET = 0x1, - /* Store the field value into a file. */ - FORM_FIELD_STORAGE_STORE = 0x2, - /* Stop parsing this request. Skip the remaining fields. */ - FORM_FIELD_STORAGE_ABORT = 0x10 -}; -#endif -/* New nomenclature */ enum { /* Skip this field (neither get nor store it). Continue with the * next field. */ @@ -1421,6 +1397,19 @@ mg_websocket_close_handler close_func, void *user_data); +CIVETWEB_API struct mg_connection * +mg_connect_websocket_client_extensions(const char *host, + int port, + int use_ssl, + char *error_buffer, + size_t error_buffer_size, + const char *path, + const char *origin, + const char *extensions, + mg_websocket_data_handler data_func, + mg_websocket_close_handler close_func, + void *user_data); + /* Connect to a TCP server as a client (can be used to connect to a HTTP server) Parameters: @@ -1467,6 +1456,17 @@ mg_websocket_close_handler close_func, void *user_data); +CIVETWEB_API struct mg_connection * +mg_connect_websocket_client_secure_extensions( + const struct mg_client_options *client_options, + char *error_buffer, + size_t error_buffer_size, + const char *path, + const char *origin, + const char *extensions, + mg_websocket_data_handler data_func, + mg_websocket_close_handler close_func, + void *user_data); #if defined(MG_LEGACY_INTERFACE) /* 2019-11-02 */ enum { TIMEOUT_INFINITE = -1 }; @@ -1630,6 +1630,14 @@ mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen); +/* Disable HTTP keep-alive on a per-connection basis. + Reference: https://github.com/civetweb/civetweb/issues/727 + Parameters: + conn: Current connection handle. +*/ +CIVETWEB_API void mg_disable_connection_keep_alive(struct mg_connection *conn); + + #if defined(MG_EXPERIMENTAL_INTERFACES) /* Get connection information. Useful for server diagnosis. Parameters: @@ -1686,6 +1694,8 @@ CIVETWEB_API int mg_get_response2(struct mg_connection *conn, struct mg_error_data *error, int timeout); +#endif + CIVETWEB_API struct mg_context *mg_start2(struct mg_init_data *init, struct mg_error_data *error); @@ -1693,7 +1703,7 @@ CIVETWEB_API int mg_start_domain2(struct mg_context *ctx, const char **configuration_options, struct mg_error_data *error); -#endif + #ifdef __cplusplus } diff -Nru civetweb-1.13+dfsg/LICENSE.md civetweb-1.15+dfsg/LICENSE.md --- civetweb-1.13+dfsg/LICENSE.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/LICENSE.md 2021-09-01 08:46:33.000000000 +0000 @@ -11,7 +11,7 @@ ### Included with all features. -> Copyright (c) 2013-2020 The CivetWeb developers ([CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md)) +> Copyright (c) 2013-2021 The CivetWeb developers ([CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md)) > > Copyright (c) 2004-2013 Sergey Lyubka > @@ -45,7 +45,7 @@ http://www.lua.org/license.html -> Copyright (C) 1994-2015 Lua.org, PUC-Rio. +> Copyright (C) 1994-2020 Lua.org, PUC-Rio. > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal @@ -118,27 +118,29 @@ ### Included only if built with Lua support. -http://keplerproject.github.io/luafilesystem/license.html +https://github.com/keplerproject/luafilesystem/blob/master/LICENSE -> Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem) +> Copyright © 2003-2020 Kepler Project. > -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is +> Permission is hereby granted, free of charge, to any person +> obtaining a copy of this software and associated documentation +> files (the "Software"), to deal in the Software without +> restriction, including without limitation the rights to use, copy, +> modify, merge, publish, distribute, sublicense, and/or sell copies +> of the Software, and to permit persons to whom the Software is > furnished to do so, subject to the following conditions: > -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. +> The above copyright notice and this permission notice shall be +> included in all copies or substantial portions of the Software. > -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +> ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +> SOFTWARE. LuaXML License @@ -188,9 +190,9 @@ > =============== > Duktape license > =============== -> +> > (http://opensource.org/licenses/MIT) -> +> > Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst) > > Permission is hereby granted, free of charge, to any person obtaining a copy diff -Nru civetweb-1.13+dfsg/README.md civetweb-1.15+dfsg/README.md --- civetweb-1.13+dfsg/README.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/README.md 2021-09-01 08:46:33.000000000 +0000 @@ -6,9 +6,9 @@ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![GitHub contributors](https://img.shields.io/github/contributors/civetweb/civetweb.svg)](https://github.com/civetweb/civetweb/blob/master/CREDITS.md) -Continuous integration for Linux and macOS ([Travis CI](https://travis-ci.org/civetweb/civetweb)): +Continuous integration for Linux and macOS ([Travis CI](https://app.travis-ci.com/github/civetweb/civetweb)): -[![Travis Build Status](https://travis-ci.org/civetweb/civetweb.svg?branch=master)](https://travis-ci.org/civetweb/civetweb) +[![Travis Build Status](https://api.travis-ci.com/civetweb/civetweb.svg?branch=master)](https://app.travis-ci.com/github/civetweb/civetweb) Continuous integration for Windows ([AppVeyor](https://ci.appveyor.com/project/civetweb/civetweb)): @@ -55,10 +55,11 @@ Trouble tickets should be filed on GitHub [https://github.com/civetweb/civetweb/issues](https://github.com/civetweb/civetweb/issues) -Announcements are at Google Groups -[https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb). -Some older support and discussion threads are there as well. -However, recently support questions and discussions are usually [GitHub issues](https://github.com/civetweb/civetweb/issues). +New releases are announced at Google Groups +[https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb) + +Formerly some support question and discussion threads have been at [Google groups](https://groups.google.com/d/forum/civetweb). +Recent questions and discussions use [GitHub issues](https://github.com/civetweb/civetweb/issues). Source releases can be found on GitHub [https://github.com/civetweb/civetweb/releases](https://github.com/civetweb/civetweb/releases) @@ -85,6 +86,7 @@ - [docs/OpenSSL.md](https://github.com/civetweb/civetweb/blob/master/docs/OpenSSL.md) - Adding HTTPS (SSL/TLS) support using OpenSSL. - [API documentation](https://github.com/civetweb/civetweb/tree/master/docs/api) - Additional documentation on the civetweb application programming interface ([civetweb.h](https://github.com/civetweb/civetweb/blob/master/include/civetweb.h)). - [RELEASE_NOTES.md](https://github.com/civetweb/civetweb/blob/master/RELEASE_NOTES.md) - Release Notes +- [SECURITY.md](https://github.com/civetweb/civetweb/blob/master/SECURITY.md) - Security Policy - [LICENSE.md](https://github.com/civetweb/civetweb/blob/master/LICENSE.md) - Copyright License @@ -107,7 +109,7 @@ - Scripting and database support (CGI, SQLite database, Lua Server Pages, Server side Lua scripts, Server side JavaScript). This provides a ready to go, powerful web development platform in a one - single-click executable with **no dependencies**. + single-click executable with **no dependencies**.0 - Support for CGI, SSI, HTTP digest (MD5) authorization, WebSocket, WebDAV. - HTTPS (SSL/TLS) support using [OpenSSL](https://www.openssl.org/). @@ -137,23 +139,39 @@ [![Duktape](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/duktape-logo.png "Duktape Logo")](http://duktape.org) +### Optional depencencies + +[![zlib](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/zlib3d-b1.png "zlib Logo")](https://zlib.net) + +[![OpenSSL](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/OpenSSL_logo.png "OpenSSL Logo")](https://www.openssl.org/) + +[![Mbed TLS](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/mbedTLS_logo.png "mbedTLS Logo")](https://github.com/ARMmbed/mbedtls) + + + Support ------- -This project is very easy to install and use. +This project is very easy to install and use. Please read the [documentation](https://github.com/civetweb/civetweb/blob/master/docs/) and have a look at the [examples](https://github.com/civetweb/civetweb/blob/master/examples/). -Some information may be found on the [mailing list](https://groups.google.com/d/forum/civetweb), -However, since questions and discussions moved to [GitHub issues](https://github.com/civetweb/civetweb/issues), information there may be out of date. +Recent questions and discussions usually use [GitHub issues](https://github.com/civetweb/civetweb/issues). +Some old information may be found on the [mailing list](https://groups.google.com/d/forum/civetweb), +but this information may be outdated. + +Feel free to create a GitHub issue for bugs, feature requests, questions, suggestions or if you want to share tips and tricks. +When creating an issues for a bug, add enough description to reproduce the issue - at least add CivetWeb version and operating system. +Please see also the guidelines for [Contributions](https://github.com/civetweb/civetweb/blob/master/docs/Contribution.md) and the [Security Policy](https://github.com/civetweb/civetweb/blob/master/SECURITY.md) Note: We do not take any liability or warranty for any linked contents. Visit these pages and try the community support suggestions at your own risk. Any link provided in this project (including source and documentation) is provided in the hope that this information will be helpful. However, we cannot accept any responsibility for any content on an external page. + Contributions ---------------- +------------- Contributions are welcome provided all contributions carry the MIT license. @@ -164,11 +182,12 @@ Some guidelines can be found in [docs/Contribution.md](https://github.com/civetweb/civetweb/blob/master/docs/Contribution.md). -### Authors +Authors +------- CivetWeb has been forked from the last MIT version of Mongoose in 2013. Since then, CivetWeb has seen many improvements from various authors -(Copyright (c) 2013-2020 the CivetWeb developers, MIT license). +(Copyright (c) 2013-2021 the CivetWeb developers, MIT license). A list of authors can be found in [CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md). diff -Nru civetweb-1.13+dfsg/RELEASE_NOTES.md civetweb-1.15+dfsg/RELEASE_NOTES.md --- civetweb-1.13+dfsg/RELEASE_NOTES.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/RELEASE_NOTES.md 2021-09-01 08:46:33.000000000 +0000 @@ -1,3 +1,49 @@ +Release Notes v1.15 +=== +### Objectives: *bug fixes, remove legacy interfaces* + +Changes +------- + +- New configuration for URL decoding +- Sanitize filenames in handle form +- Example "embedded_c.c": Do not overwrite files (possible security issue) +- Remove obsolete examples +- Remove "experimental" label for some features +- Remove MG_LEGACY_INTERFACE that have been declared obsolete in 2017 or earlier +- Modifications to build scripts, required due to changes in the test environment +- Unix domain socket support fixed +- Fixes for NO_SSL_DL +- Fixes for some warnings / static code analysis +- Update version number + + +Release Notes v1.14 +=== +### Objectives: *mbedTLS, Lua API enhancements, log filtering* + +Changes +------- + +- Change SSL default setting to use TLS 1.2 as minimum (set config if you need an earlier version) +- Add local_uri_raw field (not sanitized URI) to request_info +- Additional API functions and a callback after closing connections +- Allow mbedTLS as OpenSSL alternative (basic functionality) +- Add OpenSSL 3.0 support (OpenSSL 3.0 Alpha 13) +- Support UNIX/Linux domain sockets +- Fuzz tests and ossfuzz integration +- Compression for websockets +- Restructure some source files +- Improve documentation +- Fix HTTP range requests +- Add some functions for Lua scripts/LSP +- Build system specific fixes (CMake, MinGW) +- Update 3rd party components (Lua, lfs, sqlite) +- Allow Lua background script to use timers, format and filter logs +- Remove WinCE code +- Update version number + + Release Notes v1.13 === ### Objectives: *Various updates and fixes, additional API functions* @@ -212,6 +258,7 @@ - Fix bug in timer logic (for Lua Websockets) - Updated version number + Release Notes v1.8 === ### Objectives: *CMake integration and continuous integration tests, Support client certificates, bug fixes* @@ -260,6 +307,7 @@ - Add status badges to the GitHub project main page - Updated version number + Release Notes v1.7 === ### Objectives: *Examples, documentation, additional API functions, some functions rewritten, bug fixes and updates* @@ -307,6 +355,7 @@ - Fix compiler warnings - Updated version number + Release Notes v1.6 === ### Objectives: *Enhance Lua support, configuration dialog for windows, new examples, bug fixes and updates* @@ -350,6 +399,7 @@ - Fixed Posix locking functions for Windows (bel2125) - Updated version number + Release Notes v1.5 === ### Objectives: *Bug fixes and updates, repository restoration* @@ -383,6 +433,7 @@ - Updated version numbers. - Added contributor credits file. + Release Notes v1.4 === ### Objectives: *New URI handler interface, feature enhancements, C++ extensions* @@ -408,6 +459,7 @@ - Conformed source files to UNIX line endings for consistency. - Unified the coding style to improve reability. + Release Notes v1.3 === ### Objectives: *Buildroot Integration* @@ -420,6 +472,7 @@ - Updated documentation - Updated Buildroot config example + Release Notes v1.2 === ### Objectives: *Installation Improvements, buildroot, cross compile support* @@ -444,6 +497,7 @@ - The prebuilt Window's version requires [Visual C++ Redistributable for Visual Studio 2012](http://www.microsoft.com/en-us/download/details.aspx?id=30679) + Release Notes v1.1 === ### Objectives: *Build, Documentation, License Improvements* @@ -488,6 +542,7 @@ - Build changes may impact current users. + As with any change of this type, changes may impact some users. + Release Notes v1.0 === diff -Nru civetweb-1.13+dfsg/resources/cert/client.crt civetweb-1.15+dfsg/resources/cert/client.crt --- civetweb-1.13+dfsg/resources/cert/client.crt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/client.crt 2021-09-01 08:46:33.000000000 +0000 @@ -1,19 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCFpskbTEyGpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIwNVoXDTI3MDkwMTE5MjIwNVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFvW3XFqAV05tV6HnPnSELEk6t3 -8aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o3MkIM3sUxUtaR6x0RMZ+sIX4 -XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKYZJyTr/oR31NmlIPU/47s74U6 -rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMBuTJIAmG2qawXaetjLi/NBwNS -d0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUdlYbiemcUHn18hZjxPVZLbtY8 -gQldrWyMZkVabSZjuIH3IKcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUZsxxYVK -l0tH8E0FCnRJTvG6gjOeiqJRIk7Mmg+hfFZK/ewqBixxg1OBM/xmPXfnI/ULRz74 -UMXnyDIsGakzrFDqWqPt3xots35yHHo2ZkVao6gV4qx0Reu86qeN5iRvG0EjoGMD -7XRaw56E0XhvMBJW1CiUg944HSw4ptJli0dJCYa+P9s1Fop3lA0d9+dwKMKUyCDr -yBz4XjyO9jXSQC/t0fkxC4gHhdH/ZaAq0Lem6Xxc40ZwoVc1+dHWFxn8d6L/RYvb -16gOuw6s2Xt9h2K8OFKzehOgNZAkI2oUELRFUx9Wc8/Bcl6uEkBmPHRqeX5l35jo -ztBrpAEsCy0cGg== +MIIDaTCCAlECFF2XPwtpHCT5muePSSzNyKO4vCEqMA0GCSqGSIb3DQEBCwUAMHEx +CzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0yMTA0MDQxODM5NTNaFw0zMTA0MDIxODM5NTNa +MHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxv +Y2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3Qx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMuj86SsMnySSmawj0G4f5EKBAvehOH5RHCZ5nPMmtOq5sLE+GtfGs47iRZF +83yjszACCAXPkKfSOdk9TuemrvaE+AUHlGQovrWzAxhjzIgXyMWGclj1pYmoOSG7 +Bj0iF/D3ITdrDjwFCCv7fWzYe9B4jvDMBlBk6Gs6FnC8Lwj741sJU4L1Q2u0gEUP +YC7+IBYru6gHbzfE4r1twkLrjLvlYxwayQNgTs07ltg+13SvGNdE9A36CYVe/Z2E +a6cCM0jXrce+WBe5VKi9ZFPIY+7GoHSxgD/sZycw5O9AbqP73kcW1jpdaoDffRz7 +tjK9CJbyDhxrXDU28kwd77s8zU0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAMrhe +SbG42fSy6azuuS3ffHcVydRIKT4Ve4PMTglWZxS6zVpY9y02fIiRpOA1qwm/gCzW +Blbwm09VRYwY4cLiXuYwrdnBhkBBLuTsTjfCa5ZtwdE8PGvCVGhaOLiAcC+tRYfX +vuuH/pvE2dlCEq7wcOFxpzDuTRBjTfJhrObVELIUrpWrQoi6aPsaVEHo3fpFL6Uh +ecgYq2MoxvsyT4D77AmfAjd0FcasaZ0S6FE9LeRqleWIYuGvoxwMOQGgbGDtH8jJ +l5t9bCx1nAdNvoI7za709z0taKcPOpbb2uanPkB3OeUFpwiZ+TiYYMhNq7IlbYp6 +10v9W8+vIcCu9jvqhw== -----END CERTIFICATE----- diff -Nru civetweb-1.13+dfsg/resources/cert/client.csr civetweb-1.15+dfsg/resources/cert/client.csr --- civetweb-1.13+dfsg/resources/cert/client.csr 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/client.csr 2021-09-01 08:46:33.000000000 +0000 @@ -1,16 +1,17 @@ -----BEGIN CERTIFICATE REQUEST----- -MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx -ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFv -W3XFqAV05tV6HnPnSELEk6t38aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o -3MkIM3sUxUtaR6x0RMZ+sIX4XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKY -ZJyTr/oR31NmlIPU/47s74U6rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMB -uTJIAmG2qawXaetjLi/NBwNSd0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUd -lYbiemcUHn18hZjxPVZLbtY8gQldrWyMZkVabSZjuIH3IKcCAwEAAaAAMA0GCSqG -SIb3DQEBCwUAA4IBAQB/bapQm4nxXA01msL6nkjiVaeh/mj8Cr8sPFtQXVu+hxl9 -mjbisxDXwPhiFOiTlokQkINf+RMxQsVNr2y/sGZrSMimabwODDXnPpyir4b2WOWp -VQQWbgnMVnvgKsjBpLLDr8VnLBiQ3mED+2QV0bxxJSgvvEuiZx/BlCgiu77D/8kj -XUY/CXIBi00fIYigpRRdv2WtMQjtQe2fCSZZKOWu2ZWu2o24kEk28x5LO/WaJ4Ft -lUHFOIp/wkKz/US4mbdQaD0bsg7MirAyGrCmZIHqQDhdDWq+o/brI7N/8yOk3qwc -qPGkr9PYIPnuzZwStLJlPxKGXjCA40HpdmWA0kyc +MIICtjCCAZ4CAQAwcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDES +MBAGA1UEBwwJbG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsM +CWxvY2FsaG9zdDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAy6PzpKwyfJJKZrCPQbh/kQoEC96E4flEcJnmc8ya06rm +wsT4a18azjuJFkXzfKOzMAIIBc+Qp9I52T1O56au9oT4BQeUZCi+tbMDGGPMiBfI +xYZyWPWliag5IbsGPSIX8PchN2sOPAUIK/t9bNh70HiO8MwGUGToazoWcLwvCPvj +WwlTgvVDa7SARQ9gLv4gFiu7qAdvN8TivW3CQuuMu+VjHBrJA2BOzTuW2D7XdK8Y +10T0DfoJhV79nYRrpwIzSNetx75YF7lUqL1kU8hj7sagdLGAP+xnJzDk70Buo/ve +RxbWOl1qgN99HPu2Mr0IlvIOHGtcNTbyTB3vuzzNTQIDAQABoAAwDQYJKoZIhvcN +AQELBQADggEBALoq9WNaqSOE21nDasUcU4DYXn9aoxfzEErJw3dxWCvXhgW3RVZ8 +lIvtirClhwNV7NE+lArLEqTrBBxLeM2PkWHLST40I0ywrBnELvxZ/+mTWfpBhSMd ++byqpkis6UWvASIKMlni0cl/+/QNwdRwXtjlCMt9xvVEDXLQ6tvi4dwnhOSK/091 +f6a7326C8S4vOopurhZ61Weqn4z2b2HAybSwFGq38sch6ka/36/Q2CHpaeg0J02c +uHFqC139EH7boRV2Hz4pq+a+EiyqoQLllsIz5PMLKNbq1TxhihpVm0qcT4S0xj7S +Yqx4/jaNT+SYJqbLRmdCOkrW7ENyEs4TyPU= -----END CERTIFICATE REQUEST----- diff -Nru civetweb-1.13+dfsg/resources/cert/client.key civetweb-1.15+dfsg/resources/cert/client.key --- civetweb-1.13+dfsg/resources/cert/client.key 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/client.key 2021-09-01 08:46:33.000000000 +0000 @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/client.key.orig civetweb-1.15+dfsg/resources/cert/client.key.orig --- civetweb-1.13+dfsg/resources/cert/client.key.orig 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/client.key.orig 2021-09-01 08:46:33.000000000 +0000 @@ -1,30 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,161D2DE9FC3C5EE4 - -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 -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/client.pem civetweb-1.15+dfsg/resources/cert/client.pem --- civetweb-1.13+dfsg/resources/cert/client.pem 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/client.pem 2021-09-01 08:46:33.000000000 +0000 @@ -1,46 +1,48 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCFpskbTEyGpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIwNVoXDTI3MDkwMTE5MjIwNVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFvW3XFqAV05tV6HnPnSELEk6t3 -8aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o3MkIM3sUxUtaR6x0RMZ+sIX4 -XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKYZJyTr/oR31NmlIPU/47s74U6 -rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMBuTJIAmG2qawXaetjLi/NBwNS -d0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUdlYbiemcUHn18hZjxPVZLbtY8 -gQldrWyMZkVabSZjuIH3IKcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUZsxxYVK -l0tH8E0FCnRJTvG6gjOeiqJRIk7Mmg+hfFZK/ewqBixxg1OBM/xmPXfnI/ULRz74 -UMXnyDIsGakzrFDqWqPt3xots35yHHo2ZkVao6gV4qx0Reu86qeN5iRvG0EjoGMD -7XRaw56E0XhvMBJW1CiUg944HSw4ptJli0dJCYa+P9s1Fop3lA0d9+dwKMKUyCDr -yBz4XjyO9jXSQC/t0fkxC4gHhdH/ZaAq0Lem6Xxc40ZwoVc1+dHWFxn8d6L/RYvb -16gOuw6s2Xt9h2K8OFKzehOgNZAkI2oUELRFUx9Wc8/Bcl6uEkBmPHRqeX5l35jo -ztBrpAEsCy0cGg== +MIIDaTCCAlECFF2XPwtpHCT5muePSSzNyKO4vCEqMA0GCSqGSIb3DQEBCwUAMHEx +CzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0yMTA0MDQxODM5NTNaFw0zMTA0MDIxODM5NTNa +MHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxv +Y2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3Qx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMuj86SsMnySSmawj0G4f5EKBAvehOH5RHCZ5nPMmtOq5sLE+GtfGs47iRZF +83yjszACCAXPkKfSOdk9TuemrvaE+AUHlGQovrWzAxhjzIgXyMWGclj1pYmoOSG7 +Bj0iF/D3ITdrDjwFCCv7fWzYe9B4jvDMBlBk6Gs6FnC8Lwj741sJU4L1Q2u0gEUP +YC7+IBYru6gHbzfE4r1twkLrjLvlYxwayQNgTs07ltg+13SvGNdE9A36CYVe/Z2E +a6cCM0jXrce+WBe5VKi9ZFPIY+7GoHSxgD/sZycw5O9AbqP73kcW1jpdaoDffRz7 +tjK9CJbyDhxrXDU28kwd77s8zU0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAMrhe +SbG42fSy6azuuS3ffHcVydRIKT4Ve4PMTglWZxS6zVpY9y02fIiRpOA1qwm/gCzW +Blbwm09VRYwY4cLiXuYwrdnBhkBBLuTsTjfCa5ZtwdE8PGvCVGhaOLiAcC+tRYfX +vuuH/pvE2dlCEq7wcOFxpzDuTRBjTfJhrObVELIUrpWrQoi6aPsaVEHo3fpFL6Uh +ecgYq2MoxvsyT4D77AmfAjd0FcasaZ0S6FE9LeRqleWIYuGvoxwMOQGgbGDtH8jJ +l5t9bCx1nAdNvoI7za709z0taKcPOpbb2uanPkB3OeUFpwiZ+TiYYMhNq7IlbYp6 +10v9W8+vIcCu9jvqhw== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- Binary files /tmp/tmp1p6obe5f/HuhoIs93Hc/civetweb-1.13+dfsg/resources/cert/client.pfx and /tmp/tmp1p6obe5f/VnSAxQw8ZZ/civetweb-1.15+dfsg/resources/cert/client.pfx differ diff -Nru civetweb-1.13+dfsg/resources/cert/make_certs.sh civetweb-1.15+dfsg/resources/cert/make_certs.sh --- civetweb-1.13+dfsg/resources/cert/make_certs.sh 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/make_certs.sh 2021-09-01 08:46:33.000000000 +0000 @@ -1,10 +1,26 @@ #!/bin/sh -#using "pass" for every password +echo "Creating new certificates" +rm server.* client.* rootCA.* server_bkup.* +echo "Using 'pass' for every password" + + +echo "Generating a root CA ..." + +openssl genrsa -passout pass:pass -out rootCA.key 2048 +openssl req -passout pass:pass -new -key rootCA.key -out rootCA.csr -subj "/C=AA/ST=localhost/L=localhost/O=localhost/OU=localhost/CN=localhost" +# For a test certificate, use "AA" as "user assigned" language code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#AA + +cp rootCA.key rootCA.key.orig +openssl rsa -in rootCA.key.orig -out rootCA.key +openssl x509 -req -days 3651 -in rootCA.csr -signkey rootCA.key -out rootCA.crt +cp rootCA.crt rootCA.pem +cat rootCA.key >> rootCA.pem + echo "Generating client certificate ..." -openssl genrsa -des3 -out client.key 2048 -openssl req -new -key client.key -out client.csr +openssl genrsa -passout pass:pass -out client.key 2048 +openssl req -passout pass:pass -new -key client.key -out client.csr -subj "/C=AA/ST=localhost/L=localhost/O=localhost/OU=localhost/CN=localhost" cp client.key client.key.orig @@ -15,24 +31,32 @@ cp client.crt client.pem cat client.key >> client.pem -openssl pkcs12 -export -inkey client.key -in client.pem -name ClientName -out client.pfx +openssl pkcs12 -passout pass:pass -export -inkey client.key -in client.pem -name ClientName -out client.pfx echo "Generating first server certificate ..." -openssl genrsa -des3 -out server.key 2048 -openssl req -new -key server.key -out server.csr +openssl genrsa -passout pass:pass -out server.key 2048 +openssl req -passout pass:pass -new -key server.key -out server.csr -subj "/C=AA/ST=localhost/L=localhost/O=localhost/OU=localhost/CN=localhost" cp server.key server.key.orig openssl rsa -in server.key.orig -out server.key -openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt +echo "authorityKeyIdentifier=keyid,issuer" > server.ext +echo "basicConstraints=critical,CA:FALSE" >> server.ext +echo "keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment" >> server.ext +echo "subjectAltName=DNS:localhost" >> server.ext + +openssl x509 -req -days 3650 -sha256 -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -extfile server.ext -in server.csr -out server.crt +#openssl x509 -req -days 3650 -sha256 -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -extfile server.ext -in server.csr -signkey server.key -out server.crt +#openssl x509 -req -days 3650 -sha256 -extfile server.ext -in server.csr -signkey server.key -out server.crt cp server.crt server.pem cat server.key >> server.pem +cat rootCA.crt >> server.pem -openssl pkcs12 -export -inkey server.key -in server.pem -name ServerName -out server.pfx +openssl pkcs12 -passout pass:pass -export -inkey server.key -in server.pem -name ServerName -out server.pfx echo "First server certificate hash for Public-Key-Pins header:" @@ -42,8 +66,8 @@ echo "Generating backup server certificate ..." -openssl genrsa -des3 -out server_bkup.key 2048 -openssl req -new -key server_bkup.key -out server_bkup.csr +openssl genrsa -passout pass:pass -out server_bkup.key 2048 +openssl req -passout pass:pass -new -key server_bkup.key -out server_bkup.csr -subj "/C=AA/ST=localhost/L=localhost/O=localhost/OU=localhost/CN=localhost" cp server_bkup.key server_bkup.key.orig @@ -54,7 +78,7 @@ cp server_bkup.crt server_bkup.pem cat server_bkup.key >> server_bkup.pem -openssl pkcs12 -export -inkey server_bkup.key -in server_bkup.pem -name ServerName -out server_bkup.pfx +openssl pkcs12 -passout pass:pass -export -inkey server_bkup.key -in server_bkup.pem -name ServerName -out server_bkup.pfx echo "Backup server certificate hash for Public-Key-Pins header:" diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.crt civetweb-1.15+dfsg/resources/cert/server_bkup.crt --- civetweb-1.13+dfsg/resources/cert/server_bkup.crt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.crt 2021-09-01 08:46:33.000000000 +0000 @@ -1,19 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCFKfFGF1i10TANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjI1MVoXDTI3MDkwMTE5MjI1MVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSferhJaWg69b2Li4t5/JxElESR -8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3WhU3DYiFL2sJndrDvAhmso122Z -xVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVkki05XcwfbI2y6gqCRpOSXdE9 -gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0KesoCwb4f5oqs2vThUmXKuxu8GO -WpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNKBJVKPCETnYw+2ArMgXzs+JuA -C4AhV0e6unLX9DcavZ6j7JcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAJJWqVuQs -guFZG/LZPeeh1WtZr9S6R5BT4+b+PH2teVyGtClXV6KpwcLNEVWzY3qPtrFFPQI1 -uEg6cY8w1JOiCmj/IWKsiHd+IdsqsFVKL+Bmvthm3HSgA6p6ZiVCG4E67p8xwiJP -p5EwtMM/7BdS/tHLUOe1OpNZ8XtHRVUNbzy/+JV0So7WLP9ksGb6COL/9MF0/qG4 -4XrrvpZ9FAgRC9/22QyYiQqoaegGEy4E+KHOBxRmipInsU2H8aQA2sZzQ49Zew9E -QI2jSJTC7EeuZ0OcZawKkJY1ZtIGmOo/Q956keOLdG8cxyq6pXW3gmq1X5QBxy1M -pZYi5eIENGE63g== +MIIDaTCCAlECFEgQo9b5Z72DXt4/2Ii6fSJTPO8WMA0GCSqGSIb3DQEBCwUAMHEx +CzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0yMTA0MDQxODM5NTVaFw0zMTA0MDIxODM5NTVa +MHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxv +Y2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3Qx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL9GtdCihe6UmPPfQJOwQGV5vePp9Jgo7fz8WvT3U1AWkcluocNgl4gD6xmZ +whwJjQuXt+Qk4Uizx0OHvHGsyZjmZ2yUnOVk1jQzVgVhvtsqtFFJkXYJORLX1ahf +TS8rjN9Nd5KObo59e+6rV+fvnH16l33I3RfPtF5iqBdiPHSSuJn8N4S/+txNzn6n +jB974rNvnaS0Uxdw2N9NY2BPFz+2AwfFu/ALfDBHUu7g7tGYTs4+kj/zedyMLkL6 +QG2XacKNAvG0i7eLdDTmAdvJmdYuU9ew5cAGpAjrFkUEJaPf9XVHC/yUibwBJC70 +3Hb7kQpzHgVSKfUCsRqMs6rhU7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAT91b +yZsoSAPsEu2Q4NZPpOt9u/SPi/wCX3YBv9QmIeu93lBKEbU/pJEhimOzttbXDn8W +S065UJt92ZVoYzP5e6c6itnFvXyOws4Di9uTuCkWaGlo+4CBAvwTszrLy6s7ss83 +zk1QCROqO7IAP+rXs87V2NYJk441RKy4LtBiUu0hfZeXZy1k8Ooxl2fIduswkf98 +Gk7Xl3rJs00D9Klm9WAbrAqyBQM2z4WP0QH9KnHpZP/K3IAjzqREcsyF840u3TXC +dByRnaml6Se1F8SA+R2D5ds+CtjFE0oMC9Uc+sjnSCepZ8lWzxgNWR5ufFAwDXPi +Lgg3GFSJ1xug7rZbkg== -----END CERTIFICATE----- diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.csr civetweb-1.15+dfsg/resources/cert/server_bkup.csr --- civetweb-1.13+dfsg/resources/cert/server_bkup.csr 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.csr 2021-09-01 08:46:33.000000000 +0000 @@ -1,16 +1,17 @@ -----BEGIN CERTIFICATE REQUEST----- -MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx -ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSf -erhJaWg69b2Li4t5/JxElESR8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3Wh -U3DYiFL2sJndrDvAhmso122ZxVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVk -ki05XcwfbI2y6gqCRpOSXdE9gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0Kes -oCwb4f5oqs2vThUmXKuxu8GOWpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNK -BJVKPCETnYw+2ArMgXzs+JuAC4AhV0e6unLX9DcavZ6j7JcCAwEAAaAAMA0GCSqG -SIb3DQEBCwUAA4IBAQBvbql7sAA8XOwsszRUzOCLkFxfDsWJ0l5re2mGgHTEd5hc -eDfM+Vdy8SVZX9OySdioVD6ACTse3rc1ULYn8jj1wvOd3/z/J9aUBcBACJG5D1Dl -+j+xvfhvgAGCEQn7ZMaWLFWrLs++aQ+EKbl0SypEI2rTJkyZlYSDVpa+LhqX4UOa -+RNlq1CX+85HCjBn0sWBNzhjrf3gwERRn5NfTab4FqwqGp2+s4GvbOJHrm8saMWu -BlhcTzGGLBRKCQUHo5i9393b3oBOqtcpWPcZGhyAF1NUbYL7USnsiH6lkGReeaFi -xy7vYmUn9j//vT64SmASG0oF+ecUF0q2W42sSqnU +MIICtjCCAZ4CAQAwcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDES +MBAGA1UEBwwJbG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsM +CWxvY2FsaG9zdDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv0a10KKF7pSY899Ak7BAZXm94+n0mCjt/Pxa9PdTUBaR +yW6hw2CXiAPrGZnCHAmNC5e35CThSLPHQ4e8cazJmOZnbJSc5WTWNDNWBWG+2yq0 +UUmRdgk5EtfVqF9NLyuM3013ko5ujn177qtX5++cfXqXfcjdF8+0XmKoF2I8dJK4 +mfw3hL/63E3OfqeMH3vis2+dpLRTF3DY301jYE8XP7YDB8W78At8MEdS7uDu0ZhO +zj6SP/N53IwuQvpAbZdpwo0C8bSLt4t0NOYB28mZ1i5T17DlwAakCOsWRQQlo9/1 +dUcL/JSJvAEkLvTcdvuRCnMeBVIp9QKxGoyzquFTuQIDAQABoAAwDQYJKoZIhvcN +AQELBQADggEBADUG6vuhqw6NoGlLg/wcVeIfAIDod2+iv95N9CW02dTof2QQq//i +/ymdJQnMY8DjrEaQtcBwA7mJoRmbMhI1soRbMFPNGwJU6cNgeuA8zCMBaBBj2Zhz +WY7Tp+gWw/m4MIBGJ5PNCXzwc7E254hS6WGLy1DIl/z5th9fUVKN0a4ueDARlXqI +ea/U6UmfgklVELbsIIZ5ixfawj02s4culjNYORNL8uqnjLT9jg9Nn0NFGDfYrDqz +UFqVdNlT25AgX7xhbvUIlMdFY0XEcR+6KneCBxuiLSxXKixY6vpYhKKUWnb/YGZO +RB3fp44zJrGSGUt7rjGqbLF9ndH6Ez2RAKk= -----END CERTIFICATE REQUEST----- diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.key civetweb-1.15+dfsg/resources/cert/server_bkup.key --- civetweb-1.13+dfsg/resources/cert/server_bkup.key 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.key 2021-09-01 08:46:33.000000000 +0000 @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEApMmvc/NY5HUeuN+T1sEDtOm0jWE1hWf9e+LYZJ96uElpaDr1 -vYuLi3n8nESURJHx/LSUEzND/JoWJBvnXLtDVz5nrFYvGTfbat/LdaFTcNiIUvaw -md2sO8CGayjXbZnFUAMDRxDCjnbQyAVikc0EXwFwVXYhG6TNVf7+dWSSLTldzB9s -jbLqCoJGk5Jd0T2AINVqfe1JFu2vAq7sgfLzyYvrTnujzZR7OmXQp6ygLBvh/miq -za9OFSZcq7G7wY5alk0rgkVadOAM4mu5tm8rHPMv0TzkNL1pcuTp00oElUo8IROd -jD7YCsyBfOz4m4ALgCFXR7q6ctf0Nxq9nqPslwIDAQABAoIBAE/B7lHIrnWk2kHQ -tNV0hj7B/smPC0COnHmhyeqp5dPcdFAmeVpMeDYBzOo1py2pFd6h6CmC3p0cVysS -9mBDosxPQA6BiDpEdsa7mtZMRv6PTywYilFuoTYqcOTc16gMjRu02ZlD22boyxSE -xria6kqxf5Vdn5ipo1jEGpTnIHkSS+Y8CetCaYgcezLaXlXN3RyjF6tCHMeS3iLl -/zY2O4avG2BM+vvDGDW2FWtZg+hN+5Yk90Qt8dFTwvWRCfYaSWfi7id91p5X0rnL -x1G07qw18LziKJj4HZiueqbDcDOYhfcA6sd0OHcvtXfGIoeqkXxi54cIOReRhN2/ -7ib3iUECgYEA2DNH5aiwc5uqTAL9RHTnuuFwQe46onJwnBkho+xEvvdsp2Q2f7VR -c5M17fL+Rb5gq0O4vzeegKiYpo8gKjFp3Duv9Gdc/TB9sLEEt4NQMD4shV7ihBwC -Rjsflww45dt0mccFZp1ncDYKWHDFzdhO+WB828FPFh/5dl6S+v4Q9bUCgYEAwx+G -XhheTMSqoKGVJ283+4bNZWUSE99wcAhx9J3FkJera030mh0OHoCn0myBjRjxOSY/ -eBH8/0YoLkGYvTdEU/tYiLIWJ/ehC0eweXiwDehb5meco6u9WCeYvyPMLErXbe3K -BQVyfcFzva4eC3dZ7lzxmyVyKXVTYgY0Hf7biJsCgYBKHdJg/eJ3z36jDkdK55Tl -cRFt2MCLHhZSvR7WNlIe8W1zORyhzUP+DhJn32yh9jDnpZC5JNUWoDWsq9ZIAKac -1G1uqNytA6mjIBxQ2RhtYXMbybp3ta5l6zDaNFtxGTmw2hSU6BMk2bHUPdzhw2zX -eudy4qM9H3sCxEs49k5UHQKBgDz7I0FRGFehtznQhg73AWYIsTSZK9cuI7O/z+2F -SXNxE0/L40AvCHSb/NcUtkBkpS8ZNwjNhmY5hOE/+v5XwXEFwpumHKqNB7XAx/SO -tWcDUYVmqFu2lsxwQ5qpE2xcT4u5n0OGeku3I/cJ7bXjrSWDwracM1uloVOnYK5n -MjE1AoGAeM6Wrb0VXRq025+OEfoFis3P9S0REkkkabM9+VLRSWi63uxg2cyipxUg -qJUThbUm1aSS1F+XWjG7vrDjWT/GQTYj9/CH3mZRflZgLUltVHEZesLwWqn15Gl/ -BDwaV6RN7F3BCSzgEfCutrfGJqxA0tx5TTcupOgwpZVakN+hm3c= +MIIEowIBAAKCAQEAv0a10KKF7pSY899Ak7BAZXm94+n0mCjt/Pxa9PdTUBaRyW6h +w2CXiAPrGZnCHAmNC5e35CThSLPHQ4e8cazJmOZnbJSc5WTWNDNWBWG+2yq0UUmR +dgk5EtfVqF9NLyuM3013ko5ujn177qtX5++cfXqXfcjdF8+0XmKoF2I8dJK4mfw3 +hL/63E3OfqeMH3vis2+dpLRTF3DY301jYE8XP7YDB8W78At8MEdS7uDu0ZhOzj6S +P/N53IwuQvpAbZdpwo0C8bSLt4t0NOYB28mZ1i5T17DlwAakCOsWRQQlo9/1dUcL +/JSJvAEkLvTcdvuRCnMeBVIp9QKxGoyzquFTuQIDAQABAoIBAQCLMN6f+5Tw/+uq +E/0/PBQwg/4eO6MFk0tUPSPHfa9/6Vyfs8U9ky3SCd/smkp58q1UEUz9VaUnLcRE +rSMBqdZuUMRUbHUcLVv/Upg3hGDJxnK/cITM23tP7gaJ5wgY2l1CJnJsEP/86u3j +yYZHvsMnQK27GA9kA37i7HIbyh3qSZRZb/4Hqnm8QJbpGkLZlvgrC4i3xdNs1+MW +c4T8eJjRUj9V5JyT3kRMSWbN2mncwkXf6RJRnsvsw/0vUGom+fM//cgbtzWl6UTp +FtcYNvxgYTXOjubq6PPPJJRf8NUKR1udvPkYaEPZQ4xDz1oXDGMmfx2mxmZ0P75S +dKTeLb0xAoGBAOjEtfwTsSNQScA2ynKxpJIrDj6RLE226Kq88+Go/hNm2SWY7ODS +8Fo7sPSLNFUwe+CAk6nU8CRazvfHTsndRbbflFFAsK6qZXA3QzCjIUuIxyzTbPAs +nwy+sz1VlhcuRXm9nYcYhnZ5cN4Lm3JWlWu4U2BsQE7owjJ8d3ULZTFVAoGBANJd +3SMcXxb7EgLshdK1OscKH7OwTZBKAbGIbXIxM7XNxxg7aunk7+5UV2XDcmnpyqMO +2lT62FF01c2rBabjhVeOwoVVfEpFaketjGZlCInIL1Sqm2/tVsZfBEJbmj1bqIa3 +OWahSCjn5zWf4Yi17KMeLtAXRL9UeG+IXVxIEijVAoGAUdeQcTBvUQ5S0B2zsv4Y +8jfnS0J6BF0yk43aZlan9yRrZ1fMugQQ9HkWb/VeEjH47GfpA4bWZMH1EZPndPyz +HWihWqxXMyLAheM4YaqJ82gFOBKitBPMXIvUs9Ua782aKgLsl2qdJJzwfXIxVtNw +uC5YSoflWJloZp3y1pmKG/0CgYBC7fA0gotScXEKkxwErPpVZ0gs0FPtK06coE5J +/ZN5LU5BzG24msknZ5gi3WsifWqmNEyMqv519BkuBVKYBV1gPSBwcYFI1Ar7YSEB +VvW/eHxukJVBqB5qoMJnJmPNT8MvkU3m9DtUIGw0aHjGGTN/tlOoiy6pPQPQYG9r +s9ZrPQKBgGovPIkY9ovz6Xy8a67ag4Hj0yS9t3aRAb7d7MqOcjL7kM0l36O3JYiG +REHuqtcK4X2LC8l8WSek2XFNcroswHchhqT1VpzJxrrfogupY0qzRQqGYCOLIdeT +VVfKcy/+vwxAnyePj9nvJHY/B8hf8WYFlRkwIH3ujsb8GfGjWE1O -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.key.orig civetweb-1.15+dfsg/resources/cert/server_bkup.key.orig --- civetweb-1.13+dfsg/resources/cert/server_bkup.key.orig 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.key.orig 2021-09-01 08:46:33.000000000 +0000 @@ -1,30 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,E700A7E4CCCF78FC - -1/jqqjzwHWxdTvayJ+y//FTMuxZbIOT8hl4h+4zzh+/o45RHUa8n6nTI3mLSIK/i -6yZqSaPaCiBINcLWmijbeDN73OhVL3rrum1VotcTUTA2LU0M+kLWpmcJrY5lsku2 -2voulXmLoCniup+nhnGXDWOk3jaLsMBOn3kYyVBgphwzGzKinFQnqzo/w6/2pJ/C -iKb/GWNEuXwHkoTz7A4o1ZVVOQyx8h0klWbwjBEPB+cPE3h/bRTkJWTTy2yfCeUC -nyRQ1BkWC6I5LLesC7gG0jsw3rcGkJnu+zNkxG43N9CkU74S/jNwktjqzKiSbO14 -SYu/NiaVLCtQTeaTeh39X8OGW4RzFbO32PVBl0jL5d8h3DpvTufbtC9BS9dADM0o -pwCUVWiKKgApmqhFDyUpQB8ptfLewmp5ksB93NzdlPLV8vojJ7nBOrppaueXKQ6Z -f380J3xCrVN7pTt/yT3mlvCnmb0gNhL6jAE53C112Upjmu40OBhwjGDjDXsOZBmZ -NH0KEsLecIPgbx0W27h0j4JDdXGtI4mjFHHEnFj75We73BZ8BIlyRt7nxS+iFYNH -hpbwuNc4dX953jwPy7CIxyms5cy4BigTv/rsgFWCxWxFcTqYkp6L3z8IC6apJDSp -htKLzhFKjlXqP3vcwZYrAF26eOl6Pxn74853dRskAZNY5F40/7IjVb8l71tedWof -WE5wpuXrZJd+GBeIM+plbPCnBiNSHuRzJPhLU3tsT3X70WfDxgIgM38P5uOOBLma -hU/0wcL8+Q3HESPx5ju+5lYZBmozs5ANwMggXv0a1vBptI/kA0HeMQx52G4m1F+9 -aYRrNc+Exl901Yjn120Y6NllIk5EolsqNifDsems9sTiC91Fvh7yiYI5Pd7qCwoR -2ssLbWda/+bgqtDXjmv4x1btWhWmbInBpCrp1YEwILlyNN6FQ/sQ8pvHtyC9+FcB -xQ7wI0JnsCpj8E+P5C08EEgpTiUfelwYyTZLarAFMRe5HWZjgQW7+JvbiQ4Q3ZXM -/DaYh6zGXvR4OomTqKN63i6iAckS7Uh3/XzaWbjOAxvMIgKhU7OBqDAlPvgXJh1y -sDig2zTR603AURkWZir2OOr7XKZcqNj8lxt+BG+E6bwxdeIeEQn7f8Ef5oUmFNXQ -o5zQwI12RDQXaBRDG/wTONrUhvc8TEM04jNGKMRPU6FlZSEF2zlTSU8/QtO56FwR -MwhPlNUSgWgvqzFWoA4W7XWjAfYqvoVRcLjcZF2WBUJwYq4ZODNqBH+j3+Ftge9l -wKc/9KjcurpAWbg7gq9XtwgiT8bYHcM3NSOwgnrOJ4wtukuwbLq2JjMLgFQeDAev -NFJfbYoZ0iTyIq1WRS0MlhAwDKujDOoQLqkF41LC5Ac6RpMeR689xN18YE6b6iXp -f93tHI+6Ru1I+2ZoGbvCPmasv3jk69C8A/StmUEcFfxmOr5qhQEVR2pIXfXKeqbE -KCUoR4Wax42q/bDhgIOOmq+E9YsTuy4Iq5J25WDIbgWN35s0qXDm91s+aY0KtDUu -fxGdOIHQHx10ARHUKZ6AhXSF+q5QQFy4ejlgiTMorvT0XUHmIQ82hw== +MIIEowIBAAKCAQEAv0a10KKF7pSY899Ak7BAZXm94+n0mCjt/Pxa9PdTUBaRyW6h +w2CXiAPrGZnCHAmNC5e35CThSLPHQ4e8cazJmOZnbJSc5WTWNDNWBWG+2yq0UUmR +dgk5EtfVqF9NLyuM3013ko5ujn177qtX5++cfXqXfcjdF8+0XmKoF2I8dJK4mfw3 +hL/63E3OfqeMH3vis2+dpLRTF3DY301jYE8XP7YDB8W78At8MEdS7uDu0ZhOzj6S +P/N53IwuQvpAbZdpwo0C8bSLt4t0NOYB28mZ1i5T17DlwAakCOsWRQQlo9/1dUcL +/JSJvAEkLvTcdvuRCnMeBVIp9QKxGoyzquFTuQIDAQABAoIBAQCLMN6f+5Tw/+uq +E/0/PBQwg/4eO6MFk0tUPSPHfa9/6Vyfs8U9ky3SCd/smkp58q1UEUz9VaUnLcRE +rSMBqdZuUMRUbHUcLVv/Upg3hGDJxnK/cITM23tP7gaJ5wgY2l1CJnJsEP/86u3j +yYZHvsMnQK27GA9kA37i7HIbyh3qSZRZb/4Hqnm8QJbpGkLZlvgrC4i3xdNs1+MW +c4T8eJjRUj9V5JyT3kRMSWbN2mncwkXf6RJRnsvsw/0vUGom+fM//cgbtzWl6UTp +FtcYNvxgYTXOjubq6PPPJJRf8NUKR1udvPkYaEPZQ4xDz1oXDGMmfx2mxmZ0P75S +dKTeLb0xAoGBAOjEtfwTsSNQScA2ynKxpJIrDj6RLE226Kq88+Go/hNm2SWY7ODS +8Fo7sPSLNFUwe+CAk6nU8CRazvfHTsndRbbflFFAsK6qZXA3QzCjIUuIxyzTbPAs +nwy+sz1VlhcuRXm9nYcYhnZ5cN4Lm3JWlWu4U2BsQE7owjJ8d3ULZTFVAoGBANJd +3SMcXxb7EgLshdK1OscKH7OwTZBKAbGIbXIxM7XNxxg7aunk7+5UV2XDcmnpyqMO +2lT62FF01c2rBabjhVeOwoVVfEpFaketjGZlCInIL1Sqm2/tVsZfBEJbmj1bqIa3 +OWahSCjn5zWf4Yi17KMeLtAXRL9UeG+IXVxIEijVAoGAUdeQcTBvUQ5S0B2zsv4Y +8jfnS0J6BF0yk43aZlan9yRrZ1fMugQQ9HkWb/VeEjH47GfpA4bWZMH1EZPndPyz +HWihWqxXMyLAheM4YaqJ82gFOBKitBPMXIvUs9Ua782aKgLsl2qdJJzwfXIxVtNw +uC5YSoflWJloZp3y1pmKG/0CgYBC7fA0gotScXEKkxwErPpVZ0gs0FPtK06coE5J +/ZN5LU5BzG24msknZ5gi3WsifWqmNEyMqv519BkuBVKYBV1gPSBwcYFI1Ar7YSEB +VvW/eHxukJVBqB5qoMJnJmPNT8MvkU3m9DtUIGw0aHjGGTN/tlOoiy6pPQPQYG9r +s9ZrPQKBgGovPIkY9ovz6Xy8a67ag4Hj0yS9t3aRAb7d7MqOcjL7kM0l36O3JYiG +REHuqtcK4X2LC8l8WSek2XFNcroswHchhqT1VpzJxrrfogupY0qzRQqGYCOLIdeT +VVfKcy/+vwxAnyePj9nvJHY/B8hf8WYFlRkwIH3ujsb8GfGjWE1O -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.pem civetweb-1.15+dfsg/resources/cert/server_bkup.pem --- civetweb-1.13+dfsg/resources/cert/server_bkup.pem 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.pem 2021-09-01 08:46:33.000000000 +0000 @@ -1,46 +1,48 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCFKfFGF1i10TANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjI1MVoXDTI3MDkwMTE5MjI1MVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSferhJaWg69b2Li4t5/JxElESR -8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3WhU3DYiFL2sJndrDvAhmso122Z -xVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVkki05XcwfbI2y6gqCRpOSXdE9 -gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0KesoCwb4f5oqs2vThUmXKuxu8GO -WpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNKBJVKPCETnYw+2ArMgXzs+JuA -C4AhV0e6unLX9DcavZ6j7JcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAJJWqVuQs -guFZG/LZPeeh1WtZr9S6R5BT4+b+PH2teVyGtClXV6KpwcLNEVWzY3qPtrFFPQI1 -uEg6cY8w1JOiCmj/IWKsiHd+IdsqsFVKL+Bmvthm3HSgA6p6ZiVCG4E67p8xwiJP -p5EwtMM/7BdS/tHLUOe1OpNZ8XtHRVUNbzy/+JV0So7WLP9ksGb6COL/9MF0/qG4 -4XrrvpZ9FAgRC9/22QyYiQqoaegGEy4E+KHOBxRmipInsU2H8aQA2sZzQ49Zew9E -QI2jSJTC7EeuZ0OcZawKkJY1ZtIGmOo/Q956keOLdG8cxyq6pXW3gmq1X5QBxy1M -pZYi5eIENGE63g== +MIIDaTCCAlECFEgQo9b5Z72DXt4/2Ii6fSJTPO8WMA0GCSqGSIb3DQEBCwUAMHEx +CzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0yMTA0MDQxODM5NTVaFw0zMTA0MDIxODM5NTVa +MHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxv +Y2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3Qx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL9GtdCihe6UmPPfQJOwQGV5vePp9Jgo7fz8WvT3U1AWkcluocNgl4gD6xmZ +whwJjQuXt+Qk4Uizx0OHvHGsyZjmZ2yUnOVk1jQzVgVhvtsqtFFJkXYJORLX1ahf +TS8rjN9Nd5KObo59e+6rV+fvnH16l33I3RfPtF5iqBdiPHSSuJn8N4S/+txNzn6n +jB974rNvnaS0Uxdw2N9NY2BPFz+2AwfFu/ALfDBHUu7g7tGYTs4+kj/zedyMLkL6 +QG2XacKNAvG0i7eLdDTmAdvJmdYuU9ew5cAGpAjrFkUEJaPf9XVHC/yUibwBJC70 +3Hb7kQpzHgVSKfUCsRqMs6rhU7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAT91b +yZsoSAPsEu2Q4NZPpOt9u/SPi/wCX3YBv9QmIeu93lBKEbU/pJEhimOzttbXDn8W +S065UJt92ZVoYzP5e6c6itnFvXyOws4Di9uTuCkWaGlo+4CBAvwTszrLy6s7ss83 +zk1QCROqO7IAP+rXs87V2NYJk441RKy4LtBiUu0hfZeXZy1k8Ooxl2fIduswkf98 +Gk7Xl3rJs00D9Klm9WAbrAqyBQM2z4WP0QH9KnHpZP/K3IAjzqREcsyF840u3TXC +dByRnaml6Se1F8SA+R2D5ds+CtjFE0oMC9Uc+sjnSCepZ8lWzxgNWR5ufFAwDXPi +Lgg3GFSJ1xug7rZbkg== -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEApMmvc/NY5HUeuN+T1sEDtOm0jWE1hWf9e+LYZJ96uElpaDr1 -vYuLi3n8nESURJHx/LSUEzND/JoWJBvnXLtDVz5nrFYvGTfbat/LdaFTcNiIUvaw -md2sO8CGayjXbZnFUAMDRxDCjnbQyAVikc0EXwFwVXYhG6TNVf7+dWSSLTldzB9s -jbLqCoJGk5Jd0T2AINVqfe1JFu2vAq7sgfLzyYvrTnujzZR7OmXQp6ygLBvh/miq -za9OFSZcq7G7wY5alk0rgkVadOAM4mu5tm8rHPMv0TzkNL1pcuTp00oElUo8IROd -jD7YCsyBfOz4m4ALgCFXR7q6ctf0Nxq9nqPslwIDAQABAoIBAE/B7lHIrnWk2kHQ -tNV0hj7B/smPC0COnHmhyeqp5dPcdFAmeVpMeDYBzOo1py2pFd6h6CmC3p0cVysS -9mBDosxPQA6BiDpEdsa7mtZMRv6PTywYilFuoTYqcOTc16gMjRu02ZlD22boyxSE -xria6kqxf5Vdn5ipo1jEGpTnIHkSS+Y8CetCaYgcezLaXlXN3RyjF6tCHMeS3iLl -/zY2O4avG2BM+vvDGDW2FWtZg+hN+5Yk90Qt8dFTwvWRCfYaSWfi7id91p5X0rnL -x1G07qw18LziKJj4HZiueqbDcDOYhfcA6sd0OHcvtXfGIoeqkXxi54cIOReRhN2/ -7ib3iUECgYEA2DNH5aiwc5uqTAL9RHTnuuFwQe46onJwnBkho+xEvvdsp2Q2f7VR -c5M17fL+Rb5gq0O4vzeegKiYpo8gKjFp3Duv9Gdc/TB9sLEEt4NQMD4shV7ihBwC -Rjsflww45dt0mccFZp1ncDYKWHDFzdhO+WB828FPFh/5dl6S+v4Q9bUCgYEAwx+G -XhheTMSqoKGVJ283+4bNZWUSE99wcAhx9J3FkJera030mh0OHoCn0myBjRjxOSY/ -eBH8/0YoLkGYvTdEU/tYiLIWJ/ehC0eweXiwDehb5meco6u9WCeYvyPMLErXbe3K -BQVyfcFzva4eC3dZ7lzxmyVyKXVTYgY0Hf7biJsCgYBKHdJg/eJ3z36jDkdK55Tl -cRFt2MCLHhZSvR7WNlIe8W1zORyhzUP+DhJn32yh9jDnpZC5JNUWoDWsq9ZIAKac -1G1uqNytA6mjIBxQ2RhtYXMbybp3ta5l6zDaNFtxGTmw2hSU6BMk2bHUPdzhw2zX -eudy4qM9H3sCxEs49k5UHQKBgDz7I0FRGFehtznQhg73AWYIsTSZK9cuI7O/z+2F -SXNxE0/L40AvCHSb/NcUtkBkpS8ZNwjNhmY5hOE/+v5XwXEFwpumHKqNB7XAx/SO -tWcDUYVmqFu2lsxwQ5qpE2xcT4u5n0OGeku3I/cJ7bXjrSWDwracM1uloVOnYK5n -MjE1AoGAeM6Wrb0VXRq025+OEfoFis3P9S0REkkkabM9+VLRSWi63uxg2cyipxUg -qJUThbUm1aSS1F+XWjG7vrDjWT/GQTYj9/CH3mZRflZgLUltVHEZesLwWqn15Gl/ -BDwaV6RN7F3BCSzgEfCutrfGJqxA0tx5TTcupOgwpZVakN+hm3c= +MIIEowIBAAKCAQEAv0a10KKF7pSY899Ak7BAZXm94+n0mCjt/Pxa9PdTUBaRyW6h +w2CXiAPrGZnCHAmNC5e35CThSLPHQ4e8cazJmOZnbJSc5WTWNDNWBWG+2yq0UUmR +dgk5EtfVqF9NLyuM3013ko5ujn177qtX5++cfXqXfcjdF8+0XmKoF2I8dJK4mfw3 +hL/63E3OfqeMH3vis2+dpLRTF3DY301jYE8XP7YDB8W78At8MEdS7uDu0ZhOzj6S +P/N53IwuQvpAbZdpwo0C8bSLt4t0NOYB28mZ1i5T17DlwAakCOsWRQQlo9/1dUcL +/JSJvAEkLvTcdvuRCnMeBVIp9QKxGoyzquFTuQIDAQABAoIBAQCLMN6f+5Tw/+uq +E/0/PBQwg/4eO6MFk0tUPSPHfa9/6Vyfs8U9ky3SCd/smkp58q1UEUz9VaUnLcRE +rSMBqdZuUMRUbHUcLVv/Upg3hGDJxnK/cITM23tP7gaJ5wgY2l1CJnJsEP/86u3j +yYZHvsMnQK27GA9kA37i7HIbyh3qSZRZb/4Hqnm8QJbpGkLZlvgrC4i3xdNs1+MW +c4T8eJjRUj9V5JyT3kRMSWbN2mncwkXf6RJRnsvsw/0vUGom+fM//cgbtzWl6UTp +FtcYNvxgYTXOjubq6PPPJJRf8NUKR1udvPkYaEPZQ4xDz1oXDGMmfx2mxmZ0P75S +dKTeLb0xAoGBAOjEtfwTsSNQScA2ynKxpJIrDj6RLE226Kq88+Go/hNm2SWY7ODS +8Fo7sPSLNFUwe+CAk6nU8CRazvfHTsndRbbflFFAsK6qZXA3QzCjIUuIxyzTbPAs +nwy+sz1VlhcuRXm9nYcYhnZ5cN4Lm3JWlWu4U2BsQE7owjJ8d3ULZTFVAoGBANJd +3SMcXxb7EgLshdK1OscKH7OwTZBKAbGIbXIxM7XNxxg7aunk7+5UV2XDcmnpyqMO +2lT62FF01c2rBabjhVeOwoVVfEpFaketjGZlCInIL1Sqm2/tVsZfBEJbmj1bqIa3 +OWahSCjn5zWf4Yi17KMeLtAXRL9UeG+IXVxIEijVAoGAUdeQcTBvUQ5S0B2zsv4Y +8jfnS0J6BF0yk43aZlan9yRrZ1fMugQQ9HkWb/VeEjH47GfpA4bWZMH1EZPndPyz +HWihWqxXMyLAheM4YaqJ82gFOBKitBPMXIvUs9Ua782aKgLsl2qdJJzwfXIxVtNw +uC5YSoflWJloZp3y1pmKG/0CgYBC7fA0gotScXEKkxwErPpVZ0gs0FPtK06coE5J +/ZN5LU5BzG24msknZ5gi3WsifWqmNEyMqv519BkuBVKYBV1gPSBwcYFI1Ar7YSEB +VvW/eHxukJVBqB5qoMJnJmPNT8MvkU3m9DtUIGw0aHjGGTN/tlOoiy6pPQPQYG9r +s9ZrPQKBgGovPIkY9ovz6Xy8a67ag4Hj0yS9t3aRAb7d7MqOcjL7kM0l36O3JYiG +REHuqtcK4X2LC8l8WSek2XFNcroswHchhqT1VpzJxrrfogupY0qzRQqGYCOLIdeT +VVfKcy/+vwxAnyePj9nvJHY/B8hf8WYFlRkwIH3ujsb8GfGjWE1O -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/server_bkup.pin civetweb-1.15+dfsg/resources/cert/server_bkup.pin --- civetweb-1.13+dfsg/resources/cert/server_bkup.pin 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server_bkup.pin 2021-09-01 08:46:33.000000000 +0000 @@ -1 +1 @@ -pf3px1MBPmlTGAPoiHWqaSJ9L9Z+DKfwgsU7LfLnmsk= +B38hE4miifPbiN4Niuf/o7I5t+eK6QPEXPDi7hkLC8s= diff -Nru civetweb-1.13+dfsg/resources/cert/server.crt civetweb-1.15+dfsg/resources/cert/server.crt --- civetweb-1.13+dfsg/resources/cert/server.crt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.crt 2021-09-01 08:46:33.000000000 +0000 @@ -1,19 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQDDIH/hK1C0BjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIyOVoXDTI3MDkwMTE5MjIyOVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALUmHEoJcebkUOyqEAhH2OdEuTTk8AxjjVvq9B1dXjlf/dvxGnZX2InScGCJA9Uy -kO1XI8nLXKAGl6OL9jDt/0K3/oFLedDLtZf1qE+kEBuaqAgL+VVAPqwtQZcyCoI9 -zx777I1tPUOl1Q1ass3T7lYsTN8QADmW5zjJn4MJPMQ55qoQUL7HVQR4VJ/ELAXu -xGkQlJFBY5q0Qq6buN102D2upNKXKpDYYPc0OgyJ73fR2+rzQapc52QD4Oh6cbD8 -Fh5Vh/qGNMckh1cQsVm6fRtlkoUqxANZk58rqkEwOuk04p7vlnVvZTidOng7G2nW -1n7YQXCycI+JhofCqOqT9x8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATx5GZCxU -KKQCDsafzAwoodbjRlpsJhvdCBGpgMrFTPyQo7BNF/E2XyVCDXbCmbxTRlhFafJG -Loj/73toGkU8+1qUIy/Fffsmeh9YCyMlA2bE+85ccMCVKgCIEx0+fa6Au6/Ref7/ -n7vN/9deJzxWUaNbP26LNq3prbuIbKN6WFNT5mR8HLTmP3O45sqy1jwOZgSwvbgH -bhugE4tSsKghMV5rUgiMhGIrEakFH+1LCZjQh+ojcWWEWyVk3QTQMmSd6tAZf4pb -/Y1GuN6DAiLfzbabUQZCeQ1iZcgrwIOGHWJUPAf+BTPcFLlR3k/kYA9lrqvra7ln -dFIuUv3YzfenfA== +MIIEQDCCAyigAwIBAgIUSWVbNc5CIBWnxIop5kRYbBHmjKcwDQYJKoZIhvcNAQEL +BQAwcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDESMBAGA1UEBwwJ +bG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsMCWxvY2FsaG9z +dDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIxMDQwNDE4Mzk1NFoXDTMxMDQwMjE4 +Mzk1NFowcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDESMBAGA1UE +BwwJbG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsMCWxvY2Fs +aG9zdDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAyiVR57QGLRHhM/ve4ZK+Yyn5GurNLXH4ya4rNa5v0XGu9W/M3c8l +0Vl4MILsZePXom98hILsL9Q3fbxsNgeCJO0h5YHDEitUlkT33WpY4S8/zWceMsiZ +m9ozVNtSXbLFgFA7QeHTqAwNI5DkYvRP1hvFWuAYqT10uzAgvYW9w71phmJ1pp4c +dEWiXmdM4KKHEyiMdr8u3+eveRKpZUJmHCXuykUpMP+cJhQGY5EIpFiNIgvIGI5C +zRa136h7erRxX8KqYJnFL+8T0ZucCowUeoq539+dqnZS/wyTaD9zDbfAIWdI/fLi +w5z11ImGqXtqG4GgiTlxyTplVNsGIoJ/xwIDAQABo4HPMIHMMIGYBgNVHSMEgZAw +gY2hdaRzMHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNV +BAcMCWxvY2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2Nh +bGhvc3QxEjAQBgNVBAMMCWxvY2FsaG9zdIIUYDp1oPxjFOFwBxYje4RjPeEdBxIw +DAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBPAwFAYDVR0RBA0wC4IJbG9jYWxob3N0 +MA0GCSqGSIb3DQEBCwUAA4IBAQATPEEDslgACnMftBXHX6UHFKbufINAhXBAbAiU +cXcc2JqzjXz6RZYDUZJG+IRtCUA6UwfD1h9y5hXrSTpjLRFYc+Ml3rCFW0XGuUYt +hi3Jmx9zahjnlElMd+oLttH7d2ob/LDPXinx1fyTj0jj4L0JpX2hUCyf3ETkhbvK +q71zp9g+MVP+1MPXBTyTcswWK+Yz8L3qml8kOX7+gjSmsiPkZ4/5YGvXLtn7mhI8 +tTv5nQq//y1rM4LmVHUr8nQ7x5alBnC2CkN6e6HDjipYzP9J61G2fH6iaJ+C6C5O ++RTHvmBCZZ1azsoJ9+5IQZNpfD5H8F5gXR2jZ1k8+TxJY3SE -----END CERTIFICATE----- diff -Nru civetweb-1.13+dfsg/resources/cert/server.csr civetweb-1.15+dfsg/resources/cert/server.csr --- civetweb-1.13+dfsg/resources/cert/server.csr 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.csr 2021-09-01 08:46:33.000000000 +0000 @@ -1,16 +1,17 @@ -----BEGIN CERTIFICATE REQUEST----- -MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx -ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALUmHEoJcebkUOyqEAhH2OdEuTTk8AxjjVvq9B1d -Xjlf/dvxGnZX2InScGCJA9UykO1XI8nLXKAGl6OL9jDt/0K3/oFLedDLtZf1qE+k -EBuaqAgL+VVAPqwtQZcyCoI9zx777I1tPUOl1Q1ass3T7lYsTN8QADmW5zjJn4MJ -PMQ55qoQUL7HVQR4VJ/ELAXuxGkQlJFBY5q0Qq6buN102D2upNKXKpDYYPc0OgyJ -73fR2+rzQapc52QD4Oh6cbD8Fh5Vh/qGNMckh1cQsVm6fRtlkoUqxANZk58rqkEw -Ouk04p7vlnVvZTidOng7G2nW1n7YQXCycI+JhofCqOqT9x8CAwEAAaAAMA0GCSqG -SIb3DQEBCwUAA4IBAQCbJgy8LBoI+XCliwPGVM+ZuxEVuR15iaUSX7epuKb4jvyC -y2+YQnNyxLkK8Bu2z9uxXUBbmhqXNiXZd7/SnbTR9MGMq3vyYg6Ggypo24DWez04 -tFaUiLJZsKVoVM6DP3zwpaKKSSJILU2GbNQKW87PHIPSdmAEh+gFD2Uy5sFrvuFJ -LtHfIMMAhMSoEMjmjaLI7N4GVgFhGEr5q5HGpLuAU8cKGyKPkIkSyYN5Ott4u22d -rpASF3TXfCJJ0YiM84U86rhZ0BrMqrVtw8r3uj+4G7hrE92eBU+DDn1D8jWzbyVc -6dlTZaknMeJqsQe2/vq+T5P2yl+/39TnlvDO+cS2 +MIICtjCCAZ4CAQAwcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDES +MBAGA1UEBwwJbG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsM +CWxvY2FsaG9zdDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAyiVR57QGLRHhM/ve4ZK+Yyn5GurNLXH4ya4rNa5v0XGu +9W/M3c8l0Vl4MILsZePXom98hILsL9Q3fbxsNgeCJO0h5YHDEitUlkT33WpY4S8/ +zWceMsiZm9ozVNtSXbLFgFA7QeHTqAwNI5DkYvRP1hvFWuAYqT10uzAgvYW9w71p +hmJ1pp4cdEWiXmdM4KKHEyiMdr8u3+eveRKpZUJmHCXuykUpMP+cJhQGY5EIpFiN +IgvIGI5CzRa136h7erRxX8KqYJnFL+8T0ZucCowUeoq539+dqnZS/wyTaD9zDbfA +IWdI/fLiw5z11ImGqXtqG4GgiTlxyTplVNsGIoJ/xwIDAQABoAAwDQYJKoZIhvcN +AQELBQADggEBAMVLhmv5MpukRGy2wS2UfCZ8gc7V4qETTKlmP2BHNk23gAjNR0O7 +txqW61fNmE0xiCjVmo3PovlyI7YsBXbAIimAT8V3B/ifrBOCWLLyz8CBlcqA8PWQ +QWhKfLHe86JCHIbw0J7+plVOOAfgAiaI8F4rzeYRrW+5r3aqvAlu4MWmNX5clwtZ +J125LEby3xX8b2Mv29/9I52KHbZHDt6lNRTT/vgP1zqsT2fbB7S/ctbj247WTdvU +5fXP85gRJq6Lqv4q59WAqknxVgnpNP4XRbJUqNWlx2ej+h8X1TLquy5ciPMmDxX4 +rC+kYHZqKhxRYSYOHWWjck1QI/9wn0ugS7Y= -----END CERTIFICATE REQUEST----- diff -Nru civetweb-1.13+dfsg/resources/cert/server.key civetweb-1.15+dfsg/resources/cert/server.key --- civetweb-1.13+dfsg/resources/cert/server.key 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.key 2021-09-01 08:46:33.000000000 +0000 @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/server.key.orig civetweb-1.15+dfsg/resources/cert/server.key.orig --- civetweb-1.13+dfsg/resources/cert/server.key.orig 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.key.orig 2021-09-01 08:46:33.000000000 +0000 @@ -1,30 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,9D77FEDB1409D1BC - -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 -----END RSA PRIVATE KEY----- diff -Nru civetweb-1.13+dfsg/resources/cert/server.pem civetweb-1.15+dfsg/resources/cert/server.pem --- civetweb-1.13+dfsg/resources/cert/server.pem 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.pem 2021-09-01 08:46:33.000000000 +0000 @@ -1,46 +1,73 @@ -----BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQDDIH/hK1C0BjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIyOVoXDTI3MDkwMTE5MjIyOVowRTELMAkG -A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALUmHEoJcebkUOyqEAhH2OdEuTTk8AxjjVvq9B1dXjlf/dvxGnZX2InScGCJA9Uy -kO1XI8nLXKAGl6OL9jDt/0K3/oFLedDLtZf1qE+kEBuaqAgL+VVAPqwtQZcyCoI9 -zx777I1tPUOl1Q1ass3T7lYsTN8QADmW5zjJn4MJPMQ55qoQUL7HVQR4VJ/ELAXu -xGkQlJFBY5q0Qq6buN102D2upNKXKpDYYPc0OgyJ73fR2+rzQapc52QD4Oh6cbD8 -Fh5Vh/qGNMckh1cQsVm6fRtlkoUqxANZk58rqkEwOuk04p7vlnVvZTidOng7G2nW -1n7YQXCycI+JhofCqOqT9x8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEATx5GZCxU -KKQCDsafzAwoodbjRlpsJhvdCBGpgMrFTPyQo7BNF/E2XyVCDXbCmbxTRlhFafJG -Loj/73toGkU8+1qUIy/Fffsmeh9YCyMlA2bE+85ccMCVKgCIEx0+fa6Au6/Ref7/ -n7vN/9deJzxWUaNbP26LNq3prbuIbKN6WFNT5mR8HLTmP3O45sqy1jwOZgSwvbgH -bhugE4tSsKghMV5rUgiMhGIrEakFH+1LCZjQh+ojcWWEWyVk3QTQMmSd6tAZf4pb -/Y1GuN6DAiLfzbabUQZCeQ1iZcgrwIOGHWJUPAf+BTPcFLlR3k/kYA9lrqvra7ln -dFIuUv3YzfenfA== +MIIEQDCCAyigAwIBAgIUSWVbNc5CIBWnxIop5kRYbBHmjKcwDQYJKoZIhvcNAQEL +BQAwcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDESMBAGA1UEBwwJ +bG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsMCWxvY2FsaG9z +dDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIxMDQwNDE4Mzk1NFoXDTMxMDQwMjE4 +Mzk1NFowcTELMAkGA1UEBhMCQUExEjAQBgNVBAgMCWxvY2FsaG9zdDESMBAGA1UE +BwwJbG9jYWxob3N0MRIwEAYDVQQKDAlsb2NhbGhvc3QxEjAQBgNVBAsMCWxvY2Fs +aG9zdDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAyiVR57QGLRHhM/ve4ZK+Yyn5GurNLXH4ya4rNa5v0XGu9W/M3c8l +0Vl4MILsZePXom98hILsL9Q3fbxsNgeCJO0h5YHDEitUlkT33WpY4S8/zWceMsiZ +m9ozVNtSXbLFgFA7QeHTqAwNI5DkYvRP1hvFWuAYqT10uzAgvYW9w71phmJ1pp4c +dEWiXmdM4KKHEyiMdr8u3+eveRKpZUJmHCXuykUpMP+cJhQGY5EIpFiNIgvIGI5C +zRa136h7erRxX8KqYJnFL+8T0ZucCowUeoq539+dqnZS/wyTaD9zDbfAIWdI/fLi +w5z11ImGqXtqG4GgiTlxyTplVNsGIoJ/xwIDAQABo4HPMIHMMIGYBgNVHSMEgZAw +gY2hdaRzMHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNV +BAcMCWxvY2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2Nh +bGhvc3QxEjAQBgNVBAMMCWxvY2FsaG9zdIIUYDp1oPxjFOFwBxYje4RjPeEdBxIw +DAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBPAwFAYDVR0RBA0wC4IJbG9jYWxob3N0 +MA0GCSqGSIb3DQEBCwUAA4IBAQATPEEDslgACnMftBXHX6UHFKbufINAhXBAbAiU +cXcc2JqzjXz6RZYDUZJG+IRtCUA6UwfD1h9y5hXrSTpjLRFYc+Ml3rCFW0XGuUYt +hi3Jmx9zahjnlElMd+oLttH7d2ob/LDPXinx1fyTj0jj4L0JpX2hUCyf3ETkhbvK +q71zp9g+MVP+1MPXBTyTcswWK+Yz8L3qml8kOX7+gjSmsiPkZ4/5YGvXLtn7mhI8 +tTv5nQq//y1rM4LmVHUr8nQ7x5alBnC2CkN6e6HDjipYzP9J61G2fH6iaJ+C6C5O ++RTHvmBCZZ1azsoJ9+5IQZNpfD5H8F5gXR2jZ1k8+TxJY3SE -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDaTCCAlECFGA6daD8YxThcAcWI3uEYz3hHQcSMA0GCSqGSIb3DQEBCwUAMHEx +CzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQ +BgNVBAMMCWxvY2FsaG9zdDAeFw0yMTA0MDQxODM5NTNaFw0zMTA0MDMxODM5NTNa +MHExCzAJBgNVBAYTAkFBMRIwEAYDVQQIDAlsb2NhbGhvc3QxEjAQBgNVBAcMCWxv +Y2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3Qx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALbkPJA3vFLtFtbwxnaGTNCo246YKSYeZvcNbe9S7PBT8gUzj2IbPlEtKxIF +lHobmPSImLlns5LHuq8Nc/AH19/tUqqYiQpAZWuJuZzybCsF8lNhMUdREERS+fUR +YKdK43RbDVpg1DbzpIqEp76FDF8ZANyBC2hGCMswy22PuZonTZMg/wAtjyMAU+ZR +/700Wc5pG1F3mzvO0qirYI53rRnF1LR8sRQqYzatg0UK5aixjVKHb4vA8MZFuXPH +eAmHOGOR1tL4J1m2/rC76L36+omnp7VxnKqAzSsWEZ32af1dUxRTugMKR7mX10tG +r0Vsj951uKMhszCKUp2Yhx/Y2vcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAL/Fh +9tbZbE06rG82lBT+m2xUTLM54gX2nEg98soD+YsX8mMvjPTXUOZ71QkKlp02KQra +Pfq8W954JhaYenwVIOnhtGDWdBGZ3ds5SZkRunI4N9nBAxjy1gBu3pGkb1CR0fnK +cgdftyVx1kilXS2hpfIIwjKXyiRS9LRG6xzxamqzZn0cOrjsvOVS353Uyvl0gjBP +s+hveQfm5eILEtaVZ868lZJjmzj+6EOE3iyDcqW7GUNU4foyAmO64ON9tzxxz3fR +0Eut0MVTmXXJPZh7l1buSKswGGGEfrO3GZs7KE+3YLOSfPijj3bg54AqwYHixC8Y +MMMcAm437dbf9GD6PQ== +-----END CERTIFICATE----- diff -Nru civetweb-1.13+dfsg/resources/cert/server.pin civetweb-1.15+dfsg/resources/cert/server.pin --- civetweb-1.13+dfsg/resources/cert/server.pin 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/cert/server.pin 2021-09-01 08:46:33.000000000 +0000 @@ -1 +1 @@ -uz1UTAPen+xb+UoQqkVlEx4H653LbMjfRJcZx5OrjbI= +jh3u6B5TdCEx5ntrP6v5MTUbPciSOGB6/Tzgdnn689M= diff -Nru civetweb-1.13+dfsg/resources/coverity_check.sh civetweb-1.15+dfsg/resources/coverity_check.sh --- civetweb-1.13+dfsg/resources/coverity_check.sh 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/coverity_check.sh 2021-09-01 08:46:33.000000000 +0000 @@ -27,6 +27,7 @@ cp src/response.inl cov_build/src/ cp src/timer.inl cov_build/src/ cp src/handle_form.inl cov_build/src/ +cp src/openssl_dl.inl cov_build/src/ cp include/civetweb.h cov_build/include/ cp resources/Makefile.in-os cov_build/resources/ diff -Nru civetweb-1.13+dfsg/resources/Makefile.in-lua civetweb-1.15+dfsg/resources/Makefile.in-lua --- civetweb-1.13+dfsg/resources/Makefile.in-lua 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/resources/Makefile.in-lua 2021-09-01 08:46:33.000000000 +0000 @@ -29,15 +29,15 @@ LUA_VERSION_KNOWN = 1 endif ifeq ($(WITH_LUA_VERSION), 503) - $(info Lua: Using version 5.3.5) - LUA_DIR = src/third_party/lua-5.3.5/src + $(info Lua: Using version 5.3.6) + LUA_DIR = src/third_party/lua-5.3.6/src LUA_SHARED_LIB_FLAG = -llua5.3 LUA_CFLAGS = -DLUA_COMPAT_5_2 -DLUA_VERSION_MAKEFILE=503 LUA_VERSION_KNOWN = 1 endif ifeq ($(WITH_LUA_VERSION), 504) - $(info Lua: Using version 5.4.0) - LUA_DIR = src/third_party/lua-5.4.0/src + $(info Lua: Using version 5.4.3) + LUA_DIR = src/third_party/lua-5.4.3/src LUA_SHARED_LIB_FLAG = -llua5.4 LUA_CFLAGS = -DLUA_COMPAT_5_2 -DLUA_VERSION_MAKEFILE=504 LUA_VERSION_KNOWN = 1 @@ -49,7 +49,7 @@ # Add flags for all Lua versions -LUA_CFLAGS += -I$(LUA_DIR) -DLUA_COMPAT_ALL -DUSE_LUA +LUA_CFLAGS += -I$(LUA_DIR) -DLUA_COMPAT_ALL -DUSE_LUA -DLUA_UCID ifneq ($(TARGET_OS),WIN32) LUA_CFLAGS += -DLUA_USE_POSIX -DLUA_USE_DLOPEN diff -Nru civetweb-1.13+dfsg/SECURITY.md civetweb-1.15+dfsg/SECURITY.md --- civetweb-1.13+dfsg/SECURITY.md 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/SECURITY.md 2021-09-01 08:46:33.000000000 +0000 @@ -2,14 +2,19 @@ ## Supported Versions -The current "head" version undergoes some automatic tests, but may have defects and vulnerabilities of any kind. -Also development branches may be in an intermediate, untested state. +The current "head" version ("master" branch) undergoes some automatic tests, but may have defects and vulnerabilities. +All development branches may be in an intermediate, untested state. -For released versions, manual tests are performed in addition to automatic tests and static source code analysis. +For released versions, additional tests are performed, including manual tests, static source code analysis and fuzz testing. -Defects will be fixed in the current head version. +Defects will be fixed in the current head version. Selected, critical defects are fixed in the latest release as well. ## Reporting a Vulnerability Please send vulnerability reports by email to bel2125 at gmail com. +Vulnerability with low severity can be sent directly by email. + +For high severity vulnerabilities, you can get an individual gpg key to encrypt your detailed description of vulnerabilities you want to report. + +If you do not get any response within on week, your email might have been lost (e.g., deleted as false positive by a spam filter). In this case, please open a GitHub issue. diff -Nru civetweb-1.13+dfsg/src/CivetServer.cpp civetweb-1.15+dfsg/src/CivetServer.cpp --- civetweb-1.13+dfsg/src/CivetServer.cpp 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/CivetServer.cpp 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017 the Civetweb developers +/* Copyright (c) 2013-2020 the Civetweb developers * Copyright (c) 2013 No Face Press, LLC * * License http://opensource.org/licenses/mit-license.php MIT License @@ -28,6 +28,19 @@ } bool +CivetHandler::handleGet(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -36,6 +49,19 @@ } bool +CivetHandler::handlePost(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handleHead(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -44,6 +70,19 @@ } bool +CivetHandler::handleHead(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -52,6 +91,19 @@ } bool +CivetHandler::handlePut(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handlePatch(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -60,6 +112,19 @@ } bool +CivetHandler::handlePatch(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -68,6 +133,19 @@ } bool +CivetHandler::handleDelete(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetHandler::handleOptions(CivetServer *server, struct mg_connection *conn) { UNUSED_PARAMETER(server); @@ -76,6 +154,19 @@ } bool +CivetHandler::handleOptions(CivetServer *server, + struct mg_connection *conn, + int *status_code) +{ + UNUSED_PARAMETER(server); + UNUSED_PARAMETER(conn); + if (status_code) { + *status_code = -1; + } + return false; +} + +bool CivetWebSocketHandler::handleConnection(CivetServer *server, const struct mg_connection *conn) { @@ -124,6 +215,8 @@ assert(request_info != NULL); CivetServer *me = (CivetServer *)(request_info->user_data); assert(me != NULL); + int http_status_code = -1; + bool status_ok = false; // Happens when a request hits the server before the context is saved if (me->context == NULL) @@ -137,23 +230,48 @@ if (handler) { if (strcmp(request_info->request_method, "GET") == 0) { - return handler->handleGet(me, conn) ? 1 : 0; + status_ok = handler->handleGet(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handleGet(me, conn); + } } else if (strcmp(request_info->request_method, "POST") == 0) { - return handler->handlePost(me, conn) ? 1 : 0; + status_ok = handler->handlePost(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handlePost(me, conn); + } } else if (strcmp(request_info->request_method, "HEAD") == 0) { - return handler->handleHead(me, conn) ? 1 : 0; + status_ok = handler->handleHead(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handleHead(me, conn); + } } else if (strcmp(request_info->request_method, "PUT") == 0) { - return handler->handlePut(me, conn) ? 1 : 0; + status_ok = handler->handlePut(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handlePut(me, conn); + } } else if (strcmp(request_info->request_method, "DELETE") == 0) { - return handler->handleDelete(me, conn) ? 1 : 0; + status_ok = handler->handleDelete(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handleDelete(me, conn); + } } else if (strcmp(request_info->request_method, "OPTIONS") == 0) { - return handler->handleOptions(me, conn) ? 1 : 0; + status_ok = handler->handleOptions(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handleOptions(me, conn); + } } else if (strcmp(request_info->request_method, "PATCH") == 0) { - return handler->handlePatch(me, conn) ? 1 : 0; + status_ok = handler->handlePatch(me, conn, &http_status_code); + if (http_status_code < 0) { + status_ok = handler->handlePatch(me, conn); + } } } - return 0; // No handler found + if (http_status_code < 0) { + http_status_code = status_ok ? 1 : 0; + } + + return http_status_code; } int @@ -278,6 +396,7 @@ : context(0) { struct CivetCallbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); UserContext = UserContextIn; @@ -289,9 +408,10 @@ } callbacks.connection_close = closeHandler; context = mg_start(&callbacks, this, options); - if (context == NULL) + if (context == NULL) { throw CivetException("null context when constructing CivetServer. " "Possible problem binding to port."); + } } CivetServer::CivetServer(const std::vector &options, @@ -300,6 +420,7 @@ : context(0) { struct CivetCallbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); UserContext = UserContextIn; @@ -424,6 +545,14 @@ return mg_get_header(conn, headerName.c_str()); } +const char * +CivetServer::getMethod(struct mg_connection *conn) +{ + const struct mg_request_info *request_info = mg_get_request_info(conn); + assert(request_info != NULL); + return request_info->request_method; +} + void CivetServer::urlDecode(const char *src, std::string &dst, diff -Nru civetweb-1.13+dfsg/src/civetweb.c civetweb-1.15+dfsg/src/civetweb.c --- civetweb-1.13+dfsg/src/civetweb.c 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/civetweb.c 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2020 the Civetweb developers +/* Copyright (c) 2013-2021 the Civetweb developers * Copyright (c) 2004-2013 Sergey Lyubka * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -248,6 +248,7 @@ #if !defined(DEBUG_ASSERT) #if defined(DEBUG) +#include #define DEBUG_ASSERT(cond) \ do { \ if (!(cond)) { \ @@ -316,7 +317,7 @@ #endif -/* Some ANSI #includes are not available on Windows CE */ +/* Some ANSI #includes are not available on Windows CE and Zephyr */ #if !defined(_WIN32_WCE) && !defined(__ZEPHYR__) #include #include @@ -361,8 +362,12 @@ #endif #endif +#ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) +#endif +#ifndef CLOCK_REALTIME #define CLOCK_REALTIME (2) +#endif #include #include @@ -527,15 +532,15 @@ typedef const char *SOCK_OPT_TYPE; -#if !defined(PATH_MAX) -#define W_PATH_MAX (MAX_PATH) -/* at most three UTF-8 chars per wchar_t */ -#define PATH_MAX (W_PATH_MAX * 3) -#else -#define W_PATH_MAX ((PATH_MAX + 2) / 3) -#endif +/* For a detailed description of these *_PATH_MAX defines, see + * https://github.com/civetweb/civetweb/issues/937. */ -mg_static_assert(PATH_MAX >= 1, "path length must be a positive number"); +/* UTF8_PATH_MAX is a char buffer size for 259 BMP characters in UTF-8 plus + * null termination, rounded up to the next 4 bytes boundary */ +#define UTF8_PATH_MAX (3 * 260) +/* UTF16_PATH_MAX is the 16-bit wchar_t buffer size required for 259 BMP + * characters plus termination. (Note: wchar_t is 16 bit on Windows) */ +#define UTF16_PATH_MAX (260) #if !defined(_IN_PORT_T) #if !defined(in_port_t) @@ -543,19 +548,14 @@ #endif #endif -#if !defined(_WIN32_WCE) +#if defined(_WIN32_WCE) +#error "WinCE support has ended" +#endif + #include #include #include -#else /* _WIN32_WCE */ -#define NO_CGI /* WinCE has no pipes */ -#define NO_POPEN /* WinCE has no popen */ - -typedef long off_t; - -#define errno ((int)(GetLastError())) -#define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10)) -#endif /* _WIN32_WCE */ + #define MAKEUQUAD(lo, hi) \ ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32)) @@ -588,6 +588,11 @@ #if defined(_WIN64) || defined(__MINGW64__) #if !defined(SSL_LIB) +#if defined(OPENSSL_API_3_0) +#define SSL_LIB "libssl-3-x64.dll" +#define CRYPTO_LIB "libcrypto-3-x64.dll" +#endif + #if defined(OPENSSL_API_1_1) #define SSL_LIB "libssl-1_1-x64.dll" #define CRYPTO_LIB "libcrypto-1_1-x64.dll" @@ -602,6 +607,11 @@ #else /* defined(_WIN64) || defined(__MINGW64__) */ #if !defined(SSL_LIB) +#if defined(OPENSSL_API_3_0) +#define SSL_LIB "libssl-3.dll" +#define CRYPTO_LIB "libcrypto-3.dll" +#endif + #if defined(OPENSSL_API_1_1) #define SSL_LIB "libssl-1_1.dll" #define CRYPTO_LIB "libcrypto-1_1.dll" @@ -816,7 +826,7 @@ /* POSIX dirent interface */ struct dirent { - char d_name[PATH_MAX]; + char d_name[UTF8_PATH_MAX]; }; typedef struct DIR { @@ -844,6 +854,9 @@ #include +/* Linux & co. internally use UTF8 */ +#define UTF8_PATH_MAX (PATH_MAX) + typedef const void *SOCK_OPT_TYPE; #if defined(ANDROID) @@ -873,6 +886,9 @@ #include #include #include +#if defined(USE_X_DOM_SOCKET) +#include +#endif #endif #define vsnprintf_impl vsnprintf @@ -1056,177 +1072,6 @@ #endif /* _WIN32 */ -#if defined(_WIN32_WCE) -/* Create substitutes for POSIX functions in Win32. */ - -#if defined(GCC_DIAGNOSTIC) -/* Show no warning in case system functions are not used. */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#endif - - -FUNCTION_MAY_BE_UNUSED -static time_t -time(time_t *ptime) -{ - time_t t; - SYSTEMTIME st; - FILETIME ft; - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); - t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime); - - if (ptime != NULL) { - *ptime = t; - } - - return t; -} - - -FUNCTION_MAY_BE_UNUSED -static struct tm * -localtime_s(const time_t *ptime, struct tm *ptm) -{ - int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF; - FILETIME ft, lft; - SYSTEMTIME st; - TIME_ZONE_INFORMATION tzinfo; - - if (ptm == NULL) { - return NULL; - } - - *(int64_t *)&ft = t; - FileTimeToLocalFileTime(&ft, &lft); - FileTimeToSystemTime(&lft, &st); - ptm->tm_year = st.wYear - 1900; - ptm->tm_mon = st.wMonth - 1; - ptm->tm_wday = st.wDayOfWeek; - ptm->tm_mday = st.wDay; - ptm->tm_hour = st.wHour; - ptm->tm_min = st.wMinute; - ptm->tm_sec = st.wSecond; - ptm->tm_yday = 0; /* hope nobody uses this */ - ptm->tm_isdst = - (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT) ? 1 : 0; - - return ptm; -} - - -FUNCTION_MAY_BE_UNUSED -static struct tm * -gmtime_s(const time_t *ptime, struct tm *ptm) -{ - /* FIXME(lsm): fix this. */ - return localtime_s(ptime, ptm); -} - - -static ptrdiff_t mg_atomic_inc(volatile ptrdiff_t *addr); -static struct tm tm_array[MAX_WORKER_THREADS]; /* Must be 2^n */ -static volatile ptrdiff_t tm_index = 0; - - -FUNCTION_MAY_BE_UNUSED -static struct tm * -localtime(const time_t *ptime) -{ - ptrdiff_t i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array); - return localtime_s(ptime, tm_array + i); -} - - -FUNCTION_MAY_BE_UNUSED -static struct tm * -gmtime(const time_t *ptime) -{ - ptrdiff_t i = mg_atomic_inc(&tm_index) % ARRAY_SIZE(tm_array); - return gmtime_s(ptime, tm_array + i); -} - - -FUNCTION_MAY_BE_UNUSED -static size_t -strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm) -{ - /* TODO: (void)mg_snprintf(NULL, dst, dst_size, "implement strftime() - * for WinCE"); */ - return 0; -} - -#define _beginthreadex(psec, stack, func, prm, flags, ptid) \ - (uintptr_t) CreateThread(psec, stack, func, prm, flags, ptid) - -#define remove(f) mg_remove(NULL, f) - - -FUNCTION_MAY_BE_UNUSED -static int -rename(const char *a, const char *b) -{ - wchar_t wa[W_PATH_MAX]; - wchar_t wb[W_PATH_MAX]; - path_to_unicode(NULL, a, wa, ARRAY_SIZE(wa)); - path_to_unicode(NULL, b, wb, ARRAY_SIZE(wb)); - - return MoveFileW(wa, wb) ? 0 : -1; -} - - -struct stat { - int64_t st_size; - time_t st_mtime; -}; - - -FUNCTION_MAY_BE_UNUSED -static int -stat(const char *name, struct stat *st) -{ - wchar_t wbuf[W_PATH_MAX]; - WIN32_FILE_ATTRIBUTE_DATA attr; - time_t creation_time, write_time; - - path_to_unicode(NULL, name, wbuf, ARRAY_SIZE(wbuf)); - memset(&attr, 0, sizeof(attr)); - - GetFileAttributesExW(wbuf, GetFileExInfoStandard, &attr); - st->st_size = - (((int64_t)attr.nFileSizeHigh) << 32) + (int64_t)attr.nFileSizeLow; - - write_time = SYS2UNIX_TIME(attr.ftLastWriteTime.dwLowDateTime, - attr.ftLastWriteTime.dwHighDateTime); - creation_time = SYS2UNIX_TIME(attr.ftCreationTime.dwLowDateTime, - attr.ftCreationTime.dwHighDateTime); - - if (creation_time > write_time) { - st->st_mtime = creation_time; - } else { - st->st_mtime = write_time; - } - return 0; -} - -#define access(x, a) 1 /* not required anyway */ - -/* WinCE-TODO: define stat, remove, rename, _rmdir, _lseeki64 */ -/* Values from errno.h in Windows SDK (Visual Studio). */ -#define EEXIST 17 -#define EACCES 13 -#define ENOENT 2 - -#if defined(GCC_DIAGNOSTIC) -/* Enable unused function warning again */ -#pragma GCC diagnostic pop -#endif - -#endif /* defined(_WIN32_WCE) */ - - #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ #pragma GCC diagnostic push @@ -1314,7 +1159,7 @@ } -#if defined(USE_SERVER_STATS) +#if defined(USE_SERVER_STATS) || defined(STOP_FLAG_NEEDS_LOCK) static ptrdiff_t mg_atomic_add(volatile ptrdiff_t *addr, ptrdiff_t value) { @@ -1704,17 +1549,24 @@ static int mg_init_library_called = 0; #if !defined(NO_SSL) -static int mg_ssl_initialized = 0; - - -/* TODO: Selection of SSL library and version */ -#if !defined(OPENSSL_API_1_0) && !defined(OPENSSL_API_1_1) +#if defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ + || defined(OPENSSL_API_3_0) +static int mg_openssl_initialized = 0; +#endif +#if !defined(OPENSSL_API_1_0) && !defined(OPENSSL_API_1_1) \ + && !defined(OPENSSL_API_3_0) && !defined(USE_MBEDTLS) #error "Please define OPENSSL_API_1_0 or OPENSSL_API_1_1" #endif -#if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_1_1) +#if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_1_1) \ + && defined(OPENSSL_API_3_0) #error "Multiple OPENSSL_API versions defined" #endif -#endif /* NO_SSL */ +#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ + || defined(OPENSSL_API_3_0)) \ + && defined(USE_MBEDTLS) +#error "Multiple SSL libraries defined" +#endif +#endif static pthread_key_t sTlsKey; /* Thread local storage index */ @@ -1772,11 +1624,11 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" -/* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)" - * or not, so one of the two conditions will be unreachable by construction. - * Unfortunately the C standard does not define a way to check this at - * compile time, since the #if preprocessor conditions can not use the sizeof - * operator as an argument. */ + /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)" + * or not, so one of the two conditions will be unreachable by construction. + * Unfortunately the C standard does not define a way to check this at + * compile time, since the #if preprocessor conditions can not use the + * sizeof operator as an argument. */ #endif if (sizeof(pthread_t) > sizeof(unsigned long)) { @@ -1876,11 +1728,18 @@ #endif -#if defined(NO_SSL) +/* SSL: mbedTLS vs. no-ssl vs. OpenSSL */ +#if defined(USE_MBEDTLS) +/* mbedTLS */ +#include "mod_mbedtls.inl" + +#elif defined(NO_SSL) +/* no SSL */ typedef struct SSL SSL; /* dummy for SSL argument to push/pull */ typedef struct SSL_CTX SSL_CTX; -#else -#if defined(NO_SSL_DL) + +#elif defined(NO_SSL_DL) +/* OpenSSL without dynamic loading */ #include #include #include @@ -1914,8 +1773,13 @@ #define ENGINE_cleanup() ((void)0) #endif - /* If OpenSSL headers are included, automatically select the API version */ +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) +#if !defined(OPENSSL_API_3_0) +#define OPENSSL_API_3_0 +#endif +#define OPENSSL_REMOVE_THREAD_STATE() +#else #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) #if !defined(OPENSSL_API_1_1) #define OPENSSL_API_1_1 @@ -1927,530 +1791,16 @@ #endif #define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL) #endif +#endif #else - -/* SSL loaded dynamically from DLL. - * I put the prototypes here to be independent from OpenSSL source +/* SSL loaded dynamically from DLL / shared object */ +/* Add all prototypes here, to be independent from OpenSSL source * installation. */ +#include "openssl_dl.inl" -typedef struct ssl_st SSL; -typedef struct ssl_method_st SSL_METHOD; -typedef struct ssl_ctx_st SSL_CTX; -typedef struct x509_store_ctx_st X509_STORE_CTX; -typedef struct x509_name X509_NAME; -typedef struct asn1_integer ASN1_INTEGER; -typedef struct bignum BIGNUM; -typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; -typedef struct evp_md EVP_MD; -typedef struct x509 X509; - - -#define SSL_CTRL_OPTIONS (32) -#define SSL_CTRL_CLEAR_OPTIONS (77) -#define SSL_CTRL_SET_ECDH_AUTO (94) - -#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L -#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L -#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L - -#define SSL_VERIFY_NONE (0) -#define SSL_VERIFY_PEER (1) -#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2) -#define SSL_VERIFY_CLIENT_ONCE (4) - -#define SSL_OP_ALL (0x80000BFFul) - -#define SSL_OP_NO_SSLv2 (0x01000000ul) -#define SSL_OP_NO_SSLv3 (0x02000000ul) -#define SSL_OP_NO_TLSv1 (0x04000000ul) -#define SSL_OP_NO_TLSv1_2 (0x08000000ul) -#define SSL_OP_NO_TLSv1_1 (0x10000000ul) -#define SSL_OP_NO_TLSv1_3 (0x20000000ul) -#define SSL_OP_SINGLE_DH_USE (0x00100000ul) -#define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000ul) -#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000ul) -#define SSL_OP_NO_COMPRESSION (0x00020000ul) -#define SSL_OP_NO_RENEGOTIATION (0x40000000ul) - -#define SSL_CB_HANDSHAKE_START (0x10) -#define SSL_CB_HANDSHAKE_DONE (0x20) - -#define SSL_ERROR_NONE (0) -#define SSL_ERROR_SSL (1) -#define SSL_ERROR_WANT_READ (2) -#define SSL_ERROR_WANT_WRITE (3) -#define SSL_ERROR_WANT_X509_LOOKUP (4) -#define SSL_ERROR_SYSCALL (5) /* see errno */ -#define SSL_ERROR_ZERO_RETURN (6) -#define SSL_ERROR_WANT_CONNECT (7) -#define SSL_ERROR_WANT_ACCEPT (8) - -#define TLSEXT_TYPE_server_name (0) -#define TLSEXT_NAMETYPE_host_name (0) -#define SSL_TLSEXT_ERR_OK (0) -#define SSL_TLSEXT_ERR_ALERT_WARNING (1) -#define SSL_TLSEXT_ERR_ALERT_FATAL (2) -#define SSL_TLSEXT_ERR_NOACK (3) - -#define SSL_SESS_CACHE_BOTH (3) - -enum ssl_func_category { - TLS_Mandatory, /* required for HTTPS */ - TLS_ALPN, /* required for Application Layer Protocol Negotiation */ - TLS_END_OF_LIST -}; - -/* Check if all TLS functions/features are available */ -static int tls_feature_missing[TLS_END_OF_LIST] = {0}; - -struct ssl_func { - const char *name; /* SSL function name */ - enum ssl_func_category required; /* Mandatory or optional */ - void (*ptr)(void); /* Function pointer */ -}; - - -#if defined(OPENSSL_API_1_1) - -#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) -#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) -#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) -#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) -#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) -#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) -#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) -#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) -#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) -#define TLS_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) -#define OPENSSL_init_ssl \ - (*(int (*)(uint64_t opts, \ - const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10] \ - .ptr) -#define SSL_CTX_use_PrivateKey_file \ - (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) -#define SSL_CTX_use_certificate_file \ - (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) -#define SSL_CTX_set_default_passwd_cb \ - (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) -#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) -#define SSL_CTX_use_certificate_chain_file \ - (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr) -#define TLS_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[16].ptr) -#define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr) -#define SSL_CTX_set_verify \ - (*(void (*)(SSL_CTX *, \ - int, \ - int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18] \ - .ptr) -#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr) -#define SSL_CTX_load_verify_locations \ - (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr) -#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr) -#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr) -#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[23].ptr) -#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr) -#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[25].ptr) -#define SSL_CIPHER_get_name \ - (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr) -#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr) -#define SSL_CTX_set_session_id_context \ - (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr) -#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr) -#define SSL_CTX_set_cipher_list \ - (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr) -#define SSL_CTX_set_options \ - (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr) -#define SSL_CTX_set_info_callback \ - (*(void (*)(SSL_CTX * ctx, void (*callback)(const SSL *, int, int))) \ - ssl_sw[32] \ - .ptr) -#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) -#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) -#define SSL_CTX_callback_ctrl \ - (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) -#define SSL_get_servername \ - (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) -#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) -#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) -#define SSL_CTX_set_alpn_protos \ - (*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr) -typedef int (*tSSL_alpn_select_cb)(SSL *ssl, - const unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen, - void *arg); -#define SSL_CTX_set_alpn_select_cb \ - (*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr) -typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl, - const unsigned char **out, - unsigned int *outlen, - void *arg); -#define SSL_CTX_set_next_protos_advertised_cb \ - (*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \ - .ptr) - -#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr) - -#define SSL_CTX_clear_options(ctx, op) \ - SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) -#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) - -#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 -#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 -#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 -#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ - SSL_CTX_callback_ctrl(ctx, \ - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \ - (void (*)(void))cb) -#define SSL_set_tlsext_host_name(ctx, arg) \ - SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) - -#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) -#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) - -#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) -#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) - -#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL) -#define SSL_CTX_set_session_cache_mode(ctx, mode) \ - SSL_CTX_ctrl(ctx, 44, mode, NULL) - - -#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr) -#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr) -#define CONF_modules_unload (*(void (*)(int))crypto_sw[2].ptr) -#define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr) -#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[4].ptr) -#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[5].ptr) -#define X509_NAME_oneline \ - (*(char *(*)(X509_NAME *, char *, int))crypto_sw[6].ptr) -#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[7].ptr) -#define EVP_get_digestbyname \ - (*(const EVP_MD *(*)(const char *))crypto_sw[8].ptr) -#define EVP_Digest \ - (*(int (*)( \ - const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ - crypto_sw[9] \ - .ptr) -#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[10].ptr) -#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[11].ptr) -#define ASN1_INTEGER_to_BN \ - (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[12].ptr) -#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[13].ptr) -#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[14].ptr) -#define ERR_clear_error (*(void (*)(void))crypto_sw[15].ptr) - -#define OPENSSL_free(a) CRYPTO_free(a) - -#define OPENSSL_REMOVE_THREAD_STATE() - -/* init_ssl_ctx() function updates this array. - * It loads SSL library dynamically and changes NULLs to the actual addresses - * of respective functions. The macros above (like SSL_connect()) are really - * just calling these functions indirectly via the pointer. */ -static struct ssl_func ssl_sw[] = { - {"SSL_free", TLS_Mandatory, NULL}, - {"SSL_accept", TLS_Mandatory, NULL}, - {"SSL_connect", TLS_Mandatory, NULL}, - {"SSL_read", TLS_Mandatory, NULL}, - {"SSL_write", TLS_Mandatory, NULL}, - {"SSL_get_error", TLS_Mandatory, NULL}, - {"SSL_set_fd", TLS_Mandatory, NULL}, - {"SSL_new", TLS_Mandatory, NULL}, - {"SSL_CTX_new", TLS_Mandatory, NULL}, - {"TLS_server_method", TLS_Mandatory, NULL}, - {"OPENSSL_init_ssl", TLS_Mandatory, NULL}, - {"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL}, - {"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL}, - {"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL}, - {"SSL_CTX_free", TLS_Mandatory, NULL}, - {"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL}, - {"TLS_client_method", TLS_Mandatory, NULL}, - {"SSL_pending", TLS_Mandatory, NULL}, - {"SSL_CTX_set_verify", TLS_Mandatory, NULL}, - {"SSL_shutdown", TLS_Mandatory, NULL}, - {"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL}, - {"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL}, - {"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL}, - {"SSL_get_peer_certificate", TLS_Mandatory, NULL}, - {"SSL_get_version", TLS_Mandatory, NULL}, - {"SSL_get_current_cipher", TLS_Mandatory, NULL}, - {"SSL_CIPHER_get_name", TLS_Mandatory, NULL}, - {"SSL_CTX_check_private_key", TLS_Mandatory, NULL}, - {"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL}, - {"SSL_CTX_ctrl", TLS_Mandatory, NULL}, - {"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL}, - {"SSL_CTX_set_options", TLS_Mandatory, NULL}, - {"SSL_CTX_set_info_callback", TLS_Mandatory, NULL}, - {"SSL_get_ex_data", TLS_Mandatory, NULL}, - {"SSL_set_ex_data", TLS_Mandatory, NULL}, - {"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL}, - {"SSL_get_servername", TLS_Mandatory, NULL}, - {"SSL_set_SSL_CTX", TLS_Mandatory, NULL}, - {"SSL_ctrl", TLS_Mandatory, NULL}, - {"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL}, - {"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL}, - {"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL}, - {"SSL_CTX_set_timeout", TLS_Mandatory, NULL}, - {NULL, TLS_END_OF_LIST, NULL}}; - - -/* Similar array as ssl_sw. These functions could be located in different - * lib. */ -static struct ssl_func crypto_sw[] = { - {"ERR_get_error", TLS_Mandatory, NULL}, - {"ERR_error_string", TLS_Mandatory, NULL}, - {"CONF_modules_unload", TLS_Mandatory, NULL}, - {"X509_free", TLS_Mandatory, NULL}, - {"X509_get_subject_name", TLS_Mandatory, NULL}, - {"X509_get_issuer_name", TLS_Mandatory, NULL}, - {"X509_NAME_oneline", TLS_Mandatory, NULL}, - {"X509_get_serialNumber", TLS_Mandatory, NULL}, - {"EVP_get_digestbyname", TLS_Mandatory, NULL}, - {"EVP_Digest", TLS_Mandatory, NULL}, - {"i2d_X509", TLS_Mandatory, NULL}, - {"BN_bn2hex", TLS_Mandatory, NULL}, - {"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL}, - {"BN_free", TLS_Mandatory, NULL}, - {"CRYPTO_free", TLS_Mandatory, NULL}, - {"ERR_clear_error", TLS_Mandatory, NULL}, - {NULL, TLS_END_OF_LIST, NULL}}; -#else - -#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) -#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) -#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) -#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) -#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) -#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) -#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) -#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) -#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) -#define SSLv23_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) -#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr) -#define SSL_CTX_use_PrivateKey_file \ - (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) -#define SSL_CTX_use_certificate_file \ - (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) -#define SSL_CTX_set_default_passwd_cb \ - (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) -#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) -#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr) -#define SSL_CTX_use_certificate_chain_file \ - (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr) -#define SSLv23_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[17].ptr) -#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr) -#define SSL_CTX_set_verify \ - (*(void (*)(SSL_CTX *, \ - int, \ - int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19] \ - .ptr) -#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr) -#define SSL_CTX_load_verify_locations \ - (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr) -#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr) -#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr) -#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[24].ptr) -#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr) -#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[26].ptr) -#define SSL_CIPHER_get_name \ - (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr) -#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr) -#define SSL_CTX_set_session_id_context \ - (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr) -#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr) -#define SSL_CTX_set_cipher_list \ - (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr) -#define SSL_CTX_set_info_callback \ - (*(void (*)(SSL_CTX *, void (*callback)(const SSL *, int, int)))ssl_sw[32] \ - .ptr) -#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) -#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) -#define SSL_CTX_callback_ctrl \ - (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) -#define SSL_get_servername \ - (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) -#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) -#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) -#define SSL_CTX_set_alpn_protos \ - (*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr) -typedef int (*tSSL_alpn_select_cb)(SSL *ssl, - const unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen, - void *arg); -#define SSL_CTX_set_alpn_select_cb \ - (*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr) -typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl, - const unsigned char **out, - unsigned int *outlen, - void *arg); -#define SSL_CTX_set_next_protos_advertised_cb \ - (*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \ - .ptr) - -#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr) - - -#define SSL_CTX_set_options(ctx, op) \ - SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL) -#define SSL_CTX_clear_options(ctx, op) \ - SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) -#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) - -#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 -#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 -#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 -#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ - SSL_CTX_callback_ctrl(ctx, \ - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \ - (void (*)(void))cb) -#define SSL_set_tlsext_host_name(ctx, arg) \ - SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) - -#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) -#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) - -#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) -#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) - -#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL) -#define SSL_CTX_set_session_cache_mode(ctx, mode) \ - SSL_CTX_ctrl(ctx, 44, mode, NULL) - - -#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr) -#define CRYPTO_set_locking_callback \ - (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr) -#define CRYPTO_set_id_callback \ - (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr) -#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr) -#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr) -#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr) -#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr) -#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr) -#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr) -#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr) -#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr) -#define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr) -#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[12].ptr) -#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[13].ptr) -#define X509_NAME_oneline \ - (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr) -#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[15].ptr) -#define i2c_ASN1_INTEGER \ - (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr) -#define EVP_get_digestbyname \ - (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr) -#define EVP_Digest \ - (*(int (*)( \ - const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ - crypto_sw[18] \ - .ptr) -#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr) -#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr) -#define ASN1_INTEGER_to_BN \ - (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[21].ptr) -#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr) -#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr) -#define ERR_clear_error (*(void (*)(void))crypto_sw[24].ptr) - -#define OPENSSL_free(a) CRYPTO_free(a) - -/* use here ERR_remove_state, - * while on some platforms function is not included into library due to - * deprication */ -#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0) - -/* init_ssl_ctx() function updates this array. - * It loads SSL library dynamically and changes NULLs to the actual addresses - * of respective functions. The macros above (like SSL_connect()) are really - * just calling these functions indirectly via the pointer. */ -static struct ssl_func ssl_sw[] = { - {"SSL_free", TLS_Mandatory, NULL}, - {"SSL_accept", TLS_Mandatory, NULL}, - {"SSL_connect", TLS_Mandatory, NULL}, - {"SSL_read", TLS_Mandatory, NULL}, - {"SSL_write", TLS_Mandatory, NULL}, - {"SSL_get_error", TLS_Mandatory, NULL}, - {"SSL_set_fd", TLS_Mandatory, NULL}, - {"SSL_new", TLS_Mandatory, NULL}, - {"SSL_CTX_new", TLS_Mandatory, NULL}, - {"SSLv23_server_method", TLS_Mandatory, NULL}, - {"SSL_library_init", TLS_Mandatory, NULL}, - {"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL}, - {"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL}, - {"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL}, - {"SSL_CTX_free", TLS_Mandatory, NULL}, - {"SSL_load_error_strings", TLS_Mandatory, NULL}, - {"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL}, - {"SSLv23_client_method", TLS_Mandatory, NULL}, - {"SSL_pending", TLS_Mandatory, NULL}, - {"SSL_CTX_set_verify", TLS_Mandatory, NULL}, - {"SSL_shutdown", TLS_Mandatory, NULL}, - {"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL}, - {"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL}, - {"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL}, - {"SSL_get_peer_certificate", TLS_Mandatory, NULL}, - {"SSL_get_version", TLS_Mandatory, NULL}, - {"SSL_get_current_cipher", TLS_Mandatory, NULL}, - {"SSL_CIPHER_get_name", TLS_Mandatory, NULL}, - {"SSL_CTX_check_private_key", TLS_Mandatory, NULL}, - {"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL}, - {"SSL_CTX_ctrl", TLS_Mandatory, NULL}, - {"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL}, - {"SSL_CTX_set_info_callback", TLS_Mandatory, NULL}, - {"SSL_get_ex_data", TLS_Mandatory, NULL}, - {"SSL_set_ex_data", TLS_Mandatory, NULL}, - {"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL}, - {"SSL_get_servername", TLS_Mandatory, NULL}, - {"SSL_set_SSL_CTX", TLS_Mandatory, NULL}, - {"SSL_ctrl", TLS_Mandatory, NULL}, - {"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL}, - {"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL}, - {"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL}, - {"SSL_CTX_set_timeout", TLS_Mandatory, NULL}, - {NULL, TLS_END_OF_LIST, NULL}}; - - -/* Similar array as ssl_sw. These functions could be located in different - * lib. */ -static struct ssl_func crypto_sw[] = { - {"CRYPTO_num_locks", TLS_Mandatory, NULL}, - {"CRYPTO_set_locking_callback", TLS_Mandatory, NULL}, - {"CRYPTO_set_id_callback", TLS_Mandatory, NULL}, - {"ERR_get_error", TLS_Mandatory, NULL}, - {"ERR_error_string", TLS_Mandatory, NULL}, - {"ERR_remove_state", TLS_Mandatory, NULL}, - {"ERR_free_strings", TLS_Mandatory, NULL}, - {"ENGINE_cleanup", TLS_Mandatory, NULL}, - {"CONF_modules_unload", TLS_Mandatory, NULL}, - {"CRYPTO_cleanup_all_ex_data", TLS_Mandatory, NULL}, - {"EVP_cleanup", TLS_Mandatory, NULL}, - {"X509_free", TLS_Mandatory, NULL}, - {"X509_get_subject_name", TLS_Mandatory, NULL}, - {"X509_get_issuer_name", TLS_Mandatory, NULL}, - {"X509_NAME_oneline", TLS_Mandatory, NULL}, - {"X509_get_serialNumber", TLS_Mandatory, NULL}, - {"i2c_ASN1_INTEGER", TLS_Mandatory, NULL}, - {"EVP_get_digestbyname", TLS_Mandatory, NULL}, - {"EVP_Digest", TLS_Mandatory, NULL}, - {"i2d_X509", TLS_Mandatory, NULL}, - {"BN_bn2hex", TLS_Mandatory, NULL}, - {"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL}, - {"BN_free", TLS_Mandatory, NULL}, - {"CRYPTO_free", TLS_Mandatory, NULL}, - {"ERR_clear_error", TLS_Mandatory, NULL}, - {NULL, TLS_END_OF_LIST, NULL}}; -#endif /* OPENSSL_API_1_1 */ -#endif /* NO_SSL_DL */ -#endif /* NO_SSL */ +#endif /* Various SSL bindings */ #if !defined(NO_CACHING) @@ -2468,6 +1818,7 @@ "Dec"}; #endif /* !NO_CACHING */ + /* Unified socket address. For IPv6 support, add IPv6 address structure in * the union u. */ union usa { @@ -2476,8 +1827,24 @@ #if defined(USE_IPV6) struct sockaddr_in6 sin6; #endif +#if defined(USE_X_DOM_SOCKET) + struct sockaddr_un sun; +#endif }; +#if defined(USE_X_DOM_SOCKET) +static unsigned short +USA_IN_PORT_UNSAFE(union usa *s) +{ + if (s->sa.sa_family == AF_INET) + return s->sin.sin_port; +#if defined(USE_IPV6) + if (s->sa.sa_family == AF_INET6) + return s->sin6.sin6_port; +#endif + return 0; +} +#endif #if defined(USE_IPV6) #define USA_IN_PORT_UNSAFE(s) \ (((s)->sa.sa_family == AF_INET6) ? (s)->sin6.sin6_port : (s)->sin.sin_port) @@ -2558,8 +1925,6 @@ CASE_SENSITIVE_FILES, #endif THROTTLE, - ACCESS_LOG_FILE, - ERROR_LOG_FILE, ENABLE_KEEP_ALIVE, REQUEST_TIMEOUT, KEEP_ALIVE_TIMEOUT, @@ -2568,6 +1933,7 @@ ENABLE_WEBSOCKET_PING_PONG, #endif DECODE_URL, + DECODE_QUERY_STRING, #if defined(USE_LUA) LUA_BACKGROUND_SCRIPT, LUA_BACKGROUND_SCRIPT_PARAMS, @@ -2579,20 +1945,44 @@ /* Once for each domain */ DOCUMENT_ROOT, + ACCESS_LOG_FILE, + ERROR_LOG_FILE, + CGI_EXTENSIONS, - CGI2_EXTENSIONS, CGI_ENVIRONMENT, - CGI2_ENVIRONMENT, CGI_INTERPRETER, - CGI2_INTERPRETER, CGI_INTERPRETER_ARGS, - CGI2_INTERPRETER_ARGS, #if defined(USE_TIMERS) CGI_TIMEOUT, +#endif + + CGI2_EXTENSIONS, + CGI2_ENVIRONMENT, + CGI2_INTERPRETER, + CGI2_INTERPRETER_ARGS, +#if defined(USE_TIMERS) CGI2_TIMEOUT, #endif - PUT_DELETE_PASSWORDS_FILE, +#if defined(USE_4_CGI) + CGI3_EXTENSIONS, + CGI3_ENVIRONMENT, + CGI3_INTERPRETER, + CGI3_INTERPRETER_ARGS, +#if defined(USE_TIMERS) + CGI3_TIMEOUT, +#endif + + CGI4_EXTENSIONS, + CGI4_ENVIRONMENT, + CGI4_INTERPRETER, + CGI4_INTERPRETER_ARGS, +#if defined(USE_TIMERS) + CGI4_TIMEOUT, +#endif +#endif + + PUT_DELETE_PASSWORDS_FILE, /* must follow CGI_* */ PROTECT_URI, AUTHENTICATION_DOMAIN, ENABLE_AUTH_DOMAIN_CHECK, @@ -2648,9 +2038,6 @@ #endif ADDITIONAL_HEADER, ALLOW_INDEX_SCRIPT_SUB_RES, -#if defined(DAEMONIZE) - ENABLE_DAEMONIZE, -#endif NUM_OPTIONS }; @@ -2677,8 +2064,6 @@ {"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"}, #endif {"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL}, - {"access_log_file", MG_CONFIG_TYPE_FILE, NULL}, - {"error_log_file", MG_CONFIG_TYPE_FILE, NULL}, {"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"}, {"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"}, {"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"}, @@ -2687,6 +2072,7 @@ {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"}, #endif {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"}, + {"decode_query_string", MG_CONFIG_TYPE_BOOLEAN, "no"}, #if defined(USE_LUA) {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL}, {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL}, @@ -2698,19 +2084,43 @@ /* Once for each domain */ {"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL}, + {"access_log_file", MG_CONFIG_TYPE_FILE, NULL}, + {"error_log_file", MG_CONFIG_TYPE_FILE, NULL}, + {"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"}, - {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, {"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, - {"cgi2_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL}, - {"cgi2_interpreter", MG_CONFIG_TYPE_FILE, NULL}, {"cgi_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, - {"cgi2_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, #if defined(USE_TIMERS) {"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, +#endif + + {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, + {"cgi2_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, + {"cgi2_interpreter", MG_CONFIG_TYPE_FILE, NULL}, + {"cgi2_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, +#if defined(USE_TIMERS) {"cgi2_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, #endif +#if defined(USE_4_CGI) + {"cgi3_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, + {"cgi3_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, + {"cgi3_interpreter", MG_CONFIG_TYPE_FILE, NULL}, + {"cgi3_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, +#if defined(USE_TIMERS) + {"cgi3_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, +#endif + + {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, + {"cgi4_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, + {"cgi4_interpreter", MG_CONFIG_TYPE_FILE, NULL}, + {"cgi4_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, +#if defined(USE_TIMERS) + {"cgi4_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, +#endif +#endif + {"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL}, {"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"}, @@ -2743,14 +2153,9 @@ {"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL}, -#if defined(USE_HTTP2) /* HTTP2 requires ALPN, and anyway TLS1.2 should be considered * as a minimum in 2020 */ {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "4"}, -#else - /* Keep the default (compatibility) */ - {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "0"}, -#endif /* defined(USE_HTTP2) */ {"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"}, @@ -2787,9 +2192,6 @@ #endif {"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL}, {"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"}, -#if defined(DAEMONIZE) - {"daemonize", MG_CONFIG_TYPE_BOOLEAN, "no"}, -#endif {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}}; @@ -2942,13 +2344,13 @@ pthread_t *worker_threadids; /* The worker thread IDs */ unsigned long starter_thread_idx; /* thread index which called mg_start */ -/* Connection to thread dispatching */ + /* Connection to thread dispatching */ #if defined(ALTERNATIVE_QUEUE) struct socket *client_socks; void **client_wait_events; #else struct socket *squeue; /* Socket queue (sq) : accepted sockets waiting for a - worker thread */ + worker thread */ volatile int sq_head; /* Head of the socket queue */ volatile int sq_tail; /* Tail of the socket queue */ pthread_cond_t sq_full; /* Signaled when socket is produced */ @@ -2976,9 +2378,11 @@ struct ttimers *timers; #endif -/* Lua specific: Background operations and shared websockets */ + /* Lua specific: Background operations and shared websockets */ #if defined(USE_LUA) - void *lua_background_state; + void *lua_background_state; /* lua_State (here as void *) */ + pthread_mutex_t lua_bg_mutex; /* Protect background state */ + int lua_bg_log_available; /* Use Lua background state for access log */ #endif /* Server nonce */ @@ -3044,7 +2448,7 @@ int connection_type; /* see CONNECTION_TYPE_* above */ int protocol_type; /* see PROTOCOL_TYPE_*: 0=http/1.x, 1=ws, 2=http/2 */ int request_state; /* 0: nothing sent, 1: header partially sent, 2: header - fully sent */ + fully sent */ #if defined(USE_HTTP2) struct mg_http2_connection http2; #endif @@ -3068,6 +2472,7 @@ #if defined(USE_SERVER_STATS) time_t conn_close_time; /* Time (wall clock) when connection was * closed (or 0 if still open) */ + double processing_time; /* Procesing time for one request. */ #endif struct timespec req_time; /* Time (since system start) when the request * was received */ @@ -3359,11 +2764,11 @@ } __except (EXCEPTION_EXECUTE_HANDLER) { } #elif defined(__MINGW32__) -/* No option known to set thread name for MinGW known */ + /* No option known to set thread name for MinGW known */ #endif #elif defined(_GNU_SOURCE) && defined(__GLIBC__) \ && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12))) -/* pthread_setname_np first appeared in glibc in version 2.12 */ + /* pthread_setname_np first appeared in glibc in version 2.12 */ #if defined(__MACH__) /* OS X only current thread name can be changed */ (void)pthread_setname_np(threadName); @@ -3424,7 +2829,7 @@ struct mg_file_stat *filep); -/* Reject files with special characters */ +/* Reject files with special characters (for Windows) */ static int mg_path_suspicious(const struct mg_connection *conn, const char *path) { @@ -3436,28 +2841,27 @@ return 1; } +#if defined(_WIN32) while (*c) { - if (*c <= 32) { - /* Control character or space */ - return 0; + if (*c < 32) { + /* Control character */ + return 1; } if ((*c == '>') || (*c == '<') || (*c == '|')) { /* stdin/stdout redirection character */ - return 0; + return 1; } -#if defined(_WIN32) - if (*c == '\\') { - /* Windows backslash */ - return 0; + if ((*c == '*') || (*c == '?')) { + /* Wildcard character */ + return 1; } -#else - if (*c == '&') { - /* Linux ampersand */ - return 0; + if (*c == '"') { + /* Windows quotation */ + return 1; } -#endif c++; } +#endif /* Nothing suspicious found */ return 0; @@ -3498,7 +2902,7 @@ #if defined(_WIN32) { - wchar_t wbuf[W_PATH_MAX]; + wchar_t wbuf[UTF16_PATH_MAX]; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); switch (mode) { case MG_FOPEN_MODE_READ: @@ -3558,7 +2962,7 @@ static void -mg_strlcpy(register char *dst, register const char *src, size_t n) +mg_strlcpy(char *dst, const char *src, size_t n) { for (; *src != '\0' && n > 1; n--) { *dst++ = *src++; @@ -3669,8 +3073,8 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" -/* Using fmt as a non-literal is intended here, since it is mostly called - * indirectly by mg_snprintf */ + /* Using fmt as a non-literal is intended here, since it is mostly called + * indirectly by mg_snprintf */ #endif n = (int)vsnprintf_impl(buf, buflen, fmt, ap); @@ -3781,9 +3185,13 @@ void -mg_set_user_connection_data(struct mg_connection *conn, void *data) +mg_set_user_connection_data(const struct mg_connection *const_conn, void *data) { - if (conn != NULL) { + if (const_conn != NULL) { + /* Const cast, since "const struct mg_connection *" does not mean + * the connection object is not modified. Here "const" is used, + * to indicate mg_read/mg_write/mg_send/.. must not be called. */ + struct mg_connection *conn = (struct mg_connection *)const_conn; conn->request_info.conn_data = data; } } @@ -3799,24 +3207,6 @@ } -#if defined(MG_LEGACY_INTERFACE) -/* Deprecated: Use mg_get_server_ports instead. */ -size_t -mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl) -{ - size_t i; - if (!ctx) { - return 0; - } - for (i = 0; i < size && i < ctx->num_listening_sockets; i++) { - ssl[i] = ctx->listening_sockets[i].is_ssl; - ports[i] = ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa))); - } - return i; -} -#endif - - int mg_get_server_ports(const struct mg_context *ctx, int size, @@ -3857,6 +3247,10 @@ } +#if defined(USE_X_DOM_SOCKET) && !defined(UNIX_DOMAIN_SOCKET_SERVER_NAME) +#define UNIX_DOMAIN_SOCKET_SERVER_NAME "*" +#endif + static void sockaddr_to_string(char *buf, size_t len, const union usa *usa) { @@ -3886,6 +3280,22 @@ NI_NUMERICHOST); } #endif +#if defined(USE_X_DOM_SOCKET) + else if (usa->sa.sa_family == AF_UNIX) { + /* TODO: Define a remote address for unix domain sockets. + * This code will always return "localhost", identical to http+tcp: + getnameinfo(&usa->sa, + sizeof(usa->sun), + buf, + (unsigned)len, + NULL, + 0, + NI_NUMERICHOST); + */ + strncpy(buf, UNIX_DOMAIN_SOCKET_SERVER_NAME, len); + buf[len] = 0; + } +#endif } @@ -4092,8 +3502,11 @@ } ((struct mg_connection *)conn)->request_info.local_uri = - ((struct mg_connection *)conn)->request_info.request_uri = - tls->txtbuf; /* use thread safe buffer */ + tls->txtbuf; /* use thread safe buffer */ + ((struct mg_connection *)conn)->request_info.local_uri_raw = + tls->txtbuf; /* use the same thread safe buffer */ + ((struct mg_connection *)conn)->request_info.request_uri = + tls->txtbuf; /* use the same thread safe buffer */ ((struct mg_connection *)conn)->request_info.num_headers = conn->response_info.num_headers; @@ -4128,11 +3541,11 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" -/* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be - * not supported. Clang raises an "unreachable code" warning for parts of ?: - * unreachable, but splitting into four different #ifdef clauses here is more - * complicated. - */ + /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be + * not supported. Clang raises an "unreachable code" warning for parts of ?: + * unreachable, but splitting into four different #ifdef clauses here is + * more complicated. + */ #endif const struct mg_request_info *ri = &conn->request_info; @@ -4160,7 +3573,6 @@ if ((buflen < 1) || (buf == 0) || (conn == 0)) { return -1; } else { - int truncated = 0; const struct mg_request_info *ri = &conn->request_info; @@ -4170,15 +3582,38 @@ (define_uri != NULL) ? define_uri : ((ri->request_uri != NULL) ? ri->request_uri : ri->local_uri); - int port = (define_port > 0) - ? define_port - : htons(USA_IN_PORT_UNSAFE(&conn->client.lsa)); + int port = (define_port > 0) ? define_port : ri->server_port; int default_port = 80; if (uri == NULL) { return -1; } +#if defined(USE_X_DOM_SOCKET) + if (conn->client.lsa.sa.sa_family == AF_UNIX) { + /* TODO: Define and document a link for UNIX domain sockets. */ + /* There seems to be no official standard for this. + * Common uses seem to be "httpunix://", "http.unix://" or + * "http+unix://" as a protocol definition string, followed by + * "localhost" or "127.0.0.1" or "/tmp/unix/path" or + * "%2Ftmp%2Funix%2Fpath" (url % encoded) or + * "localhost:%2Ftmp%2Funix%2Fpath" (domain socket path as port) or + * "" (completely skipping the server name part). In any case, the + * last part is the server local path. */ + const char *server_name = UNIX_DOMAIN_SOCKET_SERVER_NAME; + mg_snprintf(conn, + &truncated, + buf, + buflen, + "%s.unix://%s%s", + proto, + server_name, + ri->local_uri); + default_port = 0; + return 0; + } +#endif + if (define_proto) { /* If we got a protocol name, use the default port accordingly. */ if ((0 == strcmp(define_proto, "https")) @@ -4301,7 +3736,7 @@ } else { #if defined(GCC_DIAGNOSTIC) -/* Disable spurious conversion warning for GCC */ + /* Disable spurious conversion warning for GCC */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #endif /* defined(GCC_DIAGNOSTIC) */ @@ -4589,6 +4024,18 @@ } +static int +should_decode_query_string(const struct mg_connection *conn) +{ + if (!conn || !conn->dom_ctx) { + return 0; + } + + return (mg_strcasecmp(conn->dom_ctx->config[DECODE_QUERY_STRING], "yes") + == 0); +} + + static const char * suggest_connection_header(const struct mg_connection *conn) { @@ -4707,7 +4154,7 @@ */ switch (response_code) { - /* RFC2616 Section 10.1 - Informational 1xx */ + /* RFC2616 Section 10.1 - Informational 1xx */ case 100: return "Continue"; /* RFC2616 Section 10.1.1 */ case 101: @@ -4715,7 +4162,7 @@ case 102: return "Processing"; /* RFC2518 Section 10.1 */ - /* RFC2616 Section 10.2 - Successful 2xx */ + /* RFC2616 Section 10.2 - Successful 2xx */ case 200: return "OK"; /* RFC2616 Section 10.2.1 */ case 201: @@ -4739,7 +4186,7 @@ case 226: return "IM used"; /* RFC3229 Section 10.4.1 */ - /* RFC2616 Section 10.3 - Redirection 3xx */ + /* RFC2616 Section 10.3 - Redirection 3xx */ case 300: return "Multiple Choices"; /* RFC2616 Section 10.3.1 */ case 301: @@ -4757,7 +4204,7 @@ case 308: return "Permanent Redirect"; /* RFC7238 Section 3 */ - /* RFC2616 Section 10.4 - Client Error 4xx */ + /* RFC2616 Section 10.4 - Client Error 4xx */ case 400: return "Bad Request"; /* RFC2616 Section 10.4.1 */ case 401: @@ -4822,7 +4269,7 @@ return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05, * Section 3 */ - /* RFC2616 Section 10.5 - Server Error 5xx */ + /* RFC2616 Section 10.5 - Server Error 5xx */ case 500: return "Internal Server Error"; /* RFC2616 Section 10.5.1 */ case 501: @@ -4848,9 +4295,9 @@ case 511: return "Network Authentication Required"; /* RFC 6585, Section 6 */ - /* Other status codes, not shown in the IANA HTTP status code - * assignment. - * E.g., "de facto" standards due to common use, ... */ + /* Other status codes, not shown in the IANA HTTP status code + * assignment. + * E.g., "de facto" standards due to common use, ... */ case 418: return "I am a teapot"; /* RFC2324 Section 2.3.2 */ case 419: @@ -4909,7 +4356,7 @@ int has_body; #if !defined(NO_FILESYSTEMS) - char path_buf[PATH_MAX]; + char path_buf[UTF8_PATH_MAX]; int len, i, page_handler_found, scope, truncated; const char *error_handler = NULL; struct mg_file error_page_file = STRUCT_FILE_INITIALIZER; @@ -5309,7 +4756,8 @@ struct mg_workerTLS **ptls, *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); int ok; - int64_t nsnow, nswaitabs, nswaitrel; + uint64_t nsnow, nswaitabs; + int64_t nswaitrel; DWORD mswaitrel; pthread_mutex_lock(&cv->threadIdSec); @@ -5324,7 +4772,7 @@ if (abstime) { nsnow = mg_get_current_time_ns(); nswaitabs = - (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec; + (((uint64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec; nswaitrel = nswaitabs - nsnow; if (nswaitrel < 0) { nswaitrel = 0; @@ -5504,8 +4952,8 @@ wchar_t *wbuf, size_t wbuf_len) { - char buf[PATH_MAX], buf2[PATH_MAX]; - wchar_t wbuf2[W_PATH_MAX + 1]; + char buf[UTF8_PATH_MAX], buf2[UTF8_PATH_MAX]; + wchar_t wbuf2[UTF16_PATH_MAX + 1]; DWORD long_len, err; int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp; @@ -5541,7 +4989,6 @@ } (void)conn; /* conn is currently unused */ -#if !defined(_WIN32_WCE) /* Only accept a full file path, not a Windows short (8.3) path. */ memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t)); long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1); @@ -5556,15 +5003,6 @@ /* Short name is used. */ wbuf[0] = L'\0'; } -#else - (void)long_len; - (void)wbuf2; - (void)err; - - if (strchr(path, '~')) { - wbuf[0] = L'\0'; - } -#endif } @@ -5575,7 +5013,7 @@ const char *path, struct mg_file_stat *filep) { - wchar_t wbuf[W_PATH_MAX]; + wchar_t wbuf[UTF16_PATH_MAX]; WIN32_FILE_ATTRIBUTE_DATA info; time_t creation_time; size_t len; @@ -5623,7 +5061,7 @@ static int mg_remove(const struct mg_connection *conn, const char *path) { - wchar_t wbuf[W_PATH_MAX]; + wchar_t wbuf[UTF16_PATH_MAX]; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); return DeleteFileW(wbuf) ? 0 : -1; } @@ -5632,7 +5070,7 @@ static int mg_mkdir(const struct mg_connection *conn, const char *path, int mode) { - wchar_t wbuf[W_PATH_MAX]; + wchar_t wbuf[UTF16_PATH_MAX]; (void)mode; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); return CreateDirectoryW(wbuf, NULL) ? 0 : -1; @@ -5654,7 +5092,7 @@ mg_opendir(const struct mg_connection *conn, const char *name) { DIR *dir = NULL; - wchar_t wpath[W_PATH_MAX]; + wchar_t wpath[UTF16_PATH_MAX]; DWORD attrs; if (name == NULL) { @@ -5737,9 +5175,11 @@ #undef POLLIN #undef POLLPRI #undef POLLOUT +#undef POLLERR #define POLLIN (1) /* Data ready - read will not block. */ #define POLLPRI (2) /* Priority data ready. */ #define POLLOUT (4) /* Send queue not full - write will not block. */ +#define POLLERR (8) /* Error event */ FUNCTION_MAY_BE_UNUSED static int @@ -5748,6 +5188,7 @@ struct timeval tv; fd_set rset; fd_set wset; + fd_set eset; unsigned int i; int result; SOCKET maxfd = 0; @@ -5757,13 +5198,18 @@ tv.tv_usec = (milliseconds % 1000) * 1000; FD_ZERO(&rset); FD_ZERO(&wset); + FD_ZERO(&eset); for (i = 0; i < n; i++) { - if (pfd[i].events & POLLIN) { - FD_SET(pfd[i].fd, &rset); - } - if (pfd[i].events & POLLOUT) { - FD_SET(pfd[i].fd, &wset); + if (pfd[i].events & (POLLIN | POLLOUT | POLLERR)) { + if (pfd[i].events & POLLIN) { + FD_SET(pfd[i].fd, &rset); + } + if (pfd[i].events & POLLOUT) { + FD_SET(pfd[i].fd, &wset); + } + /* Check for errors for any FD in the set */ + FD_SET(pfd[i].fd, &eset); } pfd[i].revents = 0; @@ -5772,7 +5218,7 @@ } } - if ((result = select((int)maxfd + 1, &rset, &wset, NULL, &tv)) > 0) { + if ((result = select((int)maxfd + 1, &rset, &wset, &eset, &tv)) > 0) { for (i = 0; i < n; i++) { if (FD_ISSET(pfd[i].fd, &rset)) { pfd[i].revents |= POLLIN; @@ -5780,6 +5226,9 @@ if (FD_ISSET(pfd[i].fd, &wset)) { pfd[i].revents |= POLLOUT; } + if (FD_ISSET(pfd[i].fd, &eset)) { + pfd[i].revents |= POLLERR; + } } } @@ -5808,11 +5257,8 @@ { (void)conn; /* Unused. */ (void)ctx; -#if defined(_WIN32_WCE) - (void)sock; -#else + (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0); -#endif } @@ -5893,7 +5339,7 @@ static HANDLE dlopen(const char *dll_name, int flags) { - wchar_t wbuf[W_PATH_MAX]; + wchar_t wbuf[UTF16_PATH_MAX]; (void)flags; path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf)); return LoadLibraryW(wbuf); @@ -5983,12 +5429,13 @@ int fdin[2], int fdout[2], int fderr[2], - const char *dir) + const char *dir, + unsigned char cgi_config_idx) { HANDLE me; char *interp; char *interp_arg = 0; - char full_dir[PATH_MAX], cmdline[PATH_MAX], buf[PATH_MAX]; + char full_dir[UTF8_PATH_MAX], cmdline[UTF8_PATH_MAX], buf[UTF8_PATH_MAX]; int truncated; struct mg_file file = STRUCT_FILE_INITIALIZER; STARTUPINFOA si; @@ -6040,11 +5487,12 @@ /* First check, if there is a CGI interpreter configured for all CGI * scripts. */ - interp = conn->dom_ctx->config[CGI_INTERPRETER]; + interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx]; if (interp != NULL) { /* If there is a configured interpreter, check for additional arguments */ - interp_arg = conn->dom_ctx->config[CGI_INTERPRETER_ARGS]; + interp_arg = + conn->dom_ctx->config[CGI_INTERPRETER_ARGS + cgi_config_idx]; } else { /* Otherwise, the interpreter must be stated in the first line of the * CGI script file, after a #! (shebang) mark. */ @@ -6293,7 +5741,8 @@ int fdin[2], int fdout[2], int fderr[2], - const char *dir) + const char *dir, + unsigned char cgi_config_idx) { pid_t pid; const char *interp; @@ -6356,7 +5805,7 @@ sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); - interp = conn->dom_ctx->config[CGI_INTERPRETER]; + interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx]; if (interp == NULL) { /* no interpreter configured, call the programm directly */ (void)execle(prog, prog, NULL, envp); @@ -6368,7 +5817,8 @@ } else { /* call the configured interpreter */ const char *interp_args = - conn->dom_ctx->config[CGI_INTERPRETER_ARGS]; + conn->dom_ctx + ->config[CGI_INTERPRETER_ARGS + cgi_config_idx]; if ((interp_args != NULL) && (interp_args[0] != 0)) { (void)execle(interp, interp, interp_args, prog, NULL, envp); @@ -6457,13 +5907,20 @@ mg_poll(struct mg_pollfd *pfd, unsigned int n, int milliseconds, - stop_flag_t *stop_flag) + const stop_flag_t *stop_flag) { /* Call poll, but only for a maximum time of a few seconds. * This will allow to stop the server after some seconds, instead * of having to wait for a long socket timeout. */ int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */ + int check_pollerr = 0; + if ((n == 1) && ((pfd[0].events & POLLERR) == 0)) { + /* If we wait for only one file descriptor, wait on error as well */ + pfd[0].events |= POLLERR; + check_pollerr = 1; + } + do { int result; @@ -6480,6 +5937,12 @@ if (result != 0) { /* Poll returned either success (1) or error (-1). * Forward both to the caller. */ + if ((check_pollerr) + && ((pfd[0].revents & (POLLIN | POLLOUT | POLLERR)) + == POLLERR)) { + /* One and only file descriptor returned error */ + return -1; + } return result; } @@ -6531,7 +5994,7 @@ return -2; } -#if defined(NO_SSL) +#if defined(NO_SSL) && !defined(USE_MBEDTLS) if (ssl) { return -2; } @@ -6541,7 +6004,23 @@ * shuts down. */ for (;;) { -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) + if (ssl != NULL) { + n = mbed_ssl_write(ssl, (const unsigned char *)buf, len); + if (n <= 0) { + if ((n == MBEDTLS_ERR_SSL_WANT_READ) + || (n == MBEDTLS_ERR_SSL_WANT_WRITE) + || n == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { + n = 0; + } else { + fprintf(stderr, "SSL write failed, error %d\n", n); + return -2; + } + } else { + err = 0; + } + } else +#elif !defined(NO_SSL) if (ssl != NULL) { ERR_clear_error(); n = SSL_write(ssl, buf, len); @@ -6563,6 +6042,7 @@ } } else #endif + if (fp != NULL) { n = (int)fwrite(buf, 1, (size_t)len, fp); if (ferror(fp)) { @@ -6645,7 +6125,7 @@ } (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not - used */ + used */ return -1; } @@ -6670,7 +6150,8 @@ timeout = atoi(ctx->dd.config[REQUEST_TIMEOUT]) / 1000.0; } if (timeout <= 0.0) { - timeout = atof(config_options[REQUEST_TIMEOUT].default_value) / 1000.0; + timeout = strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) + / 1000.0; } while ((len > 0) && STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { @@ -6719,23 +6200,74 @@ */ if (fp != NULL) { -#if !defined(_WIN32_WCE) /* Use read() instead of fread(), because if we're reading from the * CGI pipe, fread() may block until IO buffer is filled up. We * cannot afford to block and must pass all read bytes immediately * to the client. */ nread = (int)read(fileno(fp), buf, (size_t)len); -#else - /* WinCE does not support CGI pipes */ - nread = (int)fread(buf, 1, (size_t)len, fp); -#endif + err = (nread < 0) ? ERRNO : 0; if ((nread == 0) && (len > 0)) { /* Should get data, but got EOL */ return -2; } -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) + } else if (conn->ssl != NULL) { + struct mg_pollfd pfd[1]; + int to_read; + int pollres; + + to_read = mbedtls_ssl_get_bytes_avail(conn->ssl); + + if (to_read > 0) { + /* We already know there is no more data buffered in conn->buf + * but there is more available in the SSL layer. So don't poll + * conn->client.sock yet. */ + + pollres = 1; + if (to_read > len) + to_read = len; + } else { + pfd[0].fd = conn->client.sock; + pfd[0].events = POLLIN; + + to_read = len; + + pollres = mg_poll(pfd, + 1, + (int)(timeout * 1000.0), + &(conn->phys_ctx->stop_flag)); + + if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { + return -2; + } + } + + if (pollres > 0) { + nread = mbed_ssl_read(conn->ssl, (unsigned char *)buf, to_read); + if (nread <= 0) { + if ((nread == MBEDTLS_ERR_SSL_WANT_READ) + || (nread == MBEDTLS_ERR_SSL_WANT_WRITE) + || nread == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { + nread = 0; + } else { + fprintf(stderr, "SSL read failed, error %d\n", nread); + return -2; + } + } else { + err = 0; + } + + } else if (pollres < 0) { + /* Error */ + return -2; + } else { + /* pollres = 0 means timeout */ + nread = 0; + } + +#elif !defined(NO_SSL) } else if (conn->ssl != NULL) { int ssl_pending; struct mg_pollfd pfd[1]; @@ -6829,7 +6361,7 @@ } if (nread < 0) { -/* socket error - check errno */ + /* socket error - check errno */ #if defined(_WIN32) if (err == WSAEWOULDBLOCK) { /* TODO (low): check if this is still required */ @@ -6887,7 +6419,8 @@ timeout = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0; } if (timeout <= 0.0) { - timeout = atof(config_options[REQUEST_TIMEOUT].default_value) / 1000.0; + timeout = strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) + / 1000.0; } start_time = mg_get_current_time_ns(); timeout_ns = (uint64_t)(timeout * 1.0E9); @@ -6994,6 +6527,40 @@ /* Forward declarations */ static void handle_request(struct mg_connection *); +static void log_access(const struct mg_connection *); + + +/* Handle request, update statistics and call access log */ +static void +handle_request_stat_log(struct mg_connection *conn) +{ +#if defined(USE_SERVER_STATS) + struct timespec tnow; + conn->conn_state = 4; /* processing */ +#endif + + handle_request(conn); + + +#if defined(USE_SERVER_STATS) + conn->conn_state = 5; /* processed */ + + clock_gettime(CLOCK_MONOTONIC, &tnow); + conn->processing_time = mg_difftimespec(&tnow, &(conn->req_time)); + + mg_atomic_add64(&(conn->phys_ctx->total_data_read), conn->consumed_content); + mg_atomic_add64(&(conn->phys_ctx->total_data_written), + conn->num_bytes_sent); +#endif + + DEBUG_TRACE("%s", "handle_request done"); + + if (conn->phys_ctx->callbacks.end_request != NULL) { + conn->phys_ctx->callbacks.end_request(conn, conn->status_code); + DEBUG_TRACE("%s", "end_request callback done"); + } + log_access(conn); +} #if defined(USE_HTTP2) @@ -7754,15 +7321,9 @@ ) { #if !defined(NO_CGI) - if (match_prefix_strlen(conn->dom_ctx->config[CGI_EXTENSIONS], filename) - > 0) { - return 1; - } - if (match_prefix_strlen(conn->dom_ctx->config[CGI2_EXTENSIONS], filename) - > 0) { - return 1; - } + unsigned char cgi_config_idx, inc, max; #endif + #if defined(USE_LUA) if (match_prefix_strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS], filename) @@ -7777,6 +7338,19 @@ return 1; } #endif +#if !defined(NO_CGI) + inc = CGI2_EXTENSIONS - CGI_EXTENSIONS; + max = PUT_DELETE_PASSWORDS_FILE - CGI_EXTENSIONS; + for (cgi_config_idx = 0; cgi_config_idx < max; cgi_config_idx += inc) { + if ((conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx] != NULL) + && (match_prefix_strlen( + conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx], + filename) + > 0)) { + return 1; + } + } +#endif /* filename and conn could be unused, if all preocessor conditions * are false (no script language supported). */ (void)filename; @@ -7878,7 +7452,7 @@ const char *rewrite; struct vec a, b; ptrdiff_t match_len; - char gz_path[PATH_MAX]; + char gz_path[UTF8_PATH_MAX]; int truncated; #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) char *tmp_str; @@ -7899,8 +7473,8 @@ /* Step 2: Check if the request attempts to modify the file system */ *is_put_or_delete_request = is_put_or_delete_method(conn); -/* Step 3: Check if it is a websocket request, and modify the document - * root if required */ + /* Step 3: Check if it is a websocket request, and modify the document + * root if required */ #if defined(USE_WEBSOCKET) *is_websocket_request = (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET); #if !defined(NO_FILES) @@ -8061,7 +7635,8 @@ /* Step 10: Script resources may handle sub-resources */ /* Support PATH_INFO for CGI scripts. */ tmp_str_len = strlen(filename); - tmp_str = (char *)mg_malloc_ctx(tmp_str_len + PATH_MAX + 1, conn->phys_ctx); + tmp_str = + (char *)mg_malloc_ctx(tmp_str_len + UTF8_PATH_MAX + 1, conn->phys_ctx); if (!tmp_str) { /* Out of memory */ goto interpret_cleanup; @@ -8099,7 +7674,7 @@ if (allow_substitute_script_subresources) { if (substitute_index_file( - conn, tmp_str, tmp_str_len + PATH_MAX, filestat)) { + conn, tmp_str, tmp_str_len + UTF8_PATH_MAX, filestat)) { /* some intermediate directory has an index file */ if (extention_matches_script(conn, tmp_str)) { @@ -8107,7 +7682,7 @@ size_t script_name_len = strlen(tmp_str); /* subres_name read before this memory locatio will be - overwritten */ + overwritten */ char *subres_name = filename + sep_pos; size_t subres_name_len = strlen(subres_name); @@ -8453,11 +8028,17 @@ /* IANA registered MIME types * (http://www.iana.org/assignments/media-types) * application types */ + {".bin", 4, "application/octet-stream"}, + {".deb", 4, "application/octet-stream"}, + {".dmg", 4, "application/octet-stream"}, + {".dll", 4, "application/octet-stream"}, {".doc", 4, "application/msword"}, {".eps", 4, "application/postscript"}, {".exe", 4, "application/octet-stream"}, + {".iso", 4, "application/octet-stream"}, {".js", 3, "application/javascript"}, {".json", 5, "application/json"}, + {".msi", 4, "application/octet-stream"}, {".pdf", 4, "application/pdf"}, {".ps", 3, "application/postscript"}, {".rtf", 4, "application/rtf"}, @@ -8473,6 +8054,7 @@ {".sil", 4, "application/font-sfnt"}, {".pfr", 4, "application/font-tdpfr"}, {".woff", 5, "application/font-woff"}, + {".woff2", 6, "application/font-woff2"}, /* audio */ {".mp3", 4, "audio/mpeg"}, @@ -8529,6 +8111,7 @@ {".aac", 4, "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */ + {".flac", 5, "audio/flac"}, {".aif", 4, "audio/x-aif"}, {".m3u", 4, "audio/x-mpegurl"}, {".mid", 4, "audio/x-midi"}, @@ -8693,7 +8276,7 @@ struct mg_file *filep) { if ((conn != NULL) && (conn->dom_ctx != NULL)) { - char name[PATH_MAX]; + char name[UTF8_PATH_MAX]; const char *p, *e, *gpass = conn->dom_ctx->config[GLOBAL_PASSWORDS_FILE]; int truncated; @@ -9084,7 +8667,7 @@ check_authorization(struct mg_connection *conn, const char *path) { #if !defined(NO_FILESYSTEMS) - char fname[PATH_MAX]; + char fname[UTF8_PATH_MAX]; struct vec uri_vec, filename_vec; const char *list; struct mg_file file = STRUCT_FILE_INITIALIZER; @@ -9218,14 +8801,16 @@ #endif -int -mg_modify_passwords_file(const char *fname, - const char *domain, - const char *user, - const char *pass) +static int +modify_passwords_file(const char *fname, + const char *domain, + const char *user, + const char *pass, + const char *ha1) { int found, i; - char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8]; + char line[512], u[512] = "", d[512] = "", ha1buf[33], + tmp[UTF8_PATH_MAX + 8]; FILE *fp, *fp2; found = 0; @@ -9271,7 +8856,7 @@ } /* The maximum length of the path to the password file is limited */ - if ((strlen(fname) + 4) >= PATH_MAX) { + if ((strlen(fname) + 4) >= UTF8_PATH_MAX) { return 0; } @@ -9304,7 +8889,9 @@ if (!strcmp(u, user) && !strcmp(d, domain)) { found++; if (pass != NULL) { - mg_md5(ha1, user, ":", domain, ":", pass, NULL); + mg_md5(ha1buf, user, ":", domain, ":", pass, NULL); + fprintf(fp2, "%s:%s:%s\n", user, domain, ha1buf); + } else if (ha1 != NULL) { fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); } } else { @@ -9313,9 +8900,13 @@ } /* If new user, just add it */ - if (!found && (pass != NULL)) { - mg_md5(ha1, user, ":", domain, ":", pass, NULL); - fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); + if (!found) { + if (pass != NULL) { + mg_md5(ha1buf, user, ":", domain, ":", pass, NULL); + fprintf(fp2, "%s:%s:%s\n", user, domain, ha1buf); + } else if (ha1 != NULL) { + fprintf(fp2, "%s:%s:%s\n", user, domain, ha1); + } } /* Close files */ @@ -9330,6 +8921,26 @@ } +int +mg_modify_passwords_file(const char *fname, + const char *domain, + const char *user, + const char *pass) +{ + return modify_passwords_file(fname, domain, user, pass, NULL); +} + + +int +mg_modify_passwords_file_ha1(const char *fname, + const char *domain, + const char *user, + const char *ha1) +{ + return modify_passwords_file(fname, domain, user, NULL, ha1); +} + + static int is_valid_port(unsigned long port) { @@ -9379,14 +8990,15 @@ static int -connect_socket(struct mg_context *ctx /* may be NULL */, - const char *host, - int port, - int use_ssl, - char *ebuf, - size_t ebuf_len, - SOCKET *sock /* output: socket, must not be NULL */, - union usa *sa /* output: socket address, must not be NULL */ +connect_socket( + struct mg_context *ctx /* may be NULL */, + const char *host, + int port, /* 1..65535, or -99 for domain sockets (may be changed) */ + int use_ssl, /* 0 or 1 */ + char *ebuf, + size_t ebuf_len, + SOCKET *sock /* output: socket, must not be NULL */, + union usa *sa /* output: socket address, must not be NULL */ ) { int ip_ver = 0; @@ -9409,7 +9021,22 @@ return 0; } - if ((port <= 0) || !is_valid_port((unsigned)port)) { +#if defined(USE_X_DOM_SOCKET) + if (port == -99) { + /* Unix domain socket */ + size_t hostlen = strlen(host); + if (hostlen >= sizeof(sa->sun.sun_path)) { + mg_snprintf(NULL, + NULL, /* No truncation check for ebuf */ + ebuf, + ebuf_len, + "%s", + "host length exceeds limit"); + return 0; + } + } else +#endif + if ((port <= 0) || !is_valid_port((unsigned)port)) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ ebuf, @@ -9419,9 +9046,8 @@ return 0; } -#if !defined(NO_SSL) -#if !defined(NO_SSL_DL) -#if defined(OPENSSL_API_1_1) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(NO_SSL_DL) +#if defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0) if (use_ssl && (TLS_client_method == NULL)) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ @@ -9441,16 +9067,23 @@ "SSL is not initialized"); return 0; } - -#endif /* OPENSSL_API_1_1 */ +#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0*/ #else (void)use_ssl; -#endif /* NO_SSL_DL */ -#else - (void)use_ssl; -#endif /* !defined(NO_SSL) */ +#endif /* NO SSL */ + - if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin), 1)) { +#if defined(USE_X_DOM_SOCKET) + if (port == -99) { + size_t hostlen = strlen(host); + /* check (hostlen < sizeof(sun.sun_path)) already passed above */ + ip_ver = -99; + sa->sun.sun_family = AF_UNIX; + memset(sa->sun.sun_path, 0, sizeof(sa->sun.sun_path)); + memcpy(sa->sun.sun_path, host, hostlen); + } else +#endif + if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin), 1)) { sa->sin.sin_port = htons((uint16_t)port); ip_ver = 4; #if defined(USE_IPV6) @@ -9491,6 +9124,11 @@ *sock = socket(PF_INET6, SOCK_STREAM, 0); } #endif +#if defined(USE_X_DOM_SOCKET) + else if (ip_ver == -99) { + *sock = socket(AF_UNIX, SOCK_STREAM, 0); + } +#endif if (*sock == INVALID_SOCKET) { mg_snprintf(NULL, @@ -9530,6 +9168,14 @@ sizeof(sa->sin6)); } #endif +#if defined(USE_X_DOM_SOCKET) + else if (ip_ver == -99) { + /* connected to domain socket */ + conn_ret = connect(*sock, + (struct sockaddr *)((void *)&sa->sun), + sizeof(sa->sun)); + } +#endif if (conn_ret != 0) { sockerr = ERRNO; @@ -9804,7 +9450,7 @@ void *data, int (*cb)(struct de *, void *)) { - char path[PATH_MAX]; + char path[UTF8_PATH_MAX]; struct dirent *dp; DIR *dirp; struct de de; @@ -9861,7 +9507,7 @@ static int remove_directory(struct mg_connection *conn, const char *dir) { - char path[PATH_MAX]; + char path[UTF8_PATH_MAX]; struct dirent *dp; DIR *dirp; struct de de; @@ -9941,6 +9587,8 @@ struct de *entries = dsd->entries; if ((entries == NULL) || (dsd->num_entries >= dsd->arr_size)) { + /* Here "entries" is a temporary pointer and can be replaced, + * "dsd->entries" is the original pointer */ entries = (struct de *)mg_realloc(entries, dsd->arr_size * 2 * sizeof(entries[0])); @@ -10095,7 +9743,7 @@ offset = (offset < 0) ? 0 : ((offset > size) ? size : offset); if (len > 0 && filep->access.fp != NULL) { -/* file stored on disk */ + /* file stored on disk */ #if defined(__linux__) /* sendfile is only available for Linux */ if ((conn->ssl == 0) && (conn->throttle == 0) @@ -10182,7 +9830,12 @@ static int parse_range_header(const char *header, int64_t *a, int64_t *b) { - return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b); + return sscanf(header, + "bytes=%" INT64_FMT "-%" INT64_FMT, + a, + b); // NOLINT(cert-err34-c) 'sscanf' used to convert a string + // to an integer value, but function will not report + // conversion errors; consider using 'strtol' instead } @@ -10238,7 +9891,7 @@ int64_t cl, r1, r2; struct vec mime_vec; int n, truncated; - char gz_path[PATH_MAX]; + char gz_path[UTF8_PATH_MAX]; const char *encoding = 0; const char *origin_hdr; const char *cors_orig_cfg; @@ -10363,7 +10016,7 @@ range, sizeof(range), "bytes " - "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n", + "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT, r1, r1 + cl - 1, filep->stat.size); @@ -10374,8 +10027,8 @@ #endif } -/* Do not compress small files. Small files do not benefit from file - * compression, but there is still some overhead. */ + /* Do not compress small files. Small files do not benefit from file + * compression, but there is still some overhead. */ #if defined(USE_ZLIB) if (filep->stat.size < MG_FILE_COMPRESSION_SIZE_LIMIT) { /* File is below the size limit. */ @@ -10600,7 +10253,7 @@ static int put_dir(struct mg_connection *conn, const char *path) { - char buf[PATH_MAX]; + char buf[UTF8_PATH_MAX]; const char *s, *p; struct mg_file file = STRUCT_FILE_INITIALIZER; size_t len; @@ -10767,6 +10420,12 @@ /* End of headers reached. */ break; } + + /* Drop all spaces after header name before : */ + while (*dp == ' ') { + *dp = 0; + dp++; + } if (*dp != ':') { /* This is not a valid field. */ return -1; @@ -10867,8 +10526,13 @@ * Section 9.1 of [RFC2616]). Responses to this * method MUST NOT be cached. */ + /* Methods for write access to files on WEBDAV (RFC 2518) */ + {"LOCK", 1, 1, 0, 0, 0}, + {"UNLOCK", 1, 0, 0, 0, 0}, + {"PROPPATCH", 1, 1, 0, 0, 0}, + /* Unsupported WEBDAV Methods: */ - /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */ + /* COPY, MOVE (RFC 2518) */ /* + 11 methods from RFC 3253 */ /* ORDERPATCH (RFC 3648) */ /* ACL (RFC 3744) */ @@ -10936,7 +10600,7 @@ NULL; ri->num_headers = 0; - /* RFC says that all initial whitespaces should be ingored */ + /* RFC says that all initial whitespaces should be ignored */ /* This included all leading \r and \n (isspace) */ /* See table: http://www.cplusplus.com/reference/cctype/ */ while ((len > 0) && isspace((unsigned char)*buf)) { @@ -10973,11 +10637,6 @@ return -1; } - /* Check for a valid http method */ - if (!is_valid_http_method(ri->request_method)) { - return -1; - } - /* The second word is the URI */ ri->request_uri = buf; @@ -10999,6 +10658,11 @@ } ri->http_version += 5; + /* Check for a valid http method */ + if (!is_valid_http_method(ri->request_method)) { + return -1; + } + /* Parse all HTTP headers */ ri->num_headers = parse_http_headers(&buf, ri->http_headers); if (ri->num_headers < 0) { @@ -11136,15 +10800,18 @@ if (conn->dom_ctx->config[REQUEST_TIMEOUT]) { /* value of request_timeout is in seconds, config in milliseconds */ - request_timeout = atof(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0; + request_timeout = + strtod(conn->dom_ctx->config[REQUEST_TIMEOUT], NULL) / 1000.0; } else { request_timeout = - atof(config_options[REQUEST_TIMEOUT].default_value) / 1000.0; + strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) + / 1000.0; } if (conn->handled_requests > 0) { if (conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT]) { request_timeout = - atof(conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT]) / 1000.0; + strtod(conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT], NULL) + / 1000.0; } } @@ -11278,7 +10945,7 @@ char *buf; /* Environment buffer */ size_t buflen; /* Space available in buf */ size_t bufused; /* Space taken in buf */ - /* Index block */ + /* Index block */ char **var; /* char **envp */ size_t varlen; /* Number of variables available in var */ size_t varused; /* Number of variables stored in var */ @@ -11364,7 +11031,8 @@ static int prepare_cgi_environment(struct mg_connection *conn, const char *prog, - struct cgi_environment *env) + struct cgi_environment *env, + unsigned char cgi_config_idx) { const char *s; struct vec var_vec; @@ -11407,7 +11075,7 @@ addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1"); addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */ - addenv(env, "SERVER_PORT=%d", ntohs(USA_IN_PORT_UNSAFE(&conn->client.lsa))); + addenv(env, "SERVER_PORT=%d", conn->request_info.server_port); sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); addenv(env, "REMOTE_ADDR=%s", src_addr); @@ -11417,6 +11085,7 @@ addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri); addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri); + addenv(env, "LOCAL_URI_RAW=%s", conn->request_info.local_uri_raw); /* SCRIPT_NAME */ uri_len = (int)strlen(conn->request_info.local_uri); @@ -11539,7 +11208,7 @@ } /* Add user-specified variables */ - s = conn->dom_ctx->config[CGI_ENVIRONMENT]; + s = conn->dom_ctx->config[CGI_ENVIRONMENT + cgi_config_idx]; while ((s = next_option(s, &var_vec, NULL)) != NULL) { addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr); } @@ -11593,14 +11262,16 @@ /* Local (static) function assumes all arguments are valid. */ static void -handle_cgi_request(struct mg_connection *conn, const char *prog) +handle_cgi_request(struct mg_connection *conn, + const char *prog, + unsigned char cgi_config_idx) { char *buf; size_t buflen; int headers_len, data_len, i, truncated; int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1}; const char *status, *status_text, *connection_state; - char *pbuf, dir[PATH_MAX], *p; + char *pbuf, dir[UTF8_PATH_MAX], *p; struct mg_request_info ri; struct cgi_environment blk; FILE *in = NULL, *out = NULL, *err = NULL; @@ -11610,9 +11281,10 @@ #if defined(USE_TIMERS) double cgi_timeout; - if (conn->dom_ctx->config[CGI_TIMEOUT]) { + if (conn->dom_ctx->config[CGI_TIMEOUT + cgi_config_idx]) { /* Get timeout in seconds */ - cgi_timeout = atof(conn->dom_ctx->config[CGI_TIMEOUT]) * 0.001; + cgi_timeout = + atof(conn->dom_ctx->config[CGI_TIMEOUT + cgi_config_idx]) * 0.001; } else { cgi_timeout = atof(config_options[REQUEST_TIMEOUT].default_value) * 0.001; @@ -11622,7 +11294,7 @@ buf = NULL; buflen = conn->phys_ctx->max_request_size; - i = prepare_cgi_environment(conn, prog, &blk); + i = prepare_cgi_environment(conn, prog, &blk, cgi_config_idx); if (i != 0) { blk.buf = NULL; blk.var = NULL; @@ -11671,7 +11343,8 @@ } DEBUG_TRACE("CGI: spawn %s %s\n", dir, p); - pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir); + pid = spawn_process( + conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir, cgi_config_idx); if (pid == (pid_t)-1) { status = strerror(ERRNO); @@ -12833,7 +12506,7 @@ DEBUG_ASSERT(body_len >= header_len); if (data_len + (uint64_t)header_len > (uint64_t)body_len) { mop = buf[0]; /* current mask and opcode */ - /* Overflow case */ + /* Overflow case */ len = body_len - header_len; memcpy(data, buf + header_len, len); error = 0; @@ -12937,8 +12610,8 @@ data_len * 4; // Initial guess of the inflated message // size. We double the memory when needed. - Bytef *inflated; - Bytef *new_mem; + Bytef *inflated = NULL; + Bytef *new_mem = NULL; conn->websocket_inflate_state.avail_in = (uInt)(data_len + 4); conn->websocket_inflate_state.next_in = data; @@ -12949,19 +12622,21 @@ data[data_len + 3] = '\xff'; do { if (inflate_buf_size_old == 0) { - new_mem = mg_calloc(inflate_buf_size, - sizeof(Bytef)); + new_mem = + (Bytef *)mg_calloc(inflate_buf_size, + sizeof(Bytef)); } else { inflate_buf_size *= 2; new_mem = - mg_realloc(inflated, inflate_buf_size); + (Bytef *)mg_realloc(inflated, + inflate_buf_size); } if (new_mem == NULL) { mg_cry_internal( conn, "Out of memory: Cannot allocate " - "inflate buffer of %i bytes", - inflate_buf_size); + "inflate buffer of %lu bytes", + (unsigned long)inflate_buf_size); exit_by_callback = 1; break; } @@ -12971,11 +12646,10 @@ - inflate_buf_size_old); conn->websocket_inflate_state.next_out = inflated + inflate_buf_size_old; - int ret = - inflate(&conn->websocket_inflate_state, - Z_SYNC_FLUSH); + ret = inflate(&conn->websocket_inflate_state, + Z_SYNC_FLUSH); if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR - || ret == Z_MEM_ERROR || ret < 0) { + || ret == Z_MEM_ERROR) { mg_cry_internal( conn, "ZLIB inflate error: %i %s", @@ -13109,7 +12783,7 @@ int retval; #if defined(GCC_DIAGNOSTIC) -/* Disable spurious conversion warning for GCC */ + /* Disable spurious conversion warning for GCC */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif @@ -13128,8 +12802,8 @@ (void)mg_lock_connection(conn); #if defined(USE_ZLIB) && defined(MG_EXPERIMENTAL_INTERFACES) - size_t deflated_size; - Bytef *deflated; + size_t deflated_size = 0; + Bytef *deflated = 0; // Deflate websocket messages over 100kb int use_deflate = dataLen > 100 * 1024 && conn->accept_gzip; @@ -13143,13 +12817,13 @@ header[0] = 0xC0u | (unsigned char)((unsigned)opcode & 0xf); conn->websocket_deflate_state.avail_in = (uInt)dataLen; conn->websocket_deflate_state.next_in = (unsigned char *)data; - deflated_size = compressBound((uLong)dataLen); + deflated_size = (Bytef *)compressBound((uLong)dataLen); deflated = mg_calloc(deflated_size, sizeof(Bytef)); if (deflated == NULL) { mg_cry_internal( conn, - "Out of memory: Cannot allocate deflate buffer of %i bytes", - deflated_size); + "Out of memory: Cannot allocate deflate buffer of %lu bytes", + (unsigned long)deflated_size); mg_unlock_connection(conn); return -1; } @@ -13568,9 +13242,15 @@ int n; unsigned int a, b, c, d, slash; - if (sscanf(vec->ptr, "%u.%u.%u.%u/%u%n", &a, &b, &c, &d, &slash, &n) != 5) { + if (sscanf(vec->ptr, "%u.%u.%u.%u/%u%n", &a, &b, &c, &d, &slash, &n) + != 5) { // NOLINT(cert-err34-c) 'sscanf' used to convert a string to an + // integer value, but function will not report conversion + // errors; consider using 'strtol' instead slash = 32; - if (sscanf(vec->ptr, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) != 4) { + if (sscanf(vec->ptr, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) + != 4) { // NOLINT(cert-err34-c) 'sscanf' used to convert a string to + // an integer value, but function will not report conversion + // errors; consider using 'strtol' instead n = 0; } } @@ -13579,7 +13259,7 @@ if ((a < 256) && (b < 256) && (c < 256) && (d < 256) && (slash < 33)) { /* IPv4 format */ if (sa->sa.sa_family == AF_INET) { - uint32_t ip = (uint32_t)ntohl(sa->sin.sin_addr.s_addr); + uint32_t ip = ntohl(sa->sin.sin_addr.s_addr); uint32_t net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d; uint32_t mask = slash ? (0xFFFFFFFFu << (32 - slash)) : 0; @@ -13675,7 +13355,11 @@ while ((spec = next_option(spec, &vec, &val)) != NULL) { mult = ','; - if ((val.ptr == NULL) || (sscanf(val.ptr, "%lf%c", &v, &mult) < 1) + if ((val.ptr == NULL) + || (sscanf(val.ptr, "%lf%c", &v, &mult) + < 1) // NOLINT(cert-err34-c) 'sscanf' used to convert a string + // to an integer value, but function will not report + // conversion errors; consider using 'strtol' instead || (v < 0) || ((lowercase(&mult) != 'k') && (lowercase(&mult) != 'm') && (mult != ','))) { @@ -13732,7 +13416,7 @@ host->len = 0; if (host_header != NULL) { - char *pos; + const char *pos; /* If the "Host" is an IPv6 address, like [::1], parse until ] * is found. */ @@ -13788,10 +13472,10 @@ } else { struct mg_domain_context *dom = &(conn->phys_ctx->dd); while (dom) { - if ((strlen(dom->config[AUTHENTICATION_DOMAIN]) == host.len) - && !mg_strncasecmp(host.ptr, - dom->config[AUTHENTICATION_DOMAIN], - host.len)) { + const char *domName = dom->config[AUTHENTICATION_DOMAIN]; + size_t domNameLen = strlen(domName); + if ((domNameLen == host.len) + && !mg_strncasecmp(host.ptr, domName, host.len)) { /* Found matching domain */ DEBUG_TRACE("HTTP domain %s found", @@ -13807,27 +13491,20 @@ } } + DEBUG_TRACE("HTTP%s Host: %.*s", + conn->ssl ? "S" : "", + (int)host.len, + host.ptr); + } else { DEBUG_TRACE("HTTP%s Host is not set", conn->ssl ? "S" : ""); return 1; } - DEBUG_TRACE("HTTP%s Host: %.*s", - conn->ssl ? "S" : "", - (int)host.len, - host.ptr); return 1; } -static int mg_construct_local_link(const struct mg_connection *conn, - char *buf, - size_t buflen, - const char *define_proto, - int define_port, - const char *define_uri); - - static void redirect_to_https_port(struct mg_connection *conn, int port) { @@ -13909,6 +13586,7 @@ if (auth_handler != NULL) { return; } + } else if (handler_type == REQUEST_HANDLER) { DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL && data_handler == NULL && close_handler == NULL); @@ -13925,11 +13603,12 @@ if (auth_handler != NULL) { return; } - } else { /* AUTH_HANDLER */ + + } else if (handler_type == AUTH_HANDLER) { DEBUG_ASSERT(handler == NULL); DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL && data_handler == NULL && close_handler == NULL); - DEBUG_ASSERT(auth_handler != NULL); + DEBUG_ASSERT(is_delete_request || (auth_handler != NULL)); if (handler != NULL) { return; } @@ -13940,9 +13619,13 @@ if (!is_delete_request && (auth_handler == NULL)) { return; } + } else { + /* Unknown handler type. */ + return; } if (!phys_ctx || !dom_ctx) { + /* no context available */ return; } @@ -14185,7 +13868,7 @@ && (strcmp(tmp_rh->uri, uri) == 0); } else if (step == 1) { /* next try for a partial match, we will accept - uri/something */ + uri/something */ matched = (tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == '/') @@ -14272,6 +13955,21 @@ #endif +/* Decrement recount of handler. conn must not be NULL, handler_info may be NULL + */ +static void +release_handler_ref(struct mg_connection *conn, + struct mg_handler_info *handler_info) +{ + if (handler_info != NULL) { + /* Use context lock for ref counter */ + mg_lock_context(conn->phys_ctx); + handler_info->refcount--; + mg_unlock_context(conn->phys_ctx); + } +} + + /* This is the heart of the Civetweb's logic. * This function is called when the request is read, parsed and validated, * and Civetweb must decide what action to take: serve a file, or @@ -14280,7 +13978,7 @@ handle_request(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; - char path[PATH_MAX]; + char path[UTF8_PATH_MAX]; int uri_len, ssl_index; int is_found = 0, is_script_resource = 0, is_websocket_request = 0, is_put_or_delete_request = 0, is_callback_resource = 0, @@ -14300,6 +13998,7 @@ int handler_type; time_t curtime = time(NULL); char date[64]; + char *tmp; path[0] = 0; @@ -14339,18 +14038,30 @@ if (should_decode_url(conn)) { mg_url_decode( ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0); + } - if (conn->request_info.query_string) { + /* URL decode the query-string only if explicity set in the configuration */ + if (conn->request_info.query_string) { + if (should_decode_query_string(conn)) { url_decode_in_place((char *)conn->request_info.query_string); } } - /* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is - * not possible */ - remove_dot_segments((char *)ri->local_uri); + /* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is not + * possible. The fact that we cleaned the URI is stored in that the + * pointer to ri->local_ur and ri->local_uri_raw are now different. + * ri->local_uri_raw still points to memory allocated in + * worker_thread_run(). ri->local_uri is private to the request so we + * don't have to use preallocated memory here. */ + tmp = mg_strdup(ri->local_uri_raw); + if (!tmp) { + /* Out of memory. We cannot do anything reasonable here. */ + return; + } + remove_dot_segments(tmp); + ri->local_uri = tmp; /* step 1. completed, the url is known now */ - uri_len = (int)strlen(ri->local_uri); DEBUG_TRACE("URL: %s", ri->local_uri); /* 2. if this ip has limited speed, set it for this connection */ @@ -14366,7 +14077,7 @@ i = conn->phys_ctx->callbacks.begin_request(conn); if (i > 0) { /* callback already processed the request. Store the - return value as a status code for the access log. */ + return value as a status code for the access log. */ conn->status_code = i; if (!conn->must_close) { discard_unread_request_data(conn); @@ -14516,18 +14227,25 @@ &auth_callback_data, NULL)) { if (!auth_handler(conn, auth_callback_data)) { + + /* Callback handler will not be used anymore. Release it */ + release_handler_ref(conn, handler_info); + return; } } else if (is_put_or_delete_request && !is_script_resource && !is_callback_resource) { HTTP1_only; -/* 6.2. this request is a PUT/DELETE to a real file */ -/* 6.2.1. thus, the server must have real files */ + /* 6.2. this request is a PUT/DELETE to a real file */ + /* 6.2.1. thus, the server must have real files */ #if defined(NO_FILES) if (1) { #else if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL) { #endif + /* This code path will not be called for request handlers */ + DEBUG_ASSERT(handler_info == NULL); + /* This server does not have any real files, thus the * PUT/DELETE methods are not valid. */ mg_send_http_error(conn, @@ -14553,6 +14271,10 @@ * correspond to a file. Check authorization. */ if (!check_authorization(conn, path)) { send_authorization_request(conn, NULL); + + /* Callback handler will not be used anymore. Release it */ + release_handler_ref(conn, handler_info); + return; } } @@ -14566,9 +14288,7 @@ i = callback_handler(conn, callback_data); /* Callback handler will not be used anymore. Release it */ - mg_lock_context(conn->phys_ctx); - handler_info->refcount--; - mg_unlock_context(conn->phys_ctx); + release_handler_ref(conn, handler_info); if (i > 0) { /* Do nothing, callback has served the request. Store @@ -14634,7 +14354,7 @@ return; } -/* 8. handle websocket requests */ + /* 8. handle websocket requests */ #if defined(USE_WEBSOCKET) if (is_websocket_request) { HTTP1_only; @@ -14723,14 +14443,21 @@ && (ri->local_uri[uri_len - 1] != '/')) { size_t len = strlen(ri->request_uri); - char *new_path = mg_malloc_ctx(len + 2, conn->phys_ctx); + size_t lenQS = ri->query_string ? strlen(ri->query_string) + 1 : 0; + char *new_path = (char *)mg_malloc_ctx(len + lenQS + 2, conn->phys_ctx); if (!new_path) { mg_send_http_error(conn, 500, "out or memory"); } else { memcpy(new_path, ri->request_uri, len); new_path[len] = '/'; new_path[len + 1] = 0; + if (ri->query_string) { + new_path[len + 1] = '?'; + /* Copy query string including terminating zero */ + memcpy(new_path + len + 2, ri->query_string, lenQS); + } mg_send_http_redirect(conn, new_path, 301); + mg_free(new_path); } return; } @@ -14807,15 +14534,18 @@ const char *path, struct mg_file *file) { +#if !defined(NO_CGI) + unsigned char cgi_config_idx, inc, max; +#endif + if (!conn || !conn->dom_ctx) { return; } - if (0) { #if defined(USE_LUA) - } else if (match_prefix_strlen( - conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS], path) - > 0) { + if (match_prefix_strlen(conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS], + path) + > 0) { if (is_in_script_path(conn, path)) { /* Lua server page: an SSI like page containing mostly plain * html code plus some tags with server generated contents. */ @@ -14824,25 +14554,27 @@ /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } + return; + } - } else if (match_prefix_strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS], - path) - > 0) { + if (match_prefix_strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS], path) + > 0) { if (is_in_script_path(conn, path)) { /* Lua in-server module script: a CGI like script used to - * generate - * the - * entire reply. */ + * generate the entire reply. */ mg_exec_lua_script(conn, path, NULL); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } + return; + } #endif + #if defined(USE_DUKTAPE) - } else if (match_prefix_strlen( - conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], path) - > 0) { + if (match_prefix_strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], + path) + > 0) { if (is_in_script_path(conn, path)) { /* Call duktape to generate the page */ mg_exec_duktape_script(conn, path); @@ -14850,35 +14582,51 @@ /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } + return; + } #endif + #if !defined(NO_CGI) - } else if (match_prefix_strlen(conn->dom_ctx->config[CGI_EXTENSIONS], path) - > 0) { - if (is_in_script_path(conn, path)) { - /* CGI scripts may support all HTTP methods */ - handle_cgi_request(conn, path); - } else { - /* Script was in an illegal path */ - mg_send_http_error(conn, 403, "%s", "Forbidden"); + inc = CGI2_EXTENSIONS - CGI_EXTENSIONS; + max = PUT_DELETE_PASSWORDS_FILE - CGI_EXTENSIONS; + for (cgi_config_idx = 0; cgi_config_idx < max; cgi_config_idx += inc) { + if (conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx] != NULL) { + if (match_prefix_strlen( + conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx], + path) + > 0) { + if (is_in_script_path(conn, path)) { + /* CGI scripts may support all HTTP methods */ + handle_cgi_request(conn, path, 0); + } else { + /* Script was in an illegal path */ + mg_send_http_error(conn, 403, "%s", "Forbidden"); + } + return; + } } + } #endif /* !NO_CGI */ - } else if (match_prefix_strlen(conn->dom_ctx->config[SSI_EXTENSIONS], path) - > 0) { + + if (match_prefix_strlen(conn->dom_ctx->config[SSI_EXTENSIONS], path) > 0) { if (is_in_script_path(conn, path)) { handle_ssi_file_request(conn, path, file); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } + return; + } + #if !defined(NO_CACHING) - } else if ((!conn->in_error_handler) - && is_not_modified(conn, &file->stat)) { + if ((!conn->in_error_handler) && is_not_modified(conn, &file->stat)) { /* Send 304 "Not Modified" - this must not send any body data */ handle_not_modified_static_file_request(conn, file); -#endif /* !NO_CACHING */ - } else { - handle_static_file_request(conn, path, file, NULL, NULL); + return; } +#endif /* !NO_CACHING */ + + handle_static_file_request(conn, path, file, NULL, NULL); } #endif /* NO_FILESYSTEMS */ @@ -14893,6 +14641,18 @@ for (i = 0; i < ctx->num_listening_sockets; i++) { closesocket(ctx->listening_sockets[i].sock); +#if defined(USE_X_DOM_SOCKET) + /* For unix domain sockets, the socket name represents a file that has + * to be deleted. */ + /* See + * https://stackoverflow.com/questions/15716302/so-reuseaddr-and-af-unix + */ + if ((ctx->listening_sockets[i].lsa.sin.sin_family == AF_UNIX) + && (ctx->listening_sockets[i].sock != INVALID_SOCKET)) { + IGNORE_UNUSED_RESULT( + remove(ctx->listening_sockets[i].lsa.sun.sun_path)); + } +#endif ctx->listening_sockets[i].sock = INVALID_SOCKET; } mg_free(ctx->listening_sockets); @@ -14941,7 +14701,16 @@ len = 0; /* Test for different ways to format this string */ - if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) + if (sscanf(vec->ptr, + "%u.%u.%u.%u:%u%n", + &a, + &b, + &c, + &d, + &port, + &len) // NOLINT(cert-err34-c) 'sscanf' used to convert a string + // to an integer value, but function will not report + // conversion errors; consider using 'strtol' instead == 5) { /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */ so->lsa.sin.sin_addr.s_addr = @@ -14962,7 +14731,11 @@ #endif } else if ((vec->ptr[0] == '+') - && (sscanf(vec->ptr + 1, "%u%n", &port, &len) == 1)) { + && (sscanf(vec->ptr + 1, "%u%n", &port, &len) + == 1)) { // NOLINT(cert-err34-c) 'sscanf' used to convert a + // string to an integer value, but function will not + // report conversion errors; consider using 'strtol' + // instead /* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */ /* Add 1 to len for the + character we skipped before */ @@ -15010,7 +14783,11 @@ if (mg_inet_pton( AF_INET, hostname, &so->lsa.sin, sizeof(so->lsa.sin), 1)) { - if (sscanf(cb + 1, "%u%n", &port, &len) == 1) { + if (sscanf(cb + 1, "%u%n", &port, &len) + == 1) { // NOLINT(cert-err34-c) 'sscanf' used to convert a + // string to an integer value, but function will not + // report conversion errors; consider using 'strtol' + // instead *ip_version = 4; so->lsa.sin.sin_port = htons((uint16_t)port); len += (int)(hostnlen + 1); @@ -15035,6 +14812,23 @@ len = 0; } +#if defined(USE_X_DOM_SOCKET) + + } else if (vec->ptr[0] == 'x') { + /* unix (linux) domain socket */ + if (vec->len < sizeof(so->lsa.sun.sun_path)) { + len = vec->len; + so->lsa.sun.sun_family = AF_UNIX; + memset(so->lsa.sun.sun_path, 0, sizeof(so->lsa.sun.sun_path)); + memcpy(so->lsa.sun.sun_path, (char *)vec->ptr + 1, vec->len - 1); + port = 0; + *ip_version = 99; + } else { + /* String too long */ + len = 0; + } +#endif + } else { /* Parsing failure. */ len = 0; @@ -15043,7 +14837,7 @@ /* sscanf and the option splitting code ensure the following condition * Make sure the port is valid and vector ends with the port, 's' or 'r' */ if ((len > 0) && is_valid_port(port) - && (((size_t)len == vec->len) || ((size_t)(len + 1) == vec->len))) { + && (((size_t)len == vec->len) || (((size_t)len + 1) == vec->len))) { /* Next character after the port number */ ch = ((size_t)len < vec->len) ? vec->ptr[len] : '\0'; so->is_ssl = (ch == 's'); @@ -15172,8 +14966,14 @@ continue; } #endif - - if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6)) + /* Create socket. */ + /* For a list of protocol numbers (e.g., TCP==6) see: + * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + */ + if ((so.sock = + socket(so.lsa.sa.sa_family, + SOCK_STREAM, + (ip_version == 99) ? (/* LOCAL */ 0) : (/* TCP */ 6))) == INVALID_SOCKET) { mg_cry_ctx_internal(phys_ctx, @@ -15221,8 +15021,14 @@ } #endif - if (ip_version > 4) { -/* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */ +#if defined(USE_X_DOM_SOCKET) + if (ip_version == 99) { + /* Unix domain socket */ + } else +#endif + + if (ip_version > 4) { + /* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */ #if defined(USE_IPV6) if (ip_version > 6) { if (so.lsa.sa.sa_family == AF_INET6 @@ -15295,6 +15101,22 @@ } } #endif +#if defined(USE_X_DOM_SOCKET) + else if (so.lsa.sa.sa_family == AF_UNIX) { + + len = sizeof(so.lsa.sun); + if (bind(so.sock, &so.lsa.sa, len) != 0) { + mg_cry_ctx_internal(phys_ctx, + "cannot bind to unix socket %s: %d (%s)", + so.lsa.sun.sun_path, + (int)ERRNO, + strerror(errno)); + closesocket(so.sock); + so.sock = INVALID_SOCKET; + continue; + } + } +#endif else { mg_cry_ctx_internal( phys_ctx, @@ -15345,7 +15167,7 @@ continue; } -/* Update lsa port in case of random free ports */ + /* Update lsa port in case of random free ports */ #if defined(USE_IPV6) if (so.lsa.sa.sa_family == AF_INET6) { so.lsa.sin6.sin6_port = usa.sin6.sin6_port; @@ -15413,7 +15235,6 @@ #if defined(MG_EXTERNAL_FUNCTION_log_access) -static void log_access(const struct mg_connection *conn); #include "external_log_access.inl" #elif !defined(NO_FILESYSTEMS) @@ -15428,12 +15249,58 @@ const char *referer; const char *user_agent; - char buf[4096]; + char log_buf[4096]; if (!conn || !conn->dom_ctx) { return; } + /* Set log message to "empty" */ + log_buf[0] = 0; + +#if defined(USE_LUA) + if (conn->phys_ctx->lua_bg_log_available) { + int ret; + struct mg_context *ctx = conn->phys_ctx; + lua_State *lstate = (lua_State *)ctx->lua_background_state; + pthread_mutex_lock(&ctx->lua_bg_mutex); + /* call "log()" in Lua */ + lua_getglobal(lstate, "log"); + prepare_lua_request_info_inner(conn, lstate); + push_lua_response_log_data(conn, lstate); + + ret = lua_pcall(lstate, /* args */ 2, /* results */ 1, 0); + if (ret == 0) { + int t = lua_type(lstate, -1); + if (t == LUA_TBOOLEAN) { + if (lua_toboolean(lstate, -1) == 0) { + /* log() returned false: do not log */ + pthread_mutex_unlock(&ctx->lua_bg_mutex); + return; + } + /* log returned true: continue logging */ + } else if (t == LUA_TSTRING) { + size_t len; + const char *txt = lua_tolstring(lstate, -1, &len); + if ((len == 0) || (*txt == 0)) { + /* log() returned empty string: do not log */ + pthread_mutex_unlock(&ctx->lua_bg_mutex); + return; + } + /* Copy test from Lua into log_buf */ + if (len >= sizeof(log_buf)) { + len = sizeof(log_buf) - 1; + } + memcpy(log_buf, txt, len); + log_buf[len] = 0; + } + } else { + lua_cry(conn, ret, lstate, "lua_background_script", "log"); + } + pthread_mutex_unlock(&ctx->lua_bg_mutex); + } +#endif + if (conn->dom_ctx->config[ACCESS_LOG_FILE] != NULL) { if (mg_fopen(conn, conn->dom_ctx->config[ACCESS_LOG_FILE], @@ -15453,46 +15320,58 @@ return; } - tm = localtime(&conn->conn_birth_time); - if (tm != NULL) { - strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm); - } else { - mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date)); - date[sizeof(date) - 1] = '\0'; - } + /* If we did not get a log message from Lua, create it here. */ + if (!log_buf[0]) { + tm = localtime(&conn->conn_birth_time); + if (tm != NULL) { + strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm); + } else { + mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date)); + date[sizeof(date) - 1] = '\0'; + } - ri = &conn->request_info; + ri = &conn->request_info; - sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); - referer = header_val(conn, "Referer"); - user_agent = header_val(conn, "User-Agent"); + sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); + referer = header_val(conn, "Referer"); + user_agent = header_val(conn, "User-Agent"); - mg_snprintf(conn, - NULL, /* Ignore truncation in access log */ - buf, - sizeof(buf), - "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s", - src_addr, - (ri->remote_user == NULL) ? "-" : ri->remote_user, - date, - ri->request_method ? ri->request_method : "-", - ri->request_uri ? ri->request_uri : "-", - ri->query_string ? "?" : "", - ri->query_string ? ri->query_string : "", - ri->http_version, - conn->status_code, - conn->num_bytes_sent, - referer, - user_agent); + mg_snprintf(conn, + NULL, /* Ignore truncation in access log */ + log_buf, + sizeof(log_buf), + "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT + " %s %s", + src_addr, + (ri->remote_user == NULL) ? "-" : ri->remote_user, + date, + ri->request_method ? ri->request_method : "-", + ri->request_uri ? ri->request_uri : "-", + ri->query_string ? "?" : "", + ri->query_string ? ri->query_string : "", + ri->http_version, + conn->status_code, + conn->num_bytes_sent, + referer, + user_agent); + } + /* Here we have a log message in log_buf. Call the callback */ if (conn->phys_ctx->callbacks.log_access) { - conn->phys_ctx->callbacks.log_access(conn, buf); + if (conn->phys_ctx->callbacks.log_access(conn, log_buf)) { + /* do not log if callack returns non-zero */ + if (fi.access.fp) { + mg_fclose(&fi.access); + } + return; + } } + /* Store in file */ if (fi.access.fp) { int ok = 1; flockfile(fi.access.fp); - if (fprintf(fi.access.fp, "%s\n", buf) < 1) { + if (fprintf(fi.access.fp, "%s\n", log_buf) < 1) { ok = 0; } if (fflush(fi.access.fp) != 0) { @@ -15510,7 +15389,7 @@ } } #else -#error Must either enable filesystems or provide a custom log_access implementation +#error "Either enable filesystems or provide a custom log_access implementation" #endif /* Externally provided function */ @@ -15625,7 +15504,38 @@ } -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) +/* Check if SSL is required. + * If so, set up ctx->ssl_ctx pointer. */ +static int +mg_sslctx_init(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx) +{ + if (!phys_ctx) { + return 0; + } + + if (!dom_ctx) { + dom_ctx = &(phys_ctx->dd); + } + + if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) { + /* No SSL port is set. No need to setup SSL. */ + return 1; + } + + dom_ctx->ssl_ctx = (SSL_CTX *)mg_calloc(1, sizeof(*dom_ctx->ssl_ctx)); + if (dom_ctx->ssl_ctx == NULL) { + fprintf(stderr, "ssl_ctx malloc failed\n"); + return 0; + } + + return mbed_sslctx_init(dom_ctx->ssl_ctx, dom_ctx->config[SSL_CERTIFICATE]) + == 0 + ? 1 + : 0; +} + +#elif !defined(NO_SSL) static int ssl_use_pem_file(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, @@ -16079,9 +15989,9 @@ static int -initialize_ssl(char *ebuf, size_t ebuf_len) +initialize_openssl(char *ebuf, size_t ebuf_len) { -#if !defined(OPENSSL_API_1_1) +#if !defined(OPENSSL_API_1_1) && !defined(OPENSSL_API_3_0) int i, num_locks; size_t size; #endif @@ -16113,7 +16023,7 @@ return 1; } -#if !defined(OPENSSL_API_1_1) +#if !defined(OPENSSL_API_1_1) && !defined(OPENSSL_API_3_0) /* Initialize locking callbacks, needed for thread safety. * http://www.openssl.org/support/faq.html#PROG1 */ @@ -16164,7 +16074,7 @@ CRYPTO_set_locking_callback(&ssl_locking_callback); CRYPTO_set_id_callback(&mg_current_thread_id); -#endif /* OPENSSL_API_1_1 */ +#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ #if !defined(NO_SSL_DL) if (!ssllib_dll_handle) { @@ -16180,7 +16090,8 @@ } #endif /* NO_SSL_DL */ -#if defined(OPENSSL_API_1_1) +#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ + && !defined(NO_SSL_DL) /* Initialize SSL library */ OPENSSL_init_ssl(0, NULL); OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS @@ -16514,7 +16425,8 @@ int protocol_ver; int ssl_cache_timeout; -#if defined(OPENSSL_API_1_1) +#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ + && !defined(NO_SSL_DL) if ((dom_ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_new (server) error: %s", @@ -16528,11 +16440,19 @@ ssl_error()); return 0; } -#endif /* OPENSSL_API_1_1 */ +#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ +#if defined(SSL_OP_NO_TLSv1_3) + SSL_CTX_clear_options(dom_ctx->ssl_ctx, + SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 + | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 + | SSL_OP_NO_TLSv1_3); +#else SSL_CTX_clear_options(dom_ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 - | SSL_OP_NO_TLSv1_1); + | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); +#endif + protocol_ver = atoi(dom_ctx->config[SSL_PROTOCOL_VERSION]); SSL_CTX_set_options(dom_ctx->ssl_ctx, ssl_get_protocol(protocol_ver)); SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE); @@ -16771,7 +16691,7 @@ /* Callback exists and returns >0: Initializing complete, * civetweb should not modify the SSL context. */ dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx; - if (!initialize_ssl(ebuf, sizeof(ebuf))) { + if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } @@ -16798,7 +16718,7 @@ } else if (callback_ret > 0) { /* Callback > 0: Consider init done. */ dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx; - if (!initialize_ssl(ebuf, sizeof(ebuf))) { + if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } @@ -16832,7 +16752,7 @@ chain = NULL; } - if (!initialize_ssl(ebuf, sizeof(ebuf))) { + if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } @@ -16842,9 +16762,9 @@ static void -uninitialize_ssl(void) +uninitialize_openssl(void) { -#if defined(OPENSSL_API_1_1) +#if defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0) if (mg_atomic_dec(&cryptolib_users) == 0) { @@ -16876,10 +16796,10 @@ } mg_free(ssl_mutexes); ssl_mutexes = NULL; -#endif /* OPENSSL_API_1_1 */ +#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ } } -#endif /* !NO_SSL */ +#endif /* !defined(NO_SSL) && !defined(USE_MBEDTLS) */ #if !defined(NO_FILESYSTEMS) @@ -16951,26 +16871,35 @@ conn->request_info.remote_user = NULL; conn->request_info.request_method = NULL; conn->request_info.request_uri = NULL; + + /* Free cleaned local URI (if any) */ + if (conn->request_info.local_uri != conn->request_info.local_uri_raw) { + mg_free((void *)conn->request_info.local_uri); + conn->request_info.local_uri = NULL; + } conn->request_info.local_uri = NULL; -#if defined(MG_LEGACY_INTERFACE) - /* Legacy before split into local_uri and request_uri */ - conn->request_info.uri = NULL; +#if defined(USE_SERVER_STATS) + conn->processing_time = 0; #endif } static int -set_tcp_nodelay(SOCKET sock, int nodelay_on) +set_tcp_nodelay(const struct socket *so, int nodelay_on) { - if (setsockopt(sock, - IPPROTO_TCP, - TCP_NODELAY, - (SOCK_OPT_TYPE)&nodelay_on, - sizeof(nodelay_on)) - != 0) { - /* Error */ - return 1; + if ((so->lsa.sa.sa_family == AF_INET) + || (so->lsa.sa.sa_family == AF_INET6)) { + /* Only for TCP sockets */ + if (setsockopt(so->sock, + IPPROTO_TCP, + TCP_NODELAY, + (SOCK_OPT_TYPE)&nodelay_on, + sizeof(nodelay_on)) + != 0) { + /* Error */ + return 1; + } } /* OK */ return 0; @@ -17139,7 +17068,12 @@ conn->conn_state = 7; /* closing */ #endif -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) + if (conn->ssl != NULL) { + mbed_ssl_close(conn->ssl); + conn->ssl = NULL; + } +#elif !defined(NO_SSL) if (conn->ssl != NULL) { /* Run SSL_shutdown twice to ensure completely close SSL connection */ @@ -17158,6 +17092,13 @@ conn->client.sock = INVALID_SOCKET; } + /* call the connection_closed callback if assigned */ + if (conn->phys_ctx->callbacks.connection_closed != NULL) { + if (conn->phys_ctx->context_type == CONTEXT_SERVER) { + conn->phys_ctx->callbacks.connection_closed(conn); + } + } + mg_unlock_connection(conn); #if defined(USE_SERVER_STATS) @@ -17203,7 +17144,7 @@ close_connection(conn); -#if !defined(NO_SSL) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client if (((conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) || (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT)) && (conn->phys_ctx->dd.ssl_ctx != NULL)) { @@ -17293,8 +17234,9 @@ return NULL; } -#if !defined(NO_SSL) -#if defined(OPENSSL_API_1_1) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client +#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ + && !defined(NO_SSL_DL) if (use_ssl && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) { @@ -17322,7 +17264,7 @@ mg_free(conn); return NULL; } -#endif /* OPENSSL_API_1_1 */ +#endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ #endif /* NO_SSL */ @@ -17354,7 +17296,7 @@ ebuf, ebuf_len, "Can not create mutex"); -#if !defined(NO_SSL) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client SSL_CTX_free(conn->dom_ctx->ssl_ctx); #endif closesocket(sock); @@ -17363,7 +17305,7 @@ } -#if !defined(NO_SSL) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client if (use_ssl) { /* TODO: Check ssl_verify_peer and ssl_ca_path here. * SSL_CTX_set_verify call is needed to switch off server @@ -17758,6 +17700,7 @@ *err = 500; return 0; } + /* Set the time the request was received. This value should be used for * timeouts. */ clock_gettime(CLOCK_MONOTONIC, &(conn->req_time)); @@ -17850,6 +17793,15 @@ return 0; } +#if USE_ZLIB + if (((cl = get_header(conn->request_info.http_headers, + conn->request_info.num_headers, + "Accept-Encoding")) + != NULL) + && strstr(cl, "gzip")) { + conn->accept_gzip = 1; + } +#endif if (((cl = get_header(conn->request_info.http_headers, conn->request_info.num_headers, "Transfer-Encoding")) @@ -18023,12 +17975,9 @@ ret = get_response(conn, ebuf, ebuf_len, &err); conn->dom_ctx->config[REQUEST_TIMEOUT] = save_timeout; -#if defined(MG_LEGACY_INTERFACE) - /* TODO: 1) uri is deprecated; - * 2) here, ri.uri is the http response code */ - conn->request_info.uri = conn->request_info.request_uri; -#endif - conn->request_info.local_uri = conn->request_info.request_uri; + /* TODO: here, the URI is the http response code */ + conn->request_info.local_uri_raw = conn->request_info.request_uri; + conn->request_info.local_uri = conn->request_info.local_uri_raw; /* TODO (mid): Define proper return values - maybe return length? * For the first test use <0 for error and >0 for OK */ @@ -18073,11 +18022,7 @@ conn->data_len = 0; get_response(conn, ebuf, ebuf_len, &reqerr); -#if defined(MG_LEGACY_INTERFACE) - /* TODO: 1) uri is deprecated; - * 2) here, ri.uri is the http response code */ - conn->request_info.uri = conn->request_info.request_uri; -#endif + /* TODO: here, the URI is the http response code */ conn->request_info.local_uri = conn->request_info.request_uri; } } @@ -18114,7 +18059,7 @@ void *user_thread_ptr = NULL; -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__ZEPHYR__) struct sigaction sa; /* Ignore SIGPIPE */ @@ -18143,7 +18088,7 @@ } /* The websocket_client context has only this thread. If it runs out, - set the stop_flag to 2 (= "stopped"). */ + set the stop_flag to 2 (= "stopped"). */ STOP_FLAG_ASSIGN(&cdata->conn->phys_ctx->stop_flag, 2); if (cdata->conn->phys_ctx->callbacks.exit_thread) { @@ -18170,6 +18115,7 @@ size_t error_buffer_size, const char *path, const char *origin, + const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) @@ -18179,30 +18125,10 @@ #if defined(USE_WEBSOCKET) struct websocket_client_thread_data *thread_data; static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw=="; - const char *handshake_req; const char *host = client_options->host; int i; - if (origin != NULL) { - handshake_req = "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: %s\r\n" - "Sec-WebSocket-Version: 13\r\n" - "Origin: %s\r\n" - "\r\n"; - } else { - handshake_req = "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: %s\r\n" - "Sec-WebSocket-Version: 13\r\n" - "\r\n"; - } - #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" @@ -18228,7 +18154,68 @@ return NULL; } - i = mg_printf(conn, handshake_req, path, host, magic, origin); + if (origin != NULL) { + if (extensions != NULL) { + i = mg_printf(conn, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Extensions: %s\r\n" + "Origin: %s\r\n" + "\r\n", + path, + host, + magic, + extensions, + origin); + } else { + i = mg_printf(conn, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Origin: %s\r\n" + "\r\n", + path, + host, + magic, + origin); + } + } else { + + if (extensions != NULL) { + i = mg_printf(conn, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Extensions: %s\r\n" + "\r\n", + path, + host, + magic, + extensions); + } else { + i = mg_printf(conn, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + "\r\n", + path, + host, + magic); + } + } if (i <= 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ @@ -18245,7 +18232,8 @@ mg_close_connection(conn); return NULL; } - conn->request_info.local_uri = conn->request_info.request_uri; + conn->request_info.local_uri_raw = conn->request_info.request_uri; + conn->request_info.local_uri = conn->request_info.local_uri_raw; #if defined(__clang__) #pragma clang diagnostic pop @@ -18320,6 +18308,7 @@ (void)error_buffer_size; (void)path; (void)origin; + (void)extensions; (void)user_data; (void)data_func; (void)close_func; @@ -18352,6 +18341,7 @@ error_buffer_size, path, origin, + NULL, data_func, close_func, user_data); @@ -18378,11 +18368,68 @@ error_buffer_size, path, origin, + NULL, data_func, close_func, user_data); } +struct mg_connection * +mg_connect_websocket_client_extensions(const char *host, + int port, + int use_ssl, + char *error_buffer, + size_t error_buffer_size, + const char *path, + const char *origin, + const char *extensions, + mg_websocket_data_handler data_func, + mg_websocket_close_handler close_func, + void *user_data) +{ + struct mg_client_options client_options; + memset(&client_options, 0, sizeof(client_options)); + client_options.host = host; + client_options.port = port; + + return mg_connect_websocket_client_impl(&client_options, + use_ssl, + error_buffer, + error_buffer_size, + path, + origin, + extensions, + data_func, + close_func, + user_data); +} + +struct mg_connection * +mg_connect_websocket_client_secure_extensions( + const struct mg_client_options *client_options, + char *error_buffer, + size_t error_buffer_size, + const char *path, + const char *origin, + const char *extensions, + mg_websocket_data_handler data_func, + mg_websocket_close_handler close_func, + void *user_data) +{ + if (!client_options) { + return NULL; + } + return mg_connect_websocket_client_impl(client_options, + 1, + error_buffer, + error_buffer_size, + path, + origin, + extensions, + data_func, + close_func, + user_data); +} /* Prepare connection data structure */ static void @@ -18444,7 +18491,6 @@ /* Loop over multiple requests sent using the same connection * (while "keep alive"). */ do { - DEBUG_TRACE("calling get_request (%i times for this connection)", conn->handled_requests + 1); @@ -18478,12 +18524,13 @@ switch (uri_type) { case 1: /* Asterisk */ - conn->request_info.local_uri = 0; + conn->request_info.local_uri_raw = 0; /* TODO: Deal with '*'. */ break; case 2: /* relative uri */ - conn->request_info.local_uri = conn->request_info.request_uri; + conn->request_info.local_uri_raw = + conn->request_info.request_uri; break; case 3: case 4: @@ -18491,9 +18538,9 @@ hostend = get_rel_url_at_current_server( conn->request_info.request_uri, conn); if (hostend) { - conn->request_info.local_uri = hostend; + conn->request_info.local_uri_raw = hostend; } else { - conn->request_info.local_uri = NULL; + conn->request_info.local_uri_raw = NULL; } break; default: @@ -18503,14 +18550,11 @@ sizeof(ebuf), "Invalid URI"); mg_send_http_error(conn, 400, "%s", ebuf); - conn->request_info.local_uri = NULL; + conn->request_info.local_uri_raw = NULL; break; } - -#if defined(MG_LEGACY_INTERFACE) - /* Legacy before split into local_uri and request_uri */ - conn->request_info.uri = conn->request_info.local_uri; -#endif + conn->request_info.local_uri = + (char *)conn->request_info.local_uri_raw; } if (ebuf[0] != '\0') { @@ -18538,29 +18582,8 @@ if (ebuf[0] == '\0') { if (conn->request_info.local_uri) { -/* handle request to local server */ -#if defined(USE_SERVER_STATS) - conn->conn_state = 4; /* processing */ -#endif - handle_request(conn); - -#if defined(USE_SERVER_STATS) - conn->conn_state = 5; /* processed */ - - mg_atomic_add64(&(conn->phys_ctx->total_data_read), - conn->consumed_content); - mg_atomic_add64(&(conn->phys_ctx->total_data_written), - conn->num_bytes_sent); -#endif - - DEBUG_TRACE("%s", "handle_request done"); - - if (conn->phys_ctx->callbacks.end_request != NULL) { - conn->phys_ctx->callbacks.end_request(conn, - conn->status_code); - DEBUG_TRACE("%s", "end_request callback done"); - } - log_access(conn); + /* handle request to local server */ + handle_request_stat_log(conn); } else { /* TODO: handle non-local request (PROXY) */ @@ -18603,6 +18626,7 @@ ? (int)(conn->request_len + conn->content_len) : conn->data_len; conn->data_len -= discard_len; + if (conn->data_len > 0) { DEBUG_TRACE("discard_len = %d", discard_len); memmove(conn->buf, @@ -18620,9 +18644,7 @@ (long int)conn->buf_size); break; } - conn->handled_requests++; - } while (keep_alive); DEBUG_TRACE("Done processing connection from %s (%f sec)", @@ -18873,17 +18895,40 @@ conn->request_info.remote_port = ntohs(USA_IN_PORT_UNSAFE(&conn->client.rsa)); + conn->request_info.server_port = + ntohs(USA_IN_PORT_UNSAFE(&conn->client.lsa)); + sockaddr_to_string(conn->request_info.remote_addr, sizeof(conn->request_info.remote_addr), &conn->client.rsa); - DEBUG_TRACE("Start processing connection from %s", + DEBUG_TRACE("Incomming %sconnection from %s", + (conn->client.is_ssl ? "SSL " : ""), conn->request_info.remote_addr); conn->request_info.is_ssl = conn->client.is_ssl; if (conn->client.is_ssl) { -#if !defined(NO_SSL) + +#if defined(USE_MBEDTLS) + /* HTTPS connection */ + if (mbed_ssl_accept(&(conn->ssl), + conn->dom_ctx->ssl_ctx, + (int *)&(conn->client.sock), + conn->phys_ctx) + == 0) { + /* conn->dom_ctx is set in get_request */ + /* process HTTPS connection */ + init_connection(conn); + conn->connection_type = CONNECTION_TYPE_REQUEST; + conn->protocol_type = PROTOCOL_TYPE_HTTP1; + process_new_connection(conn); + } else { + /* make sure the connection is cleaned up on SSL failure */ + close_connection(conn); + } + +#elif !defined(NO_SSL) /* HTTPS connection */ if (sslize(conn, SSL_accept, NULL)) { /* conn->dom_ctx is set in get_request */ @@ -18938,6 +18983,7 @@ close_connection(conn); } #endif + } else { /* process HTTP connection */ init_connection(conn); @@ -18971,6 +19017,12 @@ mg_free(conn->buf); conn->buf = NULL; + /* Free cleaned URI (if any) */ + if (conn->request_info.local_uri != conn->request_info.local_uri_raw) { + mg_free((void *)conn->request_info.local_uri); + conn->request_info.local_uri = NULL; + } + #if defined(USE_SERVER_STATS) conn->conn_state = 9; /* done */ #endif @@ -19041,24 +19093,27 @@ } #if !defined(__ZEPHYR__) - /* Set TCP keep-alive. This is needed because if HTTP-level - * keep-alive - * is enabled, and client resets the connection, server won't get - * TCP FIN or RST and will keep the connection open forever. With - * TCP keep-alive, next keep-alive handshake will figure out that - * the client is down and will close the server end. - * Thanks to Igor Klopov who suggested the patch. */ - if (setsockopt(so.sock, - SOL_SOCKET, - SO_KEEPALIVE, - (SOCK_OPT_TYPE)&on, - sizeof(on)) - != 0) { - mg_cry_ctx_internal( - ctx, - "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s", - __func__, - strerror(ERRNO)); + if ((so.lsa.sa.sa_family == AF_INET) + || (so.lsa.sa.sa_family == AF_INET6)) { + /* Set TCP keep-alive for TCP sockets (IPv4 and IPv6). + * This is needed because if HTTP-level keep-alive + * is enabled, and client resets the connection, server won't get + * TCP FIN or RST and will keep the connection open forever. With + * TCP keep-alive, next keep-alive handshake will figure out that + * the client is down and will close the server end. + * Thanks to Igor Klopov who suggested the patch. */ + if (setsockopt(so.sock, + SOL_SOCKET, + SO_KEEPALIVE, + (SOCK_OPT_TYPE)&on, + sizeof(on)) + != 0) { + mg_cry_ctx_internal( + ctx, + "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s", + __func__, + strerror(ERRNO)); + } } #endif @@ -19071,7 +19126,7 @@ */ if ((ctx->dd.config[CONFIG_TCP_NODELAY] != NULL) && (!strcmp(ctx->dd.config[CONFIG_TCP_NODELAY], "1"))) { - if (set_tcp_nodelay(so.sock, 1) != 0) { + if (set_tcp_nodelay(&so, 1) != 0) { mg_cry_ctx_internal( ctx, "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s", @@ -19105,7 +19160,7 @@ mg_set_thread_name("master"); -/* Increase priority of the master thread */ + /* Increase priority of the master thread */ #if defined(_WIN32) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); #elif defined(USE_MASTER_THREAD_PRIORITY) @@ -19120,7 +19175,7 @@ } #endif -/* Initialize thread local storage */ + /* Initialize thread local storage */ #if defined(_WIN32) tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL); #endif @@ -19134,10 +19189,43 @@ tls.user_ptr = NULL; } + /* Lua background script "start" event */ +#if defined(USE_LUA) + if (ctx->lua_background_state) { + lua_State *lstate = (lua_State *)ctx->lua_background_state; + pthread_mutex_lock(&ctx->lua_bg_mutex); + + /* call "start()" in Lua */ + lua_getglobal(lstate, "start"); + if (lua_type(lstate, -1) == LUA_TFUNCTION) { + int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0); + if (ret != 0) { + struct mg_connection fc; + lua_cry(fake_connection(&fc, ctx), + ret, + lstate, + "lua_background_script", + "start"); + } + } else { + lua_pop(lstate, 1); + } + + /* determine if there is a "log()" function in Lua background script */ + lua_getglobal(lstate, "log"); + if (lua_type(lstate, -1) == LUA_TFUNCTION) { + ctx->lua_bg_log_available = 1; + } + lua_pop(lstate, 1); + + pthread_mutex_unlock(&ctx->lua_bg_mutex); + } +#endif + /* Server starts *now* */ ctx->start_time = time(NULL); - /* Start the server */ + /* Server accept loop */ pfd = ctx->listening_socket_fds; while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { for (i = 0; i < ctx->num_listening_sockets; i++) { @@ -19145,7 +19233,11 @@ pfd[i].events = POLLIN; } - if (poll(pfd, ctx->num_listening_sockets, 200) > 0) { + if (mg_poll(pfd, + ctx->num_listening_sockets, + SOCKET_TIMEOUT_QUANTUM, + &(ctx->stop_flag)) + > 0) { for (i = 0; i < ctx->num_listening_sockets; i++) { /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the * successful poll, and POLLIN is defined as @@ -19189,14 +19281,26 @@ /* Free Lua state of lua background task */ if (ctx->lua_background_state) { lua_State *lstate = (lua_State *)ctx->lua_background_state; - lua_getglobal(lstate, LUABACKGROUNDPARAMS); - if (lua_istable(lstate, -1)) { - reg_boolean(lstate, "shutdown", 1); - lua_pop(lstate, 1); - mg_sleep(2); + ctx->lua_bg_log_available = 0; + + /* call "stop()" in Lua */ + pthread_mutex_lock(&ctx->lua_bg_mutex); + lua_getglobal(lstate, "stop"); + if (lua_type(lstate, -1) == LUA_TFUNCTION) { + int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0); + if (ret != 0) { + struct mg_connection fc; + lua_cry(fake_connection(&fc, ctx), + ret, + lstate, + "lua_background_script", + "stop"); + } } lua_close(lstate); + ctx->lua_background_state = 0; + pthread_mutex_unlock(&ctx->lua_bg_mutex); } #endif @@ -19283,6 +19387,10 @@ /* Destroy other context global data structures mutex */ (void)pthread_mutex_destroy(&ctx->nonce_mutex); +#if defined(USE_LUA) + (void)pthread_mutex_destroy(&ctx->lua_bg_mutex); +#endif + /* Deallocate config parameters */ for (i = 0; i < NUM_OPTIONS; i++) { if (ctx->dd.config[i] != NULL) { @@ -19301,7 +19409,14 @@ mg_free(tmp_rh); } -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) + if (ctx->dd.ssl_ctx != NULL) { + mbed_sslctx_uninit(ctx->dd.ssl_ctx); + mg_free(ctx->dd.ssl_ctx); + ctx->dd.ssl_ctx = NULL; + } + +#elif !defined(NO_SSL) /* Deallocate SSL context */ if (ctx->dd.ssl_ctx != NULL) { void *ssl_ctx = (void *)ctx->dd.ssl_ctx; @@ -19379,9 +19494,6 @@ get_system_name(char **sysName) { #if defined(_WIN32) -#if defined(_WIN32_WCE) - *sysName = mg_strdup("WinCE"); -#else char name[128]; DWORD dwVersion = 0; DWORD dwMajorVersion = 0; @@ -19391,7 +19503,7 @@ #if defined(_MSC_VER) #pragma warning(push) -/* GetVersion was declared deprecated */ + /* GetVersion was declared deprecated */ #pragma warning(disable : 4996) #endif dwVersion = GetVersion(); @@ -19413,7 +19525,7 @@ (wowRet ? (isWoW ? " (WoW64)" : "") : " (?)")); *sysName = mg_strdup(name); -#endif + #elif defined(__ZEPHYR__) *sysName = mg_strdup("Zephyr OS"); @@ -19454,11 +19566,8 @@ } -#if !defined(MG_EXPERIMENTAL_INTERFACES) -static -#endif - struct mg_context * - mg_start2(struct mg_init_data *init, struct mg_error_data *error) +struct mg_context * +mg_start2(struct mg_init_data *init, struct mg_error_data *error) { struct mg_context *ctx; const char *name, *value, *default_value; @@ -19531,6 +19640,9 @@ ctx->sq_blocked = 0; #endif ok &= (0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr)); +#if defined(USE_LUA) + ok &= (0 == pthread_mutex_init(&ctx->lua_bg_mutex, &pthread_mutex_attr)); +#endif if (!ok) { const char *err_msg = "Cannot initialize thread synchronization objects"; @@ -19698,7 +19810,7 @@ return NULL; } -/* Document root */ + /* Document root */ #if defined(NO_FILES) if (ctx->dd.config[DOCUMENT_ROOT] != NULL) { mg_cry_ctx_internal(ctx, "%s", "Document root must not be set"); @@ -19720,42 +19832,86 @@ #if defined(USE_LUA) /* If a Lua background script has been configured, start it. */ + ctx->lua_bg_log_available = 0; if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) { char ebuf[256]; struct vec opt_vec; struct vec eq_vec; const char *sparams; - lua_State *state = mg_prepare_lua_context_script( + + memset(ebuf, 0, sizeof(ebuf)); + pthread_mutex_lock(&ctx->lua_bg_mutex); + + /* Create a Lua state, load all standard libraries and the mg table */ + lua_State *state = mg_lua_context_script_prepare( ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf)); if (!state) { - mg_cry_ctx_internal(ctx, "lua_background_script error: %s", ebuf); + mg_cry_ctx_internal(ctx, + "lua_background_script load error: %s", + ebuf); if ((error != NULL) && (error->text_buffer_size > 0)) { mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Error in script %s: %s", - config_options[DOCUMENT_ROOT].name, + config_options[LUA_BACKGROUND_SCRIPT].name, ebuf); } + pthread_mutex_unlock(&ctx->lua_bg_mutex); + free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } - ctx->lua_background_state = (void *)state; - - lua_newtable(state); - reg_boolean(state, "shutdown", 0); + /* Add a table with parameters into mg.params */ sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS]; + if (sparams && sparams[0]) { + lua_getglobal(state, "mg"); + lua_pushstring(state, "params"); + lua_newtable(state); + + while ((sparams = next_option(sparams, &opt_vec, &eq_vec)) + != NULL) { + reg_llstring( + state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len); + if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0) + break; + } + lua_rawset(state, -3); + lua_pop(state, 1); + } - while ((sparams = next_option(sparams, &opt_vec, &eq_vec)) != NULL) { - reg_llstring( - state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len); - if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0) - break; + /* Call script */ + state = mg_lua_context_script_run(state, + ctx->dd.config[LUA_BACKGROUND_SCRIPT], + ctx, + ebuf, + sizeof(ebuf)); + if (!state) { + mg_cry_ctx_internal(ctx, + "lua_background_script start error: %s", + ebuf); + if ((error != NULL) && (error->text_buffer_size > 0)) { + mg_snprintf(NULL, + NULL, /* No truncation check for error buffers */ + error->text, + error->text_buffer_size, + "Error in script %s: %s", + config_options[DOCUMENT_ROOT].name, + ebuf); + } + pthread_mutex_unlock(&ctx->lua_bg_mutex); + + free_context(ctx); + pthread_setspecific(sTlsKey, NULL); + return NULL; } - lua_setglobal(state, LUABACKGROUNDPARAMS); + + /* state remains valid */ + ctx->lua_background_state = (void *)state; + pthread_mutex_unlock(&ctx->lua_bg_mutex); } else { ctx->lua_background_state = 0; @@ -19783,7 +19939,26 @@ } #endif -#if !defined(NO_SSL) +#if defined(USE_MBEDTLS) + if (!mg_sslctx_init(ctx, NULL)) { + const char *err_msg = "Error initializing SSL context"; + /* Fatal error - abort start. */ + mg_cry_ctx_internal(ctx, "%s", err_msg); + + if ((error != NULL) && (error->text_buffer_size > 0)) { + mg_snprintf(NULL, + NULL, /* No truncation check for error buffers */ + error->text, + error->text_buffer_size, + "%s", + err_msg); + } + free_context(ctx); + pthread_setspecific(sTlsKey, NULL); + return NULL; + } + +#elif !defined(NO_SSL) if (!init_ssl_ctx(ctx, NULL)) { const char *err_msg = "Error initializing SSL context"; /* Fatal error - abort start. */ @@ -20077,7 +20252,6 @@ } -#if defined(MG_EXPERIMENTAL_INTERFACES) /* Add an additional domain to an already running web server. */ int mg_start_domain2(struct mg_context *ctx, @@ -20209,7 +20383,7 @@ new_dom->shared_lua_websockets = NULL; #endif -#if !defined(NO_SSL) +#if !defined(NO_SSL) && !defined(USE_MBEDTLS) if (!init_ssl_ctx(ctx, new_dom)) { /* Init SSL failed */ if ((error != NULL) && (error->text_buffer_size > 0)) { @@ -20274,21 +20448,19 @@ return mg_start_domain2(ctx, options, NULL); } -#endif - /* Feature check API function */ unsigned mg_check_feature(unsigned feature) { static const unsigned feature_set = 0 -/* Set bits for available features according to API documentation. - * This bit mask is created at compile time, according to the active - * preprocessor defines. It is a single const value at runtime. */ + /* Set bits for available features according to API documentation. + * This bit mask is created at compile time, according to the active + * preprocessor defines. It is a single const value at runtime. */ #if !defined(NO_FILES) | MG_FEATURES_FILES #endif -#if !defined(NO_SSL) +#if !defined(NO_SSL) || defined(USE_MBEDTLS) | MG_FEATURES_SSL #endif #if !defined(NO_CGI) @@ -20315,26 +20487,26 @@ #if defined(USE_ZLIB) | MG_FEATURES_COMPRESSION #endif +#if defined(USE_HTTP2) + | MG_FEATURES_HTTP2 +#endif +#if defined(USE_X_DOM_SOCKET) + | MG_FEATURES_X_DOMAIN_SOCKET +#endif -/* Set some extra bits not defined in the API documentation. - * These bits may change without further notice. */ + /* Set some extra bits not defined in the API documentation. + * These bits may change without further notice. */ #if defined(MG_LEGACY_INTERFACE) - | 0x00008000u + | 0x80000000u #endif #if defined(MG_EXPERIMENTAL_INTERFACES) - | 0x00004000u -#endif -#if defined(MEMORY_DEBUGGING) - | 0x00001000u + | 0x40000000u #endif -#if defined(USE_TIMERS) - | 0x00020000u +#if !defined(NO_RESPONSE_BUFFERING) + | 0x20000000u #endif -#if !defined(NO_NONCE_CHECK) - | 0x00040000u -#endif -#if !defined(NO_POPEN) - | 0x00080000u +#if defined(MEMORY_DEBUGGING) + | 0x10000000u #endif ; return (feature & feature_set); @@ -20414,7 +20586,7 @@ #if defined(_MSC_VER) #pragma warning(push) -/* GetVersion was declared deprecated */ + /* GetVersion was declared deprecated */ #pragma warning(disable : 4996) #endif dwVersion = GetVersion(); @@ -20522,29 +20694,30 @@ #endif } - /* Build date */ + /* Build identifier. If BUILD_DATE is not set, __DATE__ will be used. */ { +#if defined(BUILD_DATE) + const char *bd = BUILD_DATE; +#else #if defined(GCC_DIAGNOSTIC) #if GCC_VERSION >= 40900 #pragma GCC diagnostic push -/* Disable bogus compiler warning -Wdate-time, appeared in gcc5 */ + /* Disable idiotic compiler warning -Wdate-time, appeared in gcc5. This + * does not work in some versions. If "BUILD_DATE" is defined to some + * string, it is used instead of __DATE__. */ #pragma GCC diagnostic ignored "-Wdate-time" #endif #endif -#ifdef BUILD_DATE - const char *bd = BUILD_DATE; -#else const char *bd = __DATE__; -#endif - - mg_snprintf( - NULL, NULL, block, sizeof(block), ",%s\"build\" : \"%s\"", eol, bd); - #if defined(GCC_DIAGNOSTIC) #if GCC_VERSION >= 40900 #pragma GCC diagnostic pop #endif #endif +#endif + + mg_snprintf( + NULL, NULL, block, sizeof(block), ",%s\"build\" : \"%s\"", eol, bd); system_info_length += mg_str_append(&buffer, end, block); } @@ -20721,7 +20894,7 @@ context_info_length += mg_str_append(&buffer, end, "{"); if (ms) { /* <-- should be always true */ - /* Memory information */ + /* Memory information */ int blockCount = (int)ms->blockCount; int64_t totalMemUsed = ms->totalMemUsed; int64_t maxMemUsed = ms->maxMemUsed; @@ -20890,6 +21063,16 @@ } +void +mg_disable_connection_keep_alive(struct mg_connection *conn) +{ + /* https://github.com/civetweb/civetweb/issues/727 */ + if (conn != NULL) { + conn->must_close = 1; + } +} + + #if defined(MG_EXPERIMENTAL_INTERFACES) /* Get connection information. It can be printed or stored by the caller. * Return the size of available information. */ @@ -21216,12 +21399,14 @@ mg_global_unlock(); -#if !defined(NO_SSL) +#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ + || defined(OPENSSL_API_3_0)) \ + && !defined(NO_SSL) if (features_to_init & MG_FEATURES_SSL) { - if (!mg_ssl_initialized) { + if (!mg_openssl_initialized) { char ebuf[128]; - if (initialize_ssl(ebuf, sizeof(ebuf))) { - mg_ssl_initialized = 1; + if (initialize_openssl(ebuf, sizeof(ebuf))) { + mg_openssl_initialized = 1; } else { (void)ebuf; DEBUG_TRACE("Initializing SSL failed: %s", ebuf); @@ -21257,10 +21442,10 @@ mg_init_library_called--; if (mg_init_library_called == 0) { -#if !defined(NO_SSL) - if (mg_ssl_initialized) { - uninitialize_ssl(); - mg_ssl_initialized = 0; +#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1)) && !defined(NO_SSL) + if (mg_openssl_initialized) { + uninitialize_openssl(); + mg_openssl_initialized = 0; } #endif diff -Nru civetweb-1.13+dfsg/src/CMakeLists.txt civetweb-1.15+dfsg/src/CMakeLists.txt --- civetweb-1.13+dfsg/src/CMakeLists.txt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/CMakeLists.txt 2021-09-01 08:46:33.000000000 +0000 @@ -246,6 +246,12 @@ target_link_libraries(civetweb-c-library ${LUA_LIBRARIES}) endif() +if (CIVETWEB_ENABLE_ZLIB) + find_package(ZLIB) + include_directories(${ZLIB_INCLUDE_DIRS}) + target_link_libraries(civetweb-c-library ${ZLIB_LIBRARIES}) +endif() + # The web server executable if (CIVETWEB_ENABLE_SERVER_EXECUTABLE) add_executable(civetweb-c-executable main.c) @@ -257,9 +263,7 @@ install( TARGETS civetweb-c-executable EXPORT ${PROJECT_NAME}-targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server) endif() target_include_directories( @@ -322,3 +326,23 @@ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT civetweb-cpp) endif() + +# Configure lookup behavior in civetweb config + +if(LIBDL_FOUND) + set(LOOKUP_LIBDL TRUE PARENT_SCOPE) +else() + set(LOOKUP_LIBDL FALSE PARENT_SCOPE) +endif() + +if(LIBRT_FOUND) + set(LOOKUP_LIBRT TRUE PARENT_SCOPE) +else() + set(LOOKUP_LIBRT FALSE PARENT_SCOPE) +endif() + +if(WINSOCK_FOUND) + set(LOOKUP_WINSOCK TRUE PARENT_SCOPE) +else() + set(LOOKUP_WINSOCK FALSE PARENT_SCOPE) +endif() diff -Nru civetweb-1.13+dfsg/src/handle_form.inl civetweb-1.15+dfsg/src/handle_form.inl --- civetweb-1.13+dfsg/src/handle_form.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/handle_form.inl 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2020 the Civetweb developers +/* Copyright (c) 2016-2021 the Civetweb developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -55,6 +55,8 @@ mg_cry_internal(conn, "%s: Cannot decode filename", __func__); return MG_FORM_FIELD_STORAGE_SKIP; } + remove_dot_segments(filename_dec); + } else { filename_dec[0] = 0; } @@ -83,16 +85,18 @@ } static int -url_encoded_field_get(const struct mg_connection *conn, - const char *key, - size_t key_len, - const char *value, - size_t value_len, - struct mg_form_data_handler *fdh) +url_encoded_field_get( + const struct mg_connection *conn, + const char *key, + size_t key_len, + const char *value, + size_t *value_len, /* IN: number of bytes available in "value", OUT: number + of bytes processed */ + struct mg_form_data_handler *fdh) { char key_dec[1024]; - char *value_dec = (char *)mg_malloc_ctx(value_len + 1, conn->phys_ctx); + char *value_dec = (char *)mg_malloc_ctx(*value_len + 1, conn->phys_ctx); int value_dec_len, ret; if (!value_dec) { @@ -100,14 +104,18 @@ mg_cry_internal(conn, "%s: Not enough memory (required: %lu)", __func__, - (unsigned long)(value_len + 1)); + (unsigned long)(*value_len + 1)); return MG_FORM_FIELD_STORAGE_ABORT; } mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1); - value_dec_len = - mg_url_decode(value, (int)value_len, value_dec, (int)value_len + 1, 1); + if (*value_len >= 2 && value[*value_len - 2] == '%') + *value_len -= 2; + else if (*value_len >= 1 && value[*value_len - 1] == '%') + (*value_len)--; + value_dec_len = mg_url_decode( + value, (int)*value_len, value_dec, ((int)*value_len) + 1, 1); ret = fdh->field_get(key_dec, value_dec, @@ -260,16 +268,14 @@ next = strchr(val, '&'); if (next) { vallen = next - val; - next++; } else { vallen = (ptrdiff_t)strlen(val); - next = val + vallen; } if (field_storage == MG_FORM_FIELD_STORAGE_GET) { /* Call callback */ r = url_encoded_field_get( - conn, data, (size_t)keylen, val, (size_t)vallen, fdh); + conn, data, (size_t)keylen, val, (size_t *)&vallen, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; @@ -279,6 +285,14 @@ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } + + if (next) { + next++; + } else { + /* vallen may have been modified by url_encoded_field_get */ + next = val + vallen; + } + #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { /* Store the content to a file */ @@ -450,11 +464,9 @@ next = strchr(val, '&'); if (next) { vallen = next - val; - next++; end_of_key_value_pair_found = 1; } else { vallen = (ptrdiff_t)strlen(val); - next = val + vallen; end_of_key_value_pair_found = all_data_read; } @@ -472,7 +484,7 @@ ? 0 : (size_t)keylen), val, - (size_t)vallen, + (size_t *)&vallen, fdh); get_block++; if (r == MG_FORM_FIELD_HANDLE_ABORT) { @@ -484,6 +496,14 @@ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } + + if (next) { + next++; + } else { + /* vallen may have been modified by url_encoded_field_get */ + next = val + vallen; + } + #if !defined(NO_FILESYSTEMS) if (fstore.access.fp) { size_t n = (size_t) diff -Nru civetweb-1.13+dfsg/src/main.c civetweb-1.15+dfsg/src/main.c --- civetweb-1.13+dfsg/src/main.c 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/main.c 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2020 the Civetweb developers +/* Copyright (c) 2013-2021 the Civetweb developers * Copyright (c) 2004-2013 Sergey Lyubka * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -41,7 +41,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wreserved-id-macro" #endif - +#if !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE 600 /* For PATH_MAX on linux */ /* This should also be sufficient for "realpath", according to * http://man7.org/linux/man-pages/man3/realpath.3.html, but in @@ -51,6 +51,7 @@ * #pragma clang diagnostic ignored "-Wimplicit-function-declaration" */ #endif +#endif #if !defined(IGNORE_UNUSED_RESULT) #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1)) @@ -228,6 +229,10 @@ OPTION_WEBPAGE, OPTION_ADD_DOMAIN, OPTION_HIDE_TRAY, +#if defined(DAEMONIZE) + ENABLE_DAEMONIZE, +#endif + NUM_MAIN_OPTIONS }; @@ -237,6 +242,10 @@ {"website", MG_CONFIG_TYPE_STRING, NULL}, {"add_domain", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"hide_tray", MG_CONFIG_TYPE_BOOLEAN, NULL}, +#if defined(DAEMONIZE) + {"daemonize", MG_CONFIG_TYPE_BOOLEAN, "no"}, +#endif + {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}}; @@ -268,6 +277,25 @@ } +static void +warn(const char *fmt, ...) +{ + va_list ap; + char msg[512] = ""; + + va_start(ap, fmt); + (void)vsnprintf(msg, sizeof(msg) - 1, fmt, ap); + msg[sizeof(msg) - 1] = 0; + va_end(ap); + +#if defined(_WIN32) + MessageBox(NULL, msg, "Warning", MB_OK); +#else + fprintf(stderr, "%s\n", msg); +#endif +} + + #if defined(WIN32) static int MakeConsole(void); #endif @@ -276,7 +304,7 @@ static void show_server_name(void) { -#ifdef BUILD_DATE +#if defined(BUILD_DATE) const char *bd = BUILD_DATE; #else const char *bd = __DATE__; @@ -993,7 +1021,7 @@ } -static void +static int verify_existence(char **options, const char *option_name, int must_be_dir) { struct stat st; @@ -1018,12 +1046,14 @@ if (path != NULL && (stat(path, &st) != 0 || ((S_ISDIR(st.st_mode) ? 1 : 0) != must_be_dir))) { - die("Invalid path for %s: [%s]: (%s). Make sure that path is either " - "absolute, or it is relative to civetweb executable.", - option_name, - path, - strerror(errno)); + warn("Invalid path for %s: [%s]: (%s). Make sure that path is either " + "absolute, or it is relative to civetweb executable.", + option_name, + path, + strerror(errno)); + return 0; } + return 1; } @@ -1251,10 +1281,12 @@ return 1; } -static void + +static int sanitize_options(char *options[] /* server options */, const char *arg0 /* argv[0] */) { + int ok = 1; /* Make sure we have absolute paths for files and directories */ set_absolute_path(options, "document_root", arg0); set_absolute_path(options, "put_delete_auth_file", arg0); @@ -1268,14 +1300,21 @@ set_absolute_path(options, "ssl_certificate", arg0); /* Make extra verification for certain options */ - verify_existence(options, "document_root", 1); - verify_existence(options, "cgi_interpreter", 0); - verify_existence(options, "ssl_certificate", 0); - verify_existence(options, "ssl_ca_path", 1); - verify_existence(options, "ssl_ca_file", 0); + if (!verify_existence(options, "document_root", 1)) + ok = 0; + if (!verify_existence(options, "cgi_interpreter", 0)) + ok = 0; + if (!verify_existence(options, "ssl_certificate", 0)) + ok = 0; + if (!verify_existence(options, "ssl_ca_path", 1)) + ok = 0; + if (!verify_existence(options, "ssl_ca_file", 0)) + ok = 0; #if defined(USE_LUA) - verify_existence(options, "lua_preload_file", 0); + if (!verify_existence(options, "lua_preload_file", 0)) + ok = 0; #endif + return ok; } @@ -1384,7 +1423,10 @@ /* Update config based on command line arguments */ process_command_line_arguments(argc, argv, options); - sanitize_options(options, argv[0]); + i = sanitize_options(options, argv[0]); + if (!i) { + die("Invalid options"); + } /* Setup signal handler: quit on Ctrl-C */ signal(SIGTERM, signal_handler); @@ -1435,6 +1477,7 @@ g_server_name, ((g_user_data.first_message == NULL) ? "unknown reason" : g_user_data.first_message)); + /* TODO: Edit file g_config_file_name */ } #if defined(MG_EXPERIMENTAL_INTERFACES) @@ -1450,7 +1493,10 @@ strerror(errno)); } - sanitize_options(options, argv[0]); + j = sanitize_options(options, argv[0]); + if (!j) { + die("Invalid options"); + } j = mg_start_domain(g_ctx, (const char **)options); if (j < 0) { @@ -1519,6 +1565,7 @@ static SERVICE_STATUS_HANDLE hStatus; static const char *service_magic_argument = "--"; static NOTIFYICONDATA TrayIcon; +static UINT msg_taskbar_created; static void WINAPI ControlHandler(DWORD code) @@ -2237,6 +2284,32 @@ } +static int +optioncmp(const char *o1, const char *o2) +{ + /* string compare for option names */ + while (*o1 || *o2) { + int c1 = 256 * (int)*o1; + int c2 = 256 * (int)*o2; + if (isalpha(*o1)) + c1 = toupper(*o1); + else if (*o1 == '_') + c1 = 1; + if (isalpha(*o2)) + c2 = toupper(*o2); + else if (*o2 == '_') + c2 = 1; + if (c1 < c2) + return -1; + if (c1 > c2) + return +1; + o1++; + o2++; + } + return 0; +} + + static void show_settings_dialog() { @@ -2313,8 +2386,8 @@ for (;;) { int swapped = 0; for (i = 1; i < NO_OF_OPTIONS; i++) { - if (strcmp(cv_options[option_index[i - 1]].name, - cv_options[option_index[i]].name) + if (optioncmp(cv_options[option_index[i - 1]].name, + cv_options[option_index[i]].name) > 0) { short swap = option_index[i]; option_index[i] = option_index[i - 1]; @@ -2871,6 +2944,25 @@ } +static void +add_icon_to_systray(HWND hWnd) +{ + /* tray icon is entry point to the menu */ + if (!g_hide_tray) { + TrayIcon.cbSize = sizeof(TrayIcon); + TrayIcon.uID = ID_ICON; + TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + TrayIcon.hIcon = hIcon; + TrayIcon.hWnd = hWnd; + snprintf(TrayIcon.szTip, sizeof(TrayIcon.szTip), "%s", g_server_name); + TrayIcon.uCallbackMessage = WM_USER; + Shell_NotifyIcon(NIM_ADD, &TrayIcon); + } else { + TrayIcon.cbSize = 0; + } +} + + /* Window proc for taskbar icon */ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -2994,6 +3086,12 @@ g_exit_flag = 1; PostQuitMessage(0); return 0; /* We've just sent our own quit message, with proper hwnd. */ + + default: + if (msg == msg_taskbar_created) { + add_icon_to_systray(hWnd); + } + break; } return DefWindowProc(hWnd, msg, wParam, lParam); @@ -3075,8 +3173,11 @@ init_server_name(); init_system_info(); + msg_taskbar_created = RegisterWindowMessage("TaskbarCreated"); + memset(&cls, 0, sizeof(cls)); - cls.lpfnWndProc = (WNDPROC)WindowProc; + cls.lpfnWndProc = WindowProc; + cls.hInstance = GetModuleHandle(NULL); cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); cls.lpszClassName = g_server_base_name; @@ -3090,7 +3191,7 @@ 0, NULL, NULL, - NULL, + cls.hInstance, NULL); ShowWindow(hWnd, SW_HIDE); @@ -3107,19 +3208,7 @@ 0); } - /* add icon to systray; tray icon is entry point to the menu */ - if (!g_hide_tray) { - TrayIcon.cbSize = sizeof(TrayIcon); - TrayIcon.uID = ID_ICON; - TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; - TrayIcon.hIcon = hIcon; - TrayIcon.hWnd = hWnd; - snprintf(TrayIcon.szTip, sizeof(TrayIcon.szTip), "%s", g_server_name); - TrayIcon.uCallbackMessage = WM_USER; - Shell_NotifyIcon(NIM_ADD, &TrayIcon); - } else { - TrayIcon.cbSize = 0; - } + add_icon_to_systray(hWnd); /* Message loop */ while (GetMessage(&msg, hWnd, 0, 0) > 0) { @@ -3280,3 +3369,4 @@ return EXIT_SUCCESS; } #endif /* _WIN32 */ +#undef printf diff -Nru civetweb-1.13+dfsg/src/md5.inl civetweb-1.15+dfsg/src/md5.inl --- civetweb-1.13+dfsg/src/md5.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/md5.inl 2021-09-01 08:46:33.000000000 +0000 @@ -285,8 +285,8 @@ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti) \ - t = a + F(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b + t = (a) + F(b, c, d) + X[k] + (Ti); \ + (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); @@ -312,8 +312,8 @@ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti) \ - t = a + G(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b + t = (a) + G(b, c, d) + X[k] + (Ti); \ + (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); @@ -339,8 +339,8 @@ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti) \ - t = a + H(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b + t = (a) + H(b, c, d) + X[k] + (Ti); \ + (a) = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); @@ -366,8 +366,8 @@ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti) \ - t = a + I(b, c, d) + X[k] + Ti; \ - a = ROTATE_LEFT(t, s) + b + t = (a) + I(b, c, d) + X[k] + (Ti); \ + (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); diff -Nru civetweb-1.13+dfsg/src/mod_duktape.inl civetweb-1.15+dfsg/src/mod_duktape.inl --- civetweb-1.13+dfsg/src/mod_duktape.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_duktape.inl 2021-09-01 08:46:33.000000000 +0000 @@ -262,7 +262,7 @@ duk_push_int(duk_ctx, conn->request_info.remote_port); duk_put_prop_string(duk_ctx, -2, "remote_port"); - duk_push_int(duk_ctx, ntohs(conn->client.lsa.sin.sin_port)); + duk_push_int(duk_ctx, conn->request_info.server_port); duk_put_prop_string(duk_ctx, -2, "server_port"); duk_push_object(duk_ctx); /* subfolder "conn.http_headers" */ diff -Nru civetweb-1.13+dfsg/src/mod_http2.inl civetweb-1.15+dfsg/src/mod_http2.inl --- civetweb-1.13+dfsg/src/mod_http2.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_http2.inl 2021-09-01 08:46:33.000000000 +0000 @@ -673,7 +673,7 @@ /* Now read the string */ if (!is_huff) { /* Not huffman encoded: Copy directly */ - char *result = mg_malloc_ctx(byte_len + 1, ctx); + char *result = (char *)mg_malloc_ctx(byte_len + 1, ctx); if (result) { memcpy(result, buf + (*i), byte_len); result[byte_len] = 0; @@ -948,7 +948,7 @@ uint8_t header_bin[1024]; uint16_t header_len = 0; int has_date = 0; - int has_connection = 0; + int has_connection_header = 0; int i; if ((conn->status_code < 100) || (conn->status_code > 999)) { @@ -995,7 +995,7 @@ /* Filter headers not valid in HTTP/2 */ if (!mg_strcasecmp("Connection", conn->response_info.http_headers[i].name)) { - has_connection = 1; + has_connection_header = 1; continue; /* do not send */ } @@ -1063,6 +1063,10 @@ DEBUG_TRACE("HTTP2 response header sent: stream %u", conn->http2.stream_id); + + (void)has_connection_header; /* ignore for the moment */ + + return 42; /* TODO */ } @@ -1156,25 +1160,13 @@ static int mem_h_count = 0; static int mem_d_count = 0; #define CHECK_LEAK_HDR_ALLOC(ptr) \ - DEBUG_TRACE("H NEW %08x (%i): %s", \ - (uint32_t)ptr, \ - ++mem_h_count, \ - (const char *)ptr) + DEBUG_TRACE("H NEW %p (%i): %s", ptr, ++mem_h_count, (const char *)ptr) #define CHECK_LEAK_HDR_FREE(ptr) \ - DEBUG_TRACE("H DEL %08x (%i): %s", \ - (uint32_t)ptr, \ - --mem_h_count, \ - (const char *)ptr) + DEBUG_TRACE("H DEL %p (%i): %s", ptr, --mem_h_count, (const char *)ptr) #define CHECK_LEAK_DYN_ALLOC(ptr) \ - DEBUG_TRACE("D NEW %08x (%i): %s", \ - (uint32_t)ptr, \ - ++mem_d_count, \ - (const char *)ptr) + DEBUG_TRACE("D NEW %p (%i): %s", ptr, ++mem_d_count, (const char *)ptr) #define CHECK_LEAK_DYN_FREE(ptr) \ - DEBUG_TRACE("D DEL %08x (%i): %s", \ - (uint32_t)ptr, \ - --mem_d_count, \ - (const char *)ptr) + DEBUG_TRACE("D DEL %p (%i): %s", ptr, --mem_d_count, (const char *)ptr) #else #define CHECK_LEAK_HDR_ALLOC(ptr) #define CHECK_LEAK_HDR_FREE(ptr) @@ -1250,7 +1242,6 @@ int bytes_read; uint8_t *buf; int my_settings_accepted = 0; - int my_settings_sent; const char *my_hpack_headers[128]; struct http2_settings client_settings = http2_default_settings; @@ -1258,7 +1249,6 @@ /* Send own settings */ http2_send_settings(conn, &http2_civetweb_server_settings); - my_settings_sent = 1; // http2_send_window(conn, 0, /* 0x3fff0001 */ 1024*1024); /* initialize hpack header table with predefined header fields */ @@ -1282,6 +1272,10 @@ int frame_is_padded = 0; int frame_is_priority = 0; +#if defined(USE_SERVER_STATS) + conn->conn_state = 3; /* HTTP/2 ready */ +#endif + bytes_read = mg_read(conn, http2_frame_head, sizeof(http2_frame_head)); if (bytes_read != sizeof(http2_frame_head)) { /* TODO: errormsg */ @@ -1331,7 +1325,7 @@ case 0: /* DATA */ { - int i = 0; /* TODO */ + /* TODO */ DEBUG_TRACE("%s", "HTTP2 DATA frame?"); } break; @@ -1343,6 +1337,9 @@ uint8_t weight = 0; uint8_t exclusive = 0; + /* Request start time */ + clock_gettime(CLOCK_MONOTONIC, &(conn->req_time)); + if (frame_is_padded) { padding = buf[i]; i++; @@ -1579,7 +1576,7 @@ /* header parsed */ DEBUG_TRACE("HTTP2 handle_request (stream %u)", http2_frame_stream_id); - handle_request(conn); + handle_request_stat_log(conn); /* Send "final" frame */ DEBUG_TRACE("HTTP2 handle_request done (stream %u)", @@ -1728,6 +1725,11 @@ DEBUG_TRACE("%s", "Unknown frame type"); goto clean_http2; } + + /* not used in the moment */ + (void)frame_is_end_stream; + (void)frame_is_end_headers; + (void)client_settings; } clean_http2: diff -Nru civetweb-1.13+dfsg/src/mod_lua.inl civetweb-1.15+dfsg/src/mod_lua.inl --- civetweb-1.13+dfsg/src/mod_lua.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_lua.inl 2021-09-01 08:46:33.000000000 +0000 @@ -57,7 +57,6 @@ static const char lua_regkey_lsp_include_history = 3; static const char lua_regkey_environment_type = 4; static const char lua_regkey_dtor = 5; -static const char *const LUABACKGROUNDPARAMS = "mg"; /* Limit nesting depth of mg.include. @@ -105,7 +104,7 @@ #define reg_string(L, name, val) \ - reg_lstring(L, name, val, val ? strlen(val) : 0) + reg_lstring(L, name, val, (val != NULL) ? strlen(val) : 0) static void @@ -120,6 +119,34 @@ static void +reg_i64(struct lua_State *L, const char *name, int64_t val) +{ + if (name == NULL) { + return; + } + lua_pushstring(L, name); + if (sizeof(lua_Integer) >= sizeof(val)) { + lua_pushinteger(L, (lua_Integer)val); + } else { + double d = (double)val; + lua_pushnumber(L, d); + } + lua_rawset(L, -3); +} + + +static void +reg_double(struct lua_State *L, const char *name, double val) +{ + if (name != NULL) { + lua_pushstring(L, name); + lua_pushnumber(L, val); + lua_rawset(L, -3); + } +} + + +static void reg_boolean(struct lua_State *L, const char *name, int val) { if (name != NULL) { @@ -157,7 +184,7 @@ static void -lua_cry(struct mg_connection *conn, +lua_cry(const struct mg_connection *conn, int err, lua_State *L, const char *lua_title, @@ -221,7 +248,7 @@ size_t s; SOCKET *psock; - if ((num_args == 1) && lua_istable(L, -1)) { + if ((num_args == 1) && lua_istable(L, 1)) { lua_getfield(L, -1, "sock"); psock = (SOCKET *)lua_tolstring(L, -1, &s); if (s != sizeof(SOCKET)) { @@ -245,7 +272,7 @@ size_t s; SOCKET *psock; - if ((num_args == 1) && lua_istable(L, -1)) { + if ((num_args == 1) && lua_istable(L, 1)) { lua_getfield(L, -1, "sock"); psock = (SOCKET *)lua_tolstring(L, -1, &s); if (s != sizeof(SOCKET)) { @@ -303,9 +330,9 @@ size_t s; SOCKET *psock; - if ((num_args == 1) && lua_istable(L, -1)) { + if ((num_args == 1) && lua_istable(L, 1)) { lua_getfield(L, -1, "sock"); - psock = (SOCKET *)lua_tolstring(L, -1, &s); + psock = (SOCKET *)lua_tolstring(L, 1, &s); if (s != sizeof(SOCKET)) { return luaL_error( L, @@ -337,16 +364,15 @@ union usa sa; int ok; - if ((num_args == 3) && lua_isstring(L, -3) && lua_isnumber(L, -2) - && lua_isnumber(L, -1)) { - ok = connect_socket(NULL, - lua_tostring(L, -3), - (int)lua_tonumber(L, -2), - (int)lua_tonumber(L, -1), - ebuf, - sizeof(ebuf), - &sock, - &sa); + if ((num_args == 3) && lua_isstring(L, 1) && lua_isnumber(L, 2) + && lua_isnumber(L, 3)) { + + const char *host = lua_tostring(L, 1); + const int port = lua_tointeger(L, 2); + const int is_ssl = lua_tointeger(L, 3); + + ok = connect_socket( + NULL, host, port, is_ssl, ebuf, sizeof(ebuf), &sock, &sa); if (!ok) { return luaL_error(L, ebuf); } else { @@ -1058,8 +1084,8 @@ if ((status >= 100) && (status <= 999)) { ret = mg_send_http_error(conn, status, - (auxText != NULL) ? "%s" : "", - auxText); + "%s", + (auxText != NULL) ? auxText : ""); } else { /* Syntax error */ return luaL_error(L, "invalid send_http_error() call"); @@ -1070,7 +1096,7 @@ } -/* mg.send_http_error */ +/* mg.send_http_ok */ static int lsp_send_http_ok(lua_State *L) { @@ -1117,6 +1143,44 @@ } +/* mg.mg_send_http_redirect */ +static int +lsp_send_http_redirect(lua_State *L) +{ + struct mg_connection *conn = + (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1)); + int num_args = lua_gettop(L); + int type1, type2; + const char *target_url = NULL; + int redirect_code = 300; + int ret; + + if (num_args < 2) { + /* Syntax error */ + return luaL_error(L, "invalid send_http_redirect() call"); + } + type1 = lua_type(L, 1); + type2 = lua_type(L, 2); + if (type1 == LUA_TSTRING) { + target_url = lua_tostring(L, 1); + } else if (type1 != LUA_TNIL) { + /* Syntax error */ + return luaL_error(L, "invalid send_http_redirect() call"); + } + if (type2 == LUA_TNUMBER) { + redirect_code = (int)lua_tonumber(L, 2); + } else { + /* Syntax error */ + return luaL_error(L, "invalid send_http_redirect() call"); + } + + ret = mg_send_http_redirect(conn, target_url, redirect_code); + + lua_pushnumber(L, ret); + return 1; +} + + /* mg.get_time */ static int lsp_get_time(lua_State *L) @@ -1203,7 +1267,7 @@ in = lua_tolstring(L, 1, &len); /* Create a modifyable copy */ - buf = mg_malloc_ctx(len + 1, ctx); + buf = (char *)mg_malloc_ctx(len + 1, ctx); if (buf == NULL) { return luaL_error(L, "out of memory in invalid split_form_data() call"); } @@ -1381,7 +1445,7 @@ lua_pushstring(L, dst); mg_free(dst); } else { - return luaL_error(L, "out of memory in url_decode() call"); + return luaL_error(L, "out of memory in url_encode() call"); } } else { lua_pushnil(L); @@ -1867,7 +1931,7 @@ } /* Syntax error */ - return luaL_error(L, "invalid random() call"); + return luaL_error(L, "invalid uuid() call"); } @@ -2172,8 +2236,8 @@ /* Argument for timer */ arg->L = L; - arg->script = ws->script; - arg->pmutex = &(ws->ws_mutex); + arg->script = (ws ? ws->script : NULL); + arg->pmutex = (ws ? &(ws->ws_mutex) : &(ctx->lua_bg_mutex)); memcpy(arg->txt, "return(", 7); memcpy(arg->txt + 7, action_txt, action_txt_len); arg->txt[action_txt_len + 7] = ')'; @@ -2207,8 +2271,8 @@ /* Argument for timer */ arg->L = L; - arg->script = ws->script; - arg->pmutex = &(ws->ws_mutex); + arg->script = (ws ? ws->script : NULL); + arg->pmutex = (ws ? &(ws->ws_mutex) : &(ctx->lua_bg_mutex)); arg->funcref = funcref; if (0 == timer_add(ctx, @@ -2261,7 +2325,6 @@ struct mg_connection *conn = (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1)); - int num_args = lua_gettop(L); /* Get mg.response - table */ lua_getglobal(L, "mg"); @@ -2302,7 +2365,7 @@ ret2 = 0; lua_pushnil(L); while (lua_next(L, -2)) { - int retadd; + int retadd = 0; int key_type = lua_type(L, -2); int value_type = lua_type(L, -1); if ((key_type == LUA_TSTRING) && (value_type == LUA_TSTRING)) { @@ -2310,7 +2373,7 @@ const char *key = lua_tolstring(L, -2, &key_len); const char *value = lua_tolstring(L, -1, &value_len); retadd = mg_response_header_add(conn, key, value, (int)value_len); - } else if ((key_type == LUA_TSTRING) && (value_type == LUA_TSTRING)) { + } else if ((key_type == LUA_TNUMBER) && (value_type == LUA_TSTRING)) { const char *value = lua_tostring(L, -1); retadd = mg_response_header_add_lines(conn, value); } @@ -2414,36 +2477,82 @@ /* Lua Environment */ enum { - LUA_ENV_TYPE_LUA_SERVER_PAGE = 0, - LUA_ENV_TYPE_PLAIN_LUA_PAGE = 1, - LUA_ENV_TYPE_LUA_WEBSOCKET = 2, + LUA_ENV_TYPE_LUA_SERVER_PAGE = 0, /* page.lp */ + LUA_ENV_TYPE_PLAIN_LUA_PAGE = 1, /* script.lua */ + LUA_ENV_TYPE_LUA_WEBSOCKET = 2, /* websock.lua */ + LUA_ENV_TYPE_BACKGROUND = 9 /* Lua backgrond script or exec from cmdline */ }; static void -prepare_lua_request_info(struct mg_connection *conn, lua_State *L) +push_lua_response_log_data(const struct mg_connection *conn, lua_State *L) +{ + int i; + const char *s; + + lua_newtable(L); + + /* request status */ + reg_int(L, "status", conn->status_code); + + /* protocol (http, https, ws, wss) */ + s = get_proto_name(conn); + reg_string(L, "protocol", s); + + /* request counter */ + reg_int(L, "handled_requests", conn->handled_requests); + + /* data read and written */ + reg_i64(L, "read", conn->consumed_content); + reg_i64(L, "written", conn->num_bytes_sent); + +#if !defined(NO_RESPONSE_BUFFERING) + lua_pushstring(L, "http_headers"); + lua_newtable(L); + for (i = 0; i < conn->response_info.num_headers; i++) { + reg_string(L, + conn->response_info.http_headers[i].name, + conn->response_info.http_headers[i].value); + } + lua_rawset(L, -3); +#endif + +#if defined(USE_SERVER_STATS) + reg_double(L, "processing_time", conn->processing_time); +#endif +} + + +static void +prepare_lua_request_info_inner(const struct mg_connection *conn, lua_State *L) { const char *s; int i; - /* Export mg.request_info */ - lua_pushstring(L, "request_info"); lua_newtable(L); reg_string(L, "request_method", conn->request_info.request_method); reg_string(L, "request_uri", conn->request_info.request_uri); reg_string(L, "uri", conn->request_info.local_uri); + reg_string(L, "uri_raw", conn->request_info.local_uri_raw); reg_string(L, "http_version", conn->request_info.http_version); reg_string(L, "query_string", conn->request_info.query_string); reg_string(L, "remote_addr", conn->request_info.remote_addr); /* TODO (high): ip version */ reg_int(L, "remote_port", conn->request_info.remote_port); + reg_int(L, "server_port", conn->request_info.server_port); reg_int(L, "num_headers", conn->request_info.num_headers); - reg_int(L, "server_port", ntohs(conn->client.lsa.sin.sin_port)); if (conn->path_info != NULL) { reg_string(L, "path_info", conn->path_info); } + { + char buf[2048]; + if (0 == mg_get_request_link(conn, buf, sizeof(buf))) { + reg_string(L, "request_link", buf); + } + } + if (conn->request_info.content_length >= 0) { /* reg_int64: content_length */ lua_pushstring(L, "content_length"); @@ -2489,6 +2598,15 @@ reg_string(L, "finger", conn->request_info.client_cert->finger); lua_rawset(L, -3); } +} + + +static void +prepare_lua_request_info(const struct mg_connection *conn, lua_State *L) +{ + /* Export mg.request_info */ + lua_pushstring(L, "request_info"); + prepare_lua_request_info_inner(conn, L); /* End of request_info */ lua_rawset(L, -3); @@ -2577,7 +2695,7 @@ static int lsp_mg_gc(lua_State *L) { - unsigned context_flags; + int context_flags; struct mg_context *ctx; struct mg_connection *conn = (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1)); @@ -2588,11 +2706,11 @@ lua_pushlightuserdata(L, (void *)&lua_regkey_environment_type); lua_gettable(L, LUA_REGISTRYINDEX); - context_flags = lua_tounsigned(L, -1); + context_flags = lua_tointeger(L, -1); if (ctx != NULL) { if (ctx->callbacks.exit_lua != NULL) { - ctx->callbacks.exit_lua(conn, L, context_flags); + ctx->callbacks.exit_lua(conn, L, (unsigned)context_flags); } } @@ -2630,6 +2748,30 @@ } +static int +lua_error_handler(lua_State *L) +{ + const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n"; + + lua_getglobal(L, "mg"); + if (!lua_isnil(L, -1)) { + lua_getfield(L, -1, "write"); /* call mg.write() */ + lua_pushstring(L, error_msg); + lua_pushliteral(L, "\n"); + lua_call(L, 2, 0); + IGNORE_UNUSED_RESULT( + luaL_dostring(L, "mg.write(debug.traceback(), '\\n')")); + } else { + printf("Lua error: [%s]\n", error_msg); + IGNORE_UNUSED_RESULT( + luaL_dostring(L, "print(debug.traceback(), '\\n')")); + } + /* TODO(lsm, low): leave the stack balanced */ + + return 0; +} + + static void prepare_lua_environment(struct mg_context *ctx, struct mg_connection *conn, @@ -2641,7 +2783,7 @@ const char *preload_file_name = NULL; const char *debug_params = NULL; - unsigned lua_context_flags = (unsigned)lua_env_type; + int lua_context_flags = lua_env_type; civetweb_open_lua_libs(L); @@ -2678,7 +2820,7 @@ lua_settable(L, LUA_REGISTRYINDEX); } lua_pushlightuserdata(L, (void *)&lua_regkey_environment_type); - lua_pushunsigned(L, (unsigned)lua_context_flags); + lua_pushinteger(L, lua_context_flags); lua_settable(L, LUA_REGISTRYINDEX); /* State close function */ @@ -2708,10 +2850,13 @@ case LUA_ENV_TYPE_LUA_WEBSOCKET: reg_string(L, "lua_type", "websocket"); break; + case LUA_ENV_TYPE_BACKGROUND: + reg_string(L, "lua_type", "background"); + break; } - if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE - || lua_env_type == LUA_ENV_TYPE_PLAIN_LUA_PAGE) { + if ((lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE) + || (lua_env_type == LUA_ENV_TYPE_PLAIN_LUA_PAGE)) { reg_conn_function(L, "cry", lsp_cry, conn); reg_conn_function(L, "read", lsp_read, conn); reg_conn_function(L, "write", lsp_write, conn); @@ -2720,6 +2865,10 @@ reg_conn_function(L, "send_file_body", lsp_send_file_body, conn); reg_conn_function(L, "send_http_error", lsp_send_http_error, conn); reg_conn_function(L, "send_http_ok", lsp_send_http_ok, conn); + reg_conn_function(L, + "send_http_redirect", + lsp_send_http_redirect, + conn); reg_conn_function(L, "redirect", lsp_redirect, conn); } @@ -2729,7 +2878,11 @@ if (lua_env_type == LUA_ENV_TYPE_LUA_WEBSOCKET) { reg_function(L, "write", lwebsock_write); + } + #if defined(USE_TIMERS) + if ((lua_env_type == LUA_ENV_TYPE_LUA_WEBSOCKET) + || (lua_env_type == LUA_ENV_TYPE_BACKGROUND)) { reg_function(L, "set_timeout", lwebsocket_set_timeout); reg_function(L, "set_interval", lwebsocket_set_interval); #endif @@ -2810,11 +2963,6 @@ preload_file_name = conn->dom_ctx->config[LUA_PRELOAD_FILE]; } - /* Preload file into new Lua environment */ - if (preload_file_name) { - IGNORE_UNUSED_RESULT(luaL_dofile(L, preload_file_name)); - } - /* Call user init function */ if (ctx != NULL) { if (ctx->callbacks.init_lua != NULL) { @@ -2822,6 +2970,16 @@ } } + /* Preload file into new Lua environment */ + if (preload_file_name) { + int ret = luaL_loadfile(L, preload_file_name); + if (ret != 0) { + lua_error_handler(L); + } else { + ret = lua_pcall(L, 0, 1, 0); + } + } + /* If debugging is enabled, add a hook */ if (debug_params) { int mask = 0; @@ -2839,30 +2997,6 @@ } -static int -lua_error_handler(lua_State *L) -{ - const char *error_msg = lua_isstring(L, -1) ? lua_tostring(L, -1) : "?\n"; - - lua_getglobal(L, "mg"); - if (!lua_isnil(L, -1)) { - lua_getfield(L, -1, "write"); /* call mg.write() */ - lua_pushstring(L, error_msg); - lua_pushliteral(L, "\n"); - lua_call(L, 2, 0); - IGNORE_UNUSED_RESULT( - luaL_dostring(L, "mg.write(debug.traceback(), '\\n')")); - } else { - printf("Lua error: [%s]\n", error_msg); - IGNORE_UNUSED_RESULT( - luaL_dostring(L, "print(debug.traceback(), '\\n')")); - } - /* TODO(lsm, low): leave the stack balanced */ - - return 0; -} - - static void mg_exec_lua_script(struct mg_connection *conn, const char *path, @@ -2905,8 +3039,9 @@ if (luaL_loadfile(L, path) != 0) { lua_error_handler(L); + } else { + lua_pcall(L, 0, 0, -2); } - lua_pcall(L, 0, 0, -2); lua_close(L); } } @@ -3323,7 +3458,7 @@ static lua_State * -mg_prepare_lua_context_script(const char *file_name, +mg_lua_context_script_prepare(const char *file_name, struct mg_context *ctx, char *ebuf, size_t ebuf_len) @@ -3332,8 +3467,6 @@ int lua_ret; const char *lua_err_txt; - (void)ctx; - L = luaL_newstate(); if (L == NULL) { mg_snprintf(NULL, @@ -3344,8 +3477,16 @@ "Cannot create Lua state"); return 0; } - civetweb_open_lua_libs(L); + /* Add all libraries */ + prepare_lua_environment(ctx, + NULL /* conn */, + NULL /* WS list*/, + L, + file_name, + LUA_ENV_TYPE_BACKGROUND); + + /* Load lua script file */ lua_ret = luaL_loadfile(L, file_name); if (lua_ret != LUA_OK) { /* Error when loading the file (e.g. file not found, @@ -3359,14 +3500,31 @@ "Error loading file %s: %s\n", file_name, lua_err_txt); + lua_close(L); return 0; } + /* lua_close(L); must be done somewhere else */ + return L; +} + + +static lua_State * +mg_lua_context_script_run(lua_State *L, + const char *file_name, + struct mg_context *ctx, + char *ebuf, + size_t ebuf_len) +{ + int lua_ret; + const char *lua_err_txt; + + (void)ctx; /* The script file is loaded, now call it */ lua_ret = lua_pcall(L, /* no arguments */ 0, /* zero or one return value */ 1, - /* errors as strint return value */ 0); + /* errors as string return value */ 0); if (lua_ret != LUA_OK) { /* Error when executing the script */ @@ -3378,10 +3536,28 @@ "Error running file %s: %s\n", file_name, lua_err_txt); + lua_close(L); return 0; } - /* lua_close(L); must be done somewhere else */ + /* Check optional return value */ + if (lua_isboolean(L, -1)) { + /* A boolean return value false indicates failure */ + int ret = lua_toboolean(L, -1); + if (ret == 0) { + /* Script returned false */ + mg_snprintf(NULL, + NULL, /* No truncation check for ebuf */ + ebuf, + ebuf_len, + "Script %s returned false\n", + file_name); + lua_close(L); + return 0; + } + } + + /* lua_close(L); must be done somewhere else */ return L; } @@ -3418,13 +3594,19 @@ } +/* Execute Lua script from main */ int run_lua(const char *file_name) { int func_ret = EXIT_FAILURE; char ebuf[512] = {0}; lua_State *L = - mg_prepare_lua_context_script(file_name, NULL, ebuf, sizeof(ebuf)); + mg_lua_context_script_prepare(file_name, NULL, ebuf, sizeof(ebuf)); + + if (L) { + L = mg_lua_context_script_run(L, file_name, NULL, ebuf, sizeof(ebuf)); + } + if (L) { /* Script executed */ if (lua_type(L, -1) == LUA_TNUMBER) { diff -Nru civetweb-1.13+dfsg/src/mod_lua_shared.inl civetweb-1.15+dfsg/src/mod_lua_shared.inl --- civetweb-1.13+dfsg/src/mod_lua_shared.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_lua_shared.inl 2021-09-01 08:46:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2020 CivetWeb developers +/* Copyright (c) 2018-2021 CivetWeb developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff -Nru civetweb-1.13+dfsg/src/mod_mbedtls.inl civetweb-1.15+dfsg/src/mod_mbedtls.inl --- civetweb-1.13+dfsg/src/mod_mbedtls.inl 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_mbedtls.inl 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,239 @@ +#if defined(USE_MBEDTLS) // USE_MBEDTLS used with NO_SSL + +#include "mbedtls/certs.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/debug.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/net.h" +#include "mbedtls/pk.h" +#include "mbedtls/platform.h" +#include "mbedtls/ssl.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" +#include + +typedef mbedtls_ssl_context SSL; + +typedef struct { + mbedtls_ssl_config conf; /* SSL configuration */ + mbedtls_x509_crt cert; /* Certificate */ + mbedtls_ctr_drbg_context ctr; /* Counter random generator state */ + mbedtls_entropy_context entropy; /* Entropy context */ + mbedtls_pk_context pkey; /* Private key */ +} SSL_CTX; + + +/* public api */ +int mbed_sslctx_init(SSL_CTX *ctx, const char *crt); +void mbed_sslctx_uninit(SSL_CTX *ctx); +void mbed_ssl_close(mbedtls_ssl_context *ssl); +int mbed_ssl_accept(mbedtls_ssl_context **ssl, + SSL_CTX *ssl_ctx, + int *sock, + struct mg_context *phys_ctx); +int mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len); +int mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len); + +static void mbed_debug(void *context, + int level, + const char *file, + int line, + const char *str); +static int mbed_ssl_handshake(mbedtls_ssl_context *ssl); + + +int +mbed_sslctx_init(SSL_CTX *ctx, const char *crt) +{ + mbedtls_ssl_config *conf; + int rc; + + if (ctx == NULL || crt == NULL) { + return -1; + } + + DEBUG_TRACE("%s", "Initializing MbedTLS SSL"); + mbedtls_entropy_init(&ctx->entropy); + + conf = &ctx->conf; + mbedtls_ssl_config_init(conf); + + /* Set mbedTLS debug level by defining MG_CONFIG_MBEDTLS_DEBUG: + * 0 No debug = mbedTLS DEFAULT + * 1 Error (default if "DEBUG" is set for CivetWeb) + * 2 State change + * 3 Informational + * 4 Verbose + */ +#if defined(DEBUG) || defined(MG_CONFIG_MBEDTLS_DEBUG) +#if defined(MG_CONFIG_MBEDTLS_DEBUG) + mbedtls_debug_set_threshold(MG_CONFIG_MBEDTLS_DEBUG); +#else + mbedtls_debug_set_threshold(1); +#endif + mbedtls_ssl_conf_dbg(conf, mbed_debug, (void *)ctx); +#endif + + /* Initialize TLS key and cert */ + mbedtls_pk_init(&ctx->pkey); + mbedtls_ctr_drbg_init(&ctx->ctr); + mbedtls_x509_crt_init(&ctx->cert); + + rc = mbedtls_ctr_drbg_seed(&ctx->ctr, + mbedtls_entropy_func, + &ctx->entropy, + (unsigned char *)"CivetWeb", + strlen("CivetWeb")); + if (rc != 0) { + DEBUG_TRACE("TLS random seed failed (%i)", rc); + return -1; + } + + rc = mbedtls_pk_parse_keyfile(&ctx->pkey, crt, NULL); + if (rc != 0) { + DEBUG_TRACE("TLS parse key file failed (%i)", rc); + return -1; + } + + rc = mbedtls_x509_crt_parse_file(&ctx->cert, crt); + if (rc != 0) { + DEBUG_TRACE("TLS parse crt file failed (%i)", rc); + return -1; + } + + rc = mbedtls_ssl_config_defaults(conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (rc != 0) { + DEBUG_TRACE("TLS set defaults failed (%i)", rc); + return -1; + } + + mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, &ctx->ctr); + + /* Set auth mode if peer cert should be verified */ + mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_ca_chain(conf, NULL, NULL); + + /* Configure server cert and key */ + rc = mbedtls_ssl_conf_own_cert(conf, &ctx->cert, &ctx->pkey); + if (rc != 0) { + DEBUG_TRACE("TLS cannot set certificate and private key (%i)", rc); + return -1; + } + return 0; +} + + +void +mbed_sslctx_uninit(SSL_CTX *ctx) +{ + mbedtls_ctr_drbg_free(&ctx->ctr); + mbedtls_pk_free(&ctx->pkey); + mbedtls_x509_crt_free(&ctx->cert); + mbedtls_entropy_free(&ctx->entropy); + mbedtls_ssl_config_free(&ctx->conf); +} + + +int +mbed_ssl_accept(mbedtls_ssl_context **ssl, + SSL_CTX *ssl_ctx, + int *sock, + struct mg_context *phys_ctx) +{ + int rc; + (void)phys_ctx; /* unused, if server statistics is not turned on */ + + DEBUG_TRACE("TLS accept processing %p", ssl); + + *ssl = (mbedtls_ssl_context *)mg_calloc_ctx(1, + sizeof(mbedtls_ssl_context), + phys_ctx); + if (*ssl == NULL) { + DEBUG_TRACE("TLS accept: malloc ssl failed (%i)", + (int)sizeof(mbedtls_ssl_context)); + return -1; + } + + mbedtls_ssl_init(*ssl); + mbedtls_ssl_setup(*ssl, &ssl_ctx->conf); + mbedtls_ssl_set_bio(*ssl, sock, mbedtls_net_send, mbedtls_net_recv, NULL); + rc = mbed_ssl_handshake(*ssl); + if (rc != 0) { + DEBUG_TRACE("TLS handshake failed (%i)", rc); + mbedtls_ssl_free(*ssl); + mg_free(*ssl); + *ssl = NULL; + return -1; + } + + DEBUG_TRACE("TLS connection %p accepted, state: %d", ssl, (*ssl)->state); + return 0; +} + + +void +mbed_ssl_close(mbedtls_ssl_context *ssl) +{ + DEBUG_TRACE("TLS connection %p closed", ssl); + mbedtls_ssl_close_notify(ssl); + mbedtls_ssl_free(ssl); + mg_free(ssl); /* mg_free for mg_calloc in mbed_ssl_accept */ +} + + +static int +mbed_ssl_handshake(mbedtls_ssl_context *ssl) +{ + int rc; + while ((rc = mbedtls_ssl_handshake(ssl)) != 0) { + if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE + && rc != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { + break; + } + } + + DEBUG_TRACE("TLS handshake rc: %d, state: %d", rc, ssl->state); + return rc; +} + + +int +mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len) +{ + int rc = mbedtls_ssl_read(ssl, buf, len); + /* DEBUG_TRACE("mbedtls_ssl_read: %d", rc); */ + return rc; +} + + +int +mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len) +{ + int rc = mbedtls_ssl_write(ssl, buf, len); + /* DEBUG_TRACE("mbedtls_ssl_write: %d", rc); */ + return rc; +} + + +static void +mbed_debug(void *user_param, + int level, + const char *file, + int line, + const char *str) +{ + (void)level; /* Ignored. Limit is set using mbedtls_debug_set_threshold */ + (void)user_param; /* Ignored. User parameter (context) is set using + mbedtls_ssl_conf_dbg */ + + DEBUG_TRACE("mbedTLS DEBUG: file: [%s] line: [%d] str: [%s]", + file, + line, + str); +} + +#endif /* USE_MBEDTLS */ diff -Nru civetweb-1.13+dfsg/src/mod_zlib.inl civetweb-1.15+dfsg/src/mod_zlib.inl --- civetweb-1.13+dfsg/src/mod_zlib.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/mod_zlib.inl 2021-09-01 08:46:33.000000000 +0000 @@ -12,6 +12,7 @@ { struct mg_connection *conn = (struct mg_connection *)opaque; void *ret = mg_calloc_ctx(items, size, conn->phys_ctx); + (void)conn; /* mg_calloc_ctx makro might not need it */ return ret; } @@ -125,8 +126,9 @@ mg_write(conn, "0\r\n\r\n", 5); } + #if defined(USE_WEBSOCKET) && defined(MG_EXPERIMENTAL_INTERFACES) -int +static int websocket_deflate_initialize(struct mg_connection *conn, int server) { int zret = @@ -173,7 +175,8 @@ return Z_OK; } -void + +static void websocket_deflate_negotiate(struct mg_connection *conn) { const char *extensions = mg_get_header(conn, "Sec-WebSocket-Extensions"); @@ -194,7 +197,7 @@ } else if (!strncmp(extensions, "client_no_context_takeover", 26)) { extensions += 26; conn->websocket_deflate_client_no_context_takeover = 1; - } else if (!strncmp(extensions, "server-max-window-bits", 22)) { + } else if (!strncmp(extensions, "server_max_window_bits", 22)) { extensions += 22; if (*extensions == '=') { ++extensions; @@ -218,7 +221,7 @@ if (*extensions == '"') ++extensions; } - } else if (!strncmp(extensions, "client-max-window-bits", 22)) { + } else if (!strncmp(extensions, "client_max_window_bits", 22)) { extensions += 22; if (*extensions == '=') { ++extensions; @@ -255,7 +258,8 @@ conn->websocket_deflate_initialized = 0; } -void + +static void websocket_deflate_response(struct mg_connection *conn) { if (conn->accept_gzip) { diff -Nru civetweb-1.13+dfsg/src/openssl_dl.inl civetweb-1.15+dfsg/src/openssl_dl.inl --- civetweb-1.13+dfsg/src/openssl_dl.inl 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/src/openssl_dl.inl 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,545 @@ +/* Copyright (c) 2013-2021 the Civetweb developers + * Copyright (c) 2004-2013 Sergey Lyubka + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +typedef struct ssl_st SSL; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct x509_store_ctx_st X509_STORE_CTX; +typedef struct x509_name X509_NAME; +typedef struct asn1_integer ASN1_INTEGER; +typedef struct bignum BIGNUM; +typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; +typedef struct evp_md EVP_MD; +typedef struct x509 X509; + + +#define SSL_CTRL_OPTIONS (32) +#define SSL_CTRL_CLEAR_OPTIONS (77) +#define SSL_CTRL_SET_ECDH_AUTO (94) + +#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L +#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L +#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L + +#define SSL_VERIFY_NONE (0) +#define SSL_VERIFY_PEER (1) +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2) +#define SSL_VERIFY_CLIENT_ONCE (4) + +#define SSL_OP_ALL (0x80000BFFul) + +#define SSL_OP_NO_SSLv2 (0x01000000ul) +#define SSL_OP_NO_SSLv3 (0x02000000ul) +#define SSL_OP_NO_TLSv1 (0x04000000ul) +#define SSL_OP_NO_TLSv1_2 (0x08000000ul) +#define SSL_OP_NO_TLSv1_1 (0x10000000ul) +#define SSL_OP_NO_TLSv1_3 (0x20000000ul) +#define SSL_OP_SINGLE_DH_USE (0x00100000ul) +#define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000ul) +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (0x00010000ul) +#define SSL_OP_NO_COMPRESSION (0x00020000ul) +#define SSL_OP_NO_RENEGOTIATION (0x40000000ul) + +#define SSL_CB_HANDSHAKE_START (0x10) +#define SSL_CB_HANDSHAKE_DONE (0x20) + +#define SSL_ERROR_NONE (0) +#define SSL_ERROR_SSL (1) +#define SSL_ERROR_WANT_READ (2) +#define SSL_ERROR_WANT_WRITE (3) +#define SSL_ERROR_WANT_X509_LOOKUP (4) +#define SSL_ERROR_SYSCALL (5) /* see errno */ +#define SSL_ERROR_ZERO_RETURN (6) +#define SSL_ERROR_WANT_CONNECT (7) +#define SSL_ERROR_WANT_ACCEPT (8) + +#define TLSEXT_TYPE_server_name (0) +#define TLSEXT_NAMETYPE_host_name (0) +#define SSL_TLSEXT_ERR_OK (0) +#define SSL_TLSEXT_ERR_ALERT_WARNING (1) +#define SSL_TLSEXT_ERR_ALERT_FATAL (2) +#define SSL_TLSEXT_ERR_NOACK (3) + +#define SSL_SESS_CACHE_BOTH (3) + +enum ssl_func_category { + TLS_Mandatory, /* required for HTTPS */ + TLS_ALPN, /* required for Application Layer Protocol Negotiation */ + TLS_END_OF_LIST +}; + +/* Check if all TLS functions/features are available */ +static int tls_feature_missing[TLS_END_OF_LIST] = {0}; + +struct ssl_func { + const char *name; /* SSL function name */ + enum ssl_func_category required; /* Mandatory or optional */ + void (*ptr)(void); /* Function pointer */ +}; + + +#if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ + && !defined(NO_SSL_DL) + +#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) +#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) +#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) +#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) +#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) +#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) +#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) +#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) +#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) +#define TLS_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) +#define OPENSSL_init_ssl \ + (*(int (*)(uint64_t opts, \ + const OPENSSL_INIT_SETTINGS *settings))ssl_sw[10] \ + .ptr) +#define SSL_CTX_use_PrivateKey_file \ + (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) +#define SSL_CTX_use_certificate_file \ + (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) +#define SSL_CTX_set_default_passwd_cb \ + (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) +#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) +#define SSL_CTX_use_certificate_chain_file \ + (*(int (*)(SSL_CTX *, const char *))ssl_sw[15].ptr) +#define TLS_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[16].ptr) +#define SSL_pending (*(int (*)(SSL *))ssl_sw[17].ptr) +#define SSL_CTX_set_verify \ + (*(void (*)(SSL_CTX *, \ + int, \ + int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[18] \ + .ptr) +#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[19].ptr) +#define SSL_CTX_load_verify_locations \ + (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[20].ptr) +#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[21].ptr) +#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[22].ptr) +#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[23].ptr) +#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[24].ptr) +#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[25].ptr) +#define SSL_CIPHER_get_name \ + (*(const char *(*)(const SSL_CIPHER *))ssl_sw[26].ptr) +#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[27].ptr) +#define SSL_CTX_set_session_id_context \ + (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[28].ptr) +#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[29].ptr) +#define SSL_CTX_set_cipher_list \ + (*(int (*)(SSL_CTX *, const char *))ssl_sw[30].ptr) +#define SSL_CTX_set_options \ + (*(unsigned long (*)(SSL_CTX *, unsigned long))ssl_sw[31].ptr) +#define SSL_CTX_set_info_callback \ + (*(void (*)(SSL_CTX * ctx, void (*callback)(const SSL *, int, int))) \ + ssl_sw[32] \ + .ptr) +#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) +#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) +#define SSL_CTX_callback_ctrl \ + (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) +#define SSL_get_servername \ + (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) +#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) +#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) +#define SSL_CTX_set_alpn_protos \ + (*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr) +typedef int (*tSSL_alpn_select_cb)(SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +#define SSL_CTX_set_alpn_select_cb \ + (*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr) +typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg); +#define SSL_CTX_set_next_protos_advertised_cb \ + (*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \ + .ptr) + +#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr) + +#define SSL_CTX_clear_options(ctx, op) \ + SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) +#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) + +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ + SSL_CTX_callback_ctrl(ctx, \ + SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \ + (void (*)(void))cb) +#define SSL_set_tlsext_host_name(ctx, arg) \ + SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) + +#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) +#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) + +#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) +#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) + +#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL) +#define SSL_CTX_set_session_cache_mode(ctx, mode) \ + SSL_CTX_ctrl(ctx, 44, mode, NULL) + + +#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[0].ptr) +#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[1].ptr) +#define CONF_modules_unload (*(void (*)(int))crypto_sw[2].ptr) +#define X509_free (*(void (*)(X509 *))crypto_sw[3].ptr) +#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[4].ptr) +#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[5].ptr) +#define X509_NAME_oneline \ + (*(char *(*)(X509_NAME *, char *, int))crypto_sw[6].ptr) +#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[7].ptr) +#define EVP_get_digestbyname \ + (*(const EVP_MD *(*)(const char *))crypto_sw[8].ptr) +#define EVP_Digest \ + (*(int (*)( \ + const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ + crypto_sw[9] \ + .ptr) +#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[10].ptr) +#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[11].ptr) +#define ASN1_INTEGER_to_BN \ + (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[12].ptr) +#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[13].ptr) +#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[14].ptr) +#define ERR_clear_error (*(void (*)(void))crypto_sw[15].ptr) + +#define OPENSSL_free(a) CRYPTO_free(a) + +#define OPENSSL_REMOVE_THREAD_STATE() + +/* init_ssl_ctx() function updates this array. + * It loads SSL library dynamically and changes NULLs to the actual addresses + * of respective functions. The macros above (like SSL_connect()) are really + * just calling these functions indirectly via the pointer. */ +static struct ssl_func ssl_sw[] = { + {"SSL_free", TLS_Mandatory, NULL}, + {"SSL_accept", TLS_Mandatory, NULL}, + {"SSL_connect", TLS_Mandatory, NULL}, + {"SSL_read", TLS_Mandatory, NULL}, + {"SSL_write", TLS_Mandatory, NULL}, + {"SSL_get_error", TLS_Mandatory, NULL}, + {"SSL_set_fd", TLS_Mandatory, NULL}, + {"SSL_new", TLS_Mandatory, NULL}, + {"SSL_CTX_new", TLS_Mandatory, NULL}, + {"TLS_server_method", TLS_Mandatory, NULL}, + {"OPENSSL_init_ssl", TLS_Mandatory, NULL}, + {"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL}, + {"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL}, + {"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL}, + {"SSL_CTX_free", TLS_Mandatory, NULL}, + {"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL}, + {"TLS_client_method", TLS_Mandatory, NULL}, + {"SSL_pending", TLS_Mandatory, NULL}, + {"SSL_CTX_set_verify", TLS_Mandatory, NULL}, + {"SSL_shutdown", TLS_Mandatory, NULL}, + {"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL}, + {"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL}, + {"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL}, +#if defined(OPENSSL_API_3_0) + {"SSL_get1_peer_certificate", TLS_Mandatory, NULL}, +#else + {"SSL_get_peer_certificate", TLS_Mandatory, NULL}, +#endif + {"SSL_get_version", TLS_Mandatory, NULL}, + {"SSL_get_current_cipher", TLS_Mandatory, NULL}, + {"SSL_CIPHER_get_name", TLS_Mandatory, NULL}, + {"SSL_CTX_check_private_key", TLS_Mandatory, NULL}, + {"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL}, + {"SSL_CTX_ctrl", TLS_Mandatory, NULL}, + {"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL}, + {"SSL_CTX_set_options", TLS_Mandatory, NULL}, + {"SSL_CTX_set_info_callback", TLS_Mandatory, NULL}, + {"SSL_get_ex_data", TLS_Mandatory, NULL}, + {"SSL_set_ex_data", TLS_Mandatory, NULL}, + {"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL}, + {"SSL_get_servername", TLS_Mandatory, NULL}, + {"SSL_set_SSL_CTX", TLS_Mandatory, NULL}, + {"SSL_ctrl", TLS_Mandatory, NULL}, + {"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL}, + {"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL}, + {"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL}, + {"SSL_CTX_set_timeout", TLS_Mandatory, NULL}, + {NULL, TLS_END_OF_LIST, NULL}}; + + +/* Similar array as ssl_sw. These functions could be located in different + * lib. */ +static struct ssl_func crypto_sw[] = { + {"ERR_get_error", TLS_Mandatory, NULL}, + {"ERR_error_string", TLS_Mandatory, NULL}, + {"CONF_modules_unload", TLS_Mandatory, NULL}, + {"X509_free", TLS_Mandatory, NULL}, + {"X509_get_subject_name", TLS_Mandatory, NULL}, + {"X509_get_issuer_name", TLS_Mandatory, NULL}, + {"X509_NAME_oneline", TLS_Mandatory, NULL}, + {"X509_get_serialNumber", TLS_Mandatory, NULL}, + {"EVP_get_digestbyname", TLS_Mandatory, NULL}, + {"EVP_Digest", TLS_Mandatory, NULL}, + {"i2d_X509", TLS_Mandatory, NULL}, + {"BN_bn2hex", TLS_Mandatory, NULL}, + {"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL}, + {"BN_free", TLS_Mandatory, NULL}, + {"CRYPTO_free", TLS_Mandatory, NULL}, + {"ERR_clear_error", TLS_Mandatory, NULL}, + {NULL, TLS_END_OF_LIST, NULL}}; +#endif + + +#if defined(OPENSSL_API_1_0) + +#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr) +#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr) +#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr) +#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr) +#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr) +#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr) +#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr) +#define SSL_new (*(SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr) +#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr) +#define SSLv23_server_method (*(SSL_METHOD * (*)(void)) ssl_sw[9].ptr) +#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr) +#define SSL_CTX_use_PrivateKey_file \ + (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr) +#define SSL_CTX_use_certificate_file \ + (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr) +#define SSL_CTX_set_default_passwd_cb \ + (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr) +#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr) +#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr) +#define SSL_CTX_use_certificate_chain_file \ + (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr) +#define SSLv23_client_method (*(SSL_METHOD * (*)(void)) ssl_sw[17].ptr) +#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr) +#define SSL_CTX_set_verify \ + (*(void (*)(SSL_CTX *, \ + int, \ + int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19] \ + .ptr) +#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr) +#define SSL_CTX_load_verify_locations \ + (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr) +#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr) +#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr) +#define SSL_get_peer_certificate (*(X509 * (*)(SSL *)) ssl_sw[24].ptr) +#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr) +#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *)) ssl_sw[26].ptr) +#define SSL_CIPHER_get_name \ + (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr) +#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr) +#define SSL_CTX_set_session_id_context \ + (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr) +#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr) +#define SSL_CTX_set_cipher_list \ + (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr) +#define SSL_CTX_set_info_callback \ + (*(void (*)(SSL_CTX *, void (*callback)(const SSL *, int, int)))ssl_sw[32] \ + .ptr) +#define SSL_get_ex_data (*(char *(*)(const SSL *, int))ssl_sw[33].ptr) +#define SSL_set_ex_data (*(void (*)(SSL *, int, char *))ssl_sw[34].ptr) +#define SSL_CTX_callback_ctrl \ + (*(long (*)(SSL_CTX *, int, void (*)(void)))ssl_sw[35].ptr) +#define SSL_get_servername \ + (*(const char *(*)(const SSL *, int type))ssl_sw[36].ptr) +#define SSL_set_SSL_CTX (*(SSL_CTX * (*)(SSL *, SSL_CTX *)) ssl_sw[37].ptr) +#define SSL_ctrl (*(long (*)(SSL *, int, long, void *))ssl_sw[38].ptr) +#define SSL_CTX_set_alpn_protos \ + (*(int (*)(SSL_CTX *, const unsigned char *, unsigned))ssl_sw[39].ptr) +typedef int (*tSSL_alpn_select_cb)(SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg); +#define SSL_CTX_set_alpn_select_cb \ + (*(void (*)(SSL_CTX *, tSSL_alpn_select_cb, void *))ssl_sw[40].ptr) +typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg); +#define SSL_CTX_set_next_protos_advertised_cb \ + (*(void (*)(SSL_CTX *, tSSL_next_protos_advertised_cb, void *))ssl_sw[41] \ + .ptr) + +#define SSL_CTX_set_timeout (*(long (*)(SSL_CTX *, long))ssl_sw[42].ptr) + + +#define SSL_CTX_set_options(ctx, op) \ + SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL) +#define SSL_CTX_clear_options(ctx, op) \ + SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL) +#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL) + +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ + SSL_CTX_callback_ctrl(ctx, \ + SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \ + (void (*)(void))cb) +#define SSL_set_tlsext_host_name(ctx, arg) \ + SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg) + +#define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) +#define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) + +#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg)) +#define SSL_get_app_data(s) (SSL_get_ex_data(s, 0)) + +#define SSL_CTX_sess_set_cache_size(ctx, size) SSL_CTX_ctrl(ctx, 42, size, NULL) +#define SSL_CTX_set_session_cache_mode(ctx, mode) \ + SSL_CTX_ctrl(ctx, 44, mode, NULL) + + +#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr) +#define CRYPTO_set_locking_callback \ + (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr) +#define CRYPTO_set_id_callback \ + (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr) +#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr) +#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr) +#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr) +#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr) +#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr) +#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr) +#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr) +#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr) +#define X509_free (*(void (*)(X509 *))crypto_sw[11].ptr) +#define X509_get_subject_name (*(X509_NAME * (*)(X509 *)) crypto_sw[12].ptr) +#define X509_get_issuer_name (*(X509_NAME * (*)(X509 *)) crypto_sw[13].ptr) +#define X509_NAME_oneline \ + (*(char *(*)(X509_NAME *, char *, int))crypto_sw[14].ptr) +#define X509_get_serialNumber (*(ASN1_INTEGER * (*)(X509 *)) crypto_sw[15].ptr) +#define i2c_ASN1_INTEGER \ + (*(int (*)(ASN1_INTEGER *, unsigned char **))crypto_sw[16].ptr) +#define EVP_get_digestbyname \ + (*(const EVP_MD *(*)(const char *))crypto_sw[17].ptr) +#define EVP_Digest \ + (*(int (*)( \ + const void *, size_t, void *, unsigned int *, const EVP_MD *, void *)) \ + crypto_sw[18] \ + .ptr) +#define i2d_X509 (*(int (*)(X509 *, unsigned char **))crypto_sw[19].ptr) +#define BN_bn2hex (*(char *(*)(const BIGNUM *a))crypto_sw[20].ptr) +#define ASN1_INTEGER_to_BN \ + (*(BIGNUM * (*)(const ASN1_INTEGER *ai, BIGNUM *bn)) crypto_sw[21].ptr) +#define BN_free (*(void (*)(const BIGNUM *a))crypto_sw[22].ptr) +#define CRYPTO_free (*(void (*)(void *addr))crypto_sw[23].ptr) +#define ERR_clear_error (*(void (*)(void))crypto_sw[24].ptr) + +#define OPENSSL_free(a) CRYPTO_free(a) + +/* use here ERR_remove_state, + * while on some platforms function is not included into library due to + * deprication */ +#define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_state(0) + +/* init_ssl_ctx() function updates this array. + * It loads SSL library dynamically and changes NULLs to the actual addresses + * of respective functions. The macros above (like SSL_connect()) are really + * just calling these functions indirectly via the pointer. */ +static struct ssl_func ssl_sw[] = { + {"SSL_free", TLS_Mandatory, NULL}, + {"SSL_accept", TLS_Mandatory, NULL}, + {"SSL_connect", TLS_Mandatory, NULL}, + {"SSL_read", TLS_Mandatory, NULL}, + {"SSL_write", TLS_Mandatory, NULL}, + {"SSL_get_error", TLS_Mandatory, NULL}, + {"SSL_set_fd", TLS_Mandatory, NULL}, + {"SSL_new", TLS_Mandatory, NULL}, + {"SSL_CTX_new", TLS_Mandatory, NULL}, + {"SSLv23_server_method", TLS_Mandatory, NULL}, + {"SSL_library_init", TLS_Mandatory, NULL}, + {"SSL_CTX_use_PrivateKey_file", TLS_Mandatory, NULL}, + {"SSL_CTX_use_certificate_file", TLS_Mandatory, NULL}, + {"SSL_CTX_set_default_passwd_cb", TLS_Mandatory, NULL}, + {"SSL_CTX_free", TLS_Mandatory, NULL}, + {"SSL_load_error_strings", TLS_Mandatory, NULL}, + {"SSL_CTX_use_certificate_chain_file", TLS_Mandatory, NULL}, + {"SSLv23_client_method", TLS_Mandatory, NULL}, + {"SSL_pending", TLS_Mandatory, NULL}, + {"SSL_CTX_set_verify", TLS_Mandatory, NULL}, + {"SSL_shutdown", TLS_Mandatory, NULL}, + {"SSL_CTX_load_verify_locations", TLS_Mandatory, NULL}, + {"SSL_CTX_set_default_verify_paths", TLS_Mandatory, NULL}, + {"SSL_CTX_set_verify_depth", TLS_Mandatory, NULL}, + {"SSL_get_peer_certificate", TLS_Mandatory, NULL}, + {"SSL_get_version", TLS_Mandatory, NULL}, + {"SSL_get_current_cipher", TLS_Mandatory, NULL}, + {"SSL_CIPHER_get_name", TLS_Mandatory, NULL}, + {"SSL_CTX_check_private_key", TLS_Mandatory, NULL}, + {"SSL_CTX_set_session_id_context", TLS_Mandatory, NULL}, + {"SSL_CTX_ctrl", TLS_Mandatory, NULL}, + {"SSL_CTX_set_cipher_list", TLS_Mandatory, NULL}, + {"SSL_CTX_set_info_callback", TLS_Mandatory, NULL}, + {"SSL_get_ex_data", TLS_Mandatory, NULL}, + {"SSL_set_ex_data", TLS_Mandatory, NULL}, + {"SSL_CTX_callback_ctrl", TLS_Mandatory, NULL}, + {"SSL_get_servername", TLS_Mandatory, NULL}, + {"SSL_set_SSL_CTX", TLS_Mandatory, NULL}, + {"SSL_ctrl", TLS_Mandatory, NULL}, + {"SSL_CTX_set_alpn_protos", TLS_ALPN, NULL}, + {"SSL_CTX_set_alpn_select_cb", TLS_ALPN, NULL}, + {"SSL_CTX_set_next_protos_advertised_cb", TLS_ALPN, NULL}, + {"SSL_CTX_set_timeout", TLS_Mandatory, NULL}, + {NULL, TLS_END_OF_LIST, NULL}}; + + +/* Similar array as ssl_sw. These functions could be located in different + * lib. */ +static struct ssl_func crypto_sw[] = { + {"CRYPTO_num_locks", TLS_Mandatory, NULL}, + {"CRYPTO_set_locking_callback", TLS_Mandatory, NULL}, + {"CRYPTO_set_id_callback", TLS_Mandatory, NULL}, + {"ERR_get_error", TLS_Mandatory, NULL}, + {"ERR_error_string", TLS_Mandatory, NULL}, + {"ERR_remove_state", TLS_Mandatory, NULL}, + {"ERR_free_strings", TLS_Mandatory, NULL}, + {"ENGINE_cleanup", TLS_Mandatory, NULL}, + {"CONF_modules_unload", TLS_Mandatory, NULL}, + {"CRYPTO_cleanup_all_ex_data", TLS_Mandatory, NULL}, + {"EVP_cleanup", TLS_Mandatory, NULL}, + {"X509_free", TLS_Mandatory, NULL}, + {"X509_get_subject_name", TLS_Mandatory, NULL}, + {"X509_get_issuer_name", TLS_Mandatory, NULL}, + {"X509_NAME_oneline", TLS_Mandatory, NULL}, + {"X509_get_serialNumber", TLS_Mandatory, NULL}, + {"i2c_ASN1_INTEGER", TLS_Mandatory, NULL}, + {"EVP_get_digestbyname", TLS_Mandatory, NULL}, + {"EVP_Digest", TLS_Mandatory, NULL}, + {"i2d_X509", TLS_Mandatory, NULL}, + {"BN_bn2hex", TLS_Mandatory, NULL}, + {"ASN1_INTEGER_to_BN", TLS_Mandatory, NULL}, + {"BN_free", TLS_Mandatory, NULL}, + {"CRYPTO_free", TLS_Mandatory, NULL}, + {"ERR_clear_error", TLS_Mandatory, NULL}, + {NULL, TLS_END_OF_LIST, NULL}}; +#endif /* OPENSSL_API_1_0 */ diff -Nru civetweb-1.13+dfsg/src/response.inl civetweb-1.15+dfsg/src/response.inl --- civetweb-1.13+dfsg/src/response.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/response.inl 2021-09-01 08:46:33.000000000 +0000 @@ -8,7 +8,7 @@ */ #if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2) -#error "HTTP2 currently works only if NO_RESPONSE_BUFFERING is not set" +#error "HTTP2 works only if NO_RESPONSE_BUFFERING is not set" #endif @@ -40,13 +40,22 @@ static void send_http1_response_status_line(struct mg_connection *conn) { + const char *status_txt; + const char *http_version = conn->request_info.http_version; + int status_code = conn->status_code; + + if ((status_code < 100) || (status_code > 999)) { + /* Set invalid status code to "500 Internal Server Error" */ + status_code = 500; + } + if (!http_version) { + http_version = "1.0"; + } + /* mg_get_response_code_text will never return NULL */ - const char *txt = mg_get_response_code_text(conn, conn->status_code); - mg_printf(conn, - "HTTP/%s %i %s\r\n", - conn->request_info.http_version, - conn->status_code, - txt); + status_txt = mg_get_response_code_text(conn, conn->status_code); + + mg_printf(conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt); } @@ -142,7 +151,8 @@ conn->response_info.http_headers[hidx].name = mg_strdup_ctx(header, conn->phys_ctx); if (value_len >= 0) { - char *hbuf = mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx); + char *hbuf = + (char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx); if (hbuf) { memcpy(hbuf, value, (unsigned)value_len); hbuf[value_len] = 0; @@ -231,7 +241,7 @@ } -#if defined USE_HTTP2 +#if defined(USE_HTTP2) static int http2_send_response_headers(struct mg_connection *conn); #endif @@ -272,14 +282,12 @@ conn->request_state = 2; #if !defined(NO_RESPONSE_BUFFERING) +#if defined(USE_HTTP2) if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) { -#if defined USE_HTTP2 int ret = http2_send_response_headers(conn); return ret ? 0 : 0; /* todo */ -#else - return -2; -#endif } +#endif /* Send */ send_http1_response_status_line(conn); diff -Nru civetweb-1.13+dfsg/src/timer.inl civetweb-1.15+dfsg/src/timer.inl --- civetweb-1.13+dfsg/src/timer.inl 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/src/timer.inl 2021-09-01 08:46:33.000000000 +0000 @@ -1,6 +1,6 @@ /* This file is part of the CivetWeb web server. * See https://github.com/civetweb/civetweb/ - * (C) 2014-2020 by the CivetWeb authors, MIT license. + * (C) 2014-2021 by the CivetWeb authors, MIT license. */ #if !defined(MAX_TIMERS) diff -Nru "/tmp/tmp1p6obe5f/HuhoIs93Hc/civetweb-1.13+dfsg/test/dir with spaces/r&d.txt" "/tmp/tmp1p6obe5f/VnSAxQw8ZZ/civetweb-1.15+dfsg/test/dir with spaces/r&d.txt" --- "/tmp/tmp1p6obe5f/HuhoIs93Hc/civetweb-1.13+dfsg/test/dir with spaces/r&d.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmp1p6obe5f/VnSAxQw8ZZ/civetweb-1.15+dfsg/test/dir with spaces/r&d.txt" 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1 @@ +Name with & (fine for Windows, bad for Linux) diff -Nru civetweb-1.13+dfsg/test/lua_backbround_script_logging.lua civetweb-1.15+dfsg/test/lua_backbround_script_logging.lua --- civetweb-1.13+dfsg/test/lua_backbround_script_logging.lua 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/test/lua_backbround_script_logging.lua 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,52 @@ + +function start() + -- The "start" function is called when the server is ready. + logfile = io.open("C:\\tmp\\lualog.txt", "w"); + if (logfile) then + logfile:write("Server start: " .. os.date('%Y-%m-%dT%H:%M:%S') .. "\n\n"); + end +end + + +function stop() + -- The "stop" function is called when the server is stopping. + logfile:close(); +end + + +function log(req, resp) + -- The "log" function can be used to + -- (a) filter messages and return boolean: true (log) or false (do not log) + -- (b) format log message and return it as string (empty string will not log) + -- (c) forward the log data to an external log + + if logfile then + logfile:write(os.date('%Y-%m-%dT%H:%M:%S').."\n"); + logfile:write("request:\n"); + for k,v in pairs(req) do + logfile:write(" " .. tostring(k) .. " = " .. tostring(v) .. "\n"); + if type(v) == "table" then + for k2,v2 in pairs(v) do + logfile:write(" " .. tostring(k2) .. " = " .. tostring(v2) .. "\n"); + end + end + end + logfile:write("response:\n"); + for k,v in pairs(resp) do + logfile:write(" " .. tostring(k) .. " = " .. tostring(v) .. "\n"); + if type(v) == "table" then + for k2,v2 in pairs(v) do + logfile:write(" " .. tostring(k2) .. " = " .. tostring(v2) .. "\n"); + end + end + end + logfile:write("----\n\n"); + logfile:flush(); + end + + -- Loging already done here + return false; +end + +-- Return true to continue server startup. +return true; diff -Nru civetweb-1.13+dfsg/test/lua_backbround_script_timer.lua civetweb-1.15+dfsg/test/lua_backbround_script_timer.lua --- civetweb-1.13+dfsg/test/lua_backbround_script_timer.lua 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/test/lua_backbround_script_timer.lua 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,36 @@ +-- Declare a shared "timer" counter and functions "timer" +-- and "start" when the script is loading. +shared.timer = 0 + + +function timer() + -- Increment shared value. + shared.timer = shared.timer + 1 + -- Return true to keep interval timer running or false to stop. + return true +end + + +function start() + -- The "start" function is called when the server is ready. + -- At this point, a timer can be created. + mg.set_interval(timer, 5) +end + + +function stop() + -- The "stop" function is called when the server is stopping. +end + +function log(ri) + -- The "log" function can be used to + -- (a) filter messages and return boolean: true (log) or false (do not log) + -- (b) format log message and return it as string (empty string will not log) + -- (c) forward the log data to an external log + + -- Example: Log only if the request was not made from localhost + return (ri.remote_addr ~= "127.0.0.1"); +end + +-- Return false to abort server startup. +return true; diff -Nru civetweb-1.13+dfsg/test/page2.lua civetweb-1.15+dfsg/test/page2.lua --- civetweb-1.13+dfsg/test/page2.lua 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/test/page2.lua 2021-09-01 08:46:33.000000000 +0000 @@ -184,7 +184,7 @@ mg.write(htmlEsc(xmlstr)) mg.write("\n-->\n") mg.write(type(xmlev) .. ":\n") -mg.write(printTable(xmlev, 1)) +mg.write(printTable(xmlev, 1)) mg.write("\n

\n") mg.write("

lua2xml:
\n

\n");
@@ -237,7 +237,7 @@
 mg.write(htmlEsc(jsonstr))
 mg.write("\n-->\n")
 mg.write(type(jsonev) .. ":\n")
-mg.write(printTable(jsonev, 1)) 
+mg.write(printTable(jsonev, 1))
 mg.write("
\n

\n") mg.write("

lua2json:
\n

\n");
@@ -270,11 +270,21 @@
 end
 
 
--- Next section ...
+-- Test timer from Lua background script
 mg.write("\n
\n") +mg.write("

\nLua shared.timer "); +if (shared and shared.timer) then + mg.write(tostring(shared.timer)) + mg.write([[ ]]) +else + mg.write("not available") +end +mg.write("\n

\n") + +-- Next section ... +mg.write("\n
\n") mg.write([[ ]]) - diff -Nru civetweb-1.13+dfsg/test/page7.lua civetweb-1.15+dfsg/test/page7.lua --- civetweb-1.13+dfsg/test/page7.lua 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/test/page7.lua 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,10 @@ +-- reflect the request information as JSON +json = require "json" + +response = json.encode(mg.request_info) + +mg.response.status = 200 +mg.response.http_headers["Content-Type"] = "application/json; charset=utf-8"; +mg.response.http_headers["Content-Length"] = #response; +mg.response.send() +mg.write(response) diff -Nru civetweb-1.13+dfsg/.travis.yml civetweb-1.15+dfsg/.travis.yml --- civetweb-1.13+dfsg/.travis.yml 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/.travis.yml 2021-09-01 08:46:33.000000000 +0000 @@ -9,7 +9,7 @@ directories: - $HOME/third-party -osx_image: xcode8 +osx_image: xcode9 addons: apt: @@ -37,6 +37,8 @@ PATH=~/.local/bin:${PATH}; pip install --user --upgrade pip; pip install --user cpp-coveralls; + pip install --user codecov; + pip install --user coverage; fi before_script: @@ -128,13 +130,14 @@ - if [ "${MACOSX_PACKAGE}" == "1" ]; then cd "${TRAVIS_BUILD_DIR}"; make -f Makefile.osx package; - else + fi + - if [ "${RUN_UNITTEST}" == "1" ]; then CTEST_OUTPUT_ON_FAILURE=1 make all test; fi - pwd - ls -la unittest - echo "Show all test logs:" - - if [ "${MACOSX_PACKAGE}" != "1" ]; then + - if [ "${RUN_UNITTEST}" == "1" ]; then for f in unittest/test-*.log; do printf "\n$f:\n"; cat $f; done; for f in unittest/test-*.xml; do printf "\n$f:\n"; cat $f; done; fi @@ -143,8 +146,12 @@ # Coveralls options: https://github.com/eddyxu/cpp-coveralls/blob/master/README.md after_success: - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + echo "Preparing coverage tests"; + echo "Creating coveralls coverage report"; coveralls --include src --exclude src/main.c --exclude src/third_party --include include --gcov-options '\-lp' --root .. --build-root .; + echo "Creating codecov coverage report"; bash <(curl -s https://codecov.io/bash); + echo "All coverage reports created"; fi conan-linux: &conan-linux @@ -182,15 +189,21 @@ - true -############################################################################## -# build matrix -############################################################################## - +######################################################################################### +######################################################################################### +##### START OF BUILD MATRIX ######################################################### +######################################################################################### +######################################################################################### matrix: - fast_finish: false + fast_finish: true include: + +######################################################################################### +##### TRUSTY ######################################################################## +######################################################################################### + - dist: trusty sudo: false os: linux @@ -238,42 +251,6 @@ packages: - clang-3.8 env: - idx=2 - N=Clang3.8-Linux-Default-Release - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=NO - ENABLE_WEBSOCKETS=NO - ENABLE_SERVER_STATS=NO - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=NO - NO_CACHING=NO - ALLOW_WARNINGS=YES - - - dist: trusty - sudo: false - os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.8 - packages: - - clang-3.8 - env: idx=3 N=Clang3.8-Linux-Default-Release MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" @@ -300,42 +277,6 @@ - dist: trusty sudo: required os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-precise-3.8 - packages: - - clang-3.8 - env: - idx=4 - N=Clang3.8-Linux-Complete-NoLua-Release - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=YES - ALLOW_WARNINGS=YES - - - - dist: trusty - sudo: required - os: linux compiler: gcc addons: apt: @@ -366,10 +307,16 @@ ENABLE_DUKTAPE=NO NO_CACHING=YES ALLOW_WARNINGS=YES + RUN_UNITTEST=1 + + +######################################################################################### +##### COVERAGE ###################################################################### +######################################################################################### - os: linux sudo: required - compiler: gcc + compiler: clang env: idx=6 N=GCCAnyVersion-Linux-Coverage @@ -392,84 +339,22 @@ ENABLE_DUKTAPE=NO NO_CACHING=NO ALLOW_WARNINGS=YES + RUN_UNITTEST=1 - - os: osx - sudo: required - compiler: clang - env: - idx=7 - N=Clang-OSX-Complete-NoLua-Release - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=YES - ALLOW_WARNINGS=YES +######################################################################################### +##### SHARED ######################################################################## +######################################################################################### - - - os: osx - sudo: required - compiler: clang - env: - idx=8 - N=Clang-OSX-Complete-NoLua-Release-OpenSSL_1_1_NoDynLoad - BUILD_TYPE=OSX_OPENSSL_1_1 - ENABLE_SSL_DYNAMIC_LOADING=NO - OPENSSL_1_0=NO - OPENSSL_1_1=YES - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=YES - ALLOW_WARNINGS=YES - OPENSSL_ROOT_DIR="/usr/local/opt/openssl@1.1" - LDFLAGS="-L${OPENSSL_ROOT_DIR}/lib" - CFLAGS="-I${OPENSSL_ROOT_DIR}/include" - ADDITIONAL_CMAKE_ARGS="-DCMAKE_SHARED_LINKER_FLAGS=${LDFLAGS} -DCMAKE_C_FLAGS=${CFLAGS}" - PATH="${OPENSSL_ROOT_DIR}/bin:$PATH" - DYLD_LIBRARY_PATH="${OPENSSL_ROOT_DIR}/lib:${DYLD_LIBRARY_PATH}" - - - dist: trusty - sudo: false + - sudo: false os: linux compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - packages: - - clang-5.0 env: idx=9 - N=Clang50-Linux-Default-Shared + N=Clang-Linux-Default-Shared BUILD_TYPE=Debug ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO + OPENSSL_1_0=NO + OPENSSL_1_1=YES ENABLE_CXX=NO ENABLE_LUA_SHARED=NO C_STANDARD=auto @@ -485,159 +370,17 @@ ENABLE_DUKTAPE=NO NO_CACHING=NO ALLOW_WARNINGS=YES - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0" - - - os: linux - dist: precise - sudo: required - compiler: clang - env: - idx=10 - N=Precise-Clang-Linux-Default - BUILD_TYPE=Debug - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=NO - ENABLE_WEBSOCKETS=NO - ENABLE_SERVER_STATS=NO - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=NO - ALLOW_WARNINGS=YES - - - os: osx - sudo: required - compiler: clang - env: - idx=11 - N=OSX-Package - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=NO - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=NO - ALLOW_WARNINGS=YES - MACOSX_PACKAGE=1 +######################################################################################### +##### BUILD TYPES ################################################################### +######################################################################################### - - dist: trusty - sudo: required - os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.8 - packages: - - clang-3.8 - env: - idx=12 - N=Clang-Linux-32bit-Complete-NoLua-Release - ARCH=x86 - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=YES - ALLOW_WARNINGS=YES - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - - -### Test all build types: # According to CMakeLists, options are: # None Debug Release RelWithDebInfo MinSizeRel Coverage - os: linux - sudo: required - compiler: clang - env: - idx=13 - N=NoSslDynamicLoading - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=NO - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - C_STANDARD=auto - CXX_STANDARD=auto - ENABLE_LUA_SHARED=NO - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=NO - ALLOW_WARNINGS=YES - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - - - - os: linux - compiler: gcc - env: - idx=14 - N=GCCLinuxDefault_Debug - BUILD_TYPE=Debug - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=NO - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=NO - ENABLE_WEBSOCKETS=NO - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=NO - ALLOW_WARNINGS=YES - - - - os: linux compiler: gcc env: idx=15 @@ -711,63 +454,31 @@ NO_CACHING=NO ALLOW_WARNINGS=YES - - - os: linux - compiler: clang - env: - idx=18 - N=Clang3.8-Linux-Complete-NoLua-Debug - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" - BUILD_TYPE=Debug - ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO - ENABLE_CXX=NO - ENABLE_LUA_SHARED=YES - C_STANDARD=auto - CXX_STANDARD=auto - BUILD_SHARED=NO - NO_FILES=NO - ENABLE_SSL=YES - NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES - ENABLE_LUA=NO - ENABLE_DUKTAPE=NO - NO_CACHING=YES - ALLOW_WARNINGS=YES +######################################################################################### +##### XENIAL, BIONIC, FOCAL ######################################################### +######################################################################################### - - dist: trusty - sudo: false + - os: linux - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-5.0 - packages: - - clang-5.0 + compiler: gcc + dist: xenial env: - idx=19 - N=Clang5.0-Linux-Complete-CXX-NoLua-Release - MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0" + idx=20 + N=GCCLinuxDefault_xenial BUILD_TYPE=Release ENABLE_SSL_DYNAMIC_LOADING=YES OPENSSL_1_0=YES OPENSSL_1_1=NO - ENABLE_CXX=YES - ENABLE_LUA_SHARED=YES + ENABLE_CXX=NO + ENABLE_LUA_SHARED=NO C_STANDARD=auto CXX_STANDARD=auto BUILD_SHARED=NO NO_FILES=NO ENABLE_SSL=YES NO_CGI=NO - ENABLE_IPV6=YES - ENABLE_WEBSOCKETS=YES - ENABLE_SERVER_STATS=YES + ENABLE_IPV6=NO + ENABLE_WEBSOCKETS=NO ENABLE_LUA=NO ENABLE_DUKTAPE=NO NO_CACHING=NO @@ -776,14 +487,14 @@ - os: linux compiler: gcc - dist: xenial + dist: bionic env: - idx=20 - N=GCCLinuxDefault_xenial + idx=21 + N=GCCLinuxDefault_bionic BUILD_TYPE=Release ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=YES - OPENSSL_1_1=NO + OPENSSL_1_0=NO + OPENSSL_1_1=YES ENABLE_CXX=NO ENABLE_LUA_SHARED=NO C_STANDARD=auto @@ -802,10 +513,14 @@ - os: linux compiler: gcc - dist: bionic + dist: focal + addons: + apt: + packages: + - lsb-core env: - idx=21 - N=GCCLinuxDefault_bionic + idx=23 + N=GCCLinuxDefault_focal BUILD_TYPE=Release ENABLE_SSL_DYNAMIC_LOADING=YES OPENSSL_1_0=NO @@ -824,16 +539,22 @@ ENABLE_DUKTAPE=NO NO_CACHING=NO ALLOW_WARNINGS=YES + RUN_UNITTEST=1 + + +######################################################################################### +##### OSX BUILD ##################################################################### +######################################################################################### - - os: linux - compiler: gcc - dist: eoan + os: osx + sudo: required + compiler: clang env: - idx=22 - N=GCCLinuxDefault_eoan - BUILD_TYPE=Release - ENABLE_SSL_DYNAMIC_LOADING=YES + idx=8 + N=Clang-OSX-Complete-NoLua-Release-OpenSSL_1_1_NoDynLoad + BUILD_TYPE=OSX_OPENSSL_1_1 + ENABLE_SSL_DYNAMIC_LOADING=NO OPENSSL_1_0=NO OPENSSL_1_1=YES ENABLE_CXX=NO @@ -844,28 +565,32 @@ NO_FILES=NO ENABLE_SSL=YES NO_CGI=NO - ENABLE_IPV6=NO - ENABLE_WEBSOCKETS=NO + ENABLE_IPV6=YES + ENABLE_WEBSOCKETS=YES + ENABLE_SERVER_STATS=YES ENABLE_LUA=NO ENABLE_DUKTAPE=NO - NO_CACHING=NO + NO_CACHING=YES ALLOW_WARNINGS=YES + OPENSSL_ROOT_DIR="/usr/local/opt/openssl@1.1" + LDFLAGS="-L${OPENSSL_ROOT_DIR}/lib" + CFLAGS="-I${OPENSSL_ROOT_DIR}/include" + ADDITIONAL_CMAKE_ARGS="-DCMAKE_SHARED_LINKER_FLAGS=${LDFLAGS} -DCMAKE_C_FLAGS=${CFLAGS}" + PATH="${OPENSSL_ROOT_DIR}/bin:$PATH" + DYLD_LIBRARY_PATH="${OPENSSL_ROOT_DIR}/lib:${DYLD_LIBRARY_PATH}" + RUN_UNITTEST=1 - - os: linux - compiler: gcc - dist: focal - addons: - apt: - packages: - - lsb-core + os: osx + sudo: required + compiler: clang env: - idx=23 - N=GCCLinuxDefault_focal + idx=11 + N=OSX-Package BUILD_TYPE=Release ENABLE_SSL_DYNAMIC_LOADING=YES - OPENSSL_1_0=NO - OPENSSL_1_1=YES + OPENSSL_1_0=YES + OPENSSL_1_1=NO ENABLE_CXX=NO ENABLE_LUA_SHARED=NO C_STANDARD=auto @@ -874,12 +599,20 @@ NO_FILES=NO ENABLE_SSL=YES NO_CGI=NO - ENABLE_IPV6=NO - ENABLE_WEBSOCKETS=NO + ENABLE_IPV6=YES + ENABLE_WEBSOCKETS=YES + ENABLE_SERVER_STATS=NO ENABLE_LUA=NO ENABLE_DUKTAPE=NO NO_CACHING=NO ALLOW_WARNINGS=YES + MACOSX_PACKAGE=1 + +######################################################################################### +######################################################################################### +##### END OF BUILD MATRIX ########################################################### +######################################################################################### +######################################################################################### - <<: *conan-linux env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49 CONAN_DOCKER_32_IMAGES=1 diff -Nru civetweb-1.13+dfsg/unittest/build_and_run.sh civetweb-1.15+dfsg/unittest/build_and_run.sh --- civetweb-1.13+dfsg/unittest/build_and_run.sh 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/build_and_run.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#!/bin/sh -rm -rf output -mkdir output -gcc unittest/cgi_test.c -o output/cgi_test.cgi -cd output -cmake .. -make all -make test -cd .. diff -Nru civetweb-1.13+dfsg/unittest/build_and_test_default.sh civetweb-1.15+dfsg/unittest/build_and_test_default.sh --- civetweb-1.13+dfsg/unittest/build_and_test_default.sh 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/build_and_test_default.sh 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,43 @@ +#!/bin/bash + + +if test -f "./unittest/build_and_test_default.sh" ; then + echo "Unit test (default settings) will run on a local Debian system." + rm -rf output +else + echo "This script must be started from the civetweb root directory using ./unittest/build_and_test_default.sh" + exit +fi + + +# Exit with an error message when any command fails. +set -e +trap 'lastline=$thisline; thisline=$BASH_COMMAND' DEBUG +trap 'echo "ERROR: \"${lastline}\" command failed (error $?)"' EXIT + + +# Create a test directory and add the CGI test executable +if test -f "./output/" ; then + echo "Removing old \"output\" folder." + rm -rf output +fi +mkdir output +gcc unittest/cgi_test.c -o output/cgi_test.cgi +cd output + + +# Perform build and test steps in "output" directory. +echo "Starting unit test. Write protocol to \"unittest.log\" file." +echo "Starting unit test" > unittest.log +git log -1 >> unittest.log +cmake .. &>> unittest.log +make all &>> unittest.log +make test &>> unittest.log +echo "Unit test completed. See \"unittest.log\" file." +tail -10 unittest.log | grep " tests passed" +cd .. + + +# Exit with success +trap '' EXIT +exit 0 diff -Nru civetweb-1.13+dfsg/unittest/build_and_test_full.sh civetweb-1.15+dfsg/unittest/build_and_test_full.sh --- civetweb-1.13+dfsg/unittest/build_and_test_full.sh 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/build_and_test_full.sh 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,43 @@ +#!/bin/bash + + +if test -f "./unittest/build_and_test_full.sh" ; then + echo "Unit test (full features) will run on a local Debian system." + rm -rf output +else + echo "This script must be started from the civetweb root directory using ./unittest/build_and_test_full.sh" + exit +fi + + +# Exit with an error message when any command fails. +set -e +trap 'lastline=$thisline; thisline=$BASH_COMMAND' DEBUG +trap 'echo "ERROR: \"${lastline}\" command failed (error $?)"' EXIT + + +# Create a test directory and add the CGI test executable +if test -f "./output/" ; then + echo "Removing old \"output\" folder." + rm -rf output +fi +mkdir output +gcc unittest/cgi_test.c -o output/cgi_test.cgi +cd output + + +# Perform build and test steps in "output" directory. +echo "Starting unit test. Write protocol to \"unittest.log\" file." +echo "Starting unit test" > unittest.log +git log -1 >> unittest.log +cmake -DCIVETWEB_ENABLE_SSL=YES -DCIVETWEB_DISABLE_CGI=NO -DCIVETWEB_ENABLE_WEBSOCKETS=YES -DCIVETWEB_ENABLE_SERVER_STATS=YES -DCIVETWEB_ENABLE_IPV6=YES .. &>> unittest.log +make all &>> unittest.log +make test &>> unittest.log +echo "Unit test completed. See \"unittest.log\" file." +tail -10 unittest.log | grep " tests passed" +cd .. + + +# Exit with success +trap '' EXIT +exit 0 diff -Nru civetweb-1.13+dfsg/unittest/build_and_test_minimal.sh civetweb-1.15+dfsg/unittest/build_and_test_minimal.sh --- civetweb-1.13+dfsg/unittest/build_and_test_minimal.sh 1970-01-01 00:00:00.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/build_and_test_minimal.sh 2021-09-01 08:46:33.000000000 +0000 @@ -0,0 +1,43 @@ +#!/bin/bash + + +if test -f "./unittest/build_and_test_minimal.sh" ; then + echo "Unit test (minimal features) will run on a local Debian system." + rm -rf output +else + echo "This script must be started from the civetweb root directory using ./unittest/build_and_test_minimal.sh" + exit +fi + + +# Exit with an error message when any command fails. +set -e +trap 'lastline=$thisline; thisline=$BASH_COMMAND' DEBUG +trap 'echo "ERROR: \"${lastline}\" command failed (error $?)"' EXIT + + +# Create a test directory and add the CGI test executable +if test -f "./output/" ; then + echo "Removing old \"output\" folder." + rm -rf output +fi +mkdir output +gcc unittest/cgi_test.c -o output/cgi_test.cgi +cd output + + +# Perform build and test steps in "output" directory. +echo "Starting unit test. Write protocol to \"unittest.log\" file." +echo "Starting unit test" > unittest.log +git log -1 >> unittest.log +cmake -DCIVETWEB_ENABLE_SSL=NO -DCIVETWEB_DISABLE_CGI=YES -DCIVETWEB_ENABLE_WEBSOCKETS=NO -DCIVETWEB_ENABLE_SERVER_STATS=NO -DCIVETWEB_ENABLE_IPV6=NO .. &>> unittest.log +make all &>> unittest.log +make test &>> unittest.log +echo "Unit test completed. See \"unittest.log\" file." +tail -10 unittest.log | grep " tests passed" +cd .. + + +# Exit with success +trap '' EXIT +exit 0 diff -Nru civetweb-1.13+dfsg/unittest/CMakeLists.txt civetweb-1.15+dfsg/unittest/CMakeLists.txt --- civetweb-1.13+dfsg/unittest/CMakeLists.txt 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/CMakeLists.txt 2021-09-01 08:46:33.000000000 +0000 @@ -168,6 +168,7 @@ civetweb_add_test(Private "Internal Parsing 4") civetweb_add_test(Private "Internal Parsing 5") civetweb_add_test(Private "Internal Parsing 6") +civetweb_add_test(Private "Internal Parsing 7") civetweb_add_test(Private "Encode Decode") civetweb_add_test(Private "Mask Data") civetweb_add_test(Private "Date Parsing") diff -Nru civetweb-1.13+dfsg/unittest/private.c civetweb-1.15+dfsg/unittest/private.c --- civetweb-1.13+dfsg/unittest/private.c 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/private.c 2021-09-01 08:46:33.000000000 +0000 @@ -698,15 +698,277 @@ vec.ptr = "localhost:123"; vec.len = strlen(vec.ptr); ret = parse_port_string(&vec, &so, &ip_family); - ck_assert_int_eq(ret, 1); + if (ret != 1) { + ck_abort_msg("IP of localhost seems to be unknown on this system (%i)", + (int)ret); + } if ((ip_family != 4) && (ip_family != 6)) { - ck_abort_msg("IP family must be 4 or 6 but is %i", (int)ip_family); + ck_abort_msg("IP family for localhost must be 4 or 6 but is %i", + (int)ip_family); } ck_assert_int_eq((int)htons(so.lsa.sin.sin_port), (int)123); } END_TEST +START_TEST(test_parse_http_headers) +{ + char buf[2048]; + char *ptr; + int ret; + struct mg_header hdr[MG_MAX_HEADERS]; + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 0); + ck_assert_ptr_eq(ptr, &buf[0]); + ck_assert_ptr_eq(hdr[0].name, NULL); + ck_assert_ptr_eq(hdr[0].value, NULL); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 0); + ck_assert_ptr_eq(ptr, &buf[0]); + ck_assert_ptr_eq(hdr[0].name, NULL); + ck_assert_ptr_eq(hdr[0].value, NULL); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, -1); + ck_assert_ptr_eq(ptr, &buf[0]); + ck_assert_ptr_eq(hdr[0].name, NULL); + ck_assert_ptr_eq(hdr[0].value, NULL); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a:b"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[3]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[2]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a:b\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[5]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[2]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a:b\r\n\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[5]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[2]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[6]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a :b\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[6]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a : b\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 1); + ck_assert_ptr_eq(ptr, &buf[7]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[4]); + ck_assert_ptr_eq(hdr[1].name, NULL); + ck_assert_ptr_eq(hdr[1].value, NULL); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 2); + ck_assert_ptr_eq(ptr, &buf[12]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d\r\n\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 2); + ck_assert_ptr_eq(ptr, &buf[12]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d\r\n\r\ne: f\r\n"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 2); + ck_assert_ptr_eq(ptr, &buf[12]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 2); + ck_assert_ptr_eq(ptr, &buf[10]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d\r\ne"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, -1); + /* The following could be undefined, since ret == -1 */ + ck_assert_ptr_eq(ptr, &buf[12]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, NULL); + ck_assert_ptr_eq(hdr[2].value, NULL); + + memset(hdr, 0, sizeof(hdr)); + memset(buf, 0, sizeof(buf)); + strcpy(buf, "a: b\r\nc: d\r\nefg:"); + ptr = &buf[0]; + ret = parse_http_headers(&ptr, hdr); + ck_assert_int_eq(ret, 3); + ck_assert_ptr_eq(ptr, &buf[16]); + ck_assert_str_eq(hdr[0].name, "a"); + ck_assert_str_eq(hdr[0].value, "b"); + ck_assert_str_eq(hdr[1].name, "c"); + ck_assert_str_eq(hdr[1].value, "d"); + ck_assert_str_eq(hdr[2].name, "efg"); + ck_assert_str_eq(hdr[2].value, ""); + ck_assert_ptr_eq(hdr[0].name, &buf[0]); + ck_assert_ptr_eq(hdr[0].value, &buf[3]); + ck_assert_ptr_eq(hdr[1].name, &buf[6]); + ck_assert_ptr_eq(hdr[1].value, &buf[9]); + ck_assert_ptr_eq(hdr[2].name, &buf[12]); + ck_assert_ptr_eq(hdr[2].value, &buf[16]); +} +END_TEST + + START_TEST(test_encode_decode) { char buf[128]; @@ -1082,6 +1344,8 @@ #endif ck_assert_str_eq("decode_url", config_options[DECODE_URL].name); + ck_assert_str_eq("decode_query_string", + config_options[DECODE_QUERY_STRING].name); #if defined(USE_LUA) ck_assert_str_eq("lua_preload_file", config_options[LUA_PRELOAD_FILE].name); @@ -1161,6 +1425,7 @@ TCase *const tcase_internal_parse_4 = tcase_create("Internal Parsing 4"); TCase *const tcase_internal_parse_5 = tcase_create("Internal Parsing 5"); TCase *const tcase_internal_parse_6 = tcase_create("Internal Parsing 6"); + TCase *const tcase_internal_parse_7 = tcase_create("Internal Parsing 7"); TCase *const tcase_encode_decode = tcase_create("Encode Decode"); TCase *const tcase_mask_data = tcase_create("Mask Data"); TCase *const tcase_parse_date_string = tcase_create("Date Parsing"); @@ -1211,6 +1476,10 @@ tcase_set_timeout(tcase_internal_parse_6, civetweb_min_test_timeout); suite_add_tcase(suite, tcase_internal_parse_6); + tcase_add_test(tcase_internal_parse_7, test_parse_http_headers); + tcase_set_timeout(tcase_internal_parse_7, civetweb_min_test_timeout); + suite_add_tcase(suite, tcase_internal_parse_7); + tcase_add_test(tcase_encode_decode, test_encode_decode); tcase_set_timeout(tcase_encode_decode, civetweb_min_test_timeout); suite_add_tcase(suite, tcase_encode_decode); @@ -1254,6 +1523,7 @@ test_parse_date_string(0); test_parse_port_string(0); test_parse_http_message(0); + test_parse_http_headers(0); test_sha1(0); #if defined(_WIN32) diff -Nru civetweb-1.13+dfsg/unittest/public_server.c civetweb-1.15+dfsg/unittest/public_server.c --- civetweb-1.13+dfsg/unittest/public_server.c 2020-09-30 18:24:15.000000000 +0000 +++ civetweb-1.15+dfsg/unittest/public_server.c 2021-09-01 08:46:33.000000000 +0000 @@ -41,6 +41,10 @@ #include #define test_sleep(x) (Sleep((x)*1000)) #else +#include +#include +#include +#include #include #define test_sleep(x) (sleep(x)) #endif @@ -52,7 +56,48 @@ #define SLEEP_BEFORE_MG_STOP (1) #define SLEEP_AFTER_MG_STOP (5) -static const char *external_server_ip = "140.82.118.4"; /* github.com */ + +/* Try to communicate with an external http server. */ +static const char * +get_external_server_ip(void) +{ +#define no_of_testhosts (4) + const char *testhost[no_of_testhosts] = {"github.com", + "google.com", + "sourceforge.net", + "microsoft.com"}; + static char external_ip[64] = {0}; + int testhostidx; + + if (external_ip[0]) { + /* Get IP of external server only once, then reuse it */ + return external_ip; + } + mark_point(); + + for (testhostidx = 0; testhostidx < no_of_testhosts; testhostidx++) { + struct hostent *hostentry; + struct in_addr **in_addr_list; + const char *ip; + + hostentry = gethostbyname(testhost[testhostidx]); + + if (hostentry != NULL) { + in_addr_list = (struct in_addr **)hostentry->h_addr_list; + if (in_addr_list[0] != NULL) { + ip = inet_ntoa(*in_addr_list[0]); + if (ip != NULL) { + mark_point(); + strcpy(external_ip, ip); + return external_ip; + } + } + } + } + + ck_abort_msg("Could not determine IP of any external server"); + return "0.0.0.0"; +} /* This unit test file uses the excellent Check unit testing library. @@ -283,6 +328,12 @@ { struct mg_context *ctx; struct mg_callbacks cb; + struct mg_init_data init; + struct mg_error_data error; + char error_buffer[256]; + + memset(&init, 0, sizeof(init)); + memset(&error, 0, sizeof(error)); if (callbacks) { memcpy(&cb, callbacks, sizeof(cb)); @@ -294,21 +345,33 @@ cb.log_message = test_log_message; } + init.callbacks = &cb; + init.user_data = user_data; + init.configuration_options = configuration_options; + + error.text = error_buffer; + error.text_buffer_size = sizeof(error_buffer); + mark_point(); test_sleep(SLEEP_BEFORE_MG_START); mark_point(); - ctx = mg_start(&cb, user_data, configuration_options); + ctx = mg_start2(&init, &error); mark_point(); if (ctx) { /* Give the server some time to start in the test VM. */ /* Don't need to do this if mg_start failed. */ test_sleep(SLEEP_AFTER_MG_START); + ck_assert_int_eq(error.code, 0); + ck_assert_str_eq(error.text, ""); } else if (line > 0) { /* mg_start is not supposed to fail anywhere, except for * special tests (for them, line is 0). */ - ck_abort_msg("mg_start failed in line %u, message %s", - line, - (lastMessage ? lastMessage : "")); + ck_abort_msg( + "mg_start failed in line %u\nerror %u: %s\nlast message %s\n", + line, + error.code, + error.text, + (lastMessage ? lastMessage : "")); } mark_point(); @@ -346,11 +409,6 @@ int optcnt = 0; const char *localhost_name = ((ipv6) ? "[::1]" : "127.0.0.1"); -#if defined(MG_LEGACY_INTERFACE) - size_t ports_cnt; - int ports[16]; - int ssl[16]; -#endif struct mg_callbacks callbacks; char errmsg[256]; @@ -382,10 +440,6 @@ OPTIONS[optcnt] = 0; -#if defined(MG_LEGACY_INTERFACE) - memset(ports, 0, sizeof(ports)); - memset(ssl, 0, sizeof(ssl)); -#endif memset(portinfo, 0, sizeof(portinfo)); memset(&callbacks, 0, sizeof(callbacks)); memset(errmsg, 0, sizeof(errmsg)); @@ -397,15 +451,6 @@ ck_assert_str_eq(errmsg, ""); ck_assert(ctx != NULL); -#if defined(MG_LEGACY_INTERFACE) - ports_cnt = mg_get_ports(ctx, 16, ports, ssl); - ck_assert_uint_eq(ports_cnt, 1); - ck_assert_int_eq(ports[0], 8080); - ck_assert_int_eq(ssl[0], 0); - ck_assert_int_eq(ports[1], 0); - ck_assert_int_eq(ssl[1], 0); -#endif - ret = mg_get_server_ports(ctx, 0, portinfo); ck_assert_int_lt(ret, 0); ck_assert_int_eq(portinfo[0].protocol, 0); @@ -583,11 +628,6 @@ struct mg_context *ctx; -#if defined(MG_LEGACY_INTERFACE) - size_t ports_cnt; - int ports[16]; - int ssl[16]; -#endif struct mg_callbacks callbacks; char errmsg[256]; @@ -617,10 +657,6 @@ ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 1] == NULL); ck_assert(OPTIONS[sizeof(OPTIONS) / sizeof(OPTIONS[0]) - 2] == NULL); -#if defined(MG_LEGACY_INTERFACE) - memset(ports, 0, sizeof(ports)); - memset(ssl, 0, sizeof(ssl)); -#endif memset(portinfo, 0, sizeof(portinfo)); memset(&callbacks, 0, sizeof(callbacks)); memset(errmsg, 0, sizeof(errmsg)); @@ -632,17 +668,6 @@ ck_assert_str_eq(errmsg, ""); ck_assert(ctx != NULL); -#if defined(MG_LEGACY_INTERFACE) - ports_cnt = mg_get_ports(ctx, 16, ports, ssl); - ck_assert_uint_eq(ports_cnt, 2); - ck_assert_int_eq(ports[0], 8080); - ck_assert_int_eq(ssl[0], 0); - ck_assert_int_eq(ports[1], 8443); - ck_assert_int_eq(ssl[1], 1); - ck_assert_int_eq(ports[2], 0); - ck_assert_int_eq(ssl[2], 0); -#endif - ret = mg_get_server_ports(ctx, 0, portinfo); ck_assert_int_lt(ret, 0); ck_assert_int_eq(portinfo[0].protocol, 0); @@ -979,7 +1004,7 @@ } -#ifdef USE_WEBSOCKET +#if defined(USE_WEBSOCKET) /****************************************************************************/ /* WEBSOCKET SERVER */ /****************************************************************************/ @@ -1387,7 +1412,7 @@ ipv4_port); mg_set_request_handler(ctx, "/handler2", request_test_handler2, NULL); -#ifdef USE_WEBSOCKET +#if defined(USE_WEBSOCKET) mg_set_websocket_handler(ctx, "/websocket", websock_server_connect, @@ -1980,7 +2005,7 @@ /* Websocket test */ -#ifdef USE_WEBSOCKET +#if defined(USE_WEBSOCKET) /* Then connect a first client */ ws_client1_conn = mg_connect_websocket_client("localhost", @@ -2031,7 +2056,7 @@ ws_client1_data.len = 0; /* Now connect a second client */ -#ifdef USE_IPV6 +#if defined(USE_IPV6) ws_client2_conn = mg_connect_websocket_client("[::1]", ipv6_port, @@ -2276,7 +2301,7 @@ test_mg_stop(ctx, __LINE__); mark_point(); -#ifdef USE_WEBSOCKET +#if defined(USE_WEBSOCKET) for (i = 0; i < 100; i++) { test_sleep(1); if (ws_client3_data.closed != 0) { @@ -3698,7 +3723,7 @@ ck_assert_str_eq(errmsg, "Invalid number of worker threads"); /* Set to a number - but use a number above the limit */ -#ifdef MAX_WORKER_THREADS +#if defined(MAX_WORKER_THREADS) sprintf(bad_thread_num, "%u", MAX_WORKER_THREADS + 1); #else sprintf(bad_thread_num, "%lu", 1000000000lu); @@ -4822,6 +4847,9 @@ START_TEST(test_minimal_client) { + const char *external_server_ip; + mark_point(); + external_server_ip = get_external_server_ip(); mark_point(); /* Initialize the library */ @@ -4847,6 +4875,9 @@ START_TEST(test_minimal_tls_client) { + const char *external_server_ip; + mark_point(); + external_server_ip = get_external_server_ip(); mark_point(); #if !defined(NO_SSL) /* dont run https test if SSL is not enabled */