diff --git a/.clang-format b/.clang-format index e1435c070..defae32e0 100644 --- a/.clang-format +++ b/.clang-format @@ -3,7 +3,7 @@ ColumnLimit: 0 SortIncludes: Never BreakBeforeBinaryOperators: NonAssignment BinPackArguments: False -BinPackParameters: False +BinPackParameters: OnePerLine IndentCaseBlocks: true MaxEmptyLinesToKeep: 3 BraceWrapping: diff --git a/.github/workflows/coverity-scan.yml b/.github/workflows/coverity-scan.yml index 6dc38950d..cf7c41ccd 100644 --- a/.github/workflows/coverity-scan.yml +++ b/.github/workflows/coverity-scan.yml @@ -6,11 +6,11 @@ on: jobs: latest: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check submission cache id: check_submit - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | cov-int @@ -18,29 +18,29 @@ jobs: - name: Install dependencies if: steps.check_submit.outputs.cache-hit != 'true' - run: sudo apt update && sudo apt install -y libcap-dev libjsoncpp-dev liblzo2-dev liblz4-dev libssl-dev swig + run: sudo apt update && sudo apt install -y libcap-dev libfmt-dev libjsoncpp-dev liblzo2-dev liblz4-dev libssl-dev swig - name: Checkout OpenVPN 3 if: steps.check_submit.outputs.cache-hit != 'true' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: openvpn3 - name: Checkout asio if: steps.check_submit.outputs.cache-hit != 'true' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # versioning=regex:^asio-(?\d+)-(?\d+)-(?\d+)$ repository: chriskohlhoff/asio - ref: asio-1-32-0 + ref: asio-1-38-0 path: asio - name: Checkout xxHash if: steps.check_submit.outputs.cache-hit != 'true' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # versioning=semver-coerced repository: Cyan4973/xxHash ref: v0.8.3 path: xxHash - - uses: lukka/get-cmake@5f6e04f5267c8133f1273bf2103583fc72c46b17 # v3.31.5 + - uses: lukka/get-cmake@ea83089aa35e08e459464341fe24ad024ee2466f # v4.3.1 if: steps.check_submit.outputs.cache-hit != 'true' - name: Download Coverity Build Tool @@ -77,7 +77,7 @@ jobs: - name: Cache submission if: steps.check_submit.outputs.cache-hit != 'true' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | cov-int diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 2efd57fc0..53b4b2872 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -10,11 +10,11 @@ jobs: build: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: openvpn3 - name: Checkout doxygen-awesome-css - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: doxygen-awesome-css repository: jothepro/doxygen-awesome-css @@ -25,7 +25,7 @@ jobs: sudo apt update sudo apt install -y --no-install-recommends \ build-essential cmake doxygen graphviz ninja-build \ - libasio-dev libcap-dev liblz4-dev libjsoncpp-dev libssl-dev libxxhash-dev + libasio-dev libcap-dev libfmt-dev libjsoncpp-dev liblz4-dev libssl-dev libxxhash-dev - name: Build Doxygen documentation id: build @@ -34,10 +34,9 @@ jobs: cd doxygen cmake -S ${{ github.workspace}}/openvpn3 -DENABLE_DOXYGEN=ON -DDOXYGEN_HTML_EXTRA_STYLESHEET=${{ github.workspace }}/doxygen-awesome-css/doxygen-awesome.css -GNinja ninja -v doxygen-core - touch doxygen/core/html/.nojekyll - name: Upload static files as artifact id: deployment - uses: actions/upload-pages-artifact@v3.0.1 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: doxygen/doxygen/core/html/ @@ -53,4 +52,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4.0.5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 92e7f8350..16a7ccfb5 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -6,42 +6,62 @@ jobs: msvc: strategy: matrix: - arch: [x86, amd64, amd64_arm64] + arch: [x86, x64, arm64] + include: + - arch: x64 + cmake_dir: amd64 + - arch: x86 + cmake_dir: x86 + - arch: arm64 + cmake_dir: arm64 env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + VCPKG_DEFAULT_TRIPLET: ${{ matrix.arch }}-windows + VCPKG_GIT_COMMIT_ID: d7b75fa8a30478ae5b5eb86ac730f851ef036875 BUILD_CONFIGURATION: Release - runs-on: windows-latest + runs-on: windows-2025 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: lukka/get-cmake@5f6e04f5267c8133f1273bf2103583fc72c46b17 # v3.31.5 - - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - with: - arch: ${{ matrix.arch }} - - - name: Restore from cache and install vcpkg + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: lukka/get-cmake@ea83089aa35e08e459464341fe24ad024ee2466f # v4.3.1 + - name: Install vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 + env: + VCPKG_BINARY_SOURCES: default,rw with: - vcpkgGitCommitId: 74ec888e385d189b42d6b398d0bbaa6f1b1d3b0e + vcpkgGitCommitId: ${{ env.VCPKG_GIT_COMMIT_ID }} vcpkgJsonGlob: '**/windows/vcpkg.json' + - name: Set up vcpkg binary cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + key: ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache-${{ hashFiles('**/windows/vcpkg.json') }}-${{ env.VCPKG_GIT_COMMIT_ID }} + restore-keys: | + ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache-${{ hashFiles('**/windows/vcpkg.json') }}- + ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache- + - name: Run CMake with vcpkg.json manifest - uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 - if: ${{ matrix.arch != 'amd64_arm64' }} + uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9 + if: ${{ matrix.arch != 'arm64' }} + env: + # make sure legacy provider is available for UTs + OPENSSL_MODULES: ${{ github.workspace }}\build\msvc\${{ matrix.cmake_dir }}\vcpkg_installed\${{ env.VCPKG_DEFAULT_TRIPLET }}\bin with: configurePreset: win-${{ matrix.arch }}-release buildPreset: win-${{ matrix.arch }}-release testPreset: win-${{ matrix.arch }}-release + testPresetAdditionalArgs: "['--output-on-failure']" - name: Run CMake with vcpkg.json manifest (NO TESTS) - uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 - if: ${{ matrix.arch == 'amd64_arm64' }} + uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9 + if: ${{ matrix.arch == 'arm64' }} with: configurePreset: win-${{ matrix.arch }}-release buildPreset: win-${{ matrix.arch }}-release - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: openvpn3-msvc-${{ matrix.arch }} path: | @@ -58,28 +78,40 @@ jobs: env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + VCPKG_GIT_COMMIT_ID: d7b75fa8a30478ae5b5eb86ac730f851ef036875 - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: lukka/get-cmake@5f6e04f5267c8133f1273bf2103583fc72c46b17 # v3.31.5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: lukka/get-cmake@ea83089aa35e08e459464341fe24ad024ee2466f # v4.3.1 - name: Install dependencies run: sudo apt update && sudo apt install -y mingw-w64 unzip cmake build-essential - - name: Restore from cache and install vcpkg + - name: Install vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 + env: + VCPKG_BINARY_SOURCES: default,rw with: - vcpkgGitCommitId: 74ec888e385d189b42d6b398d0bbaa6f1b1d3b0e + vcpkgGitCommitId: ${{ env.VCPKG_GIT_COMMIT_ID }} vcpkgJsonGlob: '**/mingw/vcpkg.json' + - name: Set up vcpkg binary cache + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + key: ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache-${{ hashFiles('**/mingw/vcpkg.json') }}-${{ env.VCPKG_GIT_COMMIT_ID }} + restore-keys: | + ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache-${{ hashFiles('**/mingw/vcpkg.json') }}- + ${{ runner.os }}-${{ matrix.arch }}-vcpkg-binary-cache- + - name: Run CMake with vcpkg.json manifest - uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 + uses: lukka/run-cmake@5d55ea7949e25f69f0ecb516d8d572297e03a956 # v10.9 with: configurePreset: mingw-${{ matrix.arch }}-release buildPreset: mingw-${{ matrix.arch }}-release - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: openvpn3-mingw-${{ matrix.arch }} path: | diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..211d459e7 --- /dev/null +++ b/.mailmap @@ -0,0 +1,8 @@ +Antonio Quartulli +Arne Schwabe +Charlie Vigue +Dmitriy Dudnik +Illia Polishchuk +Razvan Cojocaru +Samuli Seppänen +Yuriy Barnovych diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0df701bf8..e75a55380 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: 'v18.1.8' + rev: 'v22.1.3' hooks: - id: clang-format files: \.[ch]pp$ diff --git a/CMakeLists.txt b/CMakeLists.txt index 73c8340d3..f8eb998f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_C_STANDARD 99) @@ -46,6 +46,7 @@ add_subdirectory(openvpn/ovpnagent/mac) if (ENABLE_DOXYGEN) # Exclude some project specific directories set(DOXYGEN_EXCLUDE_PATTERNS + "${PROJECT_SOURCE_DIR}/README.md" "*/vcpkg_installed/*" "*/googletest-src/*" "*/rapidcheck-src/*" @@ -55,7 +56,8 @@ if (ENABLE_DOXYGEN) "*/test/unittests/output/*" "*/test/unittests/userpass/*" ) - set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${PROJECT_SOURCE_DIR}/README.md") + set(DOXYGEN_EXCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/test/unittests/test_addrpair.cpp;${CMAKE_CURRENT_SOURCE_DIR}/test/unittests/test_addrlist.cpp;${CMAKE_CURRENT_SOURCE_DIR}/test/unittests/test_capture.cpp") + set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${PROJECT_SOURCE_DIR}/doc/developer_guide.md") configure_doxygen("OpenVPN 3 Core Library" "core" "doxygen/core") endif () diff --git a/CMakePresets.json b/CMakePresets.json index 404b16c40..9e79c6f7b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -208,7 +208,7 @@ ] }, { - "name": "win-amd64-debug", + "name": "win-x64-debug", "inherits": [ "base", "base-windows", @@ -225,15 +225,6 @@ "debug" ] }, - { - "name": "win-amd64_arm64-debug", - "inherits": [ - "base", - "base-windows", - "arm64", - "debug" - ] - }, { "name": "win-x86-debug", "inherits": [ @@ -244,7 +235,7 @@ ] }, { - "name": "win-amd64-release", + "name": "win-x64-release", "inherits": [ "base", "base-windows", @@ -261,15 +252,6 @@ "release" ] }, - { - "name": "win-amd64_arm64-release", - "inherits": [ - "base", - "base-windows", - "arm64", - "release" - ] - }, { "name": "win-x86-release", "inherits": [ @@ -338,8 +320,8 @@ "configuration": "Release" }, { - "name": "win-amd64-debug", - "configurePreset": "win-amd64-debug", + "name": "win-x64-debug", + "configurePreset": "win-x64-debug", "configuration": "Debug" }, { @@ -353,8 +335,8 @@ "configuration": "Debug" }, { - "name": "win-amd64-release", - "configurePreset": "win-amd64-release", + "name": "win-x64-release", + "configurePreset": "win-x64-release", "configuration": "Release" }, { @@ -362,11 +344,6 @@ "configurePreset": "win-arm64-release", "configuration": "Release" }, - { - "name": "win-amd64_arm64-release", - "configurePreset": "win-arm64-release", - "configuration": "Release" - }, { "name": "win-x86-release", "configurePreset": "win-x86-release", @@ -400,8 +377,8 @@ ], "testPresets": [ { - "name": "win-amd64-debug", - "configurePreset": "win-amd64-debug", + "name": "win-x64-debug", + "configurePreset": "win-x64-debug", "configuration": "Debug" }, { @@ -410,8 +387,8 @@ "configuration": "Debug" }, { - "name": "win-amd64-release", - "configurePreset": "win-amd64-release", + "name": "win-x64-release", + "configurePreset": "win-x64-release", "configuration": "Release" }, { diff --git a/README.md b/README.md index 5a5180f6d..f72843eef 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,8 @@ the library and provides basic command line functionality. OpenVPN 3 is currently used in production as the core of the OpenVPN Connect clients for iOS, Android, Linux, Windows, and Mac OS X. -NOTE: OpenVPN 3 does not currently implement server functionality. - -[TOC] +> [!NOTE] +> OpenVPN 3 does not currently implement server functionality. OpenVPN 3 Client API -------------------- @@ -23,15 +22,17 @@ OpenVPN 3 is organized as a C++ class library, and the API is defined in A simple command-line wrapper for the API is provided in [test/ovpncli/cli.cpp](test/ovpncli/cli.cpp). +Please also refer to our Doxygen-generated [API documentation](https://openvpn.github.io/openvpn3/). + Building the OpenVPN 3 client on Linux -------------------------------------- -These instructions were tested on Ubuntu 22.04. +These instructions were tested on Ubuntu 24.04. Install essential dependencies: $ sudo apt install --no-install-recommends ca-certificates cmake g++ git iproute2 ninja-build pkg-config - $ sudo apt install --no-install-recommends libasio-dev libcap-dev liblz4-dev libjsoncpp-dev libssl-dev libxxhash-dev + $ sudo apt install --no-install-recommends libasio-dev libcap-dev libfmt-dev liblz4-dev libjsoncpp-dev libssl-dev libxxhash-dev Potentially install optional dependencies: @@ -62,20 +63,26 @@ Options used: - `route-nopull` : if you are connected via ssh, prevent ssh session lockout -### Using cli with ovpn-dco +### Using cli with the ovpn Linux kernel module -ovpn-dco is a kernel module which optimises data channel encryption and +ovpn is a kernel module which optimises data channel encryption and transport, providing better performance. The cli will detect when the kernel module is available and enable dco automatically (use `--no-dco` to disable this). -Download, build and install ovpn-dco: +The ovpn kernel module has been merged upstream as of linux-6.16. +From this kernel version onwards you directly get the DCO module as +shipped by your kernel. + +Alternatively, if you run an older kernel or if you want to use a more +recent DCO module than the one shipped by your kernel, you need to use +the ovpn-backports project. + +To learn how to use the ovpn-backports project and build your own DCO +kernel module, please refer to the README file available at: + + https://github.com/OpenVPN/ovpn-backports/blob/main/README.md - $ sudo apt install make - $ git clone https://github.com/OpenVPN/ovpn-dco.git - $ cd ovpn-dco - $ make && sudo make install - $ sudo modprobe ovpn-dco Install core dependencies: @@ -83,7 +90,7 @@ Install core dependencies: Build cli with ovpn-dco support: - $ cd $O3/core/build + $ cd openvpn3/build $ cmake -DCLI_OVPNDCO=ON .. && cmake --build . $ sudo test/ovpncli/ovpncli [--no-dco] myprofile.ovpn @@ -111,11 +118,11 @@ Install the dependencies: Ensure that [homebrew]() is set up. - $ brew install asio cmake jsoncpp lz4 openssl pkg-config xxhash + $ brew install asio cmake fmt jsoncpp lz4 openssl pkg-config xxhash Now build the OpenVPN 3 client executable: -On a ARM64 based Mac: +On an ARM64 based Mac: $ cd ~/src/ $ mkdir build-openvpn3 @@ -123,7 +130,7 @@ On a ARM64 based Mac: $ cmake -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl -DCMAKE_PREFIX_PATH=/opt/homebrew ~/src/openvpn3 $ cmake --build . -For a build on a Intel based Mac: +For a build on an Intel based Mac: $ cd ~/src/ $ mkdir build-openvpn3 @@ -155,14 +162,14 @@ Building the OpenVPN 3 client for Windows Prerequisites: -- Visual Studio 2019 or 2022 +- Visual Studio 2022 - CMake - vcpkg - git To build: - > git clone https://github.com/OpenVPN/openvpn3.git core && cd core + > git clone https://github.com/OpenVPN/openvpn3.git && cd openvpn3 > set VCPKG_ROOT= > cmake --preset win-amd64-release > cmake --build --preset win-amd64-release --target ovpncli @@ -180,7 +187,7 @@ Prerequisites: To build: - $ git clone https://github.com/OpenVPN/openvpn3.git core && cd core + $ git clone https://github.com/OpenVPN/openvpn3.git && cd openvpn3 $ export VCPKG_ROOT= $ cmake --preset mingw-x64-release $ cmake --build --preset mingw-x64-release --target ovpncli @@ -208,348 +215,10 @@ you need to install CMake and build Google Test. Build and run tests on Linux: - $ cd $O3/core/build - $ cmake --build . -- test/unittests/coreUnitTests + $ cd openvpn3/build + $ cmake --build . -- coreUnitTests $ make test -Developer Guide ---------------- - -OpenVPN 3 is written in C++17 and developers who are moving from C to -C++ should take some time to familiarize themselves with key C++ design -patterns such as -[*RAII*](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization). - -### OpenVPN 3 Client Core - -OpenVPN 3 is designed as a class library, with an API that is -essentially defined inside of **namespace openvpn::ClientAPI** with headers and -implementation in [client](client) and header-only library files under -[openvpn](openvpn). - -The concise definition of the client API is essentially -**class openvpn::ClientAPI::OpenVPNClient** in [client/ovpncli.hpp](client/ovpncli.hpp) with -several important extensions to the API found in: - -- **class openvpn::TunBuilderBase** in - [openvpn/tun/builder/base.hpp](openvpn/tun/builder/base.hpp) --- - Provides an abstraction layer defining the *tun* interface, and is - especially useful for interfacing with an OS-layer VPN API. -- **class openvpn::ExternalPKIBase** in - [openvpn/pki/epkibase.hpp](openvpn/pki/epkibase.hpp) --- Provides a - callback for external private key operations, and is useful for - interfacing with an OS-layer Keychain such as the Keychain on iOS, - Mac OS X, and Android, and the Crypto API on Windows. -- **class openvpn::ClientAPI::LogReceiver** in [client/ovpncli.hpp](client/ovpncli.hpp) --- - Provides an abstraction layer for the delivery of logging messages. - -OpenVPN 3 includes a command-line reference client (`cli`) for testing -the API. See [test/ovpncli/cli.cpp](test/ovpncli/cli.cpp). - -The basic approach to building an OpenVPN 3 client is to define a client -class that derives from openvpn::ClientAPI::OpenVPNClient, then provide -implementations for callbacks including event and logging notifications: - - class Client : public ClientAPI::OpenVPNClient - { - public: - virtual void event(const Event&) override { // events delivered here - ... - } - virtual void log(const LogInfo&) override { // logging delivered here - ... - } - - ... - }; - -To start the client, first create a **openvpn::ProtoContext::ProtoConfig** object and -initialize it with the OpenVPN config file and other options: - - ProtoContext::ProtoConfig config; - config.content = ; - ... - -Next, create a client object and evaluate the configuration: - - Client client; - ClientAPI::EvalConfig eval = client.eval_config(config); - if (eval.error) - throw ...; - -Finally, in a new worker thread, start the connection: - - ClientAPI::Status connect_status = client.connect(); - -Note that `client.connect()` will not return until the session has -terminated. - -### Top Layer - -The top layer of the OpenVPN 3 client is implemented in -[test/ovpncli/cli.cpp](test/ovpncli/cli.cpp) and -[openvpn/client/cliopt.hpp](openvpn/client/cliopt.hpp). Most of what -this code does is marshalling the configuration and dispatching the -higher-level objects that implement the OpenVPN client session. - -### Connection - -**class openvpn::ClientConnect** in -[openvpn/client/cliconnect.hpp](openvpn/client/cliconnect.hpp) -implements the top-level connection logic for an OpenVPN client -connection. It is concerned with starting, stopping, pausing, and -resuming OpenVPN client connections. It deals with retrying a connection -and handles the connection timeout. It also deals with connection -exceptions and understands the difference between an exception that -should halt any further reconnection attempts (such as `AUTH_FAILED`), -and other exceptions such as network errors that would justify a retry. - -Some of the methods in the class (such as `stop`, `pause`, and -`reconnect`) are often called by another thread that is controlling the -connection, therefore thread-safe methods are provided where the -thread-safe function posts a message to the actual connection thread. - -In an OpenVPN client connection, the following object stack would be -used: - -1. **class openvpn::ClientConnect** in - [openvpn/client/cliconnect.hpp](openvpn/client/cliconnect.hpp) --- - The top-layer object in an OpenVPN client connection. -2. **class openvpn::ClientProto::Session** in - [openvpn/client/cliproto.hpp](openvpn/client/cliproto.hpp) --- The - OpenVPN client protocol object that subinstantiates the transport - and tun layer objects. -3. **class openvpn::ProtoContext** in - [openvpn/ssl/proto.hpp](openvpn/ssl/proto.hpp) --- The core OpenVPN - protocol implementation that is common to both client and server. -4. **openvpn::ProtoStackBase** (with **openvpn::Packet**) in - [openvpn/ssl/protostack.hpp](openvpn/ssl/protostack.hpp) --- The - bottom-layer class that implements the basic functionality of - tunneling a protocol over a reliable or unreliable transport layer, - but isn't specific to OpenVPN per-se. - -### Transport Layer - -OpenVPN 3 defines abstract base classes for Transport layer -implementations in -[openvpn/transport/client/transbase.hpp](openvpn/transport/client/transbase.hpp). - -Currently, transport layer implementations are provided for: - -- **UDP** --- - [openvpn/transport/client/udpcli.hpp](openvpn/transport/client/udpcli.hpp) -- **TCP** --- - [openvpn/transport/client/tcpcli.hpp](openvpn/transport/client/tcpcli.hpp) -- **HTTP Proxy** --- - [openvpn/transport/client/httpcli.hpp](openvpn/transport/client/httpcli.hpp) - -### Tun Layer - -OpenVPN 3 defines abstract base classes for Tun layer implementations in -[openvpn/tun/client/tunbase.hpp](openvpn/tun/client/tunbase.hpp). - -There are two possible approaches to define a Tun layer implementation: - -1. Use a VPN API-centric model (such as for Android or iOS). These - models derive from **class openvpn::TunBuilderBase** in - [openvpn/tun/builder/base.hpp](openvpn/tun/builder/base.hpp) -2. Use an OS-specific model such as: - - **Linux** --- - [openvpn/tun/linux/client/tuncli.hpp](openvpn/tun/linux/client/tuncli.hpp) - - **Windows** --- - [openvpn/tun/win/client/tuncli.hpp](openvpn/tun/win/client/tuncli.hpp) - - **Mac OS X** --- - [openvpn/tun/mac/client/tuncli.hpp](openvpn/tun/mac/client/tuncli.hpp) - -### Protocol Layer - -The OpenVPN protocol is implemented in **class openvpn::ProtoContext** in -[openvpn/ssl/proto.hpp](openvpn/ssl/proto.hpp). - -### Options Processing - -The parsing and query of the OpenVPN config file is implemented by -**class openvpn::OptionList** in -[openvpn/common/options.hpp](openvpn/common/options.hpp). - -Note that OpenVPN 3 always assumes an *inline* style of configuration, -where all certs, keys, etc. are defined inline rather than through an -external file reference. - -For config files that do use external file references, -**class openvpn::ProfileMerge** in -[openvpn/options/merge.hpp](openvpn/options/merge.hpp) is provided to -merge those external file references into an inline form. - -### Calling the Client API from other languages - -The OpenVPN 3 client API, as defined by -**class openvpn::ClientAPI::OpenVPNClient** in -[client/ovpncli.hpp](client/ovpncli.hpp), can be wrapped by the -[Swig](http://www.swig.org/) tool to create bindings for other -languages. - -For example, OpenVPN Connect for Android creates a Java binding of the -API using [client/ovpncli.i](client/ovpncli.i). - -Security --------- - -When developing security software in C++, it's very important to take -advantage of the language and OpenVPN library code to insulate code from -the kinds of bugs that can introduce security vulnerabilities. - -Here is a brief set of guidelines: - -- When dealing with strings, use a `std::string` rather than a - `char *`. - -- When dealing with binary data or buffers, always try to use a - `openvpn::Buffer`, `openvpn::ConstBuffer`, `openvpn::BufferAllocatedRc`, - or `openvpn::BufferPtr` object - to provide managed access to the buffer, to protect against security - bugs that arise when using raw buffer pointers. See - [openvpn/buffer/buffer.hpp](openvpn/buffer/buffer.hpp) for the - OpenVPN `Buffer` classes. - -- When it's necessary to have a pointer to an object, use - `std::unique_ptr<>` for non-shared objects and reference-counted - smart pointers for shared objects. For shared-pointers, OpenVPN code - should use the smart pointer classes defined in - [openvpn/common/rc.hpp](openvpn/common/rc.hpp). Please see the - comments in this file for documentation. - -- Never use `malloc` or `free`. When allocating objects, use the C++ - `new` operator and then immediately construct a smart pointer to - reference the object: - - std::unique_ptr ptr = new MyObject(); - ptr->method(); - -- When interfacing with C functions that deal with raw pointers, - memory allocation, etc., consider wrapping the functionality in C++. - For an example, see `enum_dir()` in - [openvpn/common/enumdir.hpp](openvpn/common/enumdir.hpp), a function - that returns a list of files in a directory (Unix only) via a - high-level string vector, while internally calling the low level - libc methods `opendir`, `readdir`, and `closedir`. Notice how - `unique_ptr_del` is used to wrap the `DIR` struct in a smart pointer - with a custom deletion function. - -- When grabbing random entropy that is to be used for cryptographic - purposes (i.e. for keys, tokens, etc.), always ensure that the RNG - is crypto-grade by using **class openvpn::StrongRandomAPI** as the RNG type: - - StrongRandomAPI::Ptr rng; - void set_rng(StrongRandomAPI::Ptr rng_arg) { - rng = std::move(rng_arg); - } - -- Any variable whose value is not expected to change should be - declared `const`. - -- Don't use non-const global or static variables unless absolutely - necessary. - -- When formatting strings, don't use `snprintf`. Instead, use - `std::ostringstream` or build the string using the `+` `std::string` - operator: - - std::string format_reconnecting(const int n_seconds) { - return "Reconnecting in " + openvpn::to_string(n_seconds) + " seconds."; - } - - or: - - std::string format_reconnecting(const int n_seconds) { - std::ostringstream os; - os << "Reconnecting in " << n_seconds << " seconds."; - return os.str(); - } - -- OpenVPN 3 is a *header-only* library, therefore all free functions - outside of classes should have the `inline` attribute. - -### Conventions - -- Use the **Asio** library for I/O and timers. Don't deal with - sockets directly. - -- Never block. If you need to wait for something, use **Asio** timers - or sockets. - -- Use the `OPENVPN_LOG()` macro to log stuff. Don't use `printf`. - -- Don't call crypto/ssl libraries directly. Instead use the - abstraction layers ([openvpn/crypto](openvpn/crypto) and - [openvpn/ssl](openvpn/ssl)) that allow OpenVPN to link with - different crypto/ssl libraries (such as **OpenSSL** or **mbed - TLS**). - -- Use openvpn::RandomAPI as a wrapper for random number generators - ([openvpn/random/randapi.hpp](openvpn/random/randapi.hpp)). - -- If you need to deal with configuration file options, see - class openvpn::OptionList in - [openvpn/common/options.hpp](openvpn/common/options.hpp). - -- If you need to deal with time or time durations, use the classes - under [openvpn/time](openvpn/time). - -- If you need to deal with IP addresses, see the comprehensive classes - under [openvpn/addr](openvpn/addr). - -- In general, if you need a general-purpose library class or function, - look under [openvpn/common](openvpn/common). Chances are good that - it's already been implemented. - -- The OpenVPN 3 approach to errors is to count them, rather than - unconditionally log them. If you need to add a new error counter, - see [openvpn/error/error.hpp](openvpn/error/error.hpp). - -- If you need to create a new event type which can be transmitted as a - notification back to the client API user, see - [openvpn/client/clievent.hpp](openvpn/client/clievent.hpp). - -- Raw pointers or references can be okay when used by an object to - point back to its parent (or container), if you can guarantee that - the object will not outlive its parent. Backreferences to a parent - object is also a common use case for weak pointers. - -- Use C++ exceptions for error handling and as an alternative to - `goto`. See OpenVPN's general exception classes and macros in - [openvpn/common/exception.hpp](openvpn/common/exception.hpp). - -- Use C++ destructors for automatic object cleanup, and so that thrown - exceptions will not leak objects. Alternatively, use openvpn::Cleanup in - [openvpn/common/cleanup.hpp](openvpn/common/cleanup.hpp) when you - need to specify a code block to execute prior to scope exit. For - example, ensure that the file `pid_fn` is deleted before scope exit: - - auto clean = Cleanup([pid_fn]() { - if (pid_fn) - ::unlink(pid_fn); - }); - -- When calling global methods (such as libc `fork`), prepend `::` to - the symbol name, e.g.: - - struct dirent *e; - while ((e = ::readdir(dir.get())) != nullptr) { - ... - } - -- Use `nullptr` instead of `NULL`. - -### Threading - -The OpenVPN 3 client core is designed to run in a single thread, with -the UI or controller driving the OpenVPN API running in a different -thread. - -It's almost never necessary to create additional threads within the -OpenVPN 3 client core. - Contributing ------------ diff --git a/client/ovpncli.cpp b/client/ovpncli.cpp index 903e90ec5..df260f6be 100644 --- a/client/ovpncli.cpp +++ b/client/ovpncli.cpp @@ -21,7 +21,7 @@ // Set up export of our public interface unless // OPENVPN_CORE_API_VISIBILITY_HIDDEN is defined -#if defined(__GNUC__) +#ifdef __GNUC__ #define OPENVPN_CLIENT_EXPORT #ifndef OPENVPN_CORE_API_VISIBILITY_HIDDEN #pragma GCC visibility push(default) @@ -85,9 +85,11 @@ #include #include #include +#include #include #include #include +#include // copyright #include @@ -100,7 +102,7 @@ OPENVPN_SIMPLE_EXCEPTION(app_expired); class MySessionStats : public SessionStats { public: - typedef RCPtr Ptr; + using Ptr = RCPtr; MySessionStats(OpenVPNClient *parent_arg) : parent(parent_arg) @@ -111,35 +113,31 @@ class MySessionStats : public SessionStats #endif } - static size_t combined_n() + static constexpr size_t combined_n() { - return N_STATS + Error::N_ERRORS; + return static_cast(N_STATS) + static_cast(Error::N_ERRORS); } static std::string combined_name(const size_t index) { - if (index < N_STATS + Error::N_ERRORS) + if (index < combined_n()) { if (index < N_STATS) return stat_name(index); - else - return Error::name(index - N_STATS); + return Error::name(index - N_STATS); } - else - return ""; + return ""; } count_t combined_value(const size_t index) const { - if (index < N_STATS + Error::N_ERRORS) + if (index < combined_n()) { if (index < N_STATS) return get_stat(index); - else - return errors[index - N_STATS]; + return errors[index - N_STATS]; } - else - return 0; + return 0; } count_t stat_count(const size_t index) const @@ -179,7 +177,7 @@ class MySessionStats : public SessionStats class MyClientEvents : public ClientEvent::Queue { public: - typedef RCPtr Ptr; + using Ptr = RCPtr; MyClientEvents(OpenVPNClient *parent_arg) : parent(parent_arg) @@ -320,8 +318,7 @@ class MyReconnectNotify : public ReconnectNotify { if (parent) return parent->pause_on_connection_timeout(); - else - return false; + return false; } private: @@ -372,8 +369,7 @@ class MyRemoteOverride : public RemoteList::RemoteOverride throw Exception("remote override exception: " + ro.error); return ri; } - else - return RemoteList::Item::Ptr(); + return RemoteList::Item::Ptr(); } private: @@ -493,9 +489,7 @@ class ClientState remote_override.set_parent(parent); } - ClientState() - { - } + ClientState() = default; ~ClientState() { @@ -628,10 +622,10 @@ OPENVPN_CLIENT_EXPORT void OpenVPNClientHelper::parse_config(const Config &confi std::tie(eval.dcoCompatible, eval.dcoIncompatibilityReason) = ClientOptions::check_dco_compatibility(config, options); #ifdef OPENVPN_DUMP_CONFIG - std::cout << "---------- ARGS ----------" << std::endl; - std::cout << options.render(Option::RENDER_PASS_FMT | Option::RENDER_NUMBER | Option::RENDER_BRACKET) << std::endl; - std::cout << "---------- MAP ----------" << std::endl; - std::cout << options.render_map() << std::endl; + std::cout << "---------- ARGS ----------\n"; + std::cout << options.render(Option::RENDER_PASS_FMT | Option::RENDER_NUMBER | Option::RENDER_BRACKET) << "\n"; + std::cout << "---------- MAP ----------\n"; + std::cout << options.render_map() << "\n"; #endif eval.error = cc.error(); eval.message = cc.message(); @@ -860,7 +854,7 @@ OPENVPN_CLIENT_EXPORT void OpenVPNClient::process_epki_cert_chain(const External OPENVPN_CLIENT_EXPORT Status OpenVPNClient::connect() { -#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD) +#ifndef OPENVPN_OVPNCLI_SINGLE_THREAD openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread #endif #if defined(OPENVPN_LOG_LOGTHREAD_H) && !defined(OPENVPN_LOG_LOGBASE_H) @@ -882,7 +876,7 @@ OPENVPN_CLIENT_EXPORT Status OpenVPNClient::do_connect() try { connect_attach(); -#if defined(OPENVPN_OVPNCLI_ASYNC_SETUP) +#ifdef OPENVPN_OVPNCLI_ASYNC_SETUP openvpn_io::post(*state->io_context(), [this]() { do_connect_async(); }); #else @@ -953,18 +947,18 @@ OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_setup(Status &status, bool &se cc.extra_peer_info = state->extra_peer_info; cc.stop = state->async_stop_local(); cc.socket_protect = &state->socket_protect; -#if defined(USE_TUN_BUILDER) +#ifdef USE_TUN_BUILDER cc.builder = this; #endif -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#ifdef OPENVPN_EXTERNAL_TUN_FACTORY cc.extern_tun_factory = this; #endif -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) +#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY cc.extern_transport_factory = this; #endif // external PKI -#if !defined(USE_APPLE_SSL) +#ifndef USE_APPLE_SSL if (state->eval.externalPki && !state->clientconf.disableClientCert) { if (!state->clientconf.external_pki_alias.empty()) @@ -1100,7 +1094,7 @@ OPENVPN_CLIENT_EXPORT Stop *OpenVPNClient::get_async_stop() return nullptr; } -OPENVPN_CLIENT_EXPORT void OpenVPNClient::external_pki_error(const ExternalPKIRequestBase &req, const size_t err_type) +OPENVPN_CLIENT_EXPORT void OpenVPNClient::external_pki_error(const ExternalPKIRequestBase &req, const Error::Type err_type) { if (req.error) { @@ -1138,11 +1132,9 @@ OPENVPN_CLIENT_EXPORT bool OpenVPNClient::sign(const std::string &alias, sig = req.sig; return true; } - else - { - external_pki_error(req, Error::EPKI_SIGN_ERROR); - return false; - } + + external_pki_error(req, Error::EPKI_SIGN_ERROR); + return false; } OPENVPN_CLIENT_EXPORT bool OpenVPNClient::remote_override_enabled() @@ -1182,7 +1174,7 @@ OPENVPN_CLIENT_EXPORT long long OpenVPNClient::stats_value(int index) const OPENVPN_CLIENT_EXPORT std::vector OpenVPNClient::stats_bundle() const { std::vector sv; - const size_t n = MySessionStats::combined_n(); + constexpr size_t n = MySessionStats::combined_n(); sv.reserve(n); if (state->is_foreign_thread_access()) { @@ -1332,7 +1324,7 @@ static SSLLib::SSLAPI::Config::Ptr setup_certcheck_ssl_config(const std::string const std::optional &ca) { SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; - config->set_frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0))); + config->set_frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS))); config->set_mode(Mode(Mode::CLIENT)); config->load_cert(client_cert, extra_certs); unsigned int flags = SSLConst::LOG_VERIFY_STATUS; diff --git a/client/ovpncli.hpp b/client/ovpncli.hpp index 9b6d03f14..5ed2a0035 100644 --- a/client/ovpncli.hpp +++ b/client/ovpncli.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace openvpn { class OptionList; @@ -148,9 +149,7 @@ struct DynamicChallenge // passed as a dictionary struct KeyValue { - KeyValue() - { - } + KeyValue() = default; KeyValue(std::string key_arg, std::string value_arg) : key(std::move(key_arg)), @@ -436,9 +435,8 @@ struct Status // (client reads) struct LogInfo { - LogInfo() - { - } + LogInfo() = default; + LogInfo(std::string str) : text(std::move(str)) { @@ -726,7 +724,7 @@ class OpenVPNClient : public TunBuilderBase, // expose tun builder v // Callback for logging. // Will be called from the thread executing connect(). - virtual void log(const LogInfo &) override = 0; + void log(const LogInfo &) override = 0; // External PKI callbacks // Will be called from the thread executing connect(). @@ -754,7 +752,11 @@ class OpenVPNClient : public TunBuilderBase, // expose tun builder v virtual void connect_run(); virtual void connect_session_stop(); +#ifndef SWIG + /* hide this function from swig as it otherwise complains about a director + * method returning a pointer and the swig interfaces does not need this method. */ virtual Stop *get_async_stop(); +#endif Private::ClientState *state; @@ -763,7 +765,7 @@ class OpenVPNClient : public TunBuilderBase, // expose tun builder v void do_connect_async(); static Status status_from_exception(const std::exception &); void parse_extras(const Config &, EvalConfig &); - void external_pki_error(const ExternalPKIRequestBase &, const size_t); + void external_pki_error(const ExternalPKIRequestBase &, const Error::Type); void process_epki_cert_chain(const ExternalPKICertRequest &); friend class MyClientEvents; diff --git a/client/ovpncli.i b/client/ovpncli.i index 9af4f33b1..e60f02bd9 100644 --- a/client/ovpncli.i +++ b/client/ovpncli.i @@ -8,6 +8,10 @@ %include "std_vector.i" %include "std_map.i" +#ifdef SWIGJAVA +%include "swiginterface.i" +#endif + // top-level C++ implementation file %{ #include "ovpncli.hpp" @@ -19,8 +23,13 @@ %apply int { asio::detail::socket_type }; #endif +%apply size_t { openvpn::Error::Type }; + +#ifdef SWIGJAVA +%interface(openvpn::ClientAPI::LogReceiver); +#endif + // ignore these ClientAPI::OpenVPNClient bases -%ignore openvpn::ClientAPI::LogReceiver; %ignore openvpn::ExternalTun::Factory; %ignore openvpn::ExternalTransport::Factory; diff --git a/cmake/dlgoogletest.cmake b/cmake/dlgoogletest.cmake index 36806548a..36aa615d9 100644 --- a/cmake/dlgoogletest.cmake +++ b/cmake/dlgoogletest.cmake @@ -16,7 +16,7 @@ else() set(GTEST_LIB gtest_main) if(NOT OVPN_GTEST_VERSION) # renovate: datasource=github-releases depName=google/googletest - set(OVPN_GTEST_VERSION v1.16.0) + set(OVPN_GTEST_VERSION v1.17.0) endif() FetchContent_Declare( diff --git a/cmake/findcoredeps.cmake b/cmake/findcoredeps.cmake index a9dd56ac1..2657aa4f3 100644 --- a/cmake/findcoredeps.cmake +++ b/cmake/findcoredeps.cmake @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.13...3.28) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -131,6 +131,10 @@ function(add_corelibrary_dependencies target) find_package(lz4 REQUIRED) target_link_libraries(${target} lz4::lz4) + # fmtlib + find_package(fmt REQUIRED) + target_link_libraries(${target} fmt::fmt) + add_ssl_library(${target}) if (APPLE) @@ -152,6 +156,7 @@ function(add_corelibrary_dependencies target) target_compile_options(${target} PRIVATE /WX) else () target_compile_options(${target} PRIVATE -Werror) + target_link_options(${target} PRIVATE -Werror) endif () endif () @@ -167,10 +172,14 @@ function(add_corelibrary_dependencies target) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # disable noisy warnings target_compile_options(${target} PRIVATE -Wno-maybe-uninitialized) + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329 + if (CMAKE_CXX_COMPILER_VERSION MATCHES "^12") + target_compile_options(${target} PRIVATE -Wno-restrict) + endif() endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # display all warnings - target_compile_options(${target} PRIVATE -ferror-limit=0 -Wno-enum-enum-conversion) + target_compile_options(${target} PRIVATE -ferror-limit=0) endif() endif() endfunction() @@ -192,3 +201,9 @@ function (add_json_library target) target_compile_definitions(${target} PRIVATE -DHAVE_JSONCPP) endif () endfunction () + +function (add_libcap target) + find_package(PkgConfig REQUIRED) + pkg_search_module(Libcap REQUIRED IMPORTED_TARGET libcap) + target_link_libraries(${target} PkgConfig::Libcap) +endfunction () diff --git a/cmake/ovpn-doxygen.cmake b/cmake/ovpn-doxygen.cmake index 0308d77e5..234f97eba 100644 --- a/cmake/ovpn-doxygen.cmake +++ b/cmake/ovpn-doxygen.cmake @@ -19,6 +19,7 @@ function(configure_doxygen projname tgtname outputdir) set(DOXYGEN_EXTRACT_ALL YES) set(DOXYGEN_EXTRACT_PRIVATE YES) set(DOXYGEN_EXTRACT_STATIC YES) + set(DOXYGEN_PREDEFINED "HAVE_JSON:=1") set(DOXYGEN_SOURCE_BROWSER YES) set(DOXYGEN_NUM_PROC_THREADS 0) set(DOXYGEN_CALL_GRAPH "NO" CACHE STRING "Generate call graph images (value: YES/NO)") diff --git a/deps/asio/build-asio b/deps/asio/build-asio deleted file mode 100755 index 91d96a88a..000000000 --- a/deps/asio/build-asio +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -PACKAGE=${ASIO_VERSION} -FNAME=${ASIO_VERSION}.tar.gz -URL=https://github.com/chriskohlhoff/asio/archive/${ASIO_VERSION}.tar.gz -CSUM=${ASIO_CSUM} -DIST=asio - -download - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source -else - echo WIPE and reunzip source - cd $DEP_DIR - rm -rf $DIST asio-$ASIO_VERSION - tar xfz $DL/$FNAME - cd asio-$ASIO_VERSION - - apply_patches "asio" - - cd .. - - cp -a asio-$ASIO_VERSION $DIST -fi diff --git a/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch b/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch deleted file mode 100644 index 18ae1f784..000000000 --- a/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch +++ /dev/null @@ -1,38 +0,0 @@ -From fe57c9127cfc95b4673c6530f86edab5e6538425 Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Wed, 2 Sep 2015 12:18:48 -0700 -Subject: [PATCH] Added randomize() method to - asio::ip::tcp::resolver::results_type. - ---- - asio/include/asio/ip/basic_resolver_results.hpp | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp -index 3b3fad49..c070f7da 100644 ---- a/asio/include/asio/ip/basic_resolver_results.hpp -+++ b/asio/include/asio/ip/basic_resolver_results.hpp -@@ -18,6 +18,7 @@ - #include "asio/detail/config.hpp" - #include - #include -+#include - #include "asio/detail/socket_ops.hpp" - #include "asio/detail/socket_types.hpp" - #include "asio/ip/basic_resolver_iterator.hpp" -@@ -299,6 +300,12 @@ public: - return !a.equal(b); - } - -+ template -+ void randomize(Random& r) -+ { -+ std::shuffle(this->values_->begin(), this->values_->end(), r); -+ } -+ - private: - typedef std::vector > values_type; - }; --- -2.21.0 - diff --git a/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch b/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch deleted file mode 100644 index 229d0f9a2..000000000 --- a/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b8f6e3c4db6cd86657a3cbc97d17f268c7d6555a Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Sun, 19 Jul 2020 18:38:07 -0600 -Subject: basic_resolver_results: added data() and cdata() members for access - to underlying storage vector - -This commit also removes the randomize() method -since data() provides a more general solution -for arbitrary mutate methods. - -Signed-off-by: James Yonan ---- - asio/include/asio/ip/basic_resolver_results.hpp | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp -index 29898542..9483a774 100644 ---- a/asio/include/asio/ip/basic_resolver_results.hpp -+++ b/asio/include/asio/ip/basic_resolver_results.hpp -@@ -300,10 +300,18 @@ public: - return !a.equal(b); - } - -- template -- void randomize(Random& r) -+#define HAVE_ASIO_RESOLVER_RESULTS_DATA -+ -+ /// Return a pointer to the underlying results vector. -+ auto* data() -+ { -+ return this->values_.get(); -+ } -+ -+ /// Return a const pointer to the underlying results vector. -+ const auto* cdata() const - { -- std::shuffle(this->values_->begin(), this->values_->end(), r); -+ return this->values_.get(); - } - - private: --- -2.25.1 - diff --git a/deps/asio/snapshot-asio b/deps/asio/snapshot-asio deleted file mode 100755 index 2bd3e69ad..000000000 --- a/deps/asio/snapshot-asio +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -export NAME=asio -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -$DIR/../../scripts/snapshot diff --git a/deps/functions.sh b/deps/functions.sh deleted file mode 100644 index bd14cb2d4..000000000 --- a/deps/functions.sh +++ /dev/null @@ -1,58 +0,0 @@ -function check_download() -{ - if [ -f $DL/$FNAME ]; then - CHECK=$(shasum -a 256 $DL/$FNAME |awk '{printf $1};') - if [ "$CHECK" == "$CSUM" ]; then - return 0 - else - echo "Checksum mismatch for $FNAME. Was $CHECK, expected $CSUM" - fi - else - echo "$FNAME not found." - fi - - return -1 -} - -function download() -{ - check_download && return 0 - - rm -f $DL/$FNAME - if [ -n "$URL" ]; then - wget $URL -O $DL/$FNAME - else - echo URL must be specified - exit 1 - fi - - check_download || return -1 -} - -function apply_patches() -{ - DEP_NAME=$1 - - # change directory since git apply got confused when - # applying patches to files which are not found in index - DIR=$(pwd) - pushd ${DIR} - cd /tmp - # apply pre-generated patches - for file in $O3/core/deps/${DEP_NAME}/patches/*.patch; do - echo Applying patch: $file - git apply --directory ${DIR} --unsafe-path $file - done - popd -} - -function lto_flags() -{ - local seed=$1 - if [ "$TARGET" == "linux" ]; then - echo -n " -flto=4 -Wl,--no-as-needed " - if [ -n "$seed" ]; then - echo -n " -frandom-seed=$seed " - fi - fi -} diff --git a/deps/jsoncpp/build-jsoncpp b/deps/jsoncpp/build-jsoncpp deleted file mode 100755 index 1f234e5be..000000000 --- a/deps/jsoncpp/build-jsoncpp +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -[ -z "$DL" ] && DL=~/Downloads - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -GPP=g++ -LD=ld -AR="ar rc" -RANLIB=ranlib -[ "$GPP_CMD" ] && GPP=$GPP_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR="$AR_CMD" -[ "$RANLIB_CMD" ] && RANLIB="$RANLIB_CMD" - -case $PLATFORM in -android*) - echo PLATFORM android - host="x86_64-apple-darwin" - target=arm - ;; -ios*) - echo PLATFORM ios - host="x86_64-apple-darwin" - target=arm - ;; -*) - host="" - target="" - ;; -esac - -if [ "$target" ]; then - targ_opt="--target=$target" -fi - -if [ "$host" ]; then - host_opt="--host=$host" -fi - -FNAME=jsoncpp-${JSONCPP_VERSION}.tar.gz -URL=https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/${JSONCPP_VERSION}.tar.gz -CSUM=${JSONCPP_CSUM} - -download - -DIST=$(pwd)/jsoncpp/jsoncpp-$PLATFORM -rm -rf $DIST -mkdir -p $DIST/include -mkdir $DIST/lib - -tar xfz $DL/$FNAME - -cd jsoncpp-$JSONCPP_VERSION -python amalgamate.py -cd dist -CMD="$GPP -I. $PLATFORM_FLAGS $CXX_COMPILER_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c jsoncpp.cpp" -echo $CMD -$CMD -$AR $DIST/lib/libjsoncpp.a jsoncpp.o -$RANLIB $DIST/lib/libjsoncpp.a -cp -a json $DIST/include/ -exit 0 diff --git a/deps/lib-versions b/deps/lib-versions deleted file mode 100644 index 77aabcfa5..000000000 --- a/deps/lib-versions +++ /dev/null @@ -1,14 +0,0 @@ -export ASIO_VERSION=asio-1-24-0 -export ASIO_CSUM=cbcaaba0f66722787b1a7c33afe1befb3a012b5af3ad7da7ff0f6b8c9b7a8a5b - -export LZ4_VERSION=lz4-1.8.3 -export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43 - -export MBEDTLS_VERSION=mbedtls-2.28.4 -export MBEDTLS_CSUM=578c4dcd15bbff3f5cd56aa07cd4f850fc733634e3d5947be4f7157d5bfd81ac - -export JSONCPP_VERSION=1.8.4 -export JSONCPP_CSUM=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6 - -export XXHASH_VERSION=0.8.0 -export XXHASH_CSUM=7054c3ebd169c97b64a92d7b994ab63c70dd53a06974f1f630ab782c28db0f4f diff --git a/deps/lz4/build-lz4 b/deps/lz4/build-lz4 deleted file mode 100755 index 8b34f780e..000000000 --- a/deps/lz4/build-lz4 +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=${LZ4_VERSION}.tar.gz -PN=${LZ4_VERSION#*-} -URL=https://github.com/lz4/lz4/archive/v${PN}.tar.gz -CSUM=${LZ4_CSUM} - -download - -CC=cc -LD=ld -AR="ar rc" -RANLIB=ranlib -[ "$GCC_CMD" ] && CC=$GCC_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR="$AR_CMD" -[ "$RANLIB_CMD" ] && RANLIB="$RANLIB_CMD" - -if [ "$NO_WIPE" != "1" ]; then - rm -rf $LZ4_VERSION - tar xfz $DL/$LZ4_VERSION.tar.gz -fi - -if [ "x$NO_BUILD" == x1 ]; then - echo "Not building" - exit -fi - -DIST=$(pwd)/lz4/lz4-$PLATFORM -rm -rf $DIST -mkdir -p $DIST/include -mkdir $DIST/lib -cd $LZ4_VERSION/lib -CMD="$CC $PLATFORM_FLAGS $(lto_flags lz4.c) $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c lz4.c" -echo $CMD -$CMD -$AR $DIST/lib/liblz4.a lz4.o -$RANLIB $DIST/lib/liblz4.a -cp lz4.h $DIST/include/ -exit 0 diff --git a/deps/lz4/snapshot-lz4 b/deps/lz4/snapshot-lz4 deleted file mode 100755 index 10740810d..000000000 --- a/deps/lz4/snapshot-lz4 +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -export NAME=lz4 -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -$DIR/../../scripts/snapshot diff --git a/deps/mbedtls/build-mbedtls b/deps/mbedtls/build-mbedtls deleted file mode 100755 index d32fabc19..000000000 --- a/deps/mbedtls/build-mbedtls +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=${MBEDTLS_VERSION}.tar.gz -PN=${MBEDTLS_VERSION#*-} -URL=https://github.com/ARMmbed/mbedtls/archive/refs/tags/v${PN}.tar.gz -CSUM=${MBEDTLS_CSUM} - -download - -# put build targets here -DIST=$(pwd)/mbedtls/mbedtls-$PLATFORM -rm -rf $DIST -mkdir -p $DIST - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source - cd $MBEDTLS_VERSION -else - echo WIPE and reunzip source - rm -rf $MBEDTLS_VERSION - [ -z "$DL" ] && DL=~/Downloads - tar xfz $DL/$MBEDTLS_VERSION.tar.gz - cd $MBEDTLS_VERSION - - # enable MD4 (needed for NTLM auth) - perl -pi -e 's/^\/\/// if /#define MBEDTLS_MD4_C/' include/mbedtls/config.h -fi - -if [ "x$NO_BUILD" == x1 ]; then - echo "Not building" - exit 0 -fi - -if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then - # run unit tests and then clean - echo RUNNING CHECK - make check - echo CLEANING - make clean -fi - -echo BUILDING - -# compiler vars -CC=cc -LD=ld -AR="ar rc" -RANLIB=ranlib -[ "$GCC_CMD" ] && CC=$GCC_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR="$AR_CMD" -[ "$RANLIB_CMD" ] && RANLIB="$RANLIB_CMD" - -# build it -SRC=$(pwd) -cd library -rm -f *.o -for c in *.c ; do - CMD="$CC -I../include -DMBEDTLS_RELAXED_X509_DATE \ - $PLATFORM_FLAGS $(lto_flags $c) $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c $c" - echo $CMD - $CMD -done - -# create archive -cd $DIST -mkdir library -$AR library/libmbedtls.a $SRC/library/*.o -$RANLIB library/libmbedtls.a 2>&1 | grep -v "has no symbols" || true - -# copy headers -mkdir -p include/mbedtls -cp $SRC/include/mbedtls/*.h include/mbedtls/ -exit 0 diff --git a/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch b/deps/vcpkg-ports/asio/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch similarity index 83% rename from deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch rename to deps/vcpkg-ports/asio/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch index becea4edd..eef60336e 100644 --- a/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch +++ b/deps/vcpkg-ports/asio/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch @@ -1,8 +1,8 @@ -From 00c0b1b7076ebc24735071f587f9501c1595a02b Mon Sep 17 00:00:00 2001 +From 3152d98dec56afe201a4055880632017e0d4d51e Mon Sep 17 00:00:00 2001 From: James Yonan Date: Mon, 19 Mar 2018 11:24:10 +0800 -Subject: [PATCH] Added Apple NAT64 support when both ASIO_HAS_GETADDRINFO and - ASIO_APPLE_NAT64 ar defined +Subject: [PATCH 1/6] Added Apple NAT64 support when both ASIO_HAS_GETADDRINFO + and ASIO_APPLE_NAT64 ar defined * When calling getaddrinfo(), Apple recommends to set AI_DEFAULT flags in hint. @@ -11,15 +11,17 @@ Subject: [PATCH] Added Apple NAT64 support when both ASIO_HAS_GETADDRINFO and non-zero scope ID for non-link-local addresses. Workaround by forcing scope ID to 0 for non-link-local addresses. + +Signed-off-by: Frank Lichtenheld --- asio/include/asio/detail/impl/socket_ops.ipp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/asio/include/asio/detail/impl/socket_ops.ipp b/asio/include/asio/detail/impl/socket_ops.ipp -index ad203b74..b17a60ed 100644 +index e4699a6b1..e69775c0a 100644 --- a/asio/include/asio/detail/impl/socket_ops.ipp +++ b/asio/include/asio/detail/impl/socket_ops.ipp -@@ -3339,6 +3339,23 @@ asio::error_code getaddrinfo(const char* host, +@@ -3811,6 +3811,23 @@ asio::error_code getaddrinfo(const char* host, # endif #elif !defined(ASIO_HAS_GETADDRINFO) int error = getaddrinfo_emulation(host, service, &hints, result); @@ -44,5 +46,5 @@ index ad203b74..b17a60ed 100644 #else int error = ::getaddrinfo(host, service, &hints, result); -- -2.21.0 +2.34.1 diff --git a/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch b/deps/vcpkg-ports/asio/0002-Added-user-code-hook-async_connect_post_open-to-be-c.patch similarity index 65% rename from deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch rename to deps/vcpkg-ports/asio/0002-Added-user-code-hook-async_connect_post_open-to-be-c.patch index beeab24a6..5b264f6a7 100644 --- a/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch +++ b/deps/vcpkg-ports/asio/0002-Added-user-code-hook-async_connect_post_open-to-be-c.patch @@ -1,27 +1,28 @@ -From 5e0153dd0826185575242fe594dac4777874c433 Mon Sep 17 00:00:00 2001 +From 642d7e371ef02cbb1f4f28c6ae7fa2b27a3f9c37 Mon Sep 17 00:00:00 2001 From: James Yonan Date: Mon, 27 Feb 2017 13:01:26 -0700 -Subject: [PATCH] Added user code hook async_connect_post_open() to be called - immediately after socket open in async_connect. +Subject: [PATCH 2/6] Added user code hook async_connect_post_open() to be + called immediately after socket open in async_connect. +Signed-off-by: Frank Lichtenheld --- asio/include/asio/basic_socket.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/asio/include/asio/basic_socket.hpp b/asio/include/asio/basic_socket.hpp -index 29986a02..000e5154 100644 +index 1ff7ecf25..55248c72d 100644 --- a/asio/include/asio/basic_socket.hpp +++ b/asio/include/asio/basic_socket.hpp -@@ -983,6 +983,8 @@ public: +@@ -975,6 +975,8 @@ public: { const protocol_type protocol = peer_endpoint.protocol(); impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); + if (!open_ec) -+ async_connect_post_open(protocol, open_ec); ++ async_connect_post_open(protocol, open_ec); } return async_initiate( -@@ -1841,7 +1843,7 @@ protected: +@@ -1830,7 +1832,7 @@ protected: * This function destroys the socket, cancelling any outstanding asynchronous * operations associated with the socket as if by calling @c cancel. */ @@ -30,7 +31,7 @@ index 29986a02..000e5154 100644 { } -@@ -1860,6 +1862,11 @@ protected: +@@ -1849,6 +1851,11 @@ protected: #endif private: @@ -40,5 +41,8 @@ index 29986a02..000e5154 100644 + } + // Disallow copying and assignment. - basic_socket(const basic_socket&) ASIO_DELETED; - basic_socket& operator=(const basic_socket&) ASIO_DELETED; + basic_socket(const basic_socket&) = delete; + basic_socket& operator=(const basic_socket&) = delete; +-- +2.34.1 + diff --git a/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch b/deps/vcpkg-ports/asio/0003-error_code.ipp-Use-English-for-Windows-error-message.patch similarity index 80% rename from deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch rename to deps/vcpkg-ports/asio/0003-error_code.ipp-Use-English-for-Windows-error-message.patch index 81693de8e..59cc6e75f 100644 --- a/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch +++ b/deps/vcpkg-ports/asio/0003-error_code.ipp-Use-English-for-Windows-error-message.patch @@ -1,18 +1,19 @@ -From af733fe9ce8345e06947dcf8b395d4736b1cb98c Mon Sep 17 00:00:00 2001 +From b4a8d9dfc1ea8f2ba9d5545f3ebe9b5d4460876f Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Mon, 29 Apr 2019 10:26:13 +0300 -Subject: [PATCH] error_code.ipp: Use English for Windows error messages +Subject: [PATCH 3/6] error_code.ipp: Use English for Windows error messages FormatMessageA doesn't work well with non-ASCII chars so make it return error message in English. Signed-off-by: Lev Stipakov +Signed-off-by: Frank Lichtenheld --- asio/include/asio/impl/error_code.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asio/include/asio/impl/error_code.ipp b/asio/include/asio/impl/error_code.ipp -index 55f5b361..3ef34fcd 100644 +index 4ab017051..0747c8e6d 100644 --- a/asio/include/asio/impl/error_code.ipp +++ b/asio/include/asio/impl/error_code.ipp @@ -80,7 +80,7 @@ public: @@ -25,5 +26,5 @@ index 55f5b361..3ef34fcd 100644 if (length && msg[length - 1] == '\n') msg[--length] = '\0'; -- -2.16.2.windows.1 +2.34.1 diff --git a/deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch b/deps/vcpkg-ports/asio/0004-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch similarity index 83% rename from deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch rename to deps/vcpkg-ports/asio/0004-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch index a3860979e..e8c0d99ef 100644 --- a/deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch +++ b/deps/vcpkg-ports/asio/0004-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch @@ -1,20 +1,22 @@ -From df7759c141a31159d0ca4267b63f64dfd2a385b1 Mon Sep 17 00:00:00 2001 +From d9a37d216adc73cd8a7e94e2b9aceed12dd77985 Mon Sep 17 00:00:00 2001 From: James Yonan Date: Wed, 27 Jun 2018 23:12:31 -0600 -Subject: Added kovpn route_id support to endpoints for sendto/recvfrom. +Subject: [PATCH 4/6] Added kovpn route_id support to endpoints for + sendto/recvfrom. Signed-off-by: James Yonan +Signed-off-by: Frank Lichtenheld --- - asio/include/asio/ip/basic_endpoint.hpp | 12 ++++++ - asio/include/asio/ip/detail/endpoint.hpp | 55 +++++++++++++++++++++++++++ - asio/include/asio/ip/detail/impl/endpoint.ipp | 12 ++++++ + asio/include/asio/ip/basic_endpoint.hpp | 12 ++++ + asio/include/asio/ip/detail/endpoint.hpp | 55 +++++++++++++++++++ + asio/include/asio/ip/detail/impl/endpoint.ipp | 12 ++++ 3 files changed, 79 insertions(+) diff --git a/asio/include/asio/ip/basic_endpoint.hpp b/asio/include/asio/ip/basic_endpoint.hpp -index 4418ee7..179a021 100644 +index eff8e3572..e9b3401bc 100644 --- a/asio/include/asio/ip/basic_endpoint.hpp +++ b/asio/include/asio/ip/basic_endpoint.hpp -@@ -185,6 +185,18 @@ public: +@@ -187,6 +187,18 @@ public: impl_.address(addr); } @@ -32,9 +34,9 @@ index 4418ee7..179a021 100644 + /// Compare two endpoints for equality. friend bool operator==(const basic_endpoint& e1, - const basic_endpoint& e2) ASIO_NOEXCEPT + const basic_endpoint& e2) noexcept diff --git a/asio/include/asio/ip/detail/endpoint.hpp b/asio/include/asio/ip/detail/endpoint.hpp -index 9acefe5..7ba5983 100644 +index 82fbf7678..4816cb7c0 100644 --- a/asio/include/asio/ip/detail/endpoint.hpp +++ b/asio/include/asio/ip/detail/endpoint.hpp @@ -24,6 +24,11 @@ @@ -49,7 +51,7 @@ index 9acefe5..7ba5983 100644 namespace asio { namespace ip { namespace detail { -@@ -116,6 +121,47 @@ public: +@@ -118,6 +123,47 @@ public: ASIO_DECL std::string to_string() const; #endif // !defined(ASIO_NO_IOSTREAM) @@ -97,8 +99,8 @@ index 9acefe5..7ba5983 100644 private: // The underlying IP socket address. union data_union -@@ -123,6 +169,15 @@ private: - asio::detail::socket_addr_type base; +@@ -129,6 +175,15 @@ private: + #endif // defined(_FORTIFY_SOURCE) asio::detail::sockaddr_in4_type v4; asio::detail::sockaddr_in6_type v6; +#if defined(ASIO_USE_KOVPN_ROUTE_ID) @@ -114,10 +116,10 @@ index 9acefe5..7ba5983 100644 }; diff --git a/asio/include/asio/ip/detail/impl/endpoint.ipp b/asio/include/asio/ip/detail/impl/endpoint.ipp -index 304bdf3..a72fefc 100644 +index 55ad31fea..a4dc165b1 100644 --- a/asio/include/asio/ip/detail/impl/endpoint.ipp +++ b/asio/include/asio/ip/detail/impl/endpoint.ipp -@@ -37,6 +37,10 @@ endpoint::endpoint() +@@ -37,6 +37,10 @@ endpoint::endpoint() noexcept data_.v4.sin_family = ASIO_OS_DEF(AF_INET); data_.v4.sin_port = 0; data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); @@ -127,8 +129,8 @@ index 304bdf3..a72fefc 100644 +#endif } - endpoint::endpoint(int family, unsigned short port_num) ASIO_NOEXCEPT -@@ -49,6 +53,10 @@ endpoint::endpoint(int family, unsigned short port_num) + endpoint::endpoint(int family, unsigned short port_num) noexcept +@@ -49,6 +53,10 @@ endpoint::endpoint(int family, unsigned short port_num) noexcept data_.v4.sin_port = asio::detail::socket_ops::host_to_network_short(port_num); data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); @@ -151,5 +153,5 @@ index 304bdf3..a72fefc 100644 else { -- -2.7.4 +2.34.1 diff --git a/deps/vcpkg-ports/asio/0005-basic_resolver_results-added-data-and-cdata-members-.patch b/deps/vcpkg-ports/asio/0005-basic_resolver_results-added-data-and-cdata-members-.patch new file mode 100644 index 000000000..fb6c9665d --- /dev/null +++ b/deps/vcpkg-ports/asio/0005-basic_resolver_results-added-data-and-cdata-members-.patch @@ -0,0 +1,48 @@ +From b6aa5d5e4c5722425e1cc38aba8ae516a908d9cf Mon Sep 17 00:00:00 2001 +From: James Yonan +Date: Wed, 2 Sep 2015 12:18:48 -0700 +Subject: [PATCH 5/6] basic_resolver_results: added data() and cdata() members + for access to underlying storage vector + +Signed-off-by: James Yonan +Signed-off-by: Frank Lichtenheld +--- + asio/include/asio/ip/basic_resolver_results.hpp | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp +index 3b68fd55a..ebedccfc6 100644 +--- a/asio/include/asio/ip/basic_resolver_results.hpp ++++ b/asio/include/asio/ip/basic_resolver_results.hpp +@@ -18,6 +18,7 @@ + #include "asio/detail/config.hpp" + #include + #include ++#include + #include "asio/detail/socket_ops.hpp" + #include "asio/detail/socket_types.hpp" + #include "asio/ip/basic_resolver_iterator.hpp" +@@ -291,6 +292,20 @@ public: + return !a.equal(b); + } + ++#define HAVE_ASIO_RESOLVER_RESULTS_DATA ++ ++ /// Return a pointer to the underlying results vector. ++ auto* data() ++ { ++ return this->values_.get(); ++ } ++ ++ /// Return a const pointer to the underlying results vector. ++ const auto* cdata() const ++ { ++ return this->values_.get(); ++ } ++ + private: + typedef std::vector> values_type; + }; +-- +2.34.1 + diff --git a/deps/asio/patches/0007-reactive_socker_service_base-make-sure-reactor_data_.patch b/deps/vcpkg-ports/asio/0006-reactive_socket_service_base-add-constructor-for-bas.patch similarity index 91% rename from deps/asio/patches/0007-reactive_socker_service_base-make-sure-reactor_data_.patch rename to deps/vcpkg-ports/asio/0006-reactive_socket_service_base-add-constructor-for-bas.patch index 6abaa2dd3..e5a47f659 100644 --- a/deps/asio/patches/0007-reactive_socker_service_base-make-sure-reactor_data_.patch +++ b/deps/vcpkg-ports/asio/0006-reactive_socket_service_base-add-constructor-for-bas.patch @@ -1,7 +1,7 @@ -From f54cab5d37d9ee604d42c9d1b056c7a6efc2bd4a Mon Sep 17 00:00:00 2001 +From cbe3c93e979615f61e24415067781fa6f0764007 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Mon, 20 Dec 2021 13:36:01 +0100 -Subject: [PATCH] reactive_socket_service_base: add constructor for +Subject: [PATCH 6/6] reactive_socket_service_base: add constructor for basic_implementation_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -25,7 +25,7 @@ Signed-off-by: Frank Lichtenheld 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/asio/include/asio/detail/reactive_socket_service.hpp b/asio/include/asio/detail/reactive_socket_service.hpp -index 185810e8..6023945b 100644 +index 9466ca77d..da168e3e9 100644 --- a/asio/include/asio/detail/reactive_socket_service.hpp +++ b/asio/include/asio/detail/reactive_socket_service.hpp @@ -65,7 +65,8 @@ public: @@ -39,7 +39,7 @@ index 185810e8..6023945b 100644 } diff --git a/asio/include/asio/detail/reactive_socket_service_base.hpp b/asio/include/asio/detail/reactive_socket_service_base.hpp -index c67297fc..3b8d7f60 100644 +index 1e85374f2..aa5339572 100644 --- a/asio/include/asio/detail/reactive_socket_service_base.hpp +++ b/asio/include/asio/detail/reactive_socket_service_base.hpp @@ -54,6 +54,14 @@ public: @@ -58,5 +58,5 @@ index c67297fc..3b8d7f60 100644 socket_type socket_; -- -2.30.2 +2.34.1 diff --git a/deps/vcpkg-ports/asio/CMakeLists.txt b/deps/vcpkg-ports/asio/CMakeLists.txt index 6bdb490ba..ffbc3c7c7 100644 --- a/deps/vcpkg-ports/asio/CMakeLists.txt +++ b/deps/vcpkg-ports/asio/CMakeLists.txt @@ -1,28 +1,39 @@ -cmake_minimum_required(VERSION 3.8) -project(asio) - -add_library(asio INTERFACE) - -# Export target -install(TARGETS asio - EXPORT asio - INCLUDES DESTINATION include/ -) - -install(EXPORT asio - DESTINATION "share/asio" - FILE asio-targets.cmake -) - -install(DIRECTORY - asio/include/asio - DESTINATION include/ - FILES_MATCHING - PATTERN "*.hpp" - PATTERN "*.ipp" -) - -install(FILES - asio/include/asio.hpp - DESTINATION include/ -) +cmake_minimum_required(VERSION 3.10) +project(asio) + +add_library(asio INTERFACE) + +find_package(Threads) +if(Threads_FOUND) + target_link_libraries(asio INTERFACE Threads::Threads) +endif() + +# Export target +install(TARGETS asio + EXPORT asio + INCLUDES DESTINATION include/ +) + +install(EXPORT asio + DESTINATION "share/asio" + FILE asio-targets.cmake + NAMESPACE asio:: +) + +install(DIRECTORY + asio/include/asio + DESTINATION include/ + FILES_MATCHING + PATTERN "*.hpp" + PATTERN "*.ipp" +) + +install(FILES + asio/include/asio.hpp + DESTINATION include/ +) + +set(exec_prefix [[${prefix}]]) +set(package_name [[asio]]) +configure_file(asio/asio.pc.in "${PROJECT_BINARY_DIR}/asio.pc" @ONLY) +install(FILES "${PROJECT_BINARY_DIR}/asio.pc" DESTINATION share/pkgconfig) diff --git a/deps/vcpkg-ports/asio/asio-config.cmake b/deps/vcpkg-ports/asio/asio-config.cmake index dec682e17..b916a0093 100644 --- a/deps/vcpkg-ports/asio/asio-config.cmake +++ b/deps/vcpkg-ports/asio/asio-config.cmake @@ -1,9 +1,9 @@ -include ("${CMAKE_CURRENT_LIST_DIR}/asio-targets.cmake") - -if(NOT TARGET asio::asio) - add_library(asio::asio INTERFACE IMPORTED) - target_link_libraries(asio::asio INTERFACE asio) -endif() - -get_target_property(_ASIO_INCLUDE_DIR asio INTERFACE_INCLUDE_DIRECTORIES) -set(ASIO_INCLUDE_DIR "${_ASIO_INCLUDE_DIR}") +find_package(Threads) + +include("${CMAKE_CURRENT_LIST_DIR}/asio-targets.cmake") + +if(NOT TARGET asio) + add_library(asio ALIAS asio::asio) +endif() + +get_target_property(ASIO_INCLUDE_DIR asio::asio INTERFACE_INCLUDE_DIRECTORIES) diff --git a/deps/vcpkg-ports/asio/portfile.cmake b/deps/vcpkg-ports/asio/portfile.cmake index cce8fad09..5afe98cca 100644 --- a/deps/vcpkg-ports/asio/portfile.cmake +++ b/deps/vcpkg-ports/asio/portfile.cmake @@ -1,38 +1,34 @@ -#header-only library +set(VCPKG_BUILD_TYPE release) # header-only +string(REPLACE "." "-" ref "asio-${VERSION}") vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO chriskohlhoff/asio - REF asio-1-24-0 - SHA512 a5d6e597e5611b7293375965f37c09cb73e27639ebdda6163557fab8bbff2ddbb301080ad86ff7f97e8ed8454da25176385cfc43103447a4a04e35a9c41aec3e + REF "${ref}" + SHA512 d44b35d9d1900de35aa10bf339c7e16a06e110377fd70fbefba91599d24cff32cc3dc88a4b0bf1e1706f9ac46177982edb5c7f969b72a57123be6550a3b062d8 HEAD_REF master PATCHES - ../../asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch - ../../asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch - ../../asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch - ../../asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch - ../../asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch - ../../asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch - ../../asio/patches/0007-reactive_socker_service_base-make-sure-reactor_data_.patch + 0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch + 0002-Added-user-code-hook-async_connect_post_open-to-be-c.patch + 0003-error_code.ipp-Use-English-for-Windows-error-message.patch + 0004-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch + 0005-basic_resolver_results-added-data-and-cdata-members-.patch + 0006-reactive_socket_service_base-add-constructor-for-bas.patch ) +file(COPY "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" DESTINATION "${SOURCE_PATH}") # Always use "ASIO_STANDALONE" to avoid boost dependency vcpkg_replace_string("${SOURCE_PATH}/asio/include/asio/detail/config.hpp" "defined(ASIO_STANDALONE)" "!defined(VCPKG_DISABLE_ASIO_STANDALONE)") -# CMake install -file(COPY "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt" DESTINATION "${SOURCE_PATH}") vcpkg_cmake_configure( SOURCE_PATH "${SOURCE_PATH}" - + OPTIONS + -DPACKAGE_VERSION=${VERSION} ) vcpkg_cmake_install() - +vcpkg_fixup_pkgconfig() + vcpkg_cmake_config_fixup() -file(INSTALL - "${CMAKE_CURRENT_LIST_DIR}/asio-config.cmake" - DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" -) -file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug") +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/asio-config.cmake" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") -# Handle copyright -file(INSTALL "${SOURCE_PATH}/asio/LICENSE_1_0.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/asio/LICENSE_1_0.txt") diff --git a/deps/vcpkg-ports/asio/vcpkg.json b/deps/vcpkg-ports/asio/vcpkg.json index b3608e5a0..533326088 100644 --- a/deps/vcpkg-ports/asio/vcpkg.json +++ b/deps/vcpkg-ports/asio/vcpkg.json @@ -1,9 +1,9 @@ { "name": "asio", - "version": "1.24.0", + "version": "1.36.0", "description": "Asio is a cross-platform C++ library for network and low-level I/O programming that provides developers with a consistent asynchronous model using a modern C++ approach.", - "homepage": "https://github.com/chriskohlhoff/asio", - "documentation": "https://think-async.com/Asio/asio-1.24.0/doc/", + "homepage": "https://think-async.com/Asio/", + "documentation": "https://think-async.com/Asio/Documentation.html", "license": "BSL-1.0", "dependencies": [ { diff --git a/deps/vcpkg_manifests/mingw/vcpkg.json b/deps/vcpkg_manifests/mingw/vcpkg.json index 1d878b4c1..f56d00edc 100644 --- a/deps/vcpkg_manifests/mingw/vcpkg.json +++ b/deps/vcpkg_manifests/mingw/vcpkg.json @@ -1,9 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "openvpn3", - "version-string": "3.8", + "version-string": "3.11", "dependencies": [ "asio", + "fmt", "jsoncpp", "lz4", "openssl", diff --git a/deps/vcpkg_manifests/windows/vcpkg.json b/deps/vcpkg_manifests/windows/vcpkg.json index 8d980c811..34e2e5259 100644 --- a/deps/vcpkg_manifests/windows/vcpkg.json +++ b/deps/vcpkg_manifests/windows/vcpkg.json @@ -1,9 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "openvpn3", - "version-string": "3.8", + "version-string": "3.11", "dependencies": [ "asio", + "fmt", "gtest", "jsoncpp", "lz4", diff --git a/deps/xxHash/build-xxHash b/deps/xxHash/build-xxHash deleted file mode 100755 index fdde9debc..000000000 --- a/deps/xxHash/build-xxHash +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -# https://github.com/Cyan4973/xxHash/archive/v0.8.0.tar.gz - -PACKAGE=${XXHASH_VERSION} -FNAME=xxHash-${XXHASH_VERSION}.tar.gz -URL=https://github.com/Cyan4973/xxHash/archive/v${XXHASH_VERSION}.tar.gz -CSUM=${XXHASH_CSUM} -DIST=xxHash - -download - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source -else - echo WIPE and reunzip source - cd $DEP_DIR - rm -rf $DIST xxHash-${XXHASH_VERSION} - tar xfz $DL/$FNAME - cd xxHash-${XXHASH_VERSION} - - cd .. - - cp -a xxHash-${XXHASH_VERSION} $DIST -fi diff --git a/doc/core.md b/doc/core.md deleted file mode 100644 index 4d2c8d5f8..000000000 --- a/doc/core.md +++ /dev/null @@ -1,195 +0,0 @@ -# OpenVPN 3 Core Library - -*This document is a work in progress. Eventually it should either grow to encompass all of -the OpenVPN 3 core library or it should be incorporated into a different core library doc.* - -# Crypto Support - SSLAPI - -The primary TLS/SSL abstraction in OpenVPN 3 core is `SSLAPI`. This interface implements a memory buffer -based TLS state machine. It includes member functions that allow the read and write of both ciphertext -and plaintext. This allows the encyphering and decyphering operations to be done separately from any -data transport operations. - -## Interface - -The `SSLAPI` interface is defined in `class SSLAPI` and currently looks like this: - - virtual void start_handshake() = 0; - virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) = 0; - virtual ssize_t read_cleartext(void *data, const size_t capacity) = 0; - virtual bool read_cleartext_ready() const = 0; - virtual void write_ciphertext(const BufferPtr &buf) = 0; - virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) = 0; - virtual bool read_ciphertext_ready() const = 0; - virtual BufferPtr read_ciphertext() = 0; - virtual std::string ssl_handshake_details() const = 0; - virtual bool export_keying_material(const std::string &label, unsigned char *dest, size_t size) = 0; - virtual bool did_full_handshake() = 0; - virtual const AuthCert::Ptr &auth_cert() const = 0; - virtual void mark_no_cache() = 0; - uint32_t get_tls_warnings() const - -This interface will be documented via doxygen markup. - -## Instance Creation - -To create an instance of an object implementing this interface a few steps must be taken. First, pull in the -required headers. The unit tests, found in ovpn3/core/test/unittests in test_sslctx.cpp and a few other -places, can provide examples. Next one must create a configuration object, which is derived from the -`class SSLConfigAPI` interface. - - virtual void set_mode(const Mode &mode_arg) = 0; - virtual const Mode &get_mode() const = 0; - virtual void set_external_pki_callback(ExternalPKIBase *external_pki_arg) = 0; - virtual void set_session_ticket_handler(TLSSessionTicketBase *session_ticket_handler) = 0; - virtual void set_client_session_tickets(const bool v) = 0; - virtual void enable_legacy_algorithms(const bool v) = 0; - virtual void set_sni_handler(SNI::HandlerBase *sni_handler) = 0; - virtual void set_sni_name(const std::string &sni_name_arg) = 0; - virtual void set_private_key_password(const std::string &pwd) = 0; - virtual void load_ca(const std::string &ca_txt, bool strict) = 0; - virtual void load_crl(const std::string &crl_txt) = 0; - virtual void load_cert(const std::string &cert_txt) = 0; - virtual void load_cert(const std::string &cert_txt, const std::string &extra_certs_txt) = 0; - virtual void load_private_key(const std::string &key_txt) = 0; - virtual void load_dh(const std::string &dh_txt) = 0; - virtual std::string extract_ca() const = 0; - virtual std::string extract_crl() const = 0; - virtual std::string extract_cert() const = 0; - virtual std::vector extract_extra_certs() const = 0; - virtual std::string extract_private_key() const = 0; - virtual std::string extract_dh() const = 0; - virtual PKType::Type private_key_type() const = 0; - virtual size_t private_key_length() const = 0; - virtual void set_frame(const Frame::Ptr &frame_arg) = 0; - virtual void set_debug_level(const int debug_level) = 0; - virtual void set_flags(const unsigned int flags_arg) = 0; - virtual void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) = 0; - virtual void set_remote_cert_tls(const KUParse::TLSWebType wt) = 0; - virtual void set_tls_remote(const std::string &tls_remote_arg) = 0; - virtual void set_tls_version_min(const TLSVersion::Type tvm) = 0; - virtual void set_tls_version_min_override(const std::string &override) = 0; - virtual void set_tls_cert_profile(const TLSCertProfile::Type type) = 0; - virtual void set_tls_cert_profile_override(const std::string &override) = 0; - virtual void set_local_cert_enabled(const bool v) = 0; - virtual void set_x509_track(X509Track::ConfigSet x509_track_config_arg) = 0; - virtual void set_rng(const StrongRandomAPI::Ptr &rng_arg) = 0; - virtual void load(const OptionList &opt, const unsigned int lflags) = 0; - virtual std::string validate_cert(const std::string &cert_txt) const = 0; - virtual std::string validate_cert_list(const std::string &certs_txt) const = 0; - virtual std::string validate_crl(const std::string &crl_txt) const = 0; - virtual std::string validate_private_key(const std::string &key_txt) const = 0; - virtual std::string validate_dh(const std::string &dh_txt) const = 0; - virtual SSLFactoryAPI::Ptr new_factory() = 0; - -This interface will be documented via doxygen markup. - -Each supported SSL provider implementation provides a class derived from `SSLConfigAPI`, typically aliased -as `SSLLib::SSLAPI::Config` if one includes the helpful header sslchoose.hpp, which, with proper build time -definitions, will select the SSL provider for the current environment. For example: - - #include - #include - - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; - -Once the `config` object has been instantiated as above, it must be initialized, for example: - - config->set_mode(Mode(Mode::CLIENT)); - config->load_cert(cert_txt); - config->load_private_key(pvt_key_txt); - config->load_ca(cert_txt, false); - -*Note: Behavior from SSL provider to provider will vary a bit, see the unit tests for more sample code.* - -The _txt symbols are PEM encoded certificates and keys. Once all the options are set, the config -instance is ready to be used to produce a factory instance: - - auto factory = config->new_factory(); - -Note that use of `auto` is safe here since `new_factory` returns a `openvpn::SSLFactoryAPI::Ptr` and -not a raw C++ pointer as `new` did for the `SSLLib::SSLAPI::Config` previously. - -Once the factory is instantiated it may be used to create an instance of an SSLAPI implementation -as follows: - - auto sslapi = factory->ssl(); - -The SSLAPI instance is now ready for use. The factory and configuration both maintain some state information -that the SSLAPI instance requires to function properly so those must have their lifetime extended to at least -as long as the SSLAPI object is in use. - -The `new_factory()` and `ssl()` member functions both return a reference counted smart pointer, so cleanup -of those resources will occur when that pointer and all assigned from it go out of scope. The example code -above also assigns the new config to a smart pointer, which works properly since the config type is -reference count enabled. - -## Wrappers and Helpers - -*TODO* - -## External PKI - -*TODO* - -# App Control Channel - -*TODO* - -## Protocol - -*TODO* - -## Device Management - -*TODO* - -### Device Verification Certificate Check - -The device verification certificate check is intended to provide customers with a means to -ensure the connecting device is the same device as was originally provisioned by the -controlling organization. This is done by routing a normal TLS handshake via the -AppControlChannel plumbing using a set of certs and keys that are meant to be tamper -resistant to a greater degree than the certs we use to connect the tunnel. - -To implement this functionality several modules have been created: - -- SslApiBuilder in ovpn3/core/openvpn/client/acc_certcheck.hpp implements a wrapper that -instantiates and owns the SSLAPI object and the prerequisites it requires. It accepts a -ref counted pointer to the SSLLib::SSLAPI::Config object that has been initialized for the -desired functionality. It might be useful outside it's use in the handshaker at some point, -and if so we can move it to its own header. -- AccHandshaker uses SslApiBuilder and implements the read/write logic required to perform -the handshake operation. -- ClientProto::Session::ProtoContext has been extended with a member of type AccHandshaker -and gains a few member functions to glue the ACC certcheck traffic into the AccHandshaker -read / write logic. This is all hidden inside ProtoContest and should be of little concern -to users of the functionality. The only exposed API (start_acc_certcheck) is not really -for direct client use but is rather called by a more exposed interface in another class. -Member start_acc_certcheck does set up the handshake logic and then sends the start of the -client hello upstream via the ACC when it's called via the ProtoContext interface. -- ClientAPI::OpenVPNClient gains a member function 'start_cert_check' which delegates via a -few layers of abstraction to eventually call CliProto::Session::ProtoContext::start_acc_certcheck, -which as discussed before will configure the handshake mechanism and then begins the handshake -process. The server side should ensure it is ready for the handshake before directing the -connected client app to start. - -For the MVP the start_cert_check API accepts encoded certs and keys as std::string, in PEM format: - - class OpenVPNClient ... - - void start_cert_check(const std::string &client_cert, - const std::string &clientkey, - const std::optional &ca = std::nullopt); - -Alternatively one can use the EPKI enabled API: - - void start_cert_check_epki(const std::string &alias); - -Both found in ovpn3/core/client/ovpncli.hpp - -Unit tests for the various subsystems can be found here: ovpn3/core/test/unittests/test_acc_certcheck.cpp - -Note: The assurance provided by this feature is limited by the security of the certificate storage employed. - - diff --git a/doc/developer_guide.md b/doc/developer_guide.md new file mode 100644 index 000000000..29d87d4c9 --- /dev/null +++ b/doc/developer_guide.md @@ -0,0 +1,375 @@ +Developer Guide +--------------- + +OpenVPN 3 is written in C++20 and developers who are moving from C to +C++ should take some time to familiarize themselves with key C++ design +patterns such as +[*RAII*](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization). + + +OpenVPN 3 Client Core +===================== + +OpenVPN 3 is designed as a class library, with an API that is +essentially defined inside of **namespace openvpn::ClientAPI** with headers and +implementation in `client/` and header-only library files under `openvpn/`. + +The concise definition of the client API is essentially +**class openvpn::ClientAPI::OpenVPNClient** in with +several important extensions to the API found in: + +- **class openvpn::TunBuilderBase** --- + Provides an abstraction layer defining the *tun* interface, and is + especially useful for interfacing with an OS-layer VPN API. +- **class openvpn::ExternalPKIBase** --- Provides a + callback for external private key operations, and is useful for + interfacing with an OS-layer Keychain such as the Keychain on iOS, + Mac OS X, and Android, and the Crypto API on Windows. +- **class openvpn::ClientAPI::LogReceiver** --- + Provides an abstraction layer for the delivery of logging messages. + +OpenVPN 3 includes a command-line reference client (`cli`) for testing +the API. See test/ovpncli/cli.cpp. + +The basic approach to building an OpenVPN 3 client is to define a client +class that derives from openvpn::ClientAPI::OpenVPNClient, then provide +implementations for callbacks including event and logging notifications: + + class Client : public ClientAPI::OpenVPNClient + { + public: + void event(const Event&) override { // events delivered here + ... + } + void log(const LogInfo&) override { // logging delivered here + ... + } + + ... + }; + +To start the client, first create a openvpn::ProtoContext::ProtoConfig object and +initialize it with the OpenVPN config file and other options: + + ProtoContext::ProtoConfig config; + config.content = ; + ... + +Next, create a client object and evaluate the configuration: + + Client client; + ClientAPI::EvalConfig eval = client.eval_config(config); + if (eval.error) + throw ...; + +Finally, in a new worker thread, start the connection: + + ClientAPI::Status connect_status = client.connect(); + +Note that `client.connect()` will not return until the session has +terminated. + +## Top Layer + +The top layer of the OpenVPN 3 client is implemented in +test/ovpncli/cli.cpp and openvpn/client/cliopt.hpp. Most of what +this code does is marshalling the configuration and dispatching the +higher-level objects that implement the OpenVPN client session. + +## Connection + +**class openvpn::ClientConnect** +implements the top-level connection logic for an OpenVPN client +connection. It is concerned with starting, stopping, pausing, and +resuming OpenVPN client connections. It deals with retrying a connection +and handles the connection timeout. It also deals with connection +exceptions and understands the difference between an exception that +should halt any further reconnection attempts (such as `AUTH_FAILED`), +and other exceptions such as network errors that would justify a retry. + +Some of the methods in the class (such as `stop`, `pause`, and +`reconnect`) are often called by another thread that is controlling the +connection, therefore thread-safe methods are provided where the +thread-safe function posts a message to the actual connection thread. + +In an OpenVPN client connection, the following object stack would be +used: + +1. **class openvpn::ClientConnect** --- + The top-layer object in an OpenVPN client connection. +2. **class openvpn::ClientProto::Session** --- The + OpenVPN client protocol object that subinstantiates the transport + and tun layer objects. +3. **class openvpn::ProtoContext** --- The core OpenVPN + protocol implementation that is common to both client and server. +4. **openvpn::ProtoStackBase** (with **openvpn::ProtoContext::Packet**) --- + The bottom-layer class that implements the basic functionality of + tunneling a protocol over a reliable or unreliable transport layer, + but isn't specific to OpenVPN per-se. + +## Transport Layer + +OpenVPN 3 defines abstract base classes for Transport layer +implementations in openvpn/transport/client/transbase.hpp. + +Currently, transport layer implementations are provided for: + +- **UDP** --- openvpn/transport/client/udpcli.hpp +- **TCP** --- openvpn/transport/client/tcpcli.hpp +- **HTTP Proxy** --- openvpn/transport/client/httpcli.hpp + +## Tun Layer + +OpenVPN 3 defines abstract base classes for Tun layer implementations in +openvpn/tun/client/tunbase.hpp. + +There are two possible approaches to define a Tun layer implementation: + +1. Use a VPN API-centric model (such as for Android or iOS). These + models derive from **class openvpn::TunBuilderBase**. +2. Use an OS-specific model such as: + - **Linux** --- openvpn/tun/linux/client/tuncli.hpp + - **Windows** --- openvpn/tun/win/client/tuncli.hpp + - **Mac OS X** --- openvpn/tun/mac/client/tuncli.hpp + +## Protocol Layer + +The OpenVPN protocol is implemented in **class openvpn::ProtoContext**. + +## Options Processing + +The parsing and query of the OpenVPN config file is implemented by +**class openvpn::OptionList**. + +Note that OpenVPN 3 always assumes an *inline* style of configuration, +where all certs, keys, etc. are defined inline rather than through an +external file reference. + +For config files that do use external file references, +**class openvpn::ProfileMerge** is provided to +merge those external file references into an inline form. + +## Calling the Client API from other languages + +The OpenVPN 3 client API, as defined by +**class openvpn::ClientAPI::OpenVPNClient** in +client/ovpncli.hpp, can be wrapped by the +[Swig](http://www.swig.org/) tool to create bindings for other +languages. + +For example, OpenVPN Connect for Android creates a Java binding of the +API using client/ovpncli.i. + +Crypto Support - SSLAPI +======================= + +The primary TLS/SSL abstraction in OpenVPN 3 core is openvpn::SSLAPI. +This interface implements a memory buffer based TLS state machine. +It includes member functions that allow the read and write of both ciphertext +and plaintext. This allows the encyphering and decyphering operations to be +done separately from any data transport operations. + +## Instance Creation + +To create an instance of an object implementing this interface a few steps must be taken. First, pull in the +required headers. The unit tests, found in test/unittests/test_sslctx.cpp and a few other +places, can provide examples. Next one must create a configuration object, which is derived +from the openvpn::SSLConfigAPI interface. + +Each supported SSL provider implementation provides a class derived from `SSLConfigAPI`, +typically aliased as `SSLLib::SSLAPI::Config` if one includes the helpful header +openvpn/ssl/sslchoose.hpp, which, with proper build time +definitions, will select the SSL provider for the current environment. For example: + + #include + #include + + SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + +Once the `config` object has been instantiated as above, it must be initialized, for example: + + config->set_mode(Mode(Mode::CLIENT)); + config->load_cert(cert_txt); + config->load_private_key(pvt_key_txt); + config->load_ca(cert_txt, false); + +*Note: Behavior from SSL provider to provider will vary a bit, see the unit tests for more +sample code.* + +The `_txt` symbols are PEM encoded certificates and keys. Once all the options are set, +the config instance is ready to be used to produce a factory instance: + + auto factory = config->new_factory(); + +Note that use of `auto` is safe here since `new_factory` returns an +openvpn::SSLFactoryAPI::Ptr and not a raw C++ pointer as `new` did for the +`SSLLib::SSLAPI::Config` previously. + +Once the factory is instantiated it may be used to create an instance of an SSLAPI +implementation as follows: + + auto sslapi = factory->ssl(); + +The SSLAPI instance is now ready for use. The factory and configuration both maintain +some state information that the SSLAPI instance requires to function properly so +those must have their lifetime extended to at least as long as the SSLAPI object is +in use. + +The `new_factory()` and `ssl()` member functions both return a reference counted smart +pointer, so cleanup of those resources will occur when that pointer and all assigned +from it go out of scope. The example code above also assigns the new config to a smart +pointer, which works properly since the config type is reference count enabled. + + +Security +======== + +When developing security software in C++, it's very important to take +advantage of the language and OpenVPN library code to insulate code from +the kinds of bugs that can introduce security vulnerabilities. + +Here is a brief set of guidelines: + +- When dealing with strings, use a `std::string` rather than a + `char *`. When a function only needs to inspect text without taking + ownership, consider using `std::string_view` to avoid unnecessary copies. + +- When dealing with binary data or buffers, always try to use a + openvpn::Buffer, openvpn::ConstBuffer, openvpn::BufferAllocatedRc, + or openvpn::BufferPtr object + to provide managed access to the buffer, to protect against security + bugs that arise when using raw buffer pointers. See + openvpn/buffer/buffer.hpp for the OpenVPN `Buffer` classes. + +- When it's necessary to have a pointer to an object, use + `std::make_unique<>` for non-shared objects and reference-counted + smart pointers for shared objects. For shared-pointers, OpenVPN code + should use the smart pointer classes defined in + openvpn/common/rc.hpp. Please see the + comments in this file for documentation. + +- Never use `malloc` or `free`. When allocating objects, use `std::make_unique` + or `std::make_shared` to allocate the object and create the smart pointer at + the same time: + + auto ptr = std::make_unique(); + ptr->method(); + + This is preferred over using `new` directly. + +- When interfacing with C functions that deal with raw pointers, + memory allocation, etc., consider wrapping the functionality in C++. + For an example, see openvpn::enum_dir(), a function + that returns a list of files in a directory (Unix only) via a + high-level string vector, while internally calling the low level + libc methods `opendir`, `readdir`, and `closedir`. Notice how + `unique_ptr_del` is used to wrap the `DIR` struct in a smart pointer + with a custom deletion function. + +- When grabbing random entropy that is to be used for cryptographic + purposes (i.e. for keys, tokens, etc.), always ensure that the RNG + is crypto-grade by using **class openvpn::StrongRandomAPI** as the RNG type: + + StrongRandomAPI::Ptr rng; + void set_rng(StrongRandomAPI::Ptr rng_arg) { + rng = std::move(rng_arg); + } + +- Any variable whose value is not expected to change should be + declared `const`. When possible, prefer `constexpr`. + +- Don't use non-const global or static variables unless absolutely + necessary. + +- When formatting strings, don't use `snprintf`. Instead, use + `std::ostringstream` or build the string using the `+` `std::string` + operator: + + std::string format_reconnecting(const int n_seconds) { + return "Reconnecting in " + openvpn::to_string(n_seconds) + " seconds."; + } + + or: + + std::string format_reconnecting(const int n_seconds) { + std::ostringstream os; + os << "Reconnecting in " << n_seconds << " seconds."; + return os.str(); + } + +Conventions +=========== + +- Use the **Asio** library for I/O and timers. Don't deal with + sockets directly. + +- Never block. If you need to wait for something, use **Asio** timers + or sockets. + +- Use the OPENVPN_LOG() macro to log stuff. Don't use `printf`. + +- Don't call crypto/ssl libraries directly. Instead use the + abstraction layers CryptoApi (see openvpn/crypto/cryptochoose.hpp) and + openvpn::SSLAPI (see openvpn/ssl/sslchoose.hpp) that allow OpenVPN to + link with different crypto/ssl libraries (such as **OpenSSL** or **mbed + TLS**). + +- Use openvpn::RandomAPI as a wrapper for random number generators. + +- If you need to deal with configuration file options, see + class openvpn::OptionList. + +- If you need to deal with time or time durations, use the classes + under \ref openvpn/time. + +- If you need to deal with IP addresses, see the comprehensive classes + under \ref openvpn/addr. + +- In general, if you need a general-purpose library class or function, + look under \ref openvpn/common. Chances are good that + it's already been implemented. + +- The OpenVPN 3 approach to errors is to count them, rather than + unconditionally log them. If you need to add a new error counter, + see openvpn/error/error.hpp. + +- If you need to create a new event type which can be transmitted as a + notification back to the client API user, see openvpn/client/clievent.hpp. + +- Raw pointers or references can be okay when used by an object to + point back to its parent (or container), if you can guarantee that + the object will not outlive its parent. Backreferences to a parent + object is also a common use case for weak pointers. + +- Use C++ exceptions for error handling and as an alternative to + `goto`. See OpenVPN's general exception classes and macros in + openvpn/common/exception.hpp. + +- Use C++ destructors for automatic object cleanup, and so that thrown + exceptions will not leak objects. Alternatively, use openvpn::Cleanup + when you need to specify a code block to execute prior to scope exit. + For example, ensure that the file `pid_fn` is deleted before scope exit: + + auto clean = Cleanup([pid_fn]() { + if (pid_fn) + ::unlink(pid_fn); + }); + +- When calling global methods (such as libc `fork`), prepend `::` to + the symbol name, e.g.: + + struct dirent *e; + while ((e = ::readdir(dir.get())) != nullptr) { + ... + } + +- Use `nullptr` instead of `NULL`. + +## Threading + +The OpenVPN 3 client core is designed to run in a single thread, with +the UI or controller driving the OpenVPN API running in a different +thread. + +It's almost never necessary to create additional threads within the +OpenVPN 3 client core. diff --git a/doc/feature_overviews.md b/doc/feature_overviews.md new file mode 100644 index 000000000..36f840b5a --- /dev/null +++ b/doc/feature_overviews.md @@ -0,0 +1,61 @@ +# Feature Overview + +*This document is a work in progress. It is intended to give quick pointers for +newly added features.* + +## Device Management + +*TODO: general overview* + +### Device Verification Certificate Check + +The device verification certificate check is intended to provide customers with a means to +ensure the connecting device is the same device as was originally provisioned by the +controlling organization. This is done by routing a normal TLS handshake via the +AppControlChannel plumbing using a set of certs and keys that are meant to be tamper +resistant to a greater degree than the certs we use to connect the tunnel. + +To implement this functionality several modules have been created: + +- openvpn::SslApiBuilder implements a wrapper that instantiates and owns the SSLAPI + object and the prerequisites it requires. It accepts a ref-counted pointer to the + `SSLLib::SSLAPI::Config` object that has been initialized for the desired functionality. + It might be useful outside it's use in the handshaker at some point, and if so we can + move it to its own header. +- openvpn::AccHandshaker uses openvpn::SslApiBuilder and implements the read/write logic + required to perform the handshake operation. +- openvpn::ClientProto::Session has been extended with a member of type + openvpn::AccHandshaker and gains a few member functions to glue the ACC certcheck + traffic into the `AccHandshaker` read/write logic. The + only exposed API (`start_acc_certcheck()`) is not really for direct client use but + is rather called by a more exposed interface in another class. Member + openvpn::ClientProto::Session::start_acc_certcheck() does set up the + handshake logic and then sends the start of the client hello upstream via the ACC + when it's called via the `ProtoContext` interface. +- The `ClientAPI::OpenVPNClient` class gets a new member function + openvpn::ClientAPI::OpenVPNClient::start_cert_check() which + delegates via a few layers of abstraction to eventually call + openvpn::ClientProto::Session::start_acc_certcheck() + which as discussed before will configure the handshake mechanism and then begins + the handshake process. The server side should ensure it is ready for the handshake + before directing the connected client app to start. + +For the MVP the start_cert_check API accepts encoded certs and keys as std::string, in PEM format: + + class OpenVPNClient ... + + void start_cert_check(const std::string &client_cert, + const std::string &clientkey, + const std::optional &ca = std::nullopt); + +Alternatively one can use the EPKI enabled API: + + void start_cert_check_epki(const std::string &alias); + +Both found in client/ovpncli.hpp. + +Unit tests for the various subsystems can be found in +test/unittests/test_acc_certcheck.cpp. + +Note: The assurance provided by this feature is limited by the security of the +certificate storage employed. diff --git a/doc/webauth.md b/doc/webauth.md index a1aeb9814..4cbdbffd3 100644 --- a/doc/webauth.md +++ b/doc/webauth.md @@ -8,7 +8,7 @@ are expect to implement web based mechanisms according to this specification. This document has a three parts: The first focuses web based authentication during connection (AUTH_PENDING). The second describes standardised endpoints for client applications to retrieve a client profile. And final third section -describes a simpler REST based interface that OpenVPN Connect Client and Access Server use to +describes a simpler REST based interface that "OpenVPN Connect Client" and "Access Server" use to download profiles to the client with minimal user interaction. ## OpenVPN web auth protocol during Connect ## @@ -175,7 +175,7 @@ contains the additional parameters like `deviceID` and indicates `tls-cryptv2` s To start the web based method the client should load the url - https://servername/openvpn-api/profile + https://servername/openvpn-api/profile with the following optional parameters: @@ -233,7 +233,7 @@ events. keys. `profile` will contain the ovpn profile and title will have a suggested title for the new profile: - {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile>", "title": ""}} + {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile>", "title": "<title>"}} To allow a client to connect directly after downloading a profile without requiring a web authentication on the first the connect, the two optional keys `vpn-session-user` @@ -241,19 +241,19 @@ events. the first connect. These keys are not base64 encoded (unlike in the REST based download) since JSON has proper escaping: - {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile content>", "vpn-session-user": "foo\'bar", "vpn-session-token": "AT-123456789"}} + {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile content>", "vpn-session-user": "foo\'bar", "vpn-session-token": "AT-123456789"}} The implementation of `vpn-session-token` and `vpn-session-user` is optional but strongly recommended to improve user experience. ### openvpn://import-profile URL ### -To trigger a direct import of a profile in an OpenVPN app an openvpn://import-profile/ +To trigger a direct import of a profile in an OpenVPN app an `openvpn://import-profile/` link can be used. The syntax of the link is openvpn://import-profile/https://server/path/to/profile -The client will try to fetch the profile specified in the https:// URL and offer +The client will try to fetch the profile specified in the `https://` URL and offer the user the option to import the profile. The URL MUST NOT require any additional authentication or require user interaction, e.g. by embedding a session ID or a one time use token. The client MUST check certificates on a HTTPS connection and offer @@ -270,7 +270,7 @@ Any other response is invalid. The response MAY contain the `VPN-Session-User` REST is a simple and more lightweight interface to download profiles. This is currently mainly implemented by OpenVPN Access Server API and Connect clients but can also be implemented by other server and clients. -The endpoint is https://servername/rest/methodname +The endpoint is `https://servername/rest/methodname`. ### Basic API ### @@ -365,12 +365,12 @@ download method. ### Challenge/response authentication ### The challenge/response protocol for the Rest web api mirrors the approach -taken by the old (non using AUTH-PENDING,cr-response) challenge/response +taken by the old (not using `AUTH-PENDING,cr-response`) challenge/response of the OpenVPN protocol. When the server issues a challenge to the authentication request. For example suppose we have a user called 'test' and a password -of 'mypass". Get the OpenVPN config file: +of 'mypass'. Get the OpenVPN config file: curl -u test:mypass https://ACCESS_SERVER/rest/GetUserlogin @@ -384,7 +384,7 @@ we might get a challenge instead: </Error> -a challenge is indicated by the "CRV1:" prefix in the `<Message>` (meaning +a challenge is indicated by the "CRV1:" prefix in the `<%Message>` (meaning Challenge Response protocol Version 1). The CRV1 message is formatted as follows: diff --git a/javacli/.gitignore b/javacli/.gitignore deleted file mode 100644 index 2ae5f4534..000000000 --- a/javacli/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -build -ovpncli_wrap.cxx -ovpncli_wrap.h -ovpncli.java -ovpncliJNI.java -ClientAPI_*.java -SWIGTYPE_*.java diff --git a/javacli/Client.java b/javacli/Client.java deleted file mode 100644 index 76502ca67..000000000 --- a/javacli/Client.java +++ /dev/null @@ -1,133 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -// TESTING_ONLY - -public class Client implements OpenVPNClientThread.EventReceiver { - private OpenVPNClientThread client_thread; - - public static class ConfigError extends Exception { - public ConfigError(String msg) { super(msg); } - } - - public static class CredsUnspecifiedError extends Exception { - public CredsUnspecifiedError(String msg) { super(msg); } - } - - // Load OpenVPN core (implements ClientAPI_OpenVPNClient) from shared library - static { - System.loadLibrary("ovpncli"); - String test = ClientAPI_OpenVPNClient.crypto_self_test(); - System.out.format("CRYPTO SELF TEST: %s", test); - } - - public Client(String config_text, String username, String password) throws ConfigError, CredsUnspecifiedError { - // init client implementation object - client_thread = new OpenVPNClientThread(); - - // load/eval config - ClientAPI_Config config = new ClientAPI_Config(); - config.setContent(config_text); - config.setCompressionMode("yes"); - ClientAPI_EvalConfig ec = client_thread.eval_config(config); - if (ec.getError()) - throw new ConfigError("OpenVPN config file parse error: " + ec.getMessage()); - - // handle creds - ClientAPI_ProvideCreds creds = new ClientAPI_ProvideCreds(); - if (!ec.getAutologin()) - { - if (username.length() > 0) - { - creds.setUsername(username); - creds.setPassword(password); - creds.setReplacePasswordWithSessionID(true); - } - else - throw new CredsUnspecifiedError("OpenVPN config file requires username/password but none provided"); - } - client_thread.provide_creds(creds); - } - - public void connect() { - // connect - client_thread.connect(this); - - // wait for worker thread to exit - client_thread.wait_thread_long(); - } - - public void stop() { - client_thread.stop(); - } - - public void show_stats() { - int n = client_thread.stats_n(); - for (int i = 0; i < n; ++i) - { - String name = client_thread.stats_name(i); - long value = client_thread.stats_value(i); - if (value > 0) - System.out.format("STAT %s=%s%n", name, value); - } - } - - @Override - public void event(ClientAPI_Event event) { - boolean error = event.getError(); - String name = event.getName(); - String info = event.getInfo(); - System.out.format("EVENT: err=%b name=%s info='%s'%n", error, name, info); - } - - // Callback to get a certificate - @Override - public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { - req.setError(true); - req.setErrorText("cert request failed: external PKI not implemented"); - } - - // Callback to sign data - @Override - public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { - req.setError(true); - req.setErrorText("sign request failed: external PKI not implemented"); - } - - @Override - public void log(ClientAPI_LogInfo loginfo) { - String text = loginfo.getText(); - System.out.format("LOG: %s", text); - } - - @Override - public void done(ClientAPI_Status status) { - System.out.format("DONE ClientAPI_Status: err=%b msg='%s'%n", status.getError(), status.getMessage()); - } - - @Override - public boolean socket_protect(int socket) - { - return false; - } - - @Override - public boolean pause_on_connection_timeout() - { - return false; - } - - @Override - public OpenVPNClientThread.TunBuilder tun_builder_new() - { - return null; - } - } diff --git a/javacli/Main.java b/javacli/Main.java deleted file mode 100644 index 41dfdf15f..000000000 --- a/javacli/Main.java +++ /dev/null @@ -1,87 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -// TESTING_ONLY - -import java.io.*; -import java.nio.charset.Charset; - -public class Main { - // utility method to read a file and return as a String - public static String readFile(String filename) throws IOException { - return readStream(new FileInputStream(filename)); - } - - private static String readStream(InputStream stream) throws IOException { - // No real need to close the BufferedReader/InputStreamReader - // as they're only wrapping the stream - try { - Reader reader = new BufferedReader(new InputStreamReader(stream)); - StringBuilder builder = new StringBuilder(); - char[] buffer = new char[4096]; - int read; - while ((read = reader.read(buffer, 0, buffer.length)) > 0) { - builder.append(buffer, 0, read); - } - return builder.toString(); - } finally { - // Potential issue here: if this throws an IOException, - // it will mask any others. Normally I'd use a utility - // method which would log exceptions and swallow them - stream.close(); - } - } - - public static void main(String[] args) throws IOException, Client.ConfigError, Client.CredsUnspecifiedError { - if (args.length >= 1) - { - // load config file - String config = readFile(args[0]); - - // get creds - String username = ""; - String password = ""; - if (args.length >= 3) - { - username = args[1]; - password = args[2]; - } - - // instantiate client object - final Client client = new Client(config, username, password); - - // catch signals - final Thread mainThread = Thread.currentThread(); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - client.stop(); - try { - mainThread.join(); - } - catch (InterruptedException e) { - } - } - }); - - // execute client session - client.connect(); - - // show stats before exit - client.show_stats(); - } - else - { - System.err.println("OpenVPN Java client"); - System.err.println("Usage: java Client <client.ovpn> [username] [password]"); - System.exit(2); - } - } -} diff --git a/javacli/OpenVPNClientThread.java b/javacli/OpenVPNClientThread.java deleted file mode 100644 index e70e4d906..000000000 --- a/javacli/OpenVPNClientThread.java +++ /dev/null @@ -1,349 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -// package OPENVPN_PACKAGE - -import java.util.HashSet; - -public class OpenVPNClientThread extends ClientAPI_OpenVPNClient implements Runnable { - private EventReceiver parent; - private TunBuilder tun_builder; - private Thread thread; - private ClientAPI_Status m_connect_status; - private boolean connect_called = false; - - private int bytes_in_index = -1; - private int bytes_out_index = -1; - - // thrown if instantiator attempts to call connect more than once - public static class ConnectCalledTwice extends RuntimeException { - } - - public interface EventReceiver { - // Called with events from core - void event(ClientAPI_Event event); - - // Called with log text from core - void log(ClientAPI_LogInfo loginfo); - - // Called when connect() thread exits - void done(ClientAPI_Status status); - - // Called to "protect" a socket from being routed through the tunnel - boolean socket_protect(int socket); - - // When a connection is close to timeout, the core will call this - // method. If it returns false, the core will disconnect with a - // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE - // state. - boolean pause_on_connection_timeout(); - - // Callback to construct a new tun builder - TunBuilder tun_builder_new(); - - // Callback to get a certificate - void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req); - - // Callback to sign data - void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req); - } - - public interface TunBuilder { - // Tun builder methods. - // Methods documented in openvpn/tun/builder/base.hpp - - boolean tun_builder_set_remote_address(String address, boolean ipv6); - boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30); - boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags); - boolean tun_builder_add_route(String address, int prefix_length, boolean ipv6); - boolean tun_builder_exclude_route(String address, int prefix_length, boolean ipv6); - boolean tun_builder_add_dns_server(String address, boolean ipv6); - boolean tun_builder_add_search_domain(String domain); - boolean tun_builder_set_mtu(int mtu); - boolean tun_builder_set_session_name(String name); - int tun_builder_establish(); - void tun_builder_teardown(boolean disconnect); - } - - public OpenVPNClientThread() { - final int n = stats_n(); - for (int i = 0; i < n; ++i) - { - String name = stats_name(i); - if (name.equals("BYTES_IN")) - bytes_in_index = i; - if (name.equals("BYTES_OUT")) - bytes_out_index = i; - } - } - - // start connect session in worker thread - public void connect(EventReceiver parent_arg) { - if (connect_called) - throw new ConnectCalledTwice(); - connect_called = true; - - // direct client callbacks to parent - parent = parent_arg; - - // clear status - m_connect_status = null; - - // execute client in a worker thread - thread = new Thread(this, "OpenVPNClientThread"); - thread.start(); - } - - // Wait for worker thread to complete; to stop thread, - // first call super stop() method then wait_thread(). - // This method will give the thread one second to - // exit and will abandon it after this time. - public void wait_thread_short() { - final int wait_millisecs = 5000; // max time that we will wait for thread to exit - Thread th = thread; - if (th != null) { - try { - th.join(wait_millisecs); - } - catch (InterruptedException e) { - } - - // thread failed to stop? - if (th.isAlive()) { - // abandon thread and deliver our own status object to instantiator. - ClientAPI_Status status = new ClientAPI_Status(); - status.setError(true); - status.setMessage("CORE_THREAD_ABANDONED"); - call_done(status); - } - } - } - - // Wait for worker thread to complete; to stop thread, - // first call super stop() method then wait_thread(). - // This method will wait forever for the thread to exit. - public void wait_thread_long() { - if (thread != null) { - boolean interrupted; - do { - interrupted = false; - try { - thread.join(); - } - catch (InterruptedException e) { - interrupted = true; - super.stop(); // send thread a stop message - } - } while (interrupted); - } - } - - public long bytes_in() - { - return super.stats_value(bytes_in_index); - } - - public long bytes_out() - { - return super.stats_value(bytes_out_index); - } - - private void call_done(ClientAPI_Status status) - { - EventReceiver p = finalize_thread(status); - if (p != null) - p.done(m_connect_status); - } - - private synchronized EventReceiver finalize_thread(ClientAPI_Status connect_status) - { - EventReceiver p = parent; - if (p != null) { - // save thread connection status - m_connect_status = connect_status; - - // disassociate client callbacks from parent - parent = null; - tun_builder = null; - thread = null; - } - return p; - } - - // Runnable overrides - - @Override - public void run() { - // Call out to core to start connection. - // Doesn't return until connection has terminated. - ClientAPI_Status status = super.connect(); - call_done(status); - } - - // ClientAPI_OpenVPNClient (C++ class) overrides - - @Override - public boolean socket_protect(int socket) { - EventReceiver p = parent; - if (p != null) - return p.socket_protect(socket); - else - return false; - } - - @Override - public boolean pause_on_connection_timeout() { - EventReceiver p = parent; - if (p != null) - return p.pause_on_connection_timeout(); - else - return false; - } - - @Override - public void event(ClientAPI_Event event) { - EventReceiver p = parent; - if (p != null) - p.event(event); - } - - @Override - public void log(ClientAPI_LogInfo loginfo) { - EventReceiver p = parent; - if (p != null) - p.log(loginfo); - } - - @Override - public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { - EventReceiver p = parent; - if (p != null) - p.external_pki_cert_request(req); - } - - @Override - public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { - EventReceiver p = parent; - if (p != null) - p.external_pki_sign_request(req); - } - - // TunBuilderBase (C++ class) overrides - - @Override - public boolean tun_builder_new() { - EventReceiver p = parent; - if (p != null) { - tun_builder = p.tun_builder_new(); - return tun_builder != null; - } else - return false; - } - - @Override - public boolean tun_builder_set_remote_address(String address, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_remote_address(address, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_address(address, prefix_length, gateway, ipv6, net30); - else - return false; - } - - @Override - public boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_reroute_gw(ipv4, ipv6, flags); - else - return false; - } - - @Override - public boolean tun_builder_add_route(String address, int prefix_length, int metric, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_route(address, prefix_length, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_exclude_route(String address, int prefix_length, int metric, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_exclude_route(address, prefix_length, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_dns_server(String address, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_dns_server(address, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_search_domain(String domain) - { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_search_domain(domain); - else - return false; - } - - @Override - public boolean tun_builder_set_mtu(int mtu) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_mtu(mtu); - else - return false; - } - - @Override - public boolean tun_builder_set_session_name(String name) - { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_session_name(name); - else - return false; - } - - @Override - public int tun_builder_establish() { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_establish(); - else - return -1; - } - - @Override - public void tun_builder_teardown(boolean disconnect) { - TunBuilder tb = tun_builder; - if (tb != null) - tb.tun_builder_teardown(disconnect); - } -} diff --git a/javacli/build-android b/javacli/build-android deleted file mode 100755 index 0ea3a166e..000000000 --- a/javacli/build-android +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env bash -# generate expire time in python: time.mktime((2012, 5, 1, 0, 0, 0, 0, 0, -1)) -# -DAPP_EXPIRE_TIME=1364796000 \ -set -e - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -cd $O3/core -. vars/android-sdk-path -cd javacli -git clean -q -fXd . - -if [ "$PKG" ]; then - pkg=$PKG - pkg_id_def="-DOPENVPN_PACKAGE_ID=${PKG//./_}" -else - pkg=net.openvpn.openvpn - pkg_id_def="-DOPENVPN_PACKAGE_ID=net_openvpn_openvpn" -fi -echo PACKAGE $PKG - -if [ "$PT_PROXY" = "1" ] && [ -d "$O3/common" ]; then - common="-I$O3/common -DPRIVATE_TUNNEL_PROXY" -else - common="" -fi - -echo SWIG -swig -c++ -java -package $pkg -I$O3/core/client -I$O3/core ovpncli.i - -TARGETS=${TARGETS:-android-a7a android-a8a android-x86} - -for TARGET in $TARGETS; do - -if [ "$DEBUG_BUILD" = "1" ]; then - . ../vars/vars-${TARGET}-dbg - vis1="" - vis2="" - opt2="$pkg_id_def $LIB_OPT_LEVEL" -else - . ../vars/vars-${TARGET} - vis1="-fvisibility=hidden" - vis2='-DSWIGEXPORT=__attribute__((visibility("default")))' - opt2="$pkg_id_def -Os" -fi - -if [ "$OPENSSL" = "1" ]; then - ssl_def="-DUSE_OPENSSL" - ssl_inc="-I$DEP_DIR/openssl/openssl-$PLATFORM/include" - ssl_lib="-lssl -lcrypto" - ssl_libdir="-L$DEP_DIR/openssl/openssl-$PLATFORM/lib" -else - ssl_def="-DUSE_MBEDTLS" - ssl_inc="-I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" - ssl_lib="-lmbedtls" - ssl_libdir="-L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" -fi - -[ -z "$GPP_CMD" ] && GPP_CMD=g++ - -echo CORE $ABI -$GPP_CMD \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $OTHER_COMPILER_FLAGS \ - $LIB_OPT_LEVEL $LIB_FPIC \ - -Wall -Wno-sign-compare -Wno-unused-parameter \ - -Wno-unused-local-typedefs \ - $vis1 \ - $ssl_def \ - -DUSE_ASIO \ - -DASIO_STANDALONE \ - -DASIO_NO_DEPRECATED \ - -DHAVE_LZ4 \ - -DOPENVPN_ALLOW_INSECURE_CERTPROFILE \ - -DASIO_HAS_STD_STRING_VIEW \ - -I$O3/core/client \ - -I$O3/core \ - $common \ - -I$DEP_DIR/asio/asio/include \ - $ssl_inc \ - -I$DEP_DIR/lz4/lz4-$PLATFORM/include \ - -c $O3/core/client/ovpncli.cpp - -echo WRAP $ABI -$GPP_CMD \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $OTHER_COMPILER_FLAGS \ - $opt2 $LIB_FPIC \ - -fno-strict-aliasing \ - -Wall \ - $vis1 $vis2 \ - -I$O3/core/client \ - -I$O3/core \ - $common \ - $ssl_libdir \ - -L$DEP_DIR/lz4/lz4-$PLATFORM/lib \ - ovpncli_wrap.cxx \ - android/jellybean_hack.cpp \ - android/cpu.cpp \ - ovpncli.o \ - -o libovpncli.so \ - -shared -Wl,-soname,libovpncli.so \ - $ssl_lib \ - -llz4 \ - -llog - -if [ "$DEBUG_BUILD" != "1" ]; then - echo STRIP $ABI - strip libovpncli.so -fi - -mkdir -p build/libs/$ABI -mv libovpncli.so build/libs/$ABI/ -rm ovpncli.o -done - -mv ovpncli_wrap.cxx ovpncli_wrap.h ovpncli.java ovpncliJNI.java SWIGTYPE_*.java ClientAPI_*.java build/ -git clean -q -fX . - -tar -czf android-core-build.tgz build -mv android-core-build.tgz $O3/ diff --git a/openvpn/acceptor/base.hpp b/openvpn/acceptor/base.hpp index e6aa361ff..bb3729685 100644 --- a/openvpn/acceptor/base.hpp +++ b/openvpn/acceptor/base.hpp @@ -16,6 +16,7 @@ #include <vector> #include <utility> +#include <algorithm> #include <openvpn/io/io.hpp> @@ -31,16 +32,16 @@ namespace openvpn::Acceptor { -struct ListenerBase : public OPENVPN_ACCEPTOR_LISTENER_BASE_RC +struct ListenerBase : OPENVPN_ACCEPTOR_LISTENER_BASE_RC { - typedef RCPtr<ListenerBase> Ptr; + using Ptr = RCPtr<ListenerBase>; virtual void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) = 0; }; -struct Base : public RC<thread_unsafe_refcount> +struct Base : RC<thread_unsafe_refcount> { - typedef RCPtr<Base> Ptr; + using Ptr = RCPtr<Base>; virtual void async_accept(ListenerBase *listener, const size_t acceptor_index, @@ -70,12 +71,12 @@ struct Item SSLMode ssl_mode; }; -struct Set : public std::vector<Item> +struct Set : std::vector<Item> { void close() { - for (auto &i : *this) - i.acceptor->close(); + std::ranges::for_each(*this, [](const auto &i) + { i.acceptor->close(); }); } }; diff --git a/openvpn/acceptor/namedpipe.hpp b/openvpn/acceptor/namedpipe.hpp index aa53e851f..991233a91 100644 --- a/openvpn/acceptor/namedpipe.hpp +++ b/openvpn/acceptor/namedpipe.hpp @@ -22,7 +22,7 @@ class NamedPipe : public Base public: OPENVPN_EXCEPTION(named_pipe_acceptor_error); - typedef RCPtr<NamedPipe> Ptr; + using Ptr = RCPtr<NamedPipe>; NamedPipe(openvpn_io::io_context &io_context, const std::string &name_arg, diff --git a/openvpn/acceptor/tcp.hpp b/openvpn/acceptor/tcp.hpp index a55988142..fcb4c8d76 100644 --- a/openvpn/acceptor/tcp.hpp +++ b/openvpn/acceptor/tcp.hpp @@ -16,9 +16,9 @@ namespace openvpn::Acceptor { -struct TCP : public Base +struct TCP : Base { - typedef RCPtr<TCP> Ptr; + using Ptr = RCPtr<TCP>; TCP(openvpn_io::io_context &io_context) : acceptor(io_context) @@ -53,9 +53,9 @@ struct TCP : public Base }; void set_socket_options(unsigned int flags) { - static_assert(int(FIRST) > int(SSLConst::LAST), "TCP flags in conflict with SSL flags"); + static_assert(static_cast<int>(FIRST) > static_cast<int>(SSLConst::LAST), "TCP flags in conflict with SSL flags"); -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN // set Windows socket flags if (!(flags & DISABLE_REUSE_ADDR)) acceptor.set_option(openvpn_io::ip::tcp::acceptor::reuse_address(true)); diff --git a/openvpn/acceptor/unix.hpp b/openvpn/acceptor/unix.hpp index aadb8e497..95f1d2248 100644 --- a/openvpn/acceptor/unix.hpp +++ b/openvpn/acceptor/unix.hpp @@ -18,11 +18,11 @@ namespace openvpn::Acceptor { -struct Unix : public Base +struct Unix : Base { OPENVPN_EXCEPTION(unix_acceptor_error); - typedef RCPtr<Unix> Ptr; + using Ptr = RCPtr<Unix>; Unix(openvpn_io::io_context &io_context) : acceptor(io_context) @@ -56,7 +56,7 @@ struct Unix : public Base { if (unix_mode) { - if (::chmod(socket_path.c_str(), unix_mode) < 0) + if (chmod(socket_path.c_str(), unix_mode) < 0) throw unix_acceptor_error("chmod failed on unix socket"); } } diff --git a/openvpn/addr/addrlist.hpp b/openvpn/addr/addrlist.hpp index bcfc9852c..b2717e029 100644 --- a/openvpn/addr/addrlist.hpp +++ b/openvpn/addr/addrlist.hpp @@ -12,26 +12,28 @@ #ifndef OPENVPN_ADDR_ADDRLIST_H #define OPENVPN_ADDR_ADDRLIST_H +#include <algorithm> + #include <openvpn/common/rc.hpp> #include <openvpn/addr/ip.hpp> namespace openvpn::IP { // A list of unique IP addresses -class AddrList : public std::vector<IP::Addr>, public RC<thread_unsafe_refcount> +class AddrList : public std::vector<Addr>, public RC<thread_unsafe_refcount> { public: - typedef RCPtr<AddrList> Ptr; + using Ptr = RCPtr<AddrList>; - void add(const IP::Addr &a) + void add(const Addr &a) { if (!exists(a)) push_back(a); } - bool exists(const IP::Addr &a) const + bool exists(const Addr &a) const { - return std::find(begin(), end(), a) != end(); + return std::ranges::find(*this, a) != end(); } #if 0 diff --git a/openvpn/addr/addrpair.hpp b/openvpn/addr/addrpair.hpp index b6ff2e8ab..ca74eb483 100644 --- a/openvpn/addr/addrpair.hpp +++ b/openvpn/addr/addrpair.hpp @@ -102,35 +102,33 @@ struct AddrMaskPair { if (s2.empty()) { - const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s1, '/'); - return from_string_impl(pair, title); - } - else - { - const StringPair pair(s1, s2); + const auto pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s1, '/'); return from_string_impl(pair, title); } + + const StringPair pair(s1, s2); + return from_string_impl(pair, title); } catch (const std::exception &e) { const StringPair pair(s1, s2); error(e, pair.render(), title); } - return AddrMaskPair(); // NOTREACHED + return {}; // NOTREACHED } static AddrMaskPair from_string(const std::string &s, const char *title = nullptr) { try { - const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s, '/'); + const auto pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s, '/'); return from_string_impl(pair, title); } catch (const std::exception &e) { error(e, s, title); } - return AddrMaskPair(); // NOTREACHED + return {}; // NOTREACHED } static AddrMaskPair from_string(const StringPair &pair, const char *title = nullptr) @@ -143,17 +141,13 @@ struct AddrMaskPair { error(e, pair.render(), title); } - return AddrMaskPair(); // NOTREACHED + return {}; // NOTREACHED } std::string to_string(const bool netmask_form = false) const { - std::ostringstream os; - if (netmask_form) - os << addr.to_string() << '/' << netmask.to_string(); - else - os << addr.to_string() << '/' << netmask.prefix_len(); - return os.str(); + return netmask_form ? addr.to_string() + '/' + netmask.to_string() + : addr.to_string() + '/' + std::to_string(netmask.prefix_len()); } bool is_canonical() const @@ -163,12 +157,7 @@ struct AddrMaskPair Addr::Version version() const { - const Addr::Version v1 = addr.version(); - const Addr::Version v2 = netmask.version(); - if (v1 == v2) - return v1; - else - return Addr::UNSPEC; + return addr.version() == netmask.version() ? addr.version() : Addr::UNSPEC; } Addr addr; diff --git a/openvpn/addr/ip.hpp b/openvpn/addr/ip.hpp index 36a66c57c..1da232da6 100644 --- a/openvpn/addr/ip.hpp +++ b/openvpn/addr/ip.hpp @@ -50,7 +50,7 @@ class Addr V4_MASK = (1 << 0), V6_MASK = (1 << 1) }; - typedef unsigned int VersionMask; + using VersionMask = unsigned int; enum VersionSize { @@ -107,7 +107,7 @@ class Addr const Version required_version) { openvpn_io::error_code ec; - openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec); + const openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec); if (ec) OPENVPN_IP_THROW(internal::format_error(ipstr, title, "", ec)); const Addr ret = from_asio(a); diff --git a/openvpn/addr/ipv4.hpp b/openvpn/addr/ipv4.hpp index a33589f32..fa1459c6f 100644 --- a/openvpn/addr/ipv4.hpp +++ b/openvpn/addr/ipv4.hpp @@ -40,13 +40,10 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial friend class IP::Addr; public: - enum - { - SIZE = 32 - }; + static constexpr unsigned int SIZE = 32; - typedef std::uint32_t base_type; - typedef std::int32_t signed_base_type; + using base_type = std::uint32_t; + using signed_base_type = std::int32_t; static constexpr int ip_version() { @@ -205,7 +202,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial static Addr from_string(const std::string &ipstr, const TITLE &title) { openvpn_io::error_code ec; - openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec); + const openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec); if (ec) throw ipv4_exception(IP::internal::format_error(ipstr, title, "v4", ec)); return from_asio(a); @@ -579,7 +576,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial static base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) noexcept { if (prefix_len) - return ~((1u << (SIZE - prefix_len)) - 1); + return ~((1U << (SIZE - prefix_len)) - 1); return 0; } diff --git a/openvpn/addr/ipv6.hpp b/openvpn/addr/ipv6.hpp index f05bc6809..568661140 100644 --- a/openvpn/addr/ipv6.hpp +++ b/openvpn/addr/ipv6.hpp @@ -40,10 +40,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial friend class IP::Addr; public: - enum - { - SIZE = 128 - }; + static constexpr unsigned int SIZE = 128; static constexpr int ip_version() { @@ -81,10 +78,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial static Addr from_sockaddr(const sockaddr_in6 *sa) { - Addr ret; - network_to_host_order(&ret.u, reinterpret_cast<const ipv6addr *>(sa->sin6_addr.s6_addr)); - ret.scope_id_ = sa->sin6_scope_id; - return ret; + return from_in6_addr(&sa->sin6_addr); } sockaddr_in6 to_sockaddr(const unsigned short port = 0) const @@ -107,7 +101,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial static Addr from_string(const std::string &ipstr, const TITLE &title) { openvpn_io::error_code ec; - openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec); + const openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec); if (ec) throw ipv6_exception(IP::internal::format_error(ipstr, title, "v6", ec)); return from_asio(a); @@ -134,7 +128,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial std::string to_string() const { const openvpn_io::ip::address_v6 a = to_asio(); - std::string ret = a.to_string(); + const std::string ret = a.to_string(); #ifdef UNIT_TEST return string::to_lower_copy(ret); #else @@ -741,7 +735,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial if (prefix_len > 0) { const unsigned int pl = prefix_len - 1; - const std::uint32_t mask = ~((1u << (31 - (pl & 31))) - 1); + const std::uint32_t mask = ~((1U << (31 - (pl & 31))) - 1); switch (pl >> 5) { case 0: @@ -804,10 +798,10 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial { if (shift == 1) { - high <<= 1u; - if (low & (std::uint64_t(1) << 63u)) - high |= 1u; - low <<= 1u; + high <<= 1U; + if (low & (std::uint64_t(1) << 63U)) + high |= 1U; + low <<= 1U; } else if (shift == 0) { @@ -820,7 +814,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial } else if (shift < 64) { - high = (high << shift) | (low >> (64u - shift)); + high = (high << shift) | (low >> (64U - shift)); low <<= shift; } else if (shift < 128) /* in [64, 127] */ @@ -841,10 +835,10 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial { if (shift == 1) { - low >>= 1u; - if (high & 1u) - low |= (std::uint64_t(1) << 63u); - high >>= 1u; + low >>= 1U; + if (high & 1U) + low |= (std::uint64_t(1) << 63U); + high >>= 1U; } else if (shift == 0) { diff --git a/openvpn/addr/pool.hpp b/openvpn/addr/pool.hpp index 8ac7e3aa0..d36b2ca3a 100644 --- a/openvpn/addr/pool.hpp +++ b/openvpn/addr/pool.hpp @@ -29,8 +29,6 @@ template <typename ADDR> class PoolType { public: - PoolType() = default; - /** * @brief Adds range of addresses to pool (pool will own the addresses). * @param range RangeType of IP Addresses @@ -180,7 +178,7 @@ class PoolType } }; -typedef PoolType<IP::Addr> Pool; +using Pool = PoolType<IP::Addr>; } // namespace openvpn::IP #endif diff --git a/openvpn/addr/range.hpp b/openvpn/addr/range.hpp index ab41191ac..65ac7e3ff 100644 --- a/openvpn/addr/range.hpp +++ b/openvpn/addr/range.hpp @@ -380,8 +380,7 @@ inline bool RangePartitionType<ADDR>::next(RangeType<ADDR> &r) --remaining; return r.defined(); } - else - return false; + return false; } } // namespace openvpn::IP diff --git a/openvpn/addr/route.hpp b/openvpn/addr/route.hpp index 4c41a0759..e0fc5c788 100644 --- a/openvpn/addr/route.hpp +++ b/openvpn/addr/route.hpp @@ -32,7 +32,7 @@ template <typename ADDR> class RouteType { public: - typedef ADDR Addr; + using Addr = ADDR; ADDR addr; unsigned int prefix_len; @@ -201,16 +201,14 @@ class RouteType { if (prefix_len < addr.size()) return addr.size() - prefix_len; - else - return 0; + return 0; } bool contains(const ADDR &a) const // assumes canonical address/routes { if (addr.defined() && version_eq(addr, a)) return (a & netmask()) == addr; - else - return false; + return false; } bool contains(const RouteType &r) const // assumes canonical routes @@ -248,8 +246,7 @@ class RouteType { if (prefix_len == addr.size()) return addr.to_string(); - else - return addr.to_string() + '/' + openvpn::to_string(prefix_len); + return addr.to_string() + '/' + openvpn::to_string(prefix_len); } bool operator==(const RouteType &other) const @@ -318,7 +315,7 @@ class RouteType template <typename ADDR> struct RouteTypeList : public std::vector<RouteType<ADDR>> { - typedef std::vector<RouteType<ADDR>> Base; + using Base = std::vector<RouteType<ADDR>>; OPENVPN_EXCEPTION(route_list_error); @@ -326,7 +323,7 @@ struct RouteTypeList : public std::vector<RouteType<ADDR>> { std::ostringstream os; for (auto &r : *this) - os << r.to_string() << std::endl; + os << r.to_string() << "\n"; return os.str(); } @@ -354,13 +351,13 @@ struct RouteTypeList : public std::vector<RouteType<ADDR>> } }; -typedef RouteType<IP::Addr> Route; -typedef RouteType<IPv4::Addr> Route4; -typedef RouteType<IPv6::Addr> Route6; +using Route = RouteType<IP::Addr>; +using Route4 = RouteType<IPv4::Addr>; +using Route6 = RouteType<IPv6::Addr>; -typedef RouteTypeList<IP::Addr> RouteList; -typedef RouteTypeList<IPv4::Addr> Route4List; -typedef RouteTypeList<IPv6::Addr> Route6List; +using RouteList = RouteTypeList<IP::Addr>; +using Route4List = RouteTypeList<IPv4::Addr>; +using Route6List = RouteTypeList<IPv6::Addr>; OPENVPN_OSTREAM(Route, to_string); OPENVPN_OSTREAM(Route4, to_string); diff --git a/openvpn/apple/cf/cf.hpp b/openvpn/apple/cf/cf.hpp index 7ae25f3cd..4311feff9 100644 --- a/openvpn/apple/cf/cf.hpp +++ b/openvpn/apple/cf/cf.hpp @@ -180,7 +180,7 @@ class Wrap if (obj_) CFShow(obj_); else - std::cerr << "CF_UNDEFINED" << std::endl; + std::cerr << "CF_UNDEFINED\n"; } virtual ~Wrap() diff --git a/openvpn/applecrypto/crypto/hmac.hpp b/openvpn/applecrypto/crypto/hmac.hpp index 8b8541981..637aa72b3 100644 --- a/openvpn/applecrypto/crypto/hmac.hpp +++ b/openvpn/applecrypto/crypto/hmac.hpp @@ -51,9 +51,7 @@ class HMACContext init(digest, key, key_size); } - ~HMACContext() - { - } + ~HMACContext() = default; void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) { diff --git a/openvpn/applecrypto/ssl/sslctx.hpp b/openvpn/applecrypto/ssl/sslctx.hpp index 609f7f081..6ca39c308 100644 --- a/openvpn/applecrypto/ssl/sslctx.hpp +++ b/openvpn/applecrypto/ssl/sslctx.hpp @@ -71,9 +71,7 @@ class AppleSSLContext : public SSLFactoryAPI public: typedef RCPtr<Config> Ptr; - Config() - { - } + Config() = default; void load_identity(const std::string &subject_match) { diff --git a/openvpn/applecrypto/util/rand.hpp b/openvpn/applecrypto/util/rand.hpp index eadf1e611..ac50ce779 100644 --- a/openvpn/applecrypto/util/rand.hpp +++ b/openvpn/applecrypto/util/rand.hpp @@ -28,8 +28,6 @@ class AppleRandom : public StrongRandomAPI typedef RCPtr<AppleRandom> Ptr; - AppleRandom() = default; - std::string name() const override { return "AppleRandom"; diff --git a/openvpn/asio/asioboundsock.hpp b/openvpn/asio/asioboundsock.hpp index af14e4091..244b43b82 100644 --- a/openvpn/asio/asioboundsock.hpp +++ b/openvpn/asio/asioboundsock.hpp @@ -125,7 +125,7 @@ class Socket : public SocketBase unsigned short port_; }; - virtual void async_connect_post_open(const protocol_type &protocol, openvpn_io::error_code &ec) override + void async_connect_post_open(const protocol_type &protocol, openvpn_io::error_code &ec) override { if (protocol == openvpn_io::ip::tcp::v4()) v4.post_open(this, ec); diff --git a/openvpn/asio/asioerr.hpp b/openvpn/asio/asioerr.hpp index 6ef5d1238..5ee12789e 100644 --- a/openvpn/asio/asioerr.hpp +++ b/openvpn/asio/asioerr.hpp @@ -22,7 +22,7 @@ namespace openvpn { template <typename ErrorCode> inline std::string errinfo(ErrorCode err) { - openvpn_io::error_code e(err, openvpn_io::system_category()); + const openvpn_io::error_code e(err, openvpn_io::system_category()); return e.message(); } diff --git a/openvpn/auth/authcert.hpp b/openvpn/auth/authcert.hpp index b30061e5e..cbecc9e5c 100644 --- a/openvpn/auth/authcert.hpp +++ b/openvpn/auth/authcert.hpp @@ -22,7 +22,6 @@ #include <openvpn/common/exception.hpp> #include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> #include <openvpn/common/hexstr.hpp> #include <openvpn/common/binprefix.hpp> #include <openvpn/common/to_string.hpp> @@ -43,7 +42,7 @@ class AuthCert : public RC<thread_unsafe_refcount> friend class OpenSSLContext; friend class MbedTLSContext; - typedef RCPtr<AuthCert> Ptr; + using Ptr = RCPtr<AuthCert>; class Fail { @@ -177,7 +176,7 @@ class AuthCert : public RC<thread_unsafe_refcount> bool defined() const { for (size_t i = 0; i < 5; ++i) - if (serial_number32[i] != 0xffffffffu) + if (serial_number32[i] != 0xffffffffU) return true; return false; } @@ -436,16 +435,14 @@ class AuthCert : public RC<thread_unsafe_refcount> { if (openssl_fmt) return render_hex_sep(issuer_fp, sizeof(issuer_fp), ':', true); - else - return render_hex(issuer_fp, sizeof(issuer_fp), false); + return render_hex(issuer_fp, sizeof(issuer_fp), false); } std::string normalize_cn() const // remove trailing "_AUTOLOGIN" from AS certs { - if (string::ends_with(cn, "_AUTOLOGIN")) + if (cn.ends_with("_AUTOLOGIN")) return cn.substr(0, cn.length() - 10); - else - return cn; + return cn; } // Allow sni_metadata object, if it exists, to generate the client name. @@ -454,8 +451,7 @@ class AuthCert : public RC<thread_unsafe_refcount> { if (sni_metadata) return sni_metadata->sni_client_name(*this); - else - return normalize_cn(); + return normalize_cn(); } const std::string &get_sni() const @@ -499,8 +495,7 @@ class AuthCert : public RC<thread_unsafe_refcount> { if (fail) return fail->to_string(true); - else - return "OK"; + return "OK"; } #ifndef UNIT_TEST diff --git a/openvpn/auth/authcreds.hpp b/openvpn/auth/authcreds.hpp index 9a66881cf..d9c7d120b 100644 --- a/openvpn/auth/authcreds.hpp +++ b/openvpn/auth/authcreds.hpp @@ -28,7 +28,7 @@ namespace openvpn { class AuthCreds : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<AuthCreds> Ptr; + using Ptr = RCPtr<AuthCreds>; AuthCreds(std::string &&username_arg, SafeString &&password_arg, @@ -74,17 +74,17 @@ class AuthCreds : public RC<thread_unsafe_refcount> std::string to_string() const { std::ostringstream os; - os << "*** AuthCreds ***" << std::endl; - os << "user: '" << username << "'" << std::endl; + os << "*** AuthCreds ***\n"; + os << "user: '" << username << "'\n"; if (password.empty()) { - os << "pass: (empty)" << std::endl; + os << "pass: (empty)\n"; } else { - os << "pass: (non-empty)" << std::endl; + os << "pass: (non-empty)\n"; } - os << "peer info:" << std::endl; + os << "peer info:\n"; os << peer_info.render(Option::RENDER_BRACKET | Option::RENDER_NUMBER); return os.str(); } diff --git a/openvpn/auth/cr.hpp b/openvpn/auth/cr.hpp index 79a48a5ad..5ba18b6c0 100644 --- a/openvpn/auth/cr.hpp +++ b/openvpn/auth/cr.hpp @@ -22,7 +22,6 @@ #include <openvpn/common/base64.hpp> #include <openvpn/common/split.hpp> #include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> // Static Challenge response: // SCRV1:<BASE64_PASSWORD>:<BASE64_RESPONSE> @@ -41,7 +40,7 @@ namespace openvpn { class ChallengeResponse : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<ChallengeResponse> Ptr; + using Ptr = RCPtr<ChallengeResponse>; OPENVPN_SIMPLE_EXCEPTION(dynamic_challenge_parse_error); OPENVPN_SIMPLE_EXCEPTION(static_challenge_parse_error); @@ -71,7 +70,7 @@ class ChallengeResponse : public RC<thread_unsafe_refcount> void init(const std::string &cookie) { - typedef std::vector<std::string> StringList; + using StringList = std::vector<std::string>; StringList sl; sl.reserve(5); Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, cookie, ':', 0, 4); @@ -113,39 +112,35 @@ class ChallengeResponse : public RC<thread_unsafe_refcount> static bool is_dynamic(const std::string &s) { - return string::starts_with(s, "CRV1:"); + return s.starts_with("CRV1:"); } static bool is_static(const std::string &s) { - return string::starts_with(s, "SCRV1:"); + return s.starts_with("SCRV1:"); } static void validate_dynamic(const std::string &cookie) { - ChallengeResponse cr(cookie); + const ChallengeResponse cr(cookie); } std::string construct_dynamic_password(const std::string &response) const { - std::ostringstream os; - os << "CRV1::" << state_id << "::" << response; - return os.str(); + return "CRV1::" + state_id + "::" + response; } static std::string construct_static_password(const std::string &password, const std::string &response) { - std::ostringstream os; - os << "SCRV1:" << base64->encode(password) << ':' << base64->encode(response); - return os.str(); + return "SCRV1:" + base64->encode(password) + ':' + base64->encode(response); } static void parse_static_cookie(const std::string &cookie, std::string &password, std::string &response) { - typedef std::vector<std::string> StringList; + using StringList = std::vector<std::string>; StringList sl; sl.reserve(3); Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, cookie, ':'); diff --git a/openvpn/aws/awsca.hpp b/openvpn/aws/awsca.hpp index 427a4376f..579393371 100644 --- a/openvpn/aws/awsca.hpp +++ b/openvpn/aws/awsca.hpp @@ -13,6 +13,7 @@ #pragma once +#include <filesystem> #include <openvpn/common/fileunix.hpp> #include <openvpn/common/stat.hpp> @@ -21,16 +22,17 @@ inline std::string api_ca() { // paths are copied from https://golang.org/src/crypto/x509/root_linux.go std::list<std::string> certs = { - "/etc/ssl/certs/ca-certificates.crt", // debian/ubuntu - "/etc/pki/tls/certs/ca-bundle.crt", // fedora/rhel6 - "/etc/ssl/ca-bundle.pem", // opensuse, - "/etc/pki/tls/cacert.pem" // openelec - "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" // centos/rhel7 - "/etc/ssl/cert.pem" // alpine + "/etc/ssl/certs/ca-certificates.crt", // debian/ubuntu + "/etc/pki/tls/certs/ca-bundle.crt", // fedora/rhel6 + "/etc/ssl/ca-bundle.pem", // opensuse, + "/etc/pki/tls/cacert.pem", // openelec + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // centos/rhel7 + "/etc/ssl/cert.pem", // alpine }; for (const auto &cert : certs) { - if (file_exists(cert)) + std::error_code ec; + if (std::filesystem::exists(cert, ec)) return read_text_unix(cert); } throw file_unix_error("No CA certificate files found in system paths"); diff --git a/openvpn/aws/awscreds.hpp b/openvpn/aws/awscreds.hpp index 5a8184522..92b35a71d 100644 --- a/openvpn/aws/awscreds.hpp +++ b/openvpn/aws/awscreds.hpp @@ -18,9 +18,7 @@ namespace openvpn::AWS { struct Creds { - Creds() - { - } + Creds() = default; Creds(std::string access_key_arg, std::string secret_key_arg, diff --git a/openvpn/aws/awshttp.hpp b/openvpn/aws/awshttp.hpp index 415153761..7fc2c4b92 100644 --- a/openvpn/aws/awshttp.hpp +++ b/openvpn/aws/awshttp.hpp @@ -96,6 +96,7 @@ class HTTPContext ssl->set_flags(ssl_flags); ssl->set_frame(frame_); ssl->set_rng(rng_); + ssl->set_debug_level(debug_level_); // make HTTP context WS::Client::Config::Ptr hc(new WS::Client::Config()); diff --git a/openvpn/buffer/bufcomposed.hpp b/openvpn/buffer/bufcomposed.hpp index 621db51fd..c1376c985 100644 --- a/openvpn/buffer/bufcomposed.hpp +++ b/openvpn/buffer/bufcomposed.hpp @@ -49,7 +49,7 @@ class BufferComposed return iter != bc.bv.end(); } - virtual void next_buffer() override + void next_buffer() override { next_buffer_impl(); } diff --git a/openvpn/buffer/buffer.hpp b/openvpn/buffer/buffer.hpp index 15075dd22..86c49eaab 100644 --- a/openvpn/buffer/buffer.hpp +++ b/openvpn/buffer/buffer.hpp @@ -54,6 +54,7 @@ #include <openvpn/common/rc.hpp> #include <openvpn/buffer/bufclamp.hpp> #include <openvpn/common/make_rc.hpp> +#include <openvpn/common/intrinsic_type.hpp> #ifdef OPENVPN_BUFFER_ABORT #define OPENVPN_BUFFER_THROW(exc) \ @@ -144,8 +145,7 @@ class BufferException : public std::exception { if (!msg_.empty()) return msg_.c_str(); - else - return status_string(status_); + return status_string(status_); } Status status() const @@ -201,6 +201,12 @@ class BufferAllocatedType; template <typename T> class BufferType; +// Allocation and security for the buffer +struct BufferFlags : IntrinsicType<BufferFlags, unsigned int> +{ + using IntrinsicType<BufferFlags, unsigned int>::IntrinsicType; +}; + // =============================================================================================== // class ConstBufferType // =============================================================================================== @@ -228,10 +234,10 @@ template <typename T> class ConstBufferType { public: - typedef T value_type; - typedef T *type; - typedef const T *const_type; - typedef typename std::remove_const_t<T> NCT; + using value_type = T; + using type = T *; + using const_type = const T *; + using NCT = typename std::remove_const_t<T>; /** * @brief Default constructor for ConstBufferType. @@ -697,7 +703,7 @@ class ConstBufferType * @param min_capacity The minimum capacity of the buffer. * @param flags Flags to control the behavior of the reset operation. */ - void reset(const size_t min_capacity, const unsigned int flags); + void reset(const size_t min_capacity, const BufferFlags flags); /** * @brief Reset the buffer with the specified headroom, minimum capacity, and flags. @@ -705,7 +711,7 @@ class ConstBufferType * @param min_capacity The minimum capacity of the buffer. * @param flags Flags to control the behavior of the reset operation. */ - void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags); + void reset(const size_t headroom, const size_t min_capacity, const BufferFlags flags); /** * @brief Append data from another buffer to this buffer. @@ -734,8 +740,9 @@ class ConstBufferType * @brief Called when the reset method needs to expand the buffer size. * @param min_capacity The minimum capacity required for the buffer. * @param flags Flags to control the behavior of the reset operation. + * @todo Look into this odd one-off virtual dispatch + leakage of the flags parameter. */ - virtual void reset_impl(const size_t min_capacity, const unsigned int flags); + virtual void reset_impl(const size_t min_capacity, const BufferFlags flags); /** * @brief Derived classes can implement buffer growing semantics by overloading this method. @@ -862,17 +869,14 @@ class BufferType : public ConstBufferType<T> // class BufferAllocatedType // =============================================================================================== -// Allocation and security for the buffer -struct BufAllocFlags -{ - enum - { - CONSTRUCT_ZERO = (1 << 0), ///< if enabled, constructors/init will zero allocated space - DESTRUCT_ZERO = (1 << 1), ///< if enabled, destructor will zero data before deletion - GROW = (1 << 2), ///< if enabled, buffer will grow (otherwise buffer_full exception will be thrown) - ARRAY = (1 << 3), ///< if enabled, use as array - }; -}; +// Flag constants +namespace BufAllocFlags { +constexpr BufferFlags NO_FLAGS(0U); ///< no flags set +constexpr BufferFlags CONSTRUCT_ZERO(1U << 0); ///< if enabled, constructors/init will zero allocated space +constexpr BufferFlags DESTRUCT_ZERO(1U << 1); ///< if enabled, destructor will zero data before deletion +constexpr BufferFlags GROW(1U << 2); ///< if enabled, buffer will grow (otherwise buffer_full exception will be thrown) +constexpr BufferFlags ARRAY(1U << 3); ///< if enabled, use as array +} // namespace BufAllocFlags template <typename T> class BufferAllocatedType : public BufferType<T> @@ -904,7 +908,8 @@ class BufferAllocatedType : public BufferType<T> * @param capacity The initial capacity of the buffer. * @param flags The flags to set for the buffer. */ - BufferAllocatedType(const size_t capacity, const unsigned int flags); + explicit BufferAllocatedType(const size_t capacity, + const BufferFlags flags = BufAllocFlags::NO_FLAGS); /** * @brief Constructs a BufferAllocatedType with the specified data, size, and flags. @@ -912,7 +917,7 @@ class BufferAllocatedType : public BufferType<T> * @param size The size of the data to be copied. * @param flags The flags to set for the buffer. */ - BufferAllocatedType(const T *data, const size_t size, const unsigned int flags); + explicit BufferAllocatedType(const T *data, const size_t size, const BufferFlags flags); /** * @brief Copy constructor. @@ -927,7 +932,8 @@ class BufferAllocatedType : public BufferType<T> * @param flags The flags to set for the new BufferAllocatedType object. */ template <typename T_> - BufferAllocatedType(const BufferType<T_> &other, const unsigned int flags); + BufferAllocatedType(const BufferType<T_> &other, + const BufferFlags flags = BufAllocFlags::NO_FLAGS); /** * @brief Assignment operator. @@ -940,7 +946,7 @@ class BufferAllocatedType : public BufferType<T> * @param capacity The initial capacity of the buffer. * @param flags The flags to set for the buffer. */ - void init(const size_t capacity, const unsigned int flags); + void init(const size_t capacity, const BufferFlags flags = BufAllocFlags::NO_FLAGS); /** * @brief Initializes the buffer with the specified data, size, and flags. @@ -948,7 +954,7 @@ class BufferAllocatedType : public BufferType<T> * @param size The size of the data to be copied. * @param flags The flags to set for the buffer. */ - void init(const T *data, const size_t size, const unsigned int flags); + void init(const T *data, const size_t size, const BufferFlags flags); /** * @brief Reallocates the buffer to the specified new capacity. @@ -970,7 +976,7 @@ class BufferAllocatedType : public BufferType<T> * @param min_capacity The minimum capacity for the buffer. * @param flags The flags to set for the buffer. */ - void reset(const size_t min_capacity, const unsigned int flags); + void reset(const size_t min_capacity, const BufferFlags flags = BufAllocFlags::NO_FLAGS); /** * @brief Resets the buffer with the specified headroom, minimum capacity, and flags. @@ -978,7 +984,9 @@ class BufferAllocatedType : public BufferType<T> * @param min_capacity The minimum capacity for the buffer. * @param flags The flags to set for the buffer. */ - void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags); + void reset(const size_t headroom, + const size_t min_capacity, + const BufferFlags flags = BufAllocFlags::NO_FLAGS); /** * @brief Moves the contents of another BufferAllocatedType object into this object. @@ -1019,17 +1027,25 @@ class BufferAllocatedType : public BufferType<T> */ void clear(); + /** + @brief Test if the buffer has the specified flags. + @param flags Flags required for true result + @return true if all specified flags are set. + */ + bool test_flags(const BufferFlags flags) const noexcept; + /** * @brief Sets the specified flags for the buffer. * @param flags The flags to set. */ - void or_flags(const unsigned int flags); + void add_flags(const BufferFlags flags); /** * @brief Clears the specified flags for the buffer. * @param flags The flags to clear. + * @note Clears the corresponding flags by inverting and performing an &= operation */ - void and_flags(const unsigned int flags); + void clear_flags(const BufferFlags flags); /** * @brief Destructor. @@ -1046,14 +1062,14 @@ class BufferAllocatedType : public BufferType<T> BufferAllocatedType(const size_t offset, const size_t size, const size_t capacity, - const unsigned int flags); + const BufferFlags flags); /** * @brief Resets the buffer implementation with the specified minimum capacity and flags. * @param min_capacity The minimum capacity for the buffer. * @param flags The flags to set for the buffer. */ - void reset_impl(const size_t min_capacity, const unsigned int flags) override; + void reset_impl(const size_t min_capacity, const BufferFlags flags) override; /** * @brief Resizes the buffer to the specified new capacity. @@ -1074,7 +1090,7 @@ class BufferAllocatedType : public BufferType<T> void free_data(); private: - unsigned int flags_; + BufferFlags flags_; }; // =============================================================================================== @@ -1092,24 +1108,24 @@ ConstBufferType<T>::ConstBufferType() template <typename T> ConstBufferType<T>::ConstBufferType(void *data, const size_t size, const bool filled) - : ConstBufferType((T *)data, size, filled){}; + : ConstBufferType((T *)data, size, filled) {}; template <typename T> template <typename U, typename std::enable_if_t<!std::is_const_v<U>, int>> ConstBufferType<T>::ConstBufferType(const void *data, const size_t size, const bool filled) - : ConstBufferType(const_cast<void *>(data), size, filled){}; + : ConstBufferType(const_cast<void *>(data), size, filled) {}; template <typename T> ConstBufferType<T>::ConstBufferType(T *data, const size_t size, const bool filled) : data_(data), offset_(0), size_(filled ? size : 0), - capacity_(size){}; + capacity_(size) {}; template <typename T> template <typename U, typename std::enable_if_t<!std::is_const_v<U>, int>> ConstBufferType<T>::ConstBufferType(const U *data, const size_t size, const bool filled) - : ConstBufferType(const_cast<U *>(data), size, filled){}; + : ConstBufferType(const_cast<U *>(data), size, filled) {}; template <typename T> const auto &ConstBufferType<T>::operator[](const size_t index) const @@ -1337,8 +1353,7 @@ auto *ConstBufferType<T>::read_alloc(const size_t size) size_ -= size; return ret; } - else - OPENVPN_BUFFER_THROW(buffer_underflow); + OPENVPN_BUFFER_THROW(buffer_underflow); } template <typename T> @@ -1352,8 +1367,7 @@ auto ConstBufferType<T>::read_alloc_buf(const size_t size) size_ -= size; return ret; } - else - OPENVPN_BUFFER_THROW(buffer_underflow); + OPENVPN_BUFFER_THROW(buffer_underflow); } template <typename T> @@ -1589,14 +1603,16 @@ T *ConstBufferType<T>::prepend_alloc(const size_t request_size) } template <typename T> -void ConstBufferType<T>::reset(const size_t min_capacity, const unsigned int flags) +void ConstBufferType<T>::reset(const size_t min_capacity, const BufferFlags flags) { if (min_capacity > capacity_) reset_impl(min_capacity, flags); } template <typename T> -void ConstBufferType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) +void ConstBufferType<T>::reset(const size_t headroom, + const size_t min_capacity, + const BufferFlags flags) { reset(min_capacity, flags); init_headroom(headroom); @@ -1610,7 +1626,7 @@ void ConstBufferType<T>::append(const B &other) } template <typename T> -void ConstBufferType<T>::reset_impl(const size_t min_capacity, const unsigned int flags) +void ConstBufferType<T>::reset_impl(const size_t min_capacity, const BufferFlags flags) { OPENVPN_BUFFER_THROW(buffer_no_reset_impl); } @@ -1634,19 +1650,22 @@ void ConstBufferType<T>::buffer_full_error(const size_t newcap, const bool alloc template <typename T> ConstBufferType<T>::ConstBufferType(T *data, const size_t offset, const size_t size, const size_t capacity) - : data_(data), offset_(offset), size_(size), capacity_(capacity){}; + : data_(data), offset_(offset), size_(size), capacity_(capacity) {}; template <typename T> template <typename U, typename std::enable_if_t<!std::is_const_v<U>, int>> ConstBufferType<T>::ConstBufferType(const U *data, const size_t offset, const size_t size, const size_t capacity) - : ConstBufferType(const_cast<U *>(data), offset, size, capacity){}; + : ConstBufferType(const_cast<U *>(data), offset, size, capacity) {}; // =============================================================================================== // BufferAllocatedType<T> member function definitions // =============================================================================================== template <typename T> -BufferAllocatedType<T>::BufferAllocatedType(const size_t offset, const size_t size, const size_t capacity, const unsigned int flags) +BufferAllocatedType<T>::BufferAllocatedType(const size_t offset, + const size_t size, + const size_t capacity, + const BufferFlags flags) : BufferType<T>(capacity ? new T[capacity] : nullptr, offset, size, capacity), flags_(flags) { if (flags & BufAllocFlags::CONSTRUCT_ZERO) @@ -1655,18 +1674,24 @@ BufferAllocatedType<T>::BufferAllocatedType(const size_t offset, const size_t si template <typename T> BufferAllocatedType<T>::BufferAllocatedType() - : BufferAllocatedType(0, 0, 0, 0) + : BufferAllocatedType(0, 0, 0, BufAllocFlags::NO_FLAGS) { static_assert(std::is_nothrow_move_constructible_v<BufferAllocatedType>, "class BufferAllocatedType not noexcept move constructable"); } template <typename T> -BufferAllocatedType<T>::BufferAllocatedType(const size_t capacity, const unsigned int flags) - : BufferAllocatedType(0, flags & BufAllocFlags::ARRAY ? capacity : 0, capacity, flags){}; +BufferAllocatedType<T>::BufferAllocatedType(const size_t capacity, + const BufferFlags flags) + : BufferAllocatedType(0, + (flags & BufAllocFlags::ARRAY ? capacity : 0), + capacity, + flags) {}; template <typename T> -BufferAllocatedType<T>::BufferAllocatedType(const T *data, const size_t size, const unsigned int flags) +BufferAllocatedType<T>::BufferAllocatedType(const T *data, + const size_t size, + const BufferFlags flags) : BufferAllocatedType(0, size, size, flags) { if (size && data) @@ -1683,7 +1708,8 @@ BufferAllocatedType<T>::BufferAllocatedType(const BufferAllocatedType &other) template <typename T> template <typename T_> -BufferAllocatedType<T>::BufferAllocatedType(const BufferType<T_> &other, const unsigned int flags) +BufferAllocatedType<T>::BufferAllocatedType(const BufferType<T_> &other, + const BufferFlags flags) : BufferAllocatedType(other.offset(), other.size(), other.capacity(), flags) { static_assert(sizeof(T) == sizeof(T_), "size inconsistency"); @@ -1696,7 +1722,10 @@ void BufferAllocatedType<T>::operator=(const BufferAllocatedType &other) { if (this != &other) { - auto tempBuffer = BufferAllocatedType(other.offset(), other.size(), other.capacity(), other.flags_); + auto tempBuffer = BufferAllocatedType(other.offset(), + other.size(), + other.capacity(), + other.flags_); if (other.size()) std::memcpy(tempBuffer.data(), other.c_data(), tempBuffer.size() * sizeof(T)); swap(tempBuffer); @@ -1704,14 +1733,14 @@ void BufferAllocatedType<T>::operator=(const BufferAllocatedType &other) } template <typename T> -void BufferAllocatedType<T>::init(const size_t capacity, const unsigned int flags) +void BufferAllocatedType<T>::init(const size_t capacity, const BufferFlags flags) { auto tempBuffer = BufferAllocatedType(capacity, flags); swap(tempBuffer); } template <typename T> -void BufferAllocatedType<T>::init(const T *data, const size_t size, const unsigned int flags) +void BufferAllocatedType<T>::init(const T *data, const size_t size, const BufferFlags flags) { auto tempBuffer = BufferAllocatedType(data, size, flags); swap(tempBuffer); @@ -1738,14 +1767,16 @@ BufferAllocatedType<T> &BufferAllocatedType<T>::realign(const size_t headroom) } template <typename T> -void BufferAllocatedType<T>::reset(const size_t min_capacity, const unsigned int flags) +void BufferAllocatedType<T>::reset(const size_t min_capacity, const BufferFlags flags) { if (min_capacity > capacity()) init(min_capacity, flags); } template <typename T> -void BufferAllocatedType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) +void BufferAllocatedType<T>::reset(const size_t headroom, + const size_t min_capacity, + const BufferFlags flags) { reset(min_capacity, flags); init_headroom(headroom); @@ -1789,20 +1820,26 @@ BufferAllocatedType<T> &BufferAllocatedType<T>::operator=(BufferAllocatedType && template <typename T> void BufferAllocatedType<T>::clear() { - auto tempBuffer = BufferAllocatedType(0, 0, 0, 0); + auto tempBuffer = BufferAllocatedType(0, 0, 0, BufAllocFlags::NO_FLAGS); swap(tempBuffer); } template <typename T> -void BufferAllocatedType<T>::or_flags(const unsigned int flags) +bool BufferAllocatedType<T>::test_flags(const BufferFlags flags) const noexcept +{ + return flags_ & flags; +} + +template <typename T> +void BufferAllocatedType<T>::add_flags(const BufferFlags flags) { flags_ |= flags; } template <typename T> -void BufferAllocatedType<T>::and_flags(const unsigned int flags) +void BufferAllocatedType<T>::clear_flags(const BufferFlags flags) { - flags_ &= flags; + flags_ &= ~flags; } template <typename T> @@ -1813,7 +1850,7 @@ BufferAllocatedType<T>::~BufferAllocatedType() } template <typename T> -void BufferAllocatedType<T>::reset_impl(const size_t min_capacity, const unsigned int flags) +void BufferAllocatedType<T>::reset_impl(const size_t min_capacity, const BufferFlags flags) { init(min_capacity, flags); } @@ -1865,6 +1902,13 @@ using BufferPtr = RCPtr<BufferAllocatedRc>; using BufferAllocatedTS = RcEnable<BufferAllocated, RC<thread_safe_refcount>>; using BufferPtrTS = RCPtr<BufferAllocatedTS>; +// =============================================================================================== +// Deduction guide - needed to deduce converting ctor +// =============================================================================================== + +template <typename T_> +BufferAllocatedType(const BufferType<T_> &, BufferFlags) -> BufferAllocatedType<unsigned char>; + // =============================================================================================== // cast BufferType<T> to ConstBufferType<T> // =============================================================================================== @@ -1881,4 +1925,39 @@ inline const ConstBufferType<T> &const_buffer_ref(const BufferType<T> &src) return src; } +// =============================================================================================== +// Buffer related utilities - consider moving to a separate file +// =============================================================================================== + +/** + @brief Aligns buffer.data() to the required value and returns a pointer to the aligned object. + @tparam AlignT Type to align for + @param buf The buffer instance holding the possibly misaligned structure + @return AlignT* Pointer to now-aligned data in the buffer + @note This is only available on a buffer that owns the data. +*/ +template <typename AlignT, typename T> +inline AlignT *align_as(BufferAllocatedType<T> &buf) // TODO: Could be implemented noexcept +{ + /* The standard requires that alignof(T) is a power of 2, and that any allocation will be + aligned to at least alignof(std::max_align_t), so I assume offset zero in a buffer is + aligned and therefore there is no need to check for alignment of the buffer itself. + + This means a suitable address exists in the first alignof(std::max_align_t) so we never have + to increase the offset at all. This is a simplification that might not hold in all cases, + but it is a reasonable assumption for now. Given that, we can just align the buffer by + masking out the lower bits of the current data address (computation of align_ptr below) + and then realign the buffer to that address if needed. This will preserve as much of the + headroom as possible. + */ + auto data_ptr = reinterpret_cast<uintptr_t>(buf.c_data()); // Current data address in integral form + auto align_ptr = data_ptr & ~(alignof(AlignT) - 1); // 'Previous' aligned address + auto raw_data_ptr = reinterpret_cast<uintptr_t>(buf.c_data_raw()); // Start of allocated buffer + + if (align_ptr != data_ptr && align_ptr >= raw_data_ptr) + buf.realign(align_ptr - raw_data_ptr); + + return reinterpret_cast<AlignT *>(buf.data()); // unsigned char is type accessible by all types +} + } // namespace openvpn diff --git a/openvpn/buffer/bufip.hpp b/openvpn/buffer/bufip.hpp index e453629c4..27afc1274 100644 --- a/openvpn/buffer/bufip.hpp +++ b/openvpn/buffer/bufip.hpp @@ -22,7 +22,7 @@ namespace openvpn::BufferFormat { static inline void ipv4(Buffer &buf, const std::uint32_t addr) // addr is big-endian { - typedef BufferFormat::UnsignedDecimal<std::uint32_t> Decimal; + using Decimal = BufferFormat::UnsignedDecimal<std::uint32_t>; Decimal::write(buf, addr & 0xff); buf.push_back('.'); @@ -35,7 +35,7 @@ static inline void ipv4(Buffer &buf, const std::uint32_t addr) // addr is big-en static inline void ipv6(Buffer &buf, const void *addr) { - typedef BufferFormat::Hex<std::uint16_t> Hex; + using Hex = BufferFormat::Hex<std::uint16_t>; // address the IPv6 address as an array of 8 hextets const std::uint16_t *a = static_cast<const std::uint16_t *>(addr); @@ -92,7 +92,7 @@ static inline void ipv6(Buffer &buf, const void *addr) ipv4(buf, *reinterpret_cast<const std::uint32_t *>(a + 6)); return; } - else if (zero_extent == 6) + if (zero_extent == 6) { buf_append_string(buf, "::"); ipv4(buf, *reinterpret_cast<const std::uint32_t *>(a + 6)); diff --git a/openvpn/buffer/buflist.hpp b/openvpn/buffer/buflist.hpp index 21b54bd94..a681d6224 100644 --- a/openvpn/buffer/buflist.hpp +++ b/openvpn/buffer/buflist.hpp @@ -46,7 +46,7 @@ struct BufferCollection : public COLLECTION<BufferPtr> const size_t size = join_size(); // allocate buffer - auto big = BufferAllocatedRc::Create(size + headroom + tailroom, 0); + auto big = BufferAllocatedRc::Create(size + headroom + tailroom); big->init_headroom(headroom); // second pass -- copy data @@ -71,7 +71,7 @@ struct BufferCollection : public COLLECTION<BufferPtr> std::string to_string() const { - BufferPtr bp = join(); + const BufferPtr bp = join(); return buf_to_string(*bp); } @@ -93,7 +93,7 @@ struct BufferCollection : public COLLECTION<BufferPtr> // special optimization if buf data fits in // back() unused tail capacity -- if so, append // buf to existing back(). - BufferPtr &b = back(); + const BufferPtr &b = back(); const size_t r = b->remaining(tailroom); if (s < r) { @@ -105,8 +105,8 @@ struct BufferCollection : public COLLECTION<BufferPtr> } }; -typedef BufferCollection<std::list> BufferList; -typedef BufferCollection<std::vector> BufferVector; +using BufferList = BufferCollection<std::list>; +using BufferVector = BufferCollection<std::vector>; } // namespace openvpn #endif diff --git a/openvpn/buffer/bufread.hpp b/openvpn/buffer/bufread.hpp index 17923740f..7876ca4e5 100644 --- a/openvpn/buffer/bufread.hpp +++ b/openvpn/buffer/bufread.hpp @@ -45,7 +45,7 @@ inline BufferList buf_read(const int fd, const std::string &title) BufferList buflist; while (true) { - BufferAllocated buf(1024, 0); + BufferAllocated buf(1024); if (!buf_read(fd, buf, title)) break; buflist.put_consume(buf); diff --git a/openvpn/buffer/bufstr.hpp b/openvpn/buffer/bufstr.hpp index 33c4fb207..1ff387543 100644 --- a/openvpn/buffer/bufstr.hpp +++ b/openvpn/buffer/bufstr.hpp @@ -46,7 +46,7 @@ inline void buf_write_string(Buffer &buf, const char *str) inline BufferPtr buf_from_string(const std::string &str) { const size_t len = str.length(); - BufferPtr buf = BufferAllocatedRc::Create(len, 0); + BufferPtr buf = BufferAllocatedRc::Create(len); buf->write((unsigned char *)str.c_str(), len); return buf; } @@ -55,7 +55,7 @@ inline BufferPtr buf_from_string(const std::string &str) inline BufferPtr buf_from_string(const char *str) { const size_t len = std::strlen(str); - BufferPtr buf = BufferAllocatedRc::Create(len, 0); + BufferPtr buf = BufferAllocatedRc::Create(len); buf->write((unsigned char *)str, len); return buf; } @@ -64,7 +64,7 @@ inline BufferPtr buf_from_string(const char *str) inline BufferAllocated buf_alloc_from_string(const std::string &str) { const size_t len = str.length(); - BufferAllocated buf(len, 0); + BufferAllocated buf(len); buf.write((unsigned char *)str.c_str(), len); return buf; } @@ -73,7 +73,7 @@ inline BufferAllocated buf_alloc_from_string(const std::string &str) inline BufferAllocated buf_alloc_from_string(const char *str) { const size_t len = std::strlen(str); - BufferAllocated buf(len, 0); + BufferAllocated buf(len); buf.write((unsigned char *)str, len); return buf; } diff --git a/openvpn/buffer/bufstream.hpp b/openvpn/buffer/bufstream.hpp index 13dea4bea..6c5024d0c 100644 --- a/openvpn/buffer/bufstream.hpp +++ b/openvpn/buffer/bufstream.hpp @@ -47,7 +47,7 @@ class BufferStream : public std::streambuf { if (c != EOF) { - unsigned char uc = (unsigned char)c; + const unsigned char uc = (unsigned char)c; buf.push_back(uc); } return c; diff --git a/openvpn/buffer/lz4.hpp b/openvpn/buffer/lz4.hpp index 94cef65ab..89f7cd3a3 100644 --- a/openvpn/buffer/lz4.hpp +++ b/openvpn/buffer/lz4.hpp @@ -35,7 +35,7 @@ inline BufferPtr compress(const ConstBuffer &src, OPENVPN_THROW(lz4_error, "compress buffer size=" << src.size() << " exceeds LZ4_MAX_INPUT_SIZE=" << LZ4_MAX_INPUT_SIZE); // allocate dest buffer - auto dest = BufferAllocatedRc::Create(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size()), 0); + auto dest = BufferAllocatedRc::Create(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size())); dest->init_headroom(headroom); // as a hint to receiver, write the decompressed size @@ -73,7 +73,7 @@ inline BufferPtr decompress(const ConstBuffer &source, OPENVPN_THROW(lz4_error, "decompress expansion size=" << size << " is too large (must be <= " << max_decompressed_size << ')'); // allocate dest buffer - auto dest = BufferAllocatedRc::Create(headroom + tailroom + size, 0); + auto dest = BufferAllocatedRc::Create(headroom + tailroom + size); dest->init_headroom(headroom); // decompress diff --git a/openvpn/buffer/memq.hpp b/openvpn/buffer/memq.hpp index 16d7f64a9..043a24568 100644 --- a/openvpn/buffer/memq.hpp +++ b/openvpn/buffer/memq.hpp @@ -82,7 +82,7 @@ class MemQBase } protected: - typedef std::deque<BufferPtr> q_type; + using q_type = std::deque<BufferPtr>; size_t length; q_type q; }; diff --git a/openvpn/buffer/safestr.hpp b/openvpn/buffer/safestr.hpp index 110d905db..c7135dcb5 100644 --- a/openvpn/buffer/safestr.hpp +++ b/openvpn/buffer/safestr.hpp @@ -26,12 +26,10 @@ namespace openvpn { class SafeString { static constexpr size_t INITIAL_CAPACITY = 32; - static constexpr unsigned int BUF_FLAGS = BufAllocFlags::DESTRUCT_ZERO | BufAllocFlags::GROW; + static constexpr BufferFlags BUF_FLAGS{BufAllocFlags::DESTRUCT_ZERO | BufAllocFlags::GROW}; public: - SafeString() - { - } + SafeString() = default; SafeString(const char *str, const size_t size) : data(size + 1, BUF_FLAGS) @@ -56,8 +54,7 @@ class SafeString { if (data.defined()) return (const char *)data.c_data(); - else - return ""; + return ""; } // Note: unsafe because of conversion to std::string diff --git a/openvpn/buffer/zlib.hpp b/openvpn/buffer/zlib.hpp index e90f79826..6e396fd4f 100644 --- a/openvpn/buffer/zlib.hpp +++ b/openvpn/buffer/zlib.hpp @@ -80,7 +80,7 @@ inline BufferPtr compress_gzip(BufferPtr src, if (status != Z_OK) OPENVPN_THROW(zlib_error, "zlib deflateinit2 failed, error=" << status); const uLong outcap = ::deflateBound(&zs.s, src->size()); - auto b = BufferAllocatedRc::Create(outcap + headroom + tailroom, 0); + auto b = BufferAllocatedRc::Create(outcap + headroom + tailroom, BufAllocFlags::NO_FLAGS); b->init_headroom(headroom); zs.s.next_out = b->data(); zs.s.avail_out = numeric_cast<decltype(zs.s.avail_out)>(outcap); @@ -128,7 +128,7 @@ inline BufferPtr decompress_gzip(BufferPtr src, { // use headroom/tailroom on first block to take advantage // of BufferList::join() optimization for one-block lists - auto b = BufferAllocatedRc::Create(block_size + hr + tr, 0); + auto b = BufferAllocatedRc::Create(block_size + hr + tr, BufAllocFlags::NO_FLAGS); b->init_headroom(hr); const size_t avail = b->remaining(tr); zs.s.next_out = b->data(); diff --git a/openvpn/client/acc_certcheck.hpp b/openvpn/client/acc_certcheck.hpp index 9e47b98d4..8865a4ff4 100644 --- a/openvpn/client/acc_certcheck.hpp +++ b/openvpn/client/acc_certcheck.hpp @@ -124,7 +124,7 @@ inline AccHandshaker::MsgT AccHandshaker::process_msg(const MsgT &msg) { api.write_ciphertext(BufferAllocatedRc::Create(reinterpret_cast<const unsigned char *>(msg->c_str()), msg->size(), - 0)); + BufAllocFlags::NO_FLAGS)); // Won't handshake without this even though there is no data available. uint8_t cleartext[8]; diff --git a/openvpn/client/async_resolve.hpp b/openvpn/client/async_resolve.hpp index 881326260..d907a7594 100644 --- a/openvpn/client/async_resolve.hpp +++ b/openvpn/client/async_resolve.hpp @@ -20,8 +20,8 @@ // create shortcuts for common templated classes namespace openvpn { -typedef AsyncResolvable<openvpn_io::ip::udp::resolver> AsyncResolvableUDP; -typedef AsyncResolvable<openvpn_io::ip::tcp::resolver> AsyncResolvableTCP; +using AsyncResolvableUDP = AsyncResolvable<openvpn_io::ip::udp::resolver>; +using AsyncResolvableTCP = AsyncResolvable<openvpn_io::ip::tcp::resolver>; } // namespace openvpn #endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_H */ diff --git a/openvpn/client/async_resolve/asio.hpp b/openvpn/client/async_resolve/asio.hpp index de036c5b9..44e703173 100644 --- a/openvpn/client/async_resolve/asio.hpp +++ b/openvpn/client/async_resolve/asio.hpp @@ -25,14 +25,14 @@ template <typename RESOLVER_TYPE> class AsyncResolvable { private: - typedef RCPtr<AsyncResolvable> Ptr; + using Ptr = RCPtr<AsyncResolvable>; class ResolveThread : public RC<thread_safe_refcount> { friend class AsyncResolvable<RESOLVER_TYPE>; private: - typedef RCPtr<ResolveThread> Ptr; + using Ptr = RCPtr<ResolveThread>; openvpn_io::io_context &io_context; AsyncResolvable<RESOLVER_TYPE> *parent; diff --git a/openvpn/client/cliconnect.hpp b/openvpn/client/cliconnect.hpp index f5d67bba7..bae8b9bb1 100644 --- a/openvpn/client/cliconnect.hpp +++ b/openvpn/client/cliconnect.hpp @@ -64,8 +64,8 @@ class ClientConnect : ClientProto::NotifyCallback, public RC<thread_unsafe_refcount> { public: - typedef RCPtr<ClientConnect> Ptr; - typedef ClientOptions::Client Client; + using Ptr = RCPtr<ClientConnect>; + using Client = ClientOptions::Client; OPENVPN_SIMPLE_EXCEPTION(client_connect_unhandled_exception); @@ -94,10 +94,10 @@ class ClientConnect : ClientProto::NotifyCallback, if (!test_network()) throw ErrorCode(Error::NETWORK_UNAVAILABLE, true, "Network Unavailable"); - RemoteList::Ptr remote_list = client_options->remote_list_precache(); - RemoteList::BulkResolve::Ptr bulkres(new RemoteList::BulkResolve(io_context, - remote_list, - client_options->stats_ptr())); + const RemoteList::Ptr remote_list = client_options->remote_list_precache(); + const RemoteList::BulkResolve::Ptr bulkres(new RemoteList::BulkResolve(io_context, + remote_list, + client_options->stats_ptr())); if (bulkres->work_available()) { ClientEvent::Base::Ptr ev = new ClientEvent::Resolve(); @@ -309,7 +309,7 @@ class ClientConnect : ClientProto::NotifyCallback, } } - virtual void bulk_resolve_done() override + void bulk_resolve_done() override { if (!halt && generation == 0) new_client(); @@ -390,7 +390,7 @@ class ClientConnect : ClientProto::NotifyCallback, return true; } - virtual void client_proto_connected() override + void client_proto_connected() override { conn_timer.cancel(); conn_timer_pending = false; @@ -431,7 +431,7 @@ class ClientConnect : ClientProto::NotifyCallback, self->restart_wait_callback(gen, error); }); } - virtual void client_proto_auth_pending_timeout(int timeout) override + void client_proto_auth_pending_timeout(int timeout) override { if (conn_timer_pending) { @@ -455,7 +455,7 @@ class ClientConnect : ClientProto::NotifyCallback, template <typename ErrorClass> - void add_error_and_stop(const int error_code, const std::string &fatal_reason) + void add_error_and_stop(const Error::Type error_code, const std::string &fatal_reason) { ClientEvent::Base::Ptr ev = new ErrorClass{fatal_reason}; client_options->events().add_event(std::move(ev)); @@ -464,7 +464,7 @@ class ClientConnect : ClientProto::NotifyCallback, } template <typename ErrorClass> - void add_error_and_stop(const int error_code) + void add_error_and_stop(const Error::Type error_code) { ClientEvent::Base::Ptr ev = new ErrorClass{}; client_options->events().add_event(std::move(ev)); @@ -490,7 +490,7 @@ class ClientConnect : ClientProto::NotifyCallback, queue_restart(delay); } - virtual void client_proto_terminate() override + void client_proto_terminate() override { if (!halt) { @@ -507,7 +507,7 @@ class ClientConnect : ClientProto::NotifyCallback, { case Error::UNDEF: // means that there wasn't a fatal error { - std::chrono::duration client_delay = client->reconnect_delay(); + const std::chrono::duration client_delay = client->reconnect_delay(); queue_restart(client_delay.count() > 0 ? client_delay : default_delay_); } break; @@ -618,7 +618,7 @@ class ClientConnect : ClientProto::NotifyCallback, } } - void handle_auth_failed(const int error_code, const std::string &reason) + void handle_auth_failed(const Error::Type error_code, const std::string &reason) { if (ChallengeResponse::is_dynamic(reason)) // dynamic challenge/response? { @@ -672,7 +672,7 @@ class ClientConnect : ClientProto::NotifyCallback, } // client_config in cliopt.hpp - Client::Config::Ptr cli_config = client_options->client_config(!transport_factory_relay); + const Client::Config::Ptr cli_config = client_options->client_config(!transport_factory_relay); client.reset(new Client(io_context, *cli_config, this)); // build ClientProto::Session from cliproto.hpp client_finalized = false; @@ -698,22 +698,22 @@ class ClientConnect : ClientProto::NotifyCallback, // ClientLifeCycle::NotifyCallback callbacks - virtual void cln_stop() override + void cln_stop() override { thread_safe_stop(); } - virtual void cln_pause(const std::string &reason) override + void cln_pause(const std::string &reason) override { thread_safe_pause(reason); } - virtual void cln_resume() override + void cln_resume() override { thread_safe_resume(); } - virtual void cln_reconnect(int seconds) override + void cln_reconnect(int seconds) override { thread_safe_reconnect(seconds); } diff --git a/openvpn/client/clicreds.hpp b/openvpn/client/clicreds.hpp index 4e2000609..ca15629bc 100644 --- a/openvpn/client/clicreds.hpp +++ b/openvpn/client/clicreds.hpp @@ -30,9 +30,7 @@ namespace openvpn { class ClientCreds : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<ClientCreds> Ptr; - - ClientCreds() = default; + using Ptr = RCPtr<ClientCreds>; void set_username(const std::string &username_arg) { @@ -96,25 +94,22 @@ class ClientCreds : public RC<thread_unsafe_refcount> { if (dynamic_challenge) return dynamic_challenge->get_username(); - else if (!session_id_username.empty()) + if (!session_id_username.empty()) return session_id_username; - else - return username; + return username; } std::string get_password() const { if (dynamic_challenge) return dynamic_challenge->construct_dynamic_password(response); - else if (response.empty()) + if (response.empty()) { if (!session_id.empty()) return session_id; - else - return password; + return password; } - else - return ChallengeResponse::construct_static_password(password, response); + return ChallengeResponse::construct_static_password(password, response); } std::string get_http_proxy_username() const diff --git a/openvpn/client/cliemuexr.hpp b/openvpn/client/cliemuexr.hpp index f3d03f4f3..873e1055d 100644 --- a/openvpn/client/cliemuexr.hpp +++ b/openvpn/client/cliemuexr.hpp @@ -24,7 +24,7 @@ class EmulateExcludeRouteImpl : public EmulateExcludeRoute public: OPENVPN_EXCEPTION(emulate_exclude_route_error); - typedef RCPtr<EmulateExcludeRouteImpl> Ptr; + using Ptr = RCPtr<EmulateExcludeRouteImpl>; explicit EmulateExcludeRouteImpl(const bool exclude_server_address) : exclude_server_address_(exclude_server_address) @@ -47,7 +47,7 @@ class EmulateExcludeRouteImpl : public EmulateExcludeRoute bool enabled(const IPVerFlags &ipv) const override { - return exclude.size() && (ipv.rgv4() || ipv.rgv6()); + return !exclude.empty() && (ipv.rgv4() || ipv.rgv6()); } void emulate(TunBuilderBase *tb, IPVerFlags &ipv, const IP::Addr &server_addr) const override @@ -115,7 +115,7 @@ class EmulateExcludeRouteImpl : public EmulateExcludeRoute // excluded IPs. // Figure out if this particular route should be installed or not - IP::Route const *bestroute = nullptr; + const IP::Route *bestroute = nullptr; // Get the best (longest-prefix/smallest) route from included routes that completely // matches this route for (const auto &incRoute : include) @@ -148,7 +148,7 @@ class EmulateExcludeRouteImpl : public EmulateExcludeRoute class EmulateExcludeRouteFactoryImpl : public EmulateExcludeRouteFactory { public: - typedef RCPtr<EmulateExcludeRouteFactoryImpl> Ptr; + using Ptr = RCPtr<EmulateExcludeRouteFactoryImpl>; EmulateExcludeRouteFactoryImpl(const bool exclude_server_address) : exclude_server_address_(exclude_server_address) diff --git a/openvpn/client/clievent.hpp b/openvpn/client/clievent.hpp index c280eaeea..d0f78275b 100644 --- a/openvpn/client/clievent.hpp +++ b/openvpn/client/clievent.hpp @@ -169,8 +169,7 @@ inline const char *event_name(const Type type) static_assert(N_TYPES == array_size(names), "event names array inconsistency"); if (type < N_TYPES) return names[type]; - else - return "UNKNOWN_EVENT_TYPE"; + return "UNKNOWN_EVENT_TYPE"; } struct Connected; @@ -179,7 +178,7 @@ struct Connected; class Base : public RC<thread_safe_refcount> { public: - typedef RCPtr<Base> Ptr; + using Ptr = RCPtr<Base>; virtual ~Base() = default; Base(Type id) : id_(id) @@ -215,8 +214,7 @@ class Base : public RC<thread_safe_refcount> { if (id_ == CONNECTED) return (const Connected *)this; - else - return nullptr; + return nullptr; } private: @@ -416,7 +414,7 @@ struct TLSAlertProtocolUnknownCA : public Base struct InfoJSON : public Base { - typedef RCPtr<InfoJSON> Ptr; + using Ptr = RCPtr<InfoJSON>; InfoJSON(std::string msg_type_arg, Json::Value jdata_arg) @@ -443,7 +441,7 @@ struct InfoJSON : public Base struct UnsupportedFeature : public Base { - typedef RCPtr<UnsupportedFeature> Ptr; + using Ptr = RCPtr<UnsupportedFeature>; UnsupportedFeature(const std::string &name_arg, const std::string &reason_arg, bool critical_arg) : Base(UNSUPPORTED_FEATURE), @@ -467,7 +465,7 @@ struct UnsupportedFeature : public Base struct Connected : public Base { - typedef RCPtr<Connected> Ptr; + using Ptr = RCPtr<Connected>; Connected() : Base(CONNECTED) @@ -786,7 +784,7 @@ struct CompressionEnabled : public ReasonBase class Queue : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<Queue> Ptr; + using Ptr = RCPtr<Queue>; virtual void add_event(Base::Ptr event) = 0; }; diff --git a/openvpn/client/clihalt.hpp b/openvpn/client/clihalt.hpp index 871a5b93b..fe46e24e5 100644 --- a/openvpn/client/clihalt.hpp +++ b/openvpn/client/clihalt.hpp @@ -19,7 +19,6 @@ #include <openvpn/common/exception.hpp> #include <openvpn/common/split.hpp> #include <openvpn/common/unicode.hpp> -#include <openvpn/common/string.hpp> // Process halt/restart messages from server: // HALT,<client_reason> -> disconnect @@ -29,7 +28,7 @@ namespace openvpn { class ClientHalt { - typedef std::vector<std::string> StringList; + using StringList = std::vector<std::string>; public: OPENVPN_SIMPLE_EXCEPTION(client_halt_error); @@ -50,7 +49,7 @@ class ClientHalt if (sl.size() >= 2) { size_t reason_pos = 0; - if (restart_ && string::starts_with(sl[1], "[P]:")) + if (restart_ && sl[1].starts_with("[P]:")) { psid_ = true; reason_pos = 4; @@ -102,12 +101,12 @@ class ClientHalt static bool is_halt(const StringList &sl) { - return sl.size() >= 1 && sl[0] == "HALT"; + return !sl.empty() && sl[0] == "HALT"; } static bool is_restart(const StringList &sl) { - return sl.size() >= 1 && sl[0] == "RESTART"; + return !sl.empty() && sl[0] == "RESTART"; } bool restart_ = false; diff --git a/openvpn/client/clilife.hpp b/openvpn/client/clilife.hpp index 363dcd674..d8133bf31 100644 --- a/openvpn/client/clilife.hpp +++ b/openvpn/client/clilife.hpp @@ -32,7 +32,7 @@ class ClientLifeCycle : public RC<thread_unsafe_refcount> virtual void cln_reconnect(int seconds) = 0; }; - typedef RCPtr<ClientLifeCycle> Ptr; + using Ptr = RCPtr<ClientLifeCycle>; virtual bool network_available() = 0; diff --git a/openvpn/client/cliopt.hpp b/openvpn/client/cliopt.hpp index 63900570c..7d9638d3c 100644 --- a/openvpn/client/cliopt.hpp +++ b/openvpn/client/cliopt.hpp @@ -57,16 +57,16 @@ #include <openvpn/transport/gremlin.hpp> #endif -#if defined(OPENVPN_PLATFORM_ANDROID) +#ifdef OPENVPN_PLATFORM_ANDROID #include <openvpn/client/cliemuexr.hpp> #endif -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) +#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY #include <openvpn/transport/client/extern/config.hpp> #include <openvpn/transport/client/extern/fw.hpp> #endif -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#ifdef OPENVPN_EXTERNAL_TUN_FACTORY // requires that client implements ExternalTun::Factory::new_tun_factory #include <openvpn/tun/extern/config.hpp> #elif defined(USE_TUN_BUILDER) @@ -144,9 +144,9 @@ struct ClientConfigParsed : public ClientAPI::ConfigCommon class ClientOptions : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<ClientOptions> Ptr; + using Ptr = RCPtr<ClientOptions>; - typedef ClientProto::Session Client; + using Client = ClientProto::Session; struct Config { @@ -180,15 +180,15 @@ class ClientOptions : public RC<thread_unsafe_refcount> ReconnectNotify *reconnect_notify = nullptr; RemoteList::RemoteOverride *remote_override = nullptr; -#if defined(USE_TUN_BUILDER) +#ifdef USE_TUN_BUILDER TunBuilderBase *builder = nullptr; #endif -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#ifdef OPENVPN_EXTERNAL_TUN_FACTORY ExternalTun::Factory *extern_tun_factory = nullptr; #endif -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) +#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY ExternalTransport::Factory *extern_transport_factory = nullptr; #endif }; @@ -360,7 +360,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> tunconf.tun_prop.remote_list = remote_list; tunconf.stop = config.stop; tunconf.allow_local_dns_resolvers = config.clientconf.allowLocalDnsResolvers; -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN if (config.clientconf.tunPersist) tunconf.tun_persist.reset(new TunWin::DcoTunPersist(true, TunWrapObjRetain::NO_RETAIN_NO_REPLACE, nullptr)); #endif @@ -368,7 +368,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> } else { -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#ifdef OPENVPN_EXTERNAL_TUN_FACTORY { ExternalTun::Config tunconf; tunconf.tun_prop.layer = layer; @@ -598,7 +598,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> * string property (if applicable) */ static std::tuple<bool, std::string> check_dco_compatibility(const ClientAPI::ConfigCommon &config, const OptionList &opt) { -#if defined(ENABLE_KOVPN) +#ifdef ENABLE_KOVPN // only care about dco/dco-win return std::make_tuple(true, ""); #else @@ -632,10 +632,9 @@ class ClientOptions : public RC<thread_unsafe_refcount> { return std::make_tuple(true, ""); } - else - { - return std::make_tuple(false, string::join(reasons, "\n")); - } + + return std::make_tuple(false, string::join(reasons, "\n")); + #endif } @@ -881,7 +880,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> public: void add_failed_opt(const Option &o, const std::string &message, bool fatal_arg) { - if (options_per_category.find(message) == options_per_category.end()) + if (!options_per_category.contains(message)) { options_per_category[message] = {}; } @@ -909,7 +908,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> opts.push_back(o.get(0, 64)); } - os << string::join(opts, ",") << std::endl; + os << string::join(opts, ",") << '\n'; } } @@ -968,11 +967,11 @@ class ClientOptions : public RC<thread_unsafe_refcount> for (const auto &o : opt) { - if (!o.meta() && settings_ignoreSilently.find(o.get(0, 0)) != settings_ignoreSilently.end()) + if (!o.meta() && settings_ignoreSilently.contains(o.get(0, 0))) { o.touch(); } - if (o.meta() && ignoreMetaOptions.find(o.get(0, 0)) != ignoreMetaOptions.end()) + if (o.meta() && ignoreMetaOptions.contains(o.get(0, 0))) { o.touch(); } @@ -983,7 +982,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> if (opt.n_unused() == 0) return; - OPENVPN_LOG_NTNL("NOTE: This configuration contains options that were not used:" << std::endl); + OPENVPN_LOG_NTNL("NOTE: This configuration contains options that were not used:\n"); OptionErrors errors{}; @@ -1025,7 +1024,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> void showUnusedOptionsByList(const OptionList &optlist, std::unordered_set<std::string> option_set, const std::string &message, bool fatal, OptionErrors &errors) { auto func = [&option_set](const Option &opt) - { return !opt.touched() && option_set.find(opt.get(0, 0)) != option_set.end(); }; + { return !opt.touched() && option_set.contains(opt.get(0, 0)); }; showOptionsByFunction(optlist, func, message, fatal, errors); } @@ -1074,7 +1073,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> if (pcc.peerInfoUV()) { - for (auto const &kv : *pcc.peerInfoUV()) + for (const auto &kv : *pcc.peerInfoUV()) { extra_values[kv.key] = kv.value; } @@ -1083,7 +1082,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> /* Config::peerInfo takes precedence */ if (config.extra_peer_info.get()) { - for (auto const &kv : *config.extra_peer_info.get()) + for (const auto &kv : *config.extra_peer_info.get()) { extra_values[kv.key] = kv.value; } @@ -1129,8 +1128,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> { if (reconnect_notify) return reconnect_notify->pause_on_connection_timeout(); - else - return false; + return false; } bool retry_on_auth_failed() const @@ -1275,8 +1273,7 @@ class ClientOptions : public RC<thread_unsafe_refcount> { if (relay_mode && cp_relay) return *cp_relay; - else - return *cp_main; + return *cp_main; } ProtoContext::ProtoConfig::Ptr proto_config(const OptionList &opt, diff --git a/openvpn/client/cliopthelper.hpp b/openvpn/client/cliopthelper.hpp index b6cc52193..48130462b 100644 --- a/openvpn/client/cliopthelper.hpp +++ b/openvpn/client/cliopthelper.hpp @@ -94,7 +94,7 @@ class ParseClientConfig message_ = "ERR_PROFILE_SERVER_LOCKED_UNSUPPORTED: server locked profiles are currently unsupported"; return; } - else if (arg1 == "ALLOW_PASSWORD_SAVE") + if (arg1 == "ALLOW_PASSWORD_SAVE") allowPasswordSave_ = parse_bool(o, "setenv ALLOW_PASSWORD_SAVE", 2); else if (arg1 == "CLIENT_CERT") clientCertEnabled_ = parse_bool(o, "setenv CLIENT_CERT", 2); @@ -122,7 +122,7 @@ class ParseClientConfig } else if (arg1 == "PUSH_PEER_INFO") pushPeerInfo_ = true; - else if (string::starts_with(arg1, "UV_") && arg1.length() >= 4 && string::is_word(arg1)) + else if (arg1.starts_with("UV_") && arg1.length() >= 4 && string::is_word(arg1)) { const std::string value = o.get_optional(2, 256); if (string::is_printable(value)) @@ -147,7 +147,7 @@ class ParseClientConfig // userlocked username/password via <auth-user-pass> std::vector<std::string> user_pass; const bool auth_user_pass = parse_auth_user_pass(options, &user_pass); - if (auth_user_pass && user_pass.size() >= 1) + if (auth_user_pass && !user_pass.empty()) { userlockedUsername_ = user_pass[0]; if (user_pass.size() >= 2) @@ -533,9 +533,9 @@ class ParseClientConfig { std::ostringstream os; - os << "client" << std::endl; - os << "dev " << dev << std::endl; - os << "dev-type " << protoConfig->layer.dev_type() << std::endl; + os << "client\n"; + os << "dev " << dev << '\n'; + os << "dev-type " << protoConfig->layer.dev_type() << '\n'; for (size_t i = 0; i < remoteList->size(); i++) { const RemoteList::Item::Ptr item = remoteList->get_item(i); @@ -544,20 +544,18 @@ class ParseClientConfig const char *proto = item->transport_protocol.protocol_to_string(); if (proto) os << " " << proto; - os << std::endl; + os << '\n'; } if (protoConfig->tls_crypt_context) { - os << "<tls-crypt>" << std::endl - << protoConfig->tls_key.render() << "</tls-crypt>" - << std::endl; + os << "<tls-crypt>\n" + << protoConfig->tls_crypt_key.render() << "</tls-crypt>\n"; } else if (protoConfig->tls_auth_context) { - os << "<tls-auth>" << std::endl - << protoConfig->tls_key.render() << "</tls-auth>" - << std::endl; - os << "key_direction " << protoConfig->key_direction << std::endl; + os << "<tls-auth>\n" + << protoConfig->tls_auth_key.render() << "</tls-auth>\n"; + os << "key_direction " << protoConfig->key_direction << '\n'; } // SSL parameters @@ -569,28 +567,28 @@ class ParseClientConfig print_pem(os, "cert", sslConfig->extract_cert()); std::vector<std::string> extra_certs = sslConfig->extract_extra_certs(); - if (extra_certs.size() > 0) + if (!extra_certs.empty()) { - os << "<extra-certs>" << std::endl; + os << "<extra-certs>\n"; for (auto &cert : extra_certs) { os << cert; } - os << "</extra-certs>" << std::endl; + os << "</extra-certs>\n"; } } os << "cipher " << CryptoAlgs::name(protoConfig->dc.cipher(), "none") - << std::endl; + << '\n'; os << "auth " << CryptoAlgs::name(protoConfig->dc.digest(), "none") - << std::endl; + << '\n'; const char *comp = protoConfig->comp_ctx.method_to_string(); if (comp) - os << "compress " << comp << std::endl; + os << "compress " << comp << '\n'; os << "keepalive " << protoConfig->keepalive_ping.to_seconds() << " " - << protoConfig->keepalive_timeout.to_seconds() << std::endl; - os << "tun-mtu " << protoConfig->tun_mtu << std::endl; - os << "reneg-sec " << protoConfig->renegotiate.to_seconds() << std::endl; + << protoConfig->keepalive_timeout.to_seconds() << '\n'; + os << "tun-mtu " << protoConfig->tun_mtu << '\n'; + os << "reneg-sec " << protoConfig->renegotiate.to_seconds() << '\n'; return os.str(); } @@ -684,8 +682,8 @@ class ParseClientConfig { if (pem.empty()) return; - os << "<" << label << ">" << std::endl - << pem << "</" << label << ">" << std::endl; + os << "<" << label << ">\n" + << pem << "</" << label << ">\n"; } #ifdef HAVE_CONFIG_JSONCPP @@ -723,28 +721,24 @@ class ParseClientConfig { if (auth_user_pass && user_pass.size() >= 2) // embedded password? return true; - else + + const Option *autologin = options.get_ptr("AUTOLOGIN"); + if (autologin) + return string::is_true(autologin->get_optional(1, 16)); + + bool ret = !auth_user_pass; + if (ret) { - const Option *autologin = options.get_ptr("AUTOLOGIN"); - if (autologin) - return string::is_true(autologin->get_optional(1, 16)); - else - { - bool ret = !auth_user_pass; - if (ret) - { - // External PKI profiles from AS don't declare auth-user-pass, - // and we have no way of knowing if they are autologin unless - // we examine their cert, which requires accessing the system-level - // cert store on the client. For now, we are going to assume - // that External PKI profiles from the AS are always userlogin, - // unless explicitly overriden by AUTOLOGIN above. - if (options.exists("EXTERNAL_PKI")) - return false; - } - return ret; - } + // External PKI profiles from AS don't declare auth-user-pass, + // and we have no way of knowing if they are autologin unless + // we examine their cert, which requires accessing the system-level + // cert store on the client. For now, we are going to assume + // that External PKI profiles from the AS are always userlogin, + // unless explicitly overriden by AUTOLOGIN above. + if (options.exists("EXTERNAL_PKI")) + return false; } + return ret; } static bool is_external_pki(const OptionList &options) @@ -752,12 +746,10 @@ class ParseClientConfig const Option *epki = options.get_ptr("EXTERNAL_PKI"); if (epki) return string::is_true(epki->get_optional(1, 16)); - else - { - const Option *cert = options.get_ptr("cert"); - const Option *key = options.get_ptr("key"); - return !cert || !key; - } + + const Option *cert = options.get_ptr("cert"); + const Option *key = options.get_ptr("key"); + return !cert || !key; } void reset_pod() @@ -773,10 +765,9 @@ class ParseClientConfig const std::string parm = o.get(index, 16); if (parm == "0") return false; - else if (parm == "1") + if (parm == "1") return true; - else - throw option_error(ERR_INVALID_OPTION_VAL, title + ": parameter must be 0 or 1"); + throw option_error(ERR_INVALID_OPTION_VAL, title + ": parameter must be 0 or 1"); } bool error_; diff --git a/openvpn/client/cliproto.hpp b/openvpn/client/cliproto.hpp index 88fc2dc23..d2d7c5807 100644 --- a/openvpn/client/cliproto.hpp +++ b/openvpn/client/cliproto.hpp @@ -95,7 +95,7 @@ class Session : ProtoContextCallbackInterface, static inline const std::string certcheckProto = "cck1"; public: - typedef RCPtr<Session> Ptr; + using Ptr = RCPtr<Session>; OPENVPN_EXCEPTION(client_exception); OPENVPN_EXCEPTION(client_halt_restart); @@ -111,7 +111,7 @@ class Session : ProtoContextCallbackInterface, struct Config : public RC<thread_unsafe_refcount> { - typedef RCPtr<Config> Ptr; + using Ptr = RCPtr<Config>; Config() : pushed_options_limit("server-pushed options data too large", @@ -253,7 +253,7 @@ class Session : ProtoContextCallbackInterface, set_housekeeping_timer(); } - void post_app_control_message(const std::string proto, const std::string message) + void post_app_control_message(const std::string &proto, const std::string &message) { if (!proto_context.conf().app_control_config.supports_protocol(proto)) { @@ -369,14 +369,14 @@ class Session : ProtoContextCallbackInterface, } // get packet type - ProtoContext::PacketType pt = proto_context.packet_type(buf); + const ProtoContext::PacketType pt = proto_context.packet_type(buf); // process packet if (pt.is_data()) { // data packet proto_context.data_decrypt(pt, buf); - if (buf.size()) + if (!buf.empty()) { #ifdef OPENVPN_PACKET_LOG log_packet(buf, false); @@ -454,7 +454,7 @@ class Session : ProtoContextCallbackInterface, } // encrypt packet - if (buf.size()) + if (!buf.empty()) { const ProtoContext::ProtoConfig &c = proto_context.conf(); @@ -469,7 +469,7 @@ class Session : ProtoContextCallbackInterface, // here we need to add it back since we check the whole IP packet size, not just TCP payload constexpr size_t MinTcpHeader = 20; constexpr size_t MinIpHeader = 20; - size_t mss_no_tcp_ip_encap = c.mss_fix + (MinTcpHeader + MinIpHeader); + const size_t mss_no_tcp_ip_encap = c.mss_fix + (MinTcpHeader + MinIpHeader); if (df && c.mss_fix > 0 && buf.size() > mss_no_tcp_ip_encap) { @@ -479,7 +479,7 @@ class Session : ProtoContextCallbackInterface, else { proto_context.data_encrypt(buf); - if (buf.size()) + if (!buf.empty()) { // send packet via transport to destination OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << proto_context.dump_packet(buf)); @@ -735,7 +735,7 @@ class Session : ProtoContextCallbackInterface, if (msg.length() >= 13) reason = string::trim_left_copy(std::string(msg, 12)); - if (string::starts_with(reason, "TEMP")) + if (reason.starts_with("TEMP")) { log_reason = "AUTH_FAILED_TEMP:" + parse_auth_failed_temp(std::string(reason, 4)); } @@ -810,12 +810,12 @@ class Session : ProtoContextCallbackInterface, unsigned int timeout = 0; - if (string::starts_with(msg, "AUTH_PENDING,")) + if (msg.starts_with("AUTH_PENDING,")) { key_words = msg.substr(strlen("AUTH_PENDING,")); auto opts = OptionList::parse_from_csv_static(key_words, nullptr); - std::string timeout_str = opts.get_optional("timeout", 1, 20); - if (timeout_str != "") + const std::string timeout_str = opts.get_optional("timeout", 1, 20); + if (!timeout_str.empty()) { try { @@ -875,7 +875,7 @@ class Session : ProtoContextCallbackInterface, else info_msg = msg.substr(std::string_view{"INFO,"}.length()); - if (string::starts_with(info_msg, "ACC:")) + if (info_msg.starts_with("ACC:")) { // We want this to be parsed exactly like the custom-control option. // That means we replace ACC: with custom-control for the parser. @@ -886,7 +886,7 @@ class Session : ProtoContextCallbackInterface, } else { - if ((string::starts_with(info_msg, "WEB_AUTH:") || string::starts_with(info_msg, "CR_TEXT:")) && creds) + if ((info_msg.starts_with("WEB_AUTH:") || info_msg.starts_with("CR_TEXT:")) && creds) { creds->set_need_user_interaction(); } @@ -944,11 +944,11 @@ class Session : ProtoContextCallbackInterface, // OPENVPN_LOG("SERVER: " << sanitize_control_message(msg)); - if (string::starts_with(msg, "PUSH_REPLY,")) + if (msg.starts_with("PUSH_REPLY,")) { recv_push_reply(msg); } - else if (string::starts_with(msg, "AUTH_FAILED")) + else if (msg.starts_with("AUTH_FAILED")) { recv_auth_failed(msg); } @@ -956,15 +956,15 @@ class Session : ProtoContextCallbackInterface, { recv_halt_restart(msg); } - else if (info && string::starts_with(msg, "INFO,")) + else if (info && msg.starts_with("INFO,")) { recv_info(msg, false); } - else if (info && string::starts_with(msg, "INFO_PRE,")) + else if (info && msg.starts_with("INFO_PRE,")) { recv_info(msg, true); } - else if (msg == "AUTH_PENDING" || string::starts_with(msg, "AUTH_PENDING,")) + else if (msg == "AUTH_PENDING" || msg.starts_with("AUTH_PENDING,")) { recv_auth_pending(msg); } @@ -972,11 +972,11 @@ class Session : ProtoContextCallbackInterface, { recv_relay(); } - else if (string::starts_with(msg, "ACC,")) + else if (msg.starts_with("ACC,")) { recv_custom_control_message(msg); } - else if (string::starts_with(msg, "PUSH_UPDATE,")) + else if (msg.starts_with("PUSH_UPDATE,")) { recv_push_update(msg); } @@ -991,9 +991,9 @@ class Session : ProtoContextCallbackInterface, for supported protocols to be handled later. It acts as the interface between the lower-level network code receiving the raw message, and the higher-level event handling logic. */ - void recv_custom_control_message(const std::string msg) + void recv_custom_control_message(const std::string &msg) { - bool fullmessage = proto_context.conf().app_control_recv.receive_message(msg); + const bool fullmessage = proto_context.conf().app_control_recv.receive_message(msg); if (!fullmessage) return; @@ -1072,8 +1072,8 @@ class Session : ProtoContextCallbackInterface, if (received_options.complete()) { // show options - OPENVPN_LOG("OPTIONS:" << std::endl - << render_options_sanitized(received_options, Option::RENDER_PASS_FMT | Option::RENDER_NUMBER | Option::RENDER_BRACKET)); + OPENVPN_LOG("OPTIONS:\n" + << render_options_sanitized(received_options, Option::RENDER_PASS_FMT | Option::RENDER_NUMBER | Option::RENDER_BRACKET)); // relay servers are not allowed to establish a tunnel with us if (proto_context.conf().relay_mode) @@ -1197,7 +1197,7 @@ class Session : ProtoContextCallbackInterface, try { - std::string client_ip = received_options.get_optional("client-ip", 1, 256); + const std::string client_ip = received_options.get_optional("client-ip", 1, 256); if (!client_ip.empty()) ev->client_ip = IP::Addr::validate(client_ip, "client-ip"); } @@ -1327,7 +1327,7 @@ class Session : ProtoContextCallbackInterface, // react to any tls warning triggered during the tls-handshake virtual void check_tls_warnings() { - uint32_t tls_warnings = proto_context.get_tls_warnings(); + const uint32_t tls_warnings = proto_context.get_tls_warnings(); if (tls_warnings & SSLAPI::TLS_WARN_SIG_MD5) { @@ -1350,7 +1350,7 @@ class Session : ProtoContextCallbackInterface, cli_events->add_event(std::move(ev)); } - CompressContext::Type comp_type = proto_context.conf().comp_ctx.type(); + const CompressContext::Type comp_type = proto_context.conf().comp_ctx.type(); // abort connection if compression is pushed and its support is unannounced if (comp_type != CompressContext::COMP_STUBv2 @@ -1555,7 +1555,7 @@ class Session : ProtoContextCallbackInterface, void process_echo(const OptionList &opt) { - OptionList::IndexMap::const_iterator echo_opt = opt.map().find("echo"); + const OptionList::IndexMap::const_iterator echo_opt = opt.map().find("echo"); if (echo_opt != opt.map().end()) { for (OptionList::IndexList::const_iterator i = echo_opt->second.begin(); i != echo_opt->second.end(); ++i) diff --git a/openvpn/client/dns.hpp b/openvpn/client/dns.hpp index 3e1a99185..132b51f6b 100644 --- a/openvpn/client/dns.hpp +++ b/openvpn/client/dns.hpp @@ -224,7 +224,7 @@ struct DnsOptionsParser : public DnsOptions for (size_t i = 2; i < o.size(); ++i) { using StrVec = std::vector<std::string>; - StrVec domains = Split::by_space<StrVec, StandardLex, SpaceMatch, Split::NullLimit>(o.get(i, 256)); + const StrVec domains = Split::by_space<StrVec, StandardLex, SpaceMatch, Split::NullLimit>(o.get(i, 256)); if (ignore_values) { continue; @@ -266,7 +266,7 @@ struct DnsOptionsParser : public DnsOptions search_domains.insert(search_domains.begin(), DnsDomain(std::move(adapter_domain_suffix))); } - if (!ignore_values && servers.size() && servers[0].addresses.empty()) + if (!ignore_values && !servers.empty() && servers[0].addresses.empty()) { parse_errors += "\n"; parse_errors += "dns server does not have an address assigned"; diff --git a/openvpn/client/dns_options.hpp b/openvpn/client/dns_options.hpp index 11ac58088..9892c58be 100644 --- a/openvpn/client/dns_options.hpp +++ b/openvpn/client/dns_options.hpp @@ -112,7 +112,7 @@ struct DnsAddress { std::ostringstream os; - IP::Addr addr(address); + const IP::Addr addr(address); os << (addr.is_ipv6() && port ? "[" : "") << address << (addr.is_ipv6() && port ? "]" : ""); @@ -144,7 +144,7 @@ struct DnsAddress void from_json(const Json::Value &root, const std::string &title) { json::assert_dict(root, title); - json::to_uint_optional(root, port, "port", 0u, title); + json::to_uint_optional(root, port, "port", 0U, title); std::string addr_str; json::to_string(root, addr_str, "address", title); @@ -152,6 +152,8 @@ struct DnsAddress } #endif + bool operator==(const DnsAddress &) const = default; + std::string address; unsigned int port = 0; }; @@ -202,6 +204,8 @@ struct DnsDomain #endif std::string domain; + + bool operator==(const DnsDomain &) const = default; }; /** @@ -501,6 +505,8 @@ struct DnsServer } #endif + bool operator==(const DnsServer &at) const = default; + //! Parsed from --dns server n address ADDRESS[:PORT] [...] or --dhcp-option DNS/DNS6 std::vector<DnsAddress> addresses; @@ -618,6 +624,8 @@ struct DnsOptions } #endif + bool operator==(const DnsOptions &at) const = default; + bool from_dhcp_options = false; ///< Set to true if the DNS options comes from --dhcp-option options std::vector<DnsDomain> search_domains; ///< List of global DNS search domains to use std::map<int, DnsServer> servers; ///< List of DNS servers to use, according to the list of priority diff --git a/openvpn/client/optfilt.hpp b/openvpn/client/optfilt.hpp index 590f45612..c30d91b2d 100644 --- a/openvpn/client/optfilt.hpp +++ b/openvpn/client/optfilt.hpp @@ -16,7 +16,6 @@ #include <openvpn/common/options.hpp> #include <openvpn/common/numeric_util.hpp> -#include <openvpn/common/string.hpp> #include <openvpn/client/dns.hpp> // Options filters, consumes the route-nopull and pull-filter client options @@ -49,8 +48,8 @@ class PushedOptionsFilter : public OptionList::FilterBase else throw option_error(ERR_INVALID_OPTION_VAL, "invalid pull-filter action: " + action_str); - Option match = OptionList::parse_option_from_line(o.get(2, -1), nullptr); - pull_filter_list_.push_back({action, match}); + const Option match = OptionList::parse_option_from_line(o.get(2, -1), nullptr); + pull_filter_list_.push_back({.action = action, .match = match}); } } @@ -129,7 +128,7 @@ class PushedOptionsFilter : public OptionList::FilterBase if (!is_safe_conversion<int>(match.size() - 1)) return false; int i = static_cast<int>(match.size() - 1); - if (!string::starts_with(pushed.get(i, -1), match.get(i, -1))) + if (!pushed.get(i, -1).starts_with(match.get(i, -1))) return false; while (--i >= 0) @@ -145,10 +144,10 @@ class PushedOptionsFilter : public OptionList::FilterBase FilterAction route_nopull_filter_(const Option &opt) { FilterAction action = Accept; - if (opt.size() >= 1) + if (!opt.empty()) { const std::string &directive = opt.ref(0); - if (directive.length() >= 1) + if (!directive.empty()) { switch (directive[0]) { diff --git a/openvpn/client/remotelist.hpp b/openvpn/client/remotelist.hpp index efd97be5e..0c9a59d95 100644 --- a/openvpn/client/remotelist.hpp +++ b/openvpn/client/remotelist.hpp @@ -54,7 +54,7 @@ class RemoteList : public RC<thread_unsafe_refcount> // associated with a "remote" item. struct ResolvedAddr : public RC<thread_unsafe_refcount> { - typedef RCPtr<ResolvedAddr> Ptr; + using Ptr = RCPtr<ResolvedAddr>; IP::Addr addr; std::string to_string() const @@ -66,7 +66,7 @@ class RemoteList : public RC<thread_unsafe_refcount> // The IP address list associated with a single "remote" item. struct ResolvedAddrList : public std::vector<ResolvedAddr::Ptr>, public RC<thread_unsafe_refcount> { - typedef RCPtr<ResolvedAddrList> Ptr; + using Ptr = RCPtr<ResolvedAddrList>; std::string to_string() const { @@ -93,14 +93,14 @@ class RemoteList : public RC<thread_unsafe_refcount> struct ConnBlock : public RC<thread_unsafe_refcount> { - typedef RCPtr<ConnBlock> Ptr; + using Ptr = RCPtr<ConnBlock>; virtual void new_item(const Item &item) = 0; }; struct ConnBlockFactory { - typedef RCPtr<ConnBlockFactory> Ptr; + using Ptr = RCPtr<ConnBlockFactory>; virtual ~ConnBlockFactory() = default; @@ -110,7 +110,7 @@ class RemoteList : public RC<thread_unsafe_refcount> // A single "remote" item struct Item : public RC<thread_unsafe_refcount> { - typedef RCPtr<Item> Ptr; + using Ptr = RCPtr<Item>; // "remote" item parameters from config file std::string server_host; @@ -131,7 +131,7 @@ class RemoteList : public RC<thread_unsafe_refcount> bool res_addr_list_defined() const { - return res_addr_list && res_addr_list->size() > 0; + return res_addr_list && !res_addr_list->empty(); } std::string actual_host() const @@ -198,8 +198,7 @@ class RemoteList : public RC<thread_unsafe_refcount> OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint GET[" << index << "] " << endpoint << ' ' << to_string()); return true; } - else - return false; + return false; } bool need_resolve() @@ -231,7 +230,7 @@ class RemoteList : public RC<thread_unsafe_refcount> struct Directives { explicit Directives(const std::string &conn_tag = "") - : connection(conn_tag.length() ? conn_tag : "connection") + : connection(!conn_tag.empty() ? conn_tag : "connection") { } @@ -276,8 +275,7 @@ class RemoteList : public RC<thread_unsafe_refcount> item_ = 0; return true; } - else - return false; + return false; } private: @@ -291,7 +289,7 @@ class RemoteList : public RC<thread_unsafe_refcount> // (option_error used during initial options processing). OPENVPN_EXCEPTION(remote_list_error); - typedef RCPtr<RemoteList> Ptr; + using Ptr = RCPtr<RemoteList>; // Helper class used to resolve all items in remote list. // This is useful in tun_persist mode, where it may be necessary @@ -301,7 +299,7 @@ class RemoteList : public RC<thread_unsafe_refcount> class BulkResolve : public virtual RC<thread_unsafe_refcount>, protected AsyncResolvableTCP { public: - typedef RCPtr<BulkResolve> Ptr; + using Ptr = RCPtr<BulkResolve>; struct NotifyCallback { @@ -685,7 +683,7 @@ class RemoteList : public RC<thread_unsafe_refcount> // return true if object has at least one connection entry bool defined() const { - return list.size() > 0; + return !list.empty(); } // return remote list size @@ -726,7 +724,7 @@ class RemoteList : public RC<thread_unsafe_refcount> for (size_t i = 0; i < list.size(); ++i) { const Item &e = *list[i]; - out << '[' << i << "] " << e.to_string() << std::endl; + out << '[' << i << "] " << e.to_string() << '\n'; } return out.str(); } @@ -805,8 +803,7 @@ class RemoteList : public RC<thread_unsafe_refcount> const size_t pri = index.item(); if (pri < list.size()) return pri; - else - throw remote_list_error("current remote server item is undefined"); + throw remote_list_error("current remote server item is undefined"); } // return the number of cached IP addresses associated with a given item diff --git a/openvpn/client/rgopt.hpp b/openvpn/client/rgopt.hpp index b85c0fc15..935dd6dd5 100644 --- a/openvpn/client/rgopt.hpp +++ b/openvpn/client/rgopt.hpp @@ -115,7 +115,7 @@ class RedirectGatewayFlags void doinit(const OptionList &opt, const std::string &directive, const bool redirect_gateway) { - OptionList::IndexMap::const_iterator rg = opt.map().find(directive); + const OptionList::IndexMap::const_iterator rg = opt.map().find(directive); if (rg != opt.map().end()) add_flags(opt, rg->second, redirect_gateway); } diff --git a/openvpn/client/unix/cmdagent.hpp b/openvpn/client/unix/cmdagent.hpp index e9e3194a7..6c790c4e2 100644 --- a/openvpn/client/unix/cmdagent.hpp +++ b/openvpn/client/unix/cmdagent.hpp @@ -52,7 +52,7 @@ class UnixCommandAgent : public TunBuilderSetup::Factory Config config; std::ostringstream os; - os << "UnixCommandAgent: transmitting bypass route to " << config.uds_name << std::endl; + os << "UnixCommandAgent: transmitting bypass route to " << config.uds_name << "\n"; // Build JSON request Json::Value jreq(Json::objectValue); @@ -143,7 +143,7 @@ class UnixCommandAgent : public TunBuilderSetup::Factory Stop *stop, std::ostream &os) override { - os << "SetupClient: transmitting tun setup list to " << config->uds_name << std::endl; + os << "SetupClient: transmitting tun setup list to " << config->uds_name << "\n"; // Build JSON request Json::Value jreq(Json::objectValue); @@ -215,7 +215,7 @@ class UnixCommandAgent : public TunBuilderSetup::Factory void destroy(std::ostream &os) override // defined by DestructorBase { - os << "SetupClient: transmitting tun destroy request to " << config->uds_name << std::endl; + os << "SetupClient: transmitting tun destroy request to " << config->uds_name << "\n"; // Create HTTP transaction container WS::ClientSet::TransactionSet::Ptr ts = new_transaction_set(config->uds_name, config->debug_level); @@ -246,7 +246,7 @@ class UnixCommandAgent : public TunBuilderSetup::Factory throw ovpnagent("unexpected transaction set size"); WS::ClientSet::Transaction &t = *ts.transactions[0]; const std::string content = t.content_in.to_string(); - os << t.format_status(ts) << std::endl; + os << t.format_status(ts) << "\n"; if (!t.comm_status_success()) { os << content; diff --git a/openvpn/client/win/cmdagent.hpp b/openvpn/client/win/cmdagent.hpp index 519dfbcfb..39daa5193 100644 --- a/openvpn/client/win/cmdagent.hpp +++ b/openvpn/client/win/cmdagent.hpp @@ -47,7 +47,7 @@ class WinCommandAgent : public TunWin::SetupFactory static bool add_bypass_route(IP::Addr endpoint) { std::ostringstream os; - os << "WinCommandAgent: transmitting bypass route to " << endpoint.to_string() << std::endl; + os << "WinCommandAgent: transmitting bypass route to " << endpoint.to_string() << "\n"; // Build JSON request Json::Value jreq(Json::objectValue); @@ -168,7 +168,7 @@ class WinCommandAgent : public TunWin::SetupFactory // Parse TAP handle const std::string tap_handle_hex = json::get_string(jres, "tap_handle_hex"); - os << "TAP handle: " << tap_handle_hex << std::endl; + os << "TAP handle: " << tap_handle_hex << "\n"; const HANDLE h = BufHex::parse<HANDLE>(tap_handle_hex, "TAP handle"); tap_.guid = json::get_string(jres, "adapter_guid"); @@ -196,7 +196,7 @@ class WinCommandAgent : public TunWin::SetupFactory std::ostream &os, TunWin::RingBuffer::Ptr ring_buffer) override // TunWin::SetupBase { - os << "SetupClient: transmitting tun setup list to " << config->npserv << std::endl; + os << "SetupClient: transmitting tun setup list to " << config->npserv << "\n"; // Build JSON request Json::Value jreq(Json::objectValue); @@ -245,7 +245,7 @@ class WinCommandAgent : public TunWin::SetupFactory // Parse TAP handle const std::string tap_handle_hex = json::get_string(jres, "tap_handle_hex"); - os << "TAP handle: " << tap_handle_hex << std::endl; + os << "TAP handle: " << tap_handle_hex << "\n"; const HANDLE tap = BufHex::parse<HANDLE>(tap_handle_hex, "TAP handle"); return tap; } @@ -280,7 +280,7 @@ class WinCommandAgent : public TunWin::SetupFactory void destroy(std::ostream &os) override // defined by DestructorBase { - os << "SetupClient: signaling tun destroy event" << std::endl; + os << "SetupClient: signaling tun destroy event\n"; service_process.close(); destroy_event.signal_event(); } @@ -292,7 +292,7 @@ class WinCommandAgent : public TunWin::SetupFactory throw ovpnagent("unexpected transaction set size"); WS::ClientSet::Transaction &t = *ts.transactions[0]; const std::string content = t.content_in.to_string(); - os << t.format_status(ts) << std::endl; + os << t.format_status(ts) << "\n"; if (t.comm_status_timeout()) { diff --git a/openvpn/common/action.hpp b/openvpn/common/action.hpp index 1d56420b8..52a6e67e1 100644 --- a/openvpn/common/action.hpp +++ b/openvpn/common/action.hpp @@ -29,7 +29,7 @@ namespace openvpn { struct Action : public RC<thread_unsafe_refcount> { - typedef RCPtr<Action> Ptr; + using Ptr = RCPtr<Action>; virtual void execute(std::ostream &os) = 0; virtual std::string to_string() const = 0; @@ -47,7 +47,7 @@ struct Action : public RC<thread_unsafe_refcount> class ActionList : public std::vector<Action::Ptr>, public DestructorBase { public: - typedef RCPtr<ActionList> Ptr; + using Ptr = RCPtr<ActionList>; ActionList() { @@ -111,7 +111,7 @@ class ActionList : public std::vector<Action::Ptr>, public DestructorBase } catch (const std::exception &e) { - os << "action exception: " << e.what() << std::endl; + os << "action exception: " << e.what() << '\n'; failed_actions.insert(action->mark); } } @@ -174,16 +174,14 @@ class ActionList : public std::vector<Action::Ptr>, public DestructorBase */ void remove_marked(const std::unordered_set<std::string> &marks, std::ostream &os) { - erase(std::remove_if( - begin(), end(), [&](const Action::Ptr &a) mutable - { + std::erase_if(*this, [&](const Action::Ptr &a) mutable + { auto remove = !a->mark.empty() && marks.count(a->mark) > 0; if (remove) { os << "Action '" << a->to_string() << "' will be removed\n"; } - return remove; }), - end()); + return remove; }); } protected: @@ -237,7 +235,7 @@ struct ActionListReversed : public ActionList struct ActionListFactory : public RC<thread_unsafe_refcount> { - typedef RCPtr<ActionListFactory> Ptr; + using Ptr = RCPtr<ActionListFactory>; virtual ActionList::Ptr new_action_list() = 0; }; diff --git a/openvpn/common/alignment.hpp b/openvpn/common/alignment.hpp index 5e83aa416..9df61f659 100644 --- a/openvpn/common/alignment.hpp +++ b/openvpn/common/alignment.hpp @@ -21,12 +21,19 @@ namespace openvpn { * @brief Converts a byte buffer to the desired type, avoiding undefined behavior due to alignment. * @details Replaces a simple cast with an alignment safe alternative. Useful when scraping data * out of wire oriented buffers and so on. - * + * @note It is assumed that the source pointed to by the passed pointer is large enough to hold + * the type T as source, and that the type T is trivially copyable. Due to the newer RVO rules and + * typical compiler optimizations, this should boil down to a straight memcpy, and on some + * platforms that copy might even be optimized away. + * @note The reason for using a pointer to void is that using a pointer to T to allow + * inference of T would cause the compiler to require a cast to T at the call site in most + * cases which seems like a lot more work for the same thing. * @tparam T type to convert to * @param toAlign starting address of the bytes to be converted * @return T output value and type */ -template <typename T, typename = std::enable_if_t<std::is_trivially_copyable<T>::value>> +template <typename T> + requires ::std::is_trivially_copyable_v<T> T alignment_safe_extract(const void *toAlign) noexcept { T ret; diff --git a/openvpn/common/asyncsleep.hpp b/openvpn/common/asyncsleep.hpp index f82fd4a85..41b528aac 100644 --- a/openvpn/common/asyncsleep.hpp +++ b/openvpn/common/asyncsleep.hpp @@ -15,9 +15,10 @@ #define OPENVPN_COMMON_ASYNCSLEEP_H #include <algorithm> +#include <chrono> +#include <thread> #include <openvpn/common/stop.hpp> -#include <openvpn/common/sleep.hpp> namespace openvpn { @@ -34,7 +35,7 @@ inline bool async_sleep_milliseconds(int milliseconds, Stop *async_stop) while (milliseconds > 0 && !stop) { const int ms = std::min(milliseconds, milliseconds_per_retry); - sleep_milliseconds(ms); + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); milliseconds -= ms; } diff --git a/openvpn/common/circ_list.hpp b/openvpn/common/circ_list.hpp index 758e1bdaf..f466c19be 100644 --- a/openvpn/common/circ_list.hpp +++ b/openvpn/common/circ_list.hpp @@ -93,20 +93,18 @@ class CircList { if (index >= data_.size()) throw circ_list_index(); - else if (index <= head_) + if (index <= head_) return data_[head_ - index]; - else - return data_[head_ + capacity_ - index]; + return data_[head_ + capacity_ - index]; } const T &operator[](const size_t index) const { if (index >= data_.size()) throw circ_list_const_index(); - else if (index <= head_) + if (index <= head_) return data_[head_ - index]; - else - return data_[head_ + capacity_ - index]; + return data_[head_ + capacity_ - index]; } private: diff --git a/openvpn/common/cleanup.hpp b/openvpn/common/cleanup.hpp index 2e8d098a4..60bbea900 100644 --- a/openvpn/common/cleanup.hpp +++ b/openvpn/common/cleanup.hpp @@ -13,34 +13,115 @@ #define OPENVPN_COMMON_CLEANUP_H #include <utility> +#include <optional> +#include <concepts> +#include <functional> +#include <type_traits> namespace openvpn { +/** + * @brief A scope guard that runs a callable on destruction unless dismissed or released. + * @tparam F The type of the callable to run on destruction. + * @details + * The Cleanup class template provides a mechanism to ensure that a specified callable + * is executed when the Cleanup object goes out of scope, unless it has been dismissed + * or released. This is useful for resource management and cleanup tasks that need to + * be performed when exiting a scope. + * @todo Keep std::scope_exit in mind when moving to C++23. + */ template <typename F> + requires std::invocable<F> class CleanupType { public: - CleanupType(F method) noexcept + explicit CleanupType(F method) noexcept(std::is_nothrow_move_constructible_v<F>) : clean(std::move(method)) { } + CleanupType(const CleanupType &) = delete; + CleanupType &operator=(const CleanupType &) = delete; + CleanupType(CleanupType &&other) noexcept + : clean(std::exchange(other.clean, std::nullopt)) + { + } + CleanupType &operator=(CleanupType &&other) noexcept + { + if (this != &other) + { + clean = std::exchange(other.clean, std::nullopt); + } + return *this; + } - CleanupType(CleanupType &&) = default; + /** + * @brief Destructor that executes the cleanup action if not dismissed or released. + * @details When the CleanupType object is destroyed, if the cleanup action has not + * been dismissed or released, it will be invoked. Any exceptions thrown by the + * cleanup action are caught and swallowed to prevent exceptions from escaping the + * destructor. + */ + ~CleanupType() noexcept + { + if (clean) + { + try + { + std::invoke(*clean); + } + catch (...) + { + // swallow exceptions to avoid throwing from destructor + } + } + } - ~CleanupType() + public: + /** + * @brief Dismiss the cleanup action, preventing it from being executed on destruction. + * @details After calling dismiss, the cleanup action will not be invoked when the + * CleanupType object is destroyed. + */ + void dismiss() noexcept + { + clean.reset(); + } + /** + * @brief Release the cleanup action, returning the callable and preventing it from being + * executed on destruction. + * @return An optional containing the callable if it was set, or std::nullopt if it was + * dismissed or already released. + * @details After calling release, the cleanup action will not be invoked when the + * CleanupType object is destroyed, and the caller takes ownership of the callable. This + * allows the caller to manage the callable's lifetime independently, including calling it + * earlier or later than it might be otherwise called. + */ + std::optional<std::function<void()>> release() noexcept { - clean(); + if (clean) + { + std::function<void()> func = std::move(*clean); + clean.reset(); + return func; + } + return std::nullopt; } private: - CleanupType(const CleanupType &) = delete; - CleanupType &operator=(const CleanupType &) = delete; - - F clean; + std::optional<F> clean; }; +/** + * @brief Factory function to create a CleanupType object. + * @tparam F The type of the callable to run on destruction. + * @param method The callable to be executed on destruction. + * @return A CleanupType object that will execute the callable on destruction. + * @details This function simplifies the creation of CleanupType objects by deducing + the type of the callable and forwarding it to the CleanupType constructor. + */ template <typename F> -inline CleanupType<F> Cleanup(F method) noexcept + requires std::invocable<F> +inline CleanupType<F> Cleanup(F method) noexcept(std::is_nothrow_move_constructible_v<F>) { return CleanupType<F>(std::move(method)); } diff --git a/openvpn/common/complog.hpp b/openvpn/common/complog.hpp index b4cfecd6a..153432fbe 100644 --- a/openvpn/common/complog.hpp +++ b/openvpn/common/complog.hpp @@ -12,7 +12,7 @@ #pragma once namespace openvpn { -inline void log_compress(const std::string prefix, const size_t orig_size, const size_t new_size) +inline void log_compress(const std::string &prefix, const size_t orig_size, const size_t new_size) { OPENVPN_LOG(prefix << ' ' << orig_size diff --git a/openvpn/common/count.hpp b/openvpn/common/count.hpp index a37df0197..ac4724c0b 100644 --- a/openvpn/common/count.hpp +++ b/openvpn/common/count.hpp @@ -13,7 +13,7 @@ #define OPENVPN_COMMON_COUNT_H namespace openvpn { -typedef long long count_t; +using count_t = long long; } #endif diff --git a/openvpn/common/daemon.hpp b/openvpn/common/daemon.hpp index 00894d100..443f01b64 100644 --- a/openvpn/common/daemon.hpp +++ b/openvpn/common/daemon.hpp @@ -40,7 +40,7 @@ class LogReopen : public LogSetup { } - virtual void reopen() override + void reopen() override { try { @@ -56,7 +56,7 @@ class LogReopen : public LogSetup } catch (const std::exception &e) { - std::cerr << "LogReopen: " << e.what() << std::endl; + std::cerr << "LogReopen: " << e.what() << "\n"; } } diff --git a/openvpn/common/demangle.hpp b/openvpn/common/demangle.hpp index 6dac8edfe..27e807760 100644 --- a/openvpn/common/demangle.hpp +++ b/openvpn/common/demangle.hpp @@ -24,13 +24,9 @@ namespace openvpn { inline std::string cxx_demangle(const char *mangled_name) { int status; - std::unique_ptr<char[]> realname; + std::unique_ptr<char, decltype(&free)> realname{abi::__cxa_demangle(mangled_name, 0, 0, &status), &free}; - realname.reset(abi::__cxa_demangle(mangled_name, 0, 0, &status)); - if (!status) - return std::string(realname.get()); - else - return "DEMANGLE_ERROR"; + return status ? "DEMANGLE_ERROR" : realname.get(); } } // namespace openvpn diff --git a/openvpn/common/destruct.hpp b/openvpn/common/destruct.hpp index c6ddc459d..ffbe801ed 100644 --- a/openvpn/common/destruct.hpp +++ b/openvpn/common/destruct.hpp @@ -20,7 +20,7 @@ namespace openvpn { struct DestructorBase : public RC<thread_unsafe_refcount> { - typedef RCPtr<DestructorBase> Ptr; + using Ptr = RCPtr<DestructorBase>; virtual void destroy(std::ostream &os) = 0; virtual ~DestructorBase() = default; }; diff --git a/openvpn/common/endian.hpp b/openvpn/common/endian.hpp index f35b6e095..757a262fd 100644 --- a/openvpn/common/endian.hpp +++ b/openvpn/common/endian.hpp @@ -14,7 +14,7 @@ #include <openvpn/common/endian_platform.hpp> namespace openvpn::Endian { -#if defined(OPENVPN_LITTLE_ENDIAN) +#ifdef OPENVPN_LITTLE_ENDIAN inline size_t e16(const size_t v) { return v; diff --git a/openvpn/common/endian64.hpp b/openvpn/common/endian64.hpp index f2b733a03..87b30903c 100644 --- a/openvpn/common/endian64.hpp +++ b/openvpn/common/endian64.hpp @@ -32,7 +32,7 @@ inline std::uint64_t mingw_bswap64(const std::uint64_t val) inline std::uint64_t rev64(const std::uint64_t value) { #ifdef OPENVPN_LITTLE_ENDIAN -#if defined(_MSC_VER) +#ifdef _MSC_VER return _byteswap_uint64(value); #elif defined(__MINGW32__) return mingw_bswap64(value); diff --git a/openvpn/common/environ.hpp b/openvpn/common/environ.hpp index fb7f1d122..11f0a84e3 100644 --- a/openvpn/common/environ.hpp +++ b/openvpn/common/environ.hpp @@ -87,8 +87,7 @@ class Environ : public std::vector<std::string> const int i = find_index(name); if (i >= 0) return value(i); - else - return ""; + return ""; } std::string value(const size_t idx) const @@ -97,8 +96,7 @@ class Environ : public std::vector<std::string> const size_t pos = s.find_first_of('='); if (pos != std::string::npos) return s.substr(pos + 1); - else - return ""; + return ""; } void assign(const std::string &name, const std::string &value) diff --git a/openvpn/common/exception.hpp b/openvpn/common/exception.hpp index 3d7a281c3..6120eef47 100644 --- a/openvpn/common/exception.hpp +++ b/openvpn/common/exception.hpp @@ -22,7 +22,6 @@ #include <utility> #include <openvpn/common/stringize.hpp> // for OPENVPN_STRINGIZE -#include <openvpn/common/string.hpp> #ifdef OPENVPN_DEBUG_EXCEPTION // well-known preprocessor hack to get __FILE__:__LINE__ rendered as a string @@ -63,7 +62,7 @@ class Exception : public std::exception void remove_label(const std::string &label) { const std::string head = label + ": "; - if (string::starts_with(err_, head)) + if (err_.starts_with(head)) err_ = err_.substr(head.length()); } @@ -97,16 +96,16 @@ class Exception : public std::exception } // define a custom exception class that allows extra info -#define OPENVPN_EXCEPTION(C) \ - class C : public openvpn::Exception \ - { \ - public: \ - C() : openvpn::Exception(#C OPENVPN_FILE_LINE) \ - { \ - } \ - C(const std::string err) : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) \ - { \ - } \ +#define OPENVPN_EXCEPTION(C) \ + class C : public openvpn::Exception \ + { \ + public: \ + C() : openvpn::Exception(#C OPENVPN_FILE_LINE) \ + { \ + } \ + C(const std::string &err) : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) \ + { \ + } \ } // define a custom exception class that allows extra info with error code @@ -131,26 +130,26 @@ class Exception : public std::exception static std::string code2string(C##_##code code); \ } // define a custom exception class that allows extra info, but does not emit a tag -#define OPENVPN_UNTAGGED_EXCEPTION(C) \ - class C : public openvpn::Exception \ - { \ - public: \ - C(const std::string err) : openvpn::Exception(err) \ - { \ - } \ +#define OPENVPN_UNTAGGED_EXCEPTION(C) \ + class C : public openvpn::Exception \ + { \ + public: \ + C(const std::string &err) : openvpn::Exception(err) \ + { \ + } \ } // define a custom exception class that allows extra info, and inherits from a custom base -#define OPENVPN_EXCEPTION_INHERIT(B, C) \ - class C : public B \ - { \ - public: \ - C() : B(#C OPENVPN_FILE_LINE) \ - { \ - } \ - C(const std::string err) : B(#C OPENVPN_FILE_LINE ": " + err) \ - { \ - } \ +#define OPENVPN_EXCEPTION_INHERIT(B, C) \ + class C : public B \ + { \ + public: \ + C() : B(#C OPENVPN_FILE_LINE) \ + { \ + } \ + C(const std::string &err) : B(#C OPENVPN_FILE_LINE ": " + err) \ + { \ + } \ } // define a custom exception class that allows extra info, and inherits from a custom base, @@ -194,8 +193,7 @@ inline void throw_ref(const std::exception &e) const Exception *ex = dynamic_cast<const Exception *>(&e); if (ex) throw *ex; - else - throw e; + throw e; } } // namespace openvpn diff --git a/openvpn/common/ffs.hpp b/openvpn/common/ffs.hpp index 4debcec60..56a788088 100644 --- a/openvpn/common/ffs.hpp +++ b/openvpn/common/ffs.hpp @@ -20,7 +20,7 @@ namespace openvpn { -#if defined(__GNUC__) +#ifdef __GNUC__ template <typename T> inline constexpr int n_bits_type() diff --git a/openvpn/common/file.hpp b/openvpn/common/file.hpp index 3965b8b5d..0723ed218 100644 --- a/openvpn/common/file.hpp +++ b/openvpn/common/file.hpp @@ -25,7 +25,7 @@ #include <openvpn/buffer/bufstr.hpp> #include <openvpn/buffer/buflist.hpp> -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #include <filesystem> #include <openvpn/win/unicode.hpp> #endif @@ -55,9 +55,9 @@ inline std::string read_text_simple(const std::string &filename) // Read a file (may be text or binary). inline BufferPtr read_binary(const std::string &filename, const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0) + const BufferFlags buffer_flags = BufAllocFlags::NO_FLAGS) { -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN Win::UTF16 filenamew(Win::utf16(filename)); std::filesystem::path path(filenamew.get()); std::ifstream ifs(path, std::ios::binary); @@ -104,7 +104,7 @@ inline BufferPtr read_binary_linear(const std::string &filename, std::streamsize total_size = 0; while (true) { - auto b = BufferAllocatedRc::Create(block_size, 0); + auto b = BufferAllocatedRc::Create(block_size); ifs.read((char *)b->data(), b->remaining()); const std::streamsize size = ifs.gcount(); if (size) @@ -126,7 +126,7 @@ inline BufferPtr read_binary_linear(const std::string &filename, // Read a text file as a std::string, throw error if file is binary inline std::string read_text(const std::string &filename, const std::uint64_t max_size = 0) { - BufferPtr bp = read_binary(filename, max_size); + const BufferPtr bp = read_binary(filename, max_size); if (bp->contains_null()) OPENVPN_THROW(file_is_binary, "file is binary: " << filename); return std::string((const char *)bp->c_data(), bp->size()); @@ -135,7 +135,7 @@ inline std::string read_text(const std::string &filename, const std::uint64_t ma // Read a UTF-8 file as a std::string, throw errors if file is binary or malformed UTF-8 inline std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size = 0) { - BufferPtr bp = read_binary(filename, max_size); + const BufferPtr bp = read_binary(filename, max_size); // check if binary if (bp->contains_null()) @@ -198,7 +198,7 @@ inline void write_binary_list(const std::string &filename, const BUFLIST &buflis // Write std::string to file inline void write_string(const std::string &filename, const std::string &str) { - BufferPtr buf = buf_from_string(str); + const BufferPtr buf = buf_from_string(str); write_binary(filename, *buf); } diff --git a/openvpn/common/fileunix.hpp b/openvpn/common/fileunix.hpp index a9ba4f9cc..5a0530e76 100644 --- a/openvpn/common/fileunix.hpp +++ b/openvpn/common/fileunix.hpp @@ -116,7 +116,7 @@ enum }; inline BufferPtr read_binary_unix(const std::string &fn, const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0, + const unsigned int enoent_option = 0, std::uint64_t *mtime_ns = nullptr) { // open @@ -124,7 +124,7 @@ inline BufferPtr read_binary_unix(const std::string &fn, if (!fd.defined()) { const int eno = errno; - if ((buffer_flags & NULL_ON_ENOENT) && eno == ENOENT) + if ((enoent_option & NULL_ON_ENOENT) && eno == ENOENT) return BufferPtr(); throw file_unix_error(fn + " : open for read : " + strerror_str(eno)); } @@ -151,7 +151,7 @@ inline BufferPtr read_binary_unix(const std::string &fn, throw file_unix_error(fn + " : file too large [" + std::to_string(length) + '/' + std::to_string(max_size) + ']'); // allocate buffer - auto bp = BufferAllocatedRc::Create(size_t(length), buffer_flags); + auto bp = BufferAllocatedRc::Create(size_t(length)); // read file content into buffer while (buf_read(fd(), *bp, fn)) @@ -194,10 +194,10 @@ inline int read_binary_unix_fast(const STRING &fn, inline std::string read_text_unix(const std::string &filename, const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0, + const unsigned int enoent_option = 0, std::uint64_t *mtime_ns = nullptr) { - BufferPtr bp = read_binary_unix(filename, max_size, buffer_flags, mtime_ns); + BufferPtr bp = read_binary_unix(filename, max_size, enoent_option, mtime_ns); if (bp) return buf_to_string(*bp); else diff --git a/openvpn/common/format.hpp b/openvpn/common/format.hpp index f4ad91ad4..35c5918b8 100644 --- a/openvpn/common/format.hpp +++ b/openvpn/common/format.hpp @@ -268,8 +268,7 @@ class PrintFormatted out.append((char)quote); return true; } - else - out.append(c); + out.append(c); } else { diff --git a/openvpn/common/function.hpp b/openvpn/common/function.hpp index e2addab0e..f63110742 100644 --- a/openvpn/common/function.hpp +++ b/openvpn/common/function.hpp @@ -146,8 +146,7 @@ class Function<R(A...), N, INTERN_ONLY> struct Methods { - R(*invoke) - (void *, A &&...); + R (*invoke)(void *, A &&...); void (*move)(void *, void *); void (*destruct)(void *); }; diff --git a/openvpn/common/getopt.hpp b/openvpn/common/getopt.hpp index 8d2433bfa..efc25bd93 100644 --- a/openvpn/common/getopt.hpp +++ b/openvpn/common/getopt.hpp @@ -36,7 +36,7 @@ #include <openvpn/common/size.hpp> #include <openvpn/common/exception.hpp> -#if !defined(OPENVPN_PLATFORM_WIN) +#ifndef OPENVPN_PLATFORM_WIN #include <getopt.h> #else diff --git a/openvpn/common/getpw.hpp b/openvpn/common/getpw.hpp index 2df9252c2..b85a39829 100644 --- a/openvpn/common/getpw.hpp +++ b/openvpn/common/getpw.hpp @@ -14,7 +14,7 @@ #include <openvpn/common/platform.hpp> -#if !defined(OPENVPN_PLATFORM_WIN) +#ifndef OPENVPN_PLATFORM_WIN #include <pwd.h> #include <unistd.h> #else @@ -28,8 +28,8 @@ namespace openvpn { inline std::string get_password(const char *prompt) { -#if !defined(OPENVPN_PLATFORM_WIN) - char *ret = getpass(prompt); +#ifndef OPENVPN_PLATFORM_WIN + const char *ret = getpass(prompt); return ret; #else Win::Console::Input i{true}; diff --git a/openvpn/common/hash.hpp b/openvpn/common/hash.hpp index 727505623..34ad31fbb 100644 --- a/openvpn/common/hash.hpp +++ b/openvpn/common/hash.hpp @@ -64,7 +64,7 @@ class Hash64 template <typename T> inline void operator()(const T &obj) { - static_assert(std::is_pod<T>::value, "Hash64: POD type required"); + static_assert(std::is_standard_layout_v<T>, "Hash64: standard layout required"); (*this)(&obj, sizeof(obj)); } diff --git a/openvpn/common/hexstr.hpp b/openvpn/common/hexstr.hpp index c5fdd5977..10d474f77 100644 --- a/openvpn/common/hexstr.hpp +++ b/openvpn/common/hexstr.hpp @@ -45,10 +45,9 @@ inline char render_hex_char(const int c, const bool caps = false) return '?'; if (c < 10) return '0' + static_cast<char>(c); - else if (c < 16) + if (c < 16) return static_cast<char>((caps ? 'A' : 'a') - 10 + c); - else - return '?'; + return '?'; } /** @@ -66,12 +65,11 @@ inline int parse_hex_char(const int c) { if (c >= '0' && c <= '9') return c - '0'; - else if (c >= 'a' && c <= 'f') + if (c >= 'a' && c <= 'f') return c - 'a' + 10; - else if (c >= 'A' && c <= 'F') + if (c >= 'A' && c <= 'F') return c - 'A' + 10; - else - return -1; + return -1; } @@ -267,7 +265,7 @@ inline std::string dump_hex(const unsigned char *data, size_t size) { if (i) { - os << " " << chars << std::endl; + os << " " << chars << '\n'; chars.clear(); } os << std::setfill(' ') << std::setw(8) << i << ":"; @@ -280,7 +278,7 @@ inline std::string dump_hex(const unsigned char *data, size_t size) chars += '.'; } if (i) - os << string::spaces(clamp_to_typerange<int>(2 + (((i - 1) & mask) ^ mask) * 3)) << chars << std::endl; + os << string::spaces(clamp_to_typerange<int>(2 + (((i - 1) & mask) ^ mask) * 3)) << chars << '\n'; return os.str(); } diff --git a/openvpn/common/hostlist.hpp b/openvpn/common/hostlist.hpp index cfbda33c1..1633c8a27 100644 --- a/openvpn/common/hostlist.hpp +++ b/openvpn/common/hostlist.hpp @@ -26,9 +26,7 @@ namespace openvpn::HostList { struct Host { - Host() - { - } + Host() = default; Host(const std::string &host_arg, const std::string &port_arg) : host(host_arg), @@ -70,9 +68,7 @@ struct Host class List : public std::vector<Host> { public: - List() - { - } + List() = default; List(const OptionList &opt, const std::string &directive, diff --git a/openvpn/common/hostport.hpp b/openvpn/common/hostport.hpp index 18bfe9b15..6083bb2c6 100644 --- a/openvpn/common/hostport.hpp +++ b/openvpn/common/hostport.hpp @@ -63,7 +63,7 @@ inline bool is_valid_host_char(const char c) inline bool is_valid_host(const std::string &host) { - if (!host.length() || host.length() > 256) + if (host.empty() || host.length() > 256) return false; for (const auto &c : host) { @@ -80,7 +80,7 @@ inline bool is_valid_unix_sock_char(const unsigned char c) inline bool is_valid_unix_sock(const std::string &host) { - if (!host.length() || host.length() > 256) + if (host.empty() || host.length() > 256) return false; for (const auto &c : host) { @@ -131,8 +131,7 @@ inline bool split_host_port(const std::string &str, if (allow_unix && port == "unix") return is_valid_unix_sock(host); - else - return is_valid_host(host) && is_valid_port(port, port_save); + return is_valid_host(host) && is_valid_port(port, port_save); } } // namespace openvpn::HostPort diff --git a/openvpn/common/intrinsic_type.hpp b/openvpn/common/intrinsic_type.hpp new file mode 100644 index 000000000..8767aa125 --- /dev/null +++ b/openvpn/common/intrinsic_type.hpp @@ -0,0 +1,309 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012- OpenVPN Inc. +// +// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception +// + +#pragma once + +#include <type_traits> + +namespace openvpn { + +/** + @brief CRTP type designed to allow creation of strong types based on intrinsics + @tparam BaseT The final type name + @tparam T The value type + @details The IntrinsicType template struct is designed to encapsulate a value of type T + and provide a set of operations for manipulating this value. The struct uses the + Curiously Recurring Template Pattern (CRTP) to enable static polymorphism, where BaseT + is the derived type that inherits from IntrinsicType. + + This enables an arithmetic type to be essentially used as a base type for a new strong + type, which can be used to enforce type safety and prevent accidental misuse of the + underlying value. The struct provides a set of operators for bitwise operations, and + could be extended to provide additional operators as needed. +*/ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +struct IntrinsicType +{ + using value_type = T; + + /** + * @brief Constructs an IntrinsicType object + * @param v The value to initialize the object with + * @note Default constructs the value_type if no parameter is provided + */ + constexpr explicit IntrinsicType(value_type v = value_type()) noexcept + : mValue(v) {}; + + /** + * @brief Assignment operator from value_type + * @param v The value to assign + * @return Reference to the modified object + */ + BaseT &operator=(value_type v) + { + mValue = v; + return CrtpBase(); + } + + /** + * @brief Assignment operator from BaseT + * @param arg The object to assign from + * @return Reference to the modified object + */ + BaseT &operator=(BaseT arg) noexcept + { + mValue = arg.mValue; + return CrtpBase(); + } + + /** + @brief Add assignment operator + @param arg The object to add + @return Reference to the modified object + */ + constexpr BaseT operator+=(BaseT arg) noexcept + { + mValue += arg.mValue; + return CrtpBase(); + } + + /** + @brief Subtract assignment operator + @param arg The object to subtract + @return Reference to the modified object + */ + constexpr BaseT operator-=(BaseT arg) noexcept + { + mValue -= arg.mValue; + return CrtpBase(); + } + + /** + @brief Multiply assignment operator + @param arg The object to multiply + @return Reference to the modified object + */ + constexpr BaseT operator*=(BaseT arg) noexcept + { + mValue *= arg.mValue; + return CrtpBase(); + } + + /** + @brief Divide assignment operator + @param arg The object to divide + @return Reference to the modified object + */ + constexpr BaseT operator/=(BaseT arg) noexcept + { + mValue /= arg.mValue; + return CrtpBase(); + } + + /** + * @brief Bitwise OR assignment operator + * @param arg The object to OR with + * @return Reference to the modified object + * @note This operator is marked constexpr and noexcept, and is enabled only for + * integral types + */ + constexpr BaseT &operator|=(BaseT arg) noexcept + requires std::is_integral_v<T> + { + mValue |= arg.mValue; + return CrtpBase(); + } + + /** + * @brief Bitwise AND assignment operator + * @param arg The object to AND with + * @return Reference to the modified object + * @note This operator is marked constexpr and noexcept, and is enabled only for + * integral types + */ + constexpr BaseT &operator&=(BaseT arg) noexcept + requires std::is_integral_v<T> + { + mValue &= arg.mValue; + return CrtpBase(); + } + + /** + * @brief Getter for the underlying value + * @return The stored value + */ + constexpr value_type get() const noexcept + { + return mValue; + } + + /** + * @brief Conversion operator to value_type + * @return The stored value + */ + constexpr operator value_type() const noexcept + { + return mValue; + } + + private: + /** + * @brief Helper function to perform CRTP cast + * @return Reference to the derived type + */ + BaseT &CrtpBase() noexcept + { + return static_cast<BaseT &>(*this); + } + + /** + * @brief Const version of helper function to perform CRTP cast + * @return Const reference to the derived type + */ + const BaseT &CrtpBase() const noexcept + { + return static_cast<const BaseT &>(*this); + } + + private: + value_type mValue; +}; + +/** + * @brief Equality comparison operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return true if the objects are equal, false otherwise + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr bool operator==(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return lhs.get() == rhs.get(); +} + +/** + * @brief Equality comparison operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return returns the result of the comparison + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr auto operator<=>(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return lhs.get() <=> rhs.get(); +} + +/** + * @brief Addition operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return Sum of the two objects + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr BaseT operator+(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return BaseT(lhs.get() + rhs.get()); +} + +/** + * @brief Subtraction operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return Difference of the two objects + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr BaseT operator-(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return BaseT(lhs.get() - rhs.get()); +} + +/** + * @brief Multiplication operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return Product of the two objects + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr BaseT operator*(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return BaseT(lhs.get() * rhs.get()); +} + +/** + * @brief Division operator + * @param lhs The left operand of the operation + * @param rhs The right operand of the operation + * @return Quotient of the two objects + */ +template <typename BaseT, typename T> + requires std::is_arithmetic_v<T> +constexpr BaseT operator/(IntrinsicType<BaseT, T> lhs, IntrinsicType<BaseT, T> rhs) noexcept +{ + return BaseT(lhs.get() / rhs.get()); +} + +/** + * @brief Performs bitwise NOT operation on an IntrinsicType + * @tparam BaseT The base type of the IntrinsicType + * @tparam T The underlying value type of the IntrinsicType + * @param t The IntrinsicType object to perform NOT operation on + * @return A new BaseT object containing the result of the bitwise NOT operation + * @note This operator is marked constexpr and noexcept, and is enabled only for + * integral types + */ +template <typename BaseT, typename T> + requires std::is_integral_v<T> +constexpr BaseT operator~(IntrinsicType<BaseT, T> t) noexcept +{ + return BaseT{~T(t)}; +} + +/** + * @brief Performs bitwise OR operation between two IntrinsicType objects + * @tparam BaseT The base type of the IntrinsicType + * @tparam T The underlying value type of the IntrinsicType + * @param l The left operand of the OR operation + * @param r The right operand of the OR operation + * @return A new BaseT object containing the result of the bitwise OR operation + * @note This operator is marked constexpr and noexcept, and is enabled only for + * integral types + */ +template <typename BaseT, typename T> + requires std::is_integral_v<T> +constexpr BaseT operator|(IntrinsicType<BaseT, T> l, IntrinsicType<BaseT, T> r) noexcept +{ + return BaseT{T(l) | T(r)}; +} + +/** + * @brief Performs bitwise AND operation between two IntrinsicType objects + * @tparam BaseT The base type of the IntrinsicType + * @tparam T The underlying value type of the IntrinsicType + * @param l The left operand of the AND operation + * @param r The right operand of the AND operation + * @return A new BaseT object containing the result of the bitwise AND operation + * @note This operator is marked constexpr and noexcept, and is enabled only for + * integral types + */ +template <typename BaseT, typename T> + requires std::is_integral_v<T> +constexpr BaseT operator&(IntrinsicType<BaseT, T> l, IntrinsicType<BaseT, T> r) noexcept +{ + return BaseT{T(l) & T(r)}; +} + +} // namespace openvpn \ No newline at end of file diff --git a/openvpn/common/jsonhelper.hpp b/openvpn/common/jsonhelper.hpp index 0e23c31e1..c68b7efce 100644 --- a/openvpn/common/jsonhelper.hpp +++ b/openvpn/common/jsonhelper.hpp @@ -619,8 +619,7 @@ inline bool get_bool_optional(const Json::Value &root, const Json::Value &jv = root[name]; if (jv.isConvertibleTo(Json::booleanValue)) return jv.asBool(); - else - return default_value; + return default_value; } template <typename NAME> @@ -630,8 +629,7 @@ inline int get_bool_tristate(const Json::Value &root, const Json::Value &jv = root[name]; if (jv.isConvertibleTo(Json::booleanValue)) return jv.asBool() ? 1 : 0; - else - return -1; + return -1; } DISABLE_DANGLING_WARNINGS() @@ -929,8 +927,7 @@ inline std::string error(const Json::Value &root) const Json::Value &je = root["error"]; if (je.isString()) return je.asString(); - else - return std::string(); + return std::string(); } // Guarantee that json object jr is a dictionary. @@ -940,11 +937,9 @@ inline Json::Value dict_result(Json::Value jr) { if (jr.isObject()) return jr; - else - { - Json::Value jret(Json::objectValue); - jret["result"] = std::move(jr); - return jret; - } + + Json::Value jret(Json::objectValue); + jret["result"] = std::move(jr); + return jret; } } // namespace openvpn::json diff --git a/openvpn/common/jsonhelperfmt.hpp b/openvpn/common/jsonhelperfmt.hpp index 9cad14ea6..b4a6ffd8d 100644 --- a/openvpn/common/jsonhelperfmt.hpp +++ b/openvpn/common/jsonhelperfmt.hpp @@ -23,8 +23,7 @@ inline std::string fmt_name(const NAME &name, const TITLE &title) { if (!StringTempl::empty(title)) return StringTempl::to_string(title) + '.' + StringTempl::to_string(name); - else - return StringTempl::to_string(name); + return StringTempl::to_string(name); } // if title is not a number, treat as an ordinary string diff --git a/openvpn/common/jsonlib.hpp b/openvpn/common/jsonlib.hpp index 44fc77692..30239368a 100644 --- a/openvpn/common/jsonlib.hpp +++ b/openvpn/common/jsonlib.hpp @@ -11,7 +11,7 @@ #pragma once -#if defined(HAVE_JSONCPP) +#ifdef HAVE_JSONCPP #define HAVE_JSON #include "json/json.h" // JsonCpp library #elif defined(HAVE_OPENVPN_COMMON) diff --git a/openvpn/common/likely.hpp b/openvpn/common/likely.hpp index 718184db8..bd5ff8b47 100644 --- a/openvpn/common/likely.hpp +++ b/openvpn/common/likely.hpp @@ -14,7 +14,7 @@ // Branch prediction hints (these make a difference on ARM) #if !defined(likely) && !defined(unlikely) -#if defined(__GNUC__) +#ifdef __GNUC__ #define likely(x) __builtin_expect((x), 1) #define unlikely(x) __builtin_expect((x), 0) #else diff --git a/openvpn/common/logsetup.hpp b/openvpn/common/logsetup.hpp index c27ac5386..5cfaa819a 100644 --- a/openvpn/common/logsetup.hpp +++ b/openvpn/common/logsetup.hpp @@ -31,7 +31,7 @@ class MultiLogSetup : public std::vector<LogSetup::Ptr>, public: typedef RCPtr<MultiLogSetup> Ptr; - virtual void reopen() override + void reopen() override { for (const auto &e : *this) e->reopen(); diff --git a/openvpn/common/make_rc.hpp b/openvpn/common/make_rc.hpp index 52745ef6b..2f98d4b7f 100644 --- a/openvpn/common/make_rc.hpp +++ b/openvpn/common/make_rc.hpp @@ -60,7 +60,7 @@ class RcEnable : public TypeT, public RcT template <typename... ArgsT> RcEnable(ArgsT &&...args) : TypeT(std::forward<ArgsT>(args)...), - RcT(){}; + RcT() {}; }; /** diff --git a/openvpn/common/memneq.hpp b/openvpn/common/memneq.hpp index 313dc5212..20b35203d 100644 --- a/openvpn/common/memneq.hpp +++ b/openvpn/common/memneq.hpp @@ -15,7 +15,7 @@ #include <openvpn/common/size.hpp> #include <atomic> -#if defined(USE_OPENSSL) +#ifdef USE_OPENSSL #include <openssl/crypto.h> #endif @@ -27,7 +27,7 @@ // Define a portable compiler memory access fence (from Boost). -#if defined(__INTEL_COMPILER) +#ifdef __INTEL_COMPILER #define OPENVPN_COMPILER_FENCE __memory_barrier(); @@ -67,7 +67,7 @@ namespace openvpn::crypto { */ inline bool memneq(const void *a, const void *b, size_t size); -#if defined(USE_OPENSSL) +#ifdef USE_OPENSSL inline bool memneq(const void *a, const void *b, size_t size) { // memcmp does return 0 (=false) when the memory is equal. It normally diff --git a/openvpn/common/msfind.hpp b/openvpn/common/msfind.hpp index 4d1e35558..020d0064a 100644 --- a/openvpn/common/msfind.hpp +++ b/openvpn/common/msfind.hpp @@ -66,7 +66,7 @@ inline auto find(MAP_SET &ms, const KEY &k) template <typename MAP_SET, typename KEY> inline bool exists(MAP_SET &ms, const KEY &k) { - return ms.find(k) != ms.end(); + return ms.contains(k); } // Convert an ordinary, dereferenceable iterator to an MSF::Iter diff --git a/openvpn/common/msgwin.hpp b/openvpn/common/msgwin.hpp index 87cf20ba6..677635a23 100644 --- a/openvpn/common/msgwin.hpp +++ b/openvpn/common/msgwin.hpp @@ -71,8 +71,7 @@ class MessageWindow grow(id); return q_[id - head_id_]; } - else - throw message_window_ref_by_id(); + throw message_window_ref_by_id(); } // Remove the M object at id, is a no-op if diff --git a/openvpn/common/number.hpp b/openvpn/common/number.hpp index cdf9a1e25..ddc21554c 100644 --- a/openvpn/common/number.hpp +++ b/openvpn/common/number.hpp @@ -14,6 +14,7 @@ #ifndef OPENVPN_COMMON_NUMBER_H #define OPENVPN_COMMON_NUMBER_H +#include <algorithm> #include <string> #include <limits> @@ -76,8 +77,7 @@ inline T parse_number_throw(const std::string &str, const std::string &error) T ret; if (parse_number<T>(str.c_str(), ret)) return ret; - else - throw number_parse_exception(error); + throw number_parse_exception(error); } template <typename T> @@ -86,8 +86,7 @@ inline T parse_number_throw(const std::string &str, const char *error) T ret; if (parse_number<T>(str.c_str(), ret)) return ret; - else - throw number_parse_exception(std::string(error)); + throw number_parse_exception(std::string(error)); } template <typename T> @@ -96,8 +95,7 @@ inline T parse_number_throw(const char *str, const char *error) T ret; if (parse_number<T>(str, ret)) return ret; - else - throw number_parse_exception(std::string(error)); + throw number_parse_exception(std::string(error)); } template <typename T> @@ -123,18 +121,10 @@ inline bool parse_number_validate(const std::string &numstr, return false; } -inline bool is_number(const char *str) +inline bool is_number(std::string_view str) { - char c; - bool found_digit = false; - while ((c = *str++)) - { - if (c >= '0' && c <= '9') - found_digit = true; - else - return false; - } - return found_digit; + return !str.empty() && std::ranges::all_of(str, [](const unsigned char c) + { return std::isdigit(c); }); } } // namespace openvpn diff --git a/openvpn/common/olong.hpp b/openvpn/common/olong.hpp index 65e68ea35..f8b1c5a59 100644 --- a/openvpn/common/olong.hpp +++ b/openvpn/common/olong.hpp @@ -17,11 +17,11 @@ namespace openvpn { #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) -typedef long long olong; -typedef unsigned long long oulong; +using olong = long long; +using oulong = unsigned long long; #else -typedef long olong; -typedef unsigned long oulong; +using olong = long; +using oulong = unsigned long; #endif } // namespace openvpn diff --git a/openvpn/common/optional_ref.hpp b/openvpn/common/optional_ref.hpp new file mode 100644 index 000000000..3f16f89a1 --- /dev/null +++ b/openvpn/common/optional_ref.hpp @@ -0,0 +1,301 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2024- OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see <http://www.gnu.org/licenses/>. + +#pragma once + +#include <optional> // std::nullopt_t +#include <stdexcept> +#include <type_traits> + +namespace openvpn { + +/** + @brief designed to represent an optional reference to an object of type T + @tparam T reference type + @details This code defines a template class called optional<T&> which is designed to + represent an optional reference to an object of type T. The purpose of this class is + to provide a way to handle situations where a reference might or might not be + available, similar to how std::optional works for regular types. + + The class doesn't take any direct inputs, but it can be instantiated with either no + arguments (creating an empty optional), a reference to an object of type T, or + another optional object. It produces an object that can either hold a reference to + a T object or be empty. + + The class achieves its purpose by using a pointer (T *mRef) internally to store the + address of the referenced object. When the optional is empty, this pointer is set to + nullptr. The class provides various methods to check if a reference is present, + access the referenced object, and assign new references or clear the optional. + + The important logic flows in this class include: + + - Constructors and assignment operators that allow creating and modifying the optional + object. Assigning from T will write thru, modifying the T that is referred to. Assigning + from another optional will change the target of the reference. Assigning std::nullopt + will remove the reference target. + - A boolean conversion operator that checks if the optional contains a valid reference. + - Dereference operators (* and ->) that provide access to the referenced object, throwing + an exception if the optional is empty. For example when calling the * operator, a check + is done if the optional contains a valid reference. If it does, it returns the + referenced object. If it doesn't, it throws an exception with the message + "optional<T &>: access error". + - The value and value_or members behave similarly except they return a copy of the stored + value and in the case of value_or, the default is returned if the reference is not + valid. This return by value is a bit idiosyncratic but they are provided for + compatibility with the std::optional interface. Hopefully the function names serve as + a reminder that the return is a value. + + This implementation allows programmers to work with optional references in a way + that's similar to how they would work with optional values. It provides a slightly safer + alternative to using raw pointers or references when dealing with objects that may or + may not be available at runtime. The safety improvement is only that: + + - A segfault is prevented if the optional is de-refed while empty, substituting an + exception that can be caught and handled instead. + - Makes the code a little more self documenting in that a raw pointer is versatile + and therefore might be used for many reasons, whereas this class is very specifically + for representing an optional reference. +*/ + +template <typename T> + requires std::is_reference_v<T> +class optional +{ + using value_type = std::remove_reference_t<T>; + value_type *mRef = nullptr; + static constexpr char errorMsg[] = "optional<T &>: access error"; + + public: + /** + * @brief Default constructor. Creates an empty optional. + */ + constexpr optional() noexcept = default; + + /** + * @brief Constructs an empty optional. + * @param noOption Indicates that the optional should be empty. + */ + constexpr optional(std::nullopt_t noOption) noexcept; + + /** + * @brief Constructs an optional containing a reference to the given object. + * @param r Reference to the object to be stored. + */ + constexpr optional(T r) noexcept; + + /** + * @brief Constructs an optional containing a reference to the given object. + * @param r pointer to the object to be stored. + */ + constexpr optional(value_type *r) noexcept; + + /** + * @brief Copy constructor. + */ + constexpr optional(const optional &) noexcept = default; + + /** + * @brief Move constructor. + */ + constexpr optional(optional &&) noexcept = default; + + /** + * @brief Copy assignment operator. + * @return Reference to this object. + */ + optional &operator=(const optional &) noexcept = default; + + /** + * @brief Move assignment operator. + * @return Reference to this object. + */ + optional &operator=(optional &&) noexcept = default; + + /** + * @brief Assigns the optional to be empty. + * @param noOption Indicates that the optional should be empty. + * @return Reference to this object. + */ + optional &operator=(std::nullopt_t noOption) noexcept; + + /** + * @brief Resets the optional, making it empty. + */ + void reset() noexcept; + + /** + * @brief Checks whether the optional contains a value. + * @return true if the optional contains a value, false otherwise. + */ + [[nodiscard]] constexpr bool has_value() const noexcept; + + /** + * @brief Checks whether the optional contains a value. + * @return true if the optional contains a value, false otherwise. + */ + [[nodiscard]] constexpr explicit operator bool() const noexcept; + + /** + * @brief Gets the contained value. + * @return Copy of the contained value. + * @throws std::runtime_error if the optional is empty. + */ + constexpr value_type value() const; + + /** + * @brief Returns the contained value if the optional is not empty, otherwise + * returns the provided default value. + * @param default_value The value to return if the optional is empty. + * @return Copy of the contained value if the optional is not empty, + * otherwise a copy of the default value. + */ + constexpr value_type value_or(const value_type &default_value) const noexcept; + + /** + * @brief Dereference operator. + * @return Const reference to the contained value. + * @throws std::runtime_error if the optional is empty. + */ + const T operator*() const; + + /** + * @brief Dereference operator. + * @return Reference to the contained value. + * @throws std::runtime_error if the optional is empty. + */ + T operator*(); + + /** + * @brief Arrow operator. + * @return Const pointer to the contained value. + * @throws std::runtime_error if the optional is empty. + */ + const value_type *operator->() const; + + /** + * @brief Arrow operator. + * @return Pointer to the contained value. + * @throws std::runtime_error if the optional is empty. + */ + value_type *operator->(); +}; + +// Implementations below + +template <typename T> + requires std::is_reference_v<T> +inline constexpr optional<T>::optional(std::nullopt_t) noexcept + : optional() +{ +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr optional<T>::optional(T r) noexcept + : mRef(&r) +{ +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr optional<T>::optional(value_type *r) noexcept + : mRef(r) +{ +} + +template <typename T> + requires std::is_reference_v<T> +inline optional<T> &optional<T>::operator=(std::nullopt_t) noexcept +{ + reset(); + return *this; +} + +template <typename T> + requires std::is_reference_v<T> +inline void optional<T>::reset() noexcept +{ + mRef = nullptr; +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr bool optional<T>::has_value() const noexcept +{ + return mRef != nullptr; +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr optional<T>::operator bool() const noexcept +{ + return has_value(); +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr auto optional<T>::value() const -> value_type +{ + if (!bool(*this)) + throw std::runtime_error(errorMsg); + return *mRef; +} + +template <typename T> + requires std::is_reference_v<T> +inline constexpr auto optional<T>::value_or(const value_type &default_value) const noexcept -> value_type +{ + return bool(*this) ? *mRef : default_value; +} + +template <typename T> + requires std::is_reference_v<T> +inline const T optional<T>::operator*() const +{ + if (!bool(*this)) + throw std::runtime_error(errorMsg); + return *mRef; +} + +template <typename T> + requires std::is_reference_v<T> +inline T optional<T>::operator*() +{ + return const_cast<T &>(*(std::as_const(*this))); +} + +template <typename T> + requires std::is_reference_v<T> +inline auto optional<T>::operator->() const -> const value_type * +{ + if (!bool(*this)) + throw std::runtime_error(errorMsg); + return mRef; +} + +template <typename T> + requires std::is_reference_v<T> +inline auto optional<T>::operator->() -> value_type * +{ + return const_cast<value_type *>(std::as_const(*this).operator->()); +} + +} // namespace openvpn diff --git a/openvpn/common/options.hpp b/openvpn/common/options.hpp index 05af9f3fc..8caba8458 100644 --- a/openvpn/common/options.hpp +++ b/openvpn/common/options.hpp @@ -105,10 +105,9 @@ class Option const size_t len = max_len & ((size_t)MULTILINE - 1); // NOTE -- use smallest flag value here if (pos != std::string::npos && !(max_len & MULTILINE)) return STATUS_MULTILINE; - else if (len > 0 && Unicode::utf8_length(str) > len) + if (len > 0 && Unicode::utf8_length(str) > len) return STATUS_LENGTH; - else - return STATUS_GOOD; + return STATUS_GOOD; } static const char *validate_status_description(const validate_status status) @@ -158,8 +157,7 @@ class Option const size_t pos = str.find_first_of("\r\n"); return pos != std::string::npos; } - else - return false; + return false; } static void validate_string(const std::string &name, const std::string &str, const size_t max_len) @@ -173,10 +171,9 @@ class Option { try { - if (data.size() > 0) + if (!data.empty()) return Unicode::utf8_printable(data[0], 32); - else - return ""; + return ""; } catch (const std::exception &) { @@ -196,8 +193,7 @@ class Option validate_arg(index, max_len); if (index < data.size()) return data[index]; - else - return ""; + return ""; } std::string get_default(const size_t index, const size_t max_len, const std::string &default_value) const @@ -205,8 +201,7 @@ class Option validate_arg(index, max_len); if (index < data.size()) return data[index]; - else - return default_value; + return default_value; } const std::string *get_ptr(const size_t index, const size_t max_len) const @@ -214,14 +209,13 @@ class Option validate_arg(index, max_len); if (index < data.size()) return &data[index]; - else - return nullptr; + return nullptr; } template <typename T> T get_num(const size_t idx) const { - typedef typename std::remove_const<T>::type T_nonconst; + using T_nonconst = typename std::remove_const<T>::type; T_nonconst n(0); // we shouldn't need to initialize here, but some compilers complain "may be used uninitialized in this function" const std::string &numstr = get(idx, 64); if (numstr.length() >= 2 && numstr[0] == '0' && numstr[1] == 'x') @@ -239,8 +233,7 @@ class Option { if (size() > idx) return get_num<T>(idx); - else - return default_value; + return default_value; } template <typename T> @@ -425,7 +418,7 @@ class Option std::string err_ref() const { std::string ret = "option"; - if (data.size()) + if (!data.empty()) { ret += " '"; ret += printable_directive(); @@ -516,10 +509,10 @@ class Option class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_refcount> { public: - typedef RCPtr<OptionList> Ptr; - typedef std::vector<unsigned int> IndexList; - typedef std::unordered_map<std::string, IndexList> IndexMap; - typedef std::pair<std::string, IndexList> IndexPair; + using Ptr = RCPtr<OptionList>; + using IndexList = std::vector<unsigned int>; + using IndexMap = std::unordered_map<std::string, IndexList>; + using IndexPair = std::pair<std::string, IndexList>; static bool is_comment(const char c) { @@ -527,14 +520,12 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r } // standard lex filter that doesn't understand end-of-line comments - typedef StandardLex Lex; + using Lex = StandardLex; // special lex filter that recognizes end-of-line comments class LexComment : public LexQuoteMixin { public: - LexComment() = default; - void put(char c) { if (in_comment) @@ -667,14 +658,14 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r // Used by extend() to optionally control which options are copied. struct FilterBase : public RC<thread_unsafe_refcount> { - typedef RCPtr<FilterBase> Ptr; + using Ptr = RCPtr<FilterBase>; virtual bool filter(const Option &opt) = 0; }; class KeyValue : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<KeyValue> Ptr; + using Ptr = RCPtr<KeyValue>; KeyValue() : key_priority(0) @@ -696,7 +687,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r Option opt; const std::string unesc_value = unescape(value, newline_present); - if (string::starts_with(key, meta_prefix)) + if (key.starts_with(meta_prefix)) { opt.push_back(std::string(key, meta_prefix.length())); opt.set_meta(); @@ -741,10 +732,9 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const int cmp = a->key.compare(b->key); if (cmp < 0) return true; - else if (cmp > 0) + if (cmp > 0) return false; - else - return a->key_priority < b->key_priority; + return a->key_priority < b->key_priority; } std::string key; @@ -829,9 +819,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r } }; - OptionList() - { - } + OptionList() = default; template <typename T, typename... Args> explicit OptionList(T first, Args... args) @@ -895,7 +883,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); ++i) { const Option opt = Split::by_space<Option, Lex, SpaceMatch, Limits>(*i, lim); - if (opt.size()) + if (!opt.empty()) { if (lim) { @@ -914,7 +902,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r for (auto &arg : argv) { std::string a = arg; - if (string::starts_with(a, "--")) + if (a.starts_with("--")) { if (!opt.empty()) { @@ -942,7 +930,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r Option opt; opt.reserve(2); Split::by_char_void<Option, NullLex, Limits>(opt, line, '=', 0, 1, lim); - if (opt.size()) + if (!opt.empty()) { if (lim) { @@ -1021,7 +1009,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r else if (!ignore_line(line)) { Option opt = parse_option_from_line(line, lim); - if (opt.size()) + if (!opt.empty()) { if (is_open_tag(opt.ref(0))) { @@ -1062,7 +1050,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r if (in.line_overflow()) line_too_long(line_num); std::string &line = in.line_ref(); - if (string::starts_with(line, "# ")) + if (line.starts_with("# ")) { line = std::string(line, 2); if (in_multiline) @@ -1086,10 +1074,10 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r mref += '\n'; } } - else if (string::starts_with(line, prefix)) + else if (line.starts_with(prefix)) { Option opt = Split::by_char<Option, NullLex, Limits>(std::string(line, prefix.length()), '=', 0, 1, lim); - if (opt.size()) + if (!opt.empty()) { if (is_open_meta_tag(opt.ref(0))) { @@ -1173,7 +1161,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r for (std::vector<Option>::const_iterator i = other.begin(); i != other.end(); ++i) { const Option &opt = *i; - if (!opt.empty() && map().find(opt.ref(0)) == map().end()) + if (!opt.empty() && !map().contains(opt.ref(0))) { push_back(opt); opt.touch(); @@ -1216,8 +1204,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r ret->touch(); return ret; } - else - OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "more than one instance of option '" << name << '\''); + OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "more than one instance of option '" << name << '\''); } else return nullptr; @@ -1244,8 +1231,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r } return first; } - else - return nullptr; + return nullptr; } // Get option, throw error if not found @@ -1256,8 +1242,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const Option *o = get_ptr(name); if (o) return *o; - else - OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "option '" << name << "' not found"); + OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "option '" << name << "' not found"); } // Get the list of options having the same name (by index), @@ -1267,8 +1252,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r IndexMap::const_iterator e = map_.find(name); if (e != map_.end() && !e->second.empty()) return e->second; - else - OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "option '" << name << "' not found"); + OPENVPN_THROW_ARG1(option_error, ERR_INVALID_CONFIG, "option '" << name << "' not found"); } // Get the list of options having the same name (by index), @@ -1278,8 +1262,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r IndexMap::const_iterator e = map_.find(name); if (e != map_.end() && !e->second.empty()) return &e->second; - else - return nullptr; + return nullptr; } // Concatenate all one-arg directives of a given name, in index order. @@ -1344,8 +1327,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const Option *o = get_ptr(name); if (o) return o->get(index, max_len); - else - return ""; + return ""; } // Like get_optional(), but return "" if argument index is out-of-bounds. @@ -1354,8 +1336,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const Option *o = get_ptr(name); if (o) return o->get_optional(index, max_len); - else - return ""; + return ""; } // Like get_optional(), but return "" if exception is thrown. @@ -1377,8 +1358,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const Option *o = get_ptr(name); if (o) return o->get(index, max_len).c_str(); - else - return nullptr; + return nullptr; } // Convenience method that gets a particular argument index within an option, @@ -1392,8 +1372,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const Option *o = get_ptr(name); if (o) return o->get(index, max_len); - else - return default_value; + return default_value; } // Like get_default(), but return default_value if argument index is out-of-bounds. @@ -1415,7 +1394,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r template <typename T> T get_num(const std::string &name, const size_t idx, const T default_value) const { - typedef typename std::remove_const<T>::type T_nonconst; + using T_nonconst = typename std::remove_const<T>::type; T_nonconst n = default_value; const Option *o = get_ptr(name); if (o) @@ -1430,7 +1409,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r const T min_value, const T max_value) const { - typedef typename std::remove_const<T>::type T_nonconst; + using T_nonconst = typename std::remove_const<T>::type; T_nonconst n = default_value; const Option *o = get_ptr(name); if (o) @@ -1472,7 +1451,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r { if (flags & Option::RENDER_NUMBER) out << i << ' '; - out << o.render(flags) << std::endl; + out << o.render(flags) << '\n'; } } return out.str(); @@ -1502,7 +1481,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r out << i->first << " ["; for (IndexList::const_iterator j = i->second.begin(); j != i->second.end(); ++j) out << ' ' << *j; - out << " ]" << std::endl; + out << " ]\n"; } return out.str(); } @@ -1542,7 +1521,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r { if (!title) title = "NOTE: Unused Options"; - OPENVPN_LOG_NTNL(title << std::endl + OPENVPN_LOG_NTNL(title << '\n' << render(Option::RENDER_TRUNC_64 | Option::RENDER_NUMBER | Option::RENDER_BRACKET | Option::RENDER_UNUSED)); } } @@ -1651,7 +1630,7 @@ class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_r // return true if string is a meta tag, e.g. WEB_CA_BUNDLE_START static bool is_open_meta_tag(const std::string &str) { - return string::ends_with(str, "_START"); + return str.ends_with("_START"); } // return true if string is a tag, e.g. WEB_CA_BUNDLE_STOP diff --git a/openvpn/common/path.hpp b/openvpn/common/path.hpp index 81180968c..42548a9bb 100644 --- a/openvpn/common/path.hpp +++ b/openvpn/common/path.hpp @@ -60,13 +60,13 @@ inline bool win_dev(const std::string &path, const bool fully_qualified) // true if path is fully qualified inline bool is_fully_qualified(const std::string &path) { - return win_dev(path, true) || (path.length() > 0 && is_dirsep(path[0])); + return win_dev(path, true) || (!path.empty() && is_dirsep(path[0])); } // does path refer to regular file without directory traversal inline bool is_flat(const std::string &path) { - return path.length() > 0 + return !path.empty() && path != "." && path != ".." && path.find_first_of(dirsep) == std::string::npos @@ -81,11 +81,9 @@ inline std::string basename(const std::string &path) const size_t p = pos + 1; if (p >= path.length()) return ""; - else - return path.substr(p); + return path.substr(p); } - else - return path; + return path; } inline std::string dirname(const std::string &path) @@ -95,11 +93,9 @@ inline std::string dirname(const std::string &path) { if (pos == 0) return "/"; - else - return path.substr(0, pos); + return path.substr(0, pos); } - else - return ""; + return ""; } // return true if path is a regular file that doesn't try to traverse via ".." or "/..." @@ -161,11 +157,9 @@ inline std::string ext(const std::string &basename) const size_t p = pos + 1; if (p >= basename.length()) return ""; - else - return basename.substr(p); + return basename.substr(p); } - else - return ""; + return ""; } inline std::string root(const std::string &basename) @@ -173,16 +167,14 @@ inline std::string root(const std::string &basename) const size_t pos = basename.find_last_of('.'); if (pos != std::string::npos) return basename.substr(0, pos); - else - return basename; + return basename; } inline std::string join(const std::string &p1, const std::string &p2) { if (p1.empty() || is_fully_qualified(p2)) return p2; - else - return string::add_trailing_copy(p1, dirsep[0]) + p2; + return string::add_trailing_copy(p1, dirsep[0]) + p2; } template <typename... Args> diff --git a/openvpn/common/pipe.hpp b/openvpn/common/pipe.hpp index 61dec5274..8f1610f97 100644 --- a/openvpn/common/pipe.hpp +++ b/openvpn/common/pipe.hpp @@ -95,7 +95,7 @@ class SD_IN : public SD private: void queue_read() { - buf.reset(0, 2048, 0); + buf.reset(0, 2048, BufAllocFlags::NO_FLAGS); sd->async_read_some(buf.mutable_buffer_clamp(), [this](const openvpn_io::error_code &ec, const size_t bytes_recvd) { diff --git a/openvpn/common/platform.hpp b/openvpn/common/platform.hpp index 31d393482..67d029738 100644 --- a/openvpn/common/platform.hpp +++ b/openvpn/common/platform.hpp @@ -14,7 +14,7 @@ #ifndef OPENVPN_COMMON_PLATFORM_H #define OPENVPN_COMMON_PLATFORM_H -#if defined(_WIN32) +#ifdef _WIN32 #define OPENVPN_PLATFORM_WIN #if defined(__cplusplus_winrt) #include <winapifamily.h> @@ -41,7 +41,7 @@ #define OPENVPN_PLATFORM_LINUX #endif -#if !defined(_WIN32) +#ifndef _WIN32 #define OPENVPN_PLATFORM_TYPE_UNIX #endif diff --git a/openvpn/common/platform_name.hpp b/openvpn/common/platform_name.hpp index 4621c75ed..25301acc3 100644 --- a/openvpn/common/platform_name.hpp +++ b/openvpn/common/platform_name.hpp @@ -20,7 +20,7 @@ namespace openvpn { // return a string that describes our platform inline const char *platform_name() { -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #if defined(OPENVPN_PLATFORM_UWP) return "uwp"; #else diff --git a/openvpn/common/platform_string.hpp b/openvpn/common/platform_string.hpp index 00fb1206f..b4d176b34 100644 --- a/openvpn/common/platform_string.hpp +++ b/openvpn/common/platform_string.hpp @@ -27,11 +27,11 @@ inline std::string platform_string(const std::string &title, const std::string & if (!app_version.empty()) os << app_version << '/'; os << OPENVPN_VERSION; -#if defined OPENVPN_CORE_GIT_VERSION +#ifdef OPENVPN_CORE_GIT_VERSION os << "(" << OPENVPN_CORE_GIT_VERSION << ")"; #endif os << ' ' << platform_name(); -#if defined(OPENVPN_ARCH_x86_64) +#ifdef OPENVPN_ARCH_x86_64 os << " x86_64"; #elif defined(OPENVPN_ARCH_i386) os << " i386"; diff --git a/openvpn/common/process.hpp b/openvpn/common/process.hpp index 6bc7f20de..75ac536d4 100644 --- a/openvpn/common/process.hpp +++ b/openvpn/common/process.hpp @@ -46,7 +46,7 @@ inline pid_t system_cmd_async(const std::string &cmd, auto av = argv_wrap.c_argv(); auto ev = env_wrap ? env_wrap->c_argv() : ::environ; -#if defined(__APPLE__) +#ifdef __APPLE__ /* macOS vfork is deprecated and behaves identical to fork() */ const pid_t pid = ::fork(); #else @@ -109,7 +109,7 @@ inline int system_cmd(const std::string &cmd, const Argv &argv) inline int system_cmd(const Argv &argv) { int ret = -1; - if (argv.size()) + if (!argv.empty()) ret = system_cmd(argv[0], argv); return ret; } @@ -124,7 +124,7 @@ inline int system_cmd(const std::string &cmd, unsigned int redirect_pipe_flags, const sigset_t *sigmask) { - SignalBlockerPipe sbpipe; + const SignalBlockerPipe sbpipe; RedirectPipe remote; if (!inout.in.empty()) redirect_pipe_flags |= RedirectPipe::ENABLE_IN; @@ -138,11 +138,9 @@ inline int system_cmd(const std::string &cmd, struct Command : public Action { - typedef RCPtr<Command> Ptr; + using Ptr = RCPtr<Command>; - Command() - { - } + Command() = default; Command(Argv argv_arg) : argv(std::move(argv_arg)) @@ -157,20 +155,20 @@ struct Command : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (!argv.empty()) { - os << to_string() << std::endl; + os << to_string() << '\n'; #ifdef OPENVPN_PROCESS_AVOID_PIPES const int status = system_cmd(argv[0], argv); if (status < 0) - os << "Error: command failed to execute" << std::endl; + os << "Error: command failed to execute\n"; #else RedirectPipe::InOut inout; const int status = system_cmd(argv[0], argv, nullptr, inout, RedirectPipe::COMBINE_OUT_ERR, nullptr); if (status < 0) - os << "Error: command failed to execute" << std::endl; + os << "Error: command failed to execute\n"; os << inout.out; /* if route already exists, we got "File exists" in output */ @@ -179,10 +177,10 @@ struct Command : public Action #endif } else - os << "Error: command called with empty argv" << std::endl; + os << "Error: command called with empty argv\n"; } - virtual std::string to_string() const override + std::string to_string() const override { return argv.to_string(); } diff --git a/openvpn/common/rc.hpp b/openvpn/common/rc.hpp index a4d9803a9..6fb52a622 100644 --- a/openvpn/common/rc.hpp +++ b/openvpn/common/rc.hpp @@ -118,7 +118,7 @@ template <typename T> class RCPtr { public: - typedef T element_type; + using element_type = T; RCPtr() noexcept; RCPtr(T *p, const bool add_ref = true) noexcept; @@ -165,7 +165,7 @@ class RCPtr */ template <typename T> RCPtr<T>::RCPtr() noexcept - : px(nullptr){}; + : px(nullptr) {}; /** @brief Construct a new RCPtr<T>::RCPtr object @tparam T an RC enabled type @@ -449,10 +449,10 @@ RCPtr<U> RCPtr<T>::dynamic_pointer_cast() const noexcept template <typename T> class RCWeakPtr { - typedef RCPtr<T> Strong; + using Strong = RCPtr<T>; public: - typedef T element_type; + using element_type = T; RCWeakPtr() noexcept; RCWeakPtr(const Strong &p) noexcept; @@ -557,8 +557,7 @@ olong RCWeakPtr<T>::use_count() const noexcept { if (controller) return controller->use_count(); - else - return 0; + return 0; } /** @brief Returns true if the underlying object is already freed. @@ -584,8 +583,7 @@ typename RCWeakPtr<T>::Strong RCWeakPtr<T>::lock() const noexcept { if (controller) return controller->template lock<Strong>(); - else - return Strong(); + return Strong(); } /** @brief Try to move the weak pointer into a strong pointer @@ -602,8 +600,7 @@ typename RCWeakPtr<T>::Strong RCWeakPtr<T>::move_strong() noexcept c.swap(controller); if (c) return c->template lock<Strong>(); - else - return Strong(); + return Strong(); } /* We're pretty sure these are false positives. They only occur with very @@ -621,7 +618,7 @@ typename RCWeakPtr<T>::Strong RCWeakPtr<T>::move_strong() noexcept #if __GNUC__ == 12 #pragma GCC diagnostic warning "-Wuse-after-free" #endif -#if __GNUC__ == 13 || __GNUC__ == 14 +#if __GNUC__ == 13 || __GNUC__ == 14 || __GNUC__ == 15 #pragma GCC diagnostic warning "-Wstringop-overflow" #endif #endif @@ -697,8 +694,7 @@ inline bool thread_unsafe_refcount::inc_if_nonzero() noexcept ++rc; return true; } - else - return false; + return false; } /** @brief Returns the internal use count @@ -911,7 +907,7 @@ template <typename RCImpl> class RC { public: - typedef RCPtr<RC> Ptr; + using Ptr = RCPtr<RC>; RC() noexcept = default; virtual ~RC() = default; @@ -1105,8 +1101,8 @@ class RCWeak struct ControllerRef; public: - typedef RCPtr<RCWeak> Ptr; - typedef RCWeakPtr<RCWeak> WPtr; + using Ptr = RCPtr<RCWeak>; + using WPtr = RCWeakPtr<RCWeak>; RCWeak() noexcept : refcount_(this) {}; @@ -1184,7 +1180,7 @@ class RCWeak template <typename RCImpl> struct RCWeak<RCImpl>::Controller : public RC<RCImpl> { - typedef RCPtr<Controller> Ptr; + using Ptr = RCPtr<Controller>; Controller(RCWeak *parent_arg) noexcept; @@ -1203,7 +1199,7 @@ struct RCWeak<RCImpl>::Controller : public RC<RCImpl> */ template <typename RCImpl> RCWeak<RCImpl>::Controller::Controller(RCWeak *parent_arg) noexcept - : parent(parent_arg){}; + : parent(parent_arg) {}; /** @brief Get the use count of the underlying ref count implementation @tparam RCImpl the ref count implementation @@ -1229,8 +1225,7 @@ PTR RCWeak<RCImpl>::Controller::lock() noexcept { if (rc.inc_if_nonzero()) return PTR(static_cast<typename PTR::element_type *>(parent), false); - else - return PTR(); + return PTR(); } /** @@ -1267,7 +1262,7 @@ struct RCWeak<RCImpl>::ControllerRef */ template <typename RCImpl> RCWeak<RCImpl>::ControllerRef::ControllerRef(RCWeak *parent) noexcept - : controller(new Controller(parent)){}; + : controller(new Controller(parent)) {}; /** @brief Increments the ref count @tparam RCImpl the injected ref count implementation @@ -1400,7 +1395,7 @@ template <typename R> inline void intrusive_ptr_add_ref(R *rcptr) noexcept { #ifdef OPENVPN_RC_DEBUG - std::cout << "ADD REF " << cxx_demangle(typeid(rcptr).name()) << std::endl; + std::cout << "ADD REF " << cxx_demangle(typeid(rcptr).name()) << "\n"; #endif ++rcptr->refcount_; } @@ -1420,7 +1415,7 @@ inline void intrusive_ptr_release(R *rcptr) noexcept if (--rcptr->refcount_ == 0) { #ifdef OPENVPN_RC_DEBUG - std::cout << "DEL OBJ " << cxx_demangle(typeid(rcptr).name()) << std::endl; + std::cout << "DEL OBJ " << cxx_demangle(typeid(rcptr).name()) << "\n"; #endif #ifdef OPENVPN_RC_NOTIFY rcptr->refcount_.notify_release(); @@ -1430,7 +1425,7 @@ inline void intrusive_ptr_release(R *rcptr) noexcept else { #ifdef OPENVPN_RC_DEBUG - std::cout << "REL REF " << cxx_demangle(typeid(rcptr).name()) << std::endl; + std::cout << "REL REF " << cxx_demangle(typeid(rcptr).name()) << "\n"; #endif } } diff --git a/openvpn/common/redir.hpp b/openvpn/common/redir.hpp index e6409605b..ee609e3d0 100644 --- a/openvpn/common/redir.hpp +++ b/openvpn/common/redir.hpp @@ -138,9 +138,7 @@ class RedirectStd : public RedirectStdFD } protected: - RedirectStd() - { - } + RedirectStd() = default; void open_input(const std::string &fn) { @@ -210,9 +208,7 @@ class RedirectPipe : public RedirectStdFD std::string err; }; - RedirectPipe() - { - } + RedirectPipe() = default; RedirectPipe(RedirectStdFD &remote, const unsigned int flags_arg) diff --git a/openvpn/common/runcontext.hpp b/openvpn/common/runcontext.hpp index 11fea8de0..751b02810 100644 --- a/openvpn/common/runcontext.hpp +++ b/openvpn/common/runcontext.hpp @@ -212,12 +212,12 @@ class RunContext : public RunContextBase void set_exit_socket(ScopedFD &fd) { exit_sock.reset(new openvpn_io::posix::stream_descriptor(io_context, fd.release())); - exit_sock->async_read_some(openvpn_io::null_buffers(), - [self = Ptr(this)](const openvpn_io::error_code &error, const size_t bytes_recvd) - { - if (!error) - self->cancel(); - }); + exit_sock->async_wait(openvpn_io::posix::stream_descriptor::wait_read, + [self = Ptr(this)](const openvpn_io::error_code &error) + { + if (!error) + self->cancel(); + }); } #endif diff --git a/openvpn/common/scoped_fd.hpp b/openvpn/common/scoped_fd.hpp index 88c206a67..ca21a4796 100644 --- a/openvpn/common/scoped_fd.hpp +++ b/openvpn/common/scoped_fd.hpp @@ -25,7 +25,7 @@ class ScopedFD ScopedFD &operator=(const ScopedFD &) = delete; public: - typedef int base_type; + using base_type = int; ScopedFD() : fd(undefined()) diff --git a/openvpn/common/sess_id.hpp b/openvpn/common/sess_id.hpp index 142ec716b..4ac6fca12 100644 --- a/openvpn/common/sess_id.hpp +++ b/openvpn/common/sess_id.hpp @@ -180,8 +180,8 @@ class SessionIDType }; // Create two concrete types: 64 and 128-bit Session IDs. -typedef SessionIDType<8> SessionID64; -typedef SessionIDType<16> SessionID128; +using SessionID64 = SessionIDType<8>; +using SessionID128 = SessionIDType<16>; OPENVPN_OSTREAM(SessionID64, to_string); OPENVPN_OSTREAM(SessionID128, to_string); diff --git a/openvpn/common/signal.hpp b/openvpn/common/signal.hpp index 867d0cba5..5e6a98cad 100644 --- a/openvpn/common/signal.hpp +++ b/openvpn/common/signal.hpp @@ -14,7 +14,7 @@ #include <openvpn/common/platform.hpp> -#if !defined(OPENVPN_PLATFORM_WIN) +#ifndef OPENVPN_PLATFORM_WIN #include <signal.h> @@ -27,7 +27,7 @@ class Signal public: OPENVPN_SIMPLE_EXCEPTION(signal_error); - typedef void (*handler_t)(int signum); + using handler_t = void (*)(int signum); enum { @@ -131,8 +131,7 @@ class SignalBlocker { if (blocked_) return &old_mask_; - else - return nullptr; + return nullptr; } // Destructor restores the previous signal mask. diff --git a/openvpn/common/sleep.hpp b/openvpn/common/sleep.hpp deleted file mode 100644 index 79fe8bdfc..000000000 --- a/openvpn/common/sleep.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -// Portable millisecond sleep - -#ifndef OPENVPN_COMMON_SLEEP_H -#define OPENVPN_COMMON_SLEEP_H - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#include <windows.h> -#else -#include <time.h> -#endif - -namespace openvpn { -inline bool sleep_milliseconds(const unsigned int milliseconds) -{ -#ifdef OPENVPN_PLATFORM_WIN - ::Sleep(milliseconds); - return true; -#else - struct timespec ts; - ts.tv_sec = milliseconds / 1000U; - ts.tv_nsec = (milliseconds % 1000U) * 1000000U; - return ::nanosleep(&ts, nullptr) == 0; -#endif -} -} // namespace openvpn - -#endif diff --git a/openvpn/common/splitlines.hpp b/openvpn/common/splitlines.hpp index 8745c27fe..3c11237c2 100644 --- a/openvpn/common/splitlines.hpp +++ b/openvpn/common/splitlines.hpp @@ -178,7 +178,7 @@ class SplitLinesType bool overflow = false; }; -typedef SplitLinesType<std::string> SplitLines; +using SplitLines = SplitLinesType<std::string>; } // namespace openvpn #endif diff --git a/openvpn/common/stat.hpp b/openvpn/common/stat.hpp index 0c3f524b8..9e8ef6cd2 100644 --- a/openvpn/common/stat.hpp +++ b/openvpn/common/stat.hpp @@ -19,31 +19,6 @@ namespace openvpn { -// Return true if file exists -inline bool file_exists(const std::string &filename) -{ - if (filename.empty()) - return false; - struct stat buffer; - return ::stat(filename.c_str(), &buffer) == 0; -} - -/** - * Check if file exists AND is nonempty. - * - * @param filename File to check. - * @return true if file exists AND is nonempty. - */ -inline bool file_exists_nonempty(const std::string &filename) -{ - if (filename.empty()) - return false; - struct stat s; - if (::stat(filename.c_str(), &s) != 0) - return false; - return s.st_size > 0; -} - // Return true if dirname is a directory inline bool is_directory(const std::string &pathname, const bool follow_symlinks = false) { diff --git a/openvpn/common/stop.hpp b/openvpn/common/stop.hpp index a2d20e186..daca14930 100644 --- a/openvpn/common/stop.hpp +++ b/openvpn/common/stop.hpp @@ -39,7 +39,7 @@ class Stop constexpr int stop_index_limit = 1000; if (stop) { - std::lock_guard<std::recursive_mutex> lock(stop->mutex); + const std::lock_guard<std::recursive_mutex> lock(stop->mutex); if (stop->stop_called) { // stop already called, call method immediately @@ -60,7 +60,7 @@ class Stop { if (stop) { - std::lock_guard<std::recursive_mutex> lock(stop->mutex); + const std::lock_guard<std::recursive_mutex> lock(stop->mutex); if (index >= 0 && index < static_cast<int>(stop->scopes.size()) && stop->scopes[index] == this) { stop->scopes[index] = nullptr; @@ -78,15 +78,13 @@ class Stop int index; }; - Stop() - { - } + Stop() = default; void stop() { - std::lock_guard<std::recursive_mutex> lock(mutex); + const std::lock_guard<std::recursive_mutex> lock(mutex); stop_called = true; - while (scopes.size()) + while (!scopes.empty()) { Scope *scope = scopes.back(); scopes.pop_back(); @@ -109,7 +107,7 @@ class Stop private: void prune() { - while (scopes.size() && !scopes.back()) + while (!scopes.empty() && !scopes.back()) scopes.pop_back(); } diff --git a/openvpn/common/string.hpp b/openvpn/common/string.hpp index 7231616e2..c464121fc 100644 --- a/openvpn/common/string.hpp +++ b/openvpn/common/string.hpp @@ -15,10 +15,14 @@ #define OPENVPN_COMMON_STRING_H #include <string> +#include <string_view> #include <vector> #include <cstring> #include <locale> #include <algorithm> +#include <optional> + +#include <fmt/core.h> #include <openvpn/common/platform.hpp> #include <openvpn/common/size.hpp> @@ -75,72 +79,20 @@ inline bool is_true(const std::string &str) return str == "1" || !strcasecmp(str.c_str(), "true"); } -template <typename STRING> -inline bool starts_with(const STRING &str, const std::string &prefix) -{ - const size_t len = str.length(); - const size_t plen = prefix.length(); - if (plen <= len) - return std::memcmp(str.c_str(), prefix.c_str(), plen) == 0; - else - return false; -} - -template <typename STRING> -inline bool starts_with(const STRING &str, const char *prefix) -{ - const size_t len = str.length(); - const size_t plen = std::strlen(prefix); - if (plen <= len) - return std::memcmp(str.c_str(), prefix, plen) == 0; - else - return false; -} - // Return true if str == prefix or if str starts with prefix + delim template <typename STRING> inline bool starts_with_delim(const STRING &str, const std::string &prefix, const char delim) { if (prefix.length() < str.length()) - return str[prefix.length()] == delim && string::starts_with(str, prefix); - else - return prefix == str; -} - -template <typename STRING> -inline bool ends_with(const STRING &str, const std::string &suffix) -{ - const size_t len = str.length(); - const size_t slen = suffix.length(); - if (slen <= len) - return std::memcmp(str.c_str() + (len - slen), suffix.c_str(), slen) == 0; - else - return false; -} - -template <typename STRING> -inline bool ends_with(const STRING &str, const char *suffix) -{ - const size_t len = str.length(); - const size_t slen = std::strlen(suffix); - if (slen <= len) - return std::memcmp(str.c_str() + (len - slen), suffix, slen) == 0; - else - return false; -} - -// return true if string ends with char c -template <typename STRING> -inline bool ends_with(const STRING &str, const char c) -{ - return str.length() && str.back() == c; + return str[prefix.length()] == delim && str.starts_with(prefix); + return prefix == str; } // return true if string ends with a newline template <typename STRING> inline bool ends_with_newline(const STRING &str) { - return ends_with(str, '\n'); + return str.ends_with('\n'); } // return true if string ends with a CR or LF @@ -152,8 +104,7 @@ inline bool ends_with_crlf(const STRING &str) const char c = str.back(); return c == '\n' || c == '\r'; } - else - return false; + return false; } // Prepend leading characters (c) to str to obtain a minimum string length (min_len). @@ -174,27 +125,26 @@ inline std::string add_leading(const std::string &str, const size_t min_len, con // make sure that string ends with char c, if not append it inline std::string add_trailing_copy(const std::string &str, const char c) { - if (ends_with(str, c)) + if (str.ends_with(c)) return str; - else - return str + c; + return str + c; } // make sure that string ends with char c, if not append it inline void add_trailing(std::string &str, const char c) { - if (!ends_with(str, c)) + if (!str.ends_with(c)) str += c; } // make sure that string ends with CRLF, if not append it inline void add_trailing_crlf(std::string &str) { - if (ends_with(str, "\r\n")) + if (str.ends_with("\r\n")) ; - else if (ends_with(str, '\r')) + else if (str.ends_with('\r')) str += '\n'; - else if (ends_with(str, '\n')) + else if (str.ends_with('\n')) { str.pop_back(); str += "\r\n"; @@ -213,10 +163,9 @@ inline std::string add_trailing_crlf_copy(std::string str) // make sure that string ends with char c, if not append it (unless the string is empty) inline std::string add_trailing_unless_empty_copy(const std::string &str, const char c) { - if (str.empty() || ends_with(str, c)) + if (str.empty() || str.ends_with(c)) return str; - else - return str + c; + return str + c; } // remove trailing \r or \n chars @@ -264,8 +213,7 @@ inline std::string to_delim(const std::string &str, const char delim) const size_t pos = str.find_first_of(delim); if (pos != std::string::npos) return str.substr(0, pos); - else - return str; + return str; } // return the first line (without newline) of a multi-line string @@ -274,8 +222,20 @@ inline std::string first_line(const std::string &str) return to_delim(str, '\n'); } -// Define a common interpretation of what constitutes a space character. -// Return true if c is a space char. +/** + * Define a common interpretation of what constitutes a space character. + * + * According to the Notes section at + * https://en.cppreference.com/w/cpp/string/byte/isspace.html: + * + * "Like all other functions from <cctype>, the behavior of `std::isspace` + * is undefined if the argument's value is neither representable as + * `unsigned char` nor equal to `EOF`. To use these functions safely with + * plain chars (or signed chars), the argument should first be converted + * to `unsigned char`" + * + * @return true if c is a space char. + **/ inline bool is_space(const char c) { return std::isspace(static_cast<unsigned char>(c)) != 0; @@ -680,6 +640,56 @@ inline std::string remove_char(const std::string &str, const char remove) return ret; } +/** + @brief Convert variadic arguments to a string. + @details This function takes a delimiter and a variadic number of arguments, + and concatenates them into a single string, separated by the specified delimiter. + The function uses a fold expression to handle the variadic arguments and + formats each argument using format. The resulting string is returned. + @note The function is designed to work with any type that can be formatted + @tparam ArgsT variadic template parameter pack for the arguments to be formatted. + @param delim The delimiter to be used for separating the arguments in the resulting string. + @param args The variadic arguments to be concatenated into a string. + @return std::string The concatenated string with the specified delimiter separating + the arguments. + @throws format_error if formatting fails. + @throws exceptions from std::string operations +*/ +template <typename... ArgsT> +inline auto args_to_string(std::string_view delim, ArgsT &&...args) -> std::string +{ + std::string result; + ((result += std::string(result.empty() ? "" : delim) + fmt::format("{}", args)), ...); + return result; +} + +/** + @brief Format a string with error handling. + @details This function attempts to format a string using the provided format + and arguments. If an exception occurs during formatting, it catches the exception + and returns std::nullopt to indicate that the formatting failed. + @tparam ArgsT variadic template parameter pack for the arguments to be formatted. + @param format The format string to be used for formatting. + @param args The arguments to be formatted into the string. + @return std::optional<std::string> The formatted string or nullopt on format error + @note This function uses vformat and make_format_args for formatting. + @note The function is designed to handle exceptions that may occur during formatting, + including std::exception and other unknown exceptions. If an exception occurs, + it returns a nullopt to indicate that the formatting failed. +*/ +template <typename... ArgsT> +inline auto format_safe(std::string format, ArgsT &&...args) noexcept -> std::optional<std::string> +{ + try + { + return fmt::vformat(format, fmt::make_format_args(args...)); + } + catch (...) + { + return std::nullopt; + } +} + } // namespace openvpn::string #endif // OPENVPN_COMMON_STRING_H diff --git a/openvpn/common/stringtempl.hpp b/openvpn/common/stringtempl.hpp index a83fd38a0..b63303b82 100644 --- a/openvpn/common/stringtempl.hpp +++ b/openvpn/common/stringtempl.hpp @@ -52,8 +52,7 @@ inline std::string to_string(const char *str) { if (str) return std::string(str); - else - return to_string(nullptr); + return to_string(nullptr); } inline std::string to_string(std::string &&str) diff --git a/openvpn/common/tempfile.hpp b/openvpn/common/tempfile.hpp index 298d3ed3b..72993e56b 100644 --- a/openvpn/common/tempfile.hpp +++ b/openvpn/common/tempfile.hpp @@ -14,7 +14,7 @@ #include <openvpn/common/platform.hpp> -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #error temporary file methods not supported on Windows #endif @@ -122,8 +122,7 @@ class TempFile { if (fn) return fn.get(); - else - return ""; + return ""; } void close_file() diff --git a/openvpn/common/to_string.hpp b/openvpn/common/to_string.hpp index a295b8577..d0b7cec47 100644 --- a/openvpn/common/to_string.hpp +++ b/openvpn/common/to_string.hpp @@ -9,10 +9,6 @@ // SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception // -// Define openvpn::to_string() to work around the fact that -// std::to_string() is missing on Android. -// http://stackoverflow.com/questions/22774009/android-ndk-stdto-string-support - #ifndef OPENVPN_COMMON_TO_STRING_H #define OPENVPN_COMMON_TO_STRING_H @@ -22,33 +18,37 @@ #include <openvpn/common/platform.hpp> -namespace openvpn { - -// Convert an arbitrary argument to a string. +/* This file provides an openvpn::to_string function that works for all + types where either std::to_string is available or the type can be + streamed to an std::ostringstream. This is useful for types that don't + have a std::to_string overload. Also useful in cases where std::to_string + support is not complete. +*/ -#ifndef OPENVPN_PLATFORM_ANDROID -// numeric types -template <typename T, - typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> -inline std::string to_string(T value) -{ - return std::to_string(value); -} -#endif +namespace openvpn { -// non-numeric types -template <typename T -#ifndef OPENVPN_PLATFORM_ANDROID - , - typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0 -#endif - > -inline std::string to_string(const T &value) +// Use std::to_string where we can +using std::to_string; + +/** + @brief Convert a value to a string + @tparam T The type of the value to convert + @param t The value to convert + @return std::string Stringified representation of the value + @note This function uses std::ostringstream to convert the value to a string + @note This function is enabled only for types that do not have a std::to_string + overload as long as the type is ostream insertable. +*/ +template <typename T> + requires(!requires(T a) { std::to_string(a); }) + && requires(std::ostream &os, const T &t) { os << t; } +inline std::string to_string(const T &t) { std::ostringstream os; - os << value; + os << t; return os.str(); } + } // namespace openvpn #endif diff --git a/openvpn/common/unicode-impl.hpp b/openvpn/common/unicode-impl.hpp index 59cae42e5..eddf8a061 100644 --- a/openvpn/common/unicode-impl.hpp +++ b/openvpn/common/unicode-impl.hpp @@ -92,9 +92,9 @@ namespace openvpn::Unicode { bit mask & shift operations. ------------------------------------------------------------------------ */ - typedef unsigned int UTF32; /* at least 32 bits */ - typedef unsigned short UTF16; /* at least 16 bits */ - typedef unsigned char UTF8; /* typically 8 bits */ + using UTF32 = unsigned int; /* at least 32 bits */ + using UTF16 = unsigned short; /* at least 16 bits */ + using UTF8 = unsigned char; /* typically 8 bits */ /* Some fundamental constants */ const UTF32 UNI_REPLACEMENT_CHAR = (UTF32)0x0000FFFD; @@ -103,17 +103,17 @@ namespace openvpn::Unicode { const UTF32 UNI_MAX_UTF32 = (UTF32)0x7FFFFFFF; const UTF32 UNI_MAX_LEGAL_UTF32 = (UTF32)0x0010FFFF; - typedef enum { + enum ConversionResult { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ targetExhausted, /* insuff. room in target for conversion */ sourceIllegal /* source sequence is illegal/malformed */ - } ConversionResult; + }; - typedef enum { + enum ConversionFlags { strictConversion = 0, lenientConversion - } ConversionFlags; + }; /* --------------------------------------------------------------------- */ /* diff --git a/openvpn/common/unicode.hpp b/openvpn/common/unicode.hpp index 1c1baeec8..245500ce4 100644 --- a/openvpn/common/unicode.hpp +++ b/openvpn/common/unicode.hpp @@ -249,8 +249,7 @@ class UTF8Iterator { if (is_valid()) return std::string((char *)data, len); - else - return malformed; + return malformed; } }; @@ -281,8 +280,7 @@ class UTF8Iterator size -= c.len; return true; } - else - return false; + return false; } private: diff --git a/openvpn/common/unreachable.hpp b/openvpn/common/unreachable.hpp index 14a1590ed..b50ab7933 100644 --- a/openvpn/common/unreachable.hpp +++ b/openvpn/common/unreachable.hpp @@ -21,7 +21,7 @@ namespace openvpn { // Uses compiler specific extensions if possible. // Even if no extension is used, undefined behavior is still raised by // an empty function body and the noreturn attribute. -#if defined(__GNUC__) +#ifdef __GNUC__ __builtin_unreachable(); #elif defined(_MSC_VER) __assume(false); diff --git a/openvpn/common/userpass.hpp b/openvpn/common/userpass.hpp index 9025904cb..6bd85515a 100644 --- a/openvpn/common/userpass.hpp +++ b/openvpn/common/userpass.hpp @@ -153,7 +153,7 @@ inline void parse(const OptionList &options, up.reserve(2); if (!parse(options, opt_name, flags, &up) && (flags & OPT_OPTIONAL)) return; - if (up.size() >= 1) + if (!up.empty()) { user = std::move(up[0]); if (up.size() >= 2) diff --git a/openvpn/common/version.hpp b/openvpn/common/version.hpp index adc421f74..432de57fa 100644 --- a/openvpn/common/version.hpp +++ b/openvpn/common/version.hpp @@ -14,5 +14,5 @@ #pragma once #ifndef OPENVPN_VERSION -#define OPENVPN_VERSION "3.11.6" +#define OPENVPN_VERSION "3.12_git:master" #endif diff --git a/openvpn/common/wstring.hpp b/openvpn/common/wstring.hpp index e2d4e0555..8d393a4b5 100644 --- a/openvpn/common/wstring.hpp +++ b/openvpn/common/wstring.hpp @@ -61,23 +61,6 @@ inline std::string to_utf8(const std::wstring &wstr) return str; } -/** - * @brief Split a wide character string into a C array of it's letters - * - * @param wstr The wide string to be split - * @return std::unique_ptr<wchar_t[]> Smart pointer to the generated array - */ -inline std::unique_ptr<wchar_t[]> to_wchar_t(const std::wstring &wstr) -{ - const size_t len = wstr.length(); - std::unique_ptr<wchar_t[]> ret(new wchar_t[len + 1]); - size_t i; - for (i = 0; i < len; ++i) - ret[i] = wstr[i]; - ret[i] = L'\0'; - return ret; -} - /** * @brief Convert a UTF-8 string vector to a UTF-16 MULTI_SZ string * diff --git a/openvpn/common/xmlhelper.hpp b/openvpn/common/xmlhelper.hpp index b0978e037..d86c84fe2 100644 --- a/openvpn/common/xmlhelper.hpp +++ b/openvpn/common/xmlhelper.hpp @@ -41,33 +41,13 @@ class Xml static std::string format_error(const tinyxml2::XMLDocument &doc) { -#if OVPN_TINYXML2_HAS_ERROR_NAME std::string ret = doc.ErrorName(); -#else - tinyxml2::XMLError error = doc.ErrorID(); - std::string ret{"XMLError " + error}; -#endif -#if OVPN_TINYXML2_HAS_ERROR_STR const char *es = doc.ErrorStr(); if (es) { ret += ' '; ret += es; } -#else - const char *es1 = doc.GetErrorStr1(); - const char *es2 = doc.GetErrorStr2(); - if (es1) - { - ret += ' '; - ret += es1; - } - if (es2) - { - ret += ' '; - ret += es2; - } -#endif return ret; } diff --git a/openvpn/compress/compress.hpp b/openvpn/compress/compress.hpp index d5f981658..75b1ae3e9 100644 --- a/openvpn/compress/compress.hpp +++ b/openvpn/compress/compress.hpp @@ -27,7 +27,7 @@ namespace openvpn { //! Debugging level for message emitted from compression -#if !defined(OPENVPN_DEBUG_COMPRESS) +#ifndef OPENVPN_DEBUG_COMPRESS #define OPENVPN_DEBUG_COMPRESS 1 #endif @@ -35,7 +35,7 @@ class Compress : public RC<thread_unsafe_refcount>, public logging::LoggingMixin<OPENVPN_DEBUG_COMPRESS, logging::LOG_LEVEL_TRACE, Compress> { public: - typedef RCPtr<Compress> Ptr; + using Ptr = RCPtr<Compress>; // Compressor name virtual const char *name() const = 0; @@ -81,7 +81,7 @@ class Compress : public RC<thread_unsafe_refcount>, void do_swap(Buffer &buf, unsigned char op) { - if (buf.size()) + if (!buf.empty()) { buf.push_back(buf[0]); buf[0] = op; @@ -164,9 +164,7 @@ class CompressContext OPENVPN_SIMPLE_EXCEPTION(compressor_unavailable); - CompressContext() - { - } + CompressContext() = default; CompressContext(const Type t, const bool asym) : asym_(asym) // asym indicates asymmetrical compression where only downlink is compressed @@ -470,22 +468,21 @@ class CompressContext { if (method == "stub-v2") return COMP_STUBv2; - else if (method == "lz4-v2") + if (method == "lz4-v2") return LZ4v2; - else if (method == "lz4") + if (method == "lz4") return LZ4; - else if (method == "lzo") + if (method == "lzo") return LZO; - else if (method == "lzo-swap") + if (method == "lzo-swap") return LZO_SWAP; - else if (method == "lzo-stub") + if (method == "lzo-stub") return LZO_STUB; - else if (method == "snappy") + if (method == "snappy") return SNAPPY; - else if (method == "stub") + if (method == "stub") return COMP_STUB; - else - return NONE; + return NONE; } static Type stub(const Type t) diff --git a/openvpn/compress/compstub.hpp b/openvpn/compress/compstub.hpp index 884895f2d..5d674b943 100644 --- a/openvpn/compress/compstub.hpp +++ b/openvpn/compress/compstub.hpp @@ -47,7 +47,7 @@ class CompressStub : public Compress void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; // indicate that we didn't compress @@ -60,7 +60,7 @@ class CompressStub : public Compress void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const unsigned char c = buf.pop_front(); @@ -110,7 +110,7 @@ class CompressStubV2 : public Compress void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; // indicate that we didn't compress @@ -120,7 +120,7 @@ class CompressStubV2 : public Compress void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const int cop = v2_pull(buf); diff --git a/openvpn/compress/lz4.hpp b/openvpn/compress/lz4.hpp index e9ba41e0a..153a4d803 100644 --- a/openvpn/compress/lz4.hpp +++ b/openvpn/compress/lz4.hpp @@ -87,8 +87,7 @@ class CompressLZ4Base : public Compress buf.swap(work); return true; } - else - return false; + return false; } // Worst case size expansion on compress. @@ -100,8 +99,7 @@ class CompressLZ4Base : public Compress { if (likely(len < 65535)) return len + len / 256 + 17; - else - return len + len / 255 + 16; + return len + len / 255 + 16; } BufferAllocated work; @@ -131,7 +129,7 @@ class CompressLZ4 : public CompressLZ4Base void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; if (hint && !asym) @@ -150,7 +148,7 @@ class CompressLZ4 : public CompressLZ4Base void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const unsigned char c = buf.pop_front(); @@ -190,7 +188,7 @@ class CompressLZ4v2 : public CompressLZ4Base void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; if (hint && !asym) @@ -209,7 +207,7 @@ class CompressLZ4v2 : public CompressLZ4Base void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const int c = v2_pull(buf); diff --git a/openvpn/compress/lzo.hpp b/openvpn/compress/lzo.hpp index 78bccd9aa..b01cd1d8c 100644 --- a/openvpn/compress/lzo.hpp +++ b/openvpn/compress/lzo.hpp @@ -75,7 +75,7 @@ class CompressLZO : public Compress void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; if (hint && !asym) @@ -125,7 +125,7 @@ class CompressLZO : public Compress void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const unsigned char c = buf.pop_front(); diff --git a/openvpn/compress/lzoasym.hpp b/openvpn/compress/lzoasym.hpp index 8c0d03a65..a18de3e49 100644 --- a/openvpn/compress/lzoasym.hpp +++ b/openvpn/compress/lzoasym.hpp @@ -71,7 +71,7 @@ class CompressLZOAsym : public Compress void compress(BufferAllocated &buf, const bool hint) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; // indicate that we didn't compress @@ -84,7 +84,7 @@ class CompressLZOAsym : public Compress void decompress(BufferAllocated &buf) override { // skip null packets - if (!buf.size()) + if (buf.empty()) return; const unsigned char c = buf.pop_front(); diff --git a/openvpn/compress/lzoasym_impl.hpp b/openvpn/compress/lzoasym_impl.hpp index a5f8e903c..782729642 100644 --- a/openvpn/compress/lzoasym_impl.hpp +++ b/openvpn/compress/lzoasym_impl.hpp @@ -141,7 +141,7 @@ inline int lzo1x_decompress_safe(const unsigned char *input, unsigned char *output_ptr; const unsigned char *match_ptr; const unsigned char *const input_ptr_end = input + input_length; - unsigned char *const output_ptr_end = output + *output_length; + const unsigned char *const output_ptr_end = output + *output_length; *output_length = 0; diff --git a/openvpn/compress/lzoselect.hpp b/openvpn/compress/lzoselect.hpp index e936ba2f0..a38c49113 100644 --- a/openvpn/compress/lzoselect.hpp +++ b/openvpn/compress/lzoselect.hpp @@ -15,15 +15,15 @@ #ifndef OPENVPN_COMPRESS_LZOSELECT_H #define OPENVPN_COMPRESS_LZOSELECT_H -#if defined(HAVE_LZO) +#ifdef HAVE_LZO #include <openvpn/compress/lzo.hpp> #else #include <openvpn/compress/lzoasym.hpp> #endif namespace openvpn { -#if !defined(HAVE_LZO) -typedef CompressLZOAsym CompressLZO; +#ifndef HAVE_LZO +using CompressLZO = CompressLZOAsym; #endif } // namespace openvpn diff --git a/openvpn/crypto/crypto_aead.hpp b/openvpn/crypto/crypto_aead.hpp index 0d1eb697e..74bac32cc 100644 --- a/openvpn/crypto/crypto_aead.hpp +++ b/openvpn/crypto/crypto_aead.hpp @@ -171,7 +171,7 @@ class Crypto : public CryptoDCInstance }; public: - typedef CryptoDCInstance Base; + using Base = CryptoDCInstance; Crypto(SSLLib::Ctx libctx_arg, CryptoDCSettingsData dc_settings_data, @@ -190,10 +190,10 @@ class Crypto : public CryptoDCInstance bool encrypt(BufferAllocated &buf, const unsigned char *op32) override { // only process non-null packets - if (buf.size()) + if (!buf.empty()) { // build nonce/IV/AD - Nonce nonce(e.nonce, e.pid_send, op32); + const Nonce nonce(e.nonce, e.pid_send, op32); // encrypt to work buf frame->prepare(Frame::ENCRYPT_WORK, e.work); @@ -203,7 +203,7 @@ class Crypto : public CryptoDCInstance unsigned char *work_data = e.work.write_alloc(buf.size()); - unsigned char *auth_tag_tmp = nullptr; + const unsigned char *auth_tag_tmp = nullptr; // alloc auth tag in buffer at the start of the packet // Create a temporary auth tag at the end if the implementation and mode require it @@ -235,14 +235,14 @@ class Crypto : public CryptoDCInstance Error::Type decrypt(BufferAllocated &buf, const std::time_t now, const unsigned char *op32) override { // only process non-null packets - if (buf.size()) + if (!buf.empty()) { // get nonce/IV/AD Nonce nonce(d.nonce, d.pid_recv, buf, op32); // get auth tag if it is at the front. If the auth tag is at the end // the decrypt function will just treat it as part of the input - unsigned char *auth_tag = nullptr; + const unsigned char *auth_tag = nullptr; auth_tag = buf.read_alloc(CRYPTO_API::CipherContextAEAD::AUTH_TAG_LEN); @@ -356,7 +356,7 @@ template <typename CRYPTO_API> class CryptoContext : public CryptoDCContext { public: - typedef RCPtr<CryptoContext> Ptr; + using Ptr = RCPtr<CryptoContext>; CryptoContext(SSLLib::Ctx libctx_arg, CryptoDCSettingsData dc_settings_data, diff --git a/openvpn/crypto/crypto_aead_epoch.hpp b/openvpn/crypto/crypto_aead_epoch.hpp index 697f05303..cbd8522cc 100644 --- a/openvpn/crypto/crypto_aead_epoch.hpp +++ b/openvpn/crypto/crypto_aead_epoch.hpp @@ -66,7 +66,7 @@ class Crypto : public CryptoDCInstance auto &encrypt_ctx = dce.encrypt(); /* header of the packet. op32 (opcode + peer-id) + 8 byte of epoch + epoch counter */ - BufferAllocated pkt_header{4 + 8, 0}; + BufferAllocated pkt_header{4 + 8}; pkt_header.write(op32, 4); encrypt_ctx.pid.write_next(pkt_header); @@ -113,7 +113,7 @@ class Crypto : public CryptoDCInstance // Reconstruct header since we don't get the continuous memory that we received from wire but already // split into op32 and the rest of the packet. - BufferAllocated pkt_header{4 + 8, 0}; + BufferAllocated pkt_header{4 + 8}; pkt_header.write(op32, 4); auto *packet_id = pkt_header.write_alloc(8); buf.read(packet_id, 8); @@ -228,7 +228,7 @@ template <typename CRYPTO_API> class CryptoContext : public CryptoDCContext { public: - typedef RCPtr<CryptoContext> Ptr; + using Ptr = RCPtr<CryptoContext>; CryptoContext(SSLLib::Ctx libctx_arg, CryptoDCSettingsData dc_settings_data, diff --git a/openvpn/crypto/crypto_chm.hpp b/openvpn/crypto/crypto_chm.hpp index 0b510939f..0ea122b5e 100644 --- a/openvpn/crypto/crypto_chm.hpp +++ b/openvpn/crypto/crypto_chm.hpp @@ -26,7 +26,7 @@ template <typename CRYPTO_API> class CryptoCHM : public CryptoDCInstance { public: - typedef CryptoDCInstance Base; + using Base = CryptoDCInstance; CryptoCHM( SSLLib::Ctx libctx_arg, @@ -126,7 +126,7 @@ template <typename CRYPTO_API> class CryptoContextCHM : public CryptoDCContext { public: - typedef RCPtr<CryptoContextCHM> Ptr; + using Ptr = RCPtr<CryptoContextCHM>; CryptoContextCHM( SSLLib::Ctx libctx_arg, diff --git a/openvpn/crypto/cryptoalgs.hpp b/openvpn/crypto/cryptoalgs.hpp index 4bdf28145..963f75ef7 100644 --- a/openvpn/crypto/cryptoalgs.hpp +++ b/openvpn/crypto/cryptoalgs.hpp @@ -90,14 +90,13 @@ enum Mode MODE_UNDEF = 0, CBC_HMAC, AEAD, - MODE_MASK = 0x03, }; enum AlgFlags -{ // bits below must start after Mode bits - F_CIPHER = (1 << 2), // alg is a cipher - F_DIGEST = (1 << 3), // alg is a digest - F_ALLOW_DC = (1 << 4) // alg may be used in OpenVPN data channel +{ + F_CIPHER = (1 << 0), // alg is a cipher + F_DIGEST = (1 << 1), // alg is a digest + F_ALLOW_DC = (1 << 2) // alg may be used in OpenVPN data channel }; // size in bytes of AEAD "nonce tail" normally taken from @@ -112,6 +111,7 @@ class Alg public: constexpr Alg(const char *name, const unsigned int flags, + const Mode mode, const unsigned int size, const unsigned int iv_length, const unsigned int block_size, @@ -119,6 +119,7 @@ class Alg : name_(name), flags_(flags), + mode_(mode), size_(size), iv_length_(iv_length), block_size_(block_size), @@ -133,10 +134,10 @@ class Alg unsigned int flags() const { return flags_; - } // contains Mode and AlgFlags + } Mode mode() const { - return Mode(flags_ & MODE_MASK); + return mode_; } size_t size() const { @@ -181,6 +182,7 @@ class Alg private: const char *name_; unsigned int flags_; + Mode mode_; unsigned int size_; unsigned int iv_length_; unsigned int block_size_; @@ -188,29 +190,29 @@ class Alg }; /** The limit for AES-GCM ciphers according to https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/ */ -static constexpr uint64_t gcm_limit = (1ull << 36) - 1; +static constexpr uint64_t gcm_limit = (1ULL << 36) - 1; inline std::array<Alg, Type::SIZE> algs = { // clang-format off - Alg{"none", F_CIPHER|F_DIGEST|CBC_HMAC, 0, 0, 0, 0 }, - Alg{"AES-128-CBC", F_CIPHER|CBC_HMAC, 16, 16, 16, 0 }, - Alg{"AES-192-CBC", F_CIPHER|CBC_HMAC, 24, 16, 16, 0 }, - Alg{"AES-256-CBC", F_CIPHER|CBC_HMAC, 32, 16, 16, 0 }, - Alg{"DES-CBC", F_CIPHER|CBC_HMAC, 8, 8, 8, 0 }, - Alg{"DES-EDE3-CBC", F_CIPHER|CBC_HMAC, 24, 8, 8, 0 }, - Alg{"BF-CBC", F_CIPHER|CBC_HMAC, 16, 8, 8, 0 }, - Alg{"AES-256-CTR", F_CIPHER, 32, 16, 16, 0 }, - Alg{"AES-128-GCM", F_CIPHER|AEAD, 16, 12, 16, gcm_limit }, - Alg{"AES-192-GCM", F_CIPHER|AEAD, 24, 12, 16, gcm_limit }, - Alg{"AES-256-GCM", F_CIPHER|AEAD, 32, 12, 16, gcm_limit }, - Alg{"CHACHA20-POLY1305", F_CIPHER|AEAD, 32, 12, 16, 0 }, - Alg{"MD4", F_DIGEST, 16, 0, 0, 0 }, - Alg{"MD5", F_DIGEST, 16, 0, 0, 0 }, - Alg{"SHA1", F_DIGEST, 20, 0, 0, 0 }, - Alg{"SHA224", F_DIGEST, 28, 0, 0, 0 }, - Alg{"SHA256", F_DIGEST, 32, 0, 0, 0 }, - Alg{"SHA384", F_DIGEST, 48, 0, 0, 0 }, - Alg{"SHA512", F_DIGEST, 64, 0, 0, 0 } + Alg{"none", F_CIPHER|F_DIGEST, CBC_HMAC, 0, 0, 0, 0 }, + Alg{"AES-128-CBC", F_CIPHER, CBC_HMAC, 16, 16, 16, 0 }, + Alg{"AES-192-CBC", F_CIPHER, CBC_HMAC, 24, 16, 16, 0 }, + Alg{"AES-256-CBC", F_CIPHER, CBC_HMAC, 32, 16, 16, 0 }, + Alg{"DES-CBC", F_CIPHER, CBC_HMAC, 8, 8, 8, 0 }, + Alg{"DES-EDE3-CBC", F_CIPHER, CBC_HMAC, 24, 8, 8, 0 }, + Alg{"BF-CBC", F_CIPHER, CBC_HMAC, 16, 8, 8, 0 }, + Alg{"AES-256-CTR", F_CIPHER, MODE_UNDEF, 32, 16, 16, 0 }, + Alg{"AES-128-GCM", F_CIPHER, AEAD, 16, 12, 16, gcm_limit }, + Alg{"AES-192-GCM", F_CIPHER, AEAD, 24, 12, 16, gcm_limit }, + Alg{"AES-256-GCM", F_CIPHER, AEAD, 32, 12, 16, gcm_limit }, + Alg{"CHACHA20-POLY1305", F_CIPHER, AEAD, 32, 12, 16, 0 }, + Alg{"MD4", F_DIGEST, MODE_UNDEF, 16, 0, 0, 0 }, + Alg{"MD5", F_DIGEST, MODE_UNDEF, 16, 0, 0, 0 }, + Alg{"SHA1", F_DIGEST, MODE_UNDEF, 20, 0, 0, 0 }, + Alg{"SHA224", F_DIGEST, MODE_UNDEF, 28, 0, 0, 0 }, + Alg{"SHA256", F_DIGEST, MODE_UNDEF, 32, 0, 0, 0 }, + Alg{"SHA384", F_DIGEST, MODE_UNDEF, 48, 0, 0, 0 }, + Alg{"SHA512", F_DIGEST, MODE_UNDEF, 64, 0, 0, 0 } // clang-format on }; @@ -260,8 +262,7 @@ inline const char *name(const Type type, const char *default_name = nullptr) { if (type == NONE && default_name) return default_name; - else - return get(type).name(); + return get(type).name(); } inline size_t size(const Type type) @@ -319,7 +320,7 @@ inline Type legal_dc_digest(const Type type) inline Type dc_cbc_cipher(const Type type) { const Alg &alg = get(type); - if (!(alg.flags() & CBC_HMAC)) + if (!(alg.mode() == CBC_HMAC)) OPENVPN_THROW(crypto_alg, alg.name() << ": bad cipher for data channel use"); return type; } diff --git a/openvpn/crypto/cryptochoose.hpp b/openvpn/crypto/cryptochoose.hpp index be78f3ef9..928842dae 100644 --- a/openvpn/crypto/cryptochoose.hpp +++ b/openvpn/crypto/cryptochoose.hpp @@ -40,7 +40,7 @@ #endif namespace openvpn::SSLLib { -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS #define SSL_LIB_NAME "MbedTLS" using CryptoAPI = MbedTLSCryptoAPI; #if defined OPENVPN_PLATFORM_UWP diff --git a/openvpn/crypto/cryptodc.hpp b/openvpn/crypto/cryptodc.hpp index a387dfe72..0d680425a 100644 --- a/openvpn/crypto/cryptodc.hpp +++ b/openvpn/crypto/cryptodc.hpp @@ -33,7 +33,7 @@ namespace openvpn { class CryptoDCInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<CryptoDCInstance> Ptr; + using Ptr = RCPtr<CryptoDCInstance>; // Encrypt/Decrypt @@ -100,8 +100,6 @@ class CryptoDCSettingsData public: OPENVPN_SIMPLE_EXCEPTION(no_data_channel_factory); - CryptoDCSettingsData() = default; - void set_cipher(CryptoAlgs::Type cipher) { cipher_ = cipher; @@ -166,7 +164,7 @@ class CryptoDCContext : public RC<thread_unsafe_refcount> { } - typedef RCPtr<CryptoDCContext> Ptr; + using Ptr = RCPtr<CryptoDCContext>; virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) = 0; @@ -183,7 +181,7 @@ class CryptoDCContext : public RC<thread_unsafe_refcount> class CryptoDCFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<CryptoDCFactory> Ptr; + using Ptr = RCPtr<CryptoDCFactory>; virtual CryptoDCContext::Ptr new_obj(const CryptoDCSettingsData) = 0; }; @@ -195,8 +193,6 @@ class CryptoDCSettings : public CryptoDCSettingsData public: OPENVPN_SIMPLE_EXCEPTION(no_data_channel_factory); - CryptoDCSettings() = default; - void set_factory(const CryptoDCFactory::Ptr &factory) { factory_ = factory; diff --git a/openvpn/crypto/cryptodcsel.hpp b/openvpn/crypto/cryptodcsel.hpp index 373549127..d229b02e7 100644 --- a/openvpn/crypto/cryptodcsel.hpp +++ b/openvpn/crypto/cryptodcsel.hpp @@ -32,7 +32,7 @@ template <typename CRYPTO_API> class CryptoDCSelect : public CryptoDCFactory { public: - typedef RCPtr<CryptoDCSelect> Ptr; + using Ptr = RCPtr<CryptoDCSelect>; CryptoDCSelect(SSLLib::Ctx libctx_arg, const Frame::Ptr &frame_arg, @@ -48,14 +48,13 @@ class CryptoDCSelect : public CryptoDCFactory CryptoDCContext::Ptr new_obj(CryptoDCSettingsData dc_settings) override { const CryptoAlgs::Alg &alg = CryptoAlgs::get(dc_settings.cipher()); - if (alg.flags() & CryptoAlgs::CBC_HMAC) + if (alg.mode() == CryptoAlgs::CBC_HMAC) return new CryptoContextCHM<CRYPTO_API>(libctx, std::move(dc_settings), frame, stats, rng); - else if (alg.flags() & CryptoAlgs::AEAD && dc_settings.useEpochKeys()) + if (alg.mode() == CryptoAlgs::AEAD && dc_settings.useEpochKeys()) return new AEADEpoch::CryptoContext<CRYPTO_API>(libctx, std::move(dc_settings), frame, stats); - else if (alg.flags() & CryptoAlgs::AEAD) + if (alg.mode() == CryptoAlgs::AEAD) return new AEAD::CryptoContext<CRYPTO_API>(libctx, std::move(dc_settings), frame, stats); - else - OPENVPN_THROW(crypto_dc_select, alg.name() << ": only CBC/HMAC and AEAD cipher modes supported"); + OPENVPN_THROW(crypto_dc_select, alg.name() << ": only CBC/HMAC and AEAD cipher modes supported"); } private: diff --git a/openvpn/crypto/data_epoch.cpp b/openvpn/crypto/data_epoch.cpp index 35607cb76..2228ff639 100644 --- a/openvpn/crypto/data_epoch.cpp +++ b/openvpn/crypto/data_epoch.cpp @@ -75,7 +75,7 @@ void openvpn::ovpn_expand_label(const uint8_t *secret, size_t secret_len, const throw std::runtime_error("HKDF input parameters are too large"); } - openvpn::BufferAllocated hkdf_label{hkdf_label_len, 0}; + openvpn::BufferAllocated hkdf_label{hkdf_label_len}; const std::uint16_t net_out_len = htons(static_cast<std::uint16_t>(out_len)); hkdf_label.write((const unsigned char *)&net_out_len, sizeof(net_out_len)); @@ -173,7 +173,7 @@ void openvpn::DataChannelEpoch::generate_future_receive_keys() /* Either we have not generated any future keys yet or the last * index is the same as our current epoch key */ - if (future_keys.size() > 0 && future_keys.back().epoch != receive.epoch) + if (!future_keys.empty() && future_keys.back().epoch != receive.epoch) throw epoch_key_exception("Epoch key generation and future keys mismatch detected"); /* free the keys that are not used anymore */ @@ -289,12 +289,12 @@ openvpn::DataChannelEpoch::lookup_decrypt_key(uint16_t epoch) { return &decrypt_ctx; } - else if (retiring_decrypt_ctx.epoch > 0 && retiring_decrypt_ctx.epoch == epoch) + if (retiring_decrypt_ctx.epoch > 0 && retiring_decrypt_ctx.epoch == epoch) { return &retiring_decrypt_ctx; } - else if (epoch > decrypt_ctx.epoch - && epoch <= decrypt_ctx.epoch + future_keys_count) + if (epoch > decrypt_ctx.epoch + && epoch <= decrypt_ctx.epoch + future_keys_count) { /* If we have reached the edge of the valid keys we do not return * the key anymore since regenerating the new keys would move us @@ -304,17 +304,13 @@ openvpn::DataChannelEpoch::lookup_decrypt_key(uint16_t epoch) { return nullptr; } - else - { - /* Key in the range of future keys */ - int index = epoch - (decrypt_ctx.epoch + 1); - return &future_keys.at(index); - } - } - else - { - return nullptr; + + /* Key in the range of future keys */ + int index = epoch - (decrypt_ctx.epoch + 1); + return &future_keys.at(index); } + + return nullptr; } void openvpn::EpochDataChannelCryptoContext::calculate_iv(uint8_t *packet_id, std::array<uint8_t, IV_SIZE> &iv_dest) diff --git a/openvpn/crypto/decrypt_chm.hpp b/openvpn/crypto/decrypt_chm.hpp index 04eaa3085..cc80e97d5 100644 --- a/openvpn/crypto/decrypt_chm.hpp +++ b/openvpn/crypto/decrypt_chm.hpp @@ -38,7 +38,7 @@ class DecryptCHM Error::Type decrypt(BufferAllocated &buf, const std::time_t now) { // skip null packets - if (!buf.size()) + if (buf.empty()) return Error::SUCCESS; // verify the HMAC diff --git a/openvpn/crypto/digestapi.hpp b/openvpn/crypto/digestapi.hpp index 1559abf72..b49f06271 100644 --- a/openvpn/crypto/digestapi.hpp +++ b/openvpn/crypto/digestapi.hpp @@ -24,7 +24,7 @@ namespace openvpn { class DigestInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<DigestInstance> Ptr; + using Ptr = RCPtr<DigestInstance>; virtual void update(const unsigned char *in, const size_t size) = 0; virtual size_t final(unsigned char *out) = 0; @@ -34,7 +34,7 @@ class DigestInstance : public RC<thread_unsafe_refcount> class HMACInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<HMACInstance> Ptr; + using Ptr = RCPtr<HMACInstance>; virtual void reset() = 0; virtual void update(const unsigned char *in, const size_t size) = 0; @@ -45,7 +45,7 @@ class HMACInstance : public RC<thread_unsafe_refcount> class DigestFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<DigestFactory> Ptr; + using Ptr = RCPtr<DigestFactory>; virtual DigestInstance::Ptr new_digest(const CryptoAlgs::Type digest_type) = 0; diff --git a/openvpn/crypto/encrypt_chm.hpp b/openvpn/crypto/encrypt_chm.hpp index 2e25dce11..ea2d6d5f1 100644 --- a/openvpn/crypto/encrypt_chm.hpp +++ b/openvpn/crypto/encrypt_chm.hpp @@ -37,7 +37,7 @@ class EncryptCHM void encrypt(BufferAllocated &buf) { // skip null packets - if (!buf.size()) + if (buf.empty()) return; if (cipher.defined()) diff --git a/openvpn/crypto/hashstr.hpp b/openvpn/crypto/hashstr.hpp index b26aacd88..60c0910eb 100644 --- a/openvpn/crypto/hashstr.hpp +++ b/openvpn/crypto/hashstr.hpp @@ -67,13 +67,13 @@ class HashString std::string final_hex() { - BufferPtr bp = final(); + const BufferPtr bp = final(); return render_hex_generic(*bp); } std::string final_base64() { - BufferPtr bp = final(); + const BufferPtr bp = final(); return base64->encode(*bp); } diff --git a/openvpn/crypto/ovpnhmac.hpp b/openvpn/crypto/ovpnhmac.hpp index d568973e1..d5f970bb6 100644 --- a/openvpn/crypto/ovpnhmac.hpp +++ b/openvpn/crypto/ovpnhmac.hpp @@ -35,9 +35,7 @@ class OvpnHMAC OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_bad_sizing); public: - OvpnHMAC() - { - } + OvpnHMAC() = default; OvpnHMAC(const CryptoAlgs::Type digest, const StaticKey &key) { @@ -104,8 +102,7 @@ class OvpnHMAC ctx.final(local_hmac); return !crypto::memneq(data + l1, local_hmac, l2); } - else - return false; + return false; } private: @@ -139,7 +136,7 @@ class OvpnHMAC class OvpnHMACInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<OvpnHMACInstance> Ptr; + using Ptr = RCPtr<OvpnHMACInstance>; virtual void init(const StaticKey &key) = 0; @@ -161,7 +158,7 @@ class OvpnHMACInstance : public RC<thread_unsafe_refcount> class OvpnHMACContext : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<OvpnHMACContext> Ptr; + using Ptr = RCPtr<OvpnHMACContext>; virtual size_t size() const = 0; @@ -171,7 +168,7 @@ class OvpnHMACContext : public RC<thread_unsafe_refcount> class OvpnHMACFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<OvpnHMACFactory> Ptr; + using Ptr = RCPtr<OvpnHMACFactory>; virtual OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type) = 0; }; diff --git a/openvpn/crypto/packet_id_control.hpp b/openvpn/crypto/packet_id_control.hpp index 02fe74233..971c95cad 100644 --- a/openvpn/crypto/packet_id_control.hpp +++ b/openvpn/crypto/packet_id_control.hpp @@ -46,9 +46,9 @@ namespace openvpn { */ struct PacketIDControl { - typedef std::uint32_t id_t; - typedef std::uint32_t net_time_t; - typedef Time::base_type time_t; + using id_t = std::uint32_t; + using net_time_t = std::uint32_t; + using time_t = Time::base_type; id_t id; // legal values are 1 through 2^32-1 time_t time; // converted to PacketID::net_time_t before transmission @@ -155,10 +155,7 @@ class PacketIDControlSend std::string str() const { - std::string ret; - ret = pid_.str(); - ret += 'L'; - return ret; + return pid_.str() + 'L'; } private: @@ -183,11 +180,6 @@ class PacketIDControlReceiveType OPENVPN_SIMPLE_EXCEPTION(packet_id_not_initialized); - // TODO: [OVPN3-933] Consider RAII'ifying this code - PacketIDControlReceiveType() - { - } - void init(const char *name_arg, const int unit_arg, const SessionStats::Ptr &stats_arg) @@ -221,8 +213,7 @@ class PacketIDControlReceiveType stats->error(err); return false; } - else - return true; + return true; } Error::Type do_test_add(const PacketIDControl &pin, @@ -373,6 +364,6 @@ class PacketIDControlReceiveType // Our standard packet ID window with order=8 (window size=2048). // and recv expire=30 seconds. -typedef PacketIDControlReceiveType<8, 30> PacketIDControlReceive; +using PacketIDControlReceive = PacketIDControlReceiveType<8, 30>; } // namespace openvpn diff --git a/openvpn/crypto/packet_id_data.hpp b/openvpn/crypto/packet_id_data.hpp index 2f631ff5c..ef5b9603b 100644 --- a/openvpn/crypto/packet_id_data.hpp +++ b/openvpn/crypto/packet_id_data.hpp @@ -49,11 +49,11 @@ namespace openvpn { */ struct PacketIDData { - typedef std::uint64_t data_id_t; + using data_id_t = std::uint64_t; /* the part of the packet id that represents the PID, the first 16 bits * are used by the Epoch*/ - static constexpr inline data_id_t epoch_packet_id_mask = 0x0000ffffffffffffull; + static constexpr inline data_id_t epoch_packet_id_mask = 0x0000ffffffffffffULL; data_id_t id = 0; // legal values are 1 through 2^64-1 @@ -72,8 +72,7 @@ struct PacketIDData { if (wide) return long_id_size; - else - return short_id_size; + return short_id_size; } @@ -102,7 +101,7 @@ struct PacketIDData uint16_t get_epoch() { - return static_cast<uint16_t>((id & ~epoch_packet_id_mask) >> 48ull); + return static_cast<uint16_t>((id & ~epoch_packet_id_mask) >> 48ULL); } /** @@ -170,11 +169,11 @@ class PacketIDDataSend OPENVPN_SIMPLE_EXCEPTION(packet_id_wrap); /** the maximum allowed value for a epoch packet counter (48 bit) */ - static constexpr inline PacketIDData::data_id_t epoch_packet_id_max = 0x0000ffffffffffffull; + static constexpr inline PacketIDData::data_id_t epoch_packet_id_max = 0x0000ffffffffffffULL; explicit PacketIDDataSend(bool wide_arg, uint16_t epoch) - : pid_(wide_arg, static_cast<PacketIDData::data_id_t>(epoch) << 48ull) + : pid_(wide_arg, static_cast<PacketIDData::data_id_t>(epoch) << 48ULL) { } @@ -262,7 +261,7 @@ class PacketIDDataSend { return true; } - else if (unlikely((pid_.id & PacketIDData::epoch_packet_id_mask) == epoch_packet_id_max)) + if (unlikely((pid_.id & PacketIDData::epoch_packet_id_mask) == epoch_packet_id_max)) { return true; } @@ -286,7 +285,7 @@ template <unsigned int REPLAY_WINDOW_ORDER, class PacketIDDataReceiveType { public: - static constexpr unsigned int REPLAY_WINDOW_BYTES = 1u << REPLAY_WINDOW_ORDER; + static constexpr unsigned int REPLAY_WINDOW_BYTES = 1U << REPLAY_WINDOW_ORDER; static constexpr unsigned int REPLAY_WINDOW_SIZE = REPLAY_WINDOW_BYTES * 8; #if defined(__GNUC__) && (__GNUC__ < 11) @@ -366,8 +365,7 @@ class PacketIDDataReceiveType stats->error(err); return false; } - else - return true; + return true; } /** @@ -409,14 +407,14 @@ class PacketIDDataReceiveType if (delta < REPLAY_WINDOW_SIZE) { base = replay_index(-delta); - history[base / 8] |= static_cast<uint8_t>(1u << (base % 8)); + history[base / 8] |= static_cast<uint8_t>(1U << (base % 8)); extent += static_cast<std::size_t>(delta); if (extent > REPLAY_WINDOW_SIZE) extent = REPLAY_WINDOW_SIZE; for (unsigned i = 1; i < delta; ++i) { const auto newbase = replay_index(i); - history[newbase / 8] &= static_cast<uint8_t>(~(1u << (newbase % 8))); + history[newbase / 8] &= static_cast<uint8_t>(~(1U << (newbase % 8))); } } else @@ -438,7 +436,7 @@ class PacketIDDataReceiveType { const auto ri = replay_index(delta); std::uint8_t *p = &history[ri / 8]; - const std::uint8_t mask = static_cast<uint8_t>(1u << (ri % 8)); + const std::uint8_t mask = static_cast<uint8_t>(1U << (ri % 8)); if (*p & mask) return Error::PKTID_REPLAY; *p |= mask; @@ -495,6 +493,6 @@ class PacketIDDataReceiveType // Our standard packet ID window with order=8 (window size=2048). // and recv expire=30 seconds. -typedef PacketIDDataReceiveType<8, 30> PacketIDDataReceive; +using PacketIDDataReceive = PacketIDDataReceiveType<8, 30>; } // namespace openvpn diff --git a/openvpn/crypto/static_key.hpp b/openvpn/crypto/static_key.hpp index be5a85569..86f967055 100644 --- a/openvpn/crypto/static_key.hpp +++ b/openvpn/crypto/static_key.hpp @@ -30,12 +30,12 @@ namespace openvpn { class StaticKey { friend class OpenVPNStaticKey; - typedef BufferAllocated key_t; + using key_t = BufferAllocated; public: - StaticKey() - { - } + //! Default do-nothing constructor. + StaticKey() = default; + StaticKey(const unsigned char *key_data, const size_t key_size) : key_data_(key_data, key_size, BufAllocFlags::DESTRUCT_ZERO) { @@ -44,7 +44,7 @@ class StaticKey StaticKey(const key_t &keydata) : key_data_(keydata) { - key_data_.or_flags(BufAllocFlags::DESTRUCT_ZERO); + key_data_.add_flags(BufAllocFlags::DESTRUCT_ZERO); } size_t size() const @@ -89,7 +89,7 @@ class StaticKey class OpenVPNStaticKey { - typedef StaticKey::key_t key_t; + using key_t = StaticKey::key_t; public: enum diff --git a/openvpn/crypto/tls_crypt.hpp b/openvpn/crypto/tls_crypt.hpp index 2feab5c31..0db9666d7 100644 --- a/openvpn/crypto/tls_crypt.hpp +++ b/openvpn/crypto/tls_crypt.hpp @@ -146,7 +146,7 @@ class TLSCrypt class TLSCryptInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSCryptInstance> Ptr; + using Ptr = RCPtr<TLSCryptInstance>; virtual void init(SSLLib::Ctx libctx, const StaticKey &key_hmac, const StaticKey &key_crypt) = 0; @@ -164,7 +164,7 @@ class TLSCryptInstance : public RC<thread_unsafe_refcount> class TLSCryptContext : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSCryptContext> Ptr; + using Ptr = RCPtr<TLSCryptContext>; virtual size_t digest_size() const = 0; @@ -188,7 +188,7 @@ class TLSCryptContext : public RC<thread_unsafe_refcount> class TLSCryptFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSCryptFactory> Ptr; + using Ptr = RCPtr<TLSCryptFactory>; virtual TLSCryptContext::Ptr new_obj(SSLLib::Ctx libctx, const CryptoAlgs::Type digest_type, const CryptoAlgs::Type cipher_type) = 0; }; diff --git a/openvpn/crypto/tls_crypt_v2.hpp b/openvpn/crypto/tls_crypt_v2.hpp index 5833fba39..4a97eff40 100644 --- a/openvpn/crypto/tls_crypt_v2.hpp +++ b/openvpn/crypto/tls_crypt_v2.hpp @@ -70,7 +70,7 @@ class TLSCryptV2ServerKey std::string render() const { - BufferAllocated data(32 + 2 * key.size(), 0); + BufferAllocated data(32 + 2 * key.size()); if (!SSLLib::PEMAPI::pem_encode(data, key.c_data(), key.size(), tls_crypt_v2_server_key_name)) throw tls_crypt_v2_server_key_encode_error(); @@ -130,7 +130,7 @@ class TLSCryptV2ClientKey std::string render() const { - BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0); + BufferAllocated data(32 + 2 * (key.size() + wkc.size())); BufferAllocated in(key, BufAllocFlags::GROW); in.append(wkc); @@ -160,7 +160,7 @@ class TLSCryptV2ClientKey class TLSCryptMetadata : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSCryptMetadata> Ptr; + using Ptr = RCPtr<TLSCryptMetadata>; // override this method with your own verification mechanism. // @@ -176,7 +176,7 @@ class TLSCryptMetadata : public RC<thread_unsafe_refcount> class TLSCryptMetadataFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSCryptMetadataFactory> Ptr; + using Ptr = RCPtr<TLSCryptMetadataFactory>; virtual TLSCryptMetadata::Ptr new_obj() = 0; }; diff --git a/openvpn/dco/dcocli.hpp b/openvpn/dco/dcocli.hpp index 8a16c2b38..f279fc778 100644 --- a/openvpn/dco/dcocli.hpp +++ b/openvpn/dco/dcocli.hpp @@ -26,10 +26,6 @@ #include <openvpn/tun/builder/capture.hpp> #include <openvpn/tun/client/tunbase.hpp> -#if !defined(ENABLE_OVPNDCOWIN) -#include <openvpn/tun/linux/client/tunmethods.hpp> -#endif - #if defined(ENABLE_KOVPN) #include <openvpn/kovpn/kodevtun.hpp> #include <openvpn/kovpn/kostats.hpp> diff --git a/openvpn/dco/kocrypto.hpp b/openvpn/dco/kocrypto.hpp index c40b7c580..ec178ff34 100644 --- a/openvpn/dco/kocrypto.hpp +++ b/openvpn/dco/kocrypto.hpp @@ -29,9 +29,7 @@ OPENVPN_EXCEPTION(korekey_error); struct Info { - Info() - { - } + Info() = default; Info(const CryptoDCContext::Ptr &dc_context_delegate_arg, const unsigned int key_id_arg, @@ -100,9 +98,7 @@ class Key } } - Key() - { - } + Key() = default; protected: const unsigned char *verify_key(const char *title, const StaticKey &sk, const size_t size_required) diff --git a/openvpn/dco/ovpn_dco_linux.h b/openvpn/dco/ovpn_dco_linux.h index 5b7fe8d8c..680d1522d 100644 --- a/openvpn/dco/ovpn_dco_linux.h +++ b/openvpn/dco/ovpn_dco_linux.h @@ -1,244 +1,109 @@ -/* SPDX-License-Identifier: (GPL-2.0-only WITH Linux-syscall-note) OR MIT */ -/* - * OpenVPN data channel accelerator - * - * Copyright (C) 2019-2023 OpenVPN, Inc. - * - * Author: James Yonan <james@openvpn.net> - * Antonio Quartulli <antonio@openvpn.net> - */ - -#ifndef _UAPI_LINUX_OVPN_DCO_H_ -#define _UAPI_LINUX_OVPN_DCO_H_ - -#define OVPN_NL_NAME "ovpn-dco-v2" - -#define OVPN_NL_MULTICAST_GROUP_PEERS "peers" - -/// \cond KNOWN_WARNINGS -/// error: Found unknown command '@OVPN_CIPHER_ALG_NONE' -/** - * enum ovpn_nl_commands - supported netlink commands - */ -enum ovpn_nl_commands { - /** - * @OVPN_CMD_UNSPEC: unspecified command to catch errors - */ - OVPN_CMD_UNSPEC = 0, - - /** - * @OVPN_CMD_NEW_PEER: Configure peer with its crypto keys - */ - OVPN_CMD_NEW_PEER, - - /** - * @OVPN_CMD_SET_PEER: Tweak parameters for an existing peer - */ - OVPN_CMD_SET_PEER, - - /** - * @OVPN_CMD_DEL_PEER: Remove peer from internal table - */ - OVPN_CMD_DEL_PEER, - - OVPN_CMD_NEW_KEY, - - OVPN_CMD_SWAP_KEYS, - - OVPN_CMD_DEL_KEY, - - /** - * @OVPN_CMD_GET_PEER: Retrieve the status of a peer or all peers - */ - OVPN_CMD_GET_PEER, -}; +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/ovpn.yaml */ +/* YNL-GEN uapi header */ + +#ifndef _UAPI_LINUX_OVPN_H +#define _UAPI_LINUX_OVPN_H + +#define OVPN_FAMILY_NAME "ovpn" +#define OVPN_FAMILY_VERSION 1 + +#define OVPN_NONCE_TAIL_SIZE 8 enum ovpn_cipher_alg { - /** - * @OVPN_CIPHER_ALG_NONE: No encryption - reserved for debugging only - */ - OVPN_CIPHER_ALG_NONE = 0, - /** - * @OVPN_CIPHER_ALG_AES_GCM: AES-GCM AEAD cipher with any allowed key size - */ + OVPN_CIPHER_ALG_NONE, OVPN_CIPHER_ALG_AES_GCM, - /** - * @OVPN_CIPHER_ALG_CHACHA20_POLY1305: ChaCha20Poly1305 AEAD cipher - */ OVPN_CIPHER_ALG_CHACHA20_POLY1305, }; enum ovpn_del_peer_reason { - __OVPN_DEL_PEER_REASON_FIRST, - OVPN_DEL_PEER_REASON_TEARDOWN = __OVPN_DEL_PEER_REASON_FIRST, + OVPN_DEL_PEER_REASON_TEARDOWN, OVPN_DEL_PEER_REASON_USERSPACE, OVPN_DEL_PEER_REASON_EXPIRED, OVPN_DEL_PEER_REASON_TRANSPORT_ERROR, OVPN_DEL_PEER_REASON_TRANSPORT_DISCONNECT, - __OVPN_DEL_PEER_REASON_AFTER_LAST }; enum ovpn_key_slot { - __OVPN_KEY_SLOT_FIRST, - OVPN_KEY_SLOT_PRIMARY = __OVPN_KEY_SLOT_FIRST, + OVPN_KEY_SLOT_PRIMARY, OVPN_KEY_SLOT_SECONDARY, - __OVPN_KEY_SLOT_AFTER_LAST, -}; - -enum ovpn_netlink_attrs { - OVPN_ATTR_UNSPEC = 0, - OVPN_ATTR_IFINDEX, - OVPN_ATTR_NEW_PEER, - OVPN_ATTR_SET_PEER, - OVPN_ATTR_DEL_PEER, - OVPN_ATTR_NEW_KEY, - OVPN_ATTR_SWAP_KEYS, - OVPN_ATTR_DEL_KEY, - OVPN_ATTR_GET_PEER, - - __OVPN_ATTR_AFTER_LAST, - OVPN_ATTR_MAX = __OVPN_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_key_dir_attrs { - OVPN_KEY_DIR_ATTR_UNSPEC = 0, - OVPN_KEY_DIR_ATTR_CIPHER_KEY, - OVPN_KEY_DIR_ATTR_NONCE_TAIL, - - __OVPN_KEY_DIR_ATTR_AFTER_LAST, - OVPN_KEY_DIR_ATTR_MAX = __OVPN_KEY_DIR_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_new_key_attrs { - OVPN_NEW_KEY_ATTR_UNSPEC = 0, - OVPN_NEW_KEY_ATTR_PEER_ID, - OVPN_NEW_KEY_ATTR_KEY_SLOT, - OVPN_NEW_KEY_ATTR_KEY_ID, - OVPN_NEW_KEY_ATTR_CIPHER_ALG, - OVPN_NEW_KEY_ATTR_ENCRYPT_KEY, - OVPN_NEW_KEY_ATTR_DECRYPT_KEY, - - __OVPN_NEW_KEY_ATTR_AFTER_LAST, - OVPN_NEW_KEY_ATTR_MAX = __OVPN_NEW_KEY_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_del_key_attrs { - OVPN_DEL_KEY_ATTR_UNSPEC = 0, - OVPN_DEL_KEY_ATTR_PEER_ID, - OVPN_DEL_KEY_ATTR_KEY_SLOT, - - __OVPN_DEL_KEY_ATTR_AFTER_LAST, - OVPN_DEL_KEY_ATTR_MAX = __OVPN_DEL_KEY_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_swap_keys_attrs { - OVPN_SWAP_KEYS_ATTR_UNSPEC = 0, - OVPN_SWAP_KEYS_ATTR_PEER_ID, - - __OVPN_SWAP_KEYS_ATTR_AFTER_LAST, - OVPN_SWAP_KEYS_ATTR_MAX = __OVPN_SWAP_KEYS_ATTR_AFTER_LAST - 1, - -}; - -enum ovpn_netlink_new_peer_attrs { - OVPN_NEW_PEER_ATTR_UNSPEC = 0, - OVPN_NEW_PEER_ATTR_PEER_ID, - OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE, - OVPN_NEW_PEER_ATTR_SOCKET, - OVPN_NEW_PEER_ATTR_IPV4, - OVPN_NEW_PEER_ATTR_IPV6, - OVPN_NEW_PEER_ATTR_LOCAL_IP, - - __OVPN_NEW_PEER_ATTR_AFTER_LAST, - OVPN_NEW_PEER_ATTR_MAX = __OVPN_NEW_PEER_ATTR_AFTER_LAST - 1, }; -enum ovpn_netlink_set_peer_attrs { - OVPN_SET_PEER_ATTR_UNSPEC = 0, - OVPN_SET_PEER_ATTR_PEER_ID, - OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL, - OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT, - - __OVPN_SET_PEER_ATTR_AFTER_LAST, - OVPN_SET_PEER_ATTR_MAX = __OVPN_SET_PEER_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_del_peer_attrs { - OVPN_DEL_PEER_ATTR_UNSPEC = 0, - OVPN_DEL_PEER_ATTR_REASON, - OVPN_DEL_PEER_ATTR_PEER_ID, - - __OVPN_DEL_PEER_ATTR_AFTER_LAST, - OVPN_DEL_PEER_ATTR_MAX = __OVPN_DEL_PEER_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_get_peer_attrs { - OVPN_GET_PEER_ATTR_UNSPEC = 0, - OVPN_GET_PEER_ATTR_PEER_ID, - - __OVPN_GET_PEER_ATTR_AFTER_LAST, - OVPN_GET_PEER_ATTR_MAX = __OVPN_GET_PEER_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_get_peer_response_attrs { - OVPN_GET_PEER_RESP_ATTR_UNSPEC = 0, - OVPN_GET_PEER_RESP_ATTR_PEER_ID, - OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE, - OVPN_GET_PEER_RESP_ATTR_IPV4, - OVPN_GET_PEER_RESP_ATTR_IPV6, - OVPN_GET_PEER_RESP_ATTR_LOCAL_IP, - OVPN_GET_PEER_RESP_ATTR_LOCAL_PORT, - OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_INTERVAL, - OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_TIMEOUT, - OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES, - OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES, - OVPN_GET_PEER_RESP_ATTR_VPN_RX_PACKETS, - OVPN_GET_PEER_RESP_ATTR_VPN_TX_PACKETS, - OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES, - OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES, - OVPN_GET_PEER_RESP_ATTR_LINK_RX_PACKETS, - OVPN_GET_PEER_RESP_ATTR_LINK_TX_PACKETS, - - __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST, - OVPN_GET_PEER_RESP_ATTR_MAX = __OVPN_GET_PEER_RESP_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_peer_stats_attrs { - OVPN_PEER_STATS_ATTR_UNSPEC = 0, - OVPN_PEER_STATS_BYTES, - OVPN_PEER_STATS_PACKETS, - - __OVPN_PEER_STATS_ATTR_AFTER_LAST, - OVPN_PEER_STATS_ATTR_MAX = __OVPN_PEER_STATS_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_peer_attrs { - OVPN_PEER_ATTR_UNSPEC = 0, - OVPN_PEER_ATTR_PEER_ID, - OVPN_PEER_ATTR_SOCKADDR_REMOTE, - OVPN_PEER_ATTR_IPV4, - OVPN_PEER_ATTR_IPV6, - OVPN_PEER_ATTR_LOCAL_IP, - OVPN_PEER_ATTR_KEEPALIVE_INTERVAL, - OVPN_PEER_ATTR_KEEPALIVE_TIMEOUT, - OVPN_PEER_ATTR_ENCRYPT_KEY, - OVPN_PEER_ATTR_DECRYPT_KEY, - OVPN_PEER_ATTR_RX_STATS, - OVPN_PEER_ATTR_TX_STATS, - - __OVPN_PEER_ATTR_AFTER_LAST, - OVPN_PEER_ATTR_MAX = __OVPN_PEER_ATTR_AFTER_LAST - 1, -}; - -enum ovpn_netlink_packet_attrs { - OVPN_PACKET_ATTR_UNSPEC = 0, - OVPN_PACKET_ATTR_PACKET, - OVPN_PACKET_ATTR_PEER_ID, - - __OVPN_PACKET_ATTR_AFTER_LAST, - OVPN_PACKET_ATTR_MAX = __OVPN_PACKET_ATTR_AFTER_LAST - 1, -}; - -/// \endcond - -#endif /* _UAPI_LINUX_OVPN_DCO_H_ */ +enum { + OVPN_A_PEER_ID = 1, + OVPN_A_PEER_REMOTE_IPV4, + OVPN_A_PEER_REMOTE_IPV6, + OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, + OVPN_A_PEER_REMOTE_PORT, + OVPN_A_PEER_SOCKET, + OVPN_A_PEER_SOCKET_NETNSID, + OVPN_A_PEER_VPN_IPV4, + OVPN_A_PEER_VPN_IPV6, + OVPN_A_PEER_LOCAL_IPV4, + OVPN_A_PEER_LOCAL_IPV6, + OVPN_A_PEER_LOCAL_PORT, + OVPN_A_PEER_KEEPALIVE_INTERVAL, + OVPN_A_PEER_KEEPALIVE_TIMEOUT, + OVPN_A_PEER_DEL_REASON, + OVPN_A_PEER_VPN_RX_BYTES, + OVPN_A_PEER_VPN_TX_BYTES, + OVPN_A_PEER_VPN_RX_PACKETS, + OVPN_A_PEER_VPN_TX_PACKETS, + OVPN_A_PEER_LINK_RX_BYTES, + OVPN_A_PEER_LINK_TX_BYTES, + OVPN_A_PEER_LINK_RX_PACKETS, + OVPN_A_PEER_LINK_TX_PACKETS, + + __OVPN_A_PEER_MAX, + OVPN_A_PEER_MAX = (__OVPN_A_PEER_MAX - 1) +}; + +enum { + OVPN_A_KEYCONF_PEER_ID = 1, + OVPN_A_KEYCONF_SLOT, + OVPN_A_KEYCONF_KEY_ID, + OVPN_A_KEYCONF_CIPHER_ALG, + OVPN_A_KEYCONF_ENCRYPT_DIR, + OVPN_A_KEYCONF_DECRYPT_DIR, + + __OVPN_A_KEYCONF_MAX, + OVPN_A_KEYCONF_MAX = (__OVPN_A_KEYCONF_MAX - 1) +}; + +enum { + OVPN_A_KEYDIR_CIPHER_KEY = 1, + OVPN_A_KEYDIR_NONCE_TAIL, + + __OVPN_A_KEYDIR_MAX, + OVPN_A_KEYDIR_MAX = (__OVPN_A_KEYDIR_MAX - 1) +}; + +enum { + OVPN_A_IFINDEX = 1, + OVPN_A_PEER, + OVPN_A_KEYCONF, + + __OVPN_A_MAX, + OVPN_A_MAX = (__OVPN_A_MAX - 1) +}; + +enum { + OVPN_CMD_PEER_NEW = 1, + OVPN_CMD_PEER_SET, + OVPN_CMD_PEER_GET, + OVPN_CMD_PEER_DEL, + OVPN_CMD_PEER_DEL_NTF, + OVPN_CMD_KEY_NEW, + OVPN_CMD_KEY_GET, + OVPN_CMD_KEY_SWAP, + OVPN_CMD_KEY_SWAP_NTF, + OVPN_CMD_KEY_DEL, + + __OVPN_CMD_MAX, + OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) +}; + +#define OVPN_MCGRP_PEERS "peers" + +#endif /* _UAPI_LINUX_OVPN_H */ diff --git a/openvpn/dco/ovpndcocli.hpp b/openvpn/dco/ovpndcocli.hpp index f5027f409..7f176a56a 100644 --- a/openvpn/dco/ovpndcocli.hpp +++ b/openvpn/dco/ovpndcocli.hpp @@ -14,6 +14,7 @@ // tun/transport client for ovpn-dco #include <openvpn/dco/dcocli.hpp> +#include <openvpn/tun/linux/client/tunnetlink.hpp> #include <openvpn/tun/client/tunconfigflags.hpp> class OvpnDcoClient : public Client, @@ -76,17 +77,17 @@ class OvpnDcoClient : public Client, dc_settings.set_factory(CryptoDCFactory::Ptr(new KoRekey::Factory( dc_settings.factory(), this, config->transport.frame))); - // add peer in ovpn-dco - add_peer(peer_id, - state->vpn_ip4_gw.to_ipv4_zero(), - state->vpn_ip6_gw.to_ipv6_zero()); + // add peer in ovpn-dco: in client mode we do not specify + // any peer VPN IP, because all traffic will go over the + // tunnel + add_peer(peer_id, IPv4::Addr(), IPv6::Addr()); // signal that we are connected tun_parent->tun_connected(); } std::string tun_name() const override { - return "ovpn-dco"; + return OVPN_FAMILY_NAME; } IP::Addr server_endpoint_addr() const override @@ -150,6 +151,7 @@ class OvpnDcoClient : public Client, OPENVPN_THROW(dcocli_error, "Non-const send expected for data channel only, but " "ovpndcocli is not expected to handle data packets"); + return true; } void get_remote_sockaddr(struct sockaddr_storage &sa, socklen_t &salen) @@ -174,6 +176,8 @@ class OvpnDcoClient : public Client, void del_peer(uint32_t peer_id) { + OPENVPN_LOG("Deleting DCO peer " << peer_id); + TunBuilderBase *tb = config->builder; if (tb) { @@ -191,6 +195,10 @@ class OvpnDcoClient : public Client, get_remote_sockaddr(sa, salen); + OPENVPN_LOG("Adding DCO peer " << peer_id << " remote " + << transport->server_endpoint_addr() << ":" + << transport->server_endpoint_port()); + TunBuilderBase *tb = config->builder; if (tb) { @@ -215,6 +223,8 @@ class OvpnDcoClient : public Client, { const SessionStats::DCOTransportSource::Data old_stats = last_stats; + OPENVPN_LOG("Updating stats for DCO peer " << peer_id); + if (peer_id == OVPN_PEER_ID_UNDEF) return; @@ -297,29 +307,31 @@ class OvpnDcoClient : public Client, switch (rktype) { case CryptoDCInstance::ACTIVATE_PRIMARY: + OPENVPN_LOG("Installing PRIMARY key for peer " << peer_id); genl->new_key(OVPN_KEY_SLOT_PRIMARY, kc); handle_keepalive(); break; case CryptoDCInstance::NEW_SECONDARY: - + OPENVPN_LOG("Installing SECONDARY key for peer " << peer_id); genl->new_key(OVPN_KEY_SLOT_SECONDARY, kc); break; case CryptoDCInstance::PRIMARY_SECONDARY_SWAP: - + OPENVPN_LOG("Swapping keys for peer " << peer_id); genl->swap_keys(peer_id); break; case CryptoDCInstance::DEACTIVATE_SECONDARY: - + OPENVPN_LOG("Deleting SECONDARY key for peer " << peer_id); genl->del_key(peer_id, OVPN_KEY_SLOT_SECONDARY); break; case CryptoDCInstance::DEACTIVATE_ALL: - // TODO: deactivate all keys - OPENVPN_LOG("ovpndcocli: deactivate all keys"); + OPENVPN_LOG("Deleting all keys for peer " << peer_id); + genl->del_key(peer_id, OVPN_KEY_SLOT_PRIMARY); + genl->del_key(peer_id, OVPN_KEY_SLOT_SECONDARY); break; default: @@ -382,7 +394,7 @@ class OvpnDcoClient : public Client, switch (cmd) { - case OVPN_CMD_DEL_PEER: + case OVPN_CMD_PEER_DEL_NTF: { uint32_t peer_id; buf.read(&peer_id, sizeof(peer_id)); @@ -427,7 +439,7 @@ class OvpnDcoClient : public Client, break; } - case OVPN_CMD_GET_PEER: + case OVPN_CMD_PEER_GET: { struct OvpnDcoPeer peer; buf.read(&peer, sizeof(peer)); @@ -557,7 +569,7 @@ class OvpnDcoClient : public Client, OPENVPN_LOG("DCO: attempting to open iface " + n); std::ostringstream os; - res = TunNetlink::iface_new(os, n, "ovpn-dco"); + res = TunNetlink::iface_new(os, n, OVPN_FAMILY_NAME); if (res) { OPENVPN_LOG("DCO: couldn't open iface " + n + ": " << os.str()); @@ -570,7 +582,7 @@ class OvpnDcoClient : public Client, } // no successful creation. bail out - if (res) + if (res != 0) { stop_(); transport_parent->transport_error(Error::TUN_IFACE_CREATE, @@ -613,8 +625,8 @@ class OvpnDcoClient : public Client, false); if (po) - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); if (config->builder) { @@ -630,12 +642,12 @@ class OvpnDcoClient : public Client, std::vector<IP::Route> rtvec; - TUN_LINUX::tun_config(config->dev_name, - *po, - &rtvec, - *add_cmds, - *remove_cmds, - TunConfigFlags::ADD_BYPASS_ROUTES); + TunNetlink::TunMethods::tun_config(config->dev_name, + *po, + &rtvec, + *add_cmds, + *remove_cmds, + TunConfigFlags::ADD_BYPASS_ROUTES); // execute commands to bring up interface add_cmds->execute_log(); @@ -668,6 +680,8 @@ class OvpnDcoClient : public Client, } else { + OPENVPN_LOG("Setting DCO peer " << peer_id << " interval: " << keepalive_interval << " timeout: " << keepalive_timeout); + // enable keepalive in kernel genl->set_peer(peer_id, keepalive_interval, keepalive_timeout); } diff --git a/openvpn/dco/ovpndcowincli.hpp b/openvpn/dco/ovpndcowincli.hpp index d06860c9e..219394065 100644 --- a/openvpn/dco/ovpndcowincli.hpp +++ b/openvpn/dco/ovpndcowincli.hpp @@ -95,8 +95,8 @@ class OvpnDcoWinClient : public Client, opt, nullptr, false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); tun_setup_->establish(*po, Win::module_name(), NULL, os, NULL); OPENVPN_LOG_STRING(os.str()); @@ -105,8 +105,8 @@ class OvpnDcoWinClient : public Client, if (tun_persist->persist_tun_state(handle_(), {state, tun_setup_->get_adapter_state()}, is_tun_start)) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl - << tun_persist->options()); + OPENVPN_LOG("TunPersist: saving tun context:\n" + << tun_persist->options()); state->vpn_interface_index = tun_setup_->vpn_interface_index(); @@ -315,7 +315,7 @@ class OvpnDcoWinClient : public Client, void queue_read_() { - buf_.reset(0, 2048, 0); + buf_.reset(0, 2048, BufAllocFlags::NO_FLAGS); get_handle()->async_read_some( buf_.mutable_buffer_clamp(), @@ -569,7 +569,7 @@ class OvpnDcoWinClient : public Client, return nullptr; } - virtual SessionStats::DCOTransportSource::Data dco_transport_stats_delta() override + SessionStats::DCOTransportSource::Data dco_transport_stats_delta() override { if (halt) { diff --git a/openvpn/error/error.hpp b/openvpn/error/error.hpp index efb890cfc..6b0ea7fa3 100644 --- a/openvpn/error/error.hpp +++ b/openvpn/error/error.hpp @@ -18,7 +18,7 @@ namespace openvpn::Error { -enum Type +enum Type : size_t { SUCCESS = 0, // no error NETWORK_RECV_ERROR, // errors receiving on network socket @@ -205,8 +205,7 @@ inline const char *name(const size_t type) static_assert(N_ERRORS == array_size(names), "error names array inconsistency"); if (type < N_ERRORS) return names[type]; - else - return "UNKNOWN_ERROR_TYPE"; + return "UNKNOWN_ERROR_TYPE"; } } // namespace openvpn::Error diff --git a/openvpn/error/excode.hpp b/openvpn/error/excode.hpp index fdd59649e..949312b98 100644 --- a/openvpn/error/excode.hpp +++ b/openvpn/error/excode.hpp @@ -22,22 +22,14 @@ namespace openvpn { // Define an exception object that allows an Error::Type code to be thrown class ExceptionCode : public std::exception { - enum - { - FATAL_FLAG = 0x80000000 - }; - public: - ExceptionCode() - : code_(0) - { - } + ExceptionCode() = default; ExceptionCode(const Error::Type code) : code_(code) { } ExceptionCode(const Error::Type code, const bool fatal) - : code_(mkcode(code, fatal)) + : code_(code), fatal_(fatal) { } @@ -48,21 +40,22 @@ class ExceptionCode : public std::exception void set_code(const Error::Type code, const bool fatal) { - code_ = mkcode(code, fatal); + code_ = code; + fatal_ = fatal; } Error::Type code() const { - return Error::Type(code_ & ~FATAL_FLAG); + return code_; } bool fatal() const { - return (code_ & FATAL_FLAG) != 0; + return fatal_; } bool code_defined() const { - return code_ != 0; + return code_ != Error::SUCCESS; } //! Some errors may justify letting the underlying SSL library send out TLS alerts. @@ -74,15 +67,8 @@ class ExceptionCode : public std::exception virtual ~ExceptionCode() noexcept = default; private: - static unsigned int mkcode(const Error::Type code, const bool fatal) - { - unsigned int ret = code; - if (fatal) - ret |= FATAL_FLAG; - return ret; - } - - unsigned int code_; + Error::Type code_ = Error::SUCCESS; + bool fatal_ = false; }; class ErrorCode : public ExceptionCode diff --git a/openvpn/frame/frame.hpp b/openvpn/frame/frame.hpp index a45640a80..fa581bbe8 100644 --- a/openvpn/frame/frame.hpp +++ b/openvpn/frame/frame.hpp @@ -25,7 +25,7 @@ namespace openvpn { class Frame : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<Frame> Ptr; + using Ptr = RCPtr<Frame>; // Frame context types -- we maintain a Context object for each context type enum @@ -62,7 +62,7 @@ class Frame : public RC<thread_unsafe_refcount> headroom_ = 0; payload_ = 0; tailroom_ = 0; - buffer_flags_ = 0; + buffer_flags_ = BufAllocFlags::NO_FLAGS; align_adjust_ = 0; align_block_ = sizeof(std::size_t); adj_headroom_ = 0; @@ -72,9 +72,9 @@ class Frame : public RC<thread_unsafe_refcount> Context(const size_t headroom, const size_t payload, const size_t tailroom, - const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary - const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size - const unsigned int buffer_flags) // flags passed to BufferAllocatedRc constructor + const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary + const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size + const BufferFlags buffer_flags) // flags passed to BufferAllocatedRc constructor { headroom_ = headroom; payload_ = payload; @@ -106,7 +106,7 @@ class Frame : public RC<thread_unsafe_refcount> { return adj_capacity_; } - unsigned int buffer_flags() const + BufferFlags buffer_flags() const { return buffer_flags_; } @@ -172,8 +172,7 @@ class Frame : public RC<thread_unsafe_refcount> { if (payload() > buf.size()) return payload() - buf.size(); - else - return 0; + return 0; } // Used to set the capacity of a group of Context objects @@ -237,16 +236,14 @@ class Frame : public RC<thread_unsafe_refcount> size_t tailroom_; size_t align_adjust_; size_t align_block_; - unsigned int buffer_flags_; + BufferFlags buffer_flags_; // derived size_t adj_headroom_; size_t adj_capacity_; }; - Frame() - { - } + Frame() = default; explicit Frame(const Context &c) { diff --git a/openvpn/frame/frame_init.hpp b/openvpn/frame/frame_init.hpp index d75859558..7274dac62 100644 --- a/openvpn/frame/frame_init.hpp +++ b/openvpn/frame/frame_init.hpp @@ -26,10 +26,10 @@ inline Frame::Ptr frame_init(const bool align_adjust_3_1, const bool verbose) { const size_t payload = std::max(tun_mtu_max + 512, size_t(2048)); - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; + constexpr size_t headroom = 512; + constexpr size_t tailroom = 512; + constexpr size_t align_block = 16; + constexpr BufferFlags buffer_flags = BufAllocFlags::NO_FLAGS; Frame::Ptr frame(new Frame(Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags))); if (align_adjust_3_1) @@ -60,10 +60,10 @@ inline Frame::Ptr frame_init(const bool align_adjust_3_1, inline Frame::Context frame_init_context_simple(const size_t payload) { - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; + constexpr size_t headroom = 512; + constexpr size_t tailroom = 512; + constexpr size_t align_block = 16; + constexpr BufferFlags buffer_flags = BufAllocFlags::NO_FLAGS; return Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags); } diff --git a/openvpn/frame/memq_dgram.hpp b/openvpn/frame/memq_dgram.hpp index 0a8817b53..17f9ee1fa 100644 --- a/openvpn/frame/memq_dgram.hpp +++ b/openvpn/frame/memq_dgram.hpp @@ -26,9 +26,8 @@ class MemQDgram : public MemQBase public: OPENVPN_SIMPLE_EXCEPTION(frame_uninitialized); - MemQDgram() - { - } + MemQDgram() = default; + explicit MemQDgram(const Frame::Ptr &frame) : frame_(frame) { diff --git a/openvpn/frame/memq_stream.hpp b/openvpn/frame/memq_stream.hpp index d5f3aed6f..160e62d41 100644 --- a/openvpn/frame/memq_stream.hpp +++ b/openvpn/frame/memq_stream.hpp @@ -29,9 +29,8 @@ class MemQStream : public MemQBase public: OPENVPN_SIMPLE_EXCEPTION(frame_uninitialized); - MemQStream() - { - } + MemQStream() = default; + explicit MemQStream(const Frame::Ptr &frame) : frame_(frame) { @@ -57,7 +56,7 @@ class MemQStream : public MemQBase // Any residual space remaining in most recently pushed buffer? if (!q.empty()) { - BufferPtr &qb = q.back(); + const BufferPtr &qb = q.back(); const size_t write_size = std::min(b.size(), fc.remaining_payload(*qb)); const unsigned char *from = b.read_alloc(write_size); qb->write(from, write_size); @@ -65,7 +64,7 @@ class MemQStream : public MemQBase } // Start a new buffer - while (b.size()) + while (!b.empty()) { auto newbuf = BufferAllocatedRc::Create(); fc.prepare(*newbuf); @@ -89,7 +88,7 @@ class MemQStream : public MemQBase const size_t remaining = b.remaining(); if (!remaining) break; - BufferPtr &qf = q.front(); + const BufferPtr &qf = q.front(); const size_t read_size = std::min(remaining, qf->size()); unsigned char *to = b.write_alloc(read_size); qf->read(to, read_size); diff --git a/openvpn/http/header.hpp b/openvpn/http/header.hpp index 893ccda29..397f6a0e7 100644 --- a/openvpn/http/header.hpp +++ b/openvpn/http/header.hpp @@ -26,9 +26,8 @@ namespace openvpn::HTTP { struct Header { - Header() - { - } + Header() = default; + Header(std::string name_arg, std::string value_arg) : name(std::move(name_arg)), value(std::move(value_arg)) { @@ -77,8 +76,7 @@ struct HeaderList : public std::vector<Header> const Header *h = get(key); if (h) return h->value; - else - return std::string(); + return std::string(); } std::string get_value_trim(const std::string &key) const @@ -95,7 +93,7 @@ struct HeaderList : public std::vector<Header> { std::ostringstream out; for (size_t i = 0; i < size(); ++i) - out << '[' << i << "] " << (*this)[i].to_string() << std::endl; + out << '[' << i << "] " << (*this)[i].to_string() << '\n'; return out.str(); } }; diff --git a/openvpn/http/headredact.hpp b/openvpn/http/headredact.hpp index f86ba8af5..fc3e03094 100644 --- a/openvpn/http/headredact.hpp +++ b/openvpn/http/headredact.hpp @@ -39,15 +39,15 @@ inline std::string headers_redact(const std::string &headers) { authtype = argument.substr(0, arg1); } - result << line.substr(0, authpos) << "Authorization: " << authtype << " [REDACTED]\r" << std::endl; + result << line.substr(0, authpos) << "Authorization: " << authtype << " [REDACTED]\r\n"; } else if ((authpos = line.find("authorization=basic ")) != std::string::npos) { - result << line.substr(0, authpos) << "authorization=basic [REDACTED]\r" << std::endl; + result << line.substr(0, authpos) << "authorization=basic [REDACTED]\r\n"; } else { - result << line << std::endl; + result << line << '\n'; } } return result.str(); diff --git a/openvpn/http/htmlskip.hpp b/openvpn/http/htmlskip.hpp index 7f03b8454..7d5ede0d3 100644 --- a/openvpn/http/htmlskip.hpp +++ b/openvpn/http/htmlskip.hpp @@ -40,7 +40,7 @@ class HTMLSkip HTMLSkip() : state(INITIAL), - residual(64, 0), + residual(64), bytes(0) { } @@ -121,7 +121,7 @@ class HTMLSkip retain = true; if (c == ' ' || c == '\t' || c == '\r' || c == '\n') break; - else if (c == 'h' || c == 'H') + if (c == 'h' || c == 'H') state = O_HTML_H; else state = FAIL; @@ -227,7 +227,7 @@ class HTMLSkip } else { - BufferAllocated newbuf(residual.size() + buf.size(), 0); + BufferAllocated newbuf(residual.size() + buf.size()); newbuf.write(residual.c_data(), residual.size()); newbuf.write(buf.c_data(), buf.size()); buf.move(newbuf); diff --git a/openvpn/http/reply.hpp b/openvpn/http/reply.hpp index 0ade11035..3736e6597 100644 --- a/openvpn/http/reply.hpp +++ b/openvpn/http/reply.hpp @@ -44,10 +44,10 @@ struct Reply std::string to_string() const { std::ostringstream out; - out << "HTTP Reply" << std::endl; - out << "version=" << http_version_major << '/' << http_version_minor << std::endl; - out << "status_code=" << status_code << std::endl; - out << "status_text=" << status_text << std::endl; + out << "HTTP Reply\n"; + out << "version=" << http_version_major << '/' << http_version_minor << '\n'; + out << "status_code=" << status_code << '\n'; + out << "status_text=" << status_text << '\n'; out << headers.to_string(); return out.str(); } @@ -390,8 +390,8 @@ class ReplyParser struct ReplyType { - typedef Reply State; - typedef ReplyParser Parser; + using State = Reply; + using Parser = ReplyParser; }; } // namespace openvpn::HTTP diff --git a/openvpn/http/request.hpp b/openvpn/http/request.hpp index 8be4bef56..835a8e51d 100644 --- a/openvpn/http/request.hpp +++ b/openvpn/http/request.hpp @@ -44,10 +44,10 @@ struct Request std::string to_string() const { std::ostringstream out; - out << "HTTP Request" << std::endl; - out << "method=" << method << std::endl; - out << "uri=" << uri << std::endl; - out << "version=" << http_version_major << '/' << http_version_minor << std::endl; + out << "HTTP Request\n"; + out << "method=" << method << "\n"; + out << "uri=" << uri << "\n"; + out << "version=" << http_version_major << '/' << http_version_minor << "\n"; out << headers.to_string(); return out.str(); } diff --git a/openvpn/http/urlparm.hpp b/openvpn/http/urlparm.hpp index c45f8e9b2..c53d8bef4 100644 --- a/openvpn/http/urlparm.hpp +++ b/openvpn/http/urlparm.hpp @@ -26,9 +26,7 @@ OPENVPN_EXCEPTION(url_parameter_error); struct Parm { - Parm() - { - } + Parm() = default; Parm(const std::string &name_arg, const std::string &value_arg) : name(name_arg), value(value_arg) @@ -169,7 +167,7 @@ class ParmList : public std::vector<Parm> { std::ostringstream out; for (size_t i = 0; i < size(); ++i) - out << '[' << i << "] " << (*this)[i].to_string() << std::endl; + out << '[' << i << "] " << (*this)[i].to_string() << "\n"; return out.str(); } diff --git a/openvpn/http/urlparse.hpp b/openvpn/http/urlparse.hpp index a562ff14a..007d587db 100644 --- a/openvpn/http/urlparse.hpp +++ b/openvpn/http/urlparse.hpp @@ -28,9 +28,7 @@ OPENVPN_EXCEPTION(url_parse_error); class Parse { public: - Parse() - { - } + Parse() = default; Parse(const std::string &url, const bool set_default_port = false, @@ -148,7 +146,7 @@ class Parse Parse p; p.scheme = https ? "https" : "http"; p.host = host; - if (port.size() >= 1 && !string::is_digit(port[0])) // non-INET address + if (!port.empty() && !string::is_digit(port[0])) // non-INET address p.scheme = port; else p.port = port; diff --git a/openvpn/init/cryptoinit.hpp b/openvpn/init/cryptoinit.hpp deleted file mode 100644 index d7384d857..000000000 --- a/openvpn/init/cryptoinit.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -#pragma once - -#include <string> - -#ifdef USE_OPENSSL -#include <openvpn/openssl/util/init.hpp> -#endif - -namespace openvpn { - -// process-wide initialization for crypto subsystem -class crypto_init -{ -#if defined(OPENSSL_NEEDS_INIT) - openssl_init openssl_init_; -#endif - /* - * We add a dummy member so this class does not count as trivial - * class. Otherwise it will trigger: - * warning: private field 'crypto_init_' is not used [-Wunused-private-field] - */ - std::string dummy; -}; - -} // namespace openvpn diff --git a/openvpn/init/engineinit.hpp b/openvpn/init/engineinit.hpp index f0b65d7ed..cac8b5667 100644 --- a/openvpn/init/engineinit.hpp +++ b/openvpn/init/engineinit.hpp @@ -18,7 +18,7 @@ #include <openvpn/common/arch.hpp> -#if defined(USE_OPENSSL) +#ifdef USE_OPENSSL #include <openvpn/openssl/util/engine.hpp> #include <openvpn/openssl/ssl/sslctx.hpp> #endif @@ -34,7 +34,7 @@ namespace openvpn { inline void init_openssl(const std::string &engine) { -#if defined(USE_OPENSSL) +#ifdef USE_OPENSSL openssl_setup_engine(engine); OpenSSLContext::SSL::init_static(); #elif defined(USE_MINICRYPTO) && (defined(OPENVPN_ARCH_x86_64) || defined(OPENVPN_ARCH_i386)) diff --git a/openvpn/init/initprocess.hpp b/openvpn/init/initprocess.hpp index f38783890..3b84f4ec4 100644 --- a/openvpn/init/initprocess.hpp +++ b/openvpn/init/initprocess.hpp @@ -20,7 +20,6 @@ #include <openvpn/common/base64.hpp> #include <openvpn/time/time.hpp> #include <openvpn/compress/compress.hpp> -#include <openvpn/init/cryptoinit.hpp> #include <openvpn/init/engineinit.hpp> namespace openvpn::InitProcess { @@ -48,10 +47,6 @@ class Init { base64_uninit_static(); } - - private: - // SSL library init happens when instantiated - crypto_init crypto_init_; }; // process-wide singular instance @@ -64,7 +59,7 @@ class Init public: Init() { - std::lock_guard<std::mutex> lock(the_instance_mutex); + const std::lock_guard<std::mutex> lock(the_instance_mutex); initptr = init_instance.lock(); if (!initptr) @@ -77,7 +72,7 @@ class Init ~Init() { // explicitly reset smart pointer to make the destructor run under the lock_guard - std::lock_guard<std::mutex> lock(the_instance_mutex); + const std::lock_guard<std::mutex> lock(the_instance_mutex); initptr.reset(); } }; diff --git a/openvpn/ip/ping6.hpp b/openvpn/ip/ping6.hpp index e86c967f2..bc57c4871 100644 --- a/openvpn/ip/ping6.hpp +++ b/openvpn/ip/ping6.hpp @@ -30,7 +30,7 @@ namespace openvpn::Ping6 { inline static const std::uint16_t *get_addr16(const struct in6_addr *addr) { -#if defined(_WIN32) +#ifdef _WIN32 return addr->u.Word; #elif defined(__APPLE__) || defined(__FreeBSD__) return addr->__u6_addr.__u6_addr16; diff --git a/openvpn/ip/ptb.hpp b/openvpn/ip/ptb.hpp index d9b3ebd15..ad41bc1d7 100644 --- a/openvpn/ip/ptb.hpp +++ b/openvpn/ip/ptb.hpp @@ -61,7 +61,7 @@ class Ptb if ((buf.offset() < sizeof(ICMPv6)) || (buf.capacity() < (sizeof(ICMPv6) + data_size))) return; - IPv6Header *ipv6 = (IPv6Header *)buf.c_data(); + const IPv6Header *ipv6 = (IPv6Header *)buf.c_data(); uint8_t *b = buf.prepend_alloc(sizeof(ICMPv6)); ICMPv6 *icmp = (ICMPv6 *)b; @@ -97,7 +97,7 @@ class Ptb if ((buf.offset() < sizeof(ICMPv4)) || (buf.capacity() < (sizeof(ICMPv4) + data_size))) return; - IPv4Header *ipv4 = (IPv4Header *)buf.c_data(); + const IPv4Header *ipv4 = (IPv4Header *)buf.c_data(); uint8_t *b = buf.prepend_alloc(sizeof(ICMPv4)); ICMPv4 *icmp = (ICMPv4 *)b; diff --git a/openvpn/linux/procfs.hpp b/openvpn/linux/procfs.hpp index b0668e976..3d249203f 100644 --- a/openvpn/linux/procfs.hpp +++ b/openvpn/linux/procfs.hpp @@ -6,12 +6,14 @@ // #define OPENVPN_PROCFS_DEBUG +#include <chrono> +#include <filesystem> #include <string> +#include <thread> #include <openvpn/common/string.hpp> #include <openvpn/common/exception.hpp> #include <openvpn/common/fileunix.hpp> -#include <openvpn/common/sleep.hpp> #include <openvpn/common/stat.hpp> #include <openvpn/common/format.hpp> #include <openvpn/common/action.hpp> @@ -31,20 +33,20 @@ class ProcFS : public Action { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; try { write_sys(fn, text); } catch (const std::exception &e) { - os << "ProcFS exception: " << e.what() << std::endl; + os << "ProcFS exception: " << e.what() << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { return to_string(fn, text); } @@ -56,6 +58,8 @@ class ProcFS : public Action static void write_sys(const std::string &fn, const std::string &text, Stop *async_stop = nullptr) { + using namespace std::chrono_literals; + const unsigned int n_retries = 200; const unsigned int milliseconds_per_retry = 100; volatile bool stop = false; @@ -66,7 +70,8 @@ class ProcFS : public Action for (unsigned int i = 0; i < n_retries && !stop; ++i) { - if (file_exists(fn)) + std::error_code ec; + if (std::filesystem::exists(fn, ec)) { try { @@ -78,9 +83,9 @@ class ProcFS : public Action OPENVPN_LOG("ProcFS exception: " << e.what()); } #ifdef OPENVPN_PROCFS_DEBUG - sleep_milliseconds(100); + std::this_thread::sleep_for(100ms); std::string text_verify; - BufferAllocated buf(256, 0); + BufferAllocated buf(256); const int status = read_binary_unix_fast(fn, buf); if (status) { @@ -95,7 +100,7 @@ class ProcFS : public Action #endif return; } - sleep_milliseconds(milliseconds_per_retry); + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds_per_retry)); } if (stop) OPENVPN_THROW(procfs_error, "file " << fn << " : aborting write attempt due to stop signal"); diff --git a/openvpn/linux/usergroup_retain_cap.hpp b/openvpn/linux/usergroup_retain_cap.hpp index 6abed2d7d..5e069f58c 100644 --- a/openvpn/linux/usergroup_retain_cap.hpp +++ b/openvpn/linux/usergroup_retain_cap.hpp @@ -53,7 +53,7 @@ class SetUserGroupRetainCap : public SetUserGroup } // call first in all threads before user/group downgrade - virtual void pre_thread() const override + void pre_thread() const override { if (!pw) return; @@ -76,7 +76,7 @@ class SetUserGroupRetainCap : public SetUserGroup } // call once after pre_thread() called in each thread - virtual void activate() const override + void activate() const override { if (!pw) { @@ -106,7 +106,7 @@ class SetUserGroupRetainCap : public SetUserGroup } // call in all threads after activate() - virtual void post_thread() const override + void post_thread() const override { if (!pw) return; diff --git a/openvpn/log/logbasesimple.hpp b/openvpn/log/logbasesimple.hpp index 775bbf279..2e94460ea 100644 --- a/openvpn/log/logbasesimple.hpp +++ b/openvpn/log/logbasesimple.hpp @@ -29,7 +29,7 @@ class LogBaseSimple : public LogBase { } - virtual void log(const std::string &str) override + void log(const std::string &str) override { const std::string ts = date_time(); { diff --git a/openvpn/log/logbasesimplemac.hpp b/openvpn/log/logbasesimplemac.hpp index afcbb65c8..d3db375cb 100644 --- a/openvpn/log/logbasesimplemac.hpp +++ b/openvpn/log/logbasesimplemac.hpp @@ -34,7 +34,7 @@ class LogBaseSimpleMac : public LogBase "LogBaseSimple for macOS/iOS initialized"); } - virtual void log(const std::string &str) override + void log(const std::string &str) override { std::lock_guard<std::mutex> lock(mutex); os_log_with_type(OS_LOG_DEFAULT, diff --git a/openvpn/log/logdatetime.hpp b/openvpn/log/logdatetime.hpp index 84b9da899..31666e72a 100644 --- a/openvpn/log/logdatetime.hpp +++ b/openvpn/log/logdatetime.hpp @@ -20,7 +20,8 @@ #define OPENVPN_LOG_STREAM std::cout #endif -#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << date_time() << ' ' << args << std::endl +#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << date_time() << ' ' << args << "\n" \ + << std::flush // like OPENVPN_LOG but no trailing newline #define OPENVPN_LOG_NTNL(args) OPENVPN_LOG_STREAM << date_time() << ' ' << args diff --git a/openvpn/log/logsimple.hpp b/openvpn/log/logsimple.hpp index a0418b779..e32d3047c 100644 --- a/openvpn/log/logsimple.hpp +++ b/openvpn/log/logsimple.hpp @@ -19,7 +19,8 @@ #define OPENVPN_LOG_STREAM std::cout #endif -#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << args << std::endl +#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << args << "\n" \ + << std::flush // like OPENVPN_LOG but no trailing newline #define OPENVPN_LOG_NTNL(args) OPENVPN_LOG_STREAM << args << std::flush diff --git a/openvpn/log/sessionstats.hpp b/openvpn/log/sessionstats.hpp index 4ce5597cd..7db1bfd1f 100644 --- a/openvpn/log/sessionstats.hpp +++ b/openvpn/log/sessionstats.hpp @@ -27,10 +27,10 @@ namespace openvpn { class SessionStats : public RC<thread_safe_refcount> { public: - typedef RCPtr<SessionStats> Ptr; + using Ptr = RCPtr<SessionStats>; using inc_callback_t = std::function<void(const count_t value)>; - enum Stats + enum Stats : unsigned int { // operating stats BYTES_IN = 0, // network bytes in @@ -69,7 +69,7 @@ class SessionStats : public RC<thread_safe_refcount> { if (type < N_STATS) { - stats_[type] += value; + stats_[type] = stats_[type] + value; if (auto lock = inc_callbacks_[type].lock()) std::invoke(*lock, value); } @@ -79,8 +79,7 @@ class SessionStats : public RC<thread_safe_refcount> { if (type < N_STATS) return stats_[type]; - else - return 0; + return 0; } count_t get_stat_fast(const size_t type) const @@ -101,10 +100,10 @@ class SessionStats : public RC<thread_safe_refcount> "TUN_PACKETS_OUT", }; + static_assert(N_STATS == array_size(names), "stats names array inconsistency"); if (type < N_STATS) return names[type]; - else - return "UNKNOWN_STAT_TYPE"; + return "UNKNOWN_STAT_TYPE"; } void update_last_packet_received(const Time &now) @@ -119,7 +118,7 @@ class SessionStats : public RC<thread_safe_refcount> struct DCOTransportSource : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<DCOTransportSource> Ptr; + using Ptr = RCPtr<DCOTransportSource>; struct Data { @@ -210,14 +209,14 @@ class SessionStats : public RC<thread_safe_refcount> update_last_packet_received(Time::now()); } - stats_[BYTES_IN] += data.transport_bytes_in; - stats_[BYTES_OUT] += data.transport_bytes_out; - stats_[TUN_BYTES_IN] += data.tun_bytes_in; - stats_[TUN_BYTES_OUT] += data.tun_bytes_out; - stats_[PACKETS_IN] += data.transport_pkts_in; - stats_[PACKETS_OUT] += data.transport_pkts_out; - stats_[TUN_PACKETS_IN] += data.tun_pkts_in; - stats_[TUN_PACKETS_OUT] += data.tun_pkts_out; + inc_stat(BYTES_IN, data.transport_bytes_in); + inc_stat(BYTES_OUT, data.transport_bytes_out); + inc_stat(TUN_BYTES_IN, data.tun_bytes_in); + inc_stat(TUN_BYTES_OUT, data.tun_bytes_out); + inc_stat(PACKETS_IN, data.transport_pkts_in); + inc_stat(PACKETS_OUT, data.transport_pkts_out); + inc_stat(TUN_PACKETS_IN, data.tun_pkts_in); + inc_stat(TUN_PACKETS_OUT, data.tun_pkts_out); return true; } diff --git a/openvpn/mbedtls/pki/pkctx.hpp b/openvpn/mbedtls/pki/pkctx.hpp index dfe5e0672..1a7922016 100644 --- a/openvpn/mbedtls/pki/pkctx.hpp +++ b/openvpn/mbedtls/pki/pkctx.hpp @@ -105,7 +105,7 @@ class PKContext : public RC<thread_unsafe_refcount> std::string extract() const { // maximum size of the PEM data is not available at this point - BufferAllocated buff(16000, 0); + BufferAllocated buff(16000); int ret = mbedtls_pk_write_key_pem(ctx, buff.data(), buff.max_size()); if (ret < 0) diff --git a/openvpn/mbedtls/pki/x509cert.hpp b/openvpn/mbedtls/pki/x509cert.hpp index da85b39b5..0f9c6a11f 100644 --- a/openvpn/mbedtls/pki/x509cert.hpp +++ b/openvpn/mbedtls/pki/x509cert.hpp @@ -97,7 +97,7 @@ class X509Cert : public RC<thread_unsafe_refcount> if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) throw MbedTLSException("X509Cert::extract: can't calculate PEM size"); - BufferAllocated buff(olen, 0); + BufferAllocated buff(olen); ret = mbedtls_pem_write_buffer(begin_cert, end_cert, diff --git a/openvpn/mbedtls/ssl/sslctx.hpp b/openvpn/mbedtls/ssl/sslctx.hpp index 84028b05c..5b9e1c5f0 100644 --- a/openvpn/mbedtls/ssl/sslctx.hpp +++ b/openvpn/mbedtls/ssl/sslctx.hpp @@ -178,6 +178,31 @@ const mbedtls_x509_crt_profile crt_profile_preferred = // CONST GLOBAL } // namespace } // namespace mbedtls_ctx_private +// Handle different APIs regarding curves +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 +using mbedtls_compat_group_id = uint16_t; +#else +using mbedtls_compat_group_id = mbedtls_ecp_group_id; +#endif + +static inline mbedtls_compat_group_id +mbedtls_compat_get_group_id(const mbedtls_ecp_curve_info *curve_info) +{ +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 + return curve_info->tls_id; +#else + return curve_info->grp_id; +#endif +} + +#if MBEDTLS_VERSION_NUMBER < 0x03000000 +static inline void +mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, mbedtls_compat_group_id *groups) +{ + mbedtls_ssl_conf_curves(conf, groups); +} +#endif + // Represents an SSL configuration that can be used // to instantiate actual SSL sessions. class MbedTLSContext : public SSLFactoryAPI @@ -940,14 +965,11 @@ class MbedTLSContext : public SSLFactoryAPI throw MbedTLSException("CA chain not defined"); // Set hostname for SNI or if a CA chain is configured - // In pre-mbedtls-2.x the hostname for the CA chain was set in ssl_set_ca_chain(). - // From mbedtls-2.x, the hostname must be set via mbedtls_ssl_set_hostname() - // https://tls.mbed.org/kb/how-to/upgrade-2.0 - if (hostname && ((c.flags & SSLConst::ENABLE_CLIENT_SNI) || c.ca_chain)) - { - if (mbedtls_ssl_set_hostname(ssl, hostname)) - throw MbedTLSException("mbedtls_ssl_set_hostname failed"); - } + // Otherwise set the hostname explicitly to null to avoid + // MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME + bool use_hostname = hostname && ((c.flags & SSLConst::ENABLE_CLIENT_SNI) || c.ca_chain); + if (mbedtls_ssl_set_hostname(ssl, use_hostname ? hostname : nullptr)) + throw MbedTLSException("mbedtls_ssl_set_hostname failed"); // client cert+key if (c.local_cert_enabled) @@ -1008,10 +1030,10 @@ class MbedTLSContext : public SSLFactoryAPI if (c.ssl_debug_level) mbedtls_ssl_conf_dbg(sslconf, dbg_callback, ctx); - /* OpenVPN 2.x disables cbc_record_splitting by default, therefore - * we have to do the same here to keep compatibility. - * If not disabled, this setting will trigger bad behaviours on - * TLS1.0 and possibly on other setups */ + /* OpenVPN 2.x disables cbc_record_splitting by default, therefore + * we have to do the same here to keep compatibility. + * If not disabled, this setting will trigger bad behaviours on + * TLS1.0 and possibly on other setups */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) mbedtls_ssl_conf_cbc_record_splitting(sslconf, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); @@ -1028,10 +1050,10 @@ class MbedTLSContext : public SSLFactoryAPI } } - mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object - std::unique_ptr<int[]> allowed_ciphers; //! Hold the array that is used for setting the allowed ciphers - // must have the same lifetime as sslconf - std::unique_ptr<mbedtls_ecp_group_id[]> groups; //! Hold the array that is used for setting the curves + mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object + std::unique_ptr<int[]> allowed_ciphers; //! Hold the array that is used for setting the allowed ciphers + // must have the same lifetime as sslconf + std::unique_ptr<mbedtls_compat_group_id[]> groups; //! Hold the array that is used for setting the curves MbedTLSContext *parent; @@ -1083,7 +1105,7 @@ class MbedTLSContext : public SSLFactoryAPI auto num_groups = std::count(tls_groups.begin(), tls_groups.end(), ':') + 1; /* add extra space for sentinel at the end */ - groups.reset(new mbedtls_ecp_group_id[num_groups + 1]); + groups.reset(new mbedtls_compat_group_id[num_groups + 1]); std::stringstream groups_ss(tls_groups); std::string group; @@ -1095,7 +1117,7 @@ class MbedTLSContext : public SSLFactoryAPI if (ci) { - groups[i] = ci->grp_id; + groups[i] = mbedtls_compat_get_group_id(ci); i++; } else @@ -1105,8 +1127,8 @@ class MbedTLSContext : public SSLFactoryAPI } } - groups[i] = MBEDTLS_ECP_DP_NONE; - mbedtls_ssl_conf_curves(sslconf, groups.get()); + groups[i] = mbedtls_compat_group_id(0); + mbedtls_ssl_conf_groups(sslconf, groups.get()); } // cleartext read callback @@ -1343,7 +1365,7 @@ class MbedTLSContext : public SSLFactoryAPI os << "VERIFY " << status_str << " : depth=" << depth - << std::endl + << "\n" << cert_info(cert); return os.str(); } @@ -1359,10 +1381,10 @@ class MbedTLSContext : public SSLFactoryAPI if (self->config->flags & SSLConst::LOG_VERIFY_STATUS) OVPN_LOG_INFO(status_string(cert, depth, flags)); - // notify if connection is happening with an insecurely signed cert. + // notify if connection is happening with an insecurely signed cert. - // mbed TLS 3.0 does not allow the weaker signatures by default and also does not give a - // proper accessor to these fields anymore + // mbed TLS 3.0 does not allow the weaker signatures by default and also does not give a + // proper accessor to these fields anymore #if MBEDTLS_VERSION_NUMBER < 0x03000000 if (cert->sig_md == MBEDTLS_MD_MD5) { @@ -1593,7 +1615,7 @@ class MbedTLSContext : public SSLFactoryAPI } /* concatenate digest prefix with hash */ - BufferAllocated from_buf(digest_prefix_len + hashlen, 0); + BufferAllocated from_buf(digest_prefix_len + hashlen); if (digest_prefix_len) from_buf.write(digest_prefix, digest_prefix_len); from_buf.write(hash, hashlen); diff --git a/openvpn/mbedtls/util/selftest.hpp b/openvpn/mbedtls/util/selftest.hpp index 494c29e1b..d870ba3a9 100644 --- a/openvpn/mbedtls/util/selftest.hpp +++ b/openvpn/mbedtls/util/selftest.hpp @@ -32,14 +32,14 @@ inline std::string crypto_self_test_mbedtls() std::ostringstream os; #ifdef MBEDTLS_SELF_TEST const int verbose = 1; - os << "mbed TLS self test (tests return 0 if successful):" << std::endl; - os << " mbedlts_aes_self_test status=" << mbedtls_aes_self_test(verbose) << std::endl; - os << " mbedtls_sha1_self_test status=" << mbedtls_sha1_self_test(verbose) << std::endl; - os << " mbedtls_sha256_self_test status=" << mbedtls_sha256_self_test(verbose) << std::endl; - os << " mbedtls_sha512_self_test status=" << mbedtls_sha512_self_test(verbose) << std::endl; - os << " mbedtls_mpi_self_test status=" << mbedtls_mpi_self_test(verbose) << std::endl; + os << "mbed TLS self test (tests return 0 if successful):\n"; + os << " mbedlts_aes_self_test status=" << mbedtls_aes_self_test(verbose) << "\n"; + os << " mbedtls_sha1_self_test status=" << mbedtls_sha1_self_test(verbose) << "\n"; + os << " mbedtls_sha256_self_test status=" << mbedtls_sha256_self_test(verbose) << "\n"; + os << " mbedtls_sha512_self_test status=" << mbedtls_sha512_self_test(verbose) << "\n"; + os << " mbedtls_mpi_self_test status=" << mbedtls_mpi_self_test(verbose) << "\n"; #else - os << "mbed TLS self test: not compiled" << std::endl; + os << "mbed TLS self test: not compiled\n"; #endif return os.str(); } diff --git a/openvpn/netconf/enumiface.hpp b/openvpn/netconf/enumiface.hpp index bd4de56e4..921eb07f8 100644 --- a/openvpn/netconf/enumiface.hpp +++ b/openvpn/netconf/enumiface.hpp @@ -47,7 +47,7 @@ class EnumIface std::string to_string() const { std::ostringstream os; - os << "INTERFACES:" << std::endl; + os << "INTERFACES:\n"; for (const ifaddrs *i = ifinfo.get(); i->ifa_next; i = i->ifa_next) render(i, os); return os.str(); @@ -104,7 +104,7 @@ class EnumIface { os << " ERROR"; } - os << std::endl; + os << "\n"; } static std::string render_flags(const u_int flags) diff --git a/openvpn/netconf/linux/gw.hpp b/openvpn/netconf/linux/gw.hpp index 9b0bd575e..69a6ffd6d 100644 --- a/openvpn/netconf/linux/gw.hpp +++ b/openvpn/netconf/linux/gw.hpp @@ -189,10 +189,9 @@ struct LinuxGW46 { if (v4.defined()) return v4.dev(); - else if (v6.defined()) + if (v6.defined()) return v6.dev(); - else - throw LinuxGW::linux_gw_error("cannot determine gateway interface"); + throw LinuxGW::linux_gw_error("cannot determine gateway interface"); } LinuxGW v4; diff --git a/openvpn/netconf/linux/gwnetlink.hpp b/openvpn/netconf/linux/gwnetlink.hpp index 1ae7dff03..01d80766f 100644 --- a/openvpn/netconf/linux/gwnetlink.hpp +++ b/openvpn/netconf/linux/gwnetlink.hpp @@ -144,10 +144,9 @@ struct LinuxGW46Netlink { if (v4.defined()) return v4.dev(); - else if (v6.defined()) + if (v6.defined()) return v6.dev(); - else - throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface"); + throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface"); } LinuxGWNetlink v4; diff --git a/openvpn/omi/omi.hpp b/openvpn/omi/omi.hpp index eb55e0a71..f56ba531d 100644 --- a/openvpn/omi/omi.hpp +++ b/openvpn/omi/omi.hpp @@ -920,7 +920,7 @@ class OMICore : public Acceptor::ListenerBase { if (!is_sock_open() || recv_queued) return; - BufferPtr buf = BufferAllocatedRc::Create(256, 0); + BufferPtr buf = BufferAllocatedRc::Create(256); socket->async_receive(buf->mutable_buffer_clamp(), [self = Ptr(this), sock = socket, buf](const openvpn_io::error_code &error, const size_t bytes_recvd) { diff --git a/openvpn/omi/openvpn.cpp b/openvpn/omi/openvpn.cpp index 33d0340a1..2dddbbc1a 100644 --- a/openvpn/omi/openvpn.cpp +++ b/openvpn/omi/openvpn.cpp @@ -312,7 +312,7 @@ class OMI : public OMICore, public ClientAPI::LogReceiver const Option &o = opt[*i]; o.touch(); const std::string &k = o.get(1, 64); - if (string::starts_with(k, "IV_") || string::starts_with(k, "UV_")) + if (k.starts_with("IV_") || k.starts_with("UV_")) { const std::string &v = o.get(2, 256); ret.emplace_back(k, v); @@ -673,7 +673,7 @@ class OMI : public OMICore, public ClientAPI::LogReceiver { send(string::add_trailing_crlf_copy(fe)); if (is_errors_to_stderr()) - std::cerr << fe << std::endl; + std::cerr << fe << "\n"; OPENVPN_LOG_STRING(fe + '\n'); ret = true; } @@ -881,7 +881,7 @@ class OMI : public OMICore, public ClientAPI::LogReceiver reconnect_reason = ""; // generate a TCP_CONNECT event if TCP connection - if (ci && string::starts_with(ci->serverProto, "TCP")) + if (ci && ci->serverProto.starts_with("TCP")) state_line(gen_state_msg(false, "TCP_CONNECT", "")); // push the event string to state notification/history @@ -1062,7 +1062,7 @@ int run(OptionList opt) omi->stop(); if (io_context_run_called) io_context.poll(); // execute completion handlers, - std::cerr << "openvpn: run loop exception: " << e.what() << std::endl; + std::cerr << "openvpn: run loop exception: " << e.what() << "\n"; ret = 1; } return ret; @@ -1080,14 +1080,14 @@ int main(int argc, char *argv[]) } else { - std::cout << log_version() << std::endl; - std::cout << "Usage: openvpn [args...]" << std::endl; + std::cout << log_version() << "\n"; + std::cout << "Usage: openvpn [args...]\n"; ret = 2; } } catch (const std::exception &e) { - std::cerr << "openvpn: " << e.what() << std::endl; + std::cerr << "openvpn: " << e.what() << "\n"; ret = 1; } return ret; diff --git a/openvpn/openssl/bio/bio_memq_stream.hpp b/openvpn/openssl/bio/bio_memq_stream.hpp index 05945a056..0f18ca9f0 100644 --- a/openvpn/openssl/bio/bio_memq_stream.hpp +++ b/openvpn/openssl/bio/bio_memq_stream.hpp @@ -32,9 +32,7 @@ namespace openvpn::bmq_stream { class MemQ : public MemQStream { public: - MemQ() - { - } + MemQ() = default; long ctrl(BIO *b, int cmd, long num, void *ptr) { @@ -213,15 +211,13 @@ inline MemQ *memq_from_bio(BIO *b) { if (BIO_method_type(b) == bio_memq_internal::memq_method_type) return (MemQ *)(BIO_get_data(b)); - else - return nullptr; + return nullptr; } inline const MemQ *const_memq_from_bio(const BIO *b) { if (BIO_method_type(b) == bio_memq_internal::memq_method_type) return (const MemQ *)(BIO_get_data(const_cast<BIO *>(b))); - else - return nullptr; + return nullptr; } } // namespace openvpn::bmq_stream diff --git a/openvpn/openssl/compat.hpp b/openvpn/openssl/compat.hpp index 35f39c70b..7d99559c6 100644 --- a/openvpn/openssl/compat.hpp +++ b/openvpn/openssl/compat.hpp @@ -12,6 +12,8 @@ #pragma once +#include <openssl/opensslv.h> + #if OPENSSL_VERSION_NUMBER < 0x30000000L #include <cassert> #include <cstring> @@ -111,3 +113,13 @@ EVP_MD_free(const EVP_MD *md) } #endif +#if OPENSSL_VERSION_NUMBER < 0x30200000L && OPENSSL_VERSION_NUMBER >= 0x30000000L +static inline const char * +SSL_get0_group_name(SSL *s) +{ + /* int is the return type according the manual page but gcc complains that + * this a long to int conversion. So explicitly cast to int */ + int nid = static_cast<int>(SSL_get_negotiated_group(s)); + return SSL_group_to_name(s, nid); +} +#endif diff --git a/openvpn/openssl/crypto/api.hpp b/openvpn/openssl/crypto/api.hpp index 3205ad3af..89136fb27 100644 --- a/openvpn/openssl/crypto/api.hpp +++ b/openvpn/openssl/crypto/api.hpp @@ -25,14 +25,14 @@ namespace openvpn { struct OpenSSLCryptoAPI { // cipher - typedef OpenSSLCrypto::CipherContext CipherContext; - typedef OpenSSLCrypto::CipherContextAEAD CipherContextAEAD; + using CipherContext = OpenSSLCrypto::CipherContext; + using CipherContextAEAD = OpenSSLCrypto::CipherContextAEAD; // digest - typedef OpenSSLCrypto::DigestContext DigestContext; + using DigestContext = OpenSSLCrypto::DigestContext; // HMAC - typedef OpenSSLCrypto::HMACContext HMACContext; + using HMACContext = OpenSSLCrypto::HMACContext; // TLS 1.0/1.1 PRF function using TLS1PRF = OpenSSLCrypto::TLS1PRF; diff --git a/openvpn/openssl/crypto/cipher.hpp b/openvpn/openssl/crypto/cipher.hpp index 0a39f93bc..ed89145ac 100644 --- a/openvpn/openssl/crypto/cipher.hpp +++ b/openvpn/openssl/crypto/cipher.hpp @@ -17,8 +17,9 @@ #include <string> -#include <openssl/objects.h> #include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/opensslv.h> #include <openvpn/common/size.hpp> #include <openvpn/common/exception.hpp> @@ -121,11 +122,9 @@ class CipherContext out_acc += outlen; return true; } - else - { - openssl_clear_error_stack(); - return false; - } + + openssl_clear_error_stack(); + return false; } bool final(unsigned char *out, const size_t max_out_size, size_t &out_acc) @@ -137,11 +136,9 @@ class CipherContext out_acc += outlen; return true; } - else - { - openssl_clear_error_stack(); - return false; - } + + openssl_clear_error_stack(); + return false; } bool is_initialized() const diff --git a/openvpn/openssl/crypto/cipheraead.hpp b/openvpn/openssl/crypto/cipheraead.hpp index 60f9c7a63..319d02c0e 100644 --- a/openvpn/openssl/crypto/cipheraead.hpp +++ b/openvpn/openssl/crypto/cipheraead.hpp @@ -15,8 +15,9 @@ #include <string> -#include <openssl/objects.h> #include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/opensslv.h> #include <openvpn/common/size.hpp> #include <openvpn/common/exception.hpp> @@ -93,7 +94,7 @@ class CipherContextAEAD { free_cipher_context(); unsigned int ckeysz = 0; - CIPHER_unique_ptr ciph(cipher_type(libctx, alg, ckeysz), EVP_CIPHER_free); + const CIPHER_unique_ptr ciph(cipher_type(libctx, alg, ckeysz), EVP_CIPHER_free); if (!ciph) OPENVPN_THROW(openssl_gcm_error, CryptoAlgs::name(alg) << ": not usable"); @@ -267,7 +268,7 @@ class CipherContextAEAD static bool is_supported(SSLLib::Ctx libctx, const CryptoAlgs::Type alg) { unsigned int keysize = 0; - CIPHER_unique_ptr cipher(cipher_type(libctx, alg, keysize), EVP_CIPHER_free); + const CIPHER_unique_ptr cipher(cipher_type(libctx, alg, keysize), EVP_CIPHER_free); return (bool)cipher; } diff --git a/openvpn/openssl/crypto/digest.hpp b/openvpn/openssl/crypto/digest.hpp index e53cbaf5b..562b11786 100644 --- a/openvpn/openssl/crypto/digest.hpp +++ b/openvpn/openssl/crypto/digest.hpp @@ -17,6 +17,7 @@ #include <string> +#include <openssl/opensslv.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/md4.h> diff --git a/openvpn/openssl/crypto/mac.hpp b/openvpn/openssl/crypto/mac.hpp index 3e4a2181d..3ff6a78a3 100644 --- a/openvpn/openssl/crypto/mac.hpp +++ b/openvpn/openssl/crypto/mac.hpp @@ -16,6 +16,7 @@ #include <string> +#include <openssl/opensslv.h> /* The HMAC_* methods are deprecated in OpenSSL 3.0 and the EVP_MAC methods * do no exist in OpenSSL 1.1 yet. So use two distinct implementations */ #if OPENSSL_VERSION_NUMBER < 0x30000000L @@ -162,4 +163,4 @@ class HMACContext }; } // namespace openvpn::OpenSSLCrypto -#endif \ No newline at end of file +#endif diff --git a/openvpn/openssl/crypto/tls1prf.hpp b/openvpn/openssl/crypto/tls1prf.hpp index 2e222cc8a..b52e63788 100644 --- a/openvpn/openssl/crypto/tls1prf.hpp +++ b/openvpn/openssl/crypto/tls1prf.hpp @@ -10,6 +10,8 @@ // #pragma once + +#include <openssl/opensslv.h> #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #include <openssl/core_names.h> #include <openssl/params.h> @@ -17,8 +19,6 @@ #include <openssl/kdf.h> - - #include <openvpn/common/numeric_util.hpp> namespace openvpn::OpenSSLCrypto { @@ -38,13 +38,13 @@ class TLS1PRF using EVP_KDF_ptr = std::unique_ptr<EVP_KDF, decltype(&::EVP_KDF_free)>; using EVP_KDF_CTX_ptr = std::unique_ptr<EVP_KDF_CTX, decltype(&::EVP_KDF_CTX_free)>; - EVP_KDF_ptr kdf{::EVP_KDF_fetch(NULL, "TLS1-PRF", NULL), ::EVP_KDF_free}; + const EVP_KDF_ptr kdf{::EVP_KDF_fetch(NULL, "TLS1-PRF", NULL), ::EVP_KDF_free}; if (!kdf) { return false; } - EVP_KDF_CTX_ptr kctx{::EVP_KDF_CTX_new(kdf.get()), ::EVP_KDF_CTX_free}; + const EVP_KDF_CTX_ptr kctx{::EVP_KDF_CTX_new(kdf.get()), ::EVP_KDF_CTX_free}; if (!kctx) { diff --git a/openvpn/openssl/pki/crl.hpp b/openvpn/openssl/pki/crl.hpp index fa68830f2..a3bf33382 100644 --- a/openvpn/openssl/pki/crl.hpp +++ b/openvpn/openssl/pki/crl.hpp @@ -135,8 +135,7 @@ class CRL { if (crl) return ::X509_CRL_dup(const_cast<X509_CRL *>(crl)); - else - return nullptr; + return nullptr; } ::X509_CRL *crl_; @@ -145,7 +144,7 @@ class CRL class CRLList : public std::vector<CRL> { public: - typedef X509 CRL; + using CRL = X509; bool defined() const { diff --git a/openvpn/openssl/pki/dh-compat.hpp b/openvpn/openssl/pki/dh-compat.hpp index f8ca48420..e2afc034f 100644 --- a/openvpn/openssl/pki/dh-compat.hpp +++ b/openvpn/openssl/pki/dh-compat.hpp @@ -23,12 +23,6 @@ #include <openvpn/common/exception.hpp> #include <openvpn/openssl/util/error.hpp> -// workaround for bug in DHparams_dup macro on OpenSSL 0.9.8 and lower -#if SSLEAY_VERSION_NUMBER <= 0x00908000L -#undef CHECKED_PTR_OF -#define CHECKED_PTR_OF(type, p) ((char *)(1 ? p : (type *)0)) -#endif - namespace openvpn::OpenSSLPKI { namespace DH_private { diff --git a/openvpn/openssl/pki/dh.hpp b/openvpn/openssl/pki/dh.hpp index 234cbfba7..9d321d62f 100644 --- a/openvpn/openssl/pki/dh.hpp +++ b/openvpn/openssl/pki/dh.hpp @@ -15,6 +15,7 @@ #include <string> +#include <openssl/opensslv.h> #include <openvpn/common/size.hpp> #include <openvpn/common/numeric_cast.hpp> @@ -158,4 +159,4 @@ class DH ::EVP_PKEY *dh_; }; } // namespace openvpn::OpenSSLPKI -#endif \ No newline at end of file +#endif diff --git a/openvpn/openssl/pki/pkey.hpp b/openvpn/openssl/pki/pkey.hpp index 2a016a30d..bfa9f53d1 100644 --- a/openvpn/openssl/pki/pkey.hpp +++ b/openvpn/openssl/pki/pkey.hpp @@ -16,8 +16,9 @@ #include <string> #include <utility> -#include <openssl/ssl.h> #include <openssl/bio.h> +#include <openssl/opensslv.h> +#include <openssl/ssl.h> #include <openvpn/common/size.hpp> #include <openvpn/common/numeric_cast.hpp> @@ -212,8 +213,7 @@ class PKey { if (pkey) return EVP_PKEY_dup(const_cast<EVP_PKEY *>(pkey)); - else - return nullptr; + return nullptr; } #endif diff --git a/openvpn/openssl/pki/x509.hpp b/openvpn/openssl/pki/x509.hpp index ec321fd5d..5c0848f79 100644 --- a/openvpn/openssl/pki/x509.hpp +++ b/openvpn/openssl/pki/x509.hpp @@ -137,17 +137,14 @@ class X509 ::X509 *dup = ::X509_dup(const_cast<::X509 *>(x509.get())); return {dup, ::X509_free}; } - else - { - return {nullptr, ::X509_free}; - } + + return {nullptr, ::X509_free}; } static ::X509 *dup(const ::X509 *x509) { if (x509) return ::X509_dup(const_cast<::X509 *>(x509)); - else - return nullptr; + return nullptr; } X509_unique_ptr x509_{nullptr, ::X509_free}; @@ -156,7 +153,7 @@ class X509 class X509List : public std::vector<X509> { public: - typedef X509 Item; + using Item = X509; bool defined() const { diff --git a/openvpn/openssl/pki/x509certinfo.hpp b/openvpn/openssl/pki/x509certinfo.hpp index cb9a203f6..9eed7a708 100644 --- a/openvpn/openssl/pki/x509certinfo.hpp +++ b/openvpn/openssl/pki/x509certinfo.hpp @@ -63,8 +63,7 @@ static inline std::string x509_get_subject(::X509 *cert, bool new_format = false { OPENSSL_free(p); }); if (subject) return std::string(subject.get()); - else - return std::string(""); + return std::string(""); } unique_ptr_del<BIO> subject_bio(BIO_new(BIO_s_mem()), @@ -119,8 +118,7 @@ static inline std::string x509_get_signature_algorithm(const ::X509 *cert) { return sig; } - else - return "(error getting signature algorithm)"; + return "(error getting signature algorithm)"; } /** diff --git a/openvpn/openssl/pki/x509store.hpp b/openvpn/openssl/pki/x509store.hpp index acb4576db..ec484eeac 100644 --- a/openvpn/openssl/pki/x509store.hpp +++ b/openvpn/openssl/pki/x509store.hpp @@ -27,7 +27,7 @@ class X509Store public: OPENVPN_EXCEPTION(x509_store_error); - typedef CertCRLListTemplate<X509List, CRLList> CertCRLList; + using CertCRLList = CertCRLListTemplate<X509List, CRLList>; X509Store() : x509_store_(nullptr) diff --git a/openvpn/openssl/pki/xkey.hpp b/openvpn/openssl/pki/xkey.hpp index 6d5a666ae..e1667848b 100644 --- a/openvpn/openssl/pki/xkey.hpp +++ b/openvpn/openssl/pki/xkey.hpp @@ -14,6 +14,8 @@ #pragma once +#include <memory> + #include <openssl/evp.h> #include <openssl/provider.h> @@ -123,7 +125,7 @@ class XKeyExternalPKIImpl : public std::enable_shared_from_this<XKeyExternalPKII public: [[nodiscard]] static std::shared_ptr<XKeyExternalPKIImpl> create(SSL_CTX *ssl_ctx, ::X509 *cert, ExternalPKIBase *external_pki, std::string alias) { - auto ret = std::shared_ptr<XKeyExternalPKIImpl>{new XKeyExternalPKIImpl{external_pki, alias}}; + auto ret = std::make_shared<XKeyExternalPKIImpl>(external_pki, std::move(alias)); ret->use_external_key(ssl_ctx, cert); return ret; } @@ -137,7 +139,7 @@ class XKeyExternalPKIImpl : public std::enable_shared_from_this<XKeyExternalPKII } XKeyExternalPKIImpl(ExternalPKIBase *external_pki, std::string alias) - : external_pki(external_pki), alias(alias) + : external_pki(external_pki), alias(std::move(alias)) { } @@ -255,7 +257,7 @@ class XKeyExternalPKIImpl : public std::enable_shared_from_this<XKeyExternalPKII } /* convert 'tbs' to base64 */ - ConstBuffer from_buf(tbs, tbslen, true); + const ConstBuffer from_buf(tbs, tbslen, true); const std::string from_b64 = base64->encode(from_buf); std::string sig_b64; diff --git a/openvpn/openssl/sign/verify.hpp b/openvpn/openssl/sign/verify.hpp index 3cb97ac55..809ea0104 100644 --- a/openvpn/openssl/sign/verify.hpp +++ b/openvpn/openssl/sign/verify.hpp @@ -64,7 +64,7 @@ inline void verify(const OpenSSLPKI::X509 &cert, throw Exception("OpenSSLSign::verify: no public key"); // convert signature from base64 to binary - BufferAllocated binsig(1024, 0); + BufferAllocated binsig(1024); try { base64->decode(binsig, sig); diff --git a/openvpn/openssl/ssl/sess_cache.hpp b/openvpn/openssl/ssl/sess_cache.hpp index 239c08ef7..2018be5a7 100644 --- a/openvpn/openssl/ssl/sess_cache.hpp +++ b/openvpn/openssl/ssl/sess_cache.hpp @@ -31,7 +31,7 @@ namespace openvpn { class OpenSSLSessionCache : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<OpenSSLSessionCache> Ptr; + using Ptr = RCPtr<OpenSSLSessionCache>; OPENVPN_EXCEPTION(openssl_sess_cache_error); @@ -92,7 +92,7 @@ class OpenSSLSessionCache : public RC<thread_unsafe_refcount> class Key { public: - typedef std::unique_ptr<Key> UPtr; + using UPtr = std::unique_ptr<Key>; Key(const std::string &key_arg, OpenSSLSessionCache::Ptr cache_arg) @@ -158,11 +158,8 @@ class OpenSSLSessionCache : public RC<thread_unsafe_refcount> } private: - struct SessionSet : public std::set<Session> - { - }; - - typedef std::map<std::string, SessionSet> Map; + using SessionSet = std::set<Session>; + using Map = std::map<std::string, SessionSet>; void remove_session(Map::iterator mi, SessionSet &ss, SessionSet::iterator ssi) { diff --git a/openvpn/openssl/ssl/sslctx.hpp b/openvpn/openssl/ssl/sslctx.hpp index cc73097f9..da8c0e452 100644 --- a/openvpn/openssl/ssl/sslctx.hpp +++ b/openvpn/openssl/ssl/sslctx.hpp @@ -32,6 +32,7 @@ #include <openssl/bn.h> #include <openssl/rand.h> #include <openssl/evp.h> +#include <openssl/opensslv.h> #if OPENSSL_VERSION_NUMBER >= 0x30000000L #include <openssl/provider.h> #endif @@ -105,8 +106,8 @@ class OpenSSLContext : public SSLFactoryAPI using SSL_CTX_unique_ptr = std::unique_ptr<::SSL_CTX, decltype(&::SSL_CTX_free)>; public: - typedef RCPtr<OpenSSLContext> Ptr; - typedef CertCRLListTemplate<OpenSSLPKI::X509List, OpenSSLPKI::CRLList> CertCRLList; + using Ptr = RCPtr<OpenSSLContext>; + using CertCRLList = CertCRLListTemplate<OpenSSLPKI::X509List, OpenSSLPKI::CRLList>; enum { @@ -194,7 +195,7 @@ class OpenSSLContext : public SSLFactoryAPI #endif public: - typedef RCPtr<Config> Ptr; + using Ptr = RCPtr<Config>; /** @brief Return a pointer-like object that refers to a ssl factory @@ -328,7 +329,7 @@ class OpenSSLContext : public SSLFactoryAPI { std::vector<std::string> ret; - for (auto const &cert : extra_certs) + for (const auto &cert : extra_certs) ret.push_back(cert.render_pem()); return ret; @@ -704,7 +705,7 @@ class OpenSSLContext : public SSLFactoryAPI if (cached_ctx) { - lib_ctx = cached_ctx; + lib_ctx = std::move(cached_ctx); return; } } @@ -720,7 +721,7 @@ class OpenSSLContext : public SSLFactoryAPI // Return maximum TLS version supported by OpenSSL. // Assume that presence of SSL_OP_NO_TLSvX macro indicates // that local OpenSSL library implements TLSvX. -#if defined(SSL_OP_NO_TLSv1_3) +#ifdef SSL_OP_NO_TLSv1_3 return TLSVersion::Type::V1_3; #elif defined(SSL_OP_NO_TLSv1_2) return TLSVersion::Type::V1_2; @@ -787,7 +788,7 @@ class OpenSSLContext : public SSLFactoryAPI friend class OpenSSLContext; public: - typedef RCPtr<SSL> Ptr; + using Ptr = RCPtr<SSL>; void start_handshake() override { @@ -801,11 +802,9 @@ class OpenSSLContext : public SSLFactoryAPI { if (status == -1 && BIO_should_retry(ssl_bio)) return SSLConst::SHOULD_RETRY; - else - { - mark_no_cache(); - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::write_cleartext: BIO_write failed, size=" << size << " status=" << status); - } + + mark_no_cache(); + OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::write_cleartext: BIO_write failed, size=" << size << " status=" << status); } else return status; @@ -820,11 +819,9 @@ class OpenSSLContext : public SSLFactoryAPI { if ((status == 0 || status == -1) && BIO_should_retry(ssl_bio)) return SSLConst::SHOULD_RETRY; - else - { - mark_no_cache(); - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::read_cleartext: BIO_read failed, cap=" << capacity << " status=" << status); - } + + mark_no_cache(); + OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::read_cleartext: BIO_read failed, cap=" << capacity << " status=" << status); } else return status; @@ -1054,11 +1051,11 @@ class OpenSSLContext : public SSLFactoryAPI } // Print a one line summary of SSL/TLS session handshake. - static std::string ssl_handshake_details(const ::SSL *c_ssl) + static std::string ssl_handshake_details(::SSL *ssl) { std::ostringstream os; - ::X509 *cert = SSL_get_peer_certificate(c_ssl); + ::X509 *cert = SSL_get_peer_certificate(ssl); if (cert) os << "peer certificate: CN=" << OpenSSLPKI::x509_get_field(cert, NID_commonName); @@ -1070,22 +1067,28 @@ class OpenSSLContext : public SSLFactoryAPI { #ifndef OPENSSL_NO_EC if ((EVP_PKEY_id(pkey) == EVP_PKEY_EC)) - print_ec_key_details(pkey, os); - else #endif { +#if OPENSSL_VERSION_NUMBER < 0x30000000L int pkeyId = EVP_PKEY_id(pkey); const char *pkeySN = OBJ_nid2sn(pkeyId); if (!pkeySN) - pkeySN = "Unknown"; + pkeySN = "(error getting public key type)"; // Nicer names instead of rsaEncryption and dsaEncryption if (pkeyId == EVP_PKEY_RSA) pkeySN = "RSA"; else if (pkeyId == EVP_PKEY_DSA) pkeySN = "DSA"; +#else /* OpenSSL >= 3 */ + const char *pkeySN = EVP_PKEY_get0_type_name(pkey); + if (!pkeySN) + { + pkeySN = "(error getting public key type)"; + } +#endif /* if OPENSSL_VERSION_NUMBER < 0x30000000L */ os << ", " << EVP_PKEY_bits(pkey) << " bit " << pkeySN; } @@ -1094,7 +1097,7 @@ class OpenSSLContext : public SSLFactoryAPI X509_free(cert); } - const SSL_CIPHER *ciph = SSL_get_current_cipher(c_ssl); + const SSL_CIPHER *ciph = SSL_get_current_cipher(ssl); if (ciph) { char *desc = SSL_CIPHER_description(ciph, nullptr, 0); @@ -1104,15 +1107,26 @@ class OpenSSLContext : public SSLFactoryAPI } else { - os << ", cipher: " << desc; + std::string cipher_str(desc); + // remove \n at the end and any other excess whitespace + string::trim(cipher_str); + os << ", cipher: " << cipher_str; OPENSSL_free(desc); } } - // This has been changed in upstream SSL to have a const - // parameter, so we cast away const for older versions compatibility - // (Upstream commit: c04b66b18d1a90f0c6326858e4b8367be5444582) - if (SSL_session_reused(const_cast<::SSL *>(c_ssl))) + + if (SSL_session_reused(ssl)) os << " [REUSED]"; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + const char *key_agreement = SSL_get0_group_name(ssl); + if (!key_agreement) + { + key_agreement = "(error fetching key-agreeement)"; + } + os << ", key-agreement: " << key_agreement; +#endif + return os.str(); } @@ -1175,7 +1189,7 @@ class OpenSSLContext : public SSLFactoryAPI }; /////// start of main class implementation - static std::string translate_cipher_list(std::string cipherlist) + static std::string translate_cipher_list(const std::string &cipherlist) { // OpenVPN 2.x accepts IANA ciphers instead in the cipher list, we need // to do the same @@ -1370,7 +1384,7 @@ class OpenSSLContext : public SSLFactoryAPI { set_openssl_tls_groups(config->tls_groups); } -#if defined(TLS1_3_VERSION) +#ifdef TLS1_3_VERSION if (!config->tls_ciphersuite_list.empty()) { if (!SSL_CTX_set_ciphersuites(ctx.get(), config->tls_ciphersuite_list.c_str())) @@ -1401,9 +1415,6 @@ class OpenSSLContext : public SSLFactoryAPI if (TLSCertProfile::default_if_undef(config->tls_cert_profile) >= TLSCertProfile::PREFERRED) tls_cipher_list += ":!SHA1"; - - std::string translated_cipherlist; - if (!config->tls_cipher_list.empty()) { tls_cipher_list = translate_cipher_list(config->tls_cipher_list); @@ -1596,15 +1607,15 @@ class OpenSSLContext : public SSLFactoryAPI { if (config->ns_cert_type == NSCert::SERVER) return X509_check_purpose(cert, X509_PURPOSE_SSL_SERVER, 0); - else if (config->ns_cert_type == NSCert::CLIENT) + if (config->ns_cert_type == NSCert::CLIENT) return X509_check_purpose(cert, X509_PURPOSE_SSL_CLIENT, 0); - else - return true; + return true; } void set_openssl_tls_groups(const std::string &tls_groups) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L auto num_groups = std::count(tls_groups.begin(), tls_groups.end(), ':') + 1; std::unique_ptr<int[]> glist(new int[num_groups]); @@ -1638,13 +1649,17 @@ class OpenSSLContext : public SSLFactoryAPI if (!SSL_CTX_set1_groups(ctx.get(), glist.get(), glistlen)) OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set1_groups failed"); +#else + if (!SSL_CTX_set1_groups_list(ctx.get(), tls_groups.c_str())) + OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set1_groups_list failed"); +#endif } // remote-cert-ku verification bool x509_cert_ku_defined() const { - return config->ku.size() > 0; + return !config->ku.empty(); } bool verify_x509_cert_ku(::X509 *cert) const diff --git a/openvpn/openssl/util/engine.hpp b/openvpn/openssl/util/engine.hpp index dce7ec816..d5e6c76c4 100644 --- a/openvpn/openssl/util/engine.hpp +++ b/openvpn/openssl/util/engine.hpp @@ -16,7 +16,9 @@ #include <string> -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) +#include <openssl/opensslv.h> + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L #define OPENSSL_NO_ENGINE #endif diff --git a/openvpn/openssl/util/error.hpp b/openvpn/openssl/util/error.hpp index b6dcd587f..719496689 100644 --- a/openvpn/openssl/util/error.hpp +++ b/openvpn/openssl/util/error.hpp @@ -31,20 +31,15 @@ class OpenSSLException : public ExceptionCode public: OPENVPN_EXCEPTION(ssl_exception_index); - enum - { - MAX_ERRORS = 8 - }; + static constexpr size_t MAX_ERRORS = 8; OpenSSLException() { - ssl_err = -1; init_error("OpenSSL"); } explicit OpenSSLException(const std::string &error_text) noexcept { - ssl_err = -1; init_error(error_text.c_str()); } @@ -75,8 +70,7 @@ class OpenSSLException : public ExceptionCode { if (i < n_err) return errstack[i]; - else - throw ssl_exception_index(); + throw ssl_exception_index(); } int ssl_error() const @@ -118,11 +112,10 @@ class OpenSSLException : public ExceptionCode private: void init_error(const char *error_text) { - const char *prefix = ": "; - std::ostringstream tmp; + std::string prefix = ": "; char buf[256]; - tmp << error_text; + errtxt = error_text; n_err = 0; while (unsigned long err = ERR_get_error()) @@ -131,10 +124,10 @@ class OpenSSLException : public ExceptionCode errstack[n_err++] = err; ERR_error_string_n(err, buf, sizeof(buf)); auto reason = ERR_GET_REASON(err); - tmp << prefix << buf; + errtxt += prefix + buf; if (reason >= SSL_AD_REASON_OFFSET) { - tmp << "[" << SSL_alert_desc_string_long(reason - SSL_AD_REASON_OFFSET) << "]"; + errtxt += std::string{"["} + SSL_alert_desc_string_long(reason - SSL_AD_REASON_OFFSET) + "]"; } prefix = " / "; @@ -160,7 +153,7 @@ class OpenSSLException : public ExceptionCode case SSL_R_CA_KEY_TOO_SMALL: set_code(Error::SSL_CA_KEY_TOO_SMALL, true); break; -#if defined(SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED) +#ifdef SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED /* This error code has been added in OpenSSL 3.0.8 */ case SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED: set_code(Error::TLS_SIGALG_DISALLOWED_OR_UNSUPPORTED, true); @@ -201,7 +194,6 @@ class OpenSSLException : public ExceptionCode } } } - errtxt = tmp.str(); } void init_ssl_error(const int ssl_error, const char *error_text) @@ -224,10 +216,10 @@ class OpenSSLException : public ExceptionCode } } - size_t n_err; + size_t n_err = 0; unsigned long errstack[MAX_ERRORS]; std::string errtxt; - int ssl_err; + int ssl_err = -1; }; // return an OpenSSL error string diff --git a/openvpn/openssl/util/init.hpp b/openvpn/openssl/util/init.hpp deleted file mode 100644 index 08d9c630b..000000000 --- a/openvpn/openssl/util/init.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -#pragma once - -#include <openssl/opensslv.h> \ No newline at end of file diff --git a/openvpn/openssl/util/rand.hpp b/openvpn/openssl/util/rand.hpp index 4ea1feefc..e8ee18cfa 100644 --- a/openvpn/openssl/util/rand.hpp +++ b/openvpn/openssl/util/rand.hpp @@ -27,9 +27,7 @@ class OpenSSLRandom : public StrongRandomAPI public: OPENVPN_EXCEPTION(rand_error_openssl); - typedef RCPtr<OpenSSLRandom> Ptr; - - OpenSSLRandom() = default; + using Ptr = RCPtr<OpenSSLRandom>; std::string name() const override { diff --git a/openvpn/openssl/xkey/xkey_common.h b/openvpn/openssl/xkey/xkey_common.h index e004b2198..173b15d34 100644 --- a/openvpn/openssl/xkey/xkey_common.h +++ b/openvpn/openssl/xkey/xkey_common.h @@ -14,13 +14,13 @@ #ifndef XKEY_COMMON_H_ #define XKEY_COMMON_H_ -#if defined (__cplusplus) +#ifdef __cplusplus extern "C" { #endif /* Guard to only enable if OpenSSL is used and not trigger an error if mbed * TLS is compiled without OpenSSL being installed */ -#if defined(USE_OPENSSL) +#ifdef USE_OPENSSL #include <openssl/opensslv.h> #if OPENSSL_VERSION_NUMBER >= 0x30000010L && !defined(DISABLE_XKEY_PROVIDER) #define HAVE_XKEY_PROVIDER 1 @@ -131,7 +131,7 @@ void xkey_set_logging_cb_function(XKEY_LOGGING_CALLBACK_fn logfunc); #endif /* USE_OPENSSL */ -#if defined (__cplusplus) +#ifdef __cplusplus } #endif #endif /* XKEY_COMMON_H_ */ diff --git a/openvpn/openssl/xkey/xkey_provider.c b/openvpn/openssl/xkey/xkey_provider.c index 3483c230c..800b11c6a 100644 --- a/openvpn/openssl/xkey/xkey_provider.c +++ b/openvpn/openssl/xkey/xkey_provider.c @@ -533,15 +533,14 @@ keymgmt_set_params(void *keydata, const OSSL_PARAM *params) { return keymgmt_import_helper(key, params); } - else if (key->handle == NULL) /* once handle is set our key is immutable */ + if (key->handle == NULL) /* once handle is set our key is immutable */ { /* pubkey is always native -- just delegate */ return EVP_PKEY_set_params(key->pubkey, (OSSL_PARAM *)params); } - else - { - msg(M_WARN, "xkey keymgmt_set_params: key is immutable"); - } + + msg(M_WARN, "xkey keymgmt_set_params: key is immutable"); + return 1; } @@ -565,7 +564,7 @@ ec_keymgmt_name(int id) /* though we do not implement keyexch we could be queried for * keyexch mechanism supported by EC keys */ - else if (id == OSSL_OP_KEYEXCH) + if (id == OSSL_OP_KEYEXCH) { return "ECDH"; } diff --git a/openvpn/options/continuation.hpp b/openvpn/options/continuation.hpp index b425752be..c74cda94c 100644 --- a/openvpn/options/continuation.hpp +++ b/openvpn/options/continuation.hpp @@ -25,7 +25,7 @@ namespace openvpn { struct PushOptionsBase : public RC<thread_unsafe_refcount> { - typedef RCPtr<PushOptionsBase> Ptr; + using Ptr = RCPtr<PushOptionsBase>; OptionList merge; OptionList multi; @@ -35,7 +35,7 @@ struct PushOptionsBase : public RC<thread_unsafe_refcount> // Used by OptionListContinuation::finalize() to merge static and pushed options struct PushOptionsMerger : public RC<thread_unsafe_refcount> { - typedef RCPtr<PushOptionsMerger> Ptr; + using Ptr = RCPtr<PushOptionsMerger>; virtual void merge(OptionList &pushed, const OptionList &config) const = 0; }; @@ -169,20 +169,20 @@ class OptionListContinuation : public OptionList std::string &name = it->ref(0); // option prefixed with "-" should be removed - bool remove = string::starts_with(name, "-"); + const bool remove = name.starts_with("-"); if (remove) { name.erase(name.begin()); } // option prefixed with "?" is considered "optional" - bool optional = string::starts_with(name, "?"); + const bool optional = name.starts_with("?"); if (optional) { name.erase(name.begin()); } - if (updatable_options.find(name) == updatable_options.end()) + if (!updatable_options.contains(name)) { if (optional) { @@ -203,7 +203,7 @@ class OptionListContinuation : public OptionList else { // if upcoming updated option is not in update list, it should be removed from current options - if (update_list.find(name) == update_list.end()) + if (!update_list.contains(name)) { opts_to_remove.insert(name); } @@ -213,11 +213,10 @@ class OptionListContinuation : public OptionList } opts.update_map(); - erase(std::remove_if(begin(), end(), [&opts_to_remove](const Option &o) - { + erase_if(*this, [&opts_to_remove](const Option &o) + { const std::string &name = o.ref(0); - return opts_to_remove.find(name) != opts_to_remove.end(); }), - end()); + return opts_to_remove.contains(name); }); // we need to remove only original options, not the ones from ongoing PUSH_UPDATE // make sure that options are considered for removal only once diff --git a/openvpn/options/continuation_fragment.hpp b/openvpn/options/continuation_fragment.hpp index 14bffce32..895ae54b8 100644 --- a/openvpn/options/continuation_fragment.hpp +++ b/openvpn/options/continuation_fragment.hpp @@ -92,7 +92,7 @@ class PushContinuationFragment : public std::vector<BufferPtr> total_size += e->size(); // allocate return buffer - auto ret = BufferAllocatedRc::Create(total_size, 0); + auto ret = BufferAllocatedRc::Create(total_size); buf_append_string(*ret, prefix); // terminators @@ -106,7 +106,8 @@ class PushContinuationFragment : public std::vector<BufferPtr> { const Buffer &buf = *bv[i]; const char *pc = (i == size - 1) ? pc1 : pc2; - if (string::starts_with(buf, prefix_comma) && string::ends_with(buf, pc)) + const auto strbuf = buf_to_string(buf); + if (strbuf.starts_with(prefix_comma) && strbuf.ends_with(pc)) { Buffer b = buf; b.advance(prefix.size()); // advance past prefix @@ -124,7 +125,7 @@ class PushContinuationFragment : public std::vector<BufferPtr> void append_new_buffer(const std::string &prefix) { // include extra byte for null termination - auto bp = BufferAllocatedRc::Create(FRAGMENT_SIZE + 1, 0); + auto bp = BufferAllocatedRc::Create(FRAGMENT_SIZE + 1); buf_append_string(*bp, prefix); push_back(std::move(bp)); } diff --git a/openvpn/options/merge.hpp b/openvpn/options/merge.hpp index 91091969c..f399c6e45 100644 --- a/openvpn/options/merge.hpp +++ b/openvpn/options/merge.hpp @@ -199,8 +199,7 @@ class ProfileMerge max_size); if (pm.status() == ProfileMerge::MERGE_SUCCESS) return pm.profile_content(); - else - OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); + OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); } protected: @@ -253,7 +252,7 @@ class ProfileMerge else if (!OptionList::ignore_line(line)) { Option opt = Split::by_space<Option, OptionList::LexComment, SpaceMatch, Split::NullLimit>(line); - if (opt.size()) + if (!opt.empty()) { if (OptionList::is_open_tag(opt.ref(0)) && opt.size() == 1) { @@ -408,7 +407,7 @@ class ProfileMerge static bool is_fileref_directive(const std::string &d, unsigned int &flags) { - if (d.length() > 0) + if (!d.empty()) { switch (d[0]) { @@ -514,8 +513,7 @@ class ProfileMergeFromString : public ProfileMerge max_size); if (pm.status() == ProfileMerge::MERGE_SUCCESS) return pm.profile_content(); - else - OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); + OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); } }; } // namespace openvpn diff --git a/openvpn/options/pushlex.hpp b/openvpn/options/pushlex.hpp index 93d40170f..b28990944 100644 --- a/openvpn/options/pushlex.hpp +++ b/openvpn/options/pushlex.hpp @@ -38,7 +38,7 @@ class PushLex { if (!discard_prefix || !defined()) return; - if (!string::starts_with(buf_, "PUSH_")) + if (!buf_to_string(buf_).starts_with("PUSH_")) throw pushlex_error("not a valid PUSH_x message [1]"); buf_.advance(5); while (defined()) diff --git a/openvpn/options/sanitize.hpp b/openvpn/options/sanitize.hpp index a68758d28..a6153d592 100644 --- a/openvpn/options/sanitize.hpp +++ b/openvpn/options/sanitize.hpp @@ -30,10 +30,10 @@ inline std::string render_options_sanitized(const OptionList &opt, const unsigne const Option &o = opt[i]; #ifndef OPENVPN_SHOW_SESSION_TOKEN if (o.get_optional(0, 0) == "auth-token") - out << i << " [auth-token] ..." << std::endl; + out << i << " [auth-token] ...\n"; else #endif - out << i << ' ' << o.render(render_flags) << std::endl; + out << i << ' ' << o.render(render_flags) << '\n'; } return out.str(); } diff --git a/openvpn/ovpnagent/mac/ovpnagent.cpp b/openvpn/ovpnagent/mac/ovpnagent.cpp index 49c095b8b..530c85aac 100644 --- a/openvpn/ovpnagent/mac/ovpnagent.cpp +++ b/openvpn/ovpnagent/mac/ovpnagent.cpp @@ -62,7 +62,7 @@ void log_version() #ifdef OPENVPN_DEBUG << " built on " __DATE__ " " __TIME__ #endif - << std::endl; + << "\n"; } using namespace openvpn; @@ -80,7 +80,7 @@ class MySessionStats : public SessionStats std::string dump() const { std::ostringstream os; - os << "OpenVPN Agent Stats" << std::endl; + os << "OpenVPN Agent Stats\n"; return os.str(); } }; @@ -753,17 +753,17 @@ int main(int argc, char *argv[]) catch (const usage &) { log_version(); - std::cout << "usage: ovpnagent [options]" << std::endl; - std::cout << " --daemon <file>, -d : daemonize, log to file" << std::endl; - std::cout << " --append, -a : append to log file" << std::endl; - std::cout << " --pidfile <file>, -p : write pid to file" << std::endl; - std::cout << " --user <user>, -u : set UID to user" << std::endl; - std::cout << " --group <group>, -g : set group" << std::endl; + std::cout << "usage: ovpnagent [options]\n"; + std::cout << " --daemon <file>, -d : daemonize, log to file\n"; + std::cout << " --append, -a : append to log file\n"; + std::cout << " --pidfile <file>, -p : write pid to file\n"; + std::cout << " --user <user>, -u : set UID to user\n"; + std::cout << " --group <group>, -g : set group\n"; ret = 2; } catch (const std::exception &e) { - std::cout << "Main thread exception: " << e.what() << std::endl; + std::cout << "Main thread exception: " << e.what() << "\n"; ret = 1; } diff --git a/openvpn/ovpnagent/win/ovpnagent.cpp b/openvpn/ovpnagent/win/ovpnagent.cpp index 794274837..6a5a5107b 100644 --- a/openvpn/ovpnagent/win/ovpnagent.cpp +++ b/openvpn/ovpnagent/win/ovpnagent.cpp @@ -99,7 +99,7 @@ class MySessionStats : public SessionStats std::string dump() const { std::ostringstream os; - os << "OpenVPN Agent Stats" << std::endl; + os << "OpenVPN Agent Stats\n"; return os.str(); } }; @@ -180,18 +180,18 @@ class MyListener : public WS::Server::Listener FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) { - os << "destroy_tun: no client confirm, DuplicateHandle (close) succeeded" << std::endl; + os << "destroy_tun: no client confirm, DuplicateHandle (close) succeeded\n"; } else { const Win::LastError err; - os << "destroy_tun: no client confirm, DuplicateHandle (close) failed: " << err.message() << std::endl; + os << "destroy_tun: no client confirm, DuplicateHandle (close) failed: " << err.message() << "\n"; } } } catch (const std::exception &e) { - os << "destroy_tun: exception in remote tap handle close: " << e.what() << std::endl; + os << "destroy_tun: exception in remote tap handle close: " << e.what() << "\n"; } try @@ -207,7 +207,7 @@ class MyListener : public WS::Server::Listener } catch (const std::exception &e) { - os << "destroy_tun: exception in tun teardown: " << e.what() << std::endl; + os << "destroy_tun: exception in tun teardown: " << e.what() << "\n"; } try @@ -220,7 +220,7 @@ class MyListener : public WS::Server::Listener } catch (const std::exception &e) { - os << "destroy_tun: exception in cleanup: " << e.what() << std::endl; + os << "destroy_tun: exception in cleanup: " << e.what() << "\n"; } vpn_interface_index = DWORD(-1); return ret; @@ -577,7 +577,7 @@ class MyClientInstance : public WS::Server::Listener::Client // destroy previous instance if (parent()->destroy_tun(os)) { - os << "Destroyed previous TAP instance" << std::endl; + os << "Destroyed previous TAP instance\n"; ::Sleep(1000); } @@ -646,7 +646,7 @@ class MyClientInstance : public WS::Server::Listener::Client // destroy previous instance if (tun_type != TunWin::OvpnDco && parent()->destroy_tun(os)) { - os << "Destroyed previous TAP instance" << std::endl; + os << "Destroyed previous TAP instance\n"; ::Sleep(1000); } @@ -771,7 +771,7 @@ class MyClientInstance : public WS::Server::Listener::Client catch (const std::exception &e) { if (parent()->destroy_tun(os)) - os << "Destroyed previous TAP instance due to exception" << std::endl; + os << "Destroyed previous TAP instance due to exception\n"; const std::string error_msg = string::remove_blanks(os.str() + e.what() + '\n'); OPENVPN_LOG_NTNL("EXCEPTION\n" @@ -887,7 +887,7 @@ class MyService : public Win::Service } catch (const std::exception &e) { - std::cerr << e.what() << std::endl; + std::cerr << e.what() << "\n"; } } if (!log) @@ -998,20 +998,20 @@ int main(int argc, char *argv[]) else if (arg == "remove") serv.remove(); else if (arg == "modname") - std::wcout << Win::module_name() << std::endl; + std::wcout << Win::module_name() << "\n"; else if (arg == "help") { - std::cout << "usage: ovpnagent [options]" << std::endl; - std::cout << " run -- run in foreground (for debugging)" << std::endl; - std::cout << " install -- install as service" << std::endl; - std::cout << " remove -- uninstall" << std::endl; - std::cout << " modname -- show module name" << std::endl; - std::cout << " help -- show help message" << std::endl; - std::cout << " [default] -- start as service" << std::endl; + std::cout << "usage: ovpnagent [options]\n"; + std::cout << " run -- run in foreground (for debugging)\n"; + std::cout << " install -- install as service\n"; + std::cout << " remove -- uninstall\n"; + std::cout << " modname -- show module name\n"; + std::cout << " help -- show help message\n"; + std::cout << " [default] -- start as service\n"; } else { - std::cout << "unrecognized option, use 'help' for more info" << std::endl; + std::cout << "unrecognized option, use 'help' for more info\n"; ret = 2; } } @@ -1020,7 +1020,7 @@ int main(int argc, char *argv[]) } catch (const std::exception &e) { - std::cout << "ovpnagent: " << e.what() << std::endl; + std::cout << "ovpnagent: " << e.what() << "\n"; ret = 1; } diff --git a/openvpn/pki/cclist.hpp b/openvpn/pki/cclist.hpp index 7f0b5ed3d..170869dd6 100644 --- a/openvpn/pki/cclist.hpp +++ b/openvpn/pki/cclist.hpp @@ -32,9 +32,7 @@ class CertCRLListTemplate public: OPENVPN_EXCEPTION(parse_cert_crl_error); - CertCRLListTemplate() - { - } + CertCRLListTemplate() = default; explicit CertCRLListTemplate(const std::string &content, const std::string &title) { diff --git a/openvpn/pki/x509track.hpp b/openvpn/pki/x509track.hpp index 47e9199e0..02146bfbb 100644 --- a/openvpn/pki/x509track.hpp +++ b/openvpn/pki/x509track.hpp @@ -60,8 +60,7 @@ inline const char *name(const Type type) static_assert(N_TYPES == array_size(names), "x509 names array inconsistency"); if (type >= 0 && type < N_TYPES) return names[type]; - else - return "UNDEF"; + return "UNDEF"; } inline Type parse_type(const std::string &name) @@ -82,7 +81,7 @@ struct Config Config(const std::string &spec) { - full_chain = (spec.length() > 0 && spec[0] == '+'); + full_chain = (!spec.empty() && spec[0] == '+'); type = parse_type(spec.substr(full_chain ? 1 : 0)); if (type == UNDEF) throw Exception("cannot parse attribute '" + spec + "'"); @@ -108,9 +107,7 @@ struct Config struct ConfigSet : public std::vector<Config> { - ConfigSet() - { - } + ConfigSet() = default; ConfigSet(const OptionList &opt, const bool include_serial, diff --git a/openvpn/proxy/ntlm.hpp b/openvpn/proxy/ntlm.hpp index 24c31fa9c..7b7272906 100644 --- a/openvpn/proxy/ntlm.hpp +++ b/openvpn/proxy/ntlm.hpp @@ -67,15 +67,15 @@ class NTLM split_domain_username(dom_username, domain, username); // convert password from utf-8 to utf-16 and take an MD4 hash of it - BufferPtr password_u = Unicode::string_to_utf16(password); - DigestInstance::Ptr md4_ctx(digest_factory.new_digest(CryptoAlgs::MD4)); + const BufferPtr password_u = Unicode::string_to_utf16(password); + const DigestInstance::Ptr md4_ctx(digest_factory.new_digest(CryptoAlgs::MD4)); md4_ctx->update(password_u->c_data(), password_u->size()); unsigned char md4_hash[21]; md4_ctx->final(md4_hash); std::memset(md4_hash + 16, 0, 5); // pad to 21 bytes // decode phase_2_response from base64 to raw data - BufferAllocated response(phase_2_response.size(), 0); + BufferAllocated response(phase_2_response.size()); base64->decode(response, phase_2_response); if (response.size() < 32) @@ -90,8 +90,8 @@ class NTLM // convert to utf-16, and run it through HMAC-MD5 // keyed to md4_hash const std::string ud = string::to_upper_copy(username) + domain; - BufferPtr ud_u = Unicode::string_to_utf16(ud); - HMACInstance::Ptr hmac_ctx1(digest_factory.new_hmac(CryptoAlgs::MD5, md4_hash, 16)); + const BufferPtr ud_u = Unicode::string_to_utf16(ud); + const HMACInstance::Ptr hmac_ctx1(digest_factory.new_hmac(CryptoAlgs::MD5, md4_hash, 16)); hmac_ctx1->update(ud_u->c_data(), ud_u->size()); unsigned char ntlmv2_hash[16]; hmac_ctx1->final(ntlmv2_hash); @@ -109,7 +109,7 @@ class NTLM // add target information block to the blob size_t tib_len = 0; - if (response[0x16] & 0x80u) // check for Target Information block (TIB) + if (response[0x16] & 0x80U) // check for Target Information block (TIB) { tib_len = response[0x28]; // get TIB size if (tib_len > 96) @@ -132,7 +132,7 @@ class NTLM std::memcpy(&ntlmv2_response[8], challenge, 8); // hmac-md5 - HMACInstance::Ptr hmac_ctx2(digest_factory.new_hmac(CryptoAlgs::MD5, ntlmv2_hash, 16)); + const HMACInstance::Ptr hmac_ctx2(digest_factory.new_hmac(CryptoAlgs::MD5, ntlmv2_hash, 16)); hmac_ctx2->update(&ntlmv2_response[8], ntlmv2_blob_size + 8); unsigned char ntlmv2_hmacmd5[16]; hmac_ctx2->final(ntlmv2_hmacmd5); @@ -198,7 +198,7 @@ class NTLM static void split_domain_username(const std::string &combined, std::string &domain, std::string &username) { - typedef std::vector<std::string> StringList; + using StringList = std::vector<std::string>; StringList sl; sl.reserve(2); Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, combined, '\\', 1); diff --git a/openvpn/proxy/proxyauth.hpp b/openvpn/proxy/proxyauth.hpp index 32a7ebe81..d977d78e2 100644 --- a/openvpn/proxy/proxyauth.hpp +++ b/openvpn/proxy/proxyauth.hpp @@ -24,11 +24,9 @@ namespace openvpn::HTTPProxy { class ProxyAuthenticate : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<ProxyAuthenticate> Ptr; + using Ptr = RCPtr<ProxyAuthenticate>; - ProxyAuthenticate() - { - } + ProxyAuthenticate() = default; ProxyAuthenticate(const std::string &line) { @@ -45,8 +43,8 @@ class ProxyAuthenticate : public RC<thread_unsafe_refcount> std::string to_string() const { std::ostringstream out; - out << "Proxy-Authenticate header" << std::endl; - out << "method=" << method << std::endl; + out << "Proxy-Authenticate header\n"; + out << "method=" << method << '\n'; out << parms.to_string(); return out.str(); } @@ -58,7 +56,7 @@ class ProxyAuthenticate : public RC<thread_unsafe_refcount> void do_parse(const std::string &line) { std::vector<std::string> tuple = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(line, ' ', 0, 1); - if (tuple.size() >= 1) + if (!tuple.empty()) method = tuple[0]; if (tuple.size() == 2) { diff --git a/openvpn/random/mtrandapi.hpp b/openvpn/random/mtrandapi.hpp index 443a7578a..e7616e8d5 100644 --- a/openvpn/random/mtrandapi.hpp +++ b/openvpn/random/mtrandapi.hpp @@ -27,8 +27,8 @@ class MTRand : public WeakRandomAPI public: OPENVPN_EXCEPTION(mtrand_error); - typedef RCPtr<MTRand> Ptr; - typedef std::mt19937_64 rand_type; + using Ptr = RCPtr<MTRand>; + using rand_type = std::mt19937_64; MTRand(RandomAPI &seed) : rng(gen_seed(seed)) @@ -54,15 +54,19 @@ class MTRand : public WeakRandomAPI // Fill buffer with random bytes void rand_bytes(unsigned char *buf, size_t size) override { - if (!rndbytes(buf, size)) - throw mtrand_error("rand_bytes failed"); + while (size--) + *buf++ = rbs.get_byte(rng); } - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. + /** + * Like rand_bytes, but don't throw exception. At least that's the + * intent in the base class API. Here, neither function throws and + * we always return true (success). + **/ bool rand_bytes_noexcept(unsigned char *buf, size_t size) override { - return rndbytes(buf, size); + rand_bytes(buf, size); + return true; } rand_type::result_type rand() @@ -71,13 +75,6 @@ class MTRand : public WeakRandomAPI } private: - bool rndbytes(unsigned char *buf, size_t size) - { - while (size--) - *buf++ = rbs.get_byte(rng); - return true; - } - static rand_type::result_type gen_seed(RandomAPI &seed) { return seed.rand_get<rand_type::result_type>(); diff --git a/openvpn/random/rand2.hpp b/openvpn/random/rand2.hpp index 3a25639ae..0d29f00f5 100644 --- a/openvpn/random/rand2.hpp +++ b/openvpn/random/rand2.hpp @@ -20,9 +20,7 @@ namespace openvpn { // By convention, rng is crypto-strength while prng is not. struct Rand2 { - Rand2() - { - } + Rand2() = default; Rand2(StrongRandomAPI::Ptr rng_arg, RandomAPI::Ptr prng_arg) diff --git a/openvpn/random/randapi.hpp b/openvpn/random/randapi.hpp index 4b52f7c71..a6a84b88d 100644 --- a/openvpn/random/randapi.hpp +++ b/openvpn/random/randapi.hpp @@ -16,8 +16,9 @@ #pragma once -#include <string> #include <cstdint> +#include <limits> +#include <string> #include <type_traits> #include <openvpn/common/size.hpp> @@ -41,7 +42,7 @@ class RandomAPI : public RC<thread_unsafe_refcount> * @typedef RCPtr<RandomAPI> Ptr * @brief Smart pointer type for managing the ownership of RandomAPI objects */ - typedef RCPtr<RandomAPI> Ptr; + using Ptr = RCPtr<RandomAPI>; /** * @brief Get the name of the random number generation algorithm @@ -130,8 +131,7 @@ class RandomAPI : public RC<thread_unsafe_refcount> { if (start >= end) return start; - else - return start + rand_get_positive<T>() % (end - start + 1); + return start + rand_get_positive<T>() % (end - start + 1); } /** @@ -163,8 +163,7 @@ class RandomAPI : public RC<thread_unsafe_refcount> { if (start >= end) return start; - else - return start + randrange32(end - start + 1); + return start + randrange32(end - start + 1); } /** @@ -195,7 +194,7 @@ class RandomAPI : public RC<thread_unsafe_refcount> * See https://en.cppreference.com/w/cpp/named_req/UniformRandomBitGenerator */ ///@{ - typedef unsigned int result_type; + using result_type = unsigned int; static constexpr result_type min() { return result_type(0); @@ -230,7 +229,7 @@ class StrongRandomAPI : public RandomAPI * @typedef RCPtr<StrongRandomAPI> Ptr * @brief Smart pointer type for managing the ownership of StrongRandomAPI objects */ - typedef RCPtr<StrongRandomAPI> Ptr; + using Ptr = RCPtr<StrongRandomAPI>; }; /** @@ -247,7 +246,7 @@ class WeakRandomAPI : public RandomAPI * @typedef RCPtr<WeakRandomAPI> Ptr * @brief Smart pointer type for managing the ownership of WeakRandomAPI objects */ - typedef RCPtr<WeakRandomAPI> Ptr; + using Ptr = RCPtr<WeakRandomAPI>; }; } // namespace openvpn diff --git a/openvpn/random/randbytestore.hpp b/openvpn/random/randbytestore.hpp index adedf782d..ded295cb4 100644 --- a/openvpn/random/randbytestore.hpp +++ b/openvpn/random/randbytestore.hpp @@ -29,7 +29,7 @@ class RandomByteStore res.rt = rng(); n_bytes = SIZE; } - unsigned char ret = res.bytes[0]; + const unsigned char ret = res.bytes[0]; res.rt >>= 8; --n_bytes; return ret; diff --git a/openvpn/reliable/relack.hpp b/openvpn/reliable/relack.hpp index d6908966a..31511c843 100644 --- a/openvpn/reliable/relack.hpp +++ b/openvpn/reliable/relack.hpp @@ -30,7 +30,7 @@ class ReliableAck public: static constexpr size_t maximum_acks_ack_v1 = 8; static constexpr size_t maximum_acks_control_v1 = 4; - typedef reliable::id_t id_t; + using id_t = reliable::id_t; explicit ReliableAck() = default; size_t size() const; @@ -92,11 +92,11 @@ class ReliableAck */ void prepend(Buffer &buf, bool ackv1) { - size_t max_acks = ackv1 ? maximum_acks_ack_v1 : maximum_acks_control_v1; + const size_t max_acks = ackv1 ? maximum_acks_ack_v1 : maximum_acks_control_v1; size_t acks_added = 0; - while (acks_added < max_acks && data.size() > 0) + while (acks_added < max_acks && !data.empty()) { auto ack = data.front(); data.pop_front(); diff --git a/openvpn/reliable/relcommon.hpp b/openvpn/reliable/relcommon.hpp index 243ce79c5..ecf23df29 100644 --- a/openvpn/reliable/relcommon.hpp +++ b/openvpn/reliable/relcommon.hpp @@ -19,7 +19,7 @@ namespace openvpn { namespace reliable { -typedef std::uint32_t id_t; +using id_t = std::uint32_t; constexpr static std::size_t id_size = sizeof(id_t); } // namespace reliable @@ -28,7 +28,7 @@ template <typename PACKET> class ReliableMessageBase { public: - typedef reliable::id_t id_t; + using id_t = reliable::id_t; ReliableMessageBase() : id_(0), erased_(false) diff --git a/openvpn/reliable/relrecv.hpp b/openvpn/reliable/relrecv.hpp index 49389916f..10caa7e15 100644 --- a/openvpn/reliable/relrecv.hpp +++ b/openvpn/reliable/relrecv.hpp @@ -27,16 +27,16 @@ class ReliableRecvTemplate public: OPENVPN_SIMPLE_EXCEPTION(rel_next_sequenced_not_ready); - typedef reliable::id_t id_t; + using id_t = reliable::id_t; class Message : public ReliableMessageBase<PACKET> { friend class ReliableRecvTemplate; }; - ReliableRecvTemplate() - { - } + //! Default do-nothing constructor. + ReliableRecvTemplate() = default; + ReliableRecvTemplate(const id_t span, id_t start_at = 0) { init(span, start_at); diff --git a/openvpn/reliable/relsend.hpp b/openvpn/reliable/relsend.hpp index 736a2195e..f022a652b 100644 --- a/openvpn/reliable/relsend.hpp +++ b/openvpn/reliable/relsend.hpp @@ -26,7 +26,7 @@ template <typename PACKET> class ReliableSendTemplate { public: - typedef reliable::id_t id_t; + using id_t = reliable::id_t; class Message : public ReliableMessageBase<PACKET> { @@ -106,7 +106,7 @@ class ReliableSendTemplate const Message &msg = ref_by_id(i); if (msg.defined()) { - Time::Duration ut = msg.until_retransmit(now); + const Time::Duration ut = msg.until_retransmit(now); if (ut < ret) ret = ut; } diff --git a/openvpn/server/listenlist.hpp b/openvpn/server/listenlist.hpp index 90e47beaa..42d62d6cd 100644 --- a/openvpn/server/listenlist.hpp +++ b/openvpn/server/listenlist.hpp @@ -98,9 +98,7 @@ class List : public std::vector<Item> #endif }; - List() - { - } + List() = default; List(const Item &item) { @@ -169,13 +167,13 @@ class List : public std::vector<Item> int n_threads_exists = 0; { const std::string ntstr = o.get_optional(4 - local, 16); - if (ntstr.length() > 0 && string::is_digit(ntstr[0])) + if (!ntstr.empty() && string::is_digit(ntstr[0])) n_threads_exists = 1; } if (n_threads_exists) { std::string n_threads = o.get(4 - local, 16); - if (string::ends_with(n_threads, "*N")) + if (n_threads.ends_with("*N")) { mult = n_cores; n_threads = n_threads.substr(0, n_threads.length() - 2); diff --git a/openvpn/server/manage.hpp b/openvpn/server/manage.hpp index db55daac5..8d3e44883 100644 --- a/openvpn/server/manage.hpp +++ b/openvpn/server/manage.hpp @@ -48,7 +48,7 @@ namespace openvpn::ManClientInstance { // The methods here are VPN protocol agnostic. struct SendBase : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<SendBase> Ptr; + using Ptr = RCPtr<SendBase>; // clang-format off @@ -95,7 +95,7 @@ struct SendBase : public virtual RC<thread_unsafe_refcount> // protocol-specific methods. struct Send : public SendBase { - typedef RCPtr<Send> Ptr; + using Ptr = RCPtr<Send>; virtual void pre_stop() = 0; virtual void stop() = 0; @@ -127,7 +127,7 @@ struct Send : public SendBase // object will inherit from multiple receivers. struct Recv : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<Recv> Ptr; + using Ptr = RCPtr<Recv>; virtual void stop() = 0; @@ -167,7 +167,7 @@ struct Recv : public virtual RC<thread_unsafe_refcount> struct Factory : public RC<thread_unsafe_refcount> { - typedef RCPtr<Factory> Ptr; + using Ptr = RCPtr<Factory>; virtual void start() = 0; virtual void stop() = 0; diff --git a/openvpn/server/peeraddr.hpp b/openvpn/server/peeraddr.hpp index 436deb90e..49671e3ae 100644 --- a/openvpn/server/peeraddr.hpp +++ b/openvpn/server/peeraddr.hpp @@ -56,7 +56,7 @@ struct AddrPort struct PeerAddr : public RCCopyable<thread_unsafe_refcount> { - typedef RCPtr<PeerAddr> Ptr; + using Ptr = RCPtr<PeerAddr>; PeerAddr() : tcp(false) diff --git a/openvpn/server/servproto.hpp b/openvpn/server/servproto.hpp index de0676a86..7f3461d84 100644 --- a/openvpn/server/servproto.hpp +++ b/openvpn/server/servproto.hpp @@ -23,7 +23,6 @@ #include <openvpn/common/rc.hpp> #include <openvpn/common/unicode.hpp> #include <openvpn/common/link.hpp> -#include <openvpn/common/string.hpp> #include <openvpn/buffer/bufstream.hpp> #include <openvpn/time/asiotimer.hpp> #include <openvpn/time/coarsetime.hpp> @@ -43,9 +42,9 @@ namespace openvpn { class ServerProto { - typedef Link<TransportClientInstance::Send, TransportClientInstance::Recv> TransportLink; - typedef Link<TunClientInstance::Send, TunClientInstance::Recv> TunLink; - typedef Link<ManClientInstance::Send, ManClientInstance::Recv> ManLink; + using TransportLink = Link<TransportClientInstance::Send, TransportClientInstance::Recv>; + using TunLink = Link<TunClientInstance::Send, TunClientInstance::Recv>; + using ManLink = Link<ManClientInstance::Send, ManClientInstance::Recv>; public: class Session; @@ -53,32 +52,34 @@ class ServerProto class Factory : public TransportClientInstance::Factory { public: - typedef RCPtr<Factory> Ptr; - typedef ProtoContext::ProtoConfig ProtoConfig; + using Ptr = RCPtr<Factory>; + using ProtoConfig = ProtoContext::ProtoConfig; Factory(openvpn_io::io_context &io_context_arg, const ProtoConfig &c) : io_context(io_context_arg) { - if (c.tls_crypt_enabled()) - preval.reset(new ProtoContext::TLSCryptPreValidate(c, true)); - else if (c.tls_auth_enabled()) - preval.reset(new ProtoContext::TLSAuthPreValidate(c, true)); + if (c.tls_crypt_enabled() || c.tls_crypt_v2_enabled()) + tls_crypt_preval.reset(new ProtoContext::TLSCryptPreValidate(c, true)); + + if (c.tls_auth_enabled()) + tls_auth_preval.reset(new ProtoContext::TLSAuthPreValidate(c, true)); } TransportClientInstance::Recv::Ptr new_client_instance() override; bool validate_initial_packet(const BufferAllocated &net_buf) override { - if (preval) - { - const bool ret = preval->validate(net_buf); - if (!ret) - stats->error(Error::TLS_AUTH_FAIL); - return ret; - } - else + if (!tls_auth_preval && !tls_crypt_preval) return true; + + const bool ret = (tls_auth_preval && tls_auth_preval->validate(net_buf)) + || (tls_crypt_preval && tls_crypt_preval->validate(net_buf)); + + if (!ret) + stats->error(Error::TLS_AUTH_FAIL); + + return ret; } ProtoConfig::Ptr clone_proto_config() const @@ -95,7 +96,8 @@ class ServerProto SessionStats::Ptr stats; private: - ProtoContext::TLSWrapPreValidate::Ptr preval; + ProtoContext::TLSWrapPreValidate::Ptr tls_auth_preval; + ProtoContext::TLSWrapPreValidate::Ptr tls_crypt_preval; }; // This is the main server-side client instance object @@ -107,7 +109,7 @@ class ServerProto friend class Factory; // calls constructor public: - typedef RCPtr<Session> Ptr; + using Ptr = RCPtr<Session>; bool defined() const override { @@ -143,8 +145,7 @@ class ServerProto { if (TransportLink::send) return TransportLink::send->stats_poll(); - else - return PeerStats(); + return PeerStats(); } bool should_preserve_session_id() override @@ -210,7 +211,7 @@ class ServerProto { // data packet ret = proto_context.data_decrypt(pt, buf); - if (buf.size()) + if (!buf.empty()) { #ifdef OPENVPN_PACKET_LOG log_packet(buf, false); @@ -346,7 +347,7 @@ class ServerProto if (!Unicode::is_valid_utf8(msg, Unicode::UTF8_NO_CTRL)) { /* if we received invalid data from a client on the control channel terminate the connection */ - const auto reason = "Control channel message with invalid characters received"; + const std::string reason("Control channel message with invalid characters received"); auth_failed(reason, reason); return; } @@ -364,7 +365,7 @@ class ServerProto disconnect_type = DT_HALT_RESTART; disconnect_in(Time::Duration::seconds(1)); } - else if (string::starts_with(msg, "ACC,")) + else if (msg.starts_with("ACC,")) { if (get_management()) ManLink::send->app_control(msg); @@ -403,7 +404,7 @@ class ServerProto if (proto_context.primary_defined()) { - auto buf = BufferAllocatedRc::Create(64, 0); + auto buf = BufferAllocatedRc::Create(64); buf_append_string(*buf, "RELAY"); buf->null_terminate(); proto_context.control_send(std::move(buf)); @@ -447,8 +448,7 @@ class ServerProto { if (get_tun()) return TunLink::send->tun_native_handle(); - else - return TunClientInstance::NativeHandle(); + return TunClientInstance::NativeHandle(); } void push_halt_restart_msg(const HaltRestart::Type type, @@ -705,8 +705,7 @@ class ServerProto { if (TransportLink::send) return TransportLink::send->transport_info(); - else - return ""; + return ""; } void error(const std::string &error) @@ -743,8 +742,7 @@ class ServerProto { if (ManLink::send) return ManLink::send->instance_name(); - else - return "UNNAMED_CLIENT"; + return "UNNAMED_CLIENT"; } // higher values are higher priority diff --git a/openvpn/server/vpnservnetblock.hpp b/openvpn/server/vpnservnetblock.hpp index 898264920..60e15146c 100644 --- a/openvpn/server/vpnservnetblock.hpp +++ b/openvpn/server/vpnservnetblock.hpp @@ -29,9 +29,7 @@ class VPNServerNetblock struct Netblock { - Netblock() - { - } + Netblock() = default; Netblock(const IP::Route &route) { @@ -89,9 +87,7 @@ class VPNServerNetblock struct ClientNetblock : public Netblock { - ClientNetblock() - { - } + ClientNetblock() = default; ClientNetblock(const IP::Route &route) : Netblock(route) @@ -136,9 +132,7 @@ class VPNServerNetblock IP::Range range6_; }; - VPNServerNetblock() - { - } + VPNServerNetblock() = default; VPNServerNetblock(const OptionList &opt, const std::string &opt_name, @@ -232,9 +226,9 @@ class VPNServerNetblock std::string to_string() const { std::ostringstream os; - os << "IPv4: " << snb4.to_string() << std::endl; + os << "IPv4: " << snb4.to_string() << "\n"; if (snb6.defined()) - os << "IPv6: " << snb6.to_string() << std::endl; + os << "IPv6: " << snb6.to_string() << "\n"; for (size_t i = 0; i < thr.size(); ++i) { const PerThread &pt = thr[i]; @@ -242,7 +236,7 @@ class VPNServerNetblock os << " v4=" << pt.range4().to_string(); if (pt.range6_defined()) os << " v6=" << pt.range6().to_string(); - os << std::endl; + os << "\n"; } return os.str(); } diff --git a/openvpn/ssl/cn_reject_handler.hpp b/openvpn/ssl/cn_reject_handler.hpp index 1fff62c6a..92a04d544 100644 --- a/openvpn/ssl/cn_reject_handler.hpp +++ b/openvpn/ssl/cn_reject_handler.hpp @@ -23,7 +23,7 @@ namespace openvpn { class CommonNameReject { public: - typedef std::unique_ptr<CommonNameReject> UPtr; + using UPtr = std::unique_ptr<CommonNameReject>; /** * Should a leaf certificate having Common Name cn diff --git a/openvpn/ssl/customcontrolchannel.hpp b/openvpn/ssl/customcontrolchannel.hpp index d30092f14..0d1f885e5 100644 --- a/openvpn/ssl/customcontrolchannel.hpp +++ b/openvpn/ssl/customcontrolchannel.hpp @@ -197,7 +197,7 @@ class AppControlMessageReceiver throw parse_acc_message{"Discarding malformed custom app control message"}; } - for (char const &c : flags) + for (const char &c : flags) { switch (c) { diff --git a/openvpn/ssl/datalimit.hpp b/openvpn/ssl/datalimit.hpp index f9ca1b5ba..d3492f06c 100644 --- a/openvpn/ssl/datalimit.hpp +++ b/openvpn/ssl/datalimit.hpp @@ -22,7 +22,7 @@ namespace openvpn { class DataLimit { public: - typedef unsigned int size_type; + using size_type = unsigned int; enum Mode { @@ -115,10 +115,9 @@ class DataLimit flags |= mask; if ((mask & (ER | DG)) && ((flags & (ER | DG)) == (ER | DG))) return Red; - else if (mask & ER) + if (mask & ER) return None; - else - return state; + return state; } } return None; diff --git a/openvpn/ssl/iana_ciphers.hpp b/openvpn/ssl/iana_ciphers.hpp index b89221d15..9ba631fe4 100644 --- a/openvpn/ssl/iana_ciphers.hpp +++ b/openvpn/ssl/iana_ciphers.hpp @@ -22,131 +22,134 @@ struct tls_cipher_name_pair /** * SSL/TLS Cipher suite name translation table */ +// clang-format off static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { - {"ADH-SEED-SHA", "TLS-DH-anon-WITH-SEED-CBC-SHA"}, - {"AES128-GCM-SHA256", "TLS-RSA-WITH-AES-128-GCM-SHA256"}, - {"AES128-SHA256", "TLS-RSA-WITH-AES-128-CBC-SHA256"}, - {"AES128-SHA", "TLS-RSA-WITH-AES-128-CBC-SHA"}, - {"AES256-GCM-SHA384", "TLS-RSA-WITH-AES-256-GCM-SHA384"}, - {"AES256-SHA256", "TLS-RSA-WITH-AES-256-CBC-SHA256"}, - {"AES256-SHA", "TLS-RSA-WITH-AES-256-CBC-SHA"}, - {"CAMELLIA128-SHA256", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"CAMELLIA128-SHA", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"CAMELLIA256-SHA256", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"CAMELLIA256-SHA", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"DES-CBC3-SHA", "TLS-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"DES-CBC-SHA", "TLS-RSA-WITH-DES-CBC-SHA"}, - {"DH-DSS-SEED-SHA", "TLS-DH-DSS-WITH-SEED-CBC-SHA"}, - {"DHE-DSS-AES128-GCM-SHA256", "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256"}, - {"DHE-DSS-AES128-SHA256", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256"}, - {"DHE-DSS-AES128-SHA", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA"}, - {"DHE-DSS-AES256-GCM-SHA384", "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384"}, - {"DHE-DSS-AES256-SHA256", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256"}, - {"DHE-DSS-AES256-SHA", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA"}, - {"DHE-DSS-CAMELLIA128-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256"}, - {"DHE-DSS-CAMELLIA128-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA"}, - {"DHE-DSS-CAMELLIA256-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256"}, - {"DHE-DSS-CAMELLIA256-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-DSS-SEED-SHA", "TLS-DHE-DSS-WITH-SEED-CBC-SHA"}, - {"DHE-RSA-AES128-GCM-SHA256", "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"}, - {"DHE-RSA-AES128-SHA256", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"}, - {"DHE-RSA-AES128-SHA", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA"}, - {"DHE-RSA-AES256-GCM-SHA384", "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384"}, - {"DHE-RSA-AES256-SHA256", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256"}, - {"DHE-RSA-AES256-SHA", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA"}, - {"DHE-RSA-CAMELLIA128-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"DHE-RSA-CAMELLIA128-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"DHE-RSA-CAMELLIA256-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"DHE-RSA-CAMELLIA256-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-RSA-CHACHA20-POLY1305", "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"DHE-RSA-SEED-SHA", "TLS-DHE-RSA-WITH-SEED-CBC-SHA"}, - {"DH-RSA-SEED-SHA", "TLS-DH-RSA-WITH-SEED-CBC-SHA"}, - {"ECDH-ECDSA-AES128-GCM-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256"}, - {"ECDH-ECDSA-AES128-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256"}, - {"ECDH-ECDSA-AES128-SHA", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA"}, - {"ECDH-ECDSA-AES256-GCM-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384"}, - {"ECDH-ECDSA-AES256-SHA256", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA256"}, - {"ECDH-ECDSA-AES256-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384"}, - {"ECDH-ECDSA-AES256-SHA", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA"}, - {"ECDH-ECDSA-CAMELLIA128-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDH-ECDSA-CAMELLIA128-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDH-ECDSA-CAMELLIA256-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDH-ECDSA-CAMELLIA256-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDH-ECDSA-DES-CBC3-SHA", "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDH-ECDSA-DES-CBC-SHA", "TLS-ECDH-ECDSA-WITH-DES-CBC-SHA"}, - {"ECDH-ECDSA-RC4-SHA", "TLS-ECDH-ECDSA-WITH-RC4-128-SHA"}, - {"ECDHE-ECDSA-AES128-GCM-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"}, - {"ECDHE-ECDSA-AES128-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256"}, - {"ECDHE-ECDSA-AES128-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA384"}, - {"ECDHE-ECDSA-AES128-SHA", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA"}, - {"ECDHE-ECDSA-AES256-GCM-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384"}, - {"ECDHE-ECDSA-AES256-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA256"}, - {"ECDHE-ECDSA-AES256-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384"}, - {"ECDHE-ECDSA-AES256-SHA", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA"}, - {"ECDHE-ECDSA-CAMELLIA128-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDHE-ECDSA-CAMELLIA128-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDHE-ECDSA-CAMELLIA256-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDHE-ECDSA-CAMELLIA256-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDHE-ECDSA-CHACHA20-POLY1305", "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"ECDHE-ECDSA-DES-CBC3-SHA", "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDHE-ECDSA-DES-CBC-SHA", "TLS-ECDHE-ECDSA-WITH-DES-CBC-SHA"}, - {"ECDHE-ECDSA-RC4-SHA", "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA"}, - {"ECDHE-RSA-AES128-GCM-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256"}, - {"ECDHE-RSA-AES128-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256"}, - {"ECDHE-RSA-AES128-SHA384", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA384"}, - {"ECDHE-RSA-AES128-SHA", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA"}, - {"ECDHE-RSA-AES256-GCM-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"}, - {"ECDHE-RSA-AES256-SHA256", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA256"}, - {"ECDHE-RSA-AES256-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384"}, - {"ECDHE-RSA-AES256-SHA", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA"}, - {"ECDHE-RSA-CAMELLIA128-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDHE-RSA-CAMELLIA128-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDHE-RSA-CAMELLIA256-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDHE-RSA-CAMELLIA256-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDHE-RSA-CHACHA20-POLY1305", "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"ECDHE-RSA-DES-CBC3-SHA", "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDHE-RSA-DES-CBC-SHA", "TLS-ECDHE-RSA-WITH-DES-CBC-SHA"}, - {"ECDHE-RSA-RC4-SHA", "TLS-ECDHE-RSA-WITH-RC4-128-SHA"}, - {"ECDH-RSA-AES128-GCM-SHA256", "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256"}, - {"ECDH-RSA-AES128-SHA256", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256"}, - {"ECDH-RSA-AES128-SHA384", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA384"}, - {"ECDH-RSA-AES128-SHA", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA"}, - {"ECDH-RSA-AES256-GCM-SHA384", "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384"}, - {"ECDH-RSA-AES256-SHA256", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA256"}, - {"ECDH-RSA-AES256-SHA384", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384"}, - {"ECDH-RSA-AES256-SHA", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA"}, - {"ECDH-RSA-CAMELLIA128-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDH-RSA-CAMELLIA128-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDH-RSA-CAMELLIA256-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDH-RSA-CAMELLIA256-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDH-RSA-DES-CBC3-SHA", "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDH-RSA-DES-CBC-SHA", "TLS-ECDH-RSA-WITH-DES-CBC-SHA"}, - {"ECDH-RSA-RC4-SHA", "TLS-ECDH-RSA-WITH-RC4-128-SHA"}, - {"EDH-DSS-DES-CBC3-SHA", "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA"}, - {"EDH-DSS-DES-CBC-SHA", "TLS-DHE-DSS-WITH-DES-CBC-SHA"}, - {"EDH-RSA-DES-CBC3-SHA", "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"EDH-RSA-DES-CBC-SHA", "TLS-DHE-RSA-WITH-DES-CBC-SHA"}, - {"EXP-DES-CBC-SHA", "TLS-RSA-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-EDH-DSS-DES-CBC-SHA", "TLS-DH-DSS-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-EDH-RSA-DES-CBC-SHA", "TLS-DH-RSA-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-RC2-CBC-MD5", "TLS-RSA-EXPORT-WITH-RC2-CBC-40-MD5"}, - {"EXP-RC4-MD5", "TLS-RSA-EXPORT-WITH-RC4-40-MD5"}, - {"NULL-MD5", "TLS-RSA-WITH-NULL-MD5"}, - {"NULL-SHA256", "TLS-RSA-WITH-NULL-SHA256"}, - {"NULL-SHA", "TLS-RSA-WITH-NULL-SHA"}, - {"PSK-3DES-EDE-CBC-SHA", "TLS-PSK-WITH-3DES-EDE-CBC-SHA"}, - {"PSK-AES128-CBC-SHA", "TLS-PSK-WITH-AES-128-CBC-SHA"}, - {"PSK-AES256-CBC-SHA", "TLS-PSK-WITH-AES-256-CBC-SHA"}, - {"PSK-RC4-SHA", "TLS-PSK-WITH-RC4-128-SHA"}, - {"RC4-MD5", "TLS-RSA-WITH-RC4-128-MD5"}, - {"RC4-SHA", "TLS-RSA-WITH-RC4-128-SHA"}, - {"SEED-SHA", "TLS-RSA-WITH-SEED-CBC-SHA"}, - {"SRP-DSS-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-3DES-EDE-CBC-SHA"}, - {"SRP-DSS-AES-128-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-128-CBC-SHA"}, - {"SRP-DSS-AES-256-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-256-CBC-SHA"}, - {"SRP-RSA-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"SRP-RSA-AES-128-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA"}, - {"SRP-RSA-AES-256-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"}}; + {.openssl_name = "ADH-SEED-SHA", .iana_name = "TLS-DH-anon-WITH-SEED-CBC-SHA" }, + {.openssl_name = "AES128-GCM-SHA256", .iana_name = "TLS-RSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "AES128-SHA256", .iana_name = "TLS-RSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "AES128-SHA", .iana_name = "TLS-RSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "AES256-GCM-SHA384", .iana_name = "TLS-RSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "AES256-SHA256", .iana_name = "TLS-RSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "AES256-SHA", .iana_name = "TLS-RSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "CAMELLIA128-SHA256", .iana_name = "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "CAMELLIA128-SHA", .iana_name = "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "CAMELLIA256-SHA256", .iana_name = "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "CAMELLIA256-SHA", .iana_name = "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "DES-CBC3-SHA", .iana_name = "TLS-RSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "DES-CBC-SHA", .iana_name = "TLS-RSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "DH-DSS-SEED-SHA", .iana_name = "TLS-DH-DSS-WITH-SEED-CBC-SHA" }, + {.openssl_name = "DHE-DSS-AES128-GCM-SHA256", .iana_name = "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "DHE-DSS-AES128-SHA256", .iana_name = "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "DHE-DSS-AES128-SHA", .iana_name = "TLS-DHE-DSS-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "DHE-DSS-AES256-GCM-SHA384", .iana_name = "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "DHE-DSS-AES256-SHA256", .iana_name = "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "DHE-DSS-AES256-SHA", .iana_name = "TLS-DHE-DSS-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "DHE-DSS-CAMELLIA128-SHA256", .iana_name = "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "DHE-DSS-CAMELLIA128-SHA", .iana_name = "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "DHE-DSS-CAMELLIA256-SHA256", .iana_name = "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "DHE-DSS-CAMELLIA256-SHA", .iana_name = "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "DHE-DSS-SEED-SHA", .iana_name = "TLS-DHE-DSS-WITH-SEED-CBC-SHA" }, + {.openssl_name = "DHE-RSA-AES128-GCM-SHA256", .iana_name = "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "DHE-RSA-AES128-SHA256", .iana_name = "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "DHE-RSA-AES128-SHA", .iana_name = "TLS-DHE-RSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "DHE-RSA-AES256-GCM-SHA384", .iana_name = "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "DHE-RSA-AES256-SHA256", .iana_name = "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "DHE-RSA-AES256-SHA", .iana_name = "TLS-DHE-RSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "DHE-RSA-CAMELLIA128-SHA256", .iana_name = "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "DHE-RSA-CAMELLIA128-SHA", .iana_name = "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "DHE-RSA-CAMELLIA256-SHA256", .iana_name = "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "DHE-RSA-CAMELLIA256-SHA", .iana_name = "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "DHE-RSA-CHACHA20-POLY1305", .iana_name = "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256" }, + {.openssl_name = "DHE-RSA-SEED-SHA", .iana_name = "TLS-DHE-RSA-WITH-SEED-CBC-SHA" }, + {.openssl_name = "DH-RSA-SEED-SHA", .iana_name = "TLS-DH-RSA-WITH-SEED-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-AES128-GCM-SHA256", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "ECDH-ECDSA-AES128-SHA256", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "ECDH-ECDSA-AES128-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-AES256-GCM-SHA384", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "ECDH-ECDSA-AES256-SHA256", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "ECDH-ECDSA-AES256-SHA384", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384" }, + {.openssl_name = "ECDH-ECDSA-AES256-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-CAMELLIA128-SHA256", .iana_name = "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "ECDH-ECDSA-CAMELLIA128-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-CAMELLIA256-SHA256", .iana_name = "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "ECDH-ECDSA-CAMELLIA256-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-DES-CBC3-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-DES-CBC-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "ECDH-ECDSA-RC4-SHA", .iana_name = "TLS-ECDH-ECDSA-WITH-RC4-128-SHA" }, + {.openssl_name = "ECDHE-ECDSA-AES128-GCM-SHA256", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "ECDHE-ECDSA-AES128-SHA256", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "ECDHE-ECDSA-AES128-SHA384", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA384" }, + {.openssl_name = "ECDHE-ECDSA-AES128-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-AES256-GCM-SHA384", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "ECDHE-ECDSA-AES256-SHA256", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "ECDHE-ECDSA-AES256-SHA384", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384" }, + {.openssl_name = "ECDHE-ECDSA-AES256-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-CAMELLIA128-SHA256", .iana_name = "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "ECDHE-ECDSA-CAMELLIA128-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-CAMELLIA256-SHA256", .iana_name = "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "ECDHE-ECDSA-CAMELLIA256-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-CHACHA20-POLY1305", .iana_name = "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"}, + {.openssl_name = "ECDHE-ECDSA-DES-CBC3-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-DES-CBC-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "ECDHE-ECDSA-RC4-SHA", .iana_name = "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA" }, + {.openssl_name = "ECDHE-RSA-AES128-GCM-SHA256", .iana_name = "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "ECDHE-RSA-AES128-SHA256", .iana_name = "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "ECDHE-RSA-AES128-SHA384", .iana_name = "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA384" }, + {.openssl_name = "ECDHE-RSA-AES128-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-AES256-GCM-SHA384", .iana_name = "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "ECDHE-RSA-AES256-SHA256", .iana_name = "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "ECDHE-RSA-AES256-SHA384", .iana_name = "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" }, + {.openssl_name = "ECDHE-RSA-AES256-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-CAMELLIA128-SHA256", .iana_name = "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "ECDHE-RSA-CAMELLIA128-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-CAMELLIA256-SHA256", .iana_name = "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "ECDHE-RSA-CAMELLIA256-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-CHACHA20-POLY1305", .iana_name = "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" }, + {.openssl_name = "ECDHE-RSA-DES-CBC3-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-DES-CBC-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "ECDHE-RSA-RC4-SHA", .iana_name = "TLS-ECDHE-RSA-WITH-RC4-128-SHA" }, + {.openssl_name = "ECDH-RSA-AES128-GCM-SHA256", .iana_name = "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256" }, + {.openssl_name = "ECDH-RSA-AES128-SHA256", .iana_name = "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256" }, + {.openssl_name = "ECDH-RSA-AES128-SHA384", .iana_name = "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA384" }, + {.openssl_name = "ECDH-RSA-AES128-SHA", .iana_name = "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-AES256-GCM-SHA384", .iana_name = "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384" }, + {.openssl_name = "ECDH-RSA-AES256-SHA256", .iana_name = "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA256" }, + {.openssl_name = "ECDH-RSA-AES256-SHA384", .iana_name = "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384" }, + {.openssl_name = "ECDH-RSA-AES256-SHA", .iana_name = "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-CAMELLIA128-SHA256", .iana_name = "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256" }, + {.openssl_name = "ECDH-RSA-CAMELLIA128-SHA", .iana_name = "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-CAMELLIA256-SHA256", .iana_name = "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA256" }, + {.openssl_name = "ECDH-RSA-CAMELLIA256-SHA", .iana_name = "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-DES-CBC3-SHA", .iana_name = "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-DES-CBC-SHA", .iana_name = "TLS-ECDH-RSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "ECDH-RSA-RC4-SHA", .iana_name = "TLS-ECDH-RSA-WITH-RC4-128-SHA" }, + {.openssl_name = "EDH-DSS-DES-CBC3-SHA", .iana_name = "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "EDH-DSS-DES-CBC-SHA", .iana_name = "TLS-DHE-DSS-WITH-DES-CBC-SHA" }, + {.openssl_name = "EDH-RSA-DES-CBC3-SHA", .iana_name = "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "EDH-RSA-DES-CBC-SHA", .iana_name = "TLS-DHE-RSA-WITH-DES-CBC-SHA" }, + {.openssl_name = "EXP-DES-CBC-SHA", .iana_name = "TLS-RSA-EXPORT-WITH-DES40-CBC-SHA" }, + {.openssl_name = "EXP-EDH-DSS-DES-CBC-SHA", .iana_name = "TLS-DH-DSS-EXPORT-WITH-DES40-CBC-SHA" }, + {.openssl_name = "EXP-EDH-RSA-DES-CBC-SHA", .iana_name = "TLS-DH-RSA-EXPORT-WITH-DES40-CBC-SHA" }, + {.openssl_name = "EXP-RC2-CBC-MD5", .iana_name = "TLS-RSA-EXPORT-WITH-RC2-CBC-40-MD5" }, + {.openssl_name = "EXP-RC4-MD5", .iana_name = "TLS-RSA-EXPORT-WITH-RC4-40-MD5" }, + {.openssl_name = "NULL-MD5", .iana_name = "TLS-RSA-WITH-NULL-MD5" }, + {.openssl_name = "NULL-SHA256", .iana_name = "TLS-RSA-WITH-NULL-SHA256" }, + {.openssl_name = "NULL-SHA", .iana_name = "TLS-RSA-WITH-NULL-SHA" }, + {.openssl_name = "PSK-3DES-EDE-CBC-SHA", .iana_name = "TLS-PSK-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "PSK-AES128-CBC-SHA", .iana_name = "TLS-PSK-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "PSK-AES256-CBC-SHA", .iana_name = "TLS-PSK-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "PSK-RC4-SHA", .iana_name = "TLS-PSK-WITH-RC4-128-SHA" }, + {.openssl_name = "RC4-MD5", .iana_name = "TLS-RSA-WITH-RC4-128-MD5" }, + {.openssl_name = "RC4-SHA", .iana_name = "TLS-RSA-WITH-RC4-128-SHA" }, + {.openssl_name = "SEED-SHA", .iana_name = "TLS-RSA-WITH-SEED-CBC-SHA" }, + {.openssl_name = "SRP-DSS-3DES-EDE-CBC-SHA", .iana_name = "TLS-SRP-SHA-DSS-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "SRP-DSS-AES-128-CBC-SHA", .iana_name = "TLS-SRP-SHA-DSS-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "SRP-DSS-AES-256-CBC-SHA", .iana_name = "TLS-SRP-SHA-DSS-WITH-AES-256-CBC-SHA" }, + {.openssl_name = "SRP-RSA-3DES-EDE-CBC-SHA", .iana_name = "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA" }, + {.openssl_name = "SRP-RSA-AES-128-CBC-SHA", .iana_name = "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA" }, + {.openssl_name = "SRP-RSA-AES-256-CBC-SHA", .iana_name = "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA" } +}; +// clang-format on inline const tls_cipher_name_pair * tls_get_cipher_name_pair(const std::string &ciphername) diff --git a/openvpn/ssl/kuparse.hpp b/openvpn/ssl/kuparse.hpp index ddf489df2..75fd47e1c 100644 --- a/openvpn/ssl/kuparse.hpp +++ b/openvpn/ssl/kuparse.hpp @@ -59,10 +59,9 @@ inline TLSWebType remote_cert_type(const std::string &ct) { if (ct == "server") return TLS_WEB_SERVER; - else if (ct == "client") + if (ct == "client") return TLS_WEB_CLIENT; - else - throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-tls must be 'client' or 'server'"); + throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-tls must be 'client' or 'server'"); } inline void remote_cert_tls(const std::string &ct, @@ -98,19 +97,17 @@ inline void remote_cert_ku(const OptionList &opt, { if (o->empty()) throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-ku: no hex values specified"); - else if (o->size() >= 64) + if (o->size() >= 64) throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-ku: too many parameters"); - else + + try + { + for (size_t i = 1; i < o->size(); ++i) + ku.push_back(parse_hex_number<unsigned int>(o->get(i, 16))); + } + catch (parse_hex_error &) { - try - { - for (size_t i = 1; i < o->size(); ++i) - ku.push_back(parse_hex_number<unsigned int>(o->get(i, 16))); - } - catch (parse_hex_error &) - { - throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-ku: error parsing hex value list"); - } + throw option_error(ERR_INVALID_OPTION_CRYPTO, "remote-cert-ku: error parsing hex value list"); } } } diff --git a/openvpn/ssl/mssparms.hpp b/openvpn/ssl/mssparms.hpp index e7f2c5fd7..b422c7d4f 100644 --- a/openvpn/ssl/mssparms.hpp +++ b/openvpn/ssl/mssparms.hpp @@ -37,8 +37,7 @@ struct MSSParms mssfix_default = false; return; } - else - throw option_error(ERR_INVALID_OPTION_VAL, "mssfix must have a value"); + throw option_error(ERR_INVALID_OPTION_VAL, "mssfix must have a value"); } const bool status = parse_number_validate<decltype(mssfix)>(*val, diff --git a/openvpn/ssl/nscert.hpp b/openvpn/ssl/nscert.hpp index ae3c120c6..223bea50b 100644 --- a/openvpn/ssl/nscert.hpp +++ b/openvpn/ssl/nscert.hpp @@ -32,10 +32,9 @@ inline Type ns_cert_type(const std::string &ct) { if (ct == "server") return SERVER; - else if (ct == "client") + if (ct == "client") return CLIENT; - else - throw option_error(ERR_INVALID_OPTION_CRYPTO, "ns-cert-type must be 'client' or 'server'"); + throw option_error(ERR_INVALID_OPTION_CRYPTO, "ns-cert-type must be 'client' or 'server'"); } inline Type ns_cert_type(const OptionList &opt, const std::string &relay_prefix) diff --git a/openvpn/ssl/peer_fingerprint.hpp b/openvpn/ssl/peer_fingerprint.hpp index 73af123c8..82ccc4e07 100644 --- a/openvpn/ssl/peer_fingerprint.hpp +++ b/openvpn/ssl/peer_fingerprint.hpp @@ -65,7 +65,7 @@ struct PeerFingerprint output << v << ':'; std::string str(output.str()); - if (str.size()) + if (!str.empty()) str.erase(str.size() - 1); return str; @@ -99,10 +99,8 @@ struct PeerFingerprints while (std::getline(fps, fp)) { // Ignore empty lines and comments in fingerprint blocks - std::string trimmed = string::trim_copy(fp); - if (trimmed.empty() - || string::starts_with(trimmed, "#") - || string::starts_with(trimmed, ";")) + const std::string trimmed = string::trim_copy(fp); + if (trimmed.empty() || trimmed.starts_with("#") || trimmed.starts_with(";")) { continue; } diff --git a/openvpn/ssl/peerinfo.hpp b/openvpn/ssl/peerinfo.hpp index e8dfad905..48c83238d 100644 --- a/openvpn/ssl/peerinfo.hpp +++ b/openvpn/ssl/peerinfo.hpp @@ -53,7 +53,7 @@ struct KeyValue struct Set : public std::vector<KeyValue>, public RCCopyable<thread_unsafe_refcount> { - typedef RCPtr<Set> Ptr; + using Ptr = RCPtr<Set>; template <typename SET> static Ptr new_from_foreign_set(const SET &other) @@ -96,7 +96,7 @@ struct Set : public std::vector<KeyValue>, public RCCopyable<thread_unsafe_refco template <typename SET> static void parse_flexible(const std::string &src, SET &dest) { - if (src.length() >= 1 && src[0] == '@') + if (!src.empty() && src[0] == '@') { const std::string fn = src.substr(1); #ifdef OPENVPN_JSON_INTERNAL diff --git a/openvpn/ssl/proto.hpp b/openvpn/ssl/proto.hpp index 240204927..9fe1433a2 100644 --- a/openvpn/ssl/proto.hpp +++ b/openvpn/ssl/proto.hpp @@ -212,6 +212,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, protected: #endif static constexpr size_t APP_MSG_MAX = 65536; + static constexpr int OPCODE_SIZE = 1; enum { @@ -335,7 +336,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, class ProtoConfig : public RCCopyable<thread_unsafe_refcount> { public: - typedef RCPtr<ProtoConfig> Ptr; + using Ptr = RCPtr<ProtoConfig>; // master SSL context factory SSLFactoryAPI::Ptr ssl_factory; @@ -394,8 +395,14 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, Dynamic = (1 << 2) }; - //! leave this undefined to disable tls_auth/crypt - OpenVPNStaticKey tls_key; + //! leave this undefined to disable tls_auth + OpenVPNStaticKey tls_auth_key; + + //! leave this undefined to disable tls-crypt/tls-crypt-v2 + OpenVPNStaticKey tls_crypt_key; + + //! For TLS crypt V2, this (if defined()) is the wrapped WKc client key. + OpenVPNStaticKey wrapped_tls_crypt_key; //! needed to distinguish between tls-crypt and tls-crypt-v2 server mode unsigned tls_crypt_ = TLSCrypt::None; @@ -485,9 +492,9 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, if (!dev) throw proto_option_error(ERR_INVALID_CONFIG, "missing dev-type or dev option"); const std::string &dev_type = dev->get(1, 64); - if (string::starts_with(dev_type, "tun")) + if (dev_type.starts_with("tun")) layer = Layer(Layer::OSI_LAYER_3); - else if (string::starts_with(dev_type, "tap")) + else if (dev_type.starts_with("tap")) throw proto_option_error(ERR_INVALID_CONFIG, "TAP mode is not supported"); else throw proto_option_error(ERR_INVALID_OPTION_VAL, "bad dev-type"); @@ -531,10 +538,10 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const Option *o = opt.get_ptr(relay_prefix("tls-auth")); if (o) { - if (tls_crypt_context) + if (!server && tls_crypt_context) throw proto_option_error(ERR_INVALID_OPTION_CRYPTO, "tls-auth and tls-crypt are mutually exclusive"); - tls_key.parse(o->get(1, 0)); + tls_auth_key.parse(o->get(1, 0)); const Option *tad = opt.get_ptr(relay_prefix("tls-auth-digest")); if (tad) @@ -549,13 +556,13 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const Option *o = opt.get_ptr(relay_prefix("tls-crypt")); if (o) { - if (tls_auth_context) + if (!server && tls_auth_context) throw proto_option_error(ERR_INVALID_OPTION_CRYPTO, "tls-auth and tls-crypt are mutually exclusive"); if (tls_crypt_context) throw proto_option_error(ERR_INVALID_OPTION_CRYPTO, "tls-crypt and tls-crypt-v2 are mutually exclusive"); tls_crypt_ = TLSCrypt::V1; - tls_key.parse(o->get(1, 0)); + tls_crypt_key.parse(o->get(1, 0)); set_tls_crypt_algs(); } @@ -566,7 +573,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const Option *o = opt.get_ptr(relay_prefix("tls-crypt-v2")); if (o) { - if (tls_auth_context) + if (!server && tls_auth_context) throw proto_option_error(ERR_INVALID_OPTION_CRYPTO, "tls-auth and tls-crypt-v2 are mutually exclusive"); if (tls_crypt_context) throw proto_option_error(ERR_INVALID_OPTION_CRYPTO, "tls-crypt and tls-crypt-v2 are mutually exclusive"); @@ -581,7 +588,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // in client mode expect the key to be a PEM encoded tls-crypt-v2 client key (key + WKc) TLSCryptV2ClientKey tls_crypt_v2_key(tls_crypt_context); tls_crypt_v2_key.parse(keyfile); - tls_crypt_v2_key.extract_key(tls_key); + tls_crypt_v2_key.extract_key(tls_crypt_key); tls_crypt_v2_key.extract_wkc(wkc); } else @@ -591,7 +598,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // in server mode this is a PEM encoded tls-crypt-v2 server key TLSCryptV2ServerKey tls_crypt_v2_key; tls_crypt_v2_key.parse(keyfile); - tls_crypt_v2_key.extract_key(tls_key); + tls_crypt_v2_key.extract_key(tls_crypt_key); } } tls_crypt_ = TLSCrypt::V2; @@ -936,43 +943,43 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, if (dc.useEpochKeys()) os << ", aead-epoch"; - os << std::endl; + os << '\n'; } void show_cc_enc_option(std::ostringstream &os) const { if (tls_auth_enabled()) { - os << " control channel: tls-auth enabled" << std::endl; + os << " control channel: tls-auth enabled\n"; } if (tls_crypt_v2_enabled()) { - os << " control channel: tls-crypt v2 enabled" << std::endl; + os << " control channel: tls-crypt v2 enabled\n"; } else if (tls_crypt_enabled()) { - os << " control channel: tls-crypt enabled" << std::endl; + os << " control channel: tls-crypt enabled\n"; } else if (dynamic_tls_crypt_enabled()) { - os << " control channel: dynamic tls-crypt enabled" << std::endl; + os << " control channel: dynamic tls-crypt enabled\n"; } } std::string show_options() const { std::ostringstream os; - os << "PROTOCOL OPTIONS:" << std::endl; - os << " key-derivation: " << CryptoAlgs::name(dc.key_derivation()) << std::endl; + os << "PROTOCOL OPTIONS:\n"; + os << " key-derivation: " << CryptoAlgs::name(dc.key_derivation()) << '\n'; if (comp_ctx.type() != CompressContext::NONE) - os << " compress: " << comp_ctx.str() << std::endl; + os << " compress: " << comp_ctx.str() << '\n'; show_cc_enc_option(os); get_data_channel_options(os); if (!app_control_config.supported_protocols.empty()) { - os << " app custom control channel: " << app_control_config.str() << std::endl; + os << " app custom control channel: " << app_control_config.str() << '\n'; } return os.str(); @@ -1013,17 +1020,17 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, bool tls_auth_enabled() const { - return tls_key.defined() && tls_auth_context; + return tls_auth_key.defined() && tls_auth_context; } bool tls_crypt_enabled() const { - return tls_key.defined() && (tls_crypt_ & TLSCrypt::V1); + return tls_crypt_key.defined() && (tls_crypt_ & TLSCrypt::V1); } bool tls_crypt_v2_enabled() const { - return (tls_key.defined() || tls_crypt_v2_serverkey_id) && (tls_crypt_ & TLSCrypt::V2); + return (tls_crypt_key.defined() || tls_crypt_v2_serverkey_id) && (tls_crypt_ & TLSCrypt::V2); } bool dynamic_tls_crypt_enabled() const @@ -1173,8 +1180,8 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const std::string ret = out.str(); - OVPN_LOG_INFO("Sending Peer Info:" << std::endl - << ret); + OVPN_LOG_INFO("Sending Peer Info:\n" + << ret); return ret; } @@ -1358,10 +1365,11 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, break; } case CONTROL_HARD_RESET_SERVER_V2: + if (proto.is_server()) + return; + [[fallthrough]]; case CONTROL_WKC_V1: { - if (proto.is_server()) - return; flags |= CONTROL; opcode = opc; break; @@ -1520,14 +1528,13 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, static uint16_t read_uint16_length(Buffer &buf) { - if (buf.size()) + if (!buf.empty()) { std::uint16_t net_size; buf.read((unsigned char *)&net_size, sizeof(net_size)); return ntohs(net_size); } - else - return 0; + return 0; } template <typename S> @@ -1595,12 +1602,11 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, void write_control_string(const S &str) { const size_t len = str.length(); - auto bp = BufferAllocatedRc::Create(len + 1, 0); + auto bp = BufferAllocatedRc::Create(len + 1); write_control_string(str, *bp); control_send(std::move(bp)); } - protected: // Packet structure for managing network packets, passed as a template // parameter to ProtoStackBase class Packet @@ -1675,10 +1681,10 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // ProtoStackBase uses CRTP-based static polymorphism for method callbacks. class KeyContext : ProtoStackBase<Packet, KeyContext>, public RC<thread_unsafe_refcount> { - typedef ProtoStackBase<Packet, KeyContext> Base; + using Base = ProtoStackBase<Packet, KeyContext>; friend Base; - typedef Base::ReliableSend ReliableSend; - typedef Base::ReliableRecv ReliableRecv; + using ReliableSend = Base::ReliableSend; + using ReliableRecv = Base::ReliableRecv; // ProtoStackBase protected vars using Base::now; @@ -1695,16 +1701,12 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // for example if cipher/digest are pushed. struct DataChannelKey { - DataChannelKey() - { - } - OpenVPNStaticKey key; std::optional<CryptoDCInstance::RekeyType> rekey_type; }; public: - typedef RCPtr<KeyContext> Ptr; + using Ptr = RCPtr<KeyContext>; // ProtoStackBase member functions using Base::export_key_material; @@ -1892,8 +1894,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const Time t = Base::next_retransmit(); if (t <= next_event_time) return t; - else - return next_event_time; + return next_event_time; } void app_send_validate(BufferPtr &&bp) @@ -2021,8 +2022,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { if (next_event == KEV_BECOME_PRIMARY) return next_event_time; - else - return Time(); + return Time(); } // is an KEV_x event pending? @@ -2357,6 +2357,155 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, return state; } + /** + * @brief Extract and process the TLS crypt WKc information. + * @param recv Buffer containing the raw packet. + * @param proto_config Config object holding the settings needed for processing. + * This function may write to proto_config.tls_crypt_key, so + * we can't use a const reference here. + * @param tls_crypt_server Server context used only to process incoming WKc's. + * @param tls_crypt_metadata If not nullptr, the function will also check the validity + * of the WKc metadata. + * @return Error::SUCCESS on success. + */ + static Error::Type unwrap_tls_crypt_wkc(Buffer &recv, + ProtoConfig &proto_config, + TLSCryptInstance &tls_crypt_server, + TLSCryptMetadata::Ptr tls_crypt_metadata = nullptr) + { + // the ``WKc`` is located at the end of the packet, after the tls-crypt + // payload. + // + // K_id is optional, and controlled by proto_config.tls_crypt_v2_serverkey_id. + // If it is missing, we will use a single server key for all clients. + // + // Format is as follows: + // + // ``len = len(WKc)`` (16 bit, network byte order) + // ``T = HMAC-SHA256(Ka, len || K_id || Kc || metadata)`` + // ``IV = 128 most significant bits of T`` + // ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || K_id || len`` + + const unsigned char *orig_data = recv.data(); + const size_t orig_size = recv.size(); + const size_t hmac_size = proto_config.tls_crypt_context->digest_size(); + const size_t tls_frame_size = OPCODE_SIZE + ProtoSessionID::SIZE + + PacketIDControl::size() + + hmac_size + // the following is the tls-crypt payload + + sizeof(char) // length of ACK array + + sizeof(id_t); // reliable ID + + // check that at least the authentication tag ``T`` is present + if (orig_size < (tls_frame_size + hmac_size)) + return Error::CC_ERROR; + + // the ``WKc`` is just appended after the standard tls-crypt frame + const unsigned char *wkc_raw = orig_data + tls_frame_size; + size_t wkc_raw_size = orig_size - tls_frame_size - sizeof(uint16_t); + // retrieve the ``WKc`` len from the bottom of the packet and convert it to Host Order + uint16_t wkc_len; + // avoid unaligned access + std::memcpy(&wkc_len, wkc_raw + wkc_raw_size, sizeof(wkc_len)); + wkc_len = ntohs(wkc_len); + + // There's also a payload here, so the assumption that the difference in size + // from the TLS frame's end to the end of the packet constitutes the WKc no + // longer holds. We can only rely on wkc_len for P_CONTROL_WKC_V1 packets. + if (opcode_extract(orig_data[0]) != CONTROL_HARD_RESET_CLIENT_V3) + { + wkc_raw = orig_data + orig_size - wkc_len; + wkc_raw_size = wkc_len - sizeof(uint16_t); + } + + uint32_t k_id = 0; + const size_t serverkey_id_size = proto_config.tls_crypt_v2_serverkey_id ? sizeof(k_id) : 0; + + if (proto_config.tls_crypt_v2_serverkey_id) + { + std::memcpy(&k_id, wkc_raw + wkc_raw_size - serverkey_id_size, sizeof(k_id)); + k_id = ntohl(k_id); + } + + // length sanity check (the size of the ``len`` field is included in the value) + if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size) + return Error::CC_ERROR; + + BufferAllocated plaintext(wkc_len, BufAllocFlags::CONSTRUCT_ZERO); + // plaintext will be used to compute the Auth Tag, therefore start by prepending + // the WKc length in network order + const uint16_t net_wkc_len = htons(wkc_len); + plaintext.write(&net_wkc_len, sizeof(net_wkc_len)); + + if (proto_config.tls_crypt_v2_serverkey_id) + { + std::stringstream ss; + ss << std::hex << std::setfill('0') << std::uppercase << std::setw(8) << k_id; + + const std::string serverkey_fn = ss.str() + ".key"; + const std::string serverkey_path = proto_config.tls_crypt_v2_serverkey_dir + "/" + + serverkey_fn.substr(0, 2) + "/" + serverkey_fn; + + // If the key is missing, an exception will be thrown here, for example: + // "cannot open for read: <KEYS_DIR>/06/063FE634.key" + const std::string serverkey = read_text(serverkey_path); + + OVPN_LOG_VERBOSE("Using TLS-crypt-V2 server key " << serverkey_path); + + TLSCryptV2ServerKey tls_crypt_v2_key; + tls_crypt_v2_key.parse(serverkey); + tls_crypt_v2_key.extract_key(proto_config.tls_crypt_key); + + // the server key is composed by one key set only, therefore direction and + // mode should not be specified when slicing + tls_crypt_server.init(proto_config.ssl_factory->libctx(), + proto_config.tls_crypt_key.slice(OpenVPNStaticKey::HMAC), + proto_config.tls_crypt_key.slice(OpenVPNStaticKey::CIPHER)); + + k_id = htonl(k_id); + plaintext.write(&k_id, sizeof(k_id)); + } + + if (plaintext.max_size() <= 2 + serverkey_id_size) + return Error::DECRYPT_ERROR; + + const size_t decrypt_bytes = tls_crypt_server.decrypt(wkc_raw, + plaintext.data() + 2 + serverkey_id_size, + plaintext.max_size() - 2 - serverkey_id_size, + wkc_raw + hmac_size, + wkc_raw_size - hmac_size - serverkey_id_size); + plaintext.inc_size(decrypt_bytes); + // decrypted data must at least contain a full 2048bits client key + // (metadata is optional) + if (plaintext.size() < OpenVPNStaticKey::KEY_SIZE) + return Error::DECRYPT_ERROR; + + if (!tls_crypt_server.hmac_cmp(wkc_raw, 0, plaintext.c_data(), plaintext.size())) + return Error::HMAC_ERROR; + + // we can now remove the WKc length (and the server key ID, if present) + // from the plaintext, as they are not really part of the key material + plaintext.advance(sizeof(wkc_len)); + + if (proto_config.tls_crypt_v2_serverkey_id) + plaintext.advance(sizeof(k_id)); + + plaintext.read(proto_config.wrapped_tls_crypt_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE); + + // verify metadata + int metadata_type = -1; + if (!plaintext.empty()) + metadata_type = plaintext.pop_front(); + + if (tls_crypt_metadata && !tls_crypt_metadata->verify(metadata_type, plaintext)) + return Error::TLS_CRYPT_META_FAIL; + + // virtually remove the WKc from the packet + recv.set_size(orig_size - wkc_len); + + return Error::SUCCESS; + } + private: static bool validate_tls_auth(Buffer &recv, ProtoContext &proto, TimePtr now) { @@ -2374,7 +2523,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, recv.advance(proto.hmac_size); if (!proto.ta_hmac_recv->ovpn_hmac_cmp(orig_data, orig_size, - 1 + ProtoSessionID::SIZE, + OPCODE_SIZE + ProtoSessionID::SIZE, proto.hmac_size, PacketIDControl::size())) { @@ -2420,7 +2569,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, recv.advance(proto.hmac_size); - const size_t head_size = 1 + ProtoSessionID::SIZE + PacketIDControl::size(); + const size_t head_size = OPCODE_SIZE + ProtoSessionID::SIZE + PacketIDControl::size(); const size_t data_offset = head_size + proto.hmac_size; if (orig_size < data_offset) return false; @@ -2710,16 +2859,13 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { return CONTROL_SOFT_RESET_V1; } - else - { - if (proto.is_server() == sender) - return CONTROL_HARD_RESET_SERVER_V2; - if (!tls_crypt_v2) - return CONTROL_HARD_RESET_CLIENT_V2; - else - return CONTROL_HARD_RESET_CLIENT_V3; - } + if (proto.is_server() == sender) + return CONTROL_HARD_RESET_SERVER_V2; + + if (!tls_crypt_v2) + return CONTROL_HARD_RESET_CLIENT_V2; + return CONTROL_HARD_RESET_CLIENT_V3; } void send_reset() @@ -2873,7 +3019,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, if (!proto.is_server()) { OVPN_LOG_INFO("Tunnel Options:" << options); - buf->or_flags(BufAllocFlags::DESTRUCT_ZERO); + buf->add_flags(BufAllocFlags::DESTRUCT_ZERO); if (proto.config->xmit_creds) proto.client_auth(*buf); else @@ -2927,7 +3073,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, void active() { - OVPN_LOG_INFO("SSL Handshake: " << Base::ssl_handshake_details()); + OVPN_LOG_INFO("TLS Handshake: " << Base::ssl_handshake_details()); /* Our internal state machine only decides after push request what protocol * options we want to use. Therefore we also have to postpone data key @@ -3015,7 +3161,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // write hmac proto.ta_hmac_send->ovpn_hmac_gen(buf.data(), buf.size(), - 1 + ProtoSessionID::SIZE, + OPCODE_SIZE + ProtoSessionID::SIZE, proto.hmac_size, PacketIDControl::size()); } @@ -3162,7 +3308,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // was packet accepted by reliable receive object? if (rflags & ReliableRecv::IN_WINDOW) { - // remember tls_auth packet ID so that it can't be replaye + // remember tls_auth packet ID so that it can't be replayed proto.ta_pid_recv.test_add(pid, t, true); return true; } @@ -3203,7 +3349,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, recv.advance(proto.hmac_size); if (!proto.ta_hmac_recv->ovpn_hmac_cmp(orig_data, orig_size, - 1 + ProtoSessionID::SIZE, + OPCODE_SIZE + ProtoSessionID::SIZE, proto.hmac_size, PacketIDControl::size())) { @@ -3319,160 +3465,28 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, return false; } - /** - * @brief Extract and process the TLS crypt WKc information. - * @param recv Buffer containing the raw packet. - * @return true on success. - */ - bool unwrap_tls_crypt_wkc(Buffer &recv) + bool decapsulate(Packet &pkt) // called by ProtoStackBase { - // the ``WKc`` is located at the end of the packet, after the tls-crypt - // payload. - // - // K_id is optional, and controlled by proto.config->tls_crypt_v2_serverkey_id. - // If it is missing, we will use a single server key for all clients. - // - // Format is as follows: - // - // ``len = len(WKc)`` (16 bit, network byte order) - // ``T = HMAC-SHA256(Ka, len || K_id || Kc || metadata)`` - // ``IV = 128 most significant bits of T`` - // ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || K_id || len`` - - const unsigned char *orig_data = recv.data(); - const size_t orig_size = recv.size(); - const size_t hmac_size = proto.config->tls_crypt_context->digest_size(); - const size_t tls_frame_size = 1 + ProtoSessionID::SIZE - + PacketIDControl::size() - + hmac_size - // the following is the tls-crypt payload - + sizeof(char) // length of ACK array - + sizeof(id_t); // reliable ID - - // check that at least the authentication tag ``T`` is present - if (orig_size < (tls_frame_size + hmac_size)) - return false; - - // the ``WKc`` is just appended after the standard tls-crypt frame - const unsigned char *wkc_raw = orig_data + tls_frame_size; - const size_t wkc_raw_size = orig_size - tls_frame_size - sizeof(uint16_t); - // retrieve the ``WKc`` len from the bottom of the packet and convert it to Host Order - uint16_t wkc_len; - // avoid unaligned access - std::memcpy(&wkc_len, wkc_raw + wkc_raw_size, sizeof(wkc_len)); - wkc_len = ntohs(wkc_len); - - uint32_t k_id = 0; - const size_t serverkey_id_size = proto.config->tls_crypt_v2_serverkey_id ? sizeof(k_id) : 0; - - if (proto.config->tls_crypt_v2_serverkey_id) - { - std::memcpy(&k_id, wkc_raw + wkc_raw_size - serverkey_id_size, sizeof(k_id)); - k_id = ntohl(k_id); - } - - // length sanity check (the size of the ``len`` field is included in the value) - if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size) - return false; - - BufferAllocated plaintext(wkc_len, BufAllocFlags::CONSTRUCT_ZERO); - // plaintext will be used to compute the Auth Tag, therefore start by prepending - // the WKc length in network order - wkc_len = htons(wkc_len); - plaintext.write(&wkc_len, sizeof(wkc_len)); - - if (proto.config->tls_crypt_v2_serverkey_id) - { - std::stringstream ss; - ss << std::hex << std::setfill('0') << std::uppercase << std::setw(8) << k_id; - - const std::string serverkey_fn = ss.str() + ".key"; - const std::string serverkey_path = proto.config->tls_crypt_v2_serverkey_dir + "/" - + serverkey_fn.substr(0, 2) + "/" + serverkey_fn; - - // If the key is missing, an exception will be thrown here, for example: - // "cannot open for read: <KEYS_DIR>/06/063FE634.key" - const std::string serverkey = read_text(serverkey_path); - - OVPN_LOG_VERBOSE(proto.debug_prefix() << " Using TLS-crypt-V2 server key " << serverkey_path); - - TLSCryptV2ServerKey tls_crypt_v2_key; - tls_crypt_v2_key.parse(serverkey); - tls_crypt_v2_key.extract_key(proto.config->tls_key); - - // the server key is composed by one key set only, therefore direction and - // mode should not be specified when slicing - proto.tls_crypt_server->init(proto.config->ssl_factory->libctx(), - proto.config->tls_key.slice(OpenVPNStaticKey::HMAC), - proto.config->tls_key.slice(OpenVPNStaticKey::CIPHER)); - - k_id = htonl(k_id); - plaintext.write(&k_id, sizeof(k_id)); - } - - const size_t decrypt_bytes = proto.tls_crypt_server->decrypt(wkc_raw, - plaintext.data() + 2 + serverkey_id_size, - plaintext.max_size() - 2 - serverkey_id_size, - wkc_raw + hmac_size, - wkc_raw_size - hmac_size - serverkey_id_size); - plaintext.inc_size(decrypt_bytes); - // decrypted data must at least contain a full 2048bits client key - // (metadata is optional) - if (plaintext.size() < OpenVPNStaticKey::KEY_SIZE) - { - proto.stats->error(Error::DECRYPT_ERROR); - if (proto.is_tcp()) - invalidate(Error::DECRYPT_ERROR); - return false; - } - - if (!proto.tls_crypt_server->hmac_cmp(wkc_raw, - 0, - plaintext.c_data(), - plaintext.size())) - { - proto.stats->error(Error::HMAC_ERROR); - if (proto.is_tcp()) - invalidate(Error::HMAC_ERROR); - return false; - } - - // we can now remove the WKc length (and the server key ID, if present) - // from the plaintext, as they are not really part of the key material - plaintext.advance(sizeof(wkc_len)); - - if (proto.config->tls_crypt_v2_serverkey_id) - plaintext.advance(sizeof(k_id)); - - // WKc has been authenticated: it contains the client key followed - // by the optional metadata. Let's initialize the tls-crypt context - // with the client key - - OpenVPNStaticKey client_key; - plaintext.read(client_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE); - proto.reset_tls_crypt(*proto.config, client_key); - - // verify metadata - int metadata_type = -1; - if (!plaintext.empty()) - metadata_type = plaintext.pop_front(); - - if (!proto.tls_crypt_metadata->verify(metadata_type, plaintext)) + try { - proto.stats->error(Error::TLS_CRYPT_META_FAIL); - return false; - } + if (proto.is_server() + && proto.tls_wrap_mode != TLS_CRYPT_V2 + && proto.config->tls_crypt_v2_enabled() + && (pkt.opcode == CONTROL_HARD_RESET_CLIENT_V3 || pkt.opcode == CONTROL_WKC_V1)) + { + // setup key to be used to unwrap WKc upon client connection. + // tls-crypt session key setup is postponed to reception of WKc + // from client + proto.reset_tls_crypt_server(*proto.config); - // virtually remove the WKc from the packet - recv.set_size(tls_frame_size); + proto.tls_wrap_mode = TLS_CRYPT_V2; + proto.hmac_size = proto.config->tls_crypt_context->digest_size(); - return true; - } + // init tls_crypt packet ID + proto.ta_pid_send.init(EARLY_NEG_START); + proto.ta_pid_recv.init("SSL-CC", 0, proto.stats); + } - bool decapsulate(Packet &pkt) // called by ProtoStackBase - { - try - { switch (proto.tls_wrap_mode) { case TLS_AUTH: @@ -3483,10 +3497,32 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // unwrap WKc and extract Kc (client key) from packet. // This way we can initialize the tls-crypt per-client contexts // (this happens on the server side only) - if (!unwrap_tls_crypt_wkc(*pkt.buf)) + OpenVPNStaticKey client_key; + const Error::Type unwrap_wkc_result = unwrap_tls_crypt_wkc(*pkt.buf, + *proto.config, + *proto.tls_crypt_server, + proto.tls_crypt_metadata); + switch (unwrap_wkc_result) { + case Error::DECRYPT_ERROR: + case Error::HMAC_ERROR: + proto.stats->error(unwrap_wkc_result); + if (proto.is_tcp()) + invalidate(unwrap_wkc_result); + return false; + case Error::TLS_CRYPT_META_FAIL: + proto.stats->error(unwrap_wkc_result); + return false; + case Error::SUCCESS: + break; + default: return false; } + + // WKc has been authenticated: it contains the client key followed + // by the optional metadata. Let's initialize the tls-crypt context + // with the client key + proto.reset_tls_crypt(*proto.config, proto.config->wrapped_tls_crypt_key); } // now that the tls-crypt contexts have been initialized it is // possible to proceed with the standard tls-crypt decapsulation @@ -3497,7 +3533,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, return decapsulate_tls_plain(pkt); } } - catch (BufferException &) + catch (const BufferException &) { proto.stats->error(Error::BUFFER_ERROR); if (proto.is_tcp()) @@ -3544,8 +3580,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, Time::Duration d = next_time - *now; if (d.is_infinite()) return -1; - else - return numeric_cast<int>(d.to_seconds()); + return numeric_cast<int>(d.to_seconds()); } // BEGIN KeyContext data members @@ -3581,7 +3616,6 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, static BufferAllocated static_work; }; - public: class PsidCookieHelper { public: @@ -3592,14 +3626,52 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, bool is_clients_initial_reset() const { - return key_id_ == 0 && op_code_ == CONTROL_HARD_RESET_CLIENT_V2; + return key_id_ == 0 && (op_code_ == CONTROL_HARD_RESET_CLIENT_V2 || op_code_ == CONTROL_HARD_RESET_CLIENT_V3); + } + + //! Returns `true` if this is a TLS crypt V2 protocol packet. + bool is_tls_crypt_v2() const noexcept + { + return op_code_ == CONTROL_HARD_RESET_CLIENT_V3 || op_code_ == CONTROL_WKC_V1; + } + + //! Returns `true` if the peer supports early negotiation (i.e. is able to reply with `CONTROL_WKC_V1`). + bool supports_early_negotiation(const PacketIDControl &pidc) const noexcept + { + return (pidc.id & EARLY_NEG_MASK) == EARLY_NEG_START; } - bool is_clients_server_reset_ack() const + //! Returns `true` if this could be the third packet of the 3-way handshake (tls-auth/none). + bool is_clients_handshake_ack_tls_auth() const { return key_id_ == 0 && (op_code_ == CONTROL_V1 || op_code_ == ACK_V1); } + //! Returns `true` if this could be the third packet of the 3-way handshake (tls-crypt-v2). + bool is_clients_handshake_ack_tls_crypt_v2() const + { + return key_id_ == 0 && op_code_ == CONTROL_WKC_V1; + } + + //! Returns `true` if the packet is a P_ACK_V1 (no own message-id field on the wire). + bool is_ack_v1() const + { + return op_code_ == ACK_V1; + } + + //! Adds an {EARLY_NEG_FLAGS, 2, EARLY_NEG_FLAG_RESEND_WKC} TLV to a payload buffer (use with TLS crypt V2). + static void prepend_TLV(Buffer &payload) + { + // The only supported TLV payload for now. + const uint16_t type = htons(EARLY_NEG_FLAGS); + const uint16_t len = htons(sizeof(uint16_t)); + const uint16_t flags = htons(EARLY_NEG_FLAG_RESEND_WKC); + + payload.prepend(&flags, sizeof(flags)); + payload.prepend(&len, sizeof(len)); + payload.prepend(&type, sizeof(type)); + } + static unsigned char get_server_hard_reset_opfield() { return op_compose(CONTROL_HARD_RESET_SERVER_V2, 0); @@ -3673,7 +3745,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, class TLSWrapPreValidate : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSWrapPreValidate> Ptr; + using Ptr = RCPtr<TLSWrapPreValidate>; virtual bool validate(const BufferAllocated &net_buf) = 0; }; @@ -3702,12 +3774,12 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, const unsigned int key_dir = c.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); + ta_hmac_recv->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); } else { // key-direction bidirectional mode - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); + ta_hmac_recv->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC)); } } @@ -3715,7 +3787,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { try { - if (!net_buf.size()) + if (net_buf.empty()) return false; const unsigned int op = net_buf[0]; @@ -3724,11 +3796,11 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, return ta_hmac_recv->ovpn_hmac_cmp(net_buf.c_data(), net_buf.size(), - 1 + ProtoSessionID::SIZE, + OPCODE_SIZE + ProtoSessionID::SIZE, ta_hmac_recv->output_size(), PacketIDControl::size()); } - catch (BufferException &) + catch (const BufferException &) { } @@ -3747,19 +3819,36 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, TLSCryptPreValidate(const ProtoConfig &c, const bool server) { - if (!c.tls_crypt_enabled()) + const bool tls_crypt_v2_enabled = c.tls_crypt_v2_enabled(); + + if (!c.tls_crypt_enabled() && !tls_crypt_v2_enabled) throw tls_crypt_pre_validate(); // save hard reset op we expect to receive from peer - reset_op = server ? CONTROL_HARD_RESET_CLIENT_V2 : CONTROL_HARD_RESET_SERVER_V2; + reset_op = CONTROL_HARD_RESET_SERVER_V2; + + if (server) + { + // We can't pre-validate because we haven't extracted the server key from + // the server key ID that's present in the client key yet. + if (tls_crypt_v2_enabled && c.tls_crypt_v2_serverkey_id) + { + disabled = true; + return; + } + + reset_op = tls_crypt_v2_enabled + ? CONTROL_HARD_RESET_CLIENT_V3 + : CONTROL_HARD_RESET_CLIENT_V2; + } tls_crypt_recv = c.tls_crypt_context->new_obj_recv(); // static direction assignment - not user configurable const unsigned int key_dir = server ? OpenVPNStaticKey::NORMAL : OpenVPNStaticKey::INVERSE; tls_crypt_recv->init(c.ssl_factory->libctx(), - c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir), - c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); + c.tls_crypt_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir), + c.tls_crypt_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); // needed to create the decrypt buffer during validation frame = c.frame; @@ -3767,9 +3856,12 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, bool validate(const BufferAllocated &net_buf) { + if (disabled) + return true; + try { - if (!net_buf.size()) + if (net_buf.empty()) return false; const unsigned int op = net_buf[0]; @@ -3799,7 +3891,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, work.data(), work.size()); } - catch (BufferException &) + catch (const BufferException &) { } return false; @@ -3812,23 +3904,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, TLSCryptInstance::Ptr tls_crypt_recv; Frame::Ptr frame; BufferAllocated work; - }; - - class TLSCryptV2PreValidate : public TLSCryptPreValidate - { - public: - OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_pre_validate); - - TLSCryptV2PreValidate(const ProtoConfig &c, const bool server) - : TLSCryptPreValidate(c, server) - { - if (!c.tls_crypt_v2_enabled()) - throw tls_crypt_v2_pre_validate(); - - // in case of server peer, we expect the new v3 packet type - if (server) - reset_op = CONTROL_HARD_RESET_CLIENT_V3; - } + bool disabled = false; }; OPENVPN_SIMPLE_EXCEPTION(select_key_context_error); @@ -3848,33 +3924,40 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, void reset_tls_wrap_mode(const ProtoConfig &c) { - // tls-auth setup - if (c.tls_crypt_v2_enabled()) + // Prefer TLS auth as the default if both TLS crypt V2 and TLS auth + // are enabled. + if (c.tls_crypt_v2_enabled() && !c.tls_auth_enabled()) { tls_wrap_mode = TLS_CRYPT_V2; // get HMAC size from Digest object hmac_size = c.tls_crypt_context->digest_size(); + + return; } - else if (c.tls_crypt_enabled()) + + if (c.tls_crypt_enabled() && !c.tls_auth_enabled()) { tls_wrap_mode = TLS_CRYPT; // get HMAC size from Digest object hmac_size = c.tls_crypt_context->digest_size(); + + return; } - else if (c.tls_auth_enabled()) + + if (c.tls_auth_enabled()) { tls_wrap_mode = TLS_AUTH; // get HMAC size from Digest object hmac_size = c.tls_auth_context->size(); + + return; } - else - { - tls_wrap_mode = TLS_PLAIN; - hmac_size = 0; - } + + tls_wrap_mode = TLS_PLAIN; + hmac_size = 0; } uint32_t get_tls_warnings() const @@ -3912,8 +3995,10 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, OpenVPNStaticKey dyn_key; key_ctx->export_key_material(dyn_key, "EXPORTER-OpenVPN-dynamic-tls-crypt"); - if (c.tls_auth_enabled() || c.tls_crypt_enabled() || c.tls_crypt_v2_enabled()) - dyn_key.XOR(c.tls_key); + if (c.tls_auth_enabled()) + dyn_key.XOR(c.tls_auth_key); + else if (c.tls_crypt_enabled() || c.tls_crypt_v2_enabled()) + dyn_key.XOR(c.tls_crypt_key); tls_wrap_mode = TLS_CRYPT; @@ -3928,20 +4013,29 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, void reset_tls_crypt_server(const ProtoConfig &c) { - // tls-crypt session key is derived later from WKc received from the client - tls_crypt_send.reset(); - tls_crypt_recv.reset(); + // It is possible that the PSID/HMAC cookie logic has already set the TLS crypt V2 + // keys up, during the processing of the second packet. If so, just use them. + if (c.tls_crypt_key.defined() && c.wrapped_tls_crypt_key.defined()) + { + reset_tls_crypt(c, c.wrapped_tls_crypt_key); + } + else + { + // tls-crypt session key is derived later from WKc received from the client + tls_crypt_send.reset(); + tls_crypt_recv.reset(); - // server context is used only to process incoming WKc's - tls_crypt_server = c.tls_crypt_context->new_obj_recv(); + // server context is used only to process incoming WKc's + tls_crypt_server = c.tls_crypt_context->new_obj_recv(); - if (!c.tls_crypt_v2_serverkey_id) - { - // the server key is composed by one key set only, therefore direction and - // mode should not be specified when slicing - tls_crypt_server->init(c.ssl_factory->libctx(), - c.tls_key.slice(OpenVPNStaticKey::HMAC), - c.tls_key.slice(OpenVPNStaticKey::CIPHER)); + if (!c.tls_crypt_v2_serverkey_id) + { + // the server key is composed by one key set only, therefore direction and + // mode should not be specified when slicing + tls_crypt_server->init(c.ssl_factory->libctx(), + c.tls_crypt_key.slice(OpenVPNStaticKey::HMAC), + c.tls_crypt_key.slice(OpenVPNStaticKey::CIPHER)); + } } tls_crypt_metadata = c.tls_crypt_metadata_factory->new_obj(); @@ -3972,14 +4066,13 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, upcoming_key_id = 0; unsigned int key_dir; - const PacketIDControl::id_t EARLY_NEG_START = 0x0f000000; // tls-auth initialization reset_tls_wrap_mode(c); switch (tls_wrap_mode) { case TLS_CRYPT: - reset_tls_crypt(c, c.tls_key); + reset_tls_crypt(c, c.tls_crypt_key); // init tls_crypt packet ID ta_pid_send.init(); ta_pid_recv.init("SSL-CC", 0, stats); @@ -3991,7 +4084,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, // from client reset_tls_crypt_server(c); else - reset_tls_crypt(c, c.tls_key); + reset_tls_crypt(c, c.tls_crypt_key); /** tls-auth/tls-crypt packet id. We start with a different id here * to indicate EARLY_NEG_START/CONTROL_WKC_V1 support */ // init tls_crypt packet ID @@ -4008,14 +4101,14 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { // key-direction is 0 or 1 key_dir = c.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - ta_hmac_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir)); - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); + ta_hmac_send->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir)); + ta_hmac_recv->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); } else { // key-direction bidirectional mode - ta_hmac_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); + ta_hmac_send->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC)); + ta_hmac_recv->init(c.tls_auth_key.slice(OpenVPNStaticKey::HMAC)); } /** @@ -4165,8 +4258,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, ret.min(keepalive_expire); return ret; } - else - return Time(); + return Time(); } // send app-level cleartext to remote peer @@ -4188,24 +4280,24 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, } // pass received control channel network packets (ciphertext) into protocol object - - bool control_net_recv(const PacketType &type, BufferAllocated &&net_buf) + bool control_net_recv(const PacketType &type, BufferPtr &&net_bp) { - Packet pkt(BufferAllocatedRc::Create(std::move(net_buf)), type.opcode); + Packet pkt(std::move(net_bp), type.opcode); if (type.is_soft_reset() && !renegotiate_request(pkt)) return false; return select_key_context(type, true).net_recv(std::move(pkt)); } - // this version only appears to support test_proto.cpp; suggest creating a - // local BufferAllocatedRc and move the BufferPtr contents into it; then use - // the version above - bool control_net_recv(const PacketType &type, BufferPtr &&net_bp) + /** + @brief pass received control channel network packets (ciphertext) into protocol object + @param type Packet type discriminator + @param net_buf Buffer containing the network packet + @return @c true if successfully processed, @c false if not + @note Implemented in terms of control_net_recv(const PacketType &type, BufferPtr &&net_bp) + */ + bool control_net_recv(const PacketType &type, BufferAllocated &&net_buf) { - Packet pkt(std::move(net_bp), type.opcode); - if (type.is_soft_reset() && !renegotiate_request(pkt)) - return false; - return select_key_context(type, true).net_recv(std::move(pkt)); + return control_net_recv(type, BufferAllocatedRc::Create(std::move(net_buf))); } // encrypt a data channel packet using primary KeyContext @@ -4228,7 +4320,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, select_key_context(type, false).decrypt(in_out); // update time of most recent packet received - if (in_out.size()) + if (!in_out.empty()) { update_last_received(); ret = true; @@ -4469,8 +4561,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { if (primary) return primary->get_state(); - else - return STATE_UNDEF; + return STATE_UNDEF; } private: @@ -4483,6 +4574,9 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, TLS_CRYPT_V2 }; + static constexpr PacketIDControl::id_t EARLY_NEG_START = 0x0f000000; + static constexpr PacketIDControl::id_t EARLY_NEG_MASK = 0xff000000; + void reset_all() { if (primary) @@ -4526,8 +4620,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, new_secondary_key(false); return true; } - else - return false; + return false; } // select a KeyContext (primary or secondary) for received network packets @@ -4538,7 +4631,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { if (flags == (PacketType::DEFINED) && primary) return *primary; - else if (flags == (PacketType::DEFINED | PacketType::SECONDARY) && secondary) + if (flags == (PacketType::DEFINED | PacketType::SECONDARY) && secondary) return *secondary; } else @@ -4547,8 +4640,8 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO, { return *primary; } - else if (flags == (PacketType::DEFINED | PacketType::SECONDARY | PacketType::CONTROL) - && secondary) + if (flags == (PacketType::DEFINED | PacketType::SECONDARY | PacketType::CONTROL) + && secondary) { return *secondary; } diff --git a/openvpn/ssl/proto_context_options.hpp b/openvpn/ssl/proto_context_options.hpp index c1836a5af..015814b6a 100644 --- a/openvpn/ssl/proto_context_options.hpp +++ b/openvpn/ssl/proto_context_options.hpp @@ -22,7 +22,7 @@ namespace openvpn { struct ProtoContextCompressionOptions : public RC<thread_safe_refcount> { - typedef RCPtr<ProtoContextCompressionOptions> Ptr; + using Ptr = RCPtr<ProtoContextCompressionOptions>; enum CompressionMode { diff --git a/openvpn/ssl/protostack.hpp b/openvpn/ssl/protostack.hpp index 3d3d53a2b..495d32acd 100644 --- a/openvpn/ssl/protostack.hpp +++ b/openvpn/ssl/protostack.hpp @@ -71,9 +71,9 @@ class ProtoStackBase static constexpr size_t ovpn_sending_window = 6; static constexpr size_t ovpn_receiving_window = ReliableAck::maximum_acks_ack_v1; - typedef reliable::id_t id_t; - typedef ReliableSendTemplate<PACKET> ReliableSend; - typedef ReliableRecvTemplate<PACKET> ReliableRecv; + using id_t = reliable::id_t; + using ReliableSend = ReliableSendTemplate<PACKET>; + using ReliableRecv = ReliableRecvTemplate<PACKET>; OPENVPN_SIMPLE_EXCEPTION(proto_stack_invalidated); OPENVPN_SIMPLE_EXCEPTION(unknown_status_from_ssl_layer); @@ -213,8 +213,7 @@ class ProtoStackBase { if (!invalidated()) return next_retransmit_; - else - return Time::infinite(); + return Time::infinite(); } // Has SSL handshake been started yet? @@ -430,8 +429,7 @@ class ProtoStackBase up_sequenced(); return true; } - else - return false; + return false; } // if a sequenced packet is available from reliability layer, diff --git a/openvpn/ssl/psid_cookie.hpp b/openvpn/ssl/psid_cookie.hpp index fd26b6715..88bd6b9fa 100644 --- a/openvpn/ssl/psid_cookie.hpp +++ b/openvpn/ssl/psid_cookie.hpp @@ -11,6 +11,7 @@ /** + * @file * @brief Support deferred server-side state creation when client connects * * Creating OpenVPN protocol tracking state upon receipt of an initial client HARD_RESET @@ -71,7 +72,7 @@ class PsidCookieAddrInfoBase class PsidCookieTransportBase : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<PsidCookieTransportBase> Ptr; + using Ptr = RCPtr<PsidCookieTransportBase>; virtual bool psid_cookie_send_const(Buffer &send_buf, const PsidCookieAddrInfoBase &pcaib) = 0; @@ -84,7 +85,7 @@ class PsidCookieTransportBase : public RC<thread_unsafe_refcount> class PsidCookie : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<PsidCookie> Ptr; + using Ptr = RCPtr<PsidCookie>; /** * @brief Values returned by the intercept() function @@ -115,7 +116,7 @@ class PsidCookie : public RC<thread_unsafe_refcount> * that the server implementation derived from the PsidCookieAddrInfoBase class * @return Intercept Status of the packet handling */ - virtual Intercept intercept(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) = 0; + virtual Intercept intercept(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) = 0; /** * @brief Get the cookie psid from client's 2nd packet diff --git a/openvpn/ssl/psid_cookie_impl.hpp b/openvpn/ssl/psid_cookie_impl.hpp index 5c5f8c19b..040db6c79 100644 --- a/openvpn/ssl/psid_cookie_impl.hpp +++ b/openvpn/ssl/psid_cookie_impl.hpp @@ -28,6 +28,7 @@ #include <openvpn/transport/server/transbase.hpp> #include <openvpn/server/servproto.hpp> +#include <optional> namespace openvpn { @@ -45,6 +46,7 @@ class PsidCookieImpl : public PsidCookie { public: static constexpr int SID_SIZE = ProtoSessionID::SIZE; + static constexpr int OPCODE_SIZE = 1; // must be called _before_ the server implementation starts threads; it guarantees // that all per thread instances get the same psid cookie hmac key @@ -55,30 +57,29 @@ class PsidCookieImpl : public PsidCookie PsidCookieImpl(ServerProto::Factory *psfp) : pcfg_(*psfp->proto_context_config), - not_tls_auth_mode_(!pcfg_.tls_auth_enabled()), now_(pcfg_.now), handwindow_(pcfg_.handshake_window) { - if (not_tls_auth_mode_) - return; - - ta_hmac_recv_ = pcfg_.tls_auth_context->new_obj(); - ta_hmac_send_ = pcfg_.tls_auth_context->new_obj(); - - // init tls_auth hmac (see ProtoContext.reset() case TLS_AUTH; also TLSAuthPreValidate ctor) - if (pcfg_.key_direction >= 0) - { - // key-direction is 0 or 1 - const unsigned int key_dir = pcfg_.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - ta_hmac_send_->init(pcfg_.tls_key.slice(OpenVPNStaticKey::HMAC - | OpenVPNStaticKey::ENCRYPT | key_dir)); - ta_hmac_recv_->init(pcfg_.tls_key.slice(OpenVPNStaticKey::HMAC - | OpenVPNStaticKey::DECRYPT | key_dir)); - } - else + if (pcfg_.tls_auth_enabled()) { - // key-direction bidirectional mode - ta_hmac_send_->init(pcfg_.tls_key.slice(OpenVPNStaticKey::HMAC)); - ta_hmac_recv_->init(pcfg_.tls_key.slice(OpenVPNStaticKey::HMAC)); + ta_hmac_recv_ = pcfg_.tls_auth_context->new_obj(); + ta_hmac_send_ = pcfg_.tls_auth_context->new_obj(); + + // init tls_auth hmac (see ProtoContext.reset() case TLS_AUTH; also TLSAuthPreValidate ctor) + if (pcfg_.key_direction >= 0) + { + // key-direction is 0 or 1 + const unsigned int key_dir = pcfg_.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; + ta_hmac_send_->init(pcfg_.tls_auth_key.slice(OpenVPNStaticKey::HMAC + | OpenVPNStaticKey::ENCRYPT | key_dir)); + ta_hmac_recv_->init(pcfg_.tls_auth_key.slice(OpenVPNStaticKey::HMAC + | OpenVPNStaticKey::DECRYPT | key_dir)); + } + else + { + // key-direction bidirectional mode + ta_hmac_send_->init(pcfg_.tls_auth_key.slice(OpenVPNStaticKey::HMAC)); + ta_hmac_recv_->init(pcfg_.tls_auth_key.slice(OpenVPNStaticKey::HMAC)); + } } // initialize psid HMAC context with digest type and key @@ -86,28 +87,31 @@ class PsidCookieImpl : public PsidCookie hmac_ctx_.init(digest_, key.data(), key.size()); } - virtual ~PsidCookieImpl() = default; - - Intercept intercept(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) override + Intercept intercept(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) override { - // tls auth enabled is the only config we handle - if (not_tls_auth_mode_) - { // test discovered in TLSAuthPreValidate - return Intercept::DECLINE_HANDLING; // let existing code handle these cases - } + if (!pcfg_.tls_auth_enabled() && !pcfg_.tls_crypt_v2_enabled()) + return Intercept::DECLINE_HANDLING; - if (!pkt_buf.size()) - { + if (pkt_buf.empty()) return Intercept::EARLY_DROP; // packet validation fails, no opcode - } + CookieHelper chelp(pkt_buf[0]); + + const bool is_tls_crypt_v2 = (chelp.is_tls_crypt_v2() && pcfg_.tls_crypt_v2_enabled()); + if (chelp.is_clients_initial_reset()) { - return process_clients_initial_reset(pkt_buf, pcaib); + return is_tls_crypt_v2 + ? process_clients_initial_reset_tls_crypt(pkt_buf, pcaib, chelp) + : process_clients_initial_reset_tls_auth(pkt_buf, pcaib); + } + if (is_tls_crypt_v2 && chelp.is_clients_handshake_ack_tls_crypt_v2()) + { + return process_clients_server_reset_ack_tls_crypt(pkt_buf, pcaib); } - else if (chelp.is_clients_server_reset_ack()) + if (pcfg_.tls_auth_enabled() && chelp.is_clients_handshake_ack_tls_auth()) { - return process_clients_server_reset_ack(pkt_buf, pcaib); + return process_clients_server_reset_ack_tls_auth(pkt_buf, pcaib, chelp.is_ack_v1()); } // JMD_TODO: log failure? Logging DDoS? @@ -131,11 +135,55 @@ class PsidCookieImpl : public PsidCookie #endif using CookieHelper = ProtoContext::PsidCookieHelper; - Intercept process_clients_initial_reset(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) + // Returns true iff the reliable::id_t read from `buf` is within the early-handshake + // range (0 or 1); false for mid-session values (> 1). + template <typename Buf> + static bool read_id_is_early_handshake(Buf &buf) + { + reliable::id_t net_id; + buf.read(&net_id, sizeof(net_id)); + return ntohl(net_id) <= 1; + } + + // Validates the payload of the third 3WHS packet (client ACK of server HARD_RESET). + // The "0 or 1" tolerance on pktids matches OpenVPN 2's check_session_hmac_and_pkt_id(): + // anything higher is clearly mid-session traffic, not a 3WHS completion. + // When has_own_pktid is false (P_ACK_V1 wire format), the own message-id field is + // absent on the wire and the check is skipped. + // Sets cookie_psid_ and returns true on success. + template <typename Buf> + bool validate_3whs_ack_payload(Buf &buf, + const ProtoSessionID &cli_psid, + const PsidCookieAddrInfoBase &pcaib, + bool has_own_pktid = true) + { + // We _should_ have one ACK (for the HARD_RESET previous message). + if (buf[0] != 1) + return false; + + buf.advance(1); + + if (!read_id_is_early_handshake(buf)) + return false; + + cookie_psid_.read(buf); + + if (has_own_pktid && !read_id_is_early_handshake(buf)) + return false; + + return check_session_id_hmac(cookie_psid_, cli_psid, pcaib); + } + + Intercept process_clients_initial_reset_tls_auth(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) { static const size_t hmac_size = ta_hmac_recv_->output_size(); + // ovpn_hmac_cmp checks for adequate pkt_buf.size() - bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(), pkt_buf.size(), 1 + SID_SIZE, hmac_size, PacketIDControl::idsize); + bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(), + pkt_buf.size(), + OPCODE_SIZE + SID_SIZE, + hmac_size, + PacketIDControl::idsize); if (!pkt_hmac_valid) { // JMD_TODO: log failure? Logging DDoS? @@ -145,8 +193,8 @@ class PsidCookieImpl : public PsidCookie // check for adequate packet size to complete this function static const size_t reqd_packet_size // clang-format off - // [op_field] [cli_psid] [HMAC] [cli_auth_pktid] [cli_pktid] - = 1 + SID_SIZE + hmac_size + PacketIDControl::idsize + reliable::id_size; + // [op_field] [cli_psid] [HMAC] [cli_auth_pktid] [cli_pktid] + = OPCODE_SIZE + SID_SIZE + hmac_size + PacketIDControl::idsize + reliable::id_size; // clang-format on if (pkt_buf.size() < reqd_packet_size) { @@ -195,7 +243,11 @@ class PsidCookieImpl : public PsidCookie const unsigned char op_field = CookieHelper::get_server_hard_reset_opfield(); send_buf.push_front(op_field); // write hmac - ta_hmac_send_->ovpn_hmac_gen(send_buf.data(), send_buf.size(), 1 + SID_SIZE, ta_hmac_send_->output_size(), PacketIDControl::idsize); + ta_hmac_send_->ovpn_hmac_gen(send_buf.data(), + send_buf.size(), + OPCODE_SIZE + SID_SIZE, + ta_hmac_send_->output_size(), + PacketIDControl::idsize); // consumer's implementation to send the SERVER_HARD_RESET to the client bool send_ok = pctb_->psid_cookie_send_const(send_buf, pcaib); @@ -207,24 +259,28 @@ class PsidCookieImpl : public PsidCookie return Intercept::DROP_1ST; } - Intercept process_clients_server_reset_ack(ConstBuffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) + Intercept process_clients_server_reset_ack_tls_auth(ConstBuffer &pkt_buf, + const PsidCookieAddrInfoBase &pcaib, + bool is_ack_v1) { static const size_t hmac_size = ta_hmac_recv_->output_size(); // ovpn_hmac_cmp checks for adequate pkt_buf.size() - bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(), pkt_buf.size(), 1 + SID_SIZE, hmac_size, PacketIDControl::idsize); + bool pkt_hmac_valid = ta_hmac_recv_->ovpn_hmac_cmp(pkt_buf.c_data(), + pkt_buf.size(), + OPCODE_SIZE + SID_SIZE, + hmac_size, + PacketIDControl::idsize); if (!pkt_hmac_valid) { // JMD_TODO: log failure? Logging DDoS? return Intercept::DROP_2ND; } - static const size_t reqd_packet_size - // clang-format off - // [op_field] [cli_psid] [HMAC] [cli_auth_pktid] [acked] [srv_psid] - = 1 + SID_SIZE + hmac_size + PacketIDControl::size() + 5 + SID_SIZE; - // the fixed size, 5, of the [acked] field recognizes that the client's first - // response will ack exactly one packet, the server's HARD_RESET - // clang-format on + // [op_field][cli_psid][HMAC][cli_auth_pktid][acked][srv_psid] and, + // for CONTROL_V1 only, a trailing [own_pktid]. P_ACK_V1 has no own + // message-id on the wire, so its required size is shorter. + const size_t reqd_packet_size = OPCODE_SIZE + SID_SIZE + hmac_size + PacketIDControl::size() + 5 + SID_SIZE + + (is_ack_v1 ? 0 : reliable::id_size); if (pkt_buf.size() < reqd_packet_size) { // JMD_TODO: log failure? Logging DDoS? @@ -241,22 +297,131 @@ class PsidCookieImpl : public PsidCookie PacketIDControl cli_auth_pktid; // a.k.a, replay_packet_id in draft RFC cli_auth_pktid.read(recv_buf_copy); - unsigned int ack_count = recv_buf_copy[0]; - if (ack_count != 1) - { + return validate_3whs_ack_payload(recv_buf_copy, cli_psid, pcaib, !is_ack_v1) + ? Intercept::HANDLE_2ND + : Intercept::DROP_2ND; + } + + Intercept process_clients_initial_reset_tls_crypt(Buffer &pkt_buf, + const PsidCookieAddrInfoBase &pcaib, + const CookieHelper &ch) + { + static const size_t hmac_size = pcfg_.tls_crypt_context->digest_size(); + + ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true); + + ProtoSessionID client_session_id(recv_buf_copy); + PacketIDControl replay_packet_id; + replay_packet_id.read(recv_buf_copy); + + // This could be user-configurable so that we could just drop packets here if + // we don't want to allow clients that don't support re-sending the WKc. + if (!ch.supports_early_negotiation(replay_packet_id)) + return Intercept::DECLINE_HANDLING; + + auto pipes = init_tls_crypt_v2(pkt_buf); + + if (!pipes) + return Intercept::DROP_1ST; + + auto [send, recv] = *pipes; + + // Create synthetic RESET packet payload. + BufferAllocated payload; + pcfg_.frame->prepare(Frame::WRITE_SSL_INIT, payload); + + CookieHelper::prepend_TLV(payload); + + PacketIDControl packet_id{.id = 0, .time = 0}; + packet_id.write(payload, true); + + client_session_id.prepend(payload); + + const reliable::id_t acked_packet_id = 0; + payload.prepend(&acked_packet_id, sizeof(acked_packet_id)); + payload.push_front((unsigned char)1); + + BufferAllocated work; + // in 'work' we store all the fields that are not supposed to be encrypted + pcfg_.frame->prepare(Frame::ENCRYPT_WORK, work); + // make space for HMAC + work.prepend_alloc(hmac_size); + // write tls-crypt packet ID + PacketIDControlSend svr_auth_pid; + svr_auth_pid.write_next(work, true, now_->seconds_since_epoch()); + // write source PSID + const ProtoSessionID srv_psid = calculate_session_id_hmac(client_session_id, pcaib, 0); + srv_psid.prepend(work); + // write opcode + work.push_front(CookieHelper::get_server_hard_reset_opfield()); + + // compute HMAC using header fields (from 'work') and plaintext + // payload + send->hmac_gen(work.data(), TLSCryptContext::hmac_offset, payload.c_data(), payload.size()); + + const size_t data_offset = TLSCryptContext::hmac_offset + hmac_size; + + // encrypt the content of 'payload' (packet payload) into 'work' + const size_t encrypt_bytes = send->encrypt(work.c_data() + TLSCryptContext::hmac_offset, + work.data() + data_offset, + work.max_size() - data_offset, + payload.c_data(), + payload.size()); + work.inc_size(encrypt_bytes); + + // consumer's implementation to send the SERVER_HARD_RESET to the client + bool send_ok = pctb_->psid_cookie_send_const(work, pcaib); + if (send_ok) + return Intercept::HANDLE_1ST; + + return Intercept::DROP_1ST; + } + + Intercept process_clients_server_reset_ack_tls_crypt(Buffer &pkt_buf, const PsidCookieAddrInfoBase &pcaib) + { + auto pipes = init_tls_crypt_v2(pkt_buf); + + if (!pipes) return Intercept::DROP_2ND; - } - recv_buf_copy.advance(5); - cookie_psid_.read(recv_buf_copy); - // verify client's Psid Cookie - bool is_cookie_valid = check_session_id_hmac(cookie_psid_, cli_psid, pcaib); - if (is_cookie_valid) - { - return Intercept::HANDLE_2ND; - } + auto [send, recv] = *pipes; - return Intercept::DROP_2ND; + static const size_t hmac_size = pcfg_.tls_crypt_context->digest_size(); + + const size_t head_size = OPCODE_SIZE + ProtoSessionID::SIZE + PacketIDControl::size(); + const unsigned char *orig_data = pkt_buf.c_data(); + + ConstBuffer recv_buf_copy(pkt_buf.c_data() + 1, pkt_buf.size() - 1, true); + + ProtoSessionID client_session_id(recv_buf_copy); + recv_buf_copy.advance(PacketIDControl::size() + hmac_size); + + BufferAllocated work; + pcfg_.frame->prepare(Frame::DECRYPT_WORK, work); + + // Decrypt into `work`. + const size_t decrypt_bytes = recv->decrypt(orig_data + head_size, + work.data(), + work.max_size(), + recv_buf_copy.c_data(), + recv_buf_copy.size()); + if (!decrypt_bytes) + return Intercept::DROP_2ND; + + work.inc_size(decrypt_bytes); + + // Verify HMAC. + if (!recv->hmac_cmp(orig_data, TLSCryptContext::hmac_offset, work.c_data(), work.size())) + return Intercept::DROP_2ND; + + // Decrypted plaintext layout: ack_count(1) | acked_pktid(4) | peer_session_id(8) | packet_id(4) | payload + static const size_t reqd_decrypted_size = 1 + reliable::id_size + ProtoSessionID::SIZE + reliable::id_size; + if (work.size() < reqd_decrypted_size) + return Intercept::DROP_2ND; + + return validate_3whs_ack_payload(work, client_session_id, pcaib) + ? Intercept::HANDLE_2ND + : Intercept::DROP_2ND; } // key must be common to all threads @@ -317,7 +482,7 @@ class PsidCookieImpl : public PsidCookie hmac_ctx_.update(cli_psid_buf.c_data(), SID_SIZE); // finalize the hmac and package it as the server's ProtoSessionID - BufferAllocated hmac_result(SSLLib::CryptoAPI::HMACContext::MAX_HMAC_SIZE, 0); + BufferAllocated hmac_result(SSLLib::CryptoAPI::HMACContext::MAX_HMAC_SIZE); ProtoSessionID srv_psid; hmac_ctx_.final(hmac_result.write_alloc(hmac_ctx_.size())); srv_psid.read(hmac_result); @@ -343,10 +508,43 @@ class PsidCookieImpl : public PsidCookie return false; } + /** + * @brief Set up a couple of TLSCryptInstance (send, recv) from a TLS crypt V2 packet's WKc + * + * @param pkt_buf The packet holding the WKc at the end. + * @return A pair of {send, recv} objects set up with the symmetric key. std::nullopt on error. + */ + std::optional<std::pair<TLSCryptInstance::Ptr, TLSCryptInstance::Ptr>> init_tls_crypt_v2(Buffer &pkt_buf) + { + TLSCryptInstance::Ptr send; + TLSCryptInstance::Ptr recv; + + TLSCryptInstance::Ptr tls_crypt_server = pcfg_.tls_crypt_context->new_obj_recv(); + + if (ProtoContext::KeyContext::unwrap_tls_crypt_wkc(pkt_buf, pcfg_, *tls_crypt_server) != Error::SUCCESS) + return std::nullopt; + + const unsigned int key_dir = pcfg_.ssl_factory->mode().is_server() + ? OpenVPNStaticKey::NORMAL + : OpenVPNStaticKey::INVERSE; + + send = pcfg_.tls_crypt_context->new_obj_send(); + recv = pcfg_.tls_crypt_context->new_obj_recv(); + + send->init(pcfg_.ssl_factory->libctx(), + pcfg_.wrapped_tls_crypt_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir), + pcfg_.wrapped_tls_crypt_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir)); + + recv->init(pcfg_.ssl_factory->libctx(), + pcfg_.wrapped_tls_crypt_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir), + pcfg_.wrapped_tls_crypt_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); + + return std::pair{send, recv}; + } + static constexpr CryptoAlgs::Type digest_ = CryptoAlgs::Type::SHA256; - const ProtoContext::ProtoConfig &pcfg_; - bool not_tls_auth_mode_; + ProtoContext::ProtoConfig &pcfg_; TimePtr now_; const Time::Duration &handwindow_; diff --git a/openvpn/ssl/sess_ticket.hpp b/openvpn/ssl/sess_ticket.hpp index 5a0f2b34c..88e4d59ee 100644 --- a/openvpn/ssl/sess_ticket.hpp +++ b/openvpn/ssl/sess_ticket.hpp @@ -31,7 +31,7 @@ class MbedTLSContext; class TLSSessionTicketBase { public: - typedef std::unique_ptr<TLSSessionTicketBase> UPtr; + using UPtr = std::unique_ptr<TLSSessionTicketBase>; OPENVPN_EXCEPTION(sess_ticket_error); @@ -107,9 +107,8 @@ class TLSSessionTicketBase friend class OpenSSLContext; friend class MbedTLSContext; - Name() - { - } // note that default constructor leaves object in an undefined state + // note that default constructor leaves object in an undefined state + Name() = default; unsigned char value_[SIZE]; }; @@ -195,9 +194,8 @@ class TLSSessionTicketBase friend class OpenSSLContext; friend class MbedTLSContext; - Key() - { - } // note that default constructor leaves object in an undefined state + // note that default constructor leaves object in an undefined state + Key() = default; unsigned char cipher_value_[CIPHER_KEY_SIZE]; unsigned char hmac_value_[HMAC_KEY_SIZE]; diff --git a/openvpn/ssl/sni_handler.hpp b/openvpn/ssl/sni_handler.hpp index de702e6ad..5a045ebc3 100644 --- a/openvpn/ssl/sni_handler.hpp +++ b/openvpn/ssl/sni_handler.hpp @@ -23,7 +23,7 @@ namespace openvpn::SNI { class HandlerBase { public: - typedef std::unique_ptr<HandlerBase> UPtr; + using UPtr = std::unique_ptr<HandlerBase>; // Return a new SSLFactoryAPI for this SNI name. // Implementation may also set sni_metadata. diff --git a/openvpn/ssl/sni_metadata.hpp b/openvpn/ssl/sni_metadata.hpp index 50f057bdd..78f2d47bb 100644 --- a/openvpn/ssl/sni_metadata.hpp +++ b/openvpn/ssl/sni_metadata.hpp @@ -23,7 +23,7 @@ namespace SNI { class Metadata { public: - typedef std::unique_ptr<Metadata> UPtr; + using UPtr = std::unique_ptr<Metadata>; virtual std::string sni_client_name(const AuthCert &ac) const = 0; diff --git a/openvpn/ssl/sslapi.hpp b/openvpn/ssl/sslapi.hpp index 6c1ecaa2f..864b67d58 100644 --- a/openvpn/ssl/sslapi.hpp +++ b/openvpn/ssl/sslapi.hpp @@ -55,7 +55,7 @@ class SSLAPI : public RC<thread_unsafe_refcount> TLS_WARN_SIG_SHA1 = (1 << 1) }; - typedef RCPtr<SSLAPI> Ptr; + using Ptr = RCPtr<SSLAPI>; virtual void start_handshake() = 0; virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) = 0; @@ -88,7 +88,7 @@ class SSLFactoryAPI : public RC<thread_unsafe_refcount>, OPENVPN_EXCEPTION(ssl_external_pki); OPENVPN_SIMPLE_EXCEPTION(ssl_ciphertext_in_overflow); - typedef RCPtr<SSLFactoryAPI> Ptr; + using Ptr = RCPtr<SSLFactoryAPI>; // create a new SSLAPI instance virtual SSLAPI::Ptr ssl() = 0; @@ -107,7 +107,7 @@ class SSLFactoryAPI : public RC<thread_unsafe_refcount>, class SSLConfigAPI : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<SSLConfigAPI> Ptr; + using Ptr = RCPtr<SSLConfigAPI>; enum LoadFlags { @@ -118,7 +118,7 @@ class SSLConfigAPI : public RC<thread_unsafe_refcount> std::string private_key_type_string() const { - PKType::Type type = private_key_type(); + const PKType::Type type = private_key_type(); switch (type) { diff --git a/openvpn/ssl/sslchoose.hpp b/openvpn/ssl/sslchoose.hpp index 1342d4f76..1917823fe 100644 --- a/openvpn/ssl/sslchoose.hpp +++ b/openvpn/ssl/sslchoose.hpp @@ -39,7 +39,7 @@ #endif namespace openvpn::SSLLib { -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS #define SSL_LIB_NAME "MbedTLS" typedef MbedTLSContext SSLAPI; typedef MbedTLSPEM PEMAPI; @@ -54,9 +54,9 @@ typedef AppleCryptoAPI CryptoAPI; typedef AppleSSLContext SSLAPI; #elif defined(USE_OPENSSL) #define SSL_LIB_NAME "OpenSSL" -typedef OpenSSLCryptoAPI CryptoAPI; -typedef OpenSSLContext SSLAPI; -typedef OpenSSLPEM PEMAPI; +using CryptoAPI = OpenSSLCryptoAPI; +using SSLAPI = OpenSSLContext; +using PEMAPI = OpenSSLPEM; #else #error no SSL library defined #endif diff --git a/openvpn/ssl/tls_cert_profile.hpp b/openvpn/ssl/tls_cert_profile.hpp index dad7fe4ce..13783e07d 100644 --- a/openvpn/ssl/tls_cert_profile.hpp +++ b/openvpn/ssl/tls_cert_profile.hpp @@ -36,8 +36,7 @@ inline Type default_if_undef(const Type type) { if (type == UNDEF) return LEGACY; // this is the default if unspecified - else - return type; + return type; } inline const std::string to_string(const Type type) @@ -70,12 +69,11 @@ inline Type parse_tls_cert_profile(const std::string &profile_name) #endif if (profile_name == "legacy") return LEGACY; - else if (profile_name == "preferred") + if (profile_name == "preferred") return PREFERRED; - else if (profile_name == "suiteb") + if (profile_name == "suiteb") return SUITEB; - else - throw option_error(ERR_INVALID_OPTION_CRYPTO, "tls-cert-profile: unrecognized profile name"); + throw option_error(ERR_INVALID_OPTION_CRYPTO, "tls-cert-profile: unrecognized profile name"); } inline Type parse_tls_cert_profile(const OptionList &opt, diff --git a/openvpn/ssl/tls_remote.hpp b/openvpn/ssl/tls_remote.hpp index cd72ee37a..dede55620 100644 --- a/openvpn/ssl/tls_remote.hpp +++ b/openvpn/ssl/tls_remote.hpp @@ -17,20 +17,17 @@ #include <cstring> #include <string> -#include <openvpn/common/string.hpp> - namespace openvpn::TLSRemote { inline bool test(const std::string &tls_remote, const std::string &subject, const std::string &common_name) { - return tls_remote == subject || string::starts_with(common_name, tls_remote); + return tls_remote == subject || common_name.starts_with(tls_remote); } inline void log(const std::string &tls_remote, const std::string &subject, const std::string &common_name) { - OPENVPN_LOG("tls-remote validation" - << std::endl - << " tls-remote: '" << tls_remote << '\'' << std::endl - << " Subj: '" << subject << '\'' << std::endl + OPENVPN_LOG("tls-remote validation\n" + << " tls-remote: '" << tls_remote << "'\n" + << " Subj: '" << subject << "'\n" << " CN: '" << common_name << '\''); } diff --git a/openvpn/ssl/tlsprf.hpp b/openvpn/ssl/tlsprf.hpp index 9967061a7..ff4c9b77a 100644 --- a/openvpn/ssl/tlsprf.hpp +++ b/openvpn/ssl/tlsprf.hpp @@ -115,9 +115,9 @@ class TLSPRF std::string dump(const char *title) { std::ostringstream out; - out << "*** TLSPRF " << title << " pre_master: " << render_hex(pre_master, sizeof(pre_master)) << std::endl; - out << "*** TLSPRF " << title << " random1: " << render_hex(random1, sizeof(random1)) << std::endl; - out << "*** TLSPRF " << title << " random2: " << render_hex(random2, sizeof(random2)) << std::endl; + out << "*** TLSPRF " << title << " pre_master: " << render_hex(pre_master, sizeof(pre_master)) << '\n'; + out << "*** TLSPRF " << title << " random1: " << render_hex(random1, sizeof(random1)) << "\n"; + out << "*** TLSPRF " << title << " random2: " << render_hex(random2, sizeof(random2)) << "\n"; return out.str(); } @@ -229,7 +229,7 @@ class TLSPRF class TLSPRFInstance : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSPRFInstance> Ptr; + using Ptr = RCPtr<TLSPRFInstance>; virtual void self_randomize(StrongRandomAPI &rng) = 0; virtual void self_write(Buffer &buf) = 0; @@ -247,7 +247,7 @@ class TLSPRFInstance : public RC<thread_unsafe_refcount> class TLSPRFFactory : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TLSPRFFactory> Ptr; + using Ptr = RCPtr<TLSPRFFactory>; virtual TLSPRFInstance::Ptr new_obj(const bool self_is_server) = 0; }; diff --git a/openvpn/ssl/tlsver.hpp b/openvpn/ssl/tlsver.hpp index 39f5f492c..96777ff5f 100644 --- a/openvpn/ssl/tlsver.hpp +++ b/openvpn/ssl/tlsver.hpp @@ -60,16 +60,15 @@ inline Type parse_tls_version_min(const std::string &ver, { if (ver == "1.0" && Type::V1_0 <= max_version) return Type::V1_0; - else if (ver == "1.1" && Type::V1_1 <= max_version) + if (ver == "1.1" && Type::V1_1 <= max_version) return Type::V1_1; - else if (ver == "1.2" && Type::V1_2 <= max_version) + if (ver == "1.2" && Type::V1_2 <= max_version) return Type::V1_2; - else if (ver == "1.3" && Type::V1_3 <= max_version) + if (ver == "1.3" && Type::V1_3 <= max_version) return Type::V1_3; - else if (or_highest) + if (or_highest) return max_version; - else - throw option_error(ERR_INVALID_OPTION_CRYPTO, "tls-version-min: unrecognized TLS version"); + throw option_error(ERR_INVALID_OPTION_CRYPTO, "tls-version-min: unrecognized TLS version"); } inline Type parse_tls_version_min(const OptionList &opt, diff --git a/openvpn/ssl/verify_x509_name.hpp b/openvpn/ssl/verify_x509_name.hpp index 9c3741f9d..f2ecc1e31 100644 --- a/openvpn/ssl/verify_x509_name.hpp +++ b/openvpn/ssl/verify_x509_name.hpp @@ -113,11 +113,11 @@ class VerifyX509Name { return VERIFY_X509_SUBJECT_DN; } - else if (type == "name") + if (type == "name") { return VERIFY_X509_SUBJECT_RDN; } - else if (type == "name-prefix") + if (type == "name-prefix") { return VERIFY_X509_SUBJECT_RDN_PREFIX; } diff --git a/openvpn/time/asiotimer.hpp b/openvpn/time/asiotimer.hpp index 1544e6d86..ef052d0bd 100644 --- a/openvpn/time/asiotimer.hpp +++ b/openvpn/time/asiotimer.hpp @@ -25,10 +25,10 @@ namespace openvpn { struct AsioClock { - typedef olong rep; - typedef std::ratio<1, 1024> period; // time resolution of openvpn::Time, note 1024 instead of the usual 1000 - typedef std::chrono::duration<rep, period> duration; - typedef std::chrono::time_point<AsioClock> time_point; + using rep = olong; + using period = std::ratio<1, 1024>; // time resolution of openvpn::Time, note 1024 instead of the usual 1000 + using duration = std::chrono::duration<rep, period>; + using time_point = std::chrono::time_point<AsioClock>; static constexpr bool is_steady() { @@ -54,7 +54,7 @@ struct AsioClock class AsioTimer : public openvpn_io::basic_waitable_timer<AsioClock> { public: - typedef std::unique_ptr<AsioTimer> UPtr; + using UPtr = std::unique_ptr<AsioTimer>; AsioTimer(openvpn_io::io_context &io_context) : openvpn_io::basic_waitable_timer<AsioClock>(io_context) diff --git a/openvpn/time/coarsetime.hpp b/openvpn/time/coarsetime.hpp index 2b90415be..14beb9381 100644 --- a/openvpn/time/coarsetime.hpp +++ b/openvpn/time/coarsetime.hpp @@ -22,9 +22,7 @@ namespace openvpn { class CoarseTime { public: - CoarseTime() - { - } + CoarseTime() = default; CoarseTime(const Time::Duration &pre, const Time::Duration &post) : pre_(pre), post_(post) @@ -52,11 +50,9 @@ class CoarseTime { if (t >= time_) return (t - time_) <= post_; - else - return (time_ - t) <= pre_; + return (time_ - t) <= pre_; } - else - return false; + return false; } private: diff --git a/openvpn/time/cputime.hpp b/openvpn/time/cputime.hpp index d53e2c07e..1c0888437 100644 --- a/openvpn/time/cputime.hpp +++ b/openvpn/time/cputime.hpp @@ -24,7 +24,7 @@ #include <openvpn/common/number.hpp> #include <openvpn/common/exception.hpp> -#if defined(__APPLE__) +#ifdef __APPLE__ #include <mach/mach.h> /** @@ -77,12 +77,10 @@ inline double cpu_time(const bool thread = false) { try { - struct rusage usage - { - }; + struct rusage usage{}; int ret = 0; -#if defined(__APPLE__) +#ifdef __APPLE__ if (thread) ret = getrusage_thread(usage); else @@ -94,8 +92,8 @@ inline double cpu_time(const bool thread = false) { throw Exception("getrusage() call failed: " + std::string(strerror(errno))); } - double utime = static_cast<double>(usage.ru_utime.tv_sec) + (static_cast<double>(usage.ru_utime.tv_usec / 1000000)); - double stime = static_cast<double>(usage.ru_stime.tv_sec) + (static_cast<double>(usage.ru_stime.tv_usec / 1000000)); + const double utime = static_cast<double>(usage.ru_utime.tv_sec) + (static_cast<double>(usage.ru_utime.tv_usec / 1000000)); + const double stime = static_cast<double>(usage.ru_stime.tv_sec) + (static_cast<double>(usage.ru_stime.tv_usec / 1000000)); return utime + stime; } diff --git a/openvpn/time/durhelper.hpp b/openvpn/time/durhelper.hpp index 9f1b67653..686cdd4d0 100644 --- a/openvpn/time/durhelper.hpp +++ b/openvpn/time/durhelper.hpp @@ -87,8 +87,7 @@ inline Time::Duration skew_duration(const Time::Duration &dur, const Time::Duration ret = dur + delta; if (ret >= min) return ret; - else - return min; + return min; } } // namespace openvpn diff --git a/openvpn/time/time.hpp b/openvpn/time/time.hpp index 346cbfdad..c757f2c87 100644 --- a/openvpn/time/time.hpp +++ b/openvpn/time/time.hpp @@ -11,8 +11,9 @@ #pragma once -#include <limits> +#include <chrono> #include <cstdint> // for std::uint32_t, uint64_t +#include <limits> #include <openvpn/common/platform.hpp> #include <openvpn/common/exception.hpp> @@ -60,8 +61,8 @@ class TimeType { prec = 1024 }; - typedef ::time_t base_type; - typedef T type; + using base_type = ::time_t; + using type = T; class Duration { @@ -128,8 +129,7 @@ class TimeType { if (is_infinite() || d.is_infinite()) return infinite(); - else - return Duration(duration_ + d.duration_); + return Duration(duration_ + d.duration_); } Duration operator+(const int delta) const @@ -180,10 +180,9 @@ class TimeType { if (d.duration_ >= duration_) return Duration(0); - else if (is_infinite()) + if (is_infinite()) return Duration::infinite(); - else - return Duration(duration_ - d.duration_); + return Duration(duration_ - d.duration_); } Duration &operator-=(const Duration &d) @@ -261,8 +260,7 @@ class TimeType { if (t <= base_) return TimeType(T(1)); - else - return TimeType(T((t - base_) * prec)); + return TimeType(T((t - base_) * prec)); } bool is_infinite() const @@ -294,7 +292,7 @@ class TimeType } std::uint64_t nanoseconds_since_epoch() const { - return base_ * 1000000000ull + time_ * (1000000000ull / prec); + return base_ * 1000000000ULL + time_ * (1000000000ULL / prec); } T fractional_binary_ms() const { @@ -315,8 +313,7 @@ class TimeType { if (is_infinite() || d.is_infinite()) return infinite(); - else - return TimeType(time_ + d.duration_); + return TimeType(time_ + d.duration_); } TimeType &operator+=(const Duration &d) @@ -332,10 +329,9 @@ class TimeType { if (t.time_ >= time_) return Duration(0); - else if (is_infinite()) + if (is_infinite()) return Duration::infinite(); - else - return Duration(time_ - t.time_); + return Duration(time_ - t.time_); } void min(const TimeType &t) @@ -488,8 +484,8 @@ class TimeType T time_; }; -typedef TimeType<oulong> Time; +using Time = TimeType<oulong>; -typedef Time *TimePtr; +using TimePtr = Time *; } // namespace openvpn diff --git a/openvpn/time/timestr.hpp b/openvpn/time/timestr.hpp index 02a4d9a03..7c4f55623 100644 --- a/openvpn/time/timestr.hpp +++ b/openvpn/time/timestr.hpp @@ -25,7 +25,7 @@ #include <openvpn/common/size.hpp> #include <openvpn/common/string.hpp> -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #include <windows.h> #else #include <sys/time.h> @@ -33,7 +33,7 @@ namespace openvpn { -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN inline std::string date_time(const time_t now) { @@ -166,7 +166,7 @@ inline std::string date_time_rfc822(const time_t t) struct tm lt; char buf[64]; -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN if (gmtime_s(<, &t)) return ""; // MinGW doesn't yet support %T, so use %H:%M:%S diff --git a/openvpn/transport/altproxy.hpp b/openvpn/transport/altproxy.hpp index 4143f0935..ef1018772 100644 --- a/openvpn/transport/altproxy.hpp +++ b/openvpn/transport/altproxy.hpp @@ -42,7 +42,7 @@ struct AltProxy : public RC<thread_unsafe_refcount> SocketProtect *socket_protect; }; - typedef RCPtr<AltProxy> Ptr; + using Ptr = RCPtr<AltProxy>; // return proxy name virtual std::string name() const = 0; diff --git a/openvpn/transport/client/httpcli.hpp b/openvpn/transport/client/httpcli.hpp index aa4172737..dd1ef6ee4 100644 --- a/openvpn/transport/client/httpcli.hpp +++ b/openvpn/transport/client/httpcli.hpp @@ -61,7 +61,7 @@ class Options : public RC<thread_safe_refcount> public: struct CustomHeader : public RC<thread_unsafe_refcount> { - typedef RCPtr<CustomHeader> Ptr; + using Ptr = RCPtr<CustomHeader>; std::string p1; std::string p2; @@ -71,7 +71,7 @@ class Options : public RC<thread_safe_refcount> { }; - typedef RCPtr<Options> Ptr; + using Ptr = RCPtr<Options>; RemoteList::Ptr proxy_server; std::string username; @@ -191,15 +191,14 @@ class Options : public RC<thread_safe_refcount> } return true; } - else - return false; + return false; } }; class ClientConfig : public TransportClientFactory { public: - typedef RCPtr<ClientConfig> Ptr; + using Ptr = RCPtr<ClientConfig>; RemoteList::Ptr remote_list; size_t free_list_max_size; @@ -235,9 +234,9 @@ class ClientConfig : public TransportClientFactory class Client : public TransportClient, AsyncResolvableTCP { - typedef RCPtr<Client> Ptr; + using Ptr = RCPtr<Client>; - typedef TCPTransport::TCPLink<openvpn_io::ip::tcp, Client *, false> LinkImpl; + using LinkImpl = TCPTransport::TCPLink<openvpn_io::ip::tcp, Client *, false>; friend class ClientConfig; // calls constructor friend LinkImpl::Base; // calls tcp_read_handler @@ -290,8 +289,7 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) return impl->send_queue_empty(); - else - return false; + return false; } bool transport_has_send_queue() override @@ -307,8 +305,7 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) return impl->send_queue_size(); - else - return 0; + return 0; } void reset_align_adjust(const size_t align_adjust) override @@ -337,10 +334,9 @@ class Client : public TransportClient, AsyncResolvableTCP { if (server_endpoint.address().is_v4()) return Protocol(Protocol::TCPv4); - else if (server_endpoint.address().is_v6()) + if (server_endpoint.address().is_v6()) return Protocol(Protocol::TCPv6); - else - return Protocol(); + return Protocol(); } void stop() override @@ -396,19 +392,17 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) { - BufferAllocated buf(cbuf, 0); + BufferAllocated buf(cbuf); return impl->send(buf); } - else - return false; + return false; } bool send(BufferAllocated &buf) { if (impl) return impl->send(buf); - else - return false; + return false; } void tcp_error_handler(const char *error) // called by LinkImpl and internally @@ -667,16 +661,16 @@ class Client : public TransportClient, AsyncResolvableTCP throw Exception("HTTP proxy-authenticate method not allowed / supported"); } - else if (http_reply.status_code == HTTP::Status::ProxyError - || http_reply.status_code == HTTP::Status::NotFound - || http_reply.status_code == HTTP::Status::ServiceUnavailable) + if (http_reply.status_code == HTTP::Status::ProxyError + || http_reply.status_code == HTTP::Status::NotFound + || http_reply.status_code == HTTP::Status::ServiceUnavailable) { // this is a nonfatal error, so we pass Error::UNDEF to tell the upper layer to // retry the connection proxy_error(Error::UNDEF, "HTTP proxy server could not connect to OpenVPN server"); return; } - else if (http_reply.status_code == HTTP::Status::Forbidden) + if (http_reply.status_code == HTTP::Status::Forbidden) OPENVPN_THROW_EXCEPTION("HTTP proxy returned Forbidden status code"); else OPENVPN_THROW_EXCEPTION("HTTP proxy status code: " << http_reply.status_code); @@ -689,8 +683,8 @@ class Client : public TransportClient, AsyncResolvableTCP void basic_auth(HTTPProxy::ProxyAuthenticate &pa) { - OPENVPN_LOG("Proxy method: Basic" << std::endl - << pa.to_string()); + OPENVPN_LOG("Proxy method: Basic\n" + << pa.to_string()); std::ostringstream os; gen_headers(os); @@ -706,8 +700,8 @@ class Client : public TransportClient, AsyncResolvableTCP { try { - OPENVPN_LOG("Proxy method: Digest" << std::endl - << pa.to_string()); + OPENVPN_LOG("Proxy method: Digest\n" + << pa.to_string()); // constants const std::string http_method = "CONNECT"; @@ -785,8 +779,8 @@ class Client : public TransportClient, AsyncResolvableTCP void ntlm_auth_phase_1(HTTPProxy::ProxyAuthenticate &pa) { - OPENVPN_LOG("Proxy method: NTLM" << std::endl - << pa.to_string()); + OPENVPN_LOG("Proxy method: NTLM\n" + << pa.to_string()); const std::string phase_1_reply = HTTPProxy::NTLM::phase_1(); diff --git a/openvpn/transport/client/tcpcli.hpp b/openvpn/transport/client/tcpcli.hpp index 1cd7b66db..8341355ac 100644 --- a/openvpn/transport/client/tcpcli.hpp +++ b/openvpn/transport/client/tcpcli.hpp @@ -31,7 +31,7 @@ namespace openvpn::TCPTransport { class ClientConfig : public TransportClientFactory { public: - typedef RCPtr<ClientConfig> Ptr; + using Ptr = RCPtr<ClientConfig>; RemoteList::Ptr remote_list; size_t free_list_max_size; @@ -72,9 +72,9 @@ class ClientConfig : public TransportClientFactory class Client : public TransportClient, AsyncResolvableTCP { - typedef RCPtr<Client> Ptr; + using Ptr = RCPtr<Client>; - typedef TCPLink<openvpn_io::ip::tcp, Client *, false> LinkImpl; + using LinkImpl = TCPLink<openvpn_io::ip::tcp, Client *, false>; #ifdef OPENVPN_TLS_LINK typedef TLSLink<openvpn_io::ip::tcp, Client *, false> LinkImplTLS; #endif @@ -118,8 +118,7 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) return impl->send_queue_empty(); - else - return false; + return false; } bool transport_has_send_queue() override @@ -131,8 +130,7 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) return impl->send_queue_size(); - else - return 0; + return 0; } void reset_align_adjust(const size_t align_adjust) override @@ -208,19 +206,17 @@ class Client : public TransportClient, AsyncResolvableTCP { if (impl) { - BufferAllocated buf(cbuf, 0); + BufferAllocated buf(cbuf); return impl->send(buf); } - else - return false; + return false; } bool send(BufferAllocated &buf) { if (impl) return impl->send(buf); - else - return false; + return false; } void tcp_eof_handler() // called by LinkImpl::Base diff --git a/openvpn/transport/client/transbase.hpp b/openvpn/transport/client/transbase.hpp index 4323df1ca..4eb110695 100644 --- a/openvpn/transport/client/transbase.hpp +++ b/openvpn/transport/client/transbase.hpp @@ -34,7 +34,7 @@ struct TransportClientParent; // Base class for client transport object. struct TransportClient : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<TransportClient> Ptr; + using Ptr = RCPtr<TransportClient>; virtual void transport_start() = 0; virtual void stop() = 0; @@ -99,7 +99,7 @@ struct TransportClientParent // Factory for client transport object. struct TransportClientFactory : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<TransportClientFactory> Ptr; + using Ptr = RCPtr<TransportClientFactory>; // clang-format off virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context, diff --git a/openvpn/transport/client/udpcli.hpp b/openvpn/transport/client/udpcli.hpp index 3304bebd6..0e27843ff 100644 --- a/openvpn/transport/client/udpcli.hpp +++ b/openvpn/transport/client/udpcli.hpp @@ -31,7 +31,7 @@ namespace openvpn::UDPTransport { class ClientConfig : public TransportClientFactory { public: - typedef RCPtr<ClientConfig> Ptr; + using Ptr = RCPtr<ClientConfig>; RemoteList::Ptr remote_list; bool server_addr_float; @@ -71,12 +71,12 @@ class ClientConfig : public TransportClientFactory class Client : public TransportClient, AsyncResolvableUDP { - typedef RCPtr<Client> Ptr; + using Ptr = RCPtr<Client>; friend class ClientConfig; // calls constructor friend class UDPLink<Client *>; // calls udp_read_handler - typedef UDPLink<Client *> LinkImpl; + using LinkImpl = UDPLink<Client *>; public: void transport_start() override @@ -222,11 +222,9 @@ class Client : public TransportClient, AsyncResolvableUDP #endif return false; } - else - return true; + return true; } - else - return false; + return false; } void udp_read_handler(PacketFrom::SPtr &pfp) // called by LinkImpl diff --git a/openvpn/transport/dco.hpp b/openvpn/transport/dco.hpp index 4e84f0277..0756d4f6d 100644 --- a/openvpn/transport/dco.hpp +++ b/openvpn/transport/dco.hpp @@ -26,7 +26,7 @@ #include <openvpn/tun/client/tunbase.hpp> #include <openvpn/tun/client/tunprop.hpp> -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #include <openvpn/tun/win/client/tunsetup.hpp> #include <openvpn/tun/win/client/clientconfig.hpp> #endif @@ -34,7 +34,7 @@ namespace openvpn { struct DCO : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<DCO> Ptr; + using Ptr = RCPtr<DCO>; struct TransportConfig { @@ -53,9 +53,7 @@ struct DCO : public virtual RC<thread_unsafe_refcount> struct TunConfig { - TunConfig() = default; - -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN TunWin::SetupFactory::Ptr setup_factory; TunWin::SetupBase::Ptr new_setup_obj(openvpn_io::io_context &io_context, bool allow_local_dns_resolvers) diff --git a/openvpn/transport/mssfix.hpp b/openvpn/transport/mssfix.hpp index ef8e1885d..d43c3a1d1 100644 --- a/openvpn/transport/mssfix.hpp +++ b/openvpn/transport/mssfix.hpp @@ -115,7 +115,7 @@ class MSSFix { if (*opt == TCPHeader::OPT_EOL) break; - else if (*opt == TCPHeader::OPT_NOP) + if (*opt == TCPHeader::OPT_NOP) optlen = 1; else { diff --git a/openvpn/transport/mutate.hpp b/openvpn/transport/mutate.hpp index ecff7322d..5298e8836 100644 --- a/openvpn/transport/mutate.hpp +++ b/openvpn/transport/mutate.hpp @@ -20,7 +20,7 @@ namespace openvpn { class TransportMutateStream : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TransportMutateStream> Ptr; + using Ptr = RCPtr<TransportMutateStream>; virtual void pre_send(BufferAllocated &buf) = 0; virtual void post_recv(BufferAllocated &buf) = 0; diff --git a/openvpn/transport/protocol.hpp b/openvpn/transport/protocol.hpp index 385b3bd60..b49a2ff4b 100644 --- a/openvpn/transport/protocol.hpp +++ b/openvpn/transport/protocol.hpp @@ -314,15 +314,15 @@ class Protocol case NO_SUFFIX: break; case CLIENT_SUFFIX: - if (string::ends_with(s, "-client")) + if (s.ends_with("-client")) s = s.substr(0, s.length() - 7); break; case SERVER_SUFFIX: - if (string::ends_with(s, "-server")) + if (s.ends_with("-server")) s = s.substr(0, s.length() - 7); break; } - if (string::starts_with(s, "unix")) // unix domain socket + if (s.starts_with("unix")) // unix domain socket { if (s == "unix-stream") ret = UnixStream; @@ -335,7 +335,7 @@ class Protocol { const std::string s1 = s.substr(0, 3); const std::string s2 = s.substr(3); - if (s2 == "") + if (s2.empty()) { if (s1 == "udp") ret = UDP; diff --git a/openvpn/transport/server/transbase.hpp b/openvpn/transport/server/transbase.hpp index e138c8c86..40571d07a 100644 --- a/openvpn/transport/server/transbase.hpp +++ b/openvpn/transport/server/transbase.hpp @@ -49,7 +49,7 @@ namespace openvpn { // Base class for server transport object. struct TransportServer : public RC<thread_unsafe_refcount> { - typedef RCPtr<TransportServer> Ptr; + using Ptr = RCPtr<TransportServer>; virtual void start() = 0; virtual void stop() = 0; @@ -60,7 +60,7 @@ struct TransportServer : public RC<thread_unsafe_refcount> // Factory for server transport object. struct TransportServerFactory : public RC<thread_unsafe_refcount> { - typedef RCPtr<TransportServerFactory> Ptr; + using Ptr = RCPtr<TransportServerFactory>; virtual TransportServer::Ptr new_server_obj(openvpn_io::io_context &io_context) = 0; }; @@ -71,7 +71,7 @@ namespace TransportClientInstance { // Each client instance uses this class to send data to the transport layer. struct Send : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<Send> Ptr; + using Ptr = RCPtr<Send>; virtual bool defined() const = 0; virtual void stop() = 0; @@ -93,7 +93,7 @@ struct Send : public virtual RC<thread_unsafe_refcount> struct Recv : public virtual RC<thread_unsafe_refcount> { // clang-format off - typedef RCPtr<Recv> Ptr; + using Ptr = RCPtr<Recv>; virtual bool defined() const = 0; virtual void stop() = 0; @@ -146,7 +146,7 @@ struct Recv : public virtual RC<thread_unsafe_refcount> // Base class for factory used to create Recv objects. struct Factory : public RC<thread_unsafe_refcount> { - typedef RCPtr<Factory> Ptr; + using Ptr = RCPtr<Factory>; virtual Recv::Ptr new_client_instance() = 0; virtual bool validate_initial_packet(const BufferAllocated &net_buf) = 0; diff --git a/openvpn/transport/socket_protect.hpp b/openvpn/transport/socket_protect.hpp index e629c398a..1ee7c7b41 100644 --- a/openvpn/transport/socket_protect.hpp +++ b/openvpn/transport/socket_protect.hpp @@ -33,7 +33,7 @@ class BaseSocketProtect #ifdef OPENVPN_PLATFORM_UWP typedef UWPSocketProtect SocketProtect; #else -typedef BaseSocketProtect SocketProtect; +using SocketProtect = BaseSocketProtect; #endif } // namespace openvpn diff --git a/openvpn/transport/tcplink.hpp b/openvpn/transport/tcplink.hpp index 1ef5243b7..eb275d9c0 100644 --- a/openvpn/transport/tcplink.hpp +++ b/openvpn/transport/tcplink.hpp @@ -41,16 +41,15 @@ class TCPLink : public LinkCommon<Protocol, ReadHandler, RAW_MODE_ONLY> { - typedef std::deque<BufferPtr> Queue; + using Queue = std::deque<BufferPtr>; public: - typedef LinkCommon<Protocol, - ReadHandler, - RAW_MODE_ONLY> - Base; - typedef RCPtr<TCPLink> Ptr; + using Base = LinkCommon<Protocol, + ReadHandler, + RAW_MODE_ONLY>; + using Ptr = RCPtr<TCPLink>; - typedef Protocol protocol; + using protocol = Protocol; friend Base; @@ -71,12 +70,12 @@ class TCPLink : public LinkCommon<Protocol, private: // Called by LinkCommon - virtual void from_app_send_buffer(BufferPtr &buf) override + void from_app_send_buffer(BufferPtr &buf) override { Base::queue_send_buffer(buf); } - virtual void recv_buffer(PacketFrom::SPtr &pfp, const size_t bytes_recvd) override + void recv_buffer(PacketFrom::SPtr &pfp, const size_t bytes_recvd) override { bool requeue = true; OPENVPN_LOG_TCPLINK_VERBOSE("TCP recv raw=" diff --git a/openvpn/transport/tcplinkbase.hpp b/openvpn/transport/tcplinkbase.hpp index 7646b089b..b9daa1133 100644 --- a/openvpn/transport/tcplinkbase.hpp +++ b/openvpn/transport/tcplinkbase.hpp @@ -12,7 +12,7 @@ namespace openvpn::TCPTransport { struct PacketFrom { - typedef std::unique_ptr<PacketFrom> SPtr; + using SPtr = std::unique_ptr<PacketFrom>; BufferAllocated buf; }; @@ -24,7 +24,7 @@ class LinkBase : public RC<thread_unsafe_refcount> virtual void from_app_send_buffer(BufferPtr &buf) = 0; public: - typedef RCPtr<LinkBase> Ptr; + using Ptr = RCPtr<LinkBase>; virtual bool send_queue_empty() const = 0; virtual size_t send_queue_size() const = 0; diff --git a/openvpn/transport/tcplinkcommon.hpp b/openvpn/transport/tcplinkcommon.hpp index 2aed09b99..9aad8e78a 100644 --- a/openvpn/transport/tcplinkcommon.hpp +++ b/openvpn/transport/tcplinkcommon.hpp @@ -46,12 +46,12 @@ template <typename Protocol, bool RAW_MODE_ONLY> class LinkCommon : public LinkBase { - typedef std::deque<BufferPtr> Queue; + using Queue = std::deque<BufferPtr>; public: - typedef RCPtr<LinkCommon<Protocol, ReadHandler, RAW_MODE_ONLY>> Ptr; - typedef Protocol protocol; - typedef PacketStream<std::uint16_t> OpenVPNPacketStream; + using Ptr = RCPtr<LinkCommon<Protocol, ReadHandler, RAW_MODE_ONLY>>; + using protocol = Protocol; + using OpenVPNPacketStream = PacketStream<std::uint16_t>; // In raw mode, data is sent and received without any special encapsulation. // In non-raw mode, data is packetized by prepending a 16-bit length word @@ -251,16 +251,14 @@ class LinkCommon : public LinkBase { if (RAW_MODE_ONLY) return true; - else - return raw_mode_read; + return raw_mode_read; } bool is_raw_mode_write() const { if (RAW_MODE_ONLY) return true; - else - return raw_mode_write; + return raw_mode_write; } LinkCommon() @@ -406,7 +404,7 @@ class LinkCommon : public LinkBase stats->inc_stat(SessionStats::PACKETS_IN, 1); if (mutate) mutate->post_recv(buf); - while (buf.size()) + while (!buf.empty()) { pktstream.put(buf, frame_context); if (pktstream.ready()) diff --git a/openvpn/transport/udplink.hpp b/openvpn/transport/udplink.hpp index ea0cfc92d..3f2033919 100644 --- a/openvpn/transport/udplink.hpp +++ b/openvpn/transport/udplink.hpp @@ -41,7 +41,7 @@ namespace openvpn::UDPTransport { -typedef openvpn_io::ip::udp::endpoint AsioEndpoint; +using AsioEndpoint = openvpn_io::ip::udp::endpoint; enum { @@ -51,7 +51,7 @@ enum struct PacketFrom { - typedef std::unique_ptr<PacketFrom> SPtr; + using SPtr = std::unique_ptr<PacketFrom>; BufferAllocated buf; AsioEndpoint sender_endpoint; }; @@ -60,7 +60,7 @@ template <typename ReadHandler> class UDPLink : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<UDPLink> Ptr; + using Ptr = RCPtr<UDPLink>; UDPLink(ReadHandler read_handler_arg, openvpn_io::ip::udp::socket &socket_arg, @@ -185,12 +185,10 @@ class UDPLink : public RC<thread_unsafe_refcount> stats->inc_stat(SessionStats::PACKETS_OUT, 1); if (wrote == buf.size()) return 0; - else - { - OPENVPN_LOG_UDPLINK_ERROR("UDP partial send error"); - stats->error(Error::NETWORK_SEND_ERROR); - return SEND_PARTIAL; - } + + OPENVPN_LOG_UDPLINK_ERROR("UDP partial send error"); + stats->error(Error::NETWORK_SEND_ERROR); + return SEND_PARTIAL; } catch (openvpn_io::system_error &e) { @@ -209,7 +207,7 @@ class UDPLink : public RC<thread_unsafe_refcount> std::unique_ptr<AsioEndpoint> ep; if (endpoint) ep.reset(new AsioEndpoint(*endpoint)); - gremlin->send_queue([self = Ptr(this), buf = BufferAllocatedRc(buf, 0), ep = std::move(ep)]() mutable + gremlin->send_queue([self = Ptr(this), buf = BufferAllocated(buf), ep = std::move(ep)]() mutable { if (!self->halt) self->do_send(buf, ep.get()); }); diff --git a/openvpn/tun/builder/capture.hpp b/openvpn/tun/builder/capture.hpp index 6dc434ec3..1e81a7340 100644 --- a/openvpn/tun/builder/capture.hpp +++ b/openvpn/tun/builder/capture.hpp @@ -45,12 +45,24 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun // builder data classes + /** + * @brief Represents a remote %IP address with IPv4/IPv6 designation. + * @details This class encapsulates an %IP address string along with a flag indicating + * whether it's an %IPv6 address. It provides methods for validation, serialization, + * and checking if the address is defined. + */ class RemoteAddress { public: std::string address; bool ipv6 = false; + /** + * @brief Returns a string representation of the remote address. + * @details Formats the address as a string, appending " [IPv6]" suffix if + * the address is %IPv6. + * @return Formatted string representation of the address. + */ std::string to_string() const { std::string ret = address; @@ -59,17 +71,33 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return ret; } + /** + * @brief Checks if the address is defined. + * @details An address is considered defined if its string representation is not empty. + * @return @c true if the address is defined, @c false otherwise. + */ bool defined() const { return !address.empty(); } + /** + * @brief Validates the %IP address format. + * @details Uses the @c IP::Addr class to validate that the address string + * represents a valid %IPv4 or %IPv6 address based on the @c ipv6 flag. + * @param title A context string used in error messages if validation fails. + */ void validate(const std::string &title) const { IP::Addr(address, title, ipv6 ? IP::Addr::V6 : IP::Addr::V4); } #ifdef HAVE_JSON + /** + * @brief Serializes the object to a JSON value. + * @details Creates a JSON object with "address" and "ipv6" fields. + * @return A @c Json::Value object representing this remote address. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -78,6 +106,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Deserializes the object from a JSON value. + * @details Populates the object's fields from the given JSON object. + * @warning If input is not a valid JSON dictionary, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param root The JSON value to deserialize from. + * @param title A context string used in error messages if deserialization fails. + */ void from_json(const Json::Value &root, const std::string &title) { if (!json::is_dict(root, title)) @@ -88,6 +123,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Class for handling gateway rerouting configuration. + * @details This class encapsulates settings for redirecting gateway traffic in an OpenVPN connection, + * supporting both %IPv4 and %IPv6 protocols with configurable flags. It provides string representation + * and JSON serialization/deserialization capabilities (when JSON support is enabled). + */ class RerouteGW { public: @@ -95,6 +136,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun bool ipv6 = false; unsigned int flags = 0; + /** + * @brief Converts the object to a human-readable string representation. + * @details Creates a string describing the current state of the object, including IPv4/IPv6 status + * and flags using the @c RedirectGatewayFlags helper class. + * @return A string representation of the reroute gateway configuration. + */ std::string to_string() const { std::ostringstream os; @@ -105,6 +152,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #ifdef HAVE_JSON + /** + * @brief Serializes the object to a JSON value. + * @details Creates a JSON object containing the current %IPv4, %IPv6, and flags values. + * Only available when JSON support is enabled (HAVE_JSON defined). + * @return A JSON representation of the reroute gateway configuration. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -114,6 +167,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Deserializes the object from a JSON value. + * @details Populates the object's fields from a JSON object. + * Only available when JSON support is enabled (HAVE_JSON defined). + * @param root The JSON object to extract values from. + * @param title A title/context string used for error reporting. + */ void from_json(const Json::Value &root, const std::string &title) { json::assert_dict(root, title); @@ -124,6 +184,15 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Base class for route-related functionality representing a network route. + * @details This class serves as a base for route classes, providing common validation functionality. + * It encapsulates the components of a network route, including + * address, prefix length, gateway, and various options. It provides methods + * for string representation, JSON serialization/deserialization, and validation. + * The class handles both %IPv4 and %IPv6 routes, with special support for net30 + * routes commonly used in certain VPN configurations. + */ class RouteBase { public: @@ -134,6 +203,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun bool ipv6 = false; bool net30 = false; + /** + * @brief Converts the route to a human-readable string. + * @details Formats the route in CIDR notation (address/prefix_length), + * including gateway, metric, %IPv6 flag, and net30 flag if applicable. + * @return A string representation of the route. + */ std::string to_string() const { std::ostringstream os; @@ -150,6 +225,11 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } #ifdef HAVE_JSON + /** + * @brief Serializes the route to a JSON object. + * @details Creates a JSON object with keys for each route property. + * @return A JSON object representing the route. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -162,6 +242,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Deserializes the route from a JSON object. + * @details Populates the route properties from a JSON object. + * Throws exceptions if required fields are missing or have invalid types. + * @param root The JSON object to parse. + * @param title A string identifier used in error messages. + */ void from_json(const Json::Value &root, const std::string &title) { json::assert_dict(root, title); @@ -177,6 +264,16 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun protected: static constexpr int net30_prefix_length = 30; + /** + * @brief Protected validation method used by derived classes. + * @details Performs validation with different requirements based on the canonical flag. + * Checks if the route is valid and properly formatted. + * Validates address format, prefix length, gateway format if specified, + * and net30 compliance if required. + * @param title A string identifier used in error messages. + * @param require_canonical If @c true, verifies the route is in canonical form. + * @throws Exception if validation fails. + */ void validate_(const std::string &title, const bool require_canonical) const { const IP::Addr::Version ver = ipv6 ? IP::Addr::V6 : IP::Addr::V4; @@ -190,39 +287,79 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } }; + /** + * @brief %Route address class that may use non-canonical form. + * @details Extends RouteBase to represent a route address that doesn't necessarily need to be in canonical form. + */ class RouteAddress : public RouteBase // may be non-canonical { public: + /** + * @brief Validates the route address. + * @details Performs validation using @c false for the canonical parameter, allowing non-canonical forms. + * @param title A string identifier used in validation messages. + */ void validate(const std::string &title) const { validate_(title, false); } }; + /** + * @brief %Route class that must use canonical form. + * @details Extends RouteBase to represent a route that must be in canonical form. + */ class Route : public RouteBase // must be canonical { public: + /** + * @brief Validates the route. + * @details Performs validation using @c true for the canonical parameter, requiring canonical form. + * @param title A string identifier used in validation messages. + */ void validate(const std::string &title) const { validate_(title, true); } }; + /** + * @brief Class for managing proxy bypass host configurations. + * @details The ProxyBypass class provides functionality to store, validate, and + * serialize/deserialize information about a host that should bypass proxy settings. + */ class ProxyBypass { public: std::string bypass_host; + /** + * @brief Converts the bypass host to a string representation. + * @return The bypass host string. + */ std::string to_string() const { return bypass_host; } + /** + * @brief Checks if a bypass host is defined. + * @details Returns @c true if a bypass host is specified (non-empty string), + * @c false otherwise. + * @return @c true if bypass host is defined, @c false otherwise. + */ bool defined() const { return !bypass_host.empty(); } + /** + * @brief Validates the bypass host value. + * @details Validates the bypass host if defined using the HostPort validator. + * This ensures the host is properly formatted. + * @warning If bypass host is not defined, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param title A descriptive title used in error messages if validation fails. + */ void validate(const std::string &title) const { if (defined()) @@ -230,6 +367,11 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } #ifdef HAVE_JSON + /** + * @brief Serializes the object to JSON. + * @details Creates a JSON object with the bypass_host value. + * @return JSON value representing the ProxyBypass object. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -237,6 +379,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Deserializes the object from JSON. + * @details Extracts bypass_host value from the provided JSON object. + * @param root The JSON value to parse. + * @param title A descriptive title used in error messages if parsing fails. + */ void from_json(const Json::Value &root, const std::string &title) { json::assert_dict(root, title); @@ -245,21 +393,44 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Class for handling Proxy Auto-Configuration (PAC) URLs. + * @details This class provides functionality to store, validate, and convert + * a Proxy Auto-Configuration %URL. PAC files are JavaScript files that + * determine which proxy server (if any) to use for a given %URL. + */ class ProxyAutoConfigURL { public: std::string url; + /** + * @brief Returns the %URL as a string. + * @return The %URL string. + */ std::string to_string() const { return url; } + /** + * @brief Checks if the %URL is defined. + * @details A %URL is considered defined if it is not empty. + * @return @c true if the %URL is defined, @c false otherwise. + */ bool defined() const { return !url.empty(); } + /** + * @brief Validates the %URL format. + * @details Attempts to parse the %URL using the URL::Parse function to verify + * it has a valid format. Throws an exception if parsing fails. + * @warning If url is not defined, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param title A descriptive string to include in the exception message if validation fails. + * @throw Exception Throws an exception if the %URL is invalid. + */ void validate(const std::string &title) const { try @@ -274,6 +445,11 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } #ifdef HAVE_JSON + /** + * @brief Converts the %URL to a JSON object. + * @details Creates a JSON object with a single "url" field containing the %URL string. + * @return A JSON object representation of the %URL. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -281,6 +457,14 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Populates the %URL from a JSON object. + * @details Extracts the "url" field from the provided JSON object. + * Does nothing if the JSON is not an object. + * @warning If input is not a valid JSON dictionary, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param root The JSON object to extract the %URL from. + * @param title A descriptive string to include in error messages. + */ void from_json(const Json::Value &root, const std::string &title) { if (!json::is_dict(root, title)) @@ -290,12 +474,23 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Host and port configuration for proxy connections. + * @details This class stores and validates a host:port combination that represents + * a proxy server. It provides methods to check validity, convert to string + * representation, and serialize/deserialize from JSON (when available). + */ class ProxyHostPort { public: std::string host; int port = 0; + /** + * @brief Converts the host and port to a string representation. + * @details Creates a string in the format "host port". + * @return A string containing the host and port separated by a space. + */ std::string to_string() const { std::ostringstream os; @@ -303,11 +498,23 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return os.str(); } + /** + * @brief Checks if the proxy configuration is defined. + * @details A proxy is considered defined if the host is not empty. + * @return @c true if the host is not empty, @c false otherwise. + */ bool defined() const { return !host.empty(); } + /** + * @brief Validates the host and port. + * @details If the proxy is defined, validates both the host name and port number + * using the HostPort validation methods. + * @warning If host is not defined, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param title A context string used in error messages for validation. + */ void validate(const std::string &title) const { if (defined()) @@ -318,6 +525,11 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } #ifdef HAVE_JSON + /** + * @brief Converts the object to a JSON representation. + * @details Creates a JSON object with "host" and "port" fields. + * @return A JSON object containing the host and port values. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -326,6 +538,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Populates the object from a JSON representation. + * @details Extracts "host" and "port" fields from a JSON object. + * @warning If input is not a valid JSON dictionary, the method will return without processing and without raising any errors. This silent behavior may cause unexpected results. + * @param root The JSON object to parse. + * @param title A context string used in error messages during parsing. + */ void from_json(const Json::Value &root, const std::string &title) { if (!json::is_dict(root, title)) @@ -336,23 +555,45 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Windows Internet Name Service (WINS) server configuration. + * @details Represents a WINS server with its %IPv4 address. WINS provides name + * resolution services in Microsoft Windows networks, allowing NetBIOS + * names to be mapped to %IP addresses. + */ class WINSServer { public: std::string address; + /** + * @brief Converts the WINS server to a string representation. + * @return The WINS server's %IP address as a string. + */ std::string to_string() const { std::string ret = address; return ret; } + /** + * @brief Validates the WINS server address. + * @details Checks if the address is a valid %IPv4 address. Throws an exception + * if the address is invalid. + * @param title The context name used in error messages. + */ void validate(const std::string &title) const { IP::Addr(address, title, IP::Addr::V4); } #ifdef HAVE_JSON + /** + * @brief Serializes the WINS server to a JSON object. + * @details Creates a JSON object with the "address" field containing the + * server's %IP address. + * @return A JSON object representing the WINS server. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -360,6 +601,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Deserializes a WINS server from a JSON object. + * @details Extracts the "address" field from the JSON object and assigns it + * to the server address. + * @param root The JSON object to deserialize from. + * @param title The context name used in error messages. + */ void from_json(const Json::Value &root, const std::string &title) { json::assert_dict(root, title); @@ -368,6 +616,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #endif }; + /** + * @brief Sets the remote address for the TUN interface. + * @details Stores the remote endpoint address for the VPN tunnel connection. + * @param address The remote address string to set. + * @param ipv6 If @c true, indicates this is an %IPv6 address; if @c false, it's an %IPv4 address. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_remote_address(const std::string &address, bool ipv6) override { remote_address.address = address; @@ -375,6 +630,17 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Adds a local address to the TUN interface. + * @details Configures a local %IP address for the virtual network interface with specified + * prefix length and gateway. Maintains separate indices for %IPv4 and %IPv6 addresses. + * @param address The local %IP address to assign to the TUN interface. + * @param prefix_length The subnet prefix length (e.g., 24 for a /24 subnet). + * @param gateway The gateway address for this network. + * @param ipv6 If @c true, indicates this is an %IPv6 address; if @c false, it's an %IPv4 address. + * @param net30 If @c true, indicates this is a net30 topology (point-to-point with 4 addresses). + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_add_address(const std::string &address, int prefix_length, const std::string &gateway, bool ipv6, bool net30) override { RouteAddress r; @@ -391,6 +657,15 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Configures global gateway rerouting through the VPN tunnel. + * @details Sets up redirection of default traffic routes through the VPN tunnel + * for %IPv4 and/or %IPv6 traffic according to the specified flags. + * @param ipv4 If @c true, reroute %IPv4 default gateway. + * @param ipv6 If @c true, reroute %IPv6 default gateway. + * @param flags Special routing flags that modify the routing behavior. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override { reroute_gw.ipv4 = ipv4; @@ -399,12 +674,28 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets the default route metric for VPN routes. + * @details Configures the priority of routes added by the VPN, where lower + * metric values indicate higher priority routes. + * @param metric The metric value to assign to routes. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_route_metric_default(int metric) override { route_metric_default = metric; return true; } + /** + * @brief Adds a route to the tunnel. + * @details Configures a new route to be added to the routing table when the tunnel is established. + * @param address The destination network address. + * @param prefix_length The subnet prefix length (netmask). + * @param metric The route metric/priority value. If negative, a default metric will be used. + * @param ipv6 Whether this is an %IPv6 @c true or %IPv4 @c false route. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_add_route(const std::string &address, int prefix_length, int metric, bool ipv6) override { Route r; @@ -416,6 +707,16 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Excludes a route from the tunnel. + * @details Configures a route to be excluded from the tunnel routing, allowing traffic to that destination + * to bypass the VPN tunnel. + * @param address The destination network address to exclude. + * @param prefix_length The subnet prefix length (netmask). + * @param metric The route metric/priority value. + * @param ipv6 Whether this is an %IPv6 (@c true ) or %IPv4 (@c false ) route. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_exclude_route(const std::string &address, int prefix_length, int metric, bool ipv6) override { Route r; @@ -428,12 +729,10 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } /** - * @brief Set DNS options for use with tun builder - * - * Calling this invalidates any DNS related --dhcp-options previously added. - * - * @param dns The --dns options to be set - * @return true unconditionally + * @brief Set DNS options for use with tun builder. + * @details Calling this invalidates any DNS related @c --dhcp-options previously added. + * @param dns The @c --dns options to be set. + * @return Always returns @c true to indicate successful operation. */ bool tun_builder_set_dns_options(const DnsOptions &dns) override { @@ -441,24 +740,49 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets the tunnel's network layer. + * @details Configures which OSI layer the tunnel will operate at (typically layer 2 or 3). + * @param layer The network layer value to set. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_layer(int layer) override { this->layer = Layer::from_value(layer); return true; } + /** + * @brief Sets the Maximum Transmission Unit (MTU) for the tunnel. + * @details Configures the maximum packet size that can be transmitted through the tunnel. + * @param mtu The MTU value in bytes. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_mtu(int mtu) override { this->mtu = mtu; return true; } + /** + * @brief Sets a descriptive name for the VPN session. + * @details This name may be displayed in network connection UIs or logs. + * @param name The session name to set. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_session_name(const std::string &name) override { session_name = name; return true; } + /** + * @brief Adds a host to bypass proxy settings. + * @details Configures a host that should connect directly, bypassing any proxy settings + * when the VPN is active. + * @param bypass_host The hostname or address that should bypass the proxy. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_add_proxy_bypass(const std::string &bypass_host) override { ProxyBypass b; @@ -467,12 +791,26 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets the %URL for a proxy auto-configuration (PAC) file. + * @details Configures the VPN to use a PAC file at the specified %URL for determining + * proxy settings. + * @param url The %URL where the PAC file is located. + * @return Always returns @c true to indicate successful operation. + */ bool tun_builder_set_proxy_auto_config_url(const std::string &url) override { proxy_auto_config_url.url = url; return true; } + /** + * @brief Sets the %HTTP proxy for the tunnel. + * @details Configures the %HTTP proxy with the specified host and port. + * @param host The hostname or %IP address of the %HTTP proxy server. + * @param port The port number of the %HTTP proxy server. + * @return Always returns @c true to indicate successful configuration. + */ bool tun_builder_set_proxy_http(const std::string &host, int port) override { http_proxy.host = host; @@ -480,6 +818,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets the HTTPS proxy for the tunnel. + * @details Configures the HTTPS proxy with the specified host and port. + * @param host The hostname or %IP address of the HTTPS proxy server. + * @param port The port number of the HTTPS proxy server. + * @return Always returns @c true to indicate successful configuration. + */ bool tun_builder_set_proxy_https(const std::string &host, int port) override { https_proxy.host = host; @@ -487,6 +832,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Adds a WINS server to the tunnel configuration. + * @details Creates a new WINS server entry with the provided address and adds it to the list of WINS servers. + * @param address The %IP address of the WINS server. + * @return Always returns @c true to indicate successful addition. + */ bool tun_builder_add_wins_server(const std::string &address) override { WINSServer wins; @@ -495,6 +846,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets whether to allow a specific address family in the tunnel. + * @details Controls whether %IPv4 or %IPv6 traffic is allowed or blocked in the tunnel. + * @param af The address family to configure (AF_INET for %IPv4 or AF_INET6 for %IPv6). + * @param allow Whether to allow @c true or block @c false the specified address family. + * @return Always returns @c true to indicate successful configuration. + */ bool tun_builder_set_allow_family(int af, bool allow) override { if (af == AF_INET) @@ -504,12 +862,22 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return true; } + /** + * @brief Sets whether to allow local DNS resolution. + * @details Controls whether DNS requests can be resolved locally or must go through the VPN. + * @param allow Whether to allow @c true or block @c false local DNS resolution. + * @return Always returns @c true to indicate successful configuration. + */ bool tun_builder_set_allow_local_dns(bool allow) override { block_outside_dns = !allow; return true; } + /** + * @brief Resets all tunnel addresses. + * @details Clears the list of tunnel addresses and resets %IPv4 and %IPv6 address indices to invalid values. + */ void reset_tunnel_addresses() { tunnel_addresses.clear(); @@ -517,11 +885,20 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun tunnel_address_index_ipv6 = -1; } + /** + * @brief Resets DNS options to default values. + * @details Clears all DNS configuration options. + */ void reset_dns_options() { dns_options = DnsOptions(); } + /** + * @brief Gets the %IPv4 tunnel address. + * @details Returns a pointer to the RouteAddress structure for the %IPv4 tunnel if configured. + * @return Pointer to the %IPv4 tunnel address or @c nullptr if not configured. + */ const RouteAddress *vpn_ipv4() const { if (tunnel_address_index_ipv4 >= 0) @@ -529,6 +906,11 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return nullptr; } + /** + * @brief Gets the %IPv6 tunnel address. + * @details Returns a pointer to the RouteAddress structure for the %IPv6 tunnel if configured. + * @return Pointer to the %IPv6 tunnel address or @c nullptr if not configured. + */ const RouteAddress *vpn_ipv6() const { if (tunnel_address_index_ipv6 >= 0) @@ -536,6 +918,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return nullptr; } + /** + * @brief Gets the tunnel address for the specified %IP version. + * @details Returns a pointer to the RouteAddress structure for the specified %IP version. + * @param v The %IP address version (V4 or V6). + * @return Pointer to the tunnel address for the specified version or @c nullptr if not configured. + */ const RouteAddress *vpn_ip(const IP::Addr::Version v) const { switch (v) @@ -549,6 +937,12 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } } + /** + * @brief Validates the configuration of the tunnel. + * @details Performs validation on all components of the tunnel configuration, + * including layer settings, MTU, addresses, routes, and proxy settings. + * Each component's validate method is called with an appropriate context string. + */ void validate() const { validate_layer("root"); @@ -564,6 +958,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun https_proxy.validate("https_proxy"); } + /** + * @brief Converts the tunnel configuration to a human-readable string representation. + * @details Creates a formatted multi-line string containing all configured tunnel parameters + * including session name, layer, MTU, addresses, routing options, DNS settings, + * and proxy configurations. Only displays optional settings if they are defined. + * @return A string representation of the tunnel configuration. + */ std::string to_string() const { std::ostringstream os; @@ -600,6 +1001,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun #ifdef HAVE_JSON + /** + * @brief Serializes the tunnel configuration to a JSON object. + * @details Converts all tunnel parameters into a JSON representation, including + * session details, network configuration, routing options, and proxy settings. + * Optional settings are only included in the JSON if they are defined. + * @return A @c Json::Value object containing the serialized tunnel configuration. + */ Json::Value to_json() const { Json::Value root(Json::objectValue); @@ -629,6 +1037,15 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return root; } + /** + * @brief Creates a TunBuilderCapture instance from a JSON representation. + * @details Parses a JSON object to reconstruct a complete tunnel configuration, + * validating required fields and populating all configuration parameters. + * Uses helper methods from the json namespace to ensure proper type conversion + * and validation. + * @param root The JSON object containing the tunnel configuration. + * @return A shared pointer to a newly created TunBuilderCapture instance. + */ static TunBuilderCapture::Ptr from_json(const Json::Value &root) { const std::string title = "root"; @@ -685,6 +1102,15 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun static constexpr int mtu_ipv4_maximum = 65'535; private: + /** + * @brief Renders a list of elements to an output stream with a title. + * @details Outputs the title followed by each element in the list on a new line with indentation. + * Each element is rendered using its to_string() method. + * @param os The output stream to write to. + * @param title The title to display before the list. + * @param list The list of elements to render. + * @tparam LIST The list type which must contain elements with a to_string() method. + */ template <typename LIST> static void render_list(std::ostream &os, const std::string &title, const LIST &list) { @@ -695,6 +1121,14 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } } + /** + * @brief Validates each element in a list. + * @details Iterates through each element in the list and calls its validate() method + * with a title argument that includes the element's index. + * @param list The list of elements to validate. + * @param title The base title to use for validation messages. + * @tparam LIST The list type which must contain elements with a validate() method. + */ template <typename LIST> static void validate_list(const LIST &list, const std::string &title) { @@ -706,6 +1140,13 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun } } + /** + * @brief Checks if a tunnel index is valid. + * @details An index is considered valid if it's -1 (special value) or if it's within + * the range of available tunnel addresses (0 to @c tunnel_addresses.size() ). + * @param index The tunnel index to validate. + * @return @c true if the index is valid, @c false otherwise. + */ bool validate_tunnel_index(const int index) const { if (index == -1) @@ -713,6 +1154,14 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun return index >= 0 && static_cast<unsigned int>(index) <= tunnel_addresses.size(); } + /** + * @brief Validates tunnel address indices for both %IPv4 and %IPv6. + * @details Checks that both tunnel_address_index_ipv4 and tunnel_address_index_ipv6 are valid, + * and that they point to the correct address types (%IPv4 and %IPv6 respectively). + * Throws an exception if any validation fails. + * @param title The title to use in exception messages. + * @throws Exception if any validation fails, with a descriptive error message. + */ void validate_tunnel_address_indices(const std::string &title) const { if (!validate_tunnel_index(tunnel_address_index_ipv4)) @@ -727,12 +1176,26 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun OPENVPN_THROW_EXCEPTION(title << ".tunnel_address_index_ipv6 : IPv6 tunnel address index points to wrong address type: " << r6->to_string()); } + /** + * @brief Validates that the MTU value is within an acceptable range. + * @details Checks that the MTU is not negative and does not exceed mtu_ipv4_maximum. + * Throws an exception if validation fails. + * @param title The title to use in exception messages. + * @throws Exception if the MTU is out of range. + */ void validate_mtu(const std::string &title) const { if (mtu < 0 || mtu > mtu_ipv4_maximum) OPENVPN_THROW_EXCEPTION(title << ".mtu : MTU out of range: " << mtu); } + /** + * @brief Validates that the network layer is defined. + * @details Checks that the layer property has been properly initialized. + * Throws an exception if the layer is undefined. + * @param title The title to use in exception messages. + * @throws Exception if the layer is undefined. + */ void validate_layer(const std::string &title) const { if (!layer.defined()) @@ -741,4 +1204,4 @@ class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcoun }; } // namespace openvpn -#endif +#endif \ No newline at end of file diff --git a/openvpn/tun/builder/client.hpp b/openvpn/tun/builder/client.hpp index 4a10fc320..31ab24b94 100644 --- a/openvpn/tun/builder/client.hpp +++ b/openvpn/tun/builder/client.hpp @@ -180,8 +180,8 @@ class Client : public TunClient // persist state if (tun_persist->persist_tun_state(sd, state)) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl - << tun_persist->options()); + OPENVPN_LOG("TunPersist: saving tun context:\n" + << tun_persist->options()); impl.reset(new TunImpl(io_context, sd, diff --git a/openvpn/tun/builder/setup.hpp b/openvpn/tun/builder/setup.hpp index 4c675cc32..2e77ee012 100644 --- a/openvpn/tun/builder/setup.hpp +++ b/openvpn/tun/builder/setup.hpp @@ -31,14 +31,14 @@ struct Config struct Base : public DestructorBase { - typedef RCPtr<Base> Ptr; + using Ptr = RCPtr<Base>; virtual int establish(const TunBuilderCapture &pull, Config *config, Stop *stop, std::ostream &os) = 0; }; struct Factory : public RC<thread_unsafe_refcount> { - typedef RCPtr<Factory> Ptr; + using Ptr = RCPtr<Factory>; virtual Base::Ptr new_setup_obj() = 0; }; diff --git a/openvpn/tun/client/emuexr.hpp b/openvpn/tun/client/emuexr.hpp index 4f330d546..87da72e95 100644 --- a/openvpn/tun/client/emuexr.hpp +++ b/openvpn/tun/client/emuexr.hpp @@ -21,7 +21,7 @@ namespace openvpn { struct EmulateExcludeRoute : public RC<thread_unsafe_refcount> { - typedef RCPtr<EmulateExcludeRoute> Ptr; + using Ptr = RCPtr<EmulateExcludeRoute>; virtual void add_route(const bool add, const IP::Addr &addr, const int prefix_len) = 0; virtual bool enabled(const IPVerFlags &ipv) const = 0; @@ -31,7 +31,7 @@ struct EmulateExcludeRoute : public RC<thread_unsafe_refcount> struct EmulateExcludeRouteFactory : public RC<thread_unsafe_refcount> { - typedef RCPtr<EmulateExcludeRouteFactory> Ptr; + using Ptr = RCPtr<EmulateExcludeRouteFactory>; virtual EmulateExcludeRoute::Ptr new_obj() const = 0; }; diff --git a/openvpn/tun/client/tunbase.hpp b/openvpn/tun/client/tunbase.hpp index a4b91ba4b..8fd2b25bf 100644 --- a/openvpn/tun/client/tunbase.hpp +++ b/openvpn/tun/client/tunbase.hpp @@ -31,7 +31,7 @@ constexpr std::uint32_t INVALID_ADAPTER_INDEX = static_cast<std::uint32_t>(-1); // Base class for objects that implement a client tun interface. struct TunClient : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<TunClient> Ptr; + using Ptr = RCPtr<TunClient>; virtual void tun_start(const OptionList &, TransportClient &, CryptoDCSettings &) = 0; virtual void stop() = 0; @@ -99,7 +99,7 @@ struct TunClientParent // Factory for tun interface objects. struct TunClientFactory : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<TunClientFactory> Ptr; + using Ptr = RCPtr<TunClientFactory>; virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context, TunClientParent &parent, TransportClient *transcli) = 0; diff --git a/openvpn/tun/client/tunnull.hpp b/openvpn/tun/client/tunnull.hpp index 3a4166c06..bf344b588 100644 --- a/openvpn/tun/client/tunnull.hpp +++ b/openvpn/tun/client/tunnull.hpp @@ -21,7 +21,7 @@ namespace openvpn::TunNull { class ClientConfig : public TunClientFactory { public: - typedef RCPtr<ClientConfig> Ptr; + using Ptr = RCPtr<ClientConfig>; Frame::Ptr frame; SessionStats::Ptr stats; diff --git a/openvpn/tun/client/tunprop.hpp b/openvpn/tun/client/tunprop.hpp index 0ec29551f..905bcbf9c 100644 --- a/openvpn/tun/client/tunprop.hpp +++ b/openvpn/tun/client/tunprop.hpp @@ -77,7 +77,7 @@ class TunProp struct State : public RC<thread_unsafe_refcount> { - typedef RCPtr<State> Ptr; + using Ptr = RCPtr<State>; std::string iface_name; IP::Addr vpn_ip4_addr; @@ -424,13 +424,11 @@ class TunProp const std::string &target = o.ref(target_index); if (target == "vpn_gateway") return true; - else if (target == "net_gateway") + if (target == "net_gateway") return false; - else - throw tun_prop_route_error("route destinations other than vpn_gateway or net_gateway are not supported"); + throw tun_prop_route_error("route destinations other than vpn_gateway or net_gateway are not supported"); } - else - return true; + return true; } static void add_routes(TunBuilderBase *tb, @@ -595,12 +593,12 @@ class TunProp // Ignore DNS related options here continue; } - else if (type == "PROXY_BYPASS") + if (type == "PROXY_BYPASS") { o.min_args(3); for (size_t j = 2; j < o.size(); ++j) { - typedef std::vector<std::string> strvec; + using strvec = std::vector<std::string>; strvec v = Split::by_space<strvec, StandardLex, SpaceMatch, Split::NullLimit>(o.get(j, 256)); for (size_t k = 0; k < v.size(); ++k) { diff --git a/openvpn/tun/extern/fw.hpp b/openvpn/tun/extern/fw.hpp index f9adec88b..3a98b78d1 100644 --- a/openvpn/tun/extern/fw.hpp +++ b/openvpn/tun/extern/fw.hpp @@ -14,7 +14,7 @@ namespace openvpn { -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) +#ifdef OPENVPN_EXTERNAL_TUN_FACTORY struct TunClientFactory; class OptionList; diff --git a/openvpn/tun/layer.hpp b/openvpn/tun/layer.hpp index 8d6714a0a..f53bdbacb 100644 --- a/openvpn/tun/layer.hpp +++ b/openvpn/tun/layer.hpp @@ -92,24 +92,22 @@ class Layer { if (str == "OSI_LAYER_3") return Layer(OSI_LAYER_3); - else if (str == "OSI_LAYER_2") + if (str == "OSI_LAYER_2") return Layer(OSI_LAYER_2); - else if (str == "UNDEF_LAYER") + if (str == "UNDEF_LAYER") return Layer(NONE); - else - throw Exception("Layer: unrecognized layer string"); + throw Exception("Layer: unrecognized layer string"); } static Layer from_value(const int value) { if (value == 3) return Layer(OSI_LAYER_3); - else if (value == 2) + if (value == 2) return Layer(OSI_LAYER_2); - else if (value == 0) + if (value == 0) return Layer(NONE); - else - throw Exception("Layer: unrecognized layer value"); + throw Exception("Layer: unrecognized layer value"); } bool operator==(const Layer &other) const diff --git a/openvpn/tun/linux/client/genl.hpp b/openvpn/tun/linux/client/genl.hpp index cdf1fb6d4..ce34da9fa 100644 --- a/openvpn/tun/linux/client/genl.hpp +++ b/openvpn/tun/linux/client/genl.hpp @@ -29,10 +29,39 @@ #include <memory> +/* The following enum members exist in netlink.h since linux-6.1. + * However, some distro we support still ship an old header, thus + * failing the OpenVPN compilation. + * + * For the time being we add the needed defines manually. + * We will drop this definition once we stop supporting those old + * distros. + * + * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute, + * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was + * missing at the message level + * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing + */ +enum ovpn_nlmsgerr_attrs +{ + OVPN_NLMSGERR_ATTR_MISS_TYPE = 5, + OVPN_NLMSGERR_ATTR_MISS_NEST = 6, + OVPN_NLMSGERR_ATTR_MAX = 6, +}; + namespace openvpn { #define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED) +/* libnl < 3.11.0 does not implement nla_get_uint() */ +static uint64_t ovpn_nla_get_uint(struct nlattr *attr) +{ + if (nla_len(attr) == sizeof(uint32_t)) + return nla_get_u32(attr); + else + return nla_get_u64(attr); +} + typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg); struct OvpnDcoPeer @@ -71,7 +100,7 @@ struct OvpnDcoPeer * * buf has following layout: * \li first byte - command type ( \p OVPN_CMD_DEL_PEER or -1 for error) - * \li following bytes - command-specific payload + * \li following bytes - command-specific payload */ template <typename ReadHandler> class GeNL : public RC<thread_unsafe_refcount> @@ -96,7 +125,7 @@ class GeNL : public RC<thread_unsafe_refcount> int nl_family_id = -1; if (sock_ptr && genl_connect(sock_ptr.get()) == 0) - nl_family_id = genl_ctrl_resolve(sock_ptr.get(), OVPN_NL_NAME); + nl_family_id = genl_ctrl_resolve(sock_ptr.get(), OVPN_FAMILY_NAME); return nl_family_id >= 0; } @@ -127,6 +156,11 @@ class GeNL : public RC<thread_unsafe_refcount> OPENVPN_THROW(netlink_error, " cannot connect to generic netlink: " << nl_geterror(ret)); + ret = 1; + if (setsockopt(nl_socket_get_fd(sock), SOL_NETLINK, NETLINK_EXT_ACK, &ret, sizeof(ret)) < 0) + OPENVPN_THROW(netlink_error, + " cannot enable NETLINK_EXT_ACK on socket: " << errno); + int mcast_id = get_mcast_id(); if (mcast_id < 0) OPENVPN_THROW(netlink_error, @@ -136,7 +170,7 @@ class GeNL : public RC<thread_unsafe_refcount> if (ret) OPENVPN_THROW(netlink_error, "failed to join mcast group: " << ret); - ovpn_dco_id = genl_ctrl_resolve(sock, OVPN_NL_NAME); + ovpn_dco_id = genl_ctrl_resolve(sock, OVPN_FAMILY_NAME); if (ovpn_dco_id < 0) OPENVPN_THROW(netlink_error, " cannot find ovpn_dco netlink component: " << ovpn_dco_id); @@ -182,23 +216,38 @@ class GeNL : public RC<thread_unsafe_refcount> IPv4::Addr vpn4, IPv6::Addr vpn6) { - auto msg_ptr = create_msg(OVPN_CMD_NEW_PEER); + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + auto msg_ptr = create_msg(OVPN_CMD_PEER_NEW); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_NEW_PEER); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER); - NLA_PUT_U32(msg, OVPN_NEW_PEER_ATTR_PEER_ID, peer_id); - NLA_PUT_U32(msg, OVPN_NEW_PEER_ATTR_SOCKET, fd); - NLA_PUT(msg, OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE, salen, sa); + NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id); + NLA_PUT_U32(msg, OVPN_A_PEER_SOCKET, fd); + if (sa->sa_family == AF_INET) + { + NLA_PUT_U32(msg, OVPN_A_PEER_REMOTE_IPV4, sin->sin_addr.s_addr); + } + else if (sa->sa_family == AF_INET6) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + NLA_PUT(msg, OVPN_A_PEER_REMOTE_IPV6, sizeof(sin6->sin6_addr), &sin6->sin6_addr); + NLA_PUT_U32(msg, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, sin6->sin6_scope_id); + } + else + { + OPENVPN_THROW(netlink_error, " new_peer() bogus remote address family " << sa->sa_family); + } + NLA_PUT_U16(msg, OVPN_A_PEER_REMOTE_PORT, sin->sin_port); if (vpn4.specified()) { - NLA_PUT_U32(msg, OVPN_NEW_PEER_ATTR_IPV4, vpn4.to_uint32_net()); + NLA_PUT_U32(msg, OVPN_A_PEER_VPN_IPV4, vpn4.to_uint32_net()); } if (vpn6.specified()) { struct in6_addr addr6 = vpn6.to_in6_addr(); - NLA_PUT(msg, OVPN_NEW_PEER_ATTR_IPV6, sizeof(addr6), &addr6); + NLA_PUT(msg, OVPN_A_PEER_VPN_IPV6, sizeof(addr6), &addr6); } nla_nest_end(msg, attr); @@ -219,45 +268,45 @@ class GeNL : public RC<thread_unsafe_refcount> */ void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc) { - auto msg_ptr = create_msg(OVPN_CMD_NEW_KEY); + auto msg_ptr = create_msg(OVPN_CMD_KEY_NEW); auto *msg = msg_ptr.get(); const int NONCE_TAIL_LEN = 8; struct nlattr *key_dir; - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_NEW_KEY); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF); if (!attr) OPENVPN_THROW(netlink_error, " new_key() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_NEW_KEY_ATTR_PEER_ID, kc->remote_peer_id); - NLA_PUT_U8(msg, OVPN_NEW_KEY_ATTR_KEY_SLOT, static_cast<uint8_t>(key_slot)); - NLA_PUT_U8(msg, OVPN_NEW_KEY_ATTR_KEY_ID, static_cast<uint8_t>(kc->key_id)); - NLA_PUT_U16(msg, OVPN_NEW_KEY_ATTR_CIPHER_ALG, static_cast<uint16_t>(kc->cipher_alg)); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, kc->remote_peer_id); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_SLOT, key_slot); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_KEY_ID, kc->key_id); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_CIPHER_ALG, kc->cipher_alg); - key_dir = nla_nest_start(msg, OVPN_NEW_KEY_ATTR_ENCRYPT_KEY); + key_dir = nla_nest_start(msg, OVPN_A_KEYCONF_ENCRYPT_DIR); if (!key_dir) OPENVPN_THROW(netlink_error, " new_key() cannot allocate encrypt key submessage"); - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->encrypt.cipher_key_size, kc->encrypt.cipher_key); + NLA_PUT(msg, OVPN_A_KEYDIR_CIPHER_KEY, kc->encrypt.cipher_key_size, kc->encrypt.cipher_key); if (kc->cipher_alg == OVPN_CIPHER_ALG_AES_GCM || kc->cipher_alg == OVPN_CIPHER_ALG_CHACHA20_POLY1305) { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_TAIL_LEN, kc->encrypt.nonce_tail); + NLA_PUT(msg, OVPN_A_KEYDIR_NONCE_TAIL, NONCE_TAIL_LEN, kc->encrypt.nonce_tail); } nla_nest_end(msg, key_dir); - key_dir = nla_nest_start(msg, OVPN_NEW_KEY_ATTR_DECRYPT_KEY); + key_dir = nla_nest_start(msg, OVPN_A_KEYCONF_DECRYPT_DIR); if (!key_dir) OPENVPN_THROW(netlink_error, " new_key() cannot allocate decrypt key submessage"); - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->decrypt.cipher_key_size, kc->decrypt.cipher_key); + NLA_PUT(msg, OVPN_A_KEYDIR_CIPHER_KEY, kc->decrypt.cipher_key_size, kc->decrypt.cipher_key); if (kc->cipher_alg == OVPN_CIPHER_ALG_AES_GCM || kc->cipher_alg == OVPN_CIPHER_ALG_CHACHA20_POLY1305) { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_TAIL_LEN, kc->decrypt.nonce_tail); + NLA_PUT(msg, OVPN_A_KEYDIR_NONCE_TAIL, NONCE_TAIL_LEN, kc->decrypt.nonce_tail); } nla_nest_end(msg, key_dir); @@ -279,13 +328,13 @@ class GeNL : public RC<thread_unsafe_refcount> */ void swap_keys(int peer_id) { - auto msg_ptr = create_msg(OVPN_CMD_SWAP_KEYS); + auto msg_ptr = create_msg(OVPN_CMD_KEY_SWAP); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_SWAP_KEYS); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF); if (!attr) OPENVPN_THROW(netlink_error, " swap_keys() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peer_id); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, peer_id); nla_nest_end(msg, attr); @@ -305,14 +354,14 @@ class GeNL : public RC<thread_unsafe_refcount> */ void del_key(int peer_id, unsigned int key_slot) { - auto msg_ptr = create_msg(OVPN_CMD_DEL_KEY); + auto msg_ptr = create_msg(OVPN_CMD_KEY_DEL); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_DEL_KEY); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF); if (!attr) OPENVPN_THROW(netlink_error, " del_key() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_DEL_KEY_ATTR_PEER_ID, peer_id); - NLA_PUT_U8(msg, OVPN_DEL_KEY_ATTR_KEY_SLOT, static_cast<uint8_t>(key_slot)); + NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, peer_id); + NLA_PUT_U8(msg, OVPN_A_KEYCONF_SLOT, static_cast<uint8_t>(key_slot)); nla_nest_end(msg, attr); @@ -335,15 +384,15 @@ class GeNL : public RC<thread_unsafe_refcount> */ void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout) { - auto msg_ptr = create_msg(OVPN_CMD_SET_PEER); + auto msg_ptr = create_msg(OVPN_CMD_PEER_SET); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_SET_PEER); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER); if (!attr) OPENVPN_THROW(netlink_error, " set_peer() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_SET_PEER_ATTR_PEER_ID, peer_id); - NLA_PUT_U32(msg, OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL, keepalive_interval); - NLA_PUT_U32(msg, OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT, keepalive_timeout); + NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id); + NLA_PUT_U32(msg, OVPN_A_PEER_KEEPALIVE_INTERVAL, keepalive_interval); + NLA_PUT_U32(msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, keepalive_timeout); nla_nest_end(msg, attr); @@ -362,13 +411,13 @@ class GeNL : public RC<thread_unsafe_refcount> */ void del_peer(int peer_id) { - auto msg_ptr = create_msg(OVPN_CMD_DEL_PEER); + auto msg_ptr = create_msg(OVPN_CMD_PEER_DEL); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_DEL_PEER); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER); if (!attr) OPENVPN_THROW(netlink_error, " del_peer() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_DEL_PEER_ATTR_PEER_ID, peer_id); + NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id); nla_nest_end(msg, attr); @@ -388,13 +437,13 @@ class GeNL : public RC<thread_unsafe_refcount> */ void get_peer(int peer_id, bool sync) { - auto msg_ptr = create_msg(OVPN_CMD_GET_PEER); + auto msg_ptr = create_msg(OVPN_CMD_PEER_GET); auto *msg = msg_ptr.get(); - struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_GET_PEER); + struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER); if (!attr) OPENVPN_THROW(netlink_error, " get_peer() cannot allocate submessage"); - NLA_PUT_U32(msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id); + NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id); nla_nest_end(msg, attr); @@ -493,8 +542,8 @@ class GeNL : public RC<thread_unsafe_refcount> } /** - * Return id of multicast group which ovpn-dco uses to - * broadcast OVPN_CMD_DEL_PEER message + * Return id of multicast group which ovpn uses to + * broadcast OVPN_CMD_*_NTF messages * * @return int multicast group id */ @@ -502,7 +551,7 @@ class GeNL : public RC<thread_unsafe_refcount> { int ret = 1; struct mcast_handler_args grp = { - .group = OVPN_NL_MULTICAST_GROUP_PEERS, + .group = OVPN_MCGRP_PEERS, .id = -ENOENT, }; NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free); @@ -514,7 +563,7 @@ class GeNL : public RC<thread_unsafe_refcount> int ctrlid = genl_ctrl_resolve(sock, "nlctrl"); genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0); - NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME); + NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, OVPN_FAMILY_NAME); send_netlink_message(msg); @@ -590,11 +639,11 @@ class GeNL : public RC<thread_unsafe_refcount> }); } - NlMsgPtr create_msg(enum ovpn_nl_commands cmd) + NlMsgPtr create_msg(int cmd) { NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free); genlmsg_put(msg_ptr.get(), 0, 0, ovpn_dco_id, 0, 0, cmd, 0); - NLA_PUT_U32(msg_ptr.get(), OVPN_ATTR_IFINDEX, ifindex); + NLA_PUT_U32(msg_ptr.get(), OVPN_A_IFINDEX, ifindex); return msg_ptr; nla_put_failure: @@ -639,7 +688,7 @@ class GeNL : public RC<thread_unsafe_refcount> struct genlmsghdr *gnlh = static_cast<genlmsghdr *>( nlmsg_data(reinterpret_cast<const nlmsghdr *>(nlmsg_hdr(msg)))); struct nlmsghdr *nlh = nlmsg_hdr(msg); - struct nlattr *attrs[OVPN_ATTR_MAX + 1]; + struct nlattr *attrs[OVPN_A_MAX + 1]; if (!genlmsg_valid_hdr(nlh, 0)) { @@ -647,7 +696,7 @@ class GeNL : public RC<thread_unsafe_refcount> return NL_SKIP; } - if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL)) + if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL)) { OPENVPN_LOG("received bogus data from ovpn-dco"); return NL_SKIP; @@ -655,91 +704,94 @@ class GeNL : public RC<thread_unsafe_refcount> switch (gnlh->cmd) { - case OVPN_CMD_DEL_PEER: - if (!attrs[OVPN_ATTR_IFINDEX]) + case OVPN_CMD_PEER_DEL_NTF: + if (!attrs[OVPN_A_IFINDEX]) { - OPENVPN_LOG("missing OVPN_ATTR_IFINDEX attribute in message"); + OPENVPN_LOG("missing OVPN_A_IFINDEX attribute in message"); return NL_SKIP; } - if (self->ifindex != nla_get_u32(attrs[OVPN_ATTR_IFINDEX])) + if (self->ifindex != nla_get_u32(attrs[OVPN_A_IFINDEX])) return NL_SKIP; - if (!attrs[OVPN_ATTR_DEL_PEER]) - OPENVPN_THROW(netlink_error, "missing OVPN_ATTR_DEL_PEER attribute in " - "OVPN_CMD_DEL_PEER command"); + if (!attrs[OVPN_A_PEER]) + OPENVPN_THROW(netlink_error, "missing OVPN_A_PEER attribute in " + "OVPN_CMD_PEER_DEL_NTF message"); - struct nlattr *del_peer_attrs[OVPN_DEL_PEER_ATTR_MAX + 1]; - ret = nla_parse_nested(del_peer_attrs, OVPN_DEL_PEER_ATTR_MAX, attrs[OVPN_ATTR_DEL_PEER], NULL); + struct nlattr *del_peer_attrs[OVPN_A_PEER_MAX + 1]; + ret = nla_parse_nested(del_peer_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL); if (ret) OPENVPN_THROW(netlink_error, - "cannot parse OVPN_ATTR_DEL_PEER attribute"); + "cannot parse OVPN_A_PEER attribute"); - if (!del_peer_attrs[OVPN_DEL_PEER_ATTR_PEER_ID] || !del_peer_attrs[OVPN_DEL_PEER_ATTR_REASON]) - OPENVPN_THROW(netlink_error, "missing attributes in OVPN_CMD_DEL_PEER"); + if (!del_peer_attrs[OVPN_A_PEER_ID] || !del_peer_attrs[OVPN_A_PEER_DEL_REASON]) + OPENVPN_THROW(netlink_error, "missing attributes in OVPN_CMD_PEER_DEL_NTF"); self->reset_buffer(); self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd)); { - uint32_t peer_id = nla_get_u32(del_peer_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]); + uint32_t peer_id = nla_get_u32(del_peer_attrs[OVPN_A_PEER_ID]); self->buf.write(&peer_id, sizeof(peer_id)); } { - uint8_t reason = nla_get_u8(del_peer_attrs[OVPN_DEL_PEER_ATTR_REASON]); + uint8_t reason = nla_get_u8(del_peer_attrs[OVPN_A_PEER_DEL_REASON]); self->buf.write(&reason, sizeof(reason)); } self->read_handler->tun_read_handler(self->buf); break; - case OVPN_CMD_GET_PEER: + case OVPN_CMD_PEER_GET: { - if (!attrs[OVPN_ATTR_GET_PEER]) - OPENVPN_THROW(netlink_error, "missing OVPN_ATTR_GET_PEER attribute in " - "OVPN_CMD_GET_PEER command reply"); + if (!attrs[OVPN_A_PEER]) + OPENVPN_THROW(netlink_error, "missing OVPN_A_PEER attribute in " + "OVPN_CMD_PEER_GET command reply"); - struct nlattr *get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_MAX + 1]; - ret = nla_parse_nested(get_peer_attrs, OVPN_GET_PEER_RESP_ATTR_MAX, attrs[OVPN_ATTR_GET_PEER], NULL); + struct nlattr *get_peer_attrs[OVPN_A_PEER_MAX + 1]; + ret = nla_parse_nested(get_peer_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL); if (ret) - OPENVPN_THROW(netlink_error, "cannot parse OVPN_ATTR_GET_PEER attribute"); + OPENVPN_THROW(netlink_error, "cannot parse OVPN_A_PEER attribute"); - if (!get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_PEER_ID]) - OPENVPN_THROW(netlink_error, "missing attributes in OVPN_CMD_DEL_PEER"); + if (!get_peer_attrs[OVPN_A_PEER_ID]) + OPENVPN_THROW(netlink_error, "missing attribute PEER_ID in OVPN_CMD_PEER_GET reply"); struct OvpnDcoPeer peer = {0}; - peer.id = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_PEER_ID]); - - if (get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV4]) + peer.id = nla_get_u32(get_peer_attrs[OVPN_A_PEER_ID]); + + /* peer.remote is expected to contain the remote endpoint encoded in a + * sockaddr object. However, ovpn now sends us address, port and scope_id + * all separated, which means we need to manually "build" a sockaddr here. + * Since peer.remote is currently unused in the rest of the codebase, we + * can postpone this complexity. + * + * TODO: fill peer.remote with a sockaddr object built out of the remote + * attrs send by ovpn + */ + + if (get_peer_attrs[OVPN_A_PEER_VPN_IPV4]) { - memcpy(&peer.ipv4, nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV4]), sizeof(peer.ipv4)); + memcpy(&peer.ipv4, nla_data(get_peer_attrs[OVPN_A_PEER_VPN_IPV4]), sizeof(peer.ipv4)); } - if (get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV6]) + if (get_peer_attrs[OVPN_A_PEER_VPN_IPV6]) { - memcpy(&peer.ipv6, nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV6]), sizeof(peer.ipv6)); + memcpy(&peer.ipv6, nla_data(get_peer_attrs[OVPN_A_PEER_VPN_IPV6]), sizeof(peer.ipv6)); } - peer.local_port = nla_get_u16(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LOCAL_PORT]); - - if (get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE]) - { - memcpy(&peer.remote, - nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE]), - nla_len(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE])); - } + peer.local_port = nla_get_u16(get_peer_attrs[OVPN_A_PEER_LOCAL_PORT]); - peer.keepalive.interval = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_INTERVAL]); - peer.keepalive.timeout = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_TIMEOUT]); - peer.vpn.rx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]); - peer.vpn.tx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]); - peer.vpn.rx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_RX_PACKETS]); - peer.vpn.tx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_TX_PACKETS]); + peer.keepalive.interval = nla_get_u32(get_peer_attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL]); + peer.keepalive.timeout = nla_get_u32(get_peer_attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]); + peer.vpn.rx_bytes = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_VPN_RX_BYTES]); + peer.vpn.tx_bytes = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_VPN_TX_BYTES]); + peer.vpn.rx_pkts = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_VPN_RX_PACKETS]); + peer.vpn.tx_pkts = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_VPN_TX_PACKETS]); - peer.transport.rx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]); - peer.transport.tx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]); - peer.transport.rx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_RX_PACKETS]); - peer.transport.tx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_TX_PACKETS]); + peer.transport.rx_bytes = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_LINK_RX_BYTES]); + peer.transport.tx_bytes = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_LINK_TX_BYTES]); + peer.transport.rx_pkts = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_LINK_RX_PACKETS]); + peer.transport.tx_pkts = ovpn_nla_get_uint(get_peer_attrs[OVPN_A_PEER_LINK_TX_PACKETS]); self->reset_buffer(); self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd)); @@ -777,7 +829,7 @@ class GeNL : public RC<thread_unsafe_refcount> void *arg) { struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1; - struct nlattr *tb_msg[NLMSGERR_ATTR_MAX + 1]; + struct nlattr *tb_msg[OVPN_NLMSGERR_ATTR_MAX + 1]; int len = nlh->nlmsg_len; struct nlattr *attrs; int *ret = static_cast<int *>(arg); @@ -804,6 +856,18 @@ class GeNL : public RC<thread_unsafe_refcount> << (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG])); } + if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST]) + { + OPENVPN_LOG(__func__ << "missing required nesting type " + << nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST])); + } + + if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE]) + { + OPENVPN_LOG(__func__ << "missing required attribute type " + << nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE])); + } + return NL_STOP; } diff --git a/openvpn/tun/linux/client/sitnl.hpp b/openvpn/tun/linux/client/sitnl.hpp index 53df676fe..50029e1cc 100644 --- a/openvpn/tun/linux/client/sitnl.hpp +++ b/openvpn/tun/linux/client/sitnl.hpp @@ -86,7 +86,7 @@ class SITNL char buf[256]; }; - typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *msg, void *arg); + using sitnl_parse_reply_cb = int (*)(struct nlmsghdr *msg, void *arg); /** * Helper function used to easily add attributes to a rtnl message @@ -407,7 +407,7 @@ class SITNL } /* store the route entry resulting from the query */ - typedef struct + struct route_res_t { sa_family_t family; IP::Addr gw; @@ -416,7 +416,7 @@ class SITNL int metric; IP::Route dst; int prefix_len; - } route_res_t; + }; static int sitnl_route_save(struct nlmsghdr *n, void *arg) @@ -501,10 +501,9 @@ class SITNL { return 0; } - else - { - OPENVPN_LOG_RTNL(__func__ << ": RTA_GATEWAY " << gw.to_string()); - } + + OPENVPN_LOG_RTNL(__func__ << ": RTA_GATEWAY " << gw.to_string()); + if (!route.contains(res->dst)) { @@ -626,12 +625,12 @@ class SITNL } /* state info for sitnl_iface_addr_save() */ - typedef struct + struct iface_addr_res_t { sa_family_t family; __u32 ifindex; IP::Route route; - } iface_addr_res_t; + }; static int sitnl_iface_addr_save(struct nlmsghdr *n, void *arg) diff --git a/openvpn/tun/linux/client/tuncli.hpp b/openvpn/tun/linux/client/tuncli.hpp index 08756d10a..b60f66d95 100644 --- a/openvpn/tun/linux/client/tuncli.hpp +++ b/openvpn/tun/linux/client/tuncli.hpp @@ -20,23 +20,23 @@ #include <openvpn/tun/builder/setup.hpp> #include <openvpn/tun/tunio.hpp> #include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/linux/client/tunmethods.hpp> +#include <openvpn/tun/linux/client/tunnetlink.hpp> namespace openvpn::TunLinux { struct PacketFrom { - typedef std::unique_ptr<PacketFrom> SPtr; + using SPtr = std::unique_ptr<PacketFrom>; BufferAllocated buf; }; template <typename ReadHandler> class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> { - typedef TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> Base; + using Base = TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor>; public: - typedef RCPtr<Tun> Ptr; + using Ptr = RCPtr<Tun>; Tun(openvpn_io::io_context &io_context, ReadHandler read_handler_arg, @@ -58,12 +58,12 @@ class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_desc } }; -typedef TunPersistTemplate<ScopedFD> TunPersist; +using TunPersist = TunPersistTemplate<ScopedFD>; class ClientConfig : public TunClientFactory { public: - typedef RCPtr<ClientConfig> Ptr; + using Ptr = RCPtr<ClientConfig>; std::string dev_name; int txqueuelen = 200; @@ -107,8 +107,7 @@ class ClientConfig : public TunClientFactory { if (tun_setup_factory) return tun_setup_factory->new_setup_obj(); - else - return new TunLinuxSetup::Setup<TUN_LINUX>(); + return new TunLinuxSetup::Setup<TunNetlink::TunMethods>(); } bool supports_epoch_data() override @@ -118,9 +117,7 @@ class ClientConfig : public TunClientFactory } private: - ClientConfig() - { - } + ClientConfig() = default; }; class Client : public TunClient @@ -128,7 +125,7 @@ class Client : public TunClient friend class ClientConfig; // calls constructor friend class TunIO<Client *, PacketFrom, openvpn_io::posix::stream_descriptor>; // calls tun_read_handler - typedef Tun<Client *> TunImpl; + using TunImpl = Tun<Client *>; public: void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override @@ -181,14 +178,14 @@ class Client : public TunClient nullptr, false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); // create new tun setup object tun_setup = config->new_setup_obj(); // create config object for tun setup layer - TunLinuxSetup::Setup<TUN_LINUX>::Config tsconf; + TunLinuxSetup::Setup<TunNetlink::TunMethods>::Config tsconf; tsconf.layer = config->tun_prop.layer; tsconf.dev_name = config->dev_name; tsconf.txqueuelen = config->txqueuelen; @@ -202,7 +199,7 @@ class Client : public TunClient sd = tun_setup->establish(*po, &tsconf, nullptr, os); } -#if defined(HAVE_JSON) +#ifdef HAVE_JSON if (config->generate_tun_builder_capture_event) { // create an event with TunBuilderCapture data as JSON @@ -250,40 +247,35 @@ class Client : public TunClient { if (impl) return impl->name(); - else - return "UNDEF_TUN"; + return "UNDEF_TUN"; } std::string vpn_ip4() const override { if (state->vpn_ip4_addr.specified()) return state->vpn_ip4_addr.to_string(); - else - return ""; + return ""; } std::string vpn_ip6() const override { if (state->vpn_ip6_addr.specified()) return state->vpn_ip6_addr.to_string(); - else - return ""; + return ""; } std::string vpn_gw4() const override { if (state->vpn_ip4_gw.specified()) return state->vpn_ip4_gw.to_string(); - else - return ""; + return ""; } std::string vpn_gw6() const override { if (state->vpn_ip6_gw.specified()) return state->vpn_ip6_gw.to_string(); - else - return ""; + return ""; } int vpn_mtu() const override @@ -337,8 +329,7 @@ class Client : public TunClient { if (impl) return impl->write(buf); - else - return false; + return false; } void tun_read_handler(PacketFrom::SPtr &pfp) // called by TunImpl diff --git a/openvpn/tun/linux/client/tuniproute.hpp b/openvpn/tun/linux/client/tuniproute.hpp deleted file mode 100644 index 71947d13f..000000000 --- a/openvpn/tun/linux/client/tuniproute.hpp +++ /dev/null @@ -1,344 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -#pragma once - -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <net/if.h> -#include <linux/if_tun.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/tun/builder/setup.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/client/tunconfigflags.hpp> -#include <openvpn/tun/linux/client/tunsetup.hpp> -#include <openvpn/netconf/linux/gw.hpp> - -namespace openvpn::TunIPRoute { - -using namespace openvpn::TunLinuxSetup; - -enum -{ // add_del_route flags - R_IPv6 = (1 << 0), - R_ADD_SYS = (1 << 1), - R_ADD_DCO = (1 << 2), - R_ADD_ALL = R_ADD_SYS | R_ADD_DCO, -}; - -inline IP::Addr cvt_pnr_ip_v4(const std::string &hexaddr) -{ - BufferAllocated v(4, BufAllocFlags::CONSTRUCT_ZERO); - parse_hex(v, hexaddr); - if (v.size() != 4) - throw tun_linux_error("bad hex address"); - IPv4::Addr ret = IPv4::Addr::from_bytes(v.data()); - return IP::Addr::from_ipv4(ret); -} - -inline void add_del_route(const std::string &addr_str, - const int prefix_len, - const std::string &gateway_str, - const std::string &dev, - const unsigned int flags, - std::vector<IP::Route> *rtvec, - Action::Ptr &create, - Action::Ptr &destroy) -{ - if (flags & R_IPv6) - { - const IPv6::Addr addr = IPv6::Addr::from_string(addr_str); - const IPv6::Addr netmask = IPv6::Addr::netmask_from_prefix_len(prefix_len); - const IPv6::Addr net = addr & netmask; - - if (flags & R_ADD_SYS) - { - // ip route add 2001:db8:1::/48 via 2001:db8:1::1 - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-6"); - add->argv.push_back("route"); - add->argv.push_back("prepend"); - add->argv.push_back(net.to_string() + '/' + openvpn::to_string(prefix_len)); - add->argv.push_back("via"); - add->argv.push_back(gateway_str); - if (!dev.empty()) - { - add->argv.push_back("dev"); - add->argv.push_back(dev); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - destroy = del; - } - - if (rtvec && (flags & R_ADD_DCO)) - rtvec->emplace_back(IP::Addr::from_ipv6(net), prefix_len); - } - else - { - const IPv4::Addr addr = IPv4::Addr::from_string(addr_str); - const IPv4::Addr netmask = IPv4::Addr::netmask_from_prefix_len(prefix_len); - const IPv4::Addr net = addr & netmask; - - if (flags & R_ADD_SYS) - { - // ip route add 192.0.2.128/25 via 192.0.2.1 - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-4"); - add->argv.push_back("route"); - add->argv.push_back("prepend"); - add->argv.push_back(net.to_string() + '/' + openvpn::to_string(prefix_len)); - add->argv.push_back("via"); - add->argv.push_back(gateway_str); - if (!dev.empty()) - { - add->argv.push_back("dev"); - add->argv.push_back(dev); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - destroy = del; - } - - if (rtvec && (flags & R_ADD_DCO)) - rtvec->emplace_back(IP::Addr::from_ipv4(net), prefix_len); - } -} - -inline void add_del_route(const std::string &addr_str, - const int prefix_len, - const std::string &gateway_str, - const std::string &dev, - const unsigned int flags, // add interface route to rtvec if defined - std::vector<IP::Route> *rtvec, - ActionList &create, - ActionList &destroy) -{ - Action::Ptr c, d; - add_del_route(addr_str, prefix_len, gateway_str, dev, flags, rtvec, c, d); - create.add(c); - destroy.add(d); -} - -inline void iface_up(const std::string &iface_name, - const int mtu, - ActionList &create, - ActionList &destroy) -{ - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("link"); - add->argv.push_back("set"); - add->argv.push_back(iface_name); - add->argv.push_back("up"); - if (mtu > 0) - { - add->argv.push_back("mtu"); - add->argv.push_back(openvpn::to_string(mtu)); - } - create.add(add); - - // for the destroy command, copy the add command but replace "up" with "down" - Command::Ptr del(add->copy()); - del->argv[4] = "down"; - destroy.add(del); - } -} - -inline void iface_config(const std::string &iface_name, - int unit, - const TunBuilderCapture &pull, - std::vector<IP::Route> *rtvec, - ActionList &create, - ActionList &destroy) -{ - // set local4 and local6 to point to IPv4/6 route configurations - const TunBuilderCapture::RouteAddress *local4 = pull.vpn_ipv4(); - const TunBuilderCapture::RouteAddress *local6 = pull.vpn_ipv6(); - - // Set IPv4 Interface - if (local4) - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-4"); - add->argv.push_back("addr"); - add->argv.push_back("add"); - add->argv.push_back(local4->address + '/' + openvpn::to_string(local4->prefix_length)); - add->argv.push_back("broadcast"); - add->argv.push_back((IPv4::Addr::from_string(local4->address) | ~IPv4::Addr::netmask_from_prefix_len(local4->prefix_length)).to_string()); - add->argv.push_back("dev"); - add->argv.push_back(iface_name); - if (unit >= 0) - { - add->argv.push_back("label"); - add->argv.push_back(iface_name + ':' + openvpn::to_string(unit)); - } - create.add(add); - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - destroy.add(del); - - // add interface route to rtvec if defined - add_del_route(local4->address, local4->prefix_length, local4->address, iface_name, R_ADD_DCO, rtvec, create, destroy); - } - - // Set IPv6 Interface - if (local6 && !pull.block_ipv6) - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-6"); - add->argv.push_back("addr"); - add->argv.push_back("add"); - add->argv.push_back(local6->address + '/' + openvpn::to_string(local6->prefix_length)); - add->argv.push_back("dev"); - add->argv.push_back(iface_name); - create.add(add); - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - destroy.add(del); - - // add interface route to rtvec if defined - add_del_route(local6->address, local6->prefix_length, local6->address, iface_name, R_ADD_DCO | R_IPv6, rtvec, create, destroy); - } -} - -struct TunMethods -{ - static inline void tun_config(const std::string &iface_name, - const TunBuilderCapture &pull, - std::vector<IP::Route> *rtvec, - ActionList &create, - ActionList &destroy, - const unsigned int flags) // TunConfigFlags - { - const LinuxGW46 gw(true); - - // set local4 and local6 to point to IPv4/6 route configurations - const TunBuilderCapture::RouteAddress *local4 = pull.vpn_ipv4(); - const TunBuilderCapture::RouteAddress *local6 = pull.vpn_ipv6(); - - // configure interface - if (!(flags & TunConfigFlags::DISABLE_IFACE_UP)) - iface_up(iface_name, pull.mtu, create, destroy); - iface_config(iface_name, -1, pull, rtvec, create, destroy); - - // Process Routes - { - for (const auto &route : pull.add_routes) - { - if (route.ipv6) - { - if (local6 && !pull.block_ipv6) - add_del_route(route.address, route.prefix_length, local6->gateway, iface_name, R_ADD_ALL | R_IPv6, rtvec, create, destroy); - } - else - { - if (local4 && !local4->gateway.empty()) - add_del_route(route.address, route.prefix_length, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy); - else - OPENVPN_LOG("ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway"); - } - } - } - - // Process exclude routes - { - for (const auto &route : pull.exclude_routes) - { - if (route.ipv6) - { - OPENVPN_LOG("NOTE: exclude IPv6 routes not supported yet"); // fixme - } - else - { - if (gw.v4.defined()) - add_del_route(route.address, route.prefix_length, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy); - else - OPENVPN_LOG("NOTE: cannot determine gateway for exclude IPv4 routes"); - } - } - } - - // Process IPv4 redirect-gateway - if (!(flags & TunConfigFlags::DISABLE_REROUTE_GW)) - { - if (pull.reroute_gw.ipv4) - { - // add bypass route - if ((flags & TunConfigFlags::ADD_BYPASS_ROUTES) && !pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL) && gw.v4.defined()) - add_del_route(pull.remote_address.address, 32, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy); - - add_del_route("0.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy); - add_del_route("128.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy); - } - - // Process IPv6 redirect-gateway - if (pull.reroute_gw.ipv6 && !pull.block_ipv6) - { - // add bypass route - if ((flags & TunConfigFlags::ADD_BYPASS_ROUTES) && pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL) && gw.v4.defined()) - add_del_route(pull.remote_address.address, 128, gw.v6.addr().to_string(), gw.v6.dev(), R_ADD_SYS | R_IPv6, rtvec, create, destroy); - - add_del_route("0000::", 1, local6->gateway, iface_name, R_ADD_ALL | R_IPv6, rtvec, create, destroy); - add_del_route("8000::", 1, local6->gateway, iface_name, R_ADD_ALL | R_IPv6, rtvec, create, destroy); - } - } - - // fixme -- Process block-ipv6 - - // fixme -- Handle pushed DNS servers - } - - static inline void add_bypass_route(const std::string &tun_iface_name, - const std::string &address, - bool ipv6, - std::vector<IP::Route> *rtvec, - ActionList &create, - ActionList &destroy) - { - LinuxGW46 gw(true); - - if (!ipv6 && gw.v4.defined()) - add_del_route(address, 32, gw.v4.addr().to_string(), gw.dev(), R_ADD_SYS, rtvec, create, destroy); - - if (ipv6 && gw.v6.defined()) - add_del_route(address, 128, gw.v6.addr().to_string(), gw.dev(), R_ADD_SYS, rtvec, create, destroy); - } -}; -} // namespace openvpn::TunIPRoute diff --git a/openvpn/tun/linux/client/tunmethods.hpp b/openvpn/tun/linux/client/tunmethods.hpp deleted file mode 100644 index df28c6a44..000000000 --- a/openvpn/tun/linux/client/tunmethods.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// OpenVPN -- An application to securely tunnel IP networks -// over a single port, with support for SSL/TLS-based -// session authentication and key exchange, -// packet encryption, packet authentication, and -// packet compression. -// -// Copyright (C) 2012- OpenVPN Inc. -// -// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception -// - -#pragma once -// check if Netlink has been selected at compile time -#ifdef OPENVPN_USE_SITNL -#include <openvpn/tun/linux/client/tunnetlink.hpp> -#define TUN_LINUX openvpn::TunNetlink::TunMethods -#else -#include <openvpn/tun/linux/client/tuniproute.hpp> -#define TUN_LINUX openvpn::TunIPRoute::TunMethods -#endif \ No newline at end of file diff --git a/openvpn/tun/linux/client/tunnetlink.hpp b/openvpn/tun/linux/client/tunnetlink.hpp index bc4742b45..86d647c98 100644 --- a/openvpn/tun/linux/client/tunnetlink.hpp +++ b/openvpn/tun/linux/client/tunnetlink.hpp @@ -32,11 +32,9 @@ using namespace openvpn::TunLinuxSetup; struct NetlinkLinkSet : public Action { - typedef RCPtr<NetlinkLinkSet> Ptr; + using Ptr = RCPtr<NetlinkLinkSet>; - NetlinkLinkSet() - { - } + NetlinkLinkSet() = default; NetlinkLinkSet(std::string dev_arg, bool up_arg, int mtu_arg) : dev(dev_arg), @@ -54,11 +52,11 @@ struct NetlinkLinkSet : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkLinkSet with no interface" << std::endl; + os << "Error: can't call NetlinkLinkSet with no interface\n"; return; } @@ -66,18 +64,18 @@ struct NetlinkLinkSet : public Action if (ret) { os << "Error while executing NetlinkLinkSet " << dev << " mtu " << mtu - << ": " << ret << std::endl; + << ": " << ret << "\n"; } ret = SITNL::net_iface_up(dev, up); if (ret) { os << "Error while executing NetlinkLinkSet " << dev << " up " << up - << ": " << ret << std::endl; + << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; os << "netlink iface " << dev << " link set " << up << " mtu " << mtu; @@ -91,11 +89,9 @@ struct NetlinkLinkSet : public Action struct NetlinkAddr4 : public Action { - typedef RCPtr<NetlinkAddr4> Ptr; + using Ptr = RCPtr<NetlinkAddr4>; - NetlinkAddr4() - { - } + NetlinkAddr4() = default; NetlinkAddr4(std::string dev_arg, IPv4::Addr &addr_arg, @@ -121,11 +117,11 @@ struct NetlinkAddr4 : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkAddr4 with no interface" << std::endl; + os << "Error: can't call NetlinkAddr4 with no interface\n"; return; } @@ -142,11 +138,11 @@ struct NetlinkAddr4 : public Action if (ret) { os << "Error while executing NetlinkAddr4(add: " << add << ") " - << dev << ": " << ret << std::endl; + << dev << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; os << "netlink iface " << dev << " " << (add ? "add" : "del") << " " @@ -164,11 +160,9 @@ struct NetlinkAddr4 : public Action struct NetlinkAddr6 : public Action { - typedef RCPtr<NetlinkAddr6> Ptr; + using Ptr = RCPtr<NetlinkAddr6>; - NetlinkAddr6() - { - } + NetlinkAddr6() = default; NetlinkAddr6(std::string dev_arg, IPv6::Addr &addr_arg, @@ -191,11 +185,11 @@ struct NetlinkAddr6 : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkAddr6 with no interface" << std::endl; + os << "Error: can't call NetlinkAddr6 with no interface\n"; return; } @@ -212,11 +206,11 @@ struct NetlinkAddr6 : public Action if (ret) { os << "Error while executing NetlinkAddr6(add: " << add << ") " - << dev << ": " << ret << std::endl; + << dev << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; os << "netlink iface " << dev << " " << (add ? "add" : "del") << " " @@ -232,11 +226,9 @@ struct NetlinkAddr6 : public Action struct NetlinkAddr4PtP : public Action { - typedef RCPtr<NetlinkAddr4PtP> Ptr; + using Ptr = RCPtr<NetlinkAddr4PtP>; - NetlinkAddr4PtP() - { - } + NetlinkAddr4PtP() = default; NetlinkAddr4PtP(std::string dev_arg, IPv4::Addr local_arg, @@ -259,11 +251,11 @@ struct NetlinkAddr4PtP : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkAddr4PtP with no interface" << std::endl; + os << "Error: can't call NetlinkAddr4PtP with no interface\n"; return; } @@ -280,11 +272,11 @@ struct NetlinkAddr4PtP : public Action if (ret) { os << "Error while executing NetlinkAddr4PtP(add: " << add << ") " - << dev << ": " << ret << std::endl; + << dev << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { return "netlink iface " + dev + " " + (add ? "add" : "del") + " ptp " + local.to_string() + " remote " + remote.to_string(); @@ -298,11 +290,9 @@ struct NetlinkAddr4PtP : public Action struct NetlinkRoute4 : public Action { - typedef RCPtr<NetlinkRoute4> Ptr; + using Ptr = RCPtr<NetlinkRoute4>; - NetlinkRoute4() - { - } + NetlinkRoute4() = default; NetlinkRoute4(IPv4::Addr &dst_arg, int prefixlen_arg, @@ -328,11 +318,11 @@ struct NetlinkRoute4 : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkRoute4 with no interface" << std::endl; + os << "Error: can't call NetlinkRoute4 with no interface\n"; return; } @@ -349,11 +339,11 @@ struct NetlinkRoute4 : public Action if (ret) { os << "Error while executing NetlinkRoute4(add: " << add << ") " - << dev << ": " << ret << std::endl; + << dev << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " " @@ -370,11 +360,9 @@ struct NetlinkRoute4 : public Action struct NetlinkRoute6 : public Action { - typedef RCPtr<NetlinkRoute6> Ptr; + using Ptr = RCPtr<NetlinkRoute6>; - NetlinkRoute6() - { - } + NetlinkRoute6() = default; NetlinkRoute6(IPv6::Addr &dst_arg, int prefixlen_arg, @@ -400,11 +388,11 @@ struct NetlinkRoute6 : public Action return ret; } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { if (dev.empty()) { - os << "Error: can't call NetlinkRoute6 with no interface" << std::endl; + os << "Error: can't call NetlinkRoute6 with no interface\n"; return; } @@ -421,11 +409,11 @@ struct NetlinkRoute6 : public Action if (ret) { os << "Error while executing NetlinkRoute6(add: " << add << ") " - << dev << ": " << ret << std::endl; + << dev << ": " << ret << "\n"; } } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " " @@ -462,20 +450,20 @@ inline int iface_new(std::ostringstream &os, const std::string &dev, const std:: if (dev.empty()) { - os << "Error: can't call NetlinkLinkNew with no interface" << std::endl; + os << "Error: can't call NetlinkLinkNew with no interface\n"; return ret; } if (type.empty()) { - os << "Error: can't call NetlinkLinkNew with no interfacei type" << std::endl; + os << "Error: can't call NetlinkLinkNew with no interfacei type\n"; return ret; } ret = SITNL::net_iface_new(dev, type); if (ret) { - os << "Error while executing NetlinkLinkNew " << dev << ": " << ret << std::endl; + os << "Error while executing NetlinkLinkNew " << dev << ": " << ret << "\n"; } return ret; @@ -487,14 +475,14 @@ inline int iface_del(std::ostringstream &os, const std::string &dev) if (dev.empty()) { - os << "Error: can't call NetlinkLinkDel with no interface" << std::endl; + os << "Error: can't call NetlinkLinkDel with no interface\n"; return ret; } ret = SITNL::net_iface_del(dev); if (ret) { - os << "Error while executing NetlinkLinkDel " << dev << ": " << ret << std::endl; + os << "Error while executing NetlinkLinkDel " << dev << ": " << ret << "\n"; } return ret; @@ -529,7 +517,7 @@ inline void add_del_route(const std::string &addr_str, if (flags & R_ADD_SYS) { // ip route add 2001:db8:1::/48 via 2001:db8:1::1 - NetlinkRoute6::Ptr add(new NetlinkRoute6); + const NetlinkRoute6::Ptr add(new NetlinkRoute6); add->route.addr = net; add->route.prefix_len = prefix_len; add->gw = IPv6::Addr::from_string(gateway_str); @@ -539,7 +527,7 @@ inline void add_del_route(const std::string &addr_str, create = add; // for the destroy command, copy the add command but replace "add" with "delete" - NetlinkRoute6::Ptr del(add->copy()); + const NetlinkRoute6::Ptr del(add->copy()); del->add = false; destroy = del; } @@ -556,7 +544,7 @@ inline void add_del_route(const std::string &addr_str, if (flags & R_ADD_SYS) { // ip route add 192.0.2.128/25 via 192.0.2.1 - NetlinkRoute4::Ptr add(new NetlinkRoute4); + const NetlinkRoute4::Ptr add(new NetlinkRoute4); add->route.addr = net; add->route.prefix_len = prefix_len; add->gw = IPv4::Addr::from_string(gateway_str); @@ -566,7 +554,7 @@ inline void add_del_route(const std::string &addr_str, create = add; // for the destroy command, copy the add command but replace "add" with "delete" - NetlinkRoute4::Ptr del(add->copy()); + const NetlinkRoute4::Ptr del(add->copy()); del->add = false; destroy = del; } @@ -598,14 +586,14 @@ inline void iface_up(const std::string &iface_name, ActionList &destroy) { { - NetlinkLinkSet::Ptr add(new NetlinkLinkSet); + const NetlinkLinkSet::Ptr add(new NetlinkLinkSet); add->dev = iface_name; add->up = true; add->mtu = mtu; create.add(add); // for the destroy command, copy the add command but replace "up" with "down" - NetlinkLinkSet::Ptr del(add->copy()); + const NetlinkLinkSet::Ptr del(add->copy()); del->up = false; destroy.add(del); } @@ -625,7 +613,7 @@ inline void iface_config(const std::string &iface_name, // Set IPv4 Interface if (local4) { - NetlinkAddr4::Ptr add(new NetlinkAddr4); + const NetlinkAddr4::Ptr add(new NetlinkAddr4); add->addr = IPv4::Addr::from_string(local4->address); add->prefixlen = local4->prefix_length; add->broadcast = IPv4::Addr::from_string(local4->address) @@ -640,7 +628,7 @@ inline void iface_config(const std::string &iface_name, create.add(add); // for the destroy command, copy the add command but replace "add" with "delete" - NetlinkAddr4::Ptr del(add->copy()); + const NetlinkAddr4::Ptr del(add->copy()); del->add = false; destroy.add(del); @@ -659,7 +647,7 @@ inline void iface_config(const std::string &iface_name, // Set IPv6 Interface if (local6 && !pull.block_ipv6) { - NetlinkAddr6::Ptr add(new NetlinkAddr6); + const NetlinkAddr6::Ptr add(new NetlinkAddr6); add->addr = IPv6::Addr::from_string(local6->address); add->prefixlen = local6->prefix_length; add->dev = iface_name; @@ -668,7 +656,7 @@ inline void iface_config(const std::string &iface_name, create.add(add); // for the destroy command, copy the add command but replace "add" with "delete" - NetlinkAddr6::Ptr del(add->copy()); + const NetlinkAddr6::Ptr del(add->copy()); del->add = false; destroy.add(del); @@ -741,7 +729,7 @@ struct TunMethods // Process exclude routes if (!pull.exclude_routes.empty()) { - LinuxGW46Netlink gw(iface_name); + const LinuxGW46Netlink gw(iface_name); for (const auto &route : pull.exclude_routes) { @@ -822,7 +810,7 @@ struct TunMethods ActionList &create, ActionList &destroy) { - LinuxGW46Netlink gw(tun_iface_name, address); + const LinuxGW46Netlink gw(tun_iface_name, address); if (!ipv6 && gw.v4.defined()) add_del_route(address, diff --git a/openvpn/tun/linux/client/tunsetup.hpp b/openvpn/tun/linux/client/tunsetup.hpp index 32537e0a4..c4c41ddaa 100644 --- a/openvpn/tun/linux/client/tunsetup.hpp +++ b/openvpn/tun/linux/client/tunsetup.hpp @@ -52,16 +52,14 @@ template <class TUNMETHODS> class Setup : public TunBuilderSetup::Base { public: - typedef RCPtr<Setup> Ptr; + using Ptr = RCPtr<Setup>; // This empty constructor shouldn't be needed, but due to a // plausible compiler bug in GCC 4.8.5 (RHEL 7), this empty // constructor is required to be able to build. This is // related to the member initialization of the private // remove_cmds_bypass_gw and remove_cmds class members. - Setup() - { - } + Setup() = default; struct Config : public TunBuilderSetup::Config { @@ -73,7 +71,7 @@ class Setup : public TunBuilderSetup::Base bool dco = false; #ifdef HAVE_JSON - virtual Json::Value to_json() override + Json::Value to_json() override { Json::Value root(Json::objectValue); root["iface_name"] = Json::Value(iface_name); @@ -84,7 +82,7 @@ class Setup : public TunBuilderSetup::Base return root; }; - virtual void from_json(const Json::Value &root, const std::string &title) override + void from_json(const Json::Value &root, const std::string &title) override { json::assert_dict(root, title); json::to_string(root, iface_name, "iface_name", title); @@ -117,7 +115,7 @@ class Setup : public TunBuilderSetup::Base remove_cmds_bypass_gw->execute(os); remove_cmds_bypass_gw->clear(); - ActionList::Ptr add_cmds = new ActionList(); + const ActionList::Ptr add_cmds = new ActionList(); TUNMETHODS::add_bypass_route(tun_iface_name, address, ipv6, nullptr, *add_cmds, *remove_cmds_bypass_gw); // add gateway bypass route @@ -146,7 +144,7 @@ class Setup : public TunBuilderSetup::Base tun_iface_name = conf->iface_name; } - ActionList::Ptr add_cmds = new ActionList(); + const ActionList::Ptr add_cmds = new ActionList(); ActionList::Ptr remove_cmds_new = new ActionListReversed(); // configure tun properties @@ -197,7 +195,7 @@ class Setup : public TunBuilderSetup::Base if (conf->txqueuelen) { struct ifreq netifr; - ScopedFD ctl_fd(socket(AF_INET, SOCK_DGRAM, 0)); + const ScopedFD ctl_fd(socket(AF_INET, SOCK_DGRAM, 0)); if (ctl_fd.defined()) { diff --git a/openvpn/tun/mac/client/tuncli.hpp b/openvpn/tun/mac/client/tuncli.hpp index a8ba2af41..4fd509f3d 100644 --- a/openvpn/tun/mac/client/tuncli.hpp +++ b/openvpn/tun/mac/client/tuncli.hpp @@ -197,8 +197,8 @@ class Client : public TunClient if (!po->mtu) po->mtu = TUN_MTU_DEFAULT; - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); // create new tun setup object tun_setup = config->new_setup_obj(); @@ -224,8 +224,8 @@ class Client : public TunClient state->iface_name = tsconf.iface_name; state->tun_prefix = tsconf.tun_prefix; if (tun_persist->persist_tun_state(ts, state)) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl - << tun_persist->options()); + OPENVPN_LOG("TunPersist: saving tun context:\n" + << tun_persist->options()); // enable tun_setup destructor tun_persist->add_destructor(tun_setup); diff --git a/openvpn/tun/mac/client/tunsetup.hpp b/openvpn/tun/mac/client/tunsetup.hpp index fcb763263..dfe34d6e6 100644 --- a/openvpn/tun/mac/client/tunsetup.hpp +++ b/openvpn/tun/mac/client/tunsetup.hpp @@ -117,7 +117,7 @@ class Setup : public TunBuilderSetup::Base } catch (const std::exception &e) { - os << e.what() << std::endl; + os << e.what() << "\n"; } } if (fd == -1) @@ -149,7 +149,7 @@ class Setup : public TunBuilderSetup::Base // enable the remove actions remove_cmds->enable_destroy(true); - os << "open " << conf->iface_name << " SUCCEEDED" << std::endl; + os << "open " << conf->iface_name << " SUCCEEDED\n"; return fd; } @@ -363,7 +363,7 @@ class Setup : public TunBuilderSetup::Base if (local4 && !local4->gateway.empty()) add_del_route(route.address, route.prefix_length, local4->gateway, iface_name, 0, create, destroy); else - os << "ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway" << std::endl; + os << "ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway\n"; } } } @@ -388,7 +388,7 @@ class Setup : public TunBuilderSetup::Base add_del_route(route.address, route.prefix_length, gw6.gateway_addr_str(), gw6.iface(), R_IPv6, create, destroy); } else - os << "NOTE: cannot determine gateway for exclude IPv6 routes" << std::endl; + os << "NOTE: cannot determine gateway for exclude IPv6 routes\n"; } } else @@ -396,7 +396,7 @@ class Setup : public TunBuilderSetup::Base if (gw4.flags() & MacGatewayInfo::ADDR_DEFINED) add_del_route(route.address, route.prefix_length, gw4.gateway_addr_str(), gw4.iface(), 0, create, destroy); else - os << "NOTE: cannot determine gateway for exclude IPv4 routes" << std::endl; + os << "NOTE: cannot determine gateway for exclude IPv4 routes\n"; } } } @@ -420,12 +420,12 @@ class Setup : public TunBuilderSetup::Base } else { - os << "ERROR: cannot detect IPv4 default gateway" << std::endl; + os << "ERROR: cannot detect IPv4 default gateway\n"; } } else { - os << "remote is IPv6, skip bypass route for reroute-ipv4" << std::endl; + os << "remote is IPv6, skip bypass route for reroute-ipv4\n"; } if (!(pull.reroute_gw.flags & RGWFlags::EmulateExcludeRoutes)) @@ -455,12 +455,12 @@ class Setup : public TunBuilderSetup::Base } else { - os << "ERROR: cannot detect IPv6 default gateway" << std::endl; + os << "ERROR: cannot detect IPv6 default gateway\n"; } } else { - os << "remote is IPv4, skip bypass route for reroute-ipv6" << std::endl; + os << "remote is IPv4, skip bypass route for reroute-ipv6\n"; } if (!(pull.reroute_gw.flags & RGWFlags::EmulateExcludeRoutes)) diff --git a/openvpn/tun/mac/dsdict.hpp b/openvpn/tun/mac/dsdict.hpp index 6ad4c5b1e..9c168a7e7 100644 --- a/openvpn/tun/mac/dsdict.hpp +++ b/openvpn/tun/mac/dsdict.hpp @@ -129,15 +129,15 @@ class DSDict std::string to_string() const { std::ostringstream os; - os << "*** DSDict " << dskey << std::endl; + os << "*** DSDict " << dskey << "\n"; std::string orig = CF::description(dict()); string::trim_crlf(orig); - os << "ORIG " << orig << std::endl; + os << "ORIG " << orig << "\n"; if (dirty()) { std::string modstr = CF::description(mod()); string::trim_crlf(modstr); - os << "MODIFIED " << modstr << std::endl; + os << "MODIFIED " << modstr << "\n"; } return os.str(); } diff --git a/openvpn/tun/mac/gw.hpp b/openvpn/tun/mac/gw.hpp index 9223d92c4..8a66464d3 100644 --- a/openvpn/tun/mac/gw.hpp +++ b/openvpn/tun/mac/gw.hpp @@ -71,9 +71,7 @@ class MacGatewayInfo /* setup data to send to routing socket */ int seq = 0; - struct rtmsg m_rtmsg - { - }; + struct rtmsg m_rtmsg{}; m_rtmsg.m_rtm.rtm_type = RTM_GET; m_rtmsg.m_rtm.rtm_flags = RTF_UP; @@ -109,7 +107,7 @@ class MacGatewayInfo // likely no default gw or IPv6 connectivity if (os) { - *os << "GDG: problem writing to routing socket: " << std::to_string(ret) << " errno: " << std::to_string(errno) << " msg: " << ::strerror(errno) << std::endl; + *os << "GDG: problem writing to routing socket: " << std::to_string(ret) << " errno: " << std::to_string(errno) << " msg: " << ::strerror(errno) << "\n"; } return; diff --git a/openvpn/tun/mac/macdns.hpp b/openvpn/tun/mac/macdns.hpp index 19a8c15aa..7ed689c19 100644 --- a/openvpn/tun/mac/macdns.hpp +++ b/openvpn/tun/mac/macdns.hpp @@ -256,7 +256,7 @@ class MacDNS : public RC<thread_unsafe_refcount> prev = info; if (mod) - OPENVPN_LOG("MacDNS: SETDNS " << ver.to_string() << std::endl + OPENVPN_LOG("MacDNS: SETDNS " << ver.to_string() << "\n" << info->to_string()); } catch (const std::exception &e) @@ -289,7 +289,7 @@ class MacDNS : public RC<thread_unsafe_refcount> mod |= info->info.remove_from_store(); if (mod) - OPENVPN_LOG("MacDNS: RESETDNS " << ver.to_string() << std::endl + OPENVPN_LOG("MacDNS: RESETDNS " << ver.to_string() << "\n" << info->to_string()); } catch (const std::exception &e) diff --git a/openvpn/tun/mac/macdns_watchdog.hpp b/openvpn/tun/mac/macdns_watchdog.hpp index 6c963b07b..ed33aed89 100644 --- a/openvpn/tun/mac/macdns_watchdog.hpp +++ b/openvpn/tun/mac/macdns_watchdog.hpp @@ -55,7 +55,7 @@ class MacDNSWatchdog : public RC<thread_unsafe_refcount> void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; if (parent) parent->setdns(config, flags); } diff --git a/openvpn/tun/persist/tunpersist.hpp b/openvpn/tun/persist/tunpersist.hpp index 3a9e08839..ea0d22d6d 100644 --- a/openvpn/tun/persist/tunpersist.hpp +++ b/openvpn/tun/persist/tunpersist.hpp @@ -25,7 +25,7 @@ template <typename SCOPED_OBJ, typename STATE = TunProp::State::Ptr> class TunPersistTemplate : public TunWrapTemplate<SCOPED_OBJ> { public: - typedef RCPtr<TunPersistTemplate> Ptr; + using Ptr = RCPtr<TunPersistTemplate>; TunPersistTemplate(const bool enable_persistence, const TunWrapObjRetain retain_obj, TunBuilderBase *tb) : TunWrapTemplate<SCOPED_OBJ>(retain_obj), @@ -81,8 +81,8 @@ class TunPersistTemplate : public TunWrapTemplate<SCOPED_OBJ> try { TunProp::configure_builder(capture.get(), nullptr, nullptr, server_addr, tun_prop, opt, nullptr, true); - OPENVPN_LOG("*** TUN BUILDER CAPTURE" << std::endl - << capture->to_string()); + OPENVPN_LOG("*** TUN BUILDER CAPTURE\n" + << capture->to_string()); } catch (const std::exception &e) { @@ -130,8 +130,7 @@ class TunPersistTemplate : public TunWrapTemplate<SCOPED_OBJ> options_ = copt_->to_string(); return true; } - else - return false; + return false; } private: diff --git a/openvpn/tun/persist/tunwrap.hpp b/openvpn/tun/persist/tunwrap.hpp index 6c26dbfe3..14bfd9f41 100644 --- a/openvpn/tun/persist/tunwrap.hpp +++ b/openvpn/tun/persist/tunwrap.hpp @@ -43,7 +43,7 @@ template <typename SCOPED_OBJ> class TunWrapTemplate : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TunWrapTemplate> Ptr; + using Ptr = RCPtr<TunWrapTemplate>; TunWrapTemplate(const TunWrapObjRetain retain_obj) : retain_obj_(retain_obj) diff --git a/openvpn/tun/proxy.hpp b/openvpn/tun/proxy.hpp index bed051cdd..76e100ea0 100644 --- a/openvpn/tun/proxy.hpp +++ b/openvpn/tun/proxy.hpp @@ -32,14 +32,14 @@ class ProxySettings : public RC<thread_unsafe_refcount> { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; if (parent) parent->set_proxy(del); } - virtual std::string to_string() const override + std::string to_string() const override { std::ostringstream os; if (parent && parent->config.defined()) diff --git a/openvpn/tun/server/tunbase.hpp b/openvpn/tun/server/tunbase.hpp index bcd186501..51e0a31d6 100644 --- a/openvpn/tun/server/tunbase.hpp +++ b/openvpn/tun/server/tunbase.hpp @@ -25,14 +25,12 @@ namespace openvpn::TunClientInstance { -typedef Function<void(int fd)> PostCloseFunc; +using PostCloseFunc = Function<void(int fd)>; // A native reference to a client instance struct NativeHandle { - NativeHandle() - { - } + NativeHandle() = default; NativeHandle(const int fd_arg, const int peer_id_arg) : fd(fd_arg), @@ -60,7 +58,7 @@ struct NativeHandle // object will inherit from multiple receivers. struct Recv : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<Recv> Ptr; + using Ptr = RCPtr<Recv>; // virtual bool defined() const = 0; virtual void stop() = 0; @@ -80,7 +78,7 @@ struct Recv : public virtual RC<thread_unsafe_refcount> // Each client instance uses this class to send data to the tun layer. struct Send : public virtual RC<thread_unsafe_refcount> { - typedef RCPtr<Send> Ptr; + using Ptr = RCPtr<Send>; // virtual bool defined() const = 0; virtual void stop() = 0; @@ -100,7 +98,7 @@ struct Send : public virtual RC<thread_unsafe_refcount> // Factory for server tun object. struct Factory : public RC<thread_unsafe_refcount> { - typedef RCPtr<Factory> Ptr; + using Ptr = RCPtr<Factory>; virtual Send::Ptr new_tun_obj(Recv *parent) = 0; }; diff --git a/openvpn/tun/tristate_setting.hpp b/openvpn/tun/tristate_setting.hpp index 16e5f17f0..4458bd114 100644 --- a/openvpn/tun/tristate_setting.hpp +++ b/openvpn/tun/tristate_setting.hpp @@ -25,9 +25,7 @@ class TriStateSetting Default, }; - TriStateSetting() - { - } + TriStateSetting() = default; explicit TriStateSetting(const Type t) : type_(t) @@ -57,12 +55,11 @@ class TriStateSetting { if (str == "no") return TriStateSetting(No); - else if (str == "yes") + if (str == "yes") return TriStateSetting(Yes); - else if (str == "default") + if (str == "default") return TriStateSetting(Default); - else - throw Exception("IPv6Setting: unrecognized setting: '" + str + '\''); + throw Exception("IPv6Setting: unrecognized setting: '" + str + '\''); } bool operator==(const TriStateSetting &other) const diff --git a/openvpn/tun/tunio.hpp b/openvpn/tun/tunio.hpp index 12fdf63d7..2ca3ba401 100644 --- a/openvpn/tun/tunio.hpp +++ b/openvpn/tun/tunio.hpp @@ -32,7 +32,7 @@ template <typename ReadHandler, typename PacketFrom, typename STREAM> class TunIO : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<TunIO> Ptr; + using Ptr = RCPtr<TunIO>; TunIO(ReadHandler read_handler_arg, const Frame::Ptr &frame_arg, @@ -102,12 +102,10 @@ class TunIO : public RC<thread_unsafe_refcount> } if (wrote == buf.size()) return true; - else - { - OPENVPN_LOG_TUN_ERROR("TUN partial write error"); - tun_error(Error::TUN_WRITE_ERROR, nullptr); - return false; - } + + OPENVPN_LOG_TUN_ERROR("TUN partial write error"); + tun_error(Error::TUN_WRITE_ERROR, nullptr); + return false; } catch (openvpn_io::system_error &e) { @@ -137,12 +135,10 @@ class TunIO : public RC<thread_unsafe_refcount> } if (wrote == bs.size()) return true; - else - { - OPENVPN_LOG_TUN_ERROR("TUN partial write error"); - tun_error(Error::TUN_WRITE_ERROR, nullptr); - return false; - } + + OPENVPN_LOG_TUN_ERROR("TUN partial write error"); + tun_error(Error::TUN_WRITE_ERROR, nullptr); + return false; } catch (openvpn_io::system_error &e) { diff --git a/openvpn/tun/win/client/tuncli.hpp b/openvpn/tun/win/client/tuncli.hpp index 524c15cdf..c41f89756 100644 --- a/openvpn/tun/win/client/tuncli.hpp +++ b/openvpn/tun/win/client/tuncli.hpp @@ -132,8 +132,8 @@ class Client : public TunClient opt, nullptr, false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); // create new tun setup object tun_setup = config->new_setup_obj(io_context); @@ -154,8 +154,8 @@ class Client : public TunClient // persist tun settings state if (tun_persist->persist_tun_state(ts, {state, nullptr})) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl - << tun_persist->options()); + OPENVPN_LOG("TunPersist: saving tun context:\n" + << tun_persist->options()); // setup handler for external tun close tun_setup->set_service_fail_handler([self = Ptr(this)]() @@ -361,8 +361,8 @@ class Client : public TunClient { if (dhcp_capture->mod_reply(buf)) { - OPENVPN_LOG("DHCP PROPS:" << std::endl - << dhcp_capture->get_props().to_string()); + OPENVPN_LOG("DHCP PROPS:\n" + << dhcp_capture->get_props().to_string()); layer_2_schedule_timer(1); } } diff --git a/openvpn/tun/win/client/tunsetup.hpp b/openvpn/tun/win/client/tunsetup.hpp index 189d6f780..1c7fa7d86 100644 --- a/openvpn/tun/win/client/tunsetup.hpp +++ b/openvpn/tun/win/client/tunsetup.hpp @@ -99,8 +99,8 @@ class Setup : public SetupBase // enumerate available TAP adapters Util::TapNameGuidPairList guids(tun_type_); - os << "TAP ADAPTERS:" << std::endl - << guids.to_string() << std::endl; + os << "TAP ADAPTERS:\n" + << guids.to_string() << "\n"; // open TAP device handle std::string path_opened; @@ -108,15 +108,15 @@ class Setup : public SetupBase os << "Open TAP device \"" + tap_.name + "\" PATH=\"" + path_opened + '\"'; if (!th.defined()) { - os << " FAILED" << std::endl; + os << " FAILED\n"; throw ErrorCode(Error::TUN_IFACE_CREATE, true, "cannot acquire TAP handle"); } - os << " SUCCEEDED" << std::endl; + os << " SUCCEEDED\n"; if (tun_type_ == TapWindows6) { Util::TAPDriverVersion version(th()); - os << version.to_string() << std::endl; + os << version.to_string() << "\n"; } return th.release(); @@ -609,10 +609,10 @@ class Setup : public SetupBase } } if (ipv6_error) - os << "NOTE: exclude IPv6 routes not currently supported" << std::endl; + os << "NOTE: exclude IPv6 routes not currently supported\n"; } else - os << "NOTE: exclude routes error: cannot detect default gateway" << std::endl; + os << "NOTE: exclude routes error: cannot detect default gateway\n"; } // Process IPv4 redirect-gateway @@ -885,7 +885,7 @@ class Setup : public SetupBase const Util::IPAdaptersInfo ai; if (!ai.is_dhcp_enabled(tap.index)) { - os << "TAP: DHCP is disabled, attempting to enable" << std::endl; + os << "TAP: DHCP is disabled, attempting to enable\n"; ActionList::Ptr cmds(new ActionList()); cmds->add(new Util::ActionEnableDHCP(tap)); cmds->execute(os); diff --git a/openvpn/tun/win/client/wintun.hpp b/openvpn/tun/win/client/wintun.hpp index c659ee3e6..4631d4c37 100644 --- a/openvpn/tun/win/client/wintun.hpp +++ b/openvpn/tun/win/client/wintun.hpp @@ -63,8 +63,8 @@ class WintunClient : public TunClient opt, nullptr, false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl - << po->to_string()); + OPENVPN_LOG("CAPTURED OPTIONS:\n" + << po->to_string()); // create new tun setup object tun_setup = config->new_setup_obj(io_context); @@ -85,8 +85,8 @@ class WintunClient : public TunClient // persist tun settings state if (tun_persist->persist_tun_state(ts, {state, ring_buffer})) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl - << tun_persist->options()); + OPENVPN_LOG("TunPersist: saving tun context:\n" + << tun_persist->options()); // enable tun_setup destructor tun_persist->add_destructor(tun_setup); diff --git a/openvpn/tun/win/dns.hpp b/openvpn/tun/win/dns.hpp index afd051e28..3fac4205e 100644 --- a/openvpn/tun/win/dns.hpp +++ b/openvpn/tun/win/dns.hpp @@ -428,7 +428,7 @@ class Dns */ void execute(std::ostream &log) override { - log << to_string() << std::endl; + log << to_string() << "\n"; set_search_domains(itf_name_, search_domains_); } @@ -466,7 +466,7 @@ class Dns */ void execute(std::ostream &log) override { - log << to_string() << std::endl; + log << to_string() << "\n"; remove_search_domains(itf_name_, search_domains_); } @@ -507,7 +507,7 @@ class Dns } const char *status = apply_dns_settings() ? "successful" : "failed"; - log << to_string() << ": " << status << gpol_status << std::endl; + log << to_string() << ": " << status << gpol_status << "\n"; } /** diff --git a/openvpn/tun/win/nrpt.hpp b/openvpn/tun/win/nrpt.hpp index dd5a2c0b7..2f9570ef3 100644 --- a/openvpn/tun/win/nrpt.hpp +++ b/openvpn/tun/win/nrpt.hpp @@ -433,7 +433,7 @@ class Nrpt const std::string id = rule_id(process_id_); const std::wstring servers = wstring::from_utf8(string::join(dns_servers_, ";")); - log << to_string() << " id=[" << id << "]" << std::endl; + log << to_string() << " id=[" << id << "]\n"; create_rule(id, domains, servers, dnssec_); } @@ -479,7 +479,7 @@ class Nrpt */ void execute(std::ostream &log) override { - log << to_string() << std::endl; + log << to_string() << "\n"; delete_rules(process_id_); } diff --git a/openvpn/tun/win/ringbuffer.hpp b/openvpn/tun/win/ringbuffer.hpp index f45704007..6a2f6d266 100644 --- a/openvpn/tun/win/ringbuffer.hpp +++ b/openvpn/tun/win/ringbuffer.hpp @@ -111,8 +111,8 @@ class RingBuffer : public RC<thread_unsafe_refcount> receive_ring_ = (TUN_RING *)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); } - RingBuffer(RingBuffer const &) = delete; - RingBuffer &operator=(RingBuffer const &) = delete; + RingBuffer(const RingBuffer &) = delete; + RingBuffer &operator=(const RingBuffer &) = delete; ~RingBuffer() { diff --git a/openvpn/tun/win/tunutil.hpp b/openvpn/tun/win/tunutil.hpp index 967a049a7..257ee871e 100644 --- a/openvpn/tun/win/tunutil.hpp +++ b/openvpn/tun/win/tunutil.hpp @@ -369,7 +369,7 @@ struct TapNameGuidPairList : public std::vector<TapNameGuidPair> os << " index=" << pair.index; if (!pair.name.empty()) os << " name='" << pair.name << '\''; - os << std::endl; + os << "\n"; } return os.str(); } @@ -552,7 +552,7 @@ inline HANDLE tap_open(const Type tun_type, if (tun_type == OvpnDco) { - if (!string::ends_with(inst_id_interface.device_interface, OVPNDCO_DEV_INTERFACE_REF_STRING)) + if (!inst_id_interface.device_interface.ends_with(OVPNDCO_DEV_INTERFACE_REF_STRING)) continue; } path = inst_id_interface.device_interface; @@ -712,9 +712,9 @@ inline void dhcp_release(const InterfaceInfoList &ii, { const DWORD status = ::IpReleaseAddress(iface); if (status == NO_ERROR) - os << "TAP: DHCP release succeeded" << std::endl; + os << "TAP: DHCP release succeeded\n"; else - os << "TAP: DHCP release failed" << std::endl; + os << "TAP: DHCP release failed\n"; } } @@ -727,9 +727,9 @@ inline void dhcp_renew(const InterfaceInfoList &ii, { const DWORD status = ::IpRenewAddress(iface); if (status == NO_ERROR) - os << "TAP: DHCP renew succeeded" << std::endl; + os << "TAP: DHCP renew succeeded\n"; else - os << "TAP: DHCP renew failed" << std::endl; + os << "TAP: DHCP renew failed\n"; } } @@ -738,16 +738,14 @@ inline void flush_arp(const DWORD adapter_index, { const DWORD status = ::FlushIpNetTable2(AF_INET, adapter_index); if (status == NO_ERROR) - os << "TAP: ARP flush succeeded" << std::endl; + os << "TAP: ARP flush succeeded\n"; else - os << "TAP: ARP flush failed" << std::endl; + os << "TAP: ARP flush failed\n"; } struct IPNetmask4 { - IPNetmask4() - { - } + IPNetmask4() = default; IPNetmask4(const TunBuilderCapture &pull, const char *title) { @@ -909,9 +907,9 @@ class ActionSetAdapterDomainSuffix : public Action { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; LONG status; Win::Reg::Key key; @@ -938,7 +936,7 @@ class ActionSetAdapterDomainSuffix : public Action OPENVPN_THROW(tun_win_util, "ActionSetAdapterDomainSuffix: error writing Domain registry key: " << reg_key_name); } - virtual std::string to_string() const override + std::string to_string() const override { return "Set adapter domain suffix: '" + search_domain + "' " + tap_guid; } @@ -1184,7 +1182,7 @@ class BestGateway static ULONG get_iface_metric(std::map<NET_IFINDEX, ULONG> &metric_per_iface, NET_IFINDEX iface, ADDRESS_FAMILY af) { - if (metric_per_iface.find(iface) == metric_per_iface.end()) + if (!metric_per_iface.contains(iface)) { MIB_IPINTERFACE_ROW ir{}; ir.InterfaceIndex = iface; @@ -1209,9 +1207,9 @@ class ActionDeleteAllRoutesOnInterface : public Action { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; ActionList::Ptr actions = new ActionList(); remove_all_ipv4_routes_on_iface(iface_index, *actions); @@ -1219,7 +1217,7 @@ class ActionDeleteAllRoutesOnInterface : public Action actions->execute(os); } - virtual std::string to_string() const override + std::string to_string() const override { return "ActionDeleteAllRoutesOnInterface iface_index=" + std::to_string(iface_index); } @@ -1414,14 +1412,14 @@ class AddRoute4Cmd : public Action void execute(std::ostream &os) override { - os << os_.str() << std::endl; + os << os_.str() << "\n"; DWORD res; if (add) res = CreateIpForwardEntry2(&fwd_row); else res = DeleteIpForwardEntry2(&fwd_row); if (res) - os << "cannot modify route: error " << res << std::endl; + os << "cannot modify route: error " << res << "\n"; } std::string to_string() const override diff --git a/openvpn/tun/win/wfp.hpp b/openvpn/tun/win/wfp.hpp index 2fa810552..5ab1d8ef6 100644 --- a/openvpn/tun/win/wfp.hpp +++ b/openvpn/tun/win/wfp.hpp @@ -209,7 +209,7 @@ class WFP : public RC<thread_unsafe_refcount> */ void execute(std::ostream &log) override { - log << to_string() << std::endl; + log << to_string() << "\n"; if (block_) ctx_->block(openvpn_app_path_, itf_index_, block_type_, log); else @@ -360,13 +360,13 @@ class WFP : public RC<thread_unsafe_refcount> filter.numFilterConditions = 1; condition[0] = match_openvpn; add_filter(&filter, NULL, &filterid); - log << "permit IPv4 requests from OpenVPN app" << std::endl; + log << "permit IPv4 requests from OpenVPN app\n"; // Filter #2 -- permit IPv6 requests from OpenVPN app filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; add_filter(&filter, NULL, &filterid); - log << "permit IPv6 requests from OpenVPN app" << std::endl; + log << "permit IPv6 requests from OpenVPN app\n"; // Filter #3 -- block IPv4 (DNS) requests, except to loopback, from other apps @@ -383,13 +383,13 @@ class WFP : public RC<thread_unsafe_refcount> dns_str = "DNS "; } add_filter(&filter, NULL, &filterid); - log << "block IPv4 " << dns_str << "requests from other apps" << std::endl; + log << "block IPv4 " << dns_str << "requests from other apps\n"; // Filter #4 -- block IPv6 (DNS) requests, except to loopback, from other apps filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; add_filter(&filter, NULL, &filterid); - log << "block IPv6 " << dns_str << "requests from other apps" << std::endl; + log << "block IPv6 " << dns_str << "requests from other apps\n"; // Filter #5 -- allow IPv4 traffic from VPN interface @@ -398,13 +398,13 @@ class WFP : public RC<thread_unsafe_refcount> filter.numFilterConditions = 1; condition[0] = match_interface; add_filter(&filter, NULL, &filterid); - log << "allow IPv4 traffic from TAP" << std::endl; + log << "allow IPv4 traffic from TAP\n"; // Filter #6 -- allow IPv6 traffic from VPN interface filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; add_filter(&filter, NULL, &filterid); - log << "allow IPv6 traffic from TAP" << std::endl; + log << "allow IPv6 traffic from TAP\n"; if (block_type != Block::AllButLocalDns && block_type != Block::DnsButAllowLocal) { @@ -416,13 +416,13 @@ class WFP : public RC<thread_unsafe_refcount> condition[0] = match_loopback; condition[1] = match_port_53; add_filter(&filter, NULL, &filterid); - log << "block IPv4 DNS requests to loopback from other apps" << std::endl; + log << "block IPv4 DNS requests to loopback from other apps\n"; // Filter #8 -- block IPv6 DNS requests to loopback from other apps filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; add_filter(&filter, NULL, &filterid); - log << "block IPv6 DNS requests to loopback from other apps" << std::endl; + log << "block IPv6 DNS requests to loopback from other apps\n"; } } @@ -473,9 +473,9 @@ class WFP : public RC<thread_unsafe_refcount> if (log) { if (status != ERROR_SUCCESS) - *log << "FwpmEngineClose0 failed, status=" << status << std::endl; + *log << "FwpmEngineClose0 failed, status=" << status << "\n"; else - *log << "WFP Engine closed" << std::endl; + *log << "WFP Engine closed\n"; } } } diff --git a/openvpn/win/cmd.hpp b/openvpn/win/cmd.hpp index 0ffe575e7..4c6ac0616 100644 --- a/openvpn/win/cmd.hpp +++ b/openvpn/win/cmd.hpp @@ -35,14 +35,14 @@ class WinCmd : public Action { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << cmd << std::endl; + os << cmd << "\n"; std::string out = Win::call(cmd); os << out; } - virtual std::string to_string() const override + std::string to_string() const override { return cmd; } diff --git a/openvpn/win/console.hpp b/openvpn/win/console.hpp index c5b7ff5b4..a4c06b1a6 100644 --- a/openvpn/win/console.hpp +++ b/openvpn/win/console.hpp @@ -78,7 +78,7 @@ class Input std::cout << prompt; std::string s; std::getline(std::cin, s); - std::cout << std::endl; + std::cout << "\n"; return s; } diff --git a/openvpn/win/logfile.hpp b/openvpn/win/logfile.hpp index d789f70a2..34ed6dc69 100644 --- a/openvpn/win/logfile.hpp +++ b/openvpn/win/logfile.hpp @@ -29,7 +29,7 @@ class LogFile : public LogBase { } - virtual void log(const std::string &str) override + void log(const std::string &str) override { LogUtil::log(log_handle(), str); } diff --git a/openvpn/win/sleep.hpp b/openvpn/win/sleep.hpp index f817a8430..6118e3082 100644 --- a/openvpn/win/sleep.hpp +++ b/openvpn/win/sleep.hpp @@ -31,13 +31,13 @@ class WinSleep : public Action { } - virtual void execute(std::ostream &os) override + void execute(std::ostream &os) override { - os << to_string() << std::endl; + os << to_string() << "\n"; ::Sleep(dwMilliseconds); } - virtual std::string to_string() const override + std::string to_string() const override { return "Sleeping for " + openvpn::to_string(dwMilliseconds) + " milliseconds..."; } diff --git a/openvpn/win/winsvc.hpp b/openvpn/win/winsvc.hpp index 0e9944b8c..054d33171 100644 --- a/openvpn/win/winsvc.hpp +++ b/openvpn/win/winsvc.hpp @@ -164,13 +164,10 @@ class Service service = this; // convert service name to wide string - const std::wstring wname = wstring::from_utf8(config.name); - - // store it in a raw wchar_t array - std::unique_ptr<wchar_t[]> wname_raw = wstring::to_wchar_t(wname); + std::wstring wname = wstring::from_utf8(config.name); const SERVICE_TABLE_ENTRYW dispatch_table[] = { - {wname_raw.get(), (LPSERVICE_MAIN_FUNCTIONW)svc_main_static}, + {wname.data(), (LPSERVICE_MAIN_FUNCTIONW)svc_main_static}, {NULL, NULL}}; // This call returns when the service has stopped. diff --git a/openvpn/ws/chunked.hpp b/openvpn/ws/chunked.hpp index 676f8084b..f7db0e1ed 100644 --- a/openvpn/ws/chunked.hpp +++ b/openvpn/ws/chunked.hpp @@ -56,7 +56,7 @@ class ChunkedHelper } else { - BufferAllocated content(buf.read_alloc(size), size, 0); + BufferAllocated content(buf.read_alloc(size), size, BufAllocFlags::NO_FLAGS); size = 0; callback.chunked_content_in(content); } @@ -145,7 +145,7 @@ class ChunkedHelper if (!buf || buf->offset() < headroom || buf->remaining() < tailroom) { // insufficient headroom/tailroom, must realloc - Frame::Context fc(headroom, 0, tailroom, 0, sizeof(size_t), 0); + Frame::Context fc(headroom, 0, tailroom, 0, sizeof(size_t), BufAllocFlags::NO_FLAGS); buf = fc.copy(buf); } diff --git a/openvpn/ws/httpcliset.hpp b/openvpn/ws/httpcliset.hpp index f45743b37..054f6af1b 100644 --- a/openvpn/ws/httpcliset.hpp +++ b/openvpn/ws/httpcliset.hpp @@ -433,9 +433,7 @@ class ClientSet : public RC<thread_unsafe_refcount> public: typedef RCPtr<HostRetry> Ptr; - HostRetry() - { - } + HostRetry() = default; template <typename T, typename... Args> HostRetry(T first, Args... args) @@ -459,7 +457,7 @@ class ClientSet : public RC<thread_unsafe_refcount> return (*this)[index++]; } - virtual void retry(TransactionSet &ts, Transaction &t) override + void retry(TransactionSet &ts, Transaction &t) override { ts.host.host = next_host(); } @@ -1007,7 +1005,7 @@ class ClientSet : public RC<thread_unsafe_refcount> { // find an ID that's not already in use const client_t id = next_id++; - if (clients.find(id) == clients.end()) + if (!clients.contains(id)) return id; } } diff --git a/openvpn/ws/httpcommon.hpp b/openvpn/ws/httpcommon.hpp index 7a2c2cd08..6bcb5c66b 100644 --- a/openvpn/ws/httpcommon.hpp +++ b/openvpn/ws/httpcommon.hpp @@ -301,7 +301,7 @@ class HTTPBase : public REFCOUNT_BASE if (actual >= 0) { #if defined(OPENVPN_DEBUG_HTTP) - BufferAllocated tmp(outbuf->c_data(), actual, 0); + BufferAllocated tmp(outbuf->c_data(), actual, BufAllocFlags::NO_FLAGS); OPENVPN_LOG("OUT: " << buf_to_string(tmp)); #endif outbuf->advance(actual); diff --git a/openvpn/ws/httpserv.hpp b/openvpn/ws/httpserv.hpp index 85aae66b3..54ac8671c 100644 --- a/openvpn/ws/httpserv.hpp +++ b/openvpn/ws/httpserv.hpp @@ -1065,7 +1065,7 @@ class Listener : public ProxyListener { // find an ID that's not already in use const client_t id = next_id++; - if (clients.find(id) == clients.end()) + if (!clients.contains(id)) return id; } } diff --git a/openvpn/ws/resolver_results.hpp b/openvpn/ws/resolver_results.hpp index 2d95b48f3..922b46358 100644 --- a/openvpn/ws/resolver_results.hpp +++ b/openvpn/ws/resolver_results.hpp @@ -53,12 +53,9 @@ inline void filter_by_ip_version(RESULTS &results, const IP::Addr::Version ip_ve return; } - // the "auto" lambda parameter makes this C++14 code - data->erase(std::remove_if(data->begin(), - data->end(), - [v4](auto &e) - { return e.endpoint().address().is_v4() != v4; }), - data->end()); + std::erase_if(*data, + [v4](const auto &e) + { return e.endpoint().address().is_v4() != v4; }); } #elif defined(ASIO_RESOLVER_RESULTS_DATA_REQUIRED) diff --git a/openvpn/ws/websocket.hpp b/openvpn/ws/websocket.hpp index e62044947..bce5d7826 100644 --- a/openvpn/ws/websocket.hpp +++ b/openvpn/ws/websocket.hpp @@ -323,7 +323,7 @@ class Receiver if (!buf.allocated()) { buf = std::move(inbuf); - buf.or_flags(BufAllocFlags::GROW); + buf.add_flags(BufAllocFlags::GROW); } else buf.append(inbuf); diff --git a/renovate.json b/renovate.json index feca7c2d3..10492dbc5 100644 --- a/renovate.json +++ b/renovate.json @@ -1,7 +1,7 @@ { "$schema": "http://nginx/renovate-schema.json", "extends": [ - "local>openvpntechnologies/ops-saas-renovate", + "local>openvpntechnologies/ops-iaas-renovate", "local>openvpntechnologies/core-team-renovate" ], "rebaseWhen": "behind-base-branch", @@ -36,7 +36,7 @@ { "customType": "regex", "fileMatch": ["^\\.github/workflows/.+\\.yml$"], - "matchStrings": ["vcpkgGitCommitId:\\s*(?<currentDigest>.*?)\\n"], + "matchStrings": ["VCPKG_GIT_COMMIT_ID:\\s*(?<currentDigest>.*?)\\n"], "currentValueTemplate": "master", "depNameTemplate": "vcpkg", "packageNameTemplate": "https://github.com/microsoft/vcpkg", diff --git a/scripts/build b/scripts/build deleted file mode 100755 index 57c7369aa..000000000 --- a/scripts/build +++ /dev/null @@ -1,443 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ "$XTRACE" = 1 ]; then - set -x -fi - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -enum_build_extras() -{ - ls -d $(echo $O3/*/scripts/build-extras/*) | sort -} - -if [ -z "$1" ]; then - echo "usage: ./build target" - echo "options:" - echo " PROF=<platform> -- source vars/vars-<platform> before running" - echo " DPROF=1 -- when PROF is specified, use the debugging variant" - echo " CLANG=1 -- use clang instead of gcc" - echo " DEBUG=1 -- enable debug symbols" - echo " CO=1 -- compile only" - echo " OBJC=1 -- top-level source file is Obj-C" - echo ' ECHO=1 -- show commands' - echo ' OUTBIN=name -- write binary to name' - echo " STRIP=1 -- strip binary" - echo " STRICT=1 -- more warnings" - echo " GPROF=1 -- build for gprof profiling" - echo " PGEN=1 -- generate data for profile-guided optimization" - echo " PUSE=1 -- use data from previous run of PGEN=1 build" - echo " ASIO=1 -- build with ASIO" - echo " ASIO_DIR=<dir> -- specify ASIO tree" - echo " MTLS=1 -- include mbedTLS" - echo " MTLS_SYS=1 -- use system mbedTLS" - echo " MTLS_PATH=path -- use user specified mbedTLS source folder" - echo " MTLS_LIBS=ldflags -- user specific mbedTLS LDFLAGS" - echo " MTLS_DIST=path -- use user-specified mbedTLS distribution" - echo " MA_HYBRID=1 -- use mbedTLS/AppleCrypto hybrid" - echo " OPENSSL_DIST=<dir> -- specify custom OpenSSL build" - echo " NOSSL=1 -- don't include OpenSSL" - echo " OPENSSL_SYS=1 -- include system OpenSSL" - echo " MINI=1 -- link with OpenSSL mini crypto lib" - echo " OSSL=1 -- include OpenSSL" - echo " SSL_BOTH=1 -- include OpenSSL and Apple SSL on Mac" - echo " NOTHREADS=1 -- disable threads" - echo ' GCC_EXTRA="-DITER=5" -- add build flags' - echo " LZO=1 -- build with LZO compression library" - echo " LZ4=1 -- build with LZ4 compression library" - echo " LZ4_SYS=1 -- build with system LZ4 compression library" - echo " SNAP=1 -- build with Snappy compression library" - echo " CITY=1 -- build with Cityhash hash library" - echo " XXHASH=1 -- build with XXHash hash library" - echo " CAP=1 -- build with libcap" - echo " JAVA=1 -- build with JVM" - echo ' EXTRA_CPP="foo1.cpp foo2.cpp" -- add extra .cpp files into single compilation unit' - echo ' EXTRA_CPP_OBJS="bar1.cpp foo2.cpp" -- add extra .cpp as separate compilation units' - echo " GTEST_DIR=<dir> -- specify googletest tree, required for building unit tests" - echo " VAL=1 -- (optional) build with valgrind run-time extensions" - echo " ASAN=1 -- (optional) enable ASAN run-time checks" - echo " PCRE=1 -- build with PCRE library" - echo " SYSD=1 -- build with systemd library" - echo " SQLITE=1 -- build with sqlite3 library" - for s in $(enum_build_extras) ; do - . $s args - done - exit 1 -fi - -# determine platform if PROF is set to "auto" -if [ "$PROF" = "auto" ]; then - if [ "$(uname)" == "Darwin" ]; then - export PROF=osx64 - elif [ "$(uname)" == "Linux" ]; then - export PROF=linux - else - echo "PROF=auto : cannot determine platform" - exit 1 - fi -fi - -# source vars file -if [ "$PROF" ]; then - suffix="" - [ "$DPROF" = "1" ] && suffix="-dbg" - pfn="$O3/core/vars/vars-$PROF$suffix" - if ! [ -f "$pfn" ]; then - pfn="$PROF" - fi - . $pfn || exit 1 -fi - -# remove previous build -[ -z "$OUTBIN" ] && OUTBIN="$(basename $1)" -rm -f $OUTBIN - -# build options -CPPFLAGS="" -LIBS="" -LIBDIRS="" -EXTRA_SRC_OBJ="" - -# MbedTLS/AppleCrypto hybrid -if [ "$MA_HYBRID" = "1" ]; then - MTLS=1 -fi - -# building on Mac OS X for osx or ios? -if [ "$APPLE_FAMILY" = "1" ]; then - [ -z "$CLANG" ] && CLANG=1 -fi - -# clang support -if [ "$CLANG" = "1" ]; then - [ -z "$GPP_CMD" ] && GPP_CMD=clang++ -fi - -# building on Linux, use system OpenSSL -if [ "$PLATFORM" = "linux" ] && [ "$OSSL" = "1" ] && [ "$NOSSL" != "1" ] && [ -z "$OPENSSL_SYS" ]; then - OSSL=0 - OPENSSL_SYS=1 -fi - -# building on Linux, use system LZ4 -if [ "$PLATFORM" = "linux" ] && [ "$LZ4" = "1" ] && [ -z "$LZ4_SYS" ]; then - LZ4_SYS=1 -fi - -# default commands -[ -z "$STRIP_CMD" ] && STRIP_CMD=strip -[ -z "$GPP_CMD" ] && GPP_CMD=g++ - -# build flags -FLAGS="-Wall" -[ "$STRICT" = "1" ] && FLAGS="$FLAGS -Wextra" -[ "$CLANG" = "1" ] && FLAGS="$FLAGS -Wno-tautological-compare -Wno-unused-private-field -Wno-c++1y-extensions" -FLAGS="$FLAGS -Wno-sign-compare -Wno-unused-parameter" - -# The Mac OS X tun/tap driver doesn't play with with kqueue. -# utun devices, however, work fine with kqueue. -#if [ "$PLATFORM" = "osx" ]; then -# CPPFLAGS="$CPPFLAGS -DBOOST_ASIO_DISABLE_KQUEUE" -#fi - -# MbedTLS -if [ -n "$MTLS_DIST" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS -I$MTLS_DIST/include" - LIBDIRS="$LIBDIRS -L$MTLS_DIST/library" - LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" - MTLS=1 -elif [ "$MTLS_SYS" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS" - LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" -elif [ "$MTLS" = "1" ]; then - LIBS="$LIBS -lmbedtls $MTLS_LIBS" - if [ "$MA_HYBRID" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS_APPLE_HYBRID" - else - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS" - fi - if [ -n "$MTLS_PATH" ]; then - CPPFLAGS="$CPPFLAGS -I$MTLS_PATH/include" - LIBDIRS="$LIBDIRS -L$MTLS_PATH/library" - else - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" - LIBDIRS="$LIBDIRS -L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" - fi - if [ "$MINI" = "1" ]; then - LIBS="$LIBS -lminicrypto" - LIBDIRS="$LIBDIRS -L$DEP_DIR/minicrypto/minicrypto-$PLATFORM" - CPPFLAGS="$CPPFLAGS -DUSE_MINICRYPTO" - NOSSL=1 - fi -fi - -# OpenSSL -if [ "$OPENSSL_DIST" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL -I$OPENSSL_DIST/include" - LIBDIRS="$LIBDIRS -L$OPENSSL_DIST/lib" - LIBS="$LIBS -lssl -lcrypto" -elif [ "$APPLE_FAMILY" = "1" ]; then - # On Mac, only link with OpenSSL if OSSL is defined. - # On other platforms, usually link with OpenSSL. - if [ "$OPENSSL_SYS" == "1" ]; then - NO_DEPRECATE="-Wno-deprecated-declarations" - else - NO_DEPRECATE="" - fi - if [ "$OPENSSL_LINK" = "1" ]; then - LIBS="$LIBS -lcrypto -lssl" - elif [ "$OSSL" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL" - LIBS="$LIBS -lcrypto -lssl" - [ "$CLANG" = "1" ] && [ "$NO_DEPRECATE" ] && FLAGS="$FLAGS $NO_DEPRECATE" - elif [ "$SSL_BOTH" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_APPLE_SSL -DUSE_OPENSSL" - LIBS="$LIBS -lcrypto -lssl" - [ "$CLANG" = "1" ] && [ "$NO_DEPRECATE" ] && FLAGS="$FLAGS $NO_DEPRECATE" - elif [ "$MTLS" = "1" ]; then - NOSSL=1 - else - NOSSL=1 - CPPFLAGS="$CPPFLAGS -DUSE_APPLE_SSL" - fi - LIBS="$LIBS -framework Security" -else - if [ "$OPENSSL_LINK" = "1" ]; then - LIBS="$LIBS -lcrypto -lssl" - elif [ "$NOSSL" != "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL" - LIBS="$LIBS -lssl -lcrypto -ldl" - fi -fi -if [ "$OPENSSL_SYS" != "1" ] && [ "$OPENSSL_LINK" != "1" ] && [ "$NOSSL" != "1" ] && [ -z "$OPENSSL_DIST" ]; then - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/openssl/openssl-$PLATFORM/include" - LIBDIRS="$LIBDIRS -L$DEP_DIR/openssl/openssl-$PLATFORM/lib" -fi - -# Apple libs -if [ "$APPLE_FAMILY" = "1" ]; then - LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration -framework IOKit -framework ApplicationServices" -fi - -# boost -#CPPFLAGS="$CPPFLAGS -I$DEP_DIR/boost" -#LIBS="$LIBS -lboost_system" -#LIBDIRS="$LIBDIRS -L$DEP_DIR/boost/stage-$PLATFORM/lib" -#if [ "$NOTHREADS" = "1" ]; then -# CPPFLAGS="$CPPFLAGS -DBOOST_DISABLE_THREADS" -#else -# #LIBS="$LIBS -lboost_thread" # no longer needed because we use std::thread now -# [ "$PLATFORM" != "android" ] && FLAGS="$FLAGS -pthread" -#fi - -# asio -if [ "$ASIO" = "1" ] || [ "$ASIO_DIR" ]; then - [ -z "$ASIO_DIR" ] && ASIO_DIR="$DEP_DIR/asio" - CPPFLAGS="$CPPFLAGS -DUSE_ASIO -DASIO_STANDALONE -DASIO_NO_DEPRECATED -I$ASIO_DIR/asio/include" -fi - -# gtest -if [ "$GTEST_DIR" ]; then - CPPFLAGS="$CPPFLAGS -I$GTEST_DIR/googletest/include" - LIBDIRS="$LIBDIRS -L$GTEST_DIR/lib" - LIBS="$LIBS -lgtest" -fi - -# LZO compression -if [ "$LZO" = "1" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/lzo/lzo-$PLATFORM/lib" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/lzo/lzo-$PLATFORM/include" - LIBS="$LIBS -llzo2" - CPPFLAGS="$CPPFLAGS -DHAVE_LZO" -fi - -# LZ4 compression -if [ "$LZ4_SYS" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DHAVE_LZ4" - LIBS="$LIBS -llz4" -elif [ "$LZ4" = "1" ]; then - EXTRA_SRC_OBJ="$EXTRA_SRC_OBJ $DEP_DIR/lz4/lz4-$PLATFORM/lib/liblz4.a" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/lz4/lz4-$PLATFORM/include -DHAVE_LZ4" -fi - -# Snappy compression -if [ "$SNAP" = "1" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/snappy/snappy-$PLATFORM/lib" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/snappy/snappy-$PLATFORM/include" - LIBS="$LIBS -lsnappy" - CPPFLAGS="$CPPFLAGS -DHAVE_SNAPPY" -fi - -# Cityhash -if [ "$CITY" = "1" ]; then - if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" - fi - if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/include" ]; then - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include" - fi - LIBS="$LIBS -lcityhash" - CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH" -fi - -# XXHash -if [ "$XXHASH" = "1" ] || [ "$XXHASH_DIR" ]; then - [ -z "$XXHASH_DIR" ] && XXHASH_DIR="$DEP_DIR/xxHash" - CPPFLAGS="$CPPFLAGS -DHAVE_XXHASH -I$XXHASH_DIR" -fi - -# libcap -if [ "$CAP" = "1" ]; then - LIBS="$LIBS -lcap" - CPPFLAGS="$CPPFLAGS -DHAVE_LIBCAP" -fi - -# libsystemd -if [ "$SYSD" = "1" ]; then - LIBS="$LIBS -lsystemd" - CPPFLAGS="$CPPFLAGS -DHAVE_LIBSYSTEMD" -fi - -# libsqlite3 -if [ "$SQLITE" = "1" ]; then - LIBS="$LIBS -lsqlite3" - CPPFLAGS="$CPPFLAGS -DHAVE_SQLITE" -fi - -# PCRE -if [ "$PCRE" = "1" ]; then - LIBS="$LIBS -lpcre" -fi - -# ASAN requested -- ensure higher-fidelity stacks -if [ "$ASAN" = "1" ]; then - FLAGS+=" -ggdb3 -fno-omit-frame-pointer -fsanitize=address" - CPPFLAGS="$CPPFLAGS -DINSTRUMENTATION_SLOWDOWN" -else - ASAN= -fi - -# Valgrind -- but only if ASAN is not enabled -if [ "$ASAN" = "" -a "$VAL" ]; then - CPPFLAGS="$CPPFLAGS -DHAVE_VALGRIND -DINSTRUMENTATION_SLOWDOWN" -fi - -# JVM -if [ "$JAVA" = "1" ]; then - if [ -z "$JAVA_HOME" ]; then - echo JAVA_HOME not defined - exit 1 - fi - LIBDIRS="$LIBDIRS -L$JAVA_HOME/jre/lib/amd64/server" - CPPFLAGS="$CPPFLAGS -I$JAVA_HOME/include -I$JAVA_HOME/include/linux" - LIBS="$LIBS -ljvm" -fi - -# other environments -for s in $(enum_build_extras) ; do - . $s deps -done - -# Android NDK -if [ "$PLATFORM" = "android" ]; then - CPPFLAGS="$CPPFLAGS -D__GLIBC__" - CPPFLAGS="$CPPFLAGS -D_GLIBCXX_HAVE_FENV_H=1" -# CPPFLAGS="$CPPFLAGS -DBOOST_NO_INTRINSIC_WCHAR_T" -fi - -# Special platform flags -if [ "$PLATFORM_FLAGS" ]; then - FLAGS="$FLAGS $PLATFORM_FLAGS" -fi - -# C++ compiler flags -if [ "$CXX_COMPILER_FLAGS" ]; then - FLAGS="$FLAGS $CXX_COMPILER_FLAGS" -fi - -# Other compiler flags -if [ "$OTHER_COMPILER_FLAGS" ]; then - FLAGS="$FLAGS $OTHER_COMPILER_FLAGS" -fi - -# ovpn3 -CPPFLAGS="$CPPFLAGS -I$O3/core" - -# profile-guided optimization -if [ "$PGEN" = "1" ]; then - FLAGS="$FLAGS -fprofile-generate" -elif [ "$PUSE" = "1" ]; then - FLAGS="$FLAGS -fprofile-use" -fi - -# compiler flags -FLAGS="$LIB_OPT_LEVEL $FLAGS" - -# whole-program -if [ "$CLANG" != "1" ] && [ "$DEBUG_BUILD" != "1" ] && [ -z "$EXTRA_CPP" ] && [ "$CO" != "1" ]; then - FLAGS="-fwhole-program $FLAGS" -fi - -# compile only -if [ "$CO" == "1" ]; then - OUTPUT="-c" - LIBDIRS="" - LIBS="" - EXTRA_SRC_OBJ="" -else - OUTPUT="-o $OUTBIN" -fi - -# main source file -MAIN_CPP="$1.cpp" -if ! [ -e "$MAIN_CPP" ] && [ "$EXTRA_CPP" ]; then - MAIN_CPP="" -fi - -# release/debug builds -if [ "$DEBUG" = "1" ]; then - # build with debug symbols - if [ "$PLATFORM" = "linux" ]; then - FLAGS="-ggdb $FLAGS" - else - FLAGS="-g $FLAGS" - fi -else - # release build - [ "$CLANG" != "1" ] && FLAGS="$FLAGS -flto=4 -Wl,--no-as-needed" - [ "$GPROF" = "1" ] && FLAGS="$FLAGS -pg" -fi - - -if [ ! -z "${EXTRA_CPP_OBJS}" ]; then - for CPP_OBJ in $EXTRA_CPP_OBJS $MAIN_CPP; do - [ "$ECHO" = "1" ] && echo "compiling $CPP_OBJ" - CMD="$GPP_CMD $FLAGS $GCC_EXTRA $CPPFLAGS $LIBDIRS $CPP_OBJ -c -o $CPP_OBJ.o" - [ "$ECHO" = "1" ] && echo $CMD - $CMD - EXTRA_SRC_OBJ="${EXTRA_SRC_OBJ} $CPP_OBJ.o" - done - MAIN_CPP="" -fi - -# Construct command -if [ "$OBJC" == "1" ]; then - FLAGS="$FLAGS -fobjc-arc" - LIBS="-framework Foundation $LIBS" - SRC="$1.mm" - CMD="$GPP_CMD $FLAGS $GCC_EXTRA $CPPFLAGS $LIBDIRS $SRC $EXTRA_CPP $EXTRA_SRC_OBJ $OUTPUT $LIBS" -else - CMD="$GPP_CMD $FLAGS $GCC_EXTRA $CPPFLAGS $LIBDIRS $MAIN_CPP $EXTRA_CPP $EXTRA_SRC_OBJ $OUTPUT $LIBS" -fi - -# execute CMD -[ "$ECHO" = "1" ] && echo $CMD -$CMD - -# maybe strip -[ "$STRIP" = "1" ] && $STRIP_CMD $OUTBIN -exit 0 diff --git a/scripts/build-extras/jsoncpp.sh b/scripts/build-extras/jsoncpp.sh deleted file mode 100644 index 0ba6fc384..000000000 --- a/scripts/build-extras/jsoncpp.sh +++ /dev/null @@ -1,9 +0,0 @@ -if [ "$1" = "args" ]; then - echo " JSON=1 -- build with JsonCpp library" -elif [ "$1" = "deps" ]; then - # JsonCpp - if [ "$JSON" = "1" ]; then - CPPFLAGS="$CPPFLAGS $(pkg-config --cflags jsoncpp) -DHAVE_JSONCPP" - EXTRA_SRC_OBJ="$EXTRA_SRC_OBJ $(pkg-config --libs jsoncpp)" - fi -fi diff --git a/scripts/build-extras/zlib.sh b/scripts/build-extras/zlib.sh deleted file mode 100644 index c06adabd9..000000000 --- a/scripts/build-extras/zlib.sh +++ /dev/null @@ -1,8 +0,0 @@ -if [ "$1" = "args" ]; then - echo " ZLIB=1 -- link with zlib" -elif [ "$1" = "deps" ]; then - if [ "$ZLIB" = "1" ]; then - LIBS="$LIBS -lz" - CPPFLAGS="$CPPFLAGS -DHAVE_ZLIB" - fi -fi diff --git a/scripts/linux/build-all b/scripts/linux/build-all deleted file mode 100755 index 2e73eea4d..000000000 --- a/scripts/linux/build-all +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e -set -u -if [ -z "${O3:-}" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -export DEP_DIR="${DEP_DIR:-$HOME/linux}" -export TARGET="${TARGET:-linux}" -cd "$DEP_DIR" -rm -rf asio* boost* lz4* lzo* minicrypto openssl* polarssl* snappy* -echo "******* ASIO" -"$O3"/core/deps/asio/build-asio -echo "******* xxHash" -"$O3"/core/deps/xxHash/build-xxHash -if [ "${MTLS:-1}" = 0 ] ; then - echo "******* MBEDTLS (skipped)" -else - echo "******* MBEDTLS" - "$O3"/core/scripts/linux/build-mbedtls -fi -echo "******* LZ4" -"$O3"/core/scripts/linux/build-lz4 - diff --git a/scripts/linux/build-lz4 b/scripts/linux/build-lz4 deleted file mode 100755 index 956fb5634..000000000 --- a/scripts/linux/build-lz4 +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf lz4 -mkdir lz4 -TARGET=${TARGET:-linux} $O3/core/deps/lz4/build-lz4 -exit 0 diff --git a/scripts/linux/build-mbedtls b/scripts/linux/build-mbedtls deleted file mode 100755 index de355db78..000000000 --- a/scripts/linux/build-mbedtls +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf mbedtls - -if [ "$LINK_MODE" = "shared" ]; then - SHARED=1 -else - SHARED=0 -fi -VERBOSE=1 TARGET=${TARGET:-linux} ENABLE_SERVER=1 SHARED=$SHARED $O3/core/deps/mbedtls/build-mbedtls -exit 0 diff --git a/scripts/mingw/.gitignore b/scripts/mingw/.gitignore deleted file mode 100644 index 86f931caa..000000000 --- a/scripts/mingw/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build-i686 -build-x86_64 -deps-i686 -deps-x86_64 diff --git a/scripts/mingw/build b/scripts/mingw/build deleted file mode 100755 index fa798447b..000000000 --- a/scripts/mingw/build +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -DL="${DL:-/tmp/dl}" -DEP_DIR_PREFIX=$PWD/deps -CORE_DIR=$(dirname $(realpath -s $0))/../.. -CMAKE_C_COMPILER="w64-mingw32-gcc-posix" -CMAKE_CXX_COMPILER="w64-mingw32-g++-posix" -ARCH=${ARCH:-i686 x86_64} - -download_deps() -{ - if [ -n "$NO_DEPS" ]; then - echo "Skip dependencies download" - return - fi - - pushd $DL - - rm -rf lz4 - git clone https://github.com/lz4/lz4.git - portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/lz4/portfile.cmake - gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2) - git -C lz4 checkout "${gitref}" - - rm -rf jsoncpp - git clone https://github.com/open-source-parsers/jsoncpp.git - portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/jsoncpp/portfile.cmake - gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2) - git -C jsoncpp checkout "${gitref}" - - if [ -z "$NO_OPENSSL" ]; then - rm -rf openssl - portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/openssl/vcpkg.json - osslver=$(wget -q -O- "$portfile_url" | grep -oP '\"version": \"\S+' | cut -d' ' -f2 | tr -d "\",") - git clone --single-branch --branch "openssl-$osslver" https://github.com/openssl/openssl.git - fi - - rm -rf tap-windows6 - git clone https://github.com/OpenVPN/tap-windows6.git - portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/tap-windows6/portfile.cmake - gitref=$(wget -q -O- "$portfile_url" | grep -oP '\bREF\s+\S+' | cut -d' ' -f2) - git -C tap-windows6 checkout "${gitref}" - - rm -rf asio - portfile=${CORE_DIR}/deps/vcpkg-ports/asio/portfile.cmake - gitref=$(grep -oP '\bREF\s+\S+' "$portfile" | cut -d' ' -f2) - git clone --single-branch --branch "$gitref" https://github.com/chriskohlhoff/asio - # apply asio patches - for patchfile in $(grep -o patches.* "$portfile" | cut -d '/' -f2); do - echo applying patch $patchfile - patch -d asio -p1 < "${CORE_DIR}/deps/asio/patches/$patchfile" - done - - rm -rf xxHash - git clone https://github.com/Cyan4973/xxHash.git - portfile_url=https://raw.githubusercontent.com/microsoft/vcpkg/master/ports/xxhash/vcpkg.json - gitref=$(wget -q -O- "$portfile_url" | grep -oP '\"version": \"\S+' | cut -d' ' -f2 | tr -d "\",") - git -C xxHash checkout "v${gitref}" - - popd -} - -build_lz4() -{ - ARCH=$1 - - pushd $DL/lz4 - - mkdir build-${ARCH} - cd build-${ARCH} - - cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \ - ../build/cmake/ - make && make install - - popd -} - -build_jsoncpp() -{ - ARCH=$1 - - pushd $DL/jsoncpp - - mkdir build-${ARCH} - cd build-${ARCH} - - cmake -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \ - -D JSONCPP_WITH_TESTS=false \ - -D BUILD_SHARED_LIBS=true \ - -D CMAKE_BUILD_TYPE=Release \ - .. - make && make install - - popd -} - -build_openssl() -{ - if [ -n "$NO_OPENSSL" ]; then - echo "Skip OpenSSL build" - return - fi - - ARCH=$1 - - pushd $DL/openssl - - [ "$ARCH" == "x86_64" ] && OUT="mingw64" || OUT="mingw" - make clean || true - ./Configure --prefix=$DEP_DIR_PREFIX-$ARCH --libdir=lib no-idea no-mdc2 no-rc5 shared $OUT --cross-compile-prefix=$ARCH-w64-mingw32- - make && make install - - popd -} - -build_tap_windows6() -{ - ARCH=$1 - - cp $DL/tap-windows6/src/tap-windows.h $DEP_DIR_PREFIX-$ARCH/include -} - -build_asio() -{ - ARCH=$1 - - mkdir -p $DEP_DIR_PREFIX-$ARCH/asio - cp -R $DL/asio/* $DEP_DIR_PREFIX-$ARCH/asio -} - -build_xxhash() -{ - ARCH=$1 - - mkdir -p $DEP_DIR_PREFIX-$ARCH/xxHash - cp -R $DL/xxHash/* $DEP_DIR_PREFIX-$ARCH/xxHash -} - -build_deps() -{ - if [ -n "$NO_DEPS" ]; then - echo "Skip dependencies build" - return - fi - - ARCH=$1 - - echo "Building deps for $arch" - - mkdir -p $DEP_DIR_PREFIX-$ARCH - - build_lz4 $ARCH - build_jsoncpp $ARCH - build_tap_windows6 $ARCH - build_asio $ARCH - build_xxhash $ARCH - build_openssl $ARCH -} - -build_core() -{ - ARCH=$1 - - echo "Building core for $arch" - - rm -rf build-$ARCH - mkdir build-$ARCH - - [ -z "$DCO" ] || { - WITH_OVPNDCOWIN="-D CLI_OVPNDCOWIN=ON" - } - - pushd build-$ARCH - - DEP_DIR=$DEP_DIR_PREFIX-$ARCH \ - OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR:-$DEP_DIR_PREFIX-$ARCH} \ - cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \ - -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_PREFIX_PATH=/usr/local/$ARCH-w64-mingw32 \ - -D CMAKE_BUILD_TYPE=Release \ - -D USE_WERROR=true \ - $WITH_OVPNDCOWIN \ - $CORE_DIR - - make - - popd -} - -mkdir -p $DL - -download_deps -for arch in $ARCH -do - echo "Building for $arch" - build_deps $arch - build_core $arch -done diff --git a/scripts/mingw/build-vcpkg b/scripts/mingw/build-vcpkg deleted file mode 100755 index 254f5168f..000000000 --- a/scripts/mingw/build-vcpkg +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -: ${VCPKG_ROOT?:VCPKG_ROOT needs to be set} -: ${ARCH:=i686 x86_64} -: ${DCO:=1} -CORE_DIR=$(dirname $(realpath -s $0))/../.. -CMAKE_C_COMPILER="w64-mingw32-gcc-posix" -CMAKE_CXX_COMPILER="w64-mingw32-g++-posix" - -build_core() -{ - local ARCH=$1 - local VCPKG_ARCH=$ARCH - if [ "$ARCH" = i686 ]; then - VCPKG_ARCH=x86 - fi - if [ "$ARCH" = x86_64 ]; then - VCPKG_ARCH=x64 - fi - - echo "Building core for $ARCH (vcpkg: $VCPKG_ARCH-mingw-dynamic)" - - rm -rf "build-$ARCH" - mkdir "build-$ARCH" - - [ -z "$DCO" ] || { - WITH_OVPNDCOWIN="-D CLI_OVPNDCOWIN=ON" - } - - pushd build-$ARCH - - cmake -D CMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" \ - -D VCPKG_TARGET_TRIPLET="$VCPKG_ARCH-mingw-dynamic" \ - -D VCPKG_APPLOCAL_DEPS=OFF \ - -D VCPKG_OVERLAY_PORTS="$CORE_DIR/deps/vcpkg-ports" \ - -D CMAKE_C_COMPILER="$ARCH-$CMAKE_C_COMPILER" \ - -D CMAKE_CXX_COMPILER="$ARCH-$CMAKE_CXX_COMPILER" \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_PREFIX_PATH="/usr/local/$ARCH-w64-mingw32" \ - -D CMAKE_BUILD_TYPE=Release \ - -D USE_WERROR=true \ - $WITH_OVPNDCOWIN \ - $CORE_DIR - - make - - popd -} - -for arch in $ARCH -do - echo "Building for $arch" - build_core $arch -done diff --git a/scripts/snapshot b/scripts/snapshot deleted file mode 100755 index 537a069ca..000000000 --- a/scripts/snapshot +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -# Create a tarball from a git checkout. -# -# DEP_DIR : dependency directory -# NAME : basename of git root directory in dependency directory -# DL : download directory, where to build tarball, defaults to ~/Downloads - -# Note: this script gives priority to $NAME-yyyymmdd as source location, -# so for Asio, make sure to delete such directories if you want to -# favor straight "asio" directory. - -set -e -if [ -z "$NAME" ]; then - echo "NAME var must exist" - exit 1 -fi -[ -z "$DL" ] && DL=~/Downloads -if ! [ -d "$DL" ]; then - echo $DL directory must exist - exit 1 -fi -[ "$DEP_DIR" ] && cd $DEP_DIR -NAMETS=$(ls -dt ${NAME}-* 2>/dev/null | head -n1) -if [ -z "$NAMETS" ]; then - cd $NAME - NAMETS=${NAME}-$(git log -1 --date=short --pretty=format:%cd | tr -d '-') - cd .. - mv $NAME $NAMETS -fi -NAMEVER=$(echo $NAME | awk '{print toupper($0)}')_VERSION -TGZ=$DL/$NAMETS.tar.gz -echo "creating $TGZ" -tar cfz $TGZ $NAMETS -echo 'Add to $O3/core/deps/lib-versions :' -echo "export $NAMEVER=$NAMETS" diff --git a/scripts/update-copyright b/scripts/update-copyright deleted file mode 100755 index 61450557a..000000000 --- a/scripts/update-copyright +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -# update-copyright - Simple tool to update the Copyright lines -# in all files checked into git -# -# Copyright (C) 2018-2022 OpenVPN Inc -# Copyright (C) 2018-2022 David Sommerseth <davids@openvpn.net> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License Version 3 -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program in the COPYING file. -# If not, see <http://www.gnu.org/licenses/>. -# - -# Basic shell sanity -set -eu - -# Simple argument control -if [ $# -ne 1 ]; then - echo "Usage: $0 <New Copyright Year>" - exit 1 -fi - -# Only update Copyright lines with these owners -# The 'or' operator is GNU sed specific, and must be \| -UPDATE_COPYRIGHT_LINES="OpenVPN Inc\|@openvpn\.net\\|unstable\.cc\|gmail\.com\|@fox-it\.com" -COPY_YEAR="$1" - -cd "$(git rev-parse --show-toplevel)" -for file in $(git ls-files | grep -v deps/); -do - echo -n "Updating $file ..." - # The first sed operation covers 20xx-20yy copyright lines, - # The second sed operation changes 20xx -> 20xx-20yy - sed -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) 20..-\)\(20..\)[[:blank:]]\+/\1$COPY_YEAR /" \ - -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) \)\(20..\)[[:blank:]]\+/\1\2-$COPY_YEAR /" \ - -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) $COPY_YEAR\)\(-$COPY_YEAR\)[[:blank:]]\+/\1 /" \ - -i $file - echo " Done" -done -echo -echo "** All files updated with $COPY_YEAR as the ending copyright year" -echo -exit 0 diff --git a/scripts/version b/scripts/version deleted file mode 100755 index 90623c099..000000000 --- a/scripts/version +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# OpenVPN -- An application to securely tunnel IP networks -# over a single port, with support for SSL/TLS-based -# session authentication and key exchange, -# packet encryption, packet authentication, and -# packet compression. -# -# Copyright (C) 2018-2022 OpenVPN Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License Version 3 -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program in the COPYING file. -# If not, see <http://www.gnu.org/licenses/>. - -set -eu - -# ensure this script works even when core is used as submodule, by setting -# O3/core/.git as git folder -export GIT_DIR=$(dirname $0)/../.git - -MAJOR=3 -BRANCH="$(git rev-parse --symbolic-full-name HEAD | cut -d/ -f3- | tr / _)" -COMMIT_ID="$(git rev-list HEAD -1 --abbrev-commit)" - -echo "$MAJOR.git:$BRANCH:$COMMIT_ID" diff --git a/test/ovpncli/cli.cpp b/test/ovpncli/cli.cpp index ae04e2916..a35b2aff8 100644 --- a/test/ovpncli/cli.cpp +++ b/test/ovpncli/cli.cpp @@ -43,11 +43,6 @@ // don't export core symbols #define OPENVPN_CORE_API_VISIBILITY_HIDDEN -// use SITNL on Linux by default -#if defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_USE_IPROUTE2) && !defined(OPENVPN_USE_SITNL) -#define OPENVPN_USE_SITNL -#endif - // should be included before other openvpn includes, // with the exception of openvpn/log includes #include <client/ovpncli.cpp> @@ -69,16 +64,17 @@ #include <openvpn/common/process.hpp> #endif -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS #include <openvpn/mbedtls/util/pkcs1.hpp> #elif defined(USE_OPENSSL) #include <openssl/evp.h> -#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) +#include <openssl/opensslv.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L #include <openssl/core_names.h> #endif #endif -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN #include <openvpn/win/console.hpp> #include <shellapi.h> #endif @@ -87,14 +83,14 @@ #include "client/core-client-netcfg.hpp" #endif -#if defined(OPENVPN_PLATFORM_LINUX) +#ifdef OPENVPN_PLATFORM_LINUX #include <openvpn/tun/linux/client/tuncli.hpp> // we use a static polymorphism and define a // platform-specific TunSetup class, responsible // for setting up tun device -#define TUN_CLASS_SETUP TunLinuxSetup::Setup<TUN_LINUX> +#define TUN_CLASS_SETUP TunLinuxSetup::Setup<TunNetlink::TunMethods> #include <openvpn/tun/linux/client/tuncli.hpp> #elif defined(OPENVPN_PLATFORM_MAC) #include <openvpn/tun/mac/client/tuncli.hpp> @@ -198,7 +194,7 @@ class ClientBase : public ClientAPI::OpenVPNClient public: bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, bool ipv6) override { - std::cout << "NOT IMPLEMENTED: *** socket_protect " << socket << " " << remote << std::endl; + std::cout << "NOT IMPLEMENTED: *** socket_protect " << socket << " " << remote << "\n"; return true; } }; @@ -232,7 +228,7 @@ class Client : public ClientBase std::string epki_ca; std::string epki_cert; -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS MbedTLSPKI::PKContext epki_ctx; // external PKI context MbedTLSPKI::PKContext certcheck_pkey; // external PKI context #elif defined(USE_OPENSSL) @@ -253,12 +249,12 @@ class Client : public ClientBase const int n = stats_n(); std::vector<long long> stats = stats_bundle(); - std::cout << "STATS:" << std::endl; + std::cout << "STATS:\n"; for (int i = 0; i < n; ++i) { const long long value = stats[i]; if (value) - std::cout << " " << stats_name(i) << " : " << value << std::endl; + std::cout << " " << stats_name(i) << " : " << value << "\n"; } } @@ -285,7 +281,7 @@ class Client : public ClientBase std::cout << " [FATAL-ERR]"; else if (ev.error) std::cout << " [ERR]"; - std::cout << std::endl; + std::cout << "\n"; if (ev.name == "DYNAMIC_CHALLENGE") { dc_cookie = ev.info; @@ -293,24 +289,24 @@ class Client : public ClientBase ClientAPI::DynamicChallenge dc; if (ClientAPI::OpenVPNClientHelper::parse_dynamic_challenge(ev.info, dc)) { - std::cout << "DYNAMIC CHALLENGE" << std::endl; - std::cout << "challenge: " << dc.challenge << std::endl; - std::cout << "echo: " << dc.echo << std::endl; - std::cout << "responseRequired: " << dc.responseRequired << std::endl; - std::cout << "stateID: " << dc.stateID << std::endl; + std::cout << "DYNAMIC CHALLENGE\n"; + std::cout << "challenge: " << dc.challenge << "\n"; + std::cout << "echo: " << dc.echo << "\n"; + std::cout << "responseRequired: " << dc.responseRequired << "\n"; + std::cout << "stateID: " << dc.stateID << "\n"; } } else if (ev.name == "PROXY_NEED_CREDS") { - std::cout << "PROXY_NEED_CREDS " << ev.info << std::endl; + std::cout << "PROXY_NEED_CREDS " << ev.info << "\n"; } else if (ev.name == "INFO") { - if (string::starts_with(ev.info, "OPEN_URL:")) + if (ev.info.starts_with("OPEN_URL:")) { open_url(ev.info.substr(9)); } - else if (string::starts_with(ev.info, "WEB_AUTH:")) + else if (ev.info.starts_with("WEB_AUTH:")) { auto extra = ev.info.substr(9); size_t flagsend = extra.find(':'); @@ -319,7 +315,7 @@ class Client : public ClientBase open_url(extra.substr(flagsend + 1)); } } - else if (string::starts_with(ev.info, "CR_TEXT:")) + else if (ev.info.starts_with("CR_TEXT:")) { std::string cr_response; std::cout << "\n\n" @@ -329,23 +325,25 @@ class Client : public ClientBase } else { - std::cout << "Unrecognized INFO/INFO_PRE message: " << ev.info << std::endl; + std::cout << "Unrecognized INFO/INFO_PRE message: " << ev.info << "\n"; } } else { - std::cout << "Received event " << ev.name << " " << ev.info << std::endl; + std::cout << "Received event " << ev.name << " " << ev.info << "\n"; } + // We want to log events in near real-time + std::cout << std::flush; } void handle_dpc1_protocol(const ClientAPI::AppCustomControlMessageEvent &acev) { - if (string::starts_with(acev.payload, "{\"dpc_request\"") && acev.payload.find("certificate") != std::string::npos) + if (acev.payload.starts_with("{\"dpc_request\"") && acev.payload.find("certificate") != std::string::npos) { - std::cout << "ACC CERTCHECK challenge initiated" << std::endl; + std::cout << "ACC CERTCHECK challenge initiated\n"; handle_certcheck_request(); } - else if (string::starts_with(acev.payload, "{\"dpc_request\"") && acev.payload.find("client_info") != std::string::npos) + else if (acev.payload.starts_with("{\"dpc_request\"") && acev.payload.find("client_info") != std::string::npos) { std::string fakeResponse{R"({"dpc_response": { @@ -354,17 +352,19 @@ class Client : public ClientBase } }})"}; - std::cout << "ACC DPC1: sending fake client info:" << fakeResponse << std::endl; + std::cout << "ACC DPC1: sending fake client info:" << fakeResponse << "\n"; send_app_control_channel_msg("dpc1", fakeResponse); } - else if (string::starts_with(acev.payload, "{\"dpc_request\"")) + else if (acev.payload.starts_with("{\"dpc_request\"")) { - std::cout << "Cannot parse dpc request message:" << acev.payload << std::endl; + std::cout << "Cannot parse dpc request message:" << acev.payload << "\n"; } else { - std::cout << "Cannot parse device posture message:" << acev.payload << std::endl; + std::cout << "Cannot parse device posture message:" << acev.payload << "\n"; } + // We want to log events in near real-time + std::cout << std::flush; } /** @@ -375,7 +375,7 @@ class Client : public ClientBase { if (acev.protocol == "internal:supported_protocols") { - std::cout << "Client/server common app custom control protocols: " << acev.payload << std::endl; + std::cout << "Client/server common app custom control protocols: " << acev.payload << "\n"; } else if (acev.protocol == certcheck_init_verb) { @@ -384,8 +384,10 @@ class Client : public ClientBase else { std::cout << "received unhandled app custom control message for protocol " << acev.protocol - << " msg payload: " << acev.payload << std::endl; + << " msg payload: " << acev.payload << "\n"; } + // We want to log events in near real-time + std::cout << std::flush; } /** @@ -395,7 +397,7 @@ class Client : public ClientBase { if (certcheck_cert.empty() || !certcheck_pkey.defined()) { - std::cout << "ACC CERTCHECK FAILED: MISSING PARAMETERS" << std::endl; + std::cout << "ACC CERTCHECK FAILED: MISSING PARAMETERS\n"; return; } @@ -421,12 +423,13 @@ class Client : public ClientBase { start_cert_check_epki("certcheck", clientca_pem); } + // We want to log events in near real-time + std::cout << std::flush; } - void open_url(std::string url_str) + void open_url(const std::string &url_str) { - if (string::starts_with(url_str, "http://") - || string::starts_with(url_str, "https://")) + if (url_str.starts_with("http://") || url_str.starts_with("https://")) { if (!write_url_fn.empty()) { @@ -434,7 +437,7 @@ class Client : public ClientBase return; } #ifdef OPENVPN_PLATFORM_MAC - std::cout << "Trying to launch " << url_str << std::endl; + std::cout << "Trying to launch " << url_str << "\n"; std::thread thr([url_str]() { CFURLRef url = CFURLCreateWithBytes( @@ -459,7 +462,7 @@ class Client : public ClientBase argv.emplace_back(url_str); system_cmd(argv); #else - std::cout << "No implementation to launch " << url_str << std::endl; + std::cout << "No implementation to launch " << url_str << "\n"; #endif } } @@ -478,23 +481,23 @@ class Client : public ClientBase switch (action) { case CT_STOP: - std::cout << "signal: CT_STOP" << std::endl; + std::cout << "signal: CT_STOP\n"; stop(); break; case CT_RECONNECT: - std::cout << "signal: CT_RECONNECT" << std::endl; + std::cout << "signal: CT_RECONNECT\n"; reconnect(0); break; case CT_PAUSE: - std::cout << "signal: CT_PAUSE" << std::endl; + std::cout << "signal: CT_PAUSE\n"; pause("clock-tick pause"); break; case CT_RESUME: - std::cout << "signal: CT_RESUME" << std::endl; + std::cout << "signal: CT_RESUME\n"; resume(); break; case CT_STATS: - std::cout << "signal: CT_STATS" << std::endl; + std::cout << "signal: CT_STATS\n"; print_stats(); break; default: @@ -577,7 +580,7 @@ class Client : public ClientBase OPENVPN_LOG("SIGNATURE[" << outlen << "]: " << signreq.sig); } -#if (OPENSSL_VERSION_NUMBER < 0x30000000L) +#if OPENSSL_VERSION_NUMBER < 0x30000000L void doOpenSSLDigestSignature(ClientAPI::ExternalPKISignRequest &signreq) { /* technically implementing this without OpenSSL 3.0 is possible but @@ -681,7 +684,7 @@ class Client : public ClientBase void external_pki_sign_request(ClientAPI::ExternalPKISignRequest &signreq) override { -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS if (epki_ctx.defined()) { try @@ -821,47 +824,45 @@ static Client *the_client = nullptr; // GLOBAL static void worker_thread() { -#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD) +#ifndef OPENVPN_OVPNCLI_SINGLE_THREAD openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread #endif try { - std::cout << "Thread starting..." << std::endl; + std::cout << "Thread starting...\n"; ClientAPI::Status connect_status = the_client->connect(); if (connect_status.error) { std::cout << "connect error: "; if (!connect_status.status.empty()) - std::cout << connect_status.status << ": " << std::endl; - std::cout << connect_status.message << std::endl; + std::cout << connect_status.status << ": \n"; + std::cout << connect_status.message << "\n"; } } catch (const std::exception &e) { - std::cout << "Connect thread exception: " << e.what() << std::endl; + std::cout << "Connect thread exception: " << e.what() << "\n"; } - std::cout << "Thread finished" << std::endl; + std::cout << "Thread finished\n"; } static std::string read_profile(const char *fn, const std::string *profile_content) { if (!string::strcasecmp(fn, "http") && profile_content && !profile_content->empty()) return *profile_content; - else - { - ProfileMerge pm(fn, - "ovpn", - "", - ProfileMerge::FOLLOW_FULL, - ProfileParseLimits::MAX_LINE_SIZE, - ProfileParseLimits::MAX_PROFILE_SIZE); - if (pm.status() != ProfileMerge::MERGE_SUCCESS) - OPENVPN_THROW_EXCEPTION("merge config error: " << pm.status_string() << " : " << pm.error()); - return pm.profile_content(); - } + + ProfileMerge pm(fn, + "ovpn", + "", + ProfileMerge::FOLLOW_FULL, + ProfileParseLimits::MAX_LINE_SIZE, + ProfileParseLimits::MAX_PROFILE_SIZE); + if (pm.status() != ProfileMerge::MERGE_SUCCESS) + OPENVPN_THROW_EXCEPTION("merge config error: " << pm.status_string() << " : " << pm.error()); + return pm.profile_content(); } -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN static void start_thread(Client &client) { @@ -964,12 +965,12 @@ static void handler(int signum) { case SIGTERM: case SIGINT: - std::cout << "received stop signal " << signum << std::endl; + std::cout << "received stop signal " << signum << "\n"; if (the_client) the_client->stop(); break; case SIGHUP: - std::cout << "received reconnect signal " << signum << std::endl; + std::cout << "received reconnect signal " << signum << "\n"; if (the_client) the_client->reconnect(0); break; @@ -981,7 +982,7 @@ static void handler(int signum) { // toggle pause/resume static bool hup = false; - std::cout << "received pause/resume toggle signal " << signum << std::endl; + std::cout << "received pause/resume toggle signal " << signum << "\n"; if (the_client) { if (hup) @@ -993,7 +994,7 @@ static void handler(int signum) } break; default: - std::cout << "received unknown signal " << signum << std::endl; + std::cout << "received unknown signal " << signum << "\n"; break; } } @@ -1021,66 +1022,66 @@ static void start_thread(Client &client) int openvpn_client(int argc, char *argv[], const std::string *profile_content) { + // clang-format off static const struct option longopts[] = { - // clang-format off - { "username", required_argument, nullptr, 'u' }, - { "password", required_argument, nullptr, 'p' }, - { "response", required_argument, nullptr, 'r' }, - { "dc", required_argument, nullptr, 'D' }, - { "proto", required_argument, nullptr, 'P' }, - { "ipv6", required_argument, nullptr, '6' }, - { "server", required_argument, nullptr, 's' }, - { "port", required_argument, nullptr, 'R' }, - { "timeout", required_argument, nullptr, 't' }, - { "compress", required_argument, nullptr, 'c' }, - { "pk-password", required_argument, nullptr, 'z' }, - { "tvm-override", required_argument, nullptr, 'M' }, - { "proxy-host", required_argument, nullptr, 'h' }, - { "proxy-port", required_argument, nullptr, 'q' }, - { "proxy-username", required_argument, nullptr, 'U' }, - { "proxy-password", required_argument, nullptr, 'W' }, - { "peer-info", required_argument, nullptr, 'I' }, - { "acc-protos", required_argument, nullptr, 'K' }, - { "gremlin", required_argument, nullptr, 'G' }, - { "proxy-basic", no_argument, nullptr, 'B' }, - { "alt-proxy", no_argument, nullptr, 'A' }, + {.name = "username", .has_arg = required_argument, .flag = nullptr, .val = 'u'}, + {.name = "password", .has_arg = required_argument, .flag = nullptr, .val = 'p'}, + {.name = "response", .has_arg = required_argument, .flag = nullptr, .val = 'r'}, + {.name = "dc", .has_arg = required_argument, .flag = nullptr, .val = 'D'}, + {.name = "proto", .has_arg = required_argument, .flag = nullptr, .val = 'P'}, + {.name = "ipv6", .has_arg = required_argument, .flag = nullptr, .val = '6'}, + {.name = "server", .has_arg = required_argument, .flag = nullptr, .val = 's'}, + {.name = "port", .has_arg = required_argument, .flag = nullptr, .val = 'R'}, + {.name = "timeout", .has_arg = required_argument, .flag = nullptr, .val = 't'}, + {.name = "compress", .has_arg = required_argument, .flag = nullptr, .val = 'c'}, + {.name = "pk-password", .has_arg = required_argument, .flag = nullptr, .val = 'z'}, + {.name = "tvm-override", .has_arg = required_argument, .flag = nullptr, .val = 'M'}, + {.name = "proxy-host", .has_arg = required_argument, .flag = nullptr, .val = 'h'}, + {.name = "proxy-port", .has_arg = required_argument, .flag = nullptr, .val = 'q'}, + {.name = "proxy-username", .has_arg = required_argument, .flag = nullptr, .val = 'U'}, + {.name = "proxy-password", .has_arg = required_argument, .flag = nullptr, .val = 'W'}, + {.name = "peer-info", .has_arg = required_argument, .flag = nullptr, .val = 'I'}, + {.name = "acc-protos", .has_arg = required_argument, .flag = nullptr, .val = 'K'}, + {.name = "gremlin", .has_arg = required_argument, .flag = nullptr, .val = 'G'}, + {.name = "proxy-basic", .has_arg = no_argument, .flag = nullptr, .val = 'B'}, + {.name = "alt-proxy", .has_arg = no_argument, .flag = nullptr, .val = 'A'}, #if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN) - { "no-dco", no_argument, nullptr, 'd' }, + {.name = "no-dco", .has_arg = no_argument, .flag = nullptr, .val = 'd'}, #endif - { "eval", no_argument, nullptr, 'e' }, - { "self-test", no_argument, nullptr, 'T' }, - { "cache-password", no_argument, nullptr, 'C' }, - { "no-cert", no_argument, nullptr, 'x' }, - { "force-aes-cbc", no_argument, nullptr, 'f' }, - { "google-dns", no_argument, nullptr, 'g' }, - { "persist-tun", no_argument, nullptr, 'j' }, - { "wintun", no_argument, nullptr, 'w' }, - { "allow-local-dns-resolvers", no_argument, nullptr, 'l' }, - { "def-keydir", required_argument, nullptr, 'k' }, - { "merge", no_argument, nullptr, 'm' }, - { "version", no_argument, nullptr, 'v' }, - { "auto-sess", no_argument, nullptr, 'a' }, - { "auth-retry", no_argument, nullptr, 'Y' }, - { "tcprof-override", required_argument, nullptr, 'X' }, - { "write-url", required_argument, nullptr, 'Z' }, - { "sso-methods", required_argument, nullptr, 'S' }, - { "ssl-debug", required_argument, nullptr, 1 }, - { "epki-cert", required_argument, nullptr, 2 }, - { "epki-ca", required_argument, nullptr, 3 }, - { "epki-key", required_argument, nullptr, 4 }, - { "legacy-algorithms", no_argument, nullptr, 'L' }, - { "non-preferred-algorithms", no_argument, nullptr, 'Q' }, + {.name = "eval", .has_arg = no_argument, .flag = nullptr, .val = 'e'}, + {.name = "self-test", .has_arg = no_argument, .flag = nullptr, .val = 'T'}, + {.name = "cache-password", .has_arg = no_argument, .flag = nullptr, .val = 'C'}, + {.name = "no-cert", .has_arg = no_argument, .flag = nullptr, .val = 'x'}, + {.name = "force-aes-cbc", .has_arg = no_argument, .flag = nullptr, .val = 'f'}, + {.name = "google-dns", .has_arg = no_argument, .flag = nullptr, .val = 'g'}, + {.name = "persist-tun", .has_arg = no_argument, .flag = nullptr, .val = 'j'}, + {.name = "wintun", .has_arg = no_argument, .flag = nullptr, .val = 'w'}, + {.name = "allow-local-dns-resolvers", .has_arg = no_argument, .flag = nullptr, .val = 'l'}, + {.name = "def-keydir", .has_arg = required_argument, .flag = nullptr, .val = 'k'}, + {.name = "merge", .has_arg = no_argument, .flag = nullptr, .val = 'm'}, + {.name = "version", .has_arg = no_argument, .flag = nullptr, .val = 'v'}, + {.name = "auto-sess", .has_arg = no_argument, .flag = nullptr, .val = 'a'}, + {.name = "auth-retry", .has_arg = no_argument, .flag = nullptr, .val = 'Y'}, + {.name = "tcprof-override", .has_arg = required_argument, .flag = nullptr, .val = 'X'}, + {.name = "write-url", .has_arg = required_argument, .flag = nullptr, .val = 'Z'}, + {.name = "sso-methods", .has_arg = required_argument, .flag = nullptr, .val = 'S'}, + {.name = "ssl-debug", .has_arg = required_argument, .flag = nullptr, .val = 1 }, + {.name = "epki-cert", .has_arg = required_argument, .flag = nullptr, .val = 2 }, + {.name = "epki-ca", .has_arg = required_argument, .flag = nullptr, .val = 3 }, + {.name = "epki-key", .has_arg = required_argument, .flag = nullptr, .val = 4 }, + {.name = "legacy-algorithms", .has_arg = no_argument, .flag = nullptr, .val = 'L'}, + {.name = "non-preferred-algorithms", .has_arg = no_argument, .flag = nullptr, .val = 'Q'}, #ifdef OPENVPN_REMOTE_OVERRIDE - { "remote-override",required_argument, nullptr, 5 }, + {.name = "remote-override", .has_arg = required_argument, .flag = nullptr, .val = 5 }, #endif - { "tbc", no_argument, nullptr, 6 }, - { "app-custom-protocols", required_argument, nullptr, 'K' }, - { "certcheck-cert", required_argument, nullptr, 'o' }, - { "certcheck-pkey", required_argument, nullptr, 'O' }, - { "certcheck-clientca", required_argument, nullptr, 'b' }, - { nullptr, 0, nullptr, 0 } - // clang-format on + {.name = "tbc", .has_arg = no_argument, .flag = nullptr, .val = 6 }, + {.name = "app-custom-protocols", .has_arg = required_argument, .flag = nullptr, .val = 'K'}, + {.name = "certcheck-cert", .has_arg = required_argument, .flag = nullptr, .val = 'o'}, + {.name = "certcheck-pkey", .has_arg = required_argument, .flag = nullptr, .val = 'O'}, + {.name = "certcheck-clientca", .has_arg = required_argument, .flag = nullptr, .val = 'b'}, + {.name = nullptr, .has_arg = 0, .flag = nullptr, .val = 0 } }; + // clang-format on int ret = 0; auto cleanup = Cleanup([]() @@ -1318,9 +1319,9 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) if (version) { - std::cout << "OpenVPN cli 1.0" << std::endl; - std::cout << ClientAPI::OpenVPNClientHelper::platform() << std::endl; - std::cout << ClientAPI::OpenVPNClientHelper::copyright() << std::endl; + std::cout << "OpenVPN cli 1.0\n"; + std::cout << ClientAPI::OpenVPNClientHelper::platform() << "\n"; + std::cout << ClientAPI::OpenVPNClientHelper::copyright() << "\n"; } else if (self_test) { @@ -1345,7 +1346,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) ClientAPI::Config config; config.guiVersion = "cli 1.0"; -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN int nargs = 0; auto argvw = CommandLineToArgvW(GetCommandLineW(), &nargs); UTF8 utf8(Win::utf8(argvw[nargs - 1])); @@ -1390,7 +1391,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) config.enableNonPreferredDCAlgorithms = enableNonPreferredDCO; config.ssoMethods = ssoMethods; config.appCustomProtocols = appCustomProtocols; -#if defined(OPENVPN_OVPNCLI_SINGLE_THREAD) +#ifdef OPENVPN_OVPNCLI_SINGLE_THREAD config.clockTickMS = 250; #endif @@ -1420,31 +1421,31 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) { ClientAPI::OpenVPNClientHelper clihelper; const ClientAPI::EvalConfig cfg_eval = clihelper.eval_config(config); - std::cout << "EVAL PROFILE" << std::endl; - std::cout << "error=" << cfg_eval.error << std::endl; - std::cout << "message=" << cfg_eval.message << std::endl; - std::cout << "userlockedUsername=" << cfg_eval.userlockedUsername << std::endl; - std::cout << "profileName=" << cfg_eval.profileName << std::endl; - std::cout << "friendlyName=" << cfg_eval.friendlyName << std::endl; - std::cout << "autologin=" << cfg_eval.autologin << std::endl; - std::cout << "externalPki=" << cfg_eval.externalPki << std::endl; - std::cout << "staticChallenge=" << cfg_eval.staticChallenge << std::endl; - std::cout << "staticChallengeEcho=" << cfg_eval.staticChallengeEcho << std::endl; - std::cout << "privateKeyPasswordRequired=" << cfg_eval.privateKeyPasswordRequired << std::endl; - std::cout << "allowPasswordSave=" << cfg_eval.allowPasswordSave << std::endl; + std::cout << "EVAL PROFILE\n"; + std::cout << "error=" << cfg_eval.error << "\n"; + std::cout << "message=" << cfg_eval.message << "\n"; + std::cout << "userlockedUsername=" << cfg_eval.userlockedUsername << "\n"; + std::cout << "profileName=" << cfg_eval.profileName << "\n"; + std::cout << "friendlyName=" << cfg_eval.friendlyName << "\n"; + std::cout << "autologin=" << cfg_eval.autologin << "\n"; + std::cout << "externalPki=" << cfg_eval.externalPki << "\n"; + std::cout << "staticChallenge=" << cfg_eval.staticChallenge << "\n"; + std::cout << "staticChallengeEcho=" << cfg_eval.staticChallengeEcho << "\n"; + std::cout << "privateKeyPasswordRequired=" << cfg_eval.privateKeyPasswordRequired << "\n"; + std::cout << "allowPasswordSave=" << cfg_eval.allowPasswordSave << "\n"; if (!config.serverOverride.empty()) - std::cout << "server=" << config.serverOverride << std::endl; + std::cout << "server=" << config.serverOverride << "\n"; for (size_t i = 0; i < cfg_eval.serverList.size(); ++i) { const ClientAPI::ServerEntry &se = cfg_eval.serverList[i]; - std::cout << '[' << i << "] " << se.server << '/' << se.friendlyName << std::endl; + std::cout << '[' << i << "] " << se.server << '/' << se.friendlyName << "\n"; } } else { -#if defined(USE_NETCFG) +#ifdef USE_NETCFG auto dbus_system = DBus::Connection::Create(DBus::BusType::SYSTEM); NetCfgTunBuilder<Client> client(dbus_system); #else @@ -1456,7 +1457,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) if (eval.autologin) { if (!username.empty() || !password.empty()) - std::cout << "NOTE: creds were not needed" << std::endl; + std::cout << "NOTE: creds were not needed\n"; // still provide proxy credentials if given if (!proxyUsername.empty()) @@ -1499,7 +1500,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) if (!epki_key_fn.empty()) { const std::string epki_key_txt = read_text_utf8(epki_key_fn); -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS auto mbedrng = std::make_unique<MbedTLSRandom>(); client.epki_ctx.parse(epki_key_txt, "EPKI", privateKeyPassword, *mbedrng); @@ -1531,7 +1532,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) client.set_write_url_fn(write_url_fn); - std::cout << "CONNECTING..." << std::endl; + std::cout << "CONNECTING...\n"; // start the client thread start_thread(client); @@ -1539,7 +1540,7 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) // Get dynamic challenge response if (client.is_dynamic_challenge()) { - std::cout << "ENTER RESPONSE" << std::endl; + std::cout << "ENTER RESPONSE\n"; std::getline(std::cin, response); if (!response.empty()) { @@ -1570,65 +1571,65 @@ int openvpn_client(int argc, char *argv[], const std::string *profile_content) } catch (const usage &) { - std::cout << "OpenVPN Client (ovpncli)" << std::endl; - std::cout << "usage: cli [options] <config-file> [extra-config-directives...]" << std::endl; - std::cout << "--version, -v : show version info" << std::endl; - std::cout << "--eval, -e : evaluate profile only (standalone)" << std::endl; - std::cout << "--merge, -m : merge profile into unified format (standalone)" << std::endl; - std::cout << "--username, -u : username" << std::endl; - std::cout << "--password, -p : password" << std::endl; - std::cout << "--response, -r : static response" << std::endl; - std::cout << "--dc, -D : dynamic challenge/response cookie" << std::endl; - std::cout << "--proto, -P : protocol override (udp|tcp)" << std::endl; - std::cout << "--server, -s : server override" << std::endl; - std::cout << "--port, -R : port override" << std::endl; + std::cout << "OpenVPN Client (ovpncli)\n"; + std::cout << "usage: cli [options] <config-file> [extra-config-directives...]\n"; + std::cout << "--version, -v : show version info\n"; + std::cout << "--eval, -e : evaluate profile only (standalone)\n"; + std::cout << "--merge, -m : merge profile into unified format (standalone)\n"; + std::cout << "--username, -u : username\n"; + std::cout << "--password, -p : password\n"; + std::cout << "--response, -r : static response\n"; + std::cout << "--dc, -D : dynamic challenge/response cookie\n"; + std::cout << "--proto, -P : protocol override (udp|tcp)\n"; + std::cout << "--server, -s : server override\n"; + std::cout << "--port, -R : port override\n"; #ifdef OPENVPN_REMOTE_OVERRIDE - std::cout << "--remote-override : command to run to generate next remote (returning host,ip,port,proto)" << std::endl; + std::cout << "--remote-override : command to run to generate next remote (returning host,ip,port,proto)\n"; #endif - std::cout << "--allowAF, -6 : Allow unused address families (yes|no|default)" << std::endl; - std::cout << "--timeout, -t : timeout" << std::endl; - std::cout << "--compress, -c : compression mode (yes|no|asym)" << std::endl; - std::cout << "--pk-password, -z : private key password" << std::endl; - std::cout << "--tvm-override, -M : tls-version-min override (disabled, default, tls_1_x)" << std::endl; - std::cout << "--legacy-algorithms, -L: Enable legacy algorithm (OpenSSL legacy provider)" << std::endl; - std::cout << "--non-preferred-algorithms, -Q: Enables non preferred data channel algorithms" << std::endl; + std::cout << "--allowAF, -6 : Allow unused address families (yes|no|default)\n"; + std::cout << "--timeout, -t : timeout\n"; + std::cout << "--compress, -c : compression mode (yes|no|asym)\n"; + std::cout << "--pk-password, -z : private key password\n"; + std::cout << "--tvm-override, -M : tls-version-min override (disabled, default, tls_1_x)\n"; + std::cout << "--legacy-algorithms, -L: Enable legacy algorithm (OpenSSL legacy provider)\n"; + std::cout << "--non-preferred-algorithms, -Q: Enables non preferred data channel algorithms\n"; std::cout << "--tcprof-override, -X : tls-cert-profile override (" << #ifdef OPENVPN_ALLOW_INSECURE_CERTPROFILE "insecure, " << #endif - "legacy, preferred, etc.)" << std::endl; - std::cout << "--proxy-host, -h : HTTP proxy hostname/IP" << std::endl; - std::cout << "--proxy-port, -q : HTTP proxy port" << std::endl; - std::cout << "--proxy-username, -U : HTTP proxy username" << std::endl; - std::cout << "--proxy-password, -W : HTTP proxy password" << std::endl; - std::cout << "--proxy-basic, -B : allow HTTP basic auth" << std::endl; - std::cout << "--alt-proxy, -A : enable alternative proxy module" << std::endl; + "legacy, preferred, etc.)\n"; + std::cout << "--proxy-host, -h : HTTP proxy hostname/IP\n"; + std::cout << "--proxy-port, -q : HTTP proxy port\n"; + std::cout << "--proxy-username, -U : HTTP proxy username\n"; + std::cout << "--proxy-password, -W : HTTP proxy password\n"; + std::cout << "--proxy-basic, -B : allow HTTP basic auth\n"; + std::cout << "--alt-proxy, -A : enable alternative proxy module\n"; #if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) || defined(ENABLE_OVPNDCOWIN) - std::cout << "--no-dco, -d : disable data channel offload" << std::endl; + std::cout << "--no-dco, -d : disable data channel offload\n"; #endif - std::cout << "--cache-password, -C : cache password" << std::endl; - std::cout << "--no-cert, -x : disable client certificate" << std::endl; - std::cout << "--def-keydir, -k : default key direction ('bi', '0', or '1')" << std::endl; - std::cout << "--ssl-debug : SSL debug level" << std::endl; - std::cout << "--google-dns, -g : enable Google DNS fallback" << std::endl; - std::cout << "--auto-sess, -a : request autologin session" << std::endl; - std::cout << "--auth-retry, -Y : retry connection on auth failure" << std::endl; - std::cout << "--persist-tun, -j : keep TUN interface open across reconnects" << std::endl; - std::cout << "--wintun, -w : use WinTun instead of TAP-Windows6 on Windows" << std::endl; - std::cout << "--peer-info, -I : peer info key/value list in the form K1=V1,K2=V2,... or @kv.json" << std::endl; - std::cout << "--gremlin, -G : gremlin info (send_delay_ms, recv_delay_ms, send_drop_prob, recv_drop_prob)" << std::endl; - std::cout << "--epki-ca : simulate external PKI cert supporting intermediate/root certs" << std::endl; - std::cout << "--epki-cert : simulate external PKI cert" << std::endl; - std::cout << "--epki-key : simulate external PKI private key" << std::endl; - std::cout << "--sso-methods : auth pending methods to announce via IV_SSO" << std::endl; - std::cout << "--write-url, -Z : write INFO URL to file" << std::endl; - std::cout << "--tbc : generate INFO_JSON/TUN_BUILDER_CAPTURE event" << std::endl; - std::cout << "--app-custom-protocols, -K : ACC protocols to advertise" << std::endl; - std::cout << "--certcheck-cert, -o : path to certificate PEM for certcheck" << std::endl; - std::cout << "--certcheck-pkey, -O : path to decrypted pkey PEM for certcheck" << std::endl; - std::cout << "--certcheck-clientca, -b : path to decrypted pkey PEM for certcheck CA" << std::endl; + std::cout << "--cache-password, -C : cache password\n"; + std::cout << "--no-cert, -x : disable client certificate\n"; + std::cout << "--def-keydir, -k : default key direction ('bi', '0', or '1')\n"; + std::cout << "--ssl-debug : SSL debug level\n"; + std::cout << "--google-dns, -g : enable Google DNS fallback\n"; + std::cout << "--auto-sess, -a : request autologin session\n"; + std::cout << "--auth-retry, -Y : retry connection on auth failure\n"; + std::cout << "--persist-tun, -j : keep TUN interface open across reconnects\n"; + std::cout << "--wintun, -w : use WinTun instead of TAP-Windows6 on Windows\n"; + std::cout << "--peer-info, -I : peer info key/value list in the form K1=V1,K2=V2,... or @kv.json\n"; + std::cout << "--gremlin, -G : gremlin info (send_delay_ms, recv_delay_ms, send_drop_prob, recv_drop_prob)\n"; + std::cout << "--epki-ca : simulate external PKI cert supporting intermediate/root certs\n"; + std::cout << "--epki-cert : simulate external PKI cert\n"; + std::cout << "--epki-key : simulate external PKI private key\n"; + std::cout << "--sso-methods : auth pending methods to announce via IV_SSO\n"; + std::cout << "--write-url, -Z : write INFO URL to file\n"; + std::cout << "--tbc : generate INFO_JSON/TUN_BUILDER_CAPTURE event\n"; + std::cout << "--app-custom-protocols, -K : ACC protocols to advertise\n"; + std::cout << "--certcheck-cert, -o : path to certificate PEM for certcheck\n"; + std::cout << "--certcheck-pkey, -O : path to decrypted pkey PEM for certcheck\n"; + std::cout << "--certcheck-clientca, -b : path to decrypted pkey PEM for certcheck CA\n"; ret = 2; } return ret; @@ -1644,7 +1645,7 @@ int main(int argc, char *argv[]) LogBaseSimple log; #endif -#if defined(OPENVPN_PLATFORM_WIN) +#ifdef OPENVPN_PLATFORM_WIN SetConsoleOutputCP(CP_UTF8); #endif @@ -1654,7 +1655,7 @@ int main(int argc, char *argv[]) } catch (const std::exception &e) { - std::cout << "Main thread exception: " << e.what() << std::endl; + std::cout << "Main thread exception: " << e.what() << "\n"; ret = 1; } return ret; diff --git a/test/ovpncli/go b/test/ovpncli/go deleted file mode 100755 index f0f04b9d2..000000000 --- a/test/ovpncli/go +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# Options: -# OSSL=1 -- build using OpenSSL -# MTLS=1 -- build using mbedTLS -# PTPROXY=1 -- build using Private Tunnel proxy - -# Other options -GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN" -[ "$EER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DTEST_EER" -[ "$NULL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_FORCE_TUN_NULL" -[ "$EXIT" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DTUN_NULL_EXIT" -[ "$GREMLIN" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_GREMLIN" -[ "$DEX" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_DISABLE_EXPLICIT_EXIT" -[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000" -[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE" -[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK" -[ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL" -[ "$MDNC" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DMBEDTLS_DISABLE_NAME_CONSTRAINTS" -[ "$DAT" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_DISABLE_AUTH_TOKEN" -if [ "$AGENT" = "1" ]; then - GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT" -fi -GCC_EXTRA="$GCC_EXTRA -DOPENVPN_VERSION=\"$($(dirname $0)/../../scripts/version)\"" -export GCC_EXTRA - -export EXTRA_CPP_OBJS=../../openvpn/crypto/data_epoch.cpp - -# determine platform -if [ "$(uname)" == "Darwin" ]; then - export PROF=${PROF:-osx64} -elif [ "$(uname)" == "Linux" ]; then - export PROF=${PROF:-linux} -else - echo this script only knows how to build on Mac OS or Linux -fi - -# use mbedTLS by default -[[ -z "$OSSL" && -z "$MTLS" ]] && export MTLS=1 - -# don't link with OpenSSL if mbedTLS is specified -if [ "$MTLS" = "1" ]; then - export OSSL=0 - export NOSSL=1 -fi - -# build -ASIO=1 LZ4=1 ../../scripts/build cli diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index f612dd72b..c7bf08548 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -33,6 +33,8 @@ add_executable(coreUnitTests test_acc.cpp test_alignment.cpp test_acc_certcheck.cpp + test_addrlist.cpp + test_addrpair.cpp test_route_emulation.cpp test_log.cpp test_comp.cpp @@ -47,6 +49,7 @@ add_executable(coreUnitTests test_clamp_typerange.cpp test_pktstream.cpp test_remotelist.cpp + test_optional_ref.cpp test_relack.cpp test_http_proxy.cpp test_peer_fingerprint.cpp @@ -69,6 +72,7 @@ add_executable(coreUnitTests test_pktid_data.cpp test_prefixlen.cpp test_randapi.cpp + test_intrinsic_type.cpp test_rc.cpp test_route.cpp test_reliable.cpp @@ -84,6 +88,7 @@ add_executable(coreUnitTests test_validatecreds.cpp test_weak.cpp test_cliopt.cpp + test_string.cpp test_buffer.cpp test_proto.cpp ) @@ -120,7 +125,7 @@ else () endif () if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - target_link_libraries(coreUnitTests cap) + add_libcap(coreUnitTests) target_sources(coreUnitTests PRIVATE test_sitnl.cpp) endif () diff --git a/test/unittests/core_tests.cpp b/test/unittests/core_tests.cpp index 6d677d278..f94877a97 100644 --- a/test/unittests/core_tests.cpp +++ b/test/unittests/core_tests.cpp @@ -28,7 +28,7 @@ int main(int argc, char **argv) { testLog = new openvpn::LogOutputCollector(); ::testing::InitGoogleTest(&argc, argv); - openvpn::InitProcess::Init init; + const openvpn::InitProcess::Init init; auto ret = RUN_ALL_TESTS(); delete testLog; diff --git a/test/unittests/test_acc.cpp b/test/unittests/test_acc.cpp index 5592087c7..63e77c577 100644 --- a/test/unittests/test_acc.cpp +++ b/test/unittests/test_acc.cpp @@ -35,7 +35,7 @@ static AppControlMessageConfig genACMC() return acmc; } -TEST(customcontrolchannel, msgroundtrip) +TEST(Customcontrolchannel, Msgroundtrip) { auto acmc = genACMC(); @@ -59,7 +59,7 @@ TEST(customcontrolchannel, msgroundtrip) ASSERT_EQ(recv_proto, "flower"); } -TEST(customcontrolchannel, msgroundtripascii) +TEST(Customcontrolchannel, Msgroundtripascii) { auto acmc = genACMC(); @@ -85,7 +85,7 @@ TEST(customcontrolchannel, msgroundtripascii) ASSERT_EQ(recv_proto, "flower"); } -TEST(customcontrolchannel, msgroundtriponepacket) +TEST(Customcontrolchannel, Msgroundtriponepacket) { auto acmc = genACMC(); @@ -106,9 +106,9 @@ TEST(customcontrolchannel, msgroundtriponepacket) ASSERT_EQ(recv_proto, "flower"); } -TEST(customcontrolchannel, tinymessage) +TEST(Customcontrolchannel, Tinymessage) { - std::string request{"I want a cookie!"}; + const std::string request{"I want a cookie!"}; auto acmc = genACMC(); acmc.supported_protocols.push_back("fortune"); auto cmsgs = acmc.format_message("fortune", request); @@ -117,7 +117,7 @@ TEST(customcontrolchannel, tinymessage) EXPECT_EQ(cmsgs.at(0), std::string("ACC,fortune,16,A,I want a cookie!")); } -TEST(customcontrolchannel, acctostr) +TEST(Customcontrolchannel, Acctostr) { auto acmc = genACMC(); @@ -125,9 +125,9 @@ TEST(customcontrolchannel, acctostr) EXPECT_EQ(desc, "protocols foo flower, msg_size 140, encoding ascii base64"); } -TEST(customcontrolchannel, recv_with_nul) +TEST(Customcontrolchannel, RecvWithNul) { - std::string control_msg{"ACC,fortune,64,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; + const std::string control_msg{"ACC,fortune,64,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; bool received = false; AppControlMessageReceiver accrecv{}; @@ -145,7 +145,7 @@ TEST(customcontrolchannel, recv_with_nul) ASSERT_EQ(recv_proto, "fortune"); } -TEST(customcontrolchannel, send_with_nul) +TEST(Customcontrolchannel, SendWithNul) { auto acmc = genACMC(); acmc.supported_protocols.push_back("fortune"); @@ -162,9 +162,9 @@ TEST(customcontrolchannel, send_with_nul) EXPECT_EQ(cmsgs[0], expected_control_msg); } -TEST(customcontrolchannel, test_incorrect_len) +TEST(Customcontrolchannel, TestIncorrectLen) { - std::string control_msg{"ACC,fortune,62,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; + const std::string control_msg{"ACC,fortune,62,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; AppControlMessageReceiver accrecv{}; @@ -173,9 +173,9 @@ TEST(customcontrolchannel, test_incorrect_len) parse_acc_message); } -TEST(customcontrolchannel, test_wrong_header) +TEST(Customcontrolchannel, TestWrongHeader) { - std::string control_msg{"ABC,fortune,64,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; + const std::string control_msg{"ABC,fortune,64,6,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; AppControlMessageReceiver accrecv{}; @@ -184,9 +184,9 @@ TEST(customcontrolchannel, test_wrong_header) parse_acc_message); } -TEST(customcontrolchannel, test_unsupported_encoding) +TEST(Customcontrolchannel, TestUnsupportedEncoding) { - std::string control_msg{"ACC,fortune,64,Q,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; + const std::string control_msg{"ACC,fortune,64,Q,InsgIm1lIjogImZyb2ciLCAAeGZm/SJtc2ciOiAiSSBhbSAAS2VybWl0IiB9Ig=="}; AppControlMessageReceiver accrecv{}; @@ -195,9 +195,9 @@ TEST(customcontrolchannel, test_unsupported_encoding) parse_acc_message); } -TEST(customcontrolchannel, test_missing_message) +TEST(Customcontrolchannel, TestMissingMessage) { - std::string control_msg{"ABC,fortune,64,6"}; + const std::string control_msg{"ABC,fortune,64,6"}; AppControlMessageReceiver accrecv{}; diff --git a/test/unittests/test_acc_certcheck.cpp b/test/unittests/test_acc_certcheck.cpp index 3266f2848..b13e06084 100644 --- a/test/unittests/test_acc_certcheck.cpp +++ b/test/unittests/test_acc_certcheck.cpp @@ -235,13 +235,13 @@ I/+4kAlXuAKdhsXohHeBhC2ijg/kTOMDxEbEVv+SkCIUyM+dB8UtlPKOH9HEL5Xi static constexpr int debug_output = 0; -static inline bool xfer_oneway(SslApiBuilder &sender, SslApiBuilder &recv, std::string out) +static inline bool xfer_oneway(SslApiBuilder &sender, SslApiBuilder &recv, const std::string &out) { if (sender.get().read_ciphertext_ready()) { - BufferPtr buf = sender.get().read_ciphertext(); + const BufferPtr buf = sender.get().read_ciphertext(); recv.get().write_ciphertext(buf); - std::cout << out << buf->size() << " bytes" << std::endl; + std::cout << out << buf->size() << " bytes\n"; return true; } @@ -250,9 +250,9 @@ static inline bool xfer_oneway(SslApiBuilder &sender, SslApiBuilder &recv, std:: /* this can also indicate an error */ uint8_t cleartext[1024]; - std::cout << out << " read ready?" << std::endl; + std::cout << out << " read ready?\n"; auto ctsize = sender.get().read_cleartext(cleartext, sizeof(cleartext)); - std::cout << ctsize << std::endl; + std::cout << ctsize << '\n'; EXPECT_FALSE(ctsize > 0); /* TODO: capture output for tests with data */ @@ -346,16 +346,16 @@ SSLLib::SSLAPI::Config::Ptr CreateClientConfig(const std::string &pvtKey, return config; } -TEST(AccCertCheckSsl, SslApiBuilder_ssl_handshake) +TEST(AccCertCheckSsl, SslApiBuilderSslHandshake) { auto server = SslApiBuilder(CreateServerConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); auto client = SslApiBuilder(CreateClientConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); server.get().start_handshake(); client.get().start_handshake(); @@ -370,16 +370,16 @@ TEST(AccCertCheckSsl, SslApiBuilder_ssl_handshake) } } -TEST(AccCertCheckSsl, AccHandshaker_ssl_handshake) +TEST(AccCertCheckSsl, AccHandshakerSslHandshake) { auto server = AccHandshaker(CreateServerConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); auto client = AccHandshaker(CreateClientConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); try { @@ -391,16 +391,16 @@ TEST(AccCertCheckSsl, AccHandshaker_ssl_handshake) } } -TEST(AccCertCheckSsl, AccHandshaker_ssl_handshake_no_cli_ca) +TEST(AccCertCheckSsl, AccHandshakerSslHandshakeNoCliCa) { auto server = AccHandshaker(CreateServerConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); auto client = AccHandshaker(CreateClientConfig(pvt_key_txt, cert_txt, "", - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); try { @@ -412,16 +412,16 @@ TEST(AccCertCheckSsl, AccHandshaker_ssl_handshake_no_cli_ca) } } -TEST(AccCertCheckSsl, AccHandshaker_ssl_handshake_fail) +TEST(AccCertCheckSsl, AccHandshakerSslHandshakeFail) { auto server = AccHandshaker(CreateServerConfig(fail_pvt_key_txt, fail_cert_txt, fail_cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); auto client = AccHandshaker(CreateClientConfig(pvt_key_txt, cert_txt, cert_txt, - new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0)))); + new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS)))); try { diff --git a/test/unittests/test_addrlist.cpp b/test/unittests/test_addrlist.cpp new file mode 100644 index 000000000..144b9f9d2 --- /dev/null +++ b/test/unittests/test_addrlist.cpp @@ -0,0 +1,62 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2024- OpenVPN Inc. +// +// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception +// + +#include "test_common.hpp" +#include "test_generators.hpp" + +#include <set> +#include <vector> + +#include <openvpn/addr/addrlist.hpp> + +RC_GTEST_PROP(AddrList, AddMarksAddressAsExisting, ()) +{ + openvpn::IP::AddrList address_list; + const auto address = *rc::genIPAddr(); + address_list.add(address); + RC_ASSERT(address_list.exists(address)); +} + +RC_GTEST_PROP(AddrList, AddIsIdempotent, ()) +{ + openvpn::IP::AddrList list; + const auto addr = *rc::genIPAddr(); + list.add(addr); + list.add(addr); + RC_ASSERT(list.size() == 1U); + RC_ASSERT(list[0] == addr); +} + +RC_GTEST_PROP(AddrList, AddDistinctAddressesKeepsUniqueCount, ()) +{ + const auto addrs = *rc::gen::container<std::vector<openvpn::IP::Addr>>(rc::genIPAddr()); + const std::set unique_addrs(addrs.begin(), addrs.end()); + openvpn::IP::AddrList list; + for (const auto &addr : addrs) + { + list.add(addr); + } + RC_ASSERT(list.size() == unique_addrs.size()); +} + +RC_GTEST_PROP(AddrList, ExistsMatchesMembership, ()) +{ + const auto addrs = *rc::gen::container<std::vector<openvpn::IP::Addr>>(rc::genIPAddr()); + const std::set unique_addrs(addrs.begin(), addrs.end()); + openvpn::IP::AddrList list; + for (const auto &addr : addrs) + { + list.add(addr); + } + const auto probe = *rc::gen::oneOf(rc::gen::elementOf(unique_addrs), rc::genIPAddr()); + const bool expected = unique_addrs.contains(probe); + RC_ASSERT(list.exists(probe) == expected); +} diff --git a/test/unittests/test_addrpair.cpp b/test/unittests/test_addrpair.cpp new file mode 100644 index 000000000..3c52d9224 --- /dev/null +++ b/test/unittests/test_addrpair.cpp @@ -0,0 +1,91 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2024- OpenVPN Inc. +// +// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception +// + +#include "test_common.hpp" +#include "test_generators.hpp" + +#include <openvpn/addr/addrpair.hpp> + +RC_GTEST_PROP(AddrMaskPairStringPair, SupportsConstruction, (const std::string &first, const std::string &second)) +{ + const openvpn::IP::AddrMaskPair::StringPair empty; + const openvpn::IP::AddrMaskPair::StringPair one(first); + const openvpn::IP::AddrMaskPair::StringPair two(first, second); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, SupportsSize, (const std::string &first, const std::string &second)) +{ + const openvpn::IP::AddrMaskPair::StringPair empty; + RC_ASSERT(empty.size() == 0U); + const openvpn::IP::AddrMaskPair::StringPair one(first); + RC_ASSERT(one.size() == 1U); + const openvpn::IP::AddrMaskPair::StringPair two(first, second); + RC_ASSERT(two.size() == 2U); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, SupportsPush, (const std::string &first, const std::string &second)) +{ + openvpn::IP::AddrMaskPair::StringPair empty; + empty.push_back(*rc::gen::string<std::string>()); + RC_ASSERT(empty.size() == 1U); + empty.push_back(*rc::gen::string<std::string>()); + RC_ASSERT(empty.size() == 2U); + + openvpn::IP::AddrMaskPair::StringPair one(first); + one.push_back(*rc::gen::string<std::string>()); + RC_ASSERT(one.size() == 2U); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, SupportsRendering, (const std::string &first, const std::string &second)) +{ + const openvpn::IP::AddrMaskPair::StringPair empty; + RC_ASSERT(empty.render() == ""); + + const openvpn::IP::AddrMaskPair::StringPair one(first); + RC_ASSERT(one.render() == first); + + const openvpn::IP::AddrMaskPair::StringPair two(first, second); + RC_ASSERT(two.render() == first + "/" + second); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, SupportsSubscriptAccessOperator, (const std::string &first, const std::string &second)) +{ + openvpn::IP::AddrMaskPair::StringPair empty; + RC_ASSERT(empty[0] == ""); + RC_ASSERT(empty[1] == ""); + + openvpn::IP::AddrMaskPair::StringPair one(first); + RC_ASSERT(one[0] == first); + RC_ASSERT(one[1] == ""); + + openvpn::IP::AddrMaskPair::StringPair two(first, second); + RC_ASSERT(two[0] == first); + RC_ASSERT(two[1] == second); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, PushingMoreThanPairThrows, (const std::string &first, const std::string &second)) +{ + openvpn::IP::AddrMaskPair::StringPair pushed; + pushed.push_back(first); + pushed.push_back(second); + RC_ASSERT_THROWS_AS(pushed.push_back(*rc::gen::string<std::string>()), openvpn::IP::AddrMaskPair::StringPair::addr_pair_string_error); +} + +RC_GTEST_PROP(AddrMaskPairStringPair, AccessingOutsidePairThrows, (const std::string &first, const std::string &second)) +{ + openvpn::IP::AddrMaskPair::StringPair non_const_pair(first, second); + const openvpn::IP::AddrMaskPair::StringPair const_pair(first, second); + const int index = *rc::gen::suchThat<int>([](const int i) + { return i < 0 || i > 2; }); + + RC_ASSERT_THROWS_AS(non_const_pair[index], openvpn::IP::AddrMaskPair::StringPair::addr_pair_string_error); + RC_ASSERT_THROWS_AS(const_pair[index], openvpn::IP::AddrMaskPair::StringPair::addr_pair_string_error); +} diff --git a/test/unittests/test_alignment.cpp b/test/unittests/test_alignment.cpp index 87eedf22d..143fdc9fc 100644 --- a/test/unittests/test_alignment.cpp +++ b/test/unittests/test_alignment.cpp @@ -25,7 +25,7 @@ TEST(AlignmentSafeExtractTest, ExtractIntFromMisalignedData) unsigned char data[32]; data[0] = 0xF0; memcpy(data + 1, &i, sizeof(i)); - int value = alignment_safe_extract<int>(data + 1); + const int value = alignment_safe_extract<int>(data + 1); EXPECT_EQ(value, i); } @@ -35,7 +35,7 @@ TEST(AlignmentSafeExtractTest, ExtractDoubleFromMisalignedData) unsigned char data[32]; data[0] = 0xF0; memcpy(data + 1, &d, sizeof(d)); - double value = alignment_safe_extract<double>(data + 1); + const double value = alignment_safe_extract<double>(data + 1); EXPECT_EQ(value, d); } @@ -44,13 +44,13 @@ TEST(AlignmentSafeExtractTest, ExtractStructFromMisalignedData) struct TestStruct { int a = 42; - float b = 98.6f; + float b = 98.6F; } test_struct; unsigned char data[32]; data[0] = 0xF0; memcpy(data + 1, &test_struct, sizeof(test_struct)); - TestStruct value = alignment_safe_extract<TestStruct>(data + 1); + const TestStruct value = alignment_safe_extract<TestStruct>(data + 1); EXPECT_EQ(value.a, test_struct.a); EXPECT_EQ(value.b, test_struct.b); } diff --git a/test/unittests/test_b64.cpp b/test/unittests/test_b64.cpp index eaa34dcff..653dca3b8 100644 --- a/test/unittests/test_b64.cpp +++ b/test/unittests/test_b64.cpp @@ -42,7 +42,7 @@ std::string ssllib_b64enc(const char *text, size_t textlen) BIO_write(bio, text, (int)textlen); EXPECT_TRUE(BIO_flush(bio) == 1); const char *encdata; - long len = BIO_get_mem_data(bio, &encdata); + const long len = BIO_get_mem_data(bio, &encdata); /* If there is nothing to encode OpenSSL gives back a nullptr */ if (len == 0) @@ -81,8 +81,8 @@ std::string ssllib_b64enc(const char *text, size_t textlen) void b64_test(const Base64 &b64, const std::string &text) { const std::string enc = b64.encode(text); - std::string dec = b64.decode(enc); - std::string libenc = ssllib_b64enc(text.c_str(), text.size()); + const std::string dec = b64.decode(enc); + const std::string libenc = ssllib_b64enc(text.c_str(), text.size()); EXPECT_EQ(text, dec) << "Encode/Decode results differ"; EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result"; @@ -92,9 +92,9 @@ void b64_test_binary(const Base64 &b64, const char *data, unsigned int len) { auto enc = b64.encode(data, len); - std::unique_ptr<char[]> decdata(new char[len]); - size_t decode_len = b64.decode(decdata.get(), len, enc); - std::string libenc = ssllib_b64enc(data, len); + const std::unique_ptr<char[]> decdata(new char[len]); + const size_t decode_len = b64.decode(decdata.get(), len, enc); + const std::string libenc = ssllib_b64enc(data, len); EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result"; @@ -104,7 +104,7 @@ void b64_test_binary(const Base64 &b64, const char *data, unsigned int len) << "Encode/Decode results differ"; } -TEST(Base64, tooshortdest) +TEST(Base64, Tooshortdest) { const Base64 b64; auto enc = b64.encode(std::string("abc")); @@ -119,7 +119,7 @@ void b64_test_bad_decode(const Base64 &b64, const std::string &text) EXPECT_THROW(b64.decode(dec, text), Base64::base64_decode_error); } -TEST(Base64, baddecode) +TEST(Base64, Baddecode) { const Base64 b64; @@ -132,7 +132,7 @@ TEST(Base64, baddecode) b64_test_bad_decode(b64, "01*="); } -TEST(Base64, encode) +TEST(Base64, Encode) { const Base64 b64; @@ -160,7 +160,7 @@ TEST(Base64, encode) b64_test(b64, "???x>>>>>>>>>?????????????x>>"); } -TEST(Base64, binary_data) +TEST(Base64, BinaryData) { const Base64 b64; diff --git a/test/unittests/test_buffer.cpp b/test/unittests/test_buffer.cpp index 36d9bbc69..5f9d39145 100644 --- a/test/unittests/test_buffer.cpp +++ b/test/unittests/test_buffer.cpp @@ -2,40 +2,81 @@ #include <openvpn/buffer/bufstr.hpp> +#include <cstdint> + using namespace openvpn; +struct align_test +{ + int i = 42; +}; + +// Test align_as +template <typename T> +void realign_test(BufferAllocated &buf, std::size_t headroom) +{ + constexpr std::size_t at_align = alignof(T); + const std::size_t at_misalign = headroom; + const std::size_t at_align_ex = at_misalign & ~(at_align - 1); + + buf.write_alloc(at_misalign); + buf.read_alloc(at_misalign); + EXPECT_EQ(buf.offset(), at_misalign); + + align_test at; + std::memcpy(buf.write_alloc(sizeof(at)), &at, sizeof(at)); + EXPECT_EQ(buf.offset(), at_misalign); + + auto ptr = align_as<align_test>(buf); // Align the buffer contents + + EXPECT_EQ(ptr->i, 42); + EXPECT_EQ(buf.offset(), at_align_ex); // Nearest aligned offset + + std::cout << "Aligning buffer: " << at_misalign << " -> " << at_align_ex << '\n'; +} + +TEST(Buffer, BufferAlignas) +{ + constexpr std::size_t test_lim = std::numeric_limits<std::size_t>::digits; + for (auto i = std::size_t(0); i < test_lim; ++i) + { + BufferAllocated buf(test_lim * 2); + realign_test<align_test>(buf, i); + } +} + // test equality of Buffer and ConstBuffer -TEST(buffer, const_buffer_ref_1) +TEST(Buffer, ConstBufferRef1) { static unsigned char hello[] = "hello world"; Buffer buf(hello, sizeof(hello) - 1, true); - ConstBuffer &cbuf = const_buffer_ref(buf); - EXPECT_EQ(cbuf.size(), 11u); + const ConstBuffer &cbuf = const_buffer_ref(buf); + EXPECT_EQ(cbuf.size(), 11U); EXPECT_EQ(buf_to_string(buf), buf_to_string(cbuf)); } // test equality of BufferAllocatedRc and ConstBuffer -TEST(buffer, const_buffer_ref_2) +TEST(Buffer, ConstBufferRef2) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); - ConstBuffer &cbuf = const_buffer_ref(buf); - EXPECT_EQ(cbuf.size(), 11u); + const ConstBuffer &cbuf = const_buffer_ref(buf); + EXPECT_EQ(cbuf.size(), 11U); EXPECT_EQ(buf_to_string(buf), buf_to_string(cbuf)); } // test ConstBufferType with an explicitly const type -TEST(buffer, my_const_buffer_1) +TEST(Buffer, MyConstBuffer1) { - typedef ConstBufferType<const char> MyConstBuffer; + using MyConstBuffer = ConstBufferType<const char>; static const char hello[] = "hello world"; - MyConstBuffer cbuf(hello, sizeof(hello) - 1, true); - EXPECT_EQ(cbuf.size(), 11u); + const MyConstBuffer cbuf(hello, sizeof(hello) - 1, true); + EXPECT_EQ(cbuf.size(), 11U); EXPECT_EQ(std::string(cbuf.c_data(), cbuf.size()), "hello world"); } // Test read access and bounds check on ConstBufferType -TEST(buffer, const_buffer_access1) +TEST(Buffer, ConstBufferAccess1) { constexpr char data[] = "hello world"; ConstBufferType<char> cbuf(data, sizeof(data) - 1, true); @@ -45,7 +86,7 @@ TEST(buffer, const_buffer_access1) } // Test read access and bounds check on ConstBufferType -TEST(buffer, const_buffer_access2) +TEST(Buffer, ConstBufferAccess2) { constexpr char data[] = "hello world"; ConstBufferType<char> cbuf(data, sizeof(data) - 1, true); @@ -64,7 +105,7 @@ TEST(buffer, const_buffer_access2) } // Test read access and bounds check on ConstBufferType -TEST(buffer, const_buffer_access3) +TEST(Buffer, ConstBufferAccess3) { constexpr char data[] = "hello world"; ConstBufferType<char> cbuf(data, sizeof(data) - 1, true); @@ -83,7 +124,7 @@ TEST(buffer, const_buffer_access3) } // Test read access and bounds check -TEST(buffer, buffer_access1) +TEST(Buffer, BufferAccess1) { char data[] = "hello world"; BufferType<char> buf(data, sizeof(data) - 1, true); @@ -93,7 +134,7 @@ TEST(buffer, buffer_access1) } // Test read/write access and bounds check -TEST(buffer, buffer_access2) +TEST(Buffer, BufferAccess2) { char data[] = "hello world"; BufferType<char> buf(data, sizeof(data) - 1, true); @@ -105,7 +146,7 @@ TEST(buffer, buffer_access2) } // Test push/pop and bounds check -TEST(buffer, buffer_access3) +TEST(Buffer, BufferAccess3) { char data1[] = "hello world"; char data2[sizeof(data1)]; @@ -126,7 +167,7 @@ TEST(buffer, buffer_access3) } // Test push/pop and bounds check -TEST(buffer, buffer_access4) +TEST(Buffer, BufferAccess4) { char data1[] = "hello world"; char data2[sizeof(data1)]; @@ -153,9 +194,9 @@ TEST(buffer, buffer_access4) } // Test read access and bounds check -TEST(buffer, alloc_buffer_access1) +TEST(Buffer, AllocBufferAccess1) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); EXPECT_EQ(buf[0], 'h'); EXPECT_EQ(buf[10], 'd'); @@ -163,7 +204,7 @@ TEST(buffer, alloc_buffer_access1) } // Test read/write access and bounds check -TEST(buffer, alloc_buffer_access2) +TEST(Buffer, AllocBufferAccess2) { BufferAllocated buf(64, BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::DESTRUCT_ZERO); buf_append_string(buf, "hello world"); @@ -176,11 +217,11 @@ TEST(buffer, alloc_buffer_access2) } // Test read/write access and bounds check -TEST(buffer, alloc_buffer_access3) +TEST(Buffer, AllocBufferAccess3) { char data[] = "hello world"; BufferType<char> buf1(data, sizeof(data) - 1, true); - BufferAllocated buf(sizeof(data), 0); + BufferAllocated buf(sizeof(data)); auto items = buf1.size(); while (items--) @@ -196,9 +237,9 @@ TEST(buffer, alloc_buffer_access3) } // Test pop_front -TEST(buffer, alloc_buffer_pop_front) +TEST(Buffer, AllocBufferPopFront) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); while (buf.pop_front() != 'd') @@ -207,9 +248,9 @@ TEST(buffer, alloc_buffer_pop_front) } // Test advance -TEST(buffer, alloc_buffer_advance1) +TEST(Buffer, AllocBufferAdvance1) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); do @@ -224,20 +265,20 @@ TEST(buffer, alloc_buffer_advance1) } // Test advance -TEST(buffer, alloc_buffer_advance2) +TEST(Buffer, AllocBufferAdvance2) { constexpr char data[] = "hello world"; - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, data); EXPECT_THROW(buf.advance(sizeof(data)), BufferException); } // Test advance -TEST(buffer, alloc_buffer_advance3) +TEST(Buffer, AllocBufferAdvance3) { constexpr char data[] = "hello world"; - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, data); buf.advance(sizeof(data) - 2); @@ -249,9 +290,9 @@ TEST(buffer, alloc_buffer_advance3) } // Test remaining() -TEST(buffer, alloc_buffer_remaining) +TEST(Buffer, AllocBufferRemaining) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); for (auto remaining = buf.remaining(); remaining > 0; @@ -265,9 +306,9 @@ TEST(buffer, alloc_buffer_remaining) } // Test init_headroom() -TEST(buffer, alloc_buffer_init_headroom) +TEST(Buffer, AllocBufferInitHeadroom) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); EXPECT_EQ(buf.remaining(), 64); buf.init_headroom(32); @@ -285,9 +326,9 @@ TEST(buffer, alloc_buffer_init_headroom) } // Test reset_offset() -TEST(buffer, alloc_buffer_reset_offset) +TEST(Buffer, AllocBufferResetOffset) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); EXPECT_EQ(buf.remaining(), 64); @@ -309,9 +350,9 @@ TEST(buffer, alloc_buffer_reset_offset) } // Test reset_size() -TEST(buffer, alloc_buffer_reset_size) +TEST(Buffer, AllocBufferResetSize) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); EXPECT_EQ(buf.remaining(), 64); @@ -331,10 +372,10 @@ TEST(buffer, alloc_buffer_reset_size) } // Test read() -TEST(buffer, alloc_buffer_read1) +TEST(Buffer, AllocBufferRead1) { constexpr char data[] = "hello world"; - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, data); char raw[sizeof(data) - 1]; @@ -344,72 +385,72 @@ TEST(buffer, alloc_buffer_read1) EXPECT_EQ(memcmp(raw, data, sizeof(raw)), 0); } -TEST(buffer, prepend_alloc) +TEST(Buffer, PrependAlloc) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); - EXPECT_EQ(buf.offset(), 0u); + EXPECT_EQ(buf.offset(), 0U); buf.prepend_alloc(5); - EXPECT_EQ(buf.size(), 16u); - EXPECT_EQ(buf.remaining(), 48u); + EXPECT_EQ(buf.size(), 16U); + EXPECT_EQ(buf.remaining(), 48U); } -TEST(buffer, prepend_alloc_2) +TEST(Buffer, PrependAlloc2) { - BufferAllocated buf(64, 0); - EXPECT_EQ(buf.offset(), 0u); + BufferAllocated buf(64); + EXPECT_EQ(buf.offset(), 0U); buf.init_headroom(2); - EXPECT_EQ(buf.offset(), 2u); + EXPECT_EQ(buf.offset(), 2U); buf_append_string(buf, "hello world"); - EXPECT_EQ(buf.offset(), 2u); + EXPECT_EQ(buf.offset(), 2U); buf.prepend_alloc(5); - EXPECT_EQ(buf.offset(), 0u); - EXPECT_EQ(buf.size(), 16u); - EXPECT_EQ(buf.remaining(), 48u); + EXPECT_EQ(buf.offset(), 0U); + EXPECT_EQ(buf.size(), 16U); + EXPECT_EQ(buf.remaining(), 48U); } -TEST(buffer, prepend_alloc_fits) +TEST(Buffer, PrependAllocFits) { - BufferAllocated buf(64, 0); - EXPECT_EQ(buf.offset(), 0u); + BufferAllocated buf(64); + EXPECT_EQ(buf.offset(), 0U); buf.init_headroom(5); - EXPECT_EQ(buf.offset(), 5u); + EXPECT_EQ(buf.offset(), 5U); buf_append_string(buf, "hello world"); - EXPECT_EQ(buf.offset(), 5u); + EXPECT_EQ(buf.offset(), 5U); buf.prepend_alloc(5); - EXPECT_EQ(buf.offset(), 0u); - EXPECT_EQ(buf.size(), 16u); - EXPECT_EQ(buf.remaining(), 48u); + EXPECT_EQ(buf.offset(), 0U); + EXPECT_EQ(buf.size(), 16U); + EXPECT_EQ(buf.remaining(), 48U); } -TEST(buffer, prepend_alloc_fail) +TEST(Buffer, PrependAllocFail) { - BufferAllocated buf(11, 0); + BufferAllocated buf(11); buf_append_string(buf, "hello world"); EXPECT_THROW(buf.prepend_alloc(5), std::exception); - EXPECT_EQ(buf.size(), 11u); - EXPECT_EQ(buf.remaining(), 0u); + EXPECT_EQ(buf.size(), 11U); + EXPECT_EQ(buf.remaining(), 0U); } -TEST(buffer, prepend_alloc_fail2) +TEST(Buffer, PrependAllocFail2) { - BufferAllocated buf(14, 0); + BufferAllocated buf(14); buf_append_string(buf, "hello world"); EXPECT_THROW(buf.prepend_alloc(5), std::exception); - EXPECT_EQ(buf.size(), 11u); - EXPECT_EQ(buf.remaining(), 3u); + EXPECT_EQ(buf.size(), 11U); + EXPECT_EQ(buf.remaining(), 3U); } -TEST(buffer, realign) +TEST(Buffer, Realign) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); buf.advance(5); @@ -420,13 +461,13 @@ TEST(buffer, realign) EXPECT_EQ(buf[0], ' '); EXPECT_EQ(buf[5], 'd'); EXPECT_THROW(buf[6], BufferException); - EXPECT_EQ(buf.size(), 6u); + EXPECT_EQ(buf.size(), 6U); EXPECT_EQ(buf.c_data_raw()[0], ' '); } -TEST(buffer, realign2) +TEST(Buffer, Realign2) { - BufferAllocated buf(64, 0); + BufferAllocated buf(64); buf_append_string(buf, "hello world"); EXPECT_EQ(buf.c_data_raw()[0], 'h'); @@ -435,12 +476,12 @@ TEST(buffer, realign2) EXPECT_EQ(buf.c_data_raw()[5], 'h'); EXPECT_EQ(buf[0], 'h'); - EXPECT_EQ(buf.size(), 11u); + EXPECT_EQ(buf.size(), 11U); } -TEST(buffer, realign3) +TEST(Buffer, Realign3) { - BufferAllocated buf(11, 0); + BufferAllocated buf(11); buf_append_string(buf, "hello world"); EXPECT_EQ(buf.c_data_raw()[0], 'h'); @@ -449,16 +490,16 @@ TEST(buffer, realign3) EXPECT_EQ(buf.c_data_raw()[5], 'h'); EXPECT_EQ(buf[0], 'h'); - EXPECT_EQ(buf.size(), 11u); - EXPECT_EQ(buf.offset(), 5u); + EXPECT_EQ(buf.size(), 11U); + EXPECT_EQ(buf.offset(), 5U); } -TEST(buffer, realign4) +TEST(Buffer, Realign4) { - BufferAllocated buf(32, 0); - buf.realign(7u); + BufferAllocated buf(32); + buf.realign(7U); buf_append_string(buf, "hello world"); - EXPECT_EQ(buf.offset(), 7u); + EXPECT_EQ(buf.offset(), 7U); buf.realign(0); EXPECT_EQ(buf.c_data_raw()[0], 'h'); @@ -487,17 +528,17 @@ TEST(buffer, realign4) unspecified state." */ -TEST(buffer, invariants_after_move_safe) +TEST(Buffer, InvariantsAfterMoveSafe) { - BufferAllocated buf(32, 0u); + BufferAllocated buf(32); buf_append_string(buf, "hello world"); - BufferAllocated buf2(std::move(buf)); + const BufferAllocated buf2(std::move(buf)); // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf.size(), 0u); + EXPECT_EQ(buf.size(), 0U); // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf.capacity(), 0u); + EXPECT_EQ(buf.capacity(), 0U); // coverity[USE_AFTER_MOVE] EXPECT_THROW(buf[0], BufferException); // coverity[USE_AFTER_MOVE] @@ -509,14 +550,14 @@ TEST(buffer, invariants_after_move_safe) // coverity[USE_AFTER_MOVE] EXPECT_EQ(buf.data_raw(), nullptr); // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf.offset(), 0u); + EXPECT_EQ(buf.offset(), 0U); // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf.remaining(), 0u); + EXPECT_EQ(buf.remaining(), 0U); } -TEST(buffer, push_back_after_move_safe) +TEST(Buffer, PushBackAfterMoveSafe) { - BufferAllocated buf(32, 0u); + BufferAllocated buf(32); buf_append_string(buf, "hello world"); BufferAllocated buf2(std::move(buf)); @@ -524,7 +565,7 @@ TEST(buffer, push_back_after_move_safe) buf.push_back('X'); // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf2.size(), 11u); + EXPECT_EQ(buf2.size(), 11U); // coverity[USE_AFTER_MOVE] EXPECT_EQ(buf2[0], 'h'); // coverity[USE_AFTER_MOVE] @@ -533,18 +574,18 @@ TEST(buffer, push_back_after_move_safe) EXPECT_EQ(buf[0], 'X'); } -TEST(buffer, append_after_move_safe) +TEST(Buffer, AppendAfterMoveSafe) { - BufferAllocated buf(32, 0u); + BufferAllocated buf(32); buf_append_string(buf, "hello world"); BufferAllocated buf2(std::move(buf)); - auto buf3 = BufferAllocated(32, 0u); + auto buf3 = BufferAllocated(32); buf_append_string(buf3, "hello again"); buf = buf3; // coverity[USE_AFTER_MOVE] - EXPECT_EQ(buf2.size(), 11u); + EXPECT_EQ(buf2.size(), 11U); // coverity[USE_AFTER_MOVE] EXPECT_EQ(buf2[0], 'h'); // coverity[USE_AFTER_MOVE] diff --git a/test/unittests/test_buffer_ip.cpp b/test/unittests/test_buffer_ip.cpp index 1e6ee2ff8..e03f3f7d3 100644 --- a/test/unittests/test_buffer_ip.cpp +++ b/test/unittests/test_buffer_ip.cpp @@ -18,9 +18,9 @@ static std::string to_hex(const std::uint32_t value) return os.str(); } -TEST(buffer_ip, unsigned_decimal) +TEST(BufferIp, UnsignedDecimal) { - typedef BufferFormat::UnsignedDecimal<std::uint32_t> Decimal; + using Decimal = BufferFormat::UnsignedDecimal<std::uint32_t>; for (int i = -1000; i < 1000; ++i) { StaticBuffer<Decimal::max_length()> buf; @@ -29,9 +29,9 @@ TEST(buffer_ip, unsigned_decimal) } } -TEST(buffer_ip, hex) +TEST(BufferIp, Hex) { - typedef BufferFormat::Hex<std::uint32_t> Hex; + using Hex = BufferFormat::Hex<std::uint32_t>; for (int i = -1000; i < 1000; ++i) { StaticBuffer<10> buf; @@ -46,9 +46,9 @@ static constexpr int ITER = 10000; static constexpr int ITER = 1000000; #endif -TEST(buffer_ip, ipv4) +TEST(BufferIp, Ipv4) { - MTRand::Ptr prng(new MTRand()); + const MTRand::Ptr prng(new MTRand()); for (int count = 0; count < ITER; ++count) { std::uint32_t addr; @@ -65,9 +65,9 @@ TEST(buffer_ip, ipv4) } } -TEST(buffer_ip, ipv6) +TEST(BufferIp, Ipv6) { - MTRand::Ptr prng(new MTRand()); + const MTRand::Ptr prng(new MTRand()); for (int count = 0; count < ITER; ++count) { std::uint8_t addr[16]; diff --git a/test/unittests/test_capture.cpp b/test/unittests/test_capture.cpp index 3260d391a..c1276eebf 100644 --- a/test/unittests/test_capture.cpp +++ b/test/unittests/test_capture.cpp @@ -11,6 +11,7 @@ #include "test_common.hpp" #include "test_generators.hpp" +#include <rapidcheck/state.h> #include <iostream> @@ -19,7 +20,7 @@ using namespace openvpn; -TEST(misc, capture) +TEST(Misc, Capture) { DnsServer server; server.addresses = {DnsAddress("8.8.8.8"), DnsAddress("8.8.4.4:53")}; @@ -27,7 +28,7 @@ TEST(misc, capture) dns_options.servers[0] = std::move(server); dns_options.search_domains = {DnsDomain("yonan.net"), DnsDomain("openvpn.net")}; - TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); tbc->tun_builder_set_remote_address("52.7.171.249", false); tbc->tun_builder_add_address("1.2.3.4", 24, "10.10.0.1", false, false); @@ -55,7 +56,7 @@ TEST(misc, capture) // OPENVPN_LOG("TEXT #1:\n" << tbc->to_string()); // const std::string fn1 = "cap1.txt"; - Json::Value j1 = tbc->to_json(); + const Json::Value j1 = tbc->to_json(); const std::string j1_txt = j1.toStyledString(); // OPENVPN_LOG("writing to " << fn1); @@ -64,9 +65,9 @@ TEST(misc, capture) // OPENVPN_LOG("JSON #1:\n" << j1_txt); // const std::string fn2 = "cap2.txt"; - TunBuilderCapture::Ptr tbc2 = TunBuilderCapture::from_json(j1); + const TunBuilderCapture::Ptr tbc2 = TunBuilderCapture::from_json(j1); tbc2->validate(); - Json::Value j2 = tbc2->to_json(); + const Json::Value j2 = tbc2->to_json(); const std::string j2_txt = j2.toStyledString(); // OPENVPN_LOG("writing to " << fn2); // write_string(fn2, j2_txt); @@ -371,6 +372,77 @@ RC_GTEST_PROP(RouteBased, StringRepresentationReturnsSetOptions, (rc::RouteBased route_based); } +RC_GTEST_PROP(RouteBased, EmptyThrowsOnValidation, (rc::RouteBased route_based, const std::string &title)) +{ + std::visit( + [&title](auto &&route_base_variant) + { + using T = std::decay_t<decltype(route_base_variant)>; + if constexpr (std::is_same_v<T, TunBuilderCapture::RouteBase>) + { + RC_DISCARD("RouteBase does not have public validate method"); + } + else + { + RC_ASSERT_THROWS_AS(route_base_variant.validate(title), openvpn::IP::ip_exception); + } + }, + route_based); +} + +RC_GTEST_PROP(RouteBased, Validates, (rc::RouteBased route_based, bool ipv6, bool net30, const std::string &title)) +{ + // TODO: move to generator + std::visit( + [ipv6, net30, &title](auto &&route_base_variant) + { + using T = std::decay_t<decltype(route_base_variant)>; + if constexpr (std::is_same_v<T, TunBuilderCapture::RouteBase>) + { + RC_DISCARD("RouteBase does not have public validate method"); + } + else + { + // Performs canonicalization so Route is valid + // TODO: separate path for RouteAddress that can be not canonical + if (ipv6) + { + route_base_variant.ipv6 = true; + auto ipv6_route = route_from_string(*rc::IPv6Address(), title, IP::Addr::V6); + ipv6_route.force_canonical(); + route_base_variant.address = ipv6_route.to_string_optional_prefix_len(); + route_base_variant.prefix_length = IPv6::Addr::SIZE; + } + else + { + route_base_variant.ipv6 = false; + route_base_variant.address = *rc::IPv4Address().as("Valid IPv4 address"); + auto [prefix_min, prefix_max] = rc::calculateIPPrefixRange(route_base_variant.address); + if (net30 && prefix_min <= 30 && prefix_max >= 30) + { + route_base_variant.net30 = true; + route_base_variant.prefix_length = 30; + } + else + { + route_base_variant.net30 = false; + route_base_variant.prefix_length = *rc::gen::inRange(static_cast<char>(prefix_min), static_cast<char>(prefix_max + 1)).as("Valid prefix length"); + } + } + if (auto maybe_metric = *rc::gen::maybe(rc::gen::arbitrary<int>().as("Metric value")).as("Maybe metric")) + { + route_base_variant.metric = *maybe_metric; + } + if (auto maybe_gateway = ipv6 ? *rc::gen::maybe(rc::IPv6Address().as("Valid IPv6 gateway")) : *rc::gen::maybe(rc::IPv4Address().as("Valid IPv4 gateway"))) + { + route_base_variant.gateway = *maybe_gateway; + } + route_base_variant.validate(title); + } + }, + route_based); +} + RC_GTEST_PROP(RouteBased, EmptyJsonRoundTripHaveSameStringRepresentation, (rc::RouteBased route_based, const std::string &title)) { @@ -406,6 +478,18 @@ RC_GTEST_PROP(RouteBased, JsonRoundTripHaveSameStringRepresentation, (rc::RouteB route_based); } + +RC_GTEST_PROP(RouteBased, FromInvalidJsonThrows, (rc::RouteBased route_based, const std::string &title)) +{ + std::visit( + [&title](auto &&route_base_variant) + { + const Json::Value invalid_json = {}; + RC_ASSERT_THROWS_AS(route_base_variant.from_json(invalid_json, title), json::json_parse); + }, + route_based); +} + // =============================================================================================== // ProxyBypass tests // =============================================================================================== @@ -784,3 +868,960 @@ RC_GTEST_PROP(WINSServer, FromInvalidJsonThrows, (const std::string &title)) const Json::Value invalid_json; RC_ASSERT_THROWS_AS(from_json.from_json(invalid_json, title), json::json_parse); } + +// =============================================================================================== +// TunBuilderCapture tests +// =============================================================================================== + +RC_GTEST_PROP(TunBuilderCapture, SetsRemoteAddress, (const std::string &address, const bool ipv6)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_remote_address(address, ipv6)); + RC_ASSERT(tbc->remote_address.address == address); + RC_ASSERT(tbc->remote_address.ipv6 == ipv6); +} + +RC_GTEST_PROP(TunBuilderCapture, AddsAddress, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool ipv6, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, ipv6, net30)); + const auto ip_version = ipv6 ? IP::Addr::V6 : IP::Addr::V4; + const TunBuilderCapture::RouteAddress *vpn_address = tbc->vpn_ip(ip_version); + RC_ASSERT(vpn_address->address == address); + RC_ASSERT(vpn_address->prefix_length == prefix_length); + RC_ASSERT(vpn_address->gateway == gateway); + RC_ASSERT(vpn_address->net30 == net30); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsRerouteGW, (const bool ipv4, const bool ipv6, const unsigned int flags)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_reroute_gw(ipv4, ipv6, flags)); + RC_ASSERT(tbc->reroute_gw.ipv4 == ipv4); + RC_ASSERT(tbc->reroute_gw.ipv6 == ipv6); + RC_ASSERT(tbc->reroute_gw.flags == flags); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsRouteMetricDefault, (const int metric)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_route_metric_default(metric)); + RC_ASSERT(tbc->route_metric_default == metric); +} + +RC_GTEST_PROP(TunBuilderCapture, AddsRoute, (const std::string &address, const unsigned char prefix_length, const bool ipv6)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + const auto metric = *rc::gen::positive<int>().as("Valid route metric"); + RC_ASSERT(tbc->tun_builder_add_route(address, prefix_length, metric, ipv6)); + const auto &added_route = tbc->add_routes.back(); + RC_ASSERT(added_route.address == address); + RC_ASSERT(added_route.prefix_length == prefix_length); + RC_ASSERT(added_route.metric == metric); + RC_ASSERT(added_route.ipv6 == ipv6); +} + +RC_GTEST_PROP(TunBuilderCapture, ExcludesRoute, (const std::string &address, const unsigned char prefix_length, const int metric, const bool ipv6)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_exclude_route(address, prefix_length, metric, ipv6)); + const auto &excluded_route = tbc->exclude_routes.back(); + RC_ASSERT(excluded_route.address == address); + RC_ASSERT(excluded_route.prefix_length == prefix_length); + RC_ASSERT(excluded_route.metric == metric); + RC_ASSERT(excluded_route.ipv6 == ipv6); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsDNSOptions, (const std::string &search_domain)) +{ + DnsServer server = {}; + auto address = DnsAddress(*rc::genDnsAddressAsStr()); + server.addresses.push_back(address); + DnsOptions dns_options = {}; + dns_options.servers[0] = std::move(server); + dns_options.search_domains = {DnsDomain(search_domain)}; + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_dns_options(dns_options)); + RC_ASSERT(tbc->dns_options.search_domains.back().domain == search_domain); + RC_ASSERT(tbc->dns_options.servers.at(0).addresses.back().to_string() == address.to_string()); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsLayer, ()) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + const auto layer = *rc::gen::element(3, 2, 0).as("Layer - 3, 2 or 0"); + RC_ASSERT(tbc->tun_builder_set_layer(layer)); + RC_ASSERT(tbc->layer.value() == layer); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsMTU, (const int mtu)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_mtu(mtu)); + RC_ASSERT(tbc->mtu == mtu); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsSessionName, (const std::string &session_name)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_session_name(session_name)); + RC_ASSERT(tbc->session_name == session_name); +} + +RC_GTEST_PROP(TunBuilderCapture, AddsProxyBypass, (const std::string &bypass_host)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_add_proxy_bypass(bypass_host)); + RC_ASSERT(tbc->proxy_bypass.back().bypass_host == bypass_host); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsProxyAutoConfigURL, (const std::string &url)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_proxy_auto_config_url(url)); + RC_ASSERT(tbc->proxy_auto_config_url.url == url); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsProxyHTTP, (const std::string &host, const int port)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_proxy_http(host, port)); + RC_ASSERT(tbc->http_proxy.host == host); + RC_ASSERT(tbc->http_proxy.port == port); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsProxyHTTPS, (const std::string &host, const int port)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_proxy_https(host, port)); + RC_ASSERT(tbc->https_proxy.host == host); + RC_ASSERT(tbc->https_proxy.port == port); +} + +RC_GTEST_PROP(TunBuilderCapture, AddsWINSServer, (const std::string &address)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_add_wins_server(address)); + RC_ASSERT(tbc->wins_servers.back().address == address); +} + +RC_GTEST_PROP(TunBuilderCapture, SetsAllowFamily, (const bool allow)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + const auto allow_family = *rc::gen::element(AF_INET, AF_INET6).as("Allow family - AF_INET or AF_INET6"); + RC_ASSERT(tbc->tun_builder_set_allow_family(allow_family, allow)); + if (allow_family == AF_INET) + { + RC_ASSERT_FALSE(tbc->block_ipv4 == allow); + } + else + { + RC_ASSERT_FALSE(tbc->block_ipv6 == allow); + } +} + +RC_GTEST_PROP(TunBuilderCapture, SetsAllowLocalDNS, (const bool allow)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_allow_local_dns(allow)); + RC_ASSERT_FALSE(tbc->block_outside_dns == allow); +} + +RC_GTEST_PROP(TunBuilderCapture, ResetsTunnelAddresses, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool ipv6, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, ipv6, net30)); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, !ipv6, net30)); + RC_ASSERT_FALSE(tbc->tunnel_addresses.empty()); + RC_ASSERT(tbc->tunnel_address_index_ipv4 > -1); + RC_ASSERT(tbc->tunnel_address_index_ipv6 > -1); + tbc->reset_tunnel_addresses(); + RC_ASSERT(tbc->tunnel_addresses.empty()); + RC_ASSERT(tbc->tunnel_address_index_ipv4 == -1); + RC_ASSERT(tbc->tunnel_address_index_ipv6 == -1); +} + +RC_GTEST_PROP(TunBuilderCapture, ResetsDNSOptions, (const std::string &search_domain)) +{ + DnsServer server = {}; + auto address = DnsAddress(*rc::genDnsAddressAsStr()); + server.addresses.push_back(address); + DnsOptions dns_options = {}; + dns_options.servers[0] = std::move(server); + dns_options.search_domains = {DnsDomain(search_domain)}; + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->tun_builder_set_dns_options(dns_options)); + RC_ASSERT_FALSE(tbc->dns_options.to_string().empty()); + tbc->reset_dns_options(); + RC_ASSERT(tbc->dns_options.to_string() == "Values from dhcp-options: false\n"); +} + +RC_GTEST_PROP(TunBuilderCapture, ReturnsVPNIPv4, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->vpn_ipv4() == nullptr); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, false, net30)); + const TunBuilderCapture::RouteAddress *vpn_address = tbc->vpn_ipv4(); + RC_ASSERT(vpn_address->address == address); + RC_ASSERT(vpn_address->prefix_length == prefix_length); + RC_ASSERT(vpn_address->gateway == gateway); + RC_ASSERT(vpn_address->net30 == net30); +} + +RC_GTEST_PROP(TunBuilderCapture, ReturnsVPNIPv6, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->vpn_ipv6() == nullptr); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, true, net30)); + const TunBuilderCapture::RouteAddress *vpn_address = tbc->vpn_ipv6(); + RC_ASSERT(vpn_address->address == address); + RC_ASSERT(vpn_address->prefix_length == prefix_length); + RC_ASSERT(vpn_address->gateway == gateway); + RC_ASSERT(vpn_address->net30 == net30); +} + +RC_GTEST_PROP(TunBuilderCapture, ReturnsVPNIP, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool ipv6, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + RC_ASSERT(tbc->vpn_ip(IP::Addr::UNSPEC) == nullptr); + RC_ASSERT(tbc->tun_builder_add_address(address, prefix_length, gateway, ipv6, net30)); + const auto ip_version = ipv6 ? IP::Addr::V6 : IP::Addr::V4; + const TunBuilderCapture::RouteAddress *vpn_address = tbc->vpn_ip(ip_version); + RC_ASSERT(vpn_address->address == address); + RC_ASSERT(vpn_address->prefix_length == prefix_length); + RC_ASSERT(vpn_address->gateway == gateway); + RC_ASSERT(vpn_address->net30 == net30); +} + +RC_GTEST_PROP(TunBuilderCapture, StringRepresentation, (const std::string &address, const unsigned char prefix_length, const std::string &gateway, const bool ipv6, const bool net30)) +{ + const TunBuilderCapture::Ptr tbc(new TunBuilderCapture); + std::ostringstream os = {}; + os << "Session Name: " << tbc->session_name << '\n'; + os << "Layer: " << tbc->layer.str() << '\n'; + os << "Remote Address: " << tbc->remote_address.to_string() << '\n'; + os << "Tunnel Addresses:\n"; + os << "Reroute Gateway: " << tbc->reroute_gw.to_string() << '\n'; + os << "Block IPv4: " << (tbc->block_ipv4 ? "yes" : "no") << '\n'; + os << "Block IPv6: " << (tbc->block_ipv6 ? "yes" : "no") << '\n'; + os << "Block local DNS: " << (tbc->block_outside_dns ? "yes" : "no") << '\n'; + os << "Add Routes:\n"; + os << "Exclude Routes:\n"; + RC_ASSERT(tbc->to_string() == os.str()); +} + +struct TunBuilderCaptureModel +{ + std::string session_name; + int mtu{0}; + Layer layer{Layer::OSI_LAYER_3}; + TunBuilderCapture::RemoteAddress remote_address{}; + std::vector<TunBuilderCapture::RouteAddress> tunnel_addresses; + int tunnel_address_index_ipv4{-1}; + int tunnel_address_index_ipv6{-1}; + TunBuilderCapture::RerouteGW reroute_gw{}; + bool block_ipv4{false}; + bool block_ipv6{false}; + bool block_outside_dns{false}; + int route_metric_default{-1}; + std::vector<TunBuilderCapture::Route> add_routes; + std::vector<TunBuilderCapture::Route> exclude_routes; + DnsOptions dns_options{}; + std::vector<TunBuilderCapture::ProxyBypass> proxy_bypass; + TunBuilderCapture::ProxyAutoConfigURL proxy_auto_config_url{}; + TunBuilderCapture::ProxyHostPort http_proxy{}; + TunBuilderCapture::ProxyHostPort https_proxy{}; + std::vector<TunBuilderCapture::WINSServer> wins_servers{}; + static constexpr auto mtu_ipv4_maximum{65'535}; +}; + +struct SetRemoteAddress final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string address; + bool ipv6{false}; + + explicit SetRemoteAddress() + : address{*rc::gen::arbitrary<std::string>()}, ipv6{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.remote_address.address = address; + model.remote_address.ipv6 = ipv6; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_remote_address(address, ipv6)); + RC_ASSERT(sut.remote_address.address == address); + RC_ASSERT(sut.remote_address.ipv6 == ipv6); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set RemoteAddress to " << address << " " << (ipv6 ? "IPv6" : "IPv4"); + } +}; + +struct AddAddress final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string address; + unsigned char prefix_length{0}; + int metric{-1}; + std::string gateway; + bool ipv6{false}; + bool net30{false}; + + explicit AddAddress() + : address{*rc::gen::arbitrary<std::string>()}, prefix_length{*rc::gen::arbitrary<unsigned char>()}, gateway{*rc::gen::arbitrary<std::string>()}, ipv6{*rc::gen::arbitrary<bool>()}, net30{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + TunBuilderCapture::RouteAddress address; + address.address = this->address; + address.prefix_length = static_cast<unsigned char>(prefix_length); + address.gateway = gateway; + address.ipv6 = ipv6; + address.net30 = net30; + if (ipv6) + { + model.tunnel_address_index_ipv6 = static_cast<int>(model.tunnel_addresses.size()); + } + else + { + model.tunnel_address_index_ipv4 = static_cast<int>(model.tunnel_addresses.size()); + } + model.tunnel_addresses.push_back(std::move(address)); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_add_address(address, prefix_length, gateway, ipv6, net30)); + RC_ASSERT(sut.tunnel_addresses.size() == model.tunnel_addresses.size() + 1); + if (ipv6) + { + RC_ASSERT(sut.tunnel_address_index_ipv6 == static_cast<int>(model.tunnel_addresses.size())); + const auto *current_address = sut.vpn_ipv6(); + RC_ASSERT(current_address->address == address); + RC_ASSERT(current_address->prefix_length == prefix_length); + RC_ASSERT(current_address->gateway == gateway); + RC_ASSERT(current_address->ipv6 == ipv6); + RC_ASSERT(current_address->net30 == net30); + } + else + { + RC_ASSERT(sut.tunnel_address_index_ipv4 == static_cast<int>(model.tunnel_addresses.size())); + const auto *current_address = sut.vpn_ipv4(); + RC_ASSERT(current_address->address == address); + RC_ASSERT(current_address->prefix_length == prefix_length); + RC_ASSERT(current_address->gateway == gateway); + RC_ASSERT(current_address->ipv6 == ipv6); + RC_ASSERT(current_address->net30 == net30); + } + const auto *current_address = sut.vpn_ip(ipv6 ? IP::Addr::V6 : IP::Addr::V4); + RC_ASSERT(current_address->address == address); + RC_ASSERT(current_address->prefix_length == prefix_length); + RC_ASSERT(current_address->gateway == gateway); + RC_ASSERT(current_address->ipv6 == ipv6); + RC_ASSERT(current_address->net30 == net30); + } + + auto show(std::ostream &os) const -> void override + { + os << "Add address: " << address << " prefix_length: " << prefix_length << " gateway: " << gateway << (ipv6 ? "IPv6" : "IPv4") << " net30: " << net30; + } +}; + +struct RerouteGW final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + bool ipv4{false}; + bool ipv6{false}; + unsigned int flags{0}; + + explicit RerouteGW() + : ipv4{*rc::gen::arbitrary<bool>()}, ipv6{*rc::gen::arbitrary<bool>()}, flags{*rc::gen::arbitrary<unsigned int>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.reroute_gw.ipv4 = ipv4; + model.reroute_gw.ipv6 = ipv6; + model.reroute_gw.flags = flags; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_reroute_gw(ipv4, ipv6, flags)); + RC_ASSERT(sut.reroute_gw.ipv6 == ipv6); + RC_ASSERT(sut.reroute_gw.ipv4 == ipv4); + RC_ASSERT(sut.reroute_gw.ipv6 == ipv6); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set RerouteGW ipv4: " << ipv4 << " ipv6: " << ipv6 << " flags: " << flags; + } +}; + +struct SetRouteMetricDefault final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + int metric{}; + + explicit SetRouteMetricDefault() + : metric{*rc::gen::arbitrary<int>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.route_metric_default = metric; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_route_metric_default(metric)); + RC_ASSERT(sut.route_metric_default == metric); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set route metric default to " << metric; + } +}; + +struct AddRoute final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string address; + unsigned char prefix_length{0}; + int metric{-1}; + std::string gateway; + bool ipv6{false}; + bool net30{false}; + + explicit AddRoute() + : address{*rc::gen::arbitrary<std::string>()}, prefix_length{static_cast<unsigned char>(*rc::gen::arbitrary<int>())}, metric{*rc::gen::arbitrary<int>()}, ipv6{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + TunBuilderCapture::Route route; + route.address = address; + route.prefix_length = static_cast<unsigned char>(prefix_length); + route.metric = (metric < 0 ? model.route_metric_default : metric); + route.ipv6 = ipv6; + model.add_routes.push_back(std::move(route)); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_add_route(address, prefix_length, metric, ipv6)); + RC_ASSERT(sut.add_routes.size() == model.add_routes.size() + 1); + const auto &added_route = sut.add_routes.back(); + RC_ASSERT(added_route.address == address); + RC_ASSERT(added_route.prefix_length == prefix_length); + RC_ASSERT(added_route.metric == (metric < 0 ? model.route_metric_default : metric)); + RC_ASSERT(added_route.ipv6 == ipv6); + } + + auto show(std::ostream &os) const -> void override + { + os << "Add Route: " << address << " prefix length: " << prefix_length << " metric: " << metric << " ipv6: " << ipv6; + } +}; + +struct ExcludeRoute final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string address; + unsigned char prefix_length{0}; + int metric{-1}; + std::string gateway; + bool ipv6{false}; + bool net30{false}; + + explicit ExcludeRoute() + : address{*rc::gen::arbitrary<std::string>()}, prefix_length{static_cast<unsigned char>(*rc::gen::arbitrary<int>())}, metric{*rc::gen::arbitrary<int>()}, ipv6{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + TunBuilderCapture::Route route; + route.address = address; + route.prefix_length = static_cast<unsigned char>(prefix_length); + route.metric = metric; + route.ipv6 = ipv6; + model.exclude_routes.push_back(std::move(route)); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_exclude_route(address, prefix_length, metric, ipv6)); + RC_ASSERT(sut.exclude_routes.size() == model.exclude_routes.size() + 1); + const auto &excluded_route = sut.exclude_routes.back(); + RC_ASSERT(excluded_route.address == address); + RC_ASSERT(excluded_route.prefix_length == prefix_length); + RC_ASSERT(excluded_route.metric == metric); + RC_ASSERT(excluded_route.ipv6 == ipv6); + } + + auto show(std::ostream &os) const -> void override + { + os << "Add Exclude Route: " << address << " prefix length: " << prefix_length << " metric: " << metric << " ipv6: " << ipv6; + } +}; + +struct SetDNSOptions final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + DnsOptions options{}; + + explicit SetDNSOptions() + : options{*rc::genDNSOptions()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.dns_options = options; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_dns_options(options)); + RC_ASSERT(sut.dns_options == options); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set DNS Options with " << options.servers.size() << " servers and " + << options.search_domains.size() << " search domains"; + } +}; + +struct SetLayer final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + int layer{}; + + explicit SetLayer() : layer{*rc::gen::elementOf<std::vector<int>>({0, 2, 3})} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.layer = Layer::from_value(layer); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_layer(layer)); + RC_ASSERT(sut.layer.value() == layer); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set Layer to: " << layer; + } +}; + +struct SetMTU final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + int mtu{}; + + explicit SetMTU() : mtu(*rc::gen::arbitrary<int>()) + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.mtu = mtu; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_mtu(mtu)); + RC_ASSERT(sut.mtu == mtu); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set mtu to " << mtu; + } +}; + +struct SetSessionName final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string session_name{}; + + explicit SetSessionName() : session_name(*rc::gen::arbitrary<std::string>()) + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.session_name = session_name; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_session_name(session_name)); + RC_ASSERT(sut.session_name == session_name); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set session name to " << session_name; + } +}; + +struct AddProxyBypass final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string bypass_host{}; + + explicit AddProxyBypass() : bypass_host(*rc::gen::arbitrary<std::string>()) + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + TunBuilderCapture::ProxyBypass proxy_bypass; + proxy_bypass.bypass_host = bypass_host; + model.proxy_bypass.push_back(std::move(proxy_bypass)); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_add_proxy_bypass(bypass_host)); + RC_ASSERT(sut.proxy_bypass.size() == model.proxy_bypass.size() + 1); + const auto &added_bypass_host = sut.proxy_bypass.back(); + RC_ASSERT(added_bypass_host.bypass_host == bypass_host); + } + + auto show(std::ostream &os) const -> void override + { + os << "Add ProxyBypass: " << bypass_host; + } +}; + +struct SetProxyAutoConfigURL final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string proxy_auto_config_url{}; + + explicit SetProxyAutoConfigURL() : proxy_auto_config_url(*rc::gen::arbitrary<std::string>()) + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.proxy_auto_config_url.url = proxy_auto_config_url; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_proxy_auto_config_url(proxy_auto_config_url)); + RC_ASSERT(sut.proxy_auto_config_url.url == proxy_auto_config_url); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set ProxyAutoConfigURL to " << proxy_auto_config_url; + } +}; + +struct SetProxyHTTP final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string host; + int port{0}; + + explicit SetProxyHTTP() + : host{*rc::gen::arbitrary<std::string>()}, port{*rc::gen::arbitrary<int>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.http_proxy.host = host; + model.http_proxy.port = port; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_proxy_http(host, port)); + RC_ASSERT(sut.http_proxy.host == host); + RC_ASSERT(sut.http_proxy.port == port); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set ProxyHTTP to host: " << host << " port: " << port; + } +}; + +struct SetProxyHTTPS final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string host; + int port{0}; + + explicit SetProxyHTTPS() + : host{*rc::gen::arbitrary<std::string>()}, port{*rc::gen::arbitrary<int>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.https_proxy.host = host; + model.https_proxy.port = port; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_proxy_https(host, port)); + RC_ASSERT(sut.https_proxy.host == host); + RC_ASSERT(sut.https_proxy.port == port); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set ProxyHTTPS to host: " << host << " port: " << port; + } +}; + +struct AddWINSServer final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + std::string address{}; + + explicit AddWINSServer() : address(*rc::gen::arbitrary<std::string>()) + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + TunBuilderCapture::WINSServer wins; + wins.address = address; + model.wins_servers.push_back(std::move(wins)); + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_add_wins_server(address)); + RC_ASSERT(sut.wins_servers.size() == model.wins_servers.size() + 1); + RC_ASSERT(sut.wins_servers.back().address == address); + } + + auto show(std::ostream &os) const -> void override + { + os << "Add WINSServer: " << address; + } +}; + +struct SetAllowFamily final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + int af{}; + bool allow{false}; + + explicit SetAllowFamily() + : af(*rc::gen::elementOf<std::vector<int>>({AF_INET, AF_INET6})), + allow{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + if (af == AF_INET) + { + model.block_ipv4 = !allow; + } + else if (af == AF_INET6) + { + model.block_ipv6 = !allow; + } + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_allow_family(af, allow)); + if (af == AF_INET) + { + RC_ASSERT(sut.block_ipv4 == !allow); + } + else if (af == AF_INET6) + { + RC_ASSERT(sut.block_ipv6 == !allow); + } + } + + auto show(std::ostream &os) const -> void override + { + os << "Set allow local family to " << af << allow; + } +}; + +struct SetAllowLocalDNS final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + bool allow{false}; + + explicit SetAllowLocalDNS() + : allow{*rc::gen::arbitrary<bool>()} + { + } + + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.block_outside_dns = !allow; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + RC_ASSERT(sut.tun_builder_set_allow_local_dns(allow)); + RC_ASSERT(sut.block_outside_dns == !allow); + } + + auto show(std::ostream &os) const -> void override + { + os << "Set allow local DNS to " << !allow; + } +}; + +struct ResetTunnelAddresses final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.tunnel_addresses.clear(); + model.tunnel_address_index_ipv4 = -1; + model.tunnel_address_index_ipv6 = -1; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + sut.reset_tunnel_addresses(); + RC_ASSERT(sut.tunnel_addresses.empty()); + RC_ASSERT(sut.tunnel_address_index_ipv4 == -1); + RC_ASSERT(sut.tunnel_address_index_ipv6 == -1); + } + + auto show(std::ostream &os) const -> void override + { + os << "Reset Tunnel Addresses"; + } +}; + +struct ResetDNSOptions final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + auto apply(TunBuilderCaptureModel &model) const -> void override + { + model.dns_options = {}; + } + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + sut.reset_dns_options(); + const DnsOptions dns_options{}; + RC_ASSERT(sut.dns_options == dns_options); + } + + auto show(std::ostream &os) const -> void override + { + os << "Reset DNS Options"; + } +}; + +struct VPN_IPv4 final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + if (model.tunnel_address_index_ipv4 >= 0) + { + const auto &ipv4_address = sut.vpn_ipv4(); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].address == ipv4_address->address); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].prefix_length == ipv4_address->prefix_length); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].metric == ipv4_address->metric); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].gateway == ipv4_address->gateway); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].ipv6 == ipv4_address->ipv6); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].net30 == ipv4_address->net30); + } + else + { + RC_ASSERT(sut.vpn_ipv4() == nullptr); + } + } + + auto show(std::ostream &os) const -> void override + { + os << "VPN IPv4"; + } +}; + +struct VPN_IPv6 final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + if (model.tunnel_address_index_ipv6 >= 0) + { + const auto &ipv6_address = sut.vpn_ipv6(); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].address == ipv6_address->address); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].prefix_length == ipv6_address->prefix_length); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].metric == ipv6_address->metric); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].gateway == ipv6_address->gateway); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].ipv6 == ipv6_address->ipv6); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].net30 == ipv6_address->net30); + } + else + { + RC_ASSERT(sut.vpn_ipv6() == nullptr); + } + } + + auto show(std::ostream &os) const -> void override + { + os << "VPN IPv6"; + } +}; + +struct VPN_IP final : rc::state::Command<TunBuilderCaptureModel, TunBuilderCapture> +{ + IP::Addr::Version version{}; + + explicit VPN_IP() : version{*rc::gen::elementOf<std::vector<IP::Addr::Version>>({IP::Addr::Version::V4, IP::Addr::Version::V6, IP::Addr::Version::UNSPEC})} {}; + + auto run(const TunBuilderCaptureModel &model, TunBuilderCapture &sut) const -> void override + { + const auto &ip_address = sut.vpn_ip(version); + if (version == IP::Addr::Version::UNSPEC) + { + RC_ASSERT(ip_address == nullptr); + } + else if (version == IP::Addr::Version::V4 && model.tunnel_address_index_ipv4 >= 0) + { + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].address == ip_address->address); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].prefix_length == ip_address->prefix_length); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].metric == ip_address->metric); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].gateway == ip_address->gateway); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].ipv6 == ip_address->ipv6); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv4].net30 == ip_address->net30); + } + else if (version == IP::Addr::Version::V6 && model.tunnel_address_index_ipv6 >= 0) + { + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].address == ip_address->address); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].prefix_length == ip_address->prefix_length); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].metric == ip_address->metric); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].gateway == ip_address->gateway); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].ipv6 == ip_address->ipv6); + RC_ASSERT(model.tunnel_addresses[model.tunnel_address_index_ipv6].net30 == ip_address->net30); + } + } + + auto show(std::ostream &os) const -> void override + { + os << "VPN IP"; + } +}; + +RC_GTEST_PROP(TunBuilderCapture, Stateful, ()) +{ + const TunBuilderCaptureModel model{}; + TunBuilderCapture sut{}; + check(model, sut, rc::state::gen::execOneOfWithArgs<SetRemoteAddress, AddAddress, RerouteGW, SetRouteMetricDefault, AddRoute, ExcludeRoute, SetDNSOptions, SetLayer, SetMTU, SetSessionName, AddProxyBypass, SetProxyAutoConfigURL, SetProxyHTTP, SetProxyHTTPS, AddWINSServer, SetAllowFamily, SetAllowLocalDNS, ResetTunnelAddresses, ResetDNSOptions, VPN_IPv4, VPN_IPv6, VPN_IP>()); +} diff --git a/test/unittests/test_clamp_typerange.cpp b/test/unittests/test_clamp_typerange.cpp index 7aff71d63..037e0a729 100644 --- a/test/unittests/test_clamp_typerange.cpp +++ b/test/unittests/test_clamp_typerange.cpp @@ -25,79 +25,79 @@ using namespace openvpn::numeric_util; /* ============================================================================================================= */ -TEST(clamp_to_typerange, same_type_nocast1) +TEST(ClampToTyperange, SameTypeNocast1) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_to_typerange<int32_t>(i32); EXPECT_EQ(result, i32); } -TEST(clamp_to_typerange, sign_mismatch_32_1) +TEST(ClampToTyperange, SignMismatch321) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_to_typerange<uint32_t>(i32); EXPECT_EQ(result, 0); } -TEST(clamp_to_typerange, sign_mismatch_32_2) +TEST(ClampToTyperange, SignMismatch322) { - uint32_t u32 = std::numeric_limits<uint32_t>::max(); + const uint32_t u32 = std::numeric_limits<uint32_t>::max(); auto result = clamp_to_typerange<int32_t>(u32); EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); } -TEST(clamp_to_typerange, sign_mismatch_32_3) +TEST(ClampToTyperange, SignMismatch323) { - uint32_t u32 = 0; + const uint32_t u32 = 0; auto result = clamp_to_typerange<int32_t>(u32); EXPECT_EQ(result, 0); } -TEST(clamp_to_typerange, sign_mismatch_32_4) +TEST(ClampToTyperange, SignMismatch324) { - uint32_t u32 = 42; + const uint32_t u32 = 42; auto result = clamp_to_typerange<int32_t>(u32); EXPECT_EQ(result, 42); } -TEST(clamp_to_typerange, sign_mismatch_32_5) +TEST(ClampToTyperange, SignMismatch325) { - uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); + const uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); auto result = clamp_to_typerange<int32_t>(u32); EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); } -TEST(clamp_to_typerange, sign_mismatch_32_6) +TEST(ClampToTyperange, SignMismatch326) { - int32_t s32 = std::numeric_limits<int32_t>::max(); + const int32_t s32 = std::numeric_limits<int32_t>::max(); auto result = clamp_to_typerange<uint8_t>(s32); EXPECT_EQ(result, std::numeric_limits<uint8_t>::max()); } -TEST(clamp_to_typerange, sign_mismatch_32_7) +TEST(ClampToTyperange, SignMismatch327) { - int32_t s32 = 42; + const int32_t s32 = 42; auto result = clamp_to_typerange<uint8_t>(s32); EXPECT_EQ(result, 42); } -TEST(clamp_to_typerange, s_range_mismatch_16_64_1) +TEST(ClampToTyperange, SRangeMismatch16641) { - int64_t s64 = std::numeric_limits<int64_t>::max(); + const int64_t s64 = std::numeric_limits<int64_t>::max(); auto result = clamp_to_typerange<int16_t>(s64); EXPECT_EQ(result, std::numeric_limits<int16_t>::max()); } -TEST(clamp_to_typerange, s_range_match_16_64_1) +TEST(ClampToTyperange, SRangeMatch16641) { - int64_t s64 = 0; + const int64_t s64 = 0; auto result = clamp_to_typerange<int16_t>(s64); EXPECT_EQ(result, 0); } -TEST(clamp_to_typerange, u_range_mismatch_16_64_1) +TEST(ClampToTyperange, URangeMismatch16641) { - uint64_t u64 = std::numeric_limits<uint64_t>::max(); + const uint64_t u64 = std::numeric_limits<uint64_t>::max(); auto result = clamp_to_typerange<uint16_t>(u64); EXPECT_EQ(result, std::numeric_limits<uint16_t>::max()); } @@ -108,79 +108,79 @@ TEST(clamp_to_typerange, u_range_mismatch_16_64_1) /* ============================================================================================================= */ -TEST(clamp_to_default, same_type_nocast1) +TEST(ClampToDefault, SameTypeNocast1) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_to_default<int32_t>(i32, 0); EXPECT_EQ(result, i32); } -TEST(clamp_to_default, sign_mismatch_32_1) +TEST(ClampToDefault, SignMismatch321) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_to_default<uint32_t>(i32, 42); EXPECT_EQ(result, 42); } -TEST(clamp_to_default, sign_mismatch_32_2) +TEST(ClampToDefault, SignMismatch322) { - uint32_t u32 = std::numeric_limits<uint32_t>::max(); + const uint32_t u32 = std::numeric_limits<uint32_t>::max(); auto result = clamp_to_default<int32_t>(u32, 1); EXPECT_EQ(result, 1); } -TEST(clamp_to_default, sign_mismatch_32_3) +TEST(ClampToDefault, SignMismatch323) { - uint32_t u32 = 0; + const uint32_t u32 = 0; auto result = clamp_to_default<int32_t>(u32, 42); EXPECT_EQ(result, 0); } -TEST(clamp_to_default, sign_mismatch_32_4) +TEST(ClampToDefault, SignMismatch324) { - uint32_t u32 = 42; + const uint32_t u32 = 42; auto result = clamp_to_default<int32_t>(u32, 0); EXPECT_EQ(result, 42); } -TEST(clamp_to_default, sign_mismatch_32_5) +TEST(ClampToDefault, SignMismatch325) { - uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); + const uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); auto result = clamp_to_default<int32_t>(u32, -1); EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); } -TEST(clamp_to_default, sign_mismatch_32_6) +TEST(ClampToDefault, SignMismatch326) { - int32_t s32 = std::numeric_limits<int32_t>::max(); + const int32_t s32 = std::numeric_limits<int32_t>::max(); auto result = clamp_to_default<uint8_t>(s32, 0); EXPECT_EQ(result, 0); } -TEST(clamp_to_default, sign_mismatch_32_7) +TEST(ClampToDefault, SignMismatch327) { - int32_t s32 = 42; + const int32_t s32 = 42; auto result = clamp_to_default<uint8_t>(s32, -1); EXPECT_EQ(result, 42); } -TEST(clamp_to_default, s_range_mismatch_16_64_1) +TEST(ClampToDefault, SRangeMismatch16641) { - int64_t s64 = std::numeric_limits<int64_t>::max(); + const int64_t s64 = std::numeric_limits<int64_t>::max(); auto result = clamp_to_default<int16_t>(s64, 0); EXPECT_EQ(result, 0); } -TEST(clamp_to_default, s_range_match_16_64_1) +TEST(ClampToDefault, SRangeMatch16641) { - int64_t s64 = 0; + const int64_t s64 = 0; auto result = clamp_to_default<int16_t>(s64, -1); EXPECT_EQ(result, 0); } -TEST(clamp_to_default, u_range_mismatch_16_64_1) +TEST(ClampToDefault, URangeMismatch16641) { - uint64_t u64 = std::numeric_limits<uint64_t>::max(); + const uint64_t u64 = std::numeric_limits<uint64_t>::max(); auto result = clamp_to_default<uint16_t>(u64, 42); EXPECT_EQ(result, 42); } @@ -190,89 +190,89 @@ TEST(clamp_to_default, u_range_mismatch_16_64_1) /* ============================================================================================================= */ -TEST(clamp_notify, same_type_nocast1) +TEST(ClampNotify, SameTypeNocast1) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_notify<int32_t>(i32, [](int32_t inVal) { return 0; }); EXPECT_EQ(result, i32); } -TEST(clamp_notify, sign_mismatch_32_1) +TEST(ClampNotify, SignMismatch321) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = clamp_notify<uint32_t>(i32, [](int32_t inVal) { return 42; }); EXPECT_EQ(result, 42); } -TEST(clamp_notify, sign_mismatch_32_2) +TEST(ClampNotify, SignMismatch322) { - uint32_t u32 = std::numeric_limits<uint32_t>::max(); + const uint32_t u32 = std::numeric_limits<uint32_t>::max(); auto result = clamp_notify<int32_t>(u32, [](uint32_t inVal) { return 1; }); EXPECT_EQ(result, 1); } -TEST(clamp_notify, sign_mismatch_32_3) +TEST(ClampNotify, SignMismatch323) { - uint32_t u32 = 0; + const uint32_t u32 = 0; auto result = clamp_notify<int32_t>(u32, [](uint32_t inVal) { return 42; }); EXPECT_EQ(result, 0); } -TEST(clamp_notify, sign_mismatch_32_4) +TEST(ClampNotify, SignMismatch324) { - uint32_t u32 = 42; + const uint32_t u32 = 42; auto result = clamp_notify<int32_t>(u32, [](uint32_t inVal) { return 0; }); EXPECT_EQ(result, 42); } -TEST(clamp_notify, sign_mismatch_32_5) +TEST(ClampNotify, SignMismatch325) { - uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); + const uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); auto result = clamp_notify<int32_t>(u32, [](uint32_t inVal) { return -1; }); EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); } -TEST(clamp_notify, sign_mismatch_32_6) +TEST(ClampNotify, SignMismatch326) { - int32_t s32 = std::numeric_limits<int32_t>::max(); + const int32_t s32 = std::numeric_limits<int32_t>::max(); auto result = clamp_notify<uint8_t>(s32, [](int32_t inVal) -> uint8_t { return 0; }); EXPECT_EQ(result, 0); } -TEST(clamp_notify, sign_mismatch_32_7) +TEST(ClampNotify, SignMismatch327) { - int32_t s32 = 42; + const int32_t s32 = 42; auto result = clamp_notify<uint8_t>(s32, [](int32_t inVal) -> uint8_t { return 0; }); EXPECT_EQ(result, 42); } -TEST(clamp_notify, s_range_mismatch_16_64_1) +TEST(ClampNotify, SRangeMismatch16641) { - int64_t s64 = std::numeric_limits<int64_t>::max(); + const int64_t s64 = std::numeric_limits<int64_t>::max(); auto result = clamp_notify<int16_t>(s64, [](int64_t inVal) -> int16_t { return 0; }); EXPECT_EQ(result, 0); } -TEST(clamp_notify, s_range_match_16_64_1) +TEST(ClampNotify, SRangeMatch16641) { - int64_t s64 = 0; + const int64_t s64 = 0; auto result = clamp_notify<int16_t>(s64, [](int64_t inVal) -> int16_t { return -1; }); EXPECT_EQ(result, 0); } -TEST(clamp_notify, u_range_mismatch_16_64_1) +TEST(ClampNotify, URangeMismatch16641) { - uint64_t u64 = std::numeric_limits<uint64_t>::max(); + const uint64_t u64 = std::numeric_limits<uint64_t>::max(); auto result = clamp_notify<uint16_t>(u64, [](uint64_t inVal) -> uint16_t { return 42; }); EXPECT_EQ(result, 42); diff --git a/test/unittests/test_cleanup.cpp b/test/unittests/test_cleanup.cpp index 5756d68cf..90cb06c2e 100644 --- a/test/unittests/test_cleanup.cpp +++ b/test/unittests/test_cleanup.cpp @@ -1,17 +1,15 @@ #include "test_common.hpp" -#include <iostream> -#include <memory> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> #include <openvpn/common/cleanup.hpp> +#include <memory> +#include <stdexcept> +#include <vector> + using namespace openvpn; -TEST(misc, cleanup) +TEST(Misc, Cleanup) { - bool ran_cleanup = false; { auto c = Cleanup([&]() @@ -21,3 +19,272 @@ TEST(misc, cleanup) } ASSERT_TRUE(ran_cleanup) << "cleanup didn't run as expected"; } + +TEST(misc, cleanup_basic_execution) +{ + int counter = 0; + { + auto c = Cleanup([&counter]() + { ++counter; }); + } + ASSERT_EQ(counter, 1) << "cleanup should execute once on scope exit"; +} + +TEST(misc, cleanup_multiple_guards) +{ + std::vector<int> execution_order; + { + auto c1 = Cleanup([&]() + { execution_order.push_back(1); }); + auto c2 = Cleanup([&]() + { execution_order.push_back(2); }); + auto c3 = Cleanup([&]() + { execution_order.push_back(3); }); + } + ASSERT_EQ(execution_order.size(), 3); + // Destructors run in reverse order + ASSERT_EQ(execution_order[0], 3); + ASSERT_EQ(execution_order[1], 2); + ASSERT_EQ(execution_order[2], 1); +} + +TEST(misc, cleanup_dismiss) +{ + int counter = 0; + { + auto c = Cleanup([&counter]() + { ++counter; }); + c.dismiss(); + } + ASSERT_EQ(counter, 0) << "cleanup should not execute after dismiss()"; +} + +TEST(misc, cleanup_dismiss_idempotent) +{ + int counter = 0; + { + auto c = Cleanup([&counter]() + { ++counter; }); + c.dismiss(); + c.dismiss(); // Should be safe to call multiple times + c.dismiss(); + } + ASSERT_EQ(counter, 0) << "multiple dismiss() calls should be safe"; +} + +TEST(misc, cleanup_release) +{ + int counter = 0; + std::optional<std::function<void()>> released; + { + auto c = Cleanup([&counter]() + { ++counter; }); + released = c.release(); + } + ASSERT_EQ(counter, 0) << "cleanup should not execute after release()"; + ASSERT_TRUE(released.has_value()) << "release() should return the callable"; + + // Manually invoke the released callable + std::invoke(*released); + ASSERT_EQ(counter, 1) << "released callable should still be invocable"; +} + +TEST(misc, cleanup_release_empty) +{ + int counter = 0; + std::optional<std::function<void()>> released; + { + auto c = Cleanup([&counter]() + { ++counter; }); + c.dismiss(); + released = c.release(); + } + ASSERT_EQ(counter, 0) << "cleanup should not execute"; + ASSERT_FALSE(released.has_value()) << "release() after dismiss() should return empty optional"; +} + +TEST(misc, cleanup_move_constructor) +{ + int counter = 0; + { + auto c1 = Cleanup([&counter]() + { ++counter; }); + auto c2 = std::move(c1); + // c1 is now moved-from, c2 owns the cleanup + } + ASSERT_EQ(counter, 1) << "cleanup should execute once from moved-to object"; +} + +TEST(misc, cleanup_move_constructor_no_double_execute) +{ + int counter = 0; + { + auto c1 = Cleanup([&counter]() + { ++counter; }); + { + auto c2 = std::move(c1); + } // c2 destroyed here, should execute + } // c1 destroyed here, should NOT execute + ASSERT_EQ(counter, 1) << "cleanup should execute only once after move"; +} + +TEST(misc, cleanup_exception_swallowed) +{ + bool cleanup_started = false; + try + { + auto c = Cleanup([&]() + { + cleanup_started = true; + throw std::runtime_error("exception in cleanup"); }); + // Destructor runs here when c goes out of scope + } + catch (...) + { + // Exception should NOT escape destructor + FAIL() << "Exception should be swallowed by noexcept destructor"; + } + ASSERT_TRUE(cleanup_started) << "cleanup should start executing"; +} + +TEST(misc, cleanup_noexcept_destructor) +{ + // Verify destructor is noexcept + auto c = Cleanup([]() {}); + static_assert(std::is_nothrow_destructible_v<decltype(c)>, "Destructor should be noexcept"); +} + +TEST(misc, cleanup_with_mutable_lambda) +{ + int counter = 0; + { + auto c = Cleanup([&counter, call_count = 0]() mutable + { + ++call_count; + counter = call_count; }); + } + ASSERT_EQ(counter, 1) << "mutable lambda should work correctly"; +} + +TEST(misc, cleanup_with_captured_unique_ptr) +{ + bool deleted = false; + struct Deleter + { + bool *flag; + void operator()(int *p) + { + *flag = true; + delete p; + } + }; + { + std::unique_ptr<int, Deleter> ptr(new int(42), Deleter{&deleted}); + auto c = Cleanup([p = std::move(ptr)]() mutable + { p.reset(); }); + } + ASSERT_TRUE(deleted) << "unique_ptr should be properly moved and deleted"; +} + +TEST(misc, cleanup_concept_constraint) +{ + // Should compile with invocable types + auto c1 = Cleanup([]() {}); + auto c2 = Cleanup(std::function<void()>([]() {})); + + struct Callable + { + void operator()() const + { + } + }; + auto c3 = Cleanup(Callable{}); + + // Should NOT compile with non-invocable types (uncomment to test) + // auto c4 = Cleanup(42); // Error: does not satisfy std::invocable +} + +TEST(misc, cleanup_dismiss_then_destroy) +{ + int counter = 0; + { + auto c = Cleanup([&counter]() + { ++counter; }); + c.dismiss(); + // Additional operations after dismiss + ASSERT_EQ(counter, 0); + } + ASSERT_EQ(counter, 0) << "dismissed cleanup should not execute on destruction"; +} + +TEST(misc, cleanup_factory_function) +{ + int counter = 0; + { + auto c = Cleanup([&counter]() + { ++counter; }); + // Just verify it compiles and works - type checking is implementation detail + } + ASSERT_EQ(counter, 1); +} + +TEST(misc, cleanup_return_from_function) +{ + int counter = 0; + auto make_cleanup = [&counter]() + { + return Cleanup([&counter]() + { ++counter; }); + }; + { + auto c = make_cleanup(); + } + ASSERT_EQ(counter, 1) << "cleanup returned from function should work"; +} + +TEST(misc, cleanup_nested_scopes) +{ + std::vector<int> order; + { + auto c1 = Cleanup([&]() + { order.push_back(1); }); + { + auto c2 = Cleanup([&]() + { order.push_back(2); }); + { + auto c3 = Cleanup([&]() + { order.push_back(3); }); + } + } + } + ASSERT_EQ(order.size(), 3); + ASSERT_EQ(order[0], 3); + ASSERT_EQ(order[1], 2); + ASSERT_EQ(order[2], 1); +} + +TEST(misc, cleanup_conditional_dismiss) +{ + int counter = 0; + bool should_cleanup = false; + { + auto c = Cleanup([&counter]() + { ++counter; }); + if (!should_cleanup) + { + c.dismiss(); + } + } + ASSERT_EQ(counter, 0); + + should_cleanup = true; + { + auto c = Cleanup([&counter]() + { ++counter; }); + if (!should_cleanup) + { + c.dismiss(); + } + } + ASSERT_EQ(counter, 1); +} diff --git a/test/unittests/test_cliopt.cpp b/test/unittests/test_cliopt.cpp index 8f2c70596..1da386ab6 100644 --- a/test/unittests/test_cliopt.cpp +++ b/test/unittests/test_cliopt.cpp @@ -41,7 +41,7 @@ std::string minimalConfig = certconfig + "\n" class ValidConfigs : public testing::TestWithParam<std::string> { }; -typedef std::pair<std::string, std::string> config_error; +using config_error = std::pair<std::string, std::string>; class InvalidConfigs : public testing::TestWithParam<config_error> { }; @@ -53,20 +53,20 @@ void load_client_config(const std::string &config_content) config.clientconf.dco = true; config.proto_context_options.reset(new ProtoContextCompressionOptions()); - ClientAPI::OpenVPNClientHelper client_helper; - ParseClientConfig conf = ParseClientConfig::parse(config_content); + const ClientAPI::OpenVPNClientHelper client_helper; + const ParseClientConfig conf = ParseClientConfig::parse(config_content); auto parsed_config = ParseClientConfig::parse(config_content, nullptr, options); - ClientOptions cliopt(options, config); + const ClientOptions cliopt(options, config); } -TEST_P(ValidConfigs, valid_config) +TEST_P(ValidConfigs, ValidConfig) { load_client_config(GetParam()); } -TEST_P(InvalidConfigs, config_throws_option_error) +TEST_P(InvalidConfigs, ConfigThrowsOptionError) { OVPN_EXPECT_THROW( load_client_config(GetParam().first), @@ -74,9 +74,9 @@ TEST_P(InvalidConfigs, config_throws_option_error) GetParam().second); } -TEST(config, missingRequiredOption) +TEST(Config, MissingRequiredOption) { - ParseClientConfig conf = ParseClientConfig::parse("mode server"); + const ParseClientConfig conf = ParseClientConfig::parse("mode server"); EXPECT_EQ(conf.error(), true); EXPECT_TRUE(conf.message().find("option_error: remote option not specified") != std::string::npos); } @@ -93,7 +93,7 @@ INSTANTIATE_TEST_SUITE_P( config_error{minimalConfig + "key-method 1", "Only 'key-method 2' is supported"}, config_error{minimalConfig + "fragment", "sorry, 'fragment' directive is not supported"})); -TEST(config, parse_unknown_option) +TEST(Config, ParseUnknownOption) { OVPN_EXPECT_THROW( load_client_config(minimalConfig + "bikeshed-color green"), @@ -116,7 +116,7 @@ INSTANTIATE_TEST_SUITE_P( minimalConfig + "tun-ipv6\n", minimalConfig + "opt-verify\n")); -TEST(config, parse_management) +TEST(Config, ParseManagement) { OVPN_EXPECT_THROW( load_client_config(minimalConfig + "management-is-blue"), @@ -129,7 +129,7 @@ TEST(config, parse_management) "OpenVPN management interface is not supported by this client"); } -TEST(config, duplicate_options_sets) +TEST(Config, DuplicateOptionsSets) { /* Do the whole dance to get a ClientOption object to access the list */ OptionList options; @@ -137,15 +137,15 @@ TEST(config, duplicate_options_sets) config.clientconf.dco = false; config.proto_context_options = new ProtoContextCompressionOptions(); - ClientAPI::OpenVPNClientHelper client_helper; + const ClientAPI::OpenVPNClientHelper client_helper; - ParseClientConfig conf = ParseClientConfig::parse(minimalConfig); + const ParseClientConfig conf = ParseClientConfig::parse(minimalConfig); auto parsed_config = ParseClientConfig::parse(minimalConfig, nullptr, options); - ClientOptions cliopt(options, config); + const ClientOptions cliopt(options, config); - std::vector<std::unordered_set<std::string>> allsets = { + const std::vector<std::unordered_set<std::string>> allsets = { cliopt.settings_feature_not_implemented_fatal, cliopt.settings_feature_not_implemented_warn, cliopt.settings_ignoreSilently, @@ -163,14 +163,14 @@ TEST(config, duplicate_options_sets) { /* Use an expection instead of an assert to get the name of the option * that is a duplicate */ - if (!(allOptions.find(optname) == allOptions.end())) + if (allOptions.contains(optname)) throw std::runtime_error("duplicate element: " + optname); allOptions.insert(optname); } } } -TEST(config, dco_compatibility) +TEST(Config, DcoCompatibility) { for (auto optname : ClientOptions::dco_incompatible_opts) { @@ -195,7 +195,7 @@ TEST(config, dco_compatibility) } } -TEST(config, server_cert_in_eval) +TEST(Config, ServerCertInEval) { ClientAPI::Config api_config; api_config.content = minimalConfig; @@ -207,10 +207,10 @@ TEST(config, server_cert_in_eval) } -TEST(config, server_options_present_in_error_msg) +TEST(Config, ServerOptionsPresentInErrorMsg) { - std::vector<std::string> server_options = {"server 10.0.0.0 255.255.255.0", - "push \"foo bar\""}; + const std::vector<std::string> server_options = {"server 10.0.0.0 255.255.255.0", + "push \"foo bar\""}; for (auto &option : server_options) { @@ -224,9 +224,9 @@ TEST(config, server_options_present_in_error_msg) } } -TEST(config, unknown_options_present_in_error_msg) +TEST(Config, UnknownOptionsPresentInErrorMsg) { - std::vector<std::string> server_options = {"make-a-lot-of-noise", "water-the-plants"}; + const std::vector<std::string> server_options = {"make-a-lot-of-noise", "water-the-plants"}; for (auto &option : server_options) { @@ -240,7 +240,7 @@ TEST(config, unknown_options_present_in_error_msg) } } -TEST(config, multiple_option_errors) +TEST(Config, MultipleOptionErrors) { std::ostringstream os; os << "OpenVPN management interface is not supported by this client: management\n"; @@ -274,7 +274,7 @@ INSTANTIATE_TEST_SUITE_P( config_error{certconfig + "\nremote 1.2.3.4\npull\n", "option_error: Neither 'client' nor both 'tls-client' and 'pull' options declared. OpenVPN3 client only supports --client mode."})); -TEST(config, meta_option_in_content) +TEST(Config, MetaOptionInContent) { OptionList options; auto cfg = minimalConfig + "\n# OVPN_ACCESS_SERVER_AAA=BBB"; @@ -287,7 +287,7 @@ TEST(config, meta_option_in_content) ClientOptions::Config config; config.clientconf.dco = true; config.proto_context_options.reset(new ProtoContextCompressionOptions()); - ClientOptions cliopt(options, config); + const ClientOptions cliopt(options, config); auto opt = options.get("AAA"); ASSERT_TRUE(opt.meta()); diff --git a/test/unittests/test_comp.cpp b/test/unittests/test_comp.cpp index 4fb7f3145..b1ca11791 100644 --- a/test/unittests/test_comp.cpp +++ b/test/unittests/test_comp.cpp @@ -52,10 +52,10 @@ using namespace openvpn; Frame::Ptr frame_init(const size_t payload) { - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; + constexpr size_t headroom = 512; + constexpr size_t tailroom = 512; + constexpr size_t align_block = 16; + constexpr BufferFlags buffer_flags = BufAllocFlags::NO_FLAGS; Frame::Ptr frame(new Frame(Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags))); frame->standardize_capacity(~0); @@ -65,7 +65,7 @@ Frame::Ptr frame_init(const size_t payload) class MySessionStats : public SessionStats { public: - typedef RCPtr<MySessionStats> Ptr; + using Ptr = RCPtr<MySessionStats>; MySessionStats() { @@ -82,8 +82,7 @@ class MySessionStats : public SessionStats { if (type < Error::N_ERRORS) return errors[type]; - else - return 0; + return 0; } private: @@ -199,7 +198,7 @@ void runTest(comppair alg, bool verbose = false) switch (alg) { -#if defined(HAVE_LZO) +#ifdef HAVE_LZO case comppair::lzoasym: compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false)); decompress.reset(new CompressLZOAsym(frame, stats, SUPPORT_SWAP, false)); @@ -211,13 +210,13 @@ void runTest(comppair alg, bool verbose = false) break; #endif -#if defined(HAVE_LZ4) +#ifdef HAVE_LZ4 case comppair::lz4: compress.reset(new CompressLZ4(frame, stats, false)); decompress = compress; break; #endif -#if defined(HAVE_SNAPPY) +#ifdef HAVE_SNAPPY case comppair::snappy: compress.reset(new CompressSnappy(frame, stats, false)); decompress = compress; @@ -237,29 +236,29 @@ void runTest(comppair alg, bool verbose = false) << " bytes=" << bytes << " comp-bytes=" << compress_bytes << " comp-ratio=" << (bytes ? static_cast<float>(compress_bytes) / static_cast<float>(bytes) : 0.0) - << std::endl; + << '\n'; } namespace unittests { -#if defined(HAVE_SNAPPY) -TEST(Compression, snappy) +#ifdef HAVE_SNAPPY +TEST(Compression, Snappy) { runTest(comppair::snappy); } #endif -#if defined(HAVE_LZO) -TEST(Compression, lzo) +#ifdef HAVE_LZO +TEST(Compression, Lzo) { runTest(comppair::lzo); } -TEST(Compression, lzoasym) +TEST(Compression, Lzoasym) { runTest(comppair::lzoasym); } #endif -#if defined(HAVE_LZ4) -TEST(Compression, lz4) +#ifdef HAVE_LZ4 +TEST(Compression, Lz4) { runTest(comppair::lz4); } diff --git a/test/unittests/test_continuation.cpp b/test/unittests/test_continuation.cpp index 90fd8263e..26a4d95de 100644 --- a/test/unittests/test_continuation.cpp +++ b/test/unittests/test_continuation.cpp @@ -53,20 +53,20 @@ enum PCMode static std::string get_csv(Buffer buf, const PCMode pc_mode, const std::string &prefix) { // verify PUSH_REPLY then remove it - if (!string::starts_with(buf, prefix + ',')) + if (!buf_to_string(buf).starts_with(prefix + ',')) throw Exception("expected that buffer would begin with " + prefix); buf.advance(prefix.length() + 1); // possibly remove push-continuation options from tail of buffer if (pc_mode == PC_1) { - if (!string::ends_with(buf, ",push-continuation 1")) + if (!buf_to_string(buf).ends_with(",push-continuation 1")) throw Exception("expected that buffer would end with push-continuation 1"); buf.set_size(buf.size() - 20); } else if (pc_mode == PC_2) { - if (!string::ends_with(buf, ",push-continuation 2")) + if (!buf_to_string(buf).ends_with(",push-continuation 2")) throw Exception("expected that buffer would end with push-continuation 2"); buf.set_size(buf.size() - 20); } @@ -78,10 +78,9 @@ static std::string get_csv_from_frag(Buffer buf, const size_t index, const size_ { if (size < 2) return get_csv(std::move(buf), NO_PC, prefix); - else if (index == size - 1) + if (index == size - 1) return get_csv(std::move(buf), PC_1, prefix); - else - return get_csv(std::move(buf), PC_2, prefix); + return get_csv(std::move(buf), PC_2, prefix); } static std::string random_term(RandomAPI &prng) @@ -149,9 +148,8 @@ static void test_roundtrip(const OptionList &opt_orig, const std::string &prefix } // remove client-side push-continuation directives before comparison - cc.erase(std::remove_if(cc.begin(), cc.end(), [](const Option &o) - { return o.size() >= 1 && o.ref(0) == "push-continuation"; }), - cc.end()); + std::erase_if(cc, [](const Option &o) + { return !o.empty() && o.ref(0) == "push-continuation"; }); require_equal(opt_orig, cc, "TEST_ROUNDTRIP #3"); // defragment back to original form @@ -216,27 +214,27 @@ static void test_prefix_random(const std::string &prefix) } } -TEST(continuation, test_random_push_reply) +TEST(Continuation, TestRandomPushReply) { test_prefix_random("PUSH_REPLY"); } -TEST(continuation, test_random_push_update) +TEST(Continuation, TestRandomPushUpdate) { test_prefix_random("PUSH_UPDATE"); } -TEST(continuation, test_fragment_push_reply) +TEST(Continuation, TestFragmentPushReply) { test_prefix_fragment("PUSH_REPLY"); } -TEST(continuation, test_fragment_push_update) +TEST(Continuation, TestFragmentPushUpdate) { test_prefix_fragment("PUSH_UPDATE"); } -TEST(continuation, push_update_add) +TEST(Continuation, PushUpdateAdd) { OptionListContinuation cc; @@ -253,7 +251,7 @@ TEST(continuation, push_update_add) ASSERT_EQ(cc.size(), 5); } -TEST(continuation, push_update_add_unsupported) +TEST(Continuation, PushUpdateAddUnsupported) { OptionListContinuation cc; @@ -274,7 +272,7 @@ TEST(continuation, push_update_add_unsupported) ASSERT_EQ(cc.size(), 5); } -TEST(continuation, push_update_remove) +TEST(Continuation, PushUpdateRemove) { OptionListContinuation cc; @@ -289,7 +287,7 @@ TEST(continuation, push_update_remove) cc.reset_completion(); } -TEST(continuation, push_update_add_multiple) +TEST(Continuation, PushUpdateAddMultiple) { OptionListContinuation cc; diff --git a/test/unittests/test_cpu_time.cpp b/test/unittests/test_cpu_time.cpp index 521ddec1a..c23f5f9f6 100644 --- a/test/unittests/test_cpu_time.cpp +++ b/test/unittests/test_cpu_time.cpp @@ -38,17 +38,17 @@ #include <algorithm> #ifdef DEBUG -#define DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) \ - std::cout << msg << std::endl \ - << "start = " << std::to_string(st) << std::endl \ - << "end = " << std::to_string(en) << std::endl \ - << "runtime = " << std::to_string(rt) << std::endl \ - << "chk_start = " << std::to_string(chst) << std::endl \ - << "chk_end = " << std::to_string(chen) << std::endl \ - << "chk_runtime = " << std::to_string(chrt) << std::endl \ - << "measurement difference = " \ - << std::to_string(md) << std::endl \ - << "--------------------------------------" << std::endl +#define DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) \ + std::cout << msg << "\n" \ + << "start = " << std::to_string(st) << "\n" \ + << "end = " << std::to_string(en) << "\n" \ + << "runtime = " << std::to_string(rt) << "\n" \ + << "chk_start = " << std::to_string(chst) << "\n" \ + << "chk_end = " << std::to_string(chen) << "\n" \ + << "chk_runtime = " << std::to_string(chrt) << "\n" \ + << "measurement difference = " \ + << std::to_string(md) << "\n" \ + << "--------------------------------------\n" #else #define DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) \ @@ -68,7 +68,7 @@ DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) -typedef std::shared_ptr<std::thread> ThreadPtr; +using ThreadPtr = std::shared_ptr<std::thread>; // For simplicty, keep the total thread runtime @@ -79,7 +79,7 @@ double thread_runtime = 0; void update_thread_runtime(double val) { - std::lock_guard<std::mutex> ug(update_guard); + const std::lock_guard<std::mutex> ug(update_guard); thread_runtime += val; } @@ -107,7 +107,7 @@ static void workload(const uint16_t multiplier) } -TEST(CPUTime, cpu_time_pid) +TEST(CPUTime, CpuTimePid) { // Measure the runtime of the workload MEASURE(start, chk_start, false); @@ -180,7 +180,7 @@ void run_threads(const uint8_t num_threads) } -TEST(CPUTime, cpu_time_thread_1) +TEST(CPUTime, CpuTimeThread1) { // Meassure running a single worker thread MEASURE(parent_start, chk_parent_start, false); @@ -200,10 +200,10 @@ TEST(CPUTime, cpu_time_thread_1) } -TEST(CPUTime, cpu_time_thread_numcores) +TEST(CPUTime, CpuTimeThreadNumcores) { // Use number of available cores - auto num_cores = std::min(std::thread::hardware_concurrency(), 1u); + auto num_cores = std::min(std::thread::hardware_concurrency(), 1U); // Meassure running a single worker thread MEASURE(parent_start, chk_parent_start, false); @@ -219,7 +219,7 @@ TEST(CPUTime, cpu_time_thread_numcores) chk_runtime, parent_diff); #ifdef DEBUG - std::cout << "Total thread runtime: " << std::to_string(thread_runtime) << std::endl; + std::cout << "Total thread runtime: " << std::to_string(thread_runtime) << "\n"; #endif // The main process (this PID) will have a total runtime diff --git a/test/unittests/test_crypto.cpp b/test/unittests/test_crypto.cpp index 08415e4e1..ffc9333f2 100644 --- a/test/unittests/test_crypto.cpp +++ b/test/unittests/test_crypto.cpp @@ -13,6 +13,7 @@ #include "test_common.hpp" +#include <openvpn/buffer/buffer.hpp> #include <openvpn/ssl/sslchoose.hpp> #include <openvpn/crypto/cryptoalgs.hpp> #include <openvpn/crypto/crypto_aead.hpp> @@ -35,7 +36,7 @@ static const char *ipsumlorem = "Lorem ipsum dolor sit amet, consectetur " "adipisici elit, sed eiusmod tempor incidunt " "ut labore et dolore magna aliqua."; -TEST(crypto, hmac) +TEST(Crypto, Hmac) { uint8_t key[20]; std::memcpy(key, testkey, sizeof(key)); @@ -49,7 +50,7 @@ TEST(crypto, hmac) uint8_t hash[20]; - ASSERT_EQ(hmac.final(hash), 20u); + ASSERT_EQ(hmac.final(hash), 20U); /* Google test does not seem to have a good memory equality test macro */ ASSERT_EQ(std::memcmp(hash, goodhash, sizeof(goodhash)), 0); @@ -59,7 +60,7 @@ TEST(crypto, hmac) /* Do this again to ensure that reset works */ hmac.update(ipsum, std::strlen(ipsumlorem)); hmac.update(ipsum, std::strlen(ipsumlorem)); - ASSERT_EQ(hmac.final(hash), 20u); + ASSERT_EQ(hmac.final(hash), 20U); /* Google test does not seem to have a good memory equality test macro */ ASSERT_EQ(std::memcmp(hash, goodhash, sizeof(goodhash)), 0); @@ -73,7 +74,7 @@ TEST(crypto, hmac) /* Do this again to ensure that reset works */ hmac.update(ipsum, std::strlen(ipsumlorem)); hmac.update(ipsum, std::strlen(ipsumlorem)); - ASSERT_EQ(hmac.final(hash), 20u); + ASSERT_EQ(hmac.final(hash), 20U); /* Google test does not seem to have a good memory equality test macro */ ASSERT_EQ(std::memcmp(hash, goodhash, sizeof(goodhash)), 0); @@ -85,7 +86,7 @@ static openvpn::Frame::Context frame_ctx() const size_t headroom = 64; const size_t tailroom = 64; const size_t align_block = 16; - const unsigned int buffer_flags = 0; + const openvpn::BufferFlags buffer_flags = openvpn::BufAllocFlags::NO_FLAGS; return openvpn::Frame::Context{headroom, payload, tailroom, 0, align_block, buffer_flags}; } @@ -102,7 +103,7 @@ openvpn::CryptoDCInstance::Ptr create_dctest_instance(bool use_epoch) dc.set_use_epoch_keys(use_epoch); openvpn::SSLLib::Ctx libctx = nullptr; - openvpn::CryptoDCFactory::Ptr dc_factory_sel{new openvpn::CryptoDCSelect<openvpn::SSLLib::CryptoAPI>(libctx, frameptr, statsptr, nullptr)}; + const openvpn::CryptoDCFactory::Ptr dc_factory_sel{new openvpn::CryptoDCSelect<openvpn::SSLLib::CryptoAPI>(libctx, frameptr, statsptr, nullptr)}; auto dc_factory = dc_factory_sel->new_obj(dc); @@ -147,12 +148,12 @@ void test_datachannel_crypto(bool use_epoch) { openvpn::CryptoAlgs::allow_default_dc_algs<openvpn::SSLLib::CryptoAPI>(nullptr, true, false); - openvpn::CryptoDCInstance::Ptr cryptodc = create_dctest_instance(use_epoch); + const openvpn::CryptoDCInstance::Ptr cryptodc = create_dctest_instance(use_epoch); const char *plaintext = "The quick little fox jumps over the bureaucratic hurdles"; - openvpn::BufferAllocated work{2048, 0}; + openvpn::BufferAllocated work{2048, openvpn::BufAllocFlags::NO_FLAGS}; /* reserve some headroom */ work.realign(128); @@ -165,21 +166,21 @@ void test_datachannel_crypto(bool use_epoch) const unsigned char op32[]{7, 0, 0, 23}; - bool const wrapwarn = cryptodc->encrypt(work, op32); + const bool wrapwarn = cryptodc->encrypt(work, op32); ASSERT_FALSE(wrapwarn); - size_t pkt_counter_len = use_epoch ? 8 : 4; - size_t tag_len = 16; + const size_t pkt_counter_len = use_epoch ? 8 : 4; + const size_t tag_len = 16; /* 16 for tag, 4 or 8 for packet counter */ EXPECT_EQ(work.size(), std::strlen(plaintext) + pkt_counter_len + tag_len); const uint8_t exp_tag_short[16]{0x1f, 0xdd, 0x90, 0x8f, 0x0e, 0x9d, 0xc2, 0x5e, 0x79, 0xd8, 0x32, 0x02, 0x0d, 0x58, 0xe7, 0x3f}; - std::array<uint8_t, 16> exp_tag_epoch = {0Xa0, 0xb5, 0x4c, 0xdd, 0x93, 0xff, 0x0b, 0x01, 0xa3, 0x26, 0x5e, 0xcf, 0x19, 0xd5, 0x6a, 0x06}; + const std::array<uint8_t, 16> exp_tag_epoch = {0Xa0, 0xb5, 0x4c, 0xdd, 0x93, 0xff, 0x0b, 0x01, 0xa3, 0x26, 0x5e, 0xcf, 0x19, 0xd5, 0x6a, 0x06}; if (use_epoch) { - ptrdiff_t tag_offset = 56; + const ptrdiff_t tag_offset = 56; uint8_t packetid1[8] = {0, 0x1, 0, 0, 0, 0, 0, 1}; EXPECT_EQ(std::memcmp(work.data(), packetid1, 8), 0); @@ -195,7 +196,7 @@ void test_datachannel_crypto(bool use_epoch) } else { - ptrdiff_t tag_offset = 16; + const ptrdiff_t tag_offset = 16; uint8_t packetid1[]{0, 0, 0, 1}; EXPECT_EQ(std::memcmp(work.data(), packetid1, 4), 0); EXPECT_EQ(std::memcmp(work.data() + pkt_counter_len, exp_tag_short, 16), 0); @@ -214,12 +215,12 @@ void test_datachannel_crypto(bool use_epoch) EXPECT_EQ(std::memcmp(work.data(), plaintext, std::strlen(plaintext)), 0); } -TEST(crypto, testEpochIterateKey) +TEST(Crypto, TestEpochIterateKey) { openvpn::CryptoAlgs::allow_default_dc_algs<openvpn::SSLLib::CryptoAPI>(nullptr, true, false); - openvpn::CryptoDCInstance::Ptr cryptodcsend = create_dctest_instance(true); - openvpn::CryptoDCInstance::Ptr cryptodcrecv = create_dctest_instance(true); + const openvpn::CryptoDCInstance::Ptr cryptodcsend = create_dctest_instance(true); + const openvpn::CryptoDCInstance::Ptr cryptodcrecv = create_dctest_instance(true); auto *epochdcsend = dynamic_cast<openvpn::AEADEpoch::Crypto<openvpn::SSLLib::CryptoAPI> *>(cryptodcsend.get()); @@ -236,24 +237,24 @@ TEST(crypto, testEpochIterateKey) const unsigned char op32[]{7, 0, 0, 23}; - openvpn::BufferAllocated work{2048, 0}; + openvpn::BufferAllocated work{2048}; /* reserve some headroom */ work.realign(128); std::memcpy(work.write_alloc(std::strlen(plaintext)), plaintext, std::strlen(plaintext)); - bool const wrapwarn = cryptodcsend->encrypt(work, op32); + const bool wrapwarn = cryptodcsend->encrypt(work, op32); ASSERT_FALSE(wrapwarn); - std::size_t pkt_counter_len = 8; - std::size_t tag_len = 16; + const std::size_t pkt_counter_len = 8; + const std::size_t tag_len = 16; /* 16 for tag, 4 or 8 for packet counter */ EXPECT_EQ(work.size(), std::strlen(plaintext) + pkt_counter_len + tag_len); - std::array<uint8_t, 16> exp_tag_epoch = {0x0f, 0xff, 0xf5, 0x91, 0x3d, 0x39, 0xd7, 0x5b, 0x18, 0x57, 0x3b, 0x57, 0x48, 0x58, 0x9a, 0x7d}; - ptrdiff_t tag_offset = 56; + const std::array<uint8_t, 16> exp_tag_epoch = {0x0f, 0xff, 0xf5, 0x91, 0x3d, 0x39, 0xd7, 0x5b, 0x18, 0x57, 0x3b, 0x57, 0x48, 0x58, 0x9a, 0x7d}; + const ptrdiff_t tag_offset = 56; uint8_t packetid1[8] = {0, 0x4, 0, 0, 0, 0, 0, 1}; EXPECT_EQ(std::memcmp(work.data(), packetid1, 8), 0); @@ -275,7 +276,7 @@ TEST(crypto, testEpochIterateKey) EXPECT_EQ(std::memcmp(work.data(), plaintext, std::strlen(plaintext)), 0); } -TEST(crypto, epoch_derive_data_keys) +TEST(Crypto, EpochDeriveDataKeys) { uint8_t epoch_key[32] = {19, 12}; openvpn::StaticKey e1{epoch_key, 32}; @@ -289,9 +290,9 @@ TEST(crypto, epoch_derive_data_keys) ASSERT_EQ(key.size(), 24); ASSERT_EQ(iv.size(), 12); - std::array<uint8_t, 24> exp_key{0xed, 0x85, 0x33, 0xdb, 0x1c, 0x28, 0xac, 0xe4, 0x18, 0xe9, 0x00, 0x6a, 0xb2, 0x9c, 0x17, 0x41, 0x7d, 0x60, 0xeb, 0xe6, 0xcd, 0x90, 0xbf, 0x0a}; + const std::array<uint8_t, 24> exp_key{0xed, 0x85, 0x33, 0xdb, 0x1c, 0x28, 0xac, 0xe4, 0x18, 0xe9, 0x00, 0x6a, 0xb2, 0x9c, 0x17, 0x41, 0x7d, 0x60, 0xeb, 0xe6, 0xcd, 0x90, 0xbf, 0x0a}; - std::array<uint8_t, 12> exp_impl_iv{0x86, 0x89, 0x0a, 0xab, 0xf0, 0x32, 0xcb, 0x59, 0xf4, 0xcf, 0xa3, 0x4e}; + const std::array<uint8_t, 12> exp_impl_iv{0x86, 0x89, 0x0a, 0xab, 0xf0, 0x32, 0xcb, 0x59, 0xf4, 0xcf, 0xa3, 0x4e}; std::array<uint8_t, 24> key_array; @@ -304,7 +305,7 @@ TEST(crypto, epoch_derive_data_keys) EXPECT_EQ(exp_impl_iv, iv_array); } -TEST(crypto, aead_cipher_movable) +TEST(Crypto, AeadCipherMovable) { openvpn::CryptoAlgs::allow_default_dc_algs<openvpn::SSLLib::CryptoAPI>(nullptr, true, false); @@ -347,18 +348,18 @@ TEST(crypto, aead_cipher_movable) ASSERT_EQ(std::memcmp(input, output3, 5), 0); } -TEST(crypto, dcaead_data_v2) +TEST(Crypto, DcaeadDataV2) { test_datachannel_crypto(false); } -TEST(crypto, dcaead_epoch_data) +TEST(Crypto, DcaeadEpochData) { /* Epoch data needs more refactoring before adjusting the unit test */ test_datachannel_crypto(true); } -TEST(crypto, hkdf_expand_testa1) +TEST(Crypto, HkdfExpandTesta1) { /* RFC 5889 A.1 Test Case 1 */ // clang-format off @@ -372,7 +373,7 @@ TEST(crypto, hkdf_expand_testa1) {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}; - std::array<uint8_t,42> okm + std::array<uint8_t,42> const okm {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, @@ -388,7 +389,7 @@ TEST(crypto, hkdf_expand_testa1) ASSERT_EQ(out, okm); } -TEST(crypto, hkdf_expand_testa2) +TEST(Crypto, HkdfExpandTesta2) { // clang-format off /* RFC 5889 A.2 Test Case 2 */ @@ -411,7 +412,7 @@ TEST(crypto, hkdf_expand_testa2) 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}; const int L = 82; - std::array<uint8_t,82> okm + std::array<uint8_t,82> const okm {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, @@ -433,7 +434,7 @@ TEST(crypto, hkdf_expand_testa2) ASSERT_EQ(out, okm); } -TEST(crypto, ovpn_label_expand_test) +TEST(Crypto, OvpnLabelExpandTest) { // clang-format off uint8_t secret[32] = @@ -442,7 +443,7 @@ TEST(crypto, ovpn_label_expand_test) 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}; - std::array<uint8_t, 16> out_expected = + std::array<uint8_t, 16> const out_expected = {0x18, 0x5e, 0xaa, 0x1c, 0x7f, 0x22, 0x8a, 0xb8, 0xeb, 0x29, 0x77, 0x32, 0x14, 0xd9, 0x20, 0x46}; // clang-format on @@ -454,7 +455,7 @@ TEST(crypto, ovpn_label_expand_test) EXPECT_EQ(out, out_expected); } -TEST(crypto, hkdf_expand_testa3) +TEST(Crypto, HkdfExpandTesta3) { /* RFC 5889 A.3 Test Case 3 */ // clang-format off @@ -464,7 +465,7 @@ TEST(crypto, hkdf_expand_testa3) 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}; - std::array<uint8_t,42> okm = + std::array<uint8_t,42> const okm = {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, @@ -473,8 +474,8 @@ TEST(crypto, hkdf_expand_testa3) 0x96, 0xc8}; // clang-format off - uint8_t *info = nullptr; - int L = 42; + uint8_t const*info = nullptr; + int const L = 42; std::array<uint8_t,42> out {0xfa}; openvpn::ovpn_hkdf_expand(prk, info, 0, out.data(), L); @@ -528,7 +529,7 @@ class EpochTest : public testing::Test void initDCE(uint16_t numfuture) { uint8_t e1send_data[32] = { 0x23 }; - uint8_t e1recv_data[32] = { 0x27 }; + uint8_t const e1recv_data[32] = { 0x27 }; openvpn::StaticKey e1send{e1send_data, sizeof (e1send_data)}; openvpn::StaticKey e1recv{e1send_data, sizeof (e1recv_data)}; @@ -539,7 +540,7 @@ class EpochTest : public testing::Test }; -TEST_F(EpochTest, key_generation) +TEST_F(EpochTest, KeyGeneration) { /* check the keys look like we expect */ EXPECT_EQ(dce_.get_future_key(0).epoch, 2); @@ -549,9 +550,9 @@ TEST_F(EpochTest, key_generation) } -TEST_F(EpochTest, key_rotation) +TEST_F(EpochTest, KeyRotation) { -openvpn::SessionStats::Ptr stats{new openvpn::SessionStats{}}; +openvpn::SessionStats::Ptr const stats{new openvpn::SessionStats{}}; /* should replace send + key recv */ dce_.replace_update_recv_key(9, stats); @@ -591,9 +592,9 @@ dce_.iterate_send_key(); EXPECT_EQ(dce_.send_ctx_().epoch, 14); } -TEST_F(EpochTest, key_receive_lookup) +TEST_F(EpochTest, KeyReceiveLookup) { -openvpn::SessionStats::Ptr stats{new openvpn::SessionStats{}}; +openvpn::SessionStats::Ptr const stats{new openvpn::SessionStats{}}; /* lookup some wacky things that should fail */ EXPECT_EQ(dce_.lookup_decrypt_key(2000), nullptr); @@ -644,9 +645,9 @@ dce_.replace_update_recv_key(8, stats); EXPECT_EQ(dce_.lookup_decrypt_key(23), nullptr); } -TEST_F(EpochTest, key_overflow) +TEST_F(EpochTest, KeyOverflow) { - openvpn::SessionStats::Ptr stats{new openvpn::SessionStats{}}; + openvpn::SessionStats::Ptr const stats{new openvpn::SessionStats{}}; initDCE(32); /* Modify the receive epoch and keys to have a very high epoch to test diff --git a/test/unittests/test_crypto_hashstr.cpp b/test/unittests/test_crypto_hashstr.cpp index 45572e54b..63c36f39b 100644 --- a/test/unittests/test_crypto_hashstr.cpp +++ b/test/unittests/test_crypto_hashstr.cpp @@ -7,11 +7,11 @@ using namespace openvpn; -TEST(crypto, hashstr) +TEST(Crypto, Hashstr) { const std::string content = read_text_utf8(UNITTEST_SOURCE_DIR "/input/1984.txt"); - DigestFactory::Ptr digest_factory(new CryptoDigestFactory<SSLLib::CryptoAPI>()); + const DigestFactory::Ptr digest_factory(new CryptoDigestFactory<SSLLib::CryptoAPI>()); HashString hash(*digest_factory, CryptoAlgs::MD5); hash.update(content); const std::string actual = hash.final_hex(); diff --git a/test/unittests/test_csum.cpp b/test/unittests/test_csum.cpp index 2dc0ceac4..f0bef368c 100644 --- a/test/unittests/test_csum.cpp +++ b/test/unittests/test_csum.cpp @@ -28,10 +28,10 @@ std::uint16_t ip_checksum_slow(const void *ip, size_t size) return static_cast<uint16_t>(~cksum); } -TEST(misc, stress_csum) +TEST(Misc, StressCsum) { - RandomAPI::Ptr prng(new MTRand); - BufferAllocated buf(256, 0); + const RandomAPI::Ptr prng(new MTRand); + BufferAllocated buf(256); for (long i = 0; i < 1000000; ++i) { @@ -62,6 +62,6 @@ TEST(misc, stress_csum) << " orig=" << orig_csum << " updated=" << updated_csum << " verify=" << verify_csum - << std::endl; + << '\n'; } } diff --git a/test/unittests/test_dns.cpp b/test/unittests/test_dns.cpp index 6af1e5d58..fcb169ad3 100644 --- a/test/unittests/test_dns.cpp +++ b/test/unittests/test_dns.cpp @@ -42,12 +42,12 @@ TEST(Dns, Options) DnsOptionsParser dns(config, false); - ASSERT_EQ(dns.search_domains.size(), 3u); + ASSERT_EQ(dns.search_domains.size(), 3U); ASSERT_EQ(dns.search_domains[0].to_string(), "domain0"); ASSERT_EQ(dns.search_domains[1].to_string(), "domain1"); ASSERT_EQ(dns.search_domains[2].to_string(), "domain2"); - ASSERT_EQ(dns.servers.size(), 3u); + ASSERT_EQ(dns.servers.size(), 3U); int i = 1; for (const auto &keyval : dns.servers) @@ -59,11 +59,11 @@ TEST(Dns, Options) { ASSERT_EQ(i, 1); - ASSERT_TRUE(server.addresses.size() == 1u); + ASSERT_TRUE(server.addresses.size() == 1U); ASSERT_EQ(server.addresses[0].address, "2.2.2.2"); - ASSERT_EQ(server.addresses[0].port, 5353u); + ASSERT_EQ(server.addresses[0].port, 5353U); - ASSERT_EQ(server.domains.size(), 2u); + ASSERT_EQ(server.domains.size(), 2U); ASSERT_EQ(server.domains[0].to_string(), "rdom0"); ASSERT_EQ(server.domains[1].to_string(), "rdom1"); @@ -76,14 +76,14 @@ TEST(Dns, Options) { ASSERT_EQ(i, 2); - ASSERT_TRUE(server.addresses.size() == 2u); + ASSERT_TRUE(server.addresses.size() == 2U); ASSERT_EQ(server.addresses[0].address, "1.1.1.1"); - ASSERT_EQ(server.addresses[0].port, 0u); + ASSERT_EQ(server.addresses[0].port, 0U); ASSERT_EQ(server.addresses[1].address, "1::1"); - ASSERT_EQ(server.addresses[1].port, 5353u); + ASSERT_EQ(server.addresses[1].port, 5353U); - ASSERT_EQ(server.domains.size(), 0u); + ASSERT_EQ(server.domains.size(), 0U); ASSERT_EQ(server.dnssec, DnsServer::Security::Unset); @@ -94,17 +94,17 @@ TEST(Dns, Options) { ASSERT_EQ(i, 3); - ASSERT_TRUE(server.addresses.size() == 3u); + ASSERT_TRUE(server.addresses.size() == 3U); ASSERT_EQ(server.addresses[0].address, "3::3"); - ASSERT_EQ(server.addresses[0].port, 0u); + ASSERT_EQ(server.addresses[0].port, 0U); ASSERT_EQ(server.addresses[1].address, "3.2.1.0"); - ASSERT_EQ(server.addresses[1].port, 4242u); + ASSERT_EQ(server.addresses[1].port, 4242U); ASSERT_EQ(server.addresses[2].address, "3:3::3:3"); - ASSERT_EQ(server.addresses[2].port, 3333u); + ASSERT_EQ(server.addresses[2].port, 3333U); - ASSERT_EQ(server.domains.size(), 0u); + ASSERT_EQ(server.domains.size(), 0U); ASSERT_EQ(server.dnssec, DnsServer::Security::No); @@ -120,7 +120,7 @@ TEST(Dns, OptionsMerger) { OptionList pushed; OptionList config; - DnsOptionsMerger merger; + const DnsOptionsMerger merger; pushed.parse_from_config("dns server 1 address ::1", nullptr); config.parse_from_config("dns server 1 address 1.1.1.1\n" @@ -130,13 +130,13 @@ TEST(Dns, OptionsMerger) config.update_map(); merger.merge(pushed, config); - ASSERT_EQ(config.size(), 2u); - ASSERT_EQ(pushed.size(), 2u); + ASSERT_EQ(config.size(), 2U); + ASSERT_EQ(pushed.size(), 2U); ASSERT_EQ(pushed[0].ref(4), "::1"); ASSERT_EQ(pushed[1].ref(4), "2.2.2.2"); } -TEST(Dns, DnsAddress_tostring) +TEST(Dns, DnsAddressTostring) { /** * Supported formats: @@ -146,25 +146,25 @@ TEST(Dns, DnsAddress_tostring) * [2001:db8:1234::1]:53 */ - DnsAddress ipv4_addr("192.168.0.1"); + const DnsAddress ipv4_addr("192.168.0.1"); EXPECT_STREQ(ipv4_addr.to_string().c_str(), "192.168.0.1"); - DnsAddress parse_ipv4_addr(ipv4_addr.to_string()); + const DnsAddress parse_ipv4_addr(ipv4_addr.to_string()); EXPECT_STREQ(parse_ipv4_addr.to_string().c_str(), "192.168.0.1"); - DnsAddress ipv4_port("192.168.20.1:9876"); + const DnsAddress ipv4_port("192.168.20.1:9876"); EXPECT_STREQ(ipv4_port.to_string().c_str(), "192.168.20.1:9876"); - DnsAddress parse_ipv4_port(ipv4_port.to_string()); + const DnsAddress parse_ipv4_port(ipv4_port.to_string()); EXPECT_STREQ(parse_ipv4_port.to_string().c_str(), "192.168.20.1:9876"); - DnsAddress ipv6_addr("2001:db8:5678::1"); + const DnsAddress ipv6_addr("2001:db8:5678::1"); EXPECT_STREQ(ipv6_addr.to_string().c_str(), "2001:db8:5678::1"); - DnsAddress parse_ipv6_addr(ipv6_addr.to_string()); + const DnsAddress parse_ipv6_addr(ipv6_addr.to_string()); EXPECT_STREQ(parse_ipv6_addr.to_string().c_str(), "2001:db8:5678::1") << "parse_ipv6_addr failed"; - DnsAddress ipv6_port("[2001:db8:1234::1]:5678"); + const DnsAddress ipv6_port("[2001:db8:1234::1]:5678"); EXPECT_STREQ(ipv6_port.to_string().c_str(), "[2001:db8:1234::1]:5678"); - DnsAddress parse_ipv6_port(ipv6_port.to_string()); + const DnsAddress parse_ipv6_port(ipv6_port.to_string()); EXPECT_STREQ(parse_ipv6_port.to_string().c_str(), "[2001:db8:1234::1]:5678") << "parse_ipv6_port failed"; @@ -224,8 +224,8 @@ TEST(Dns, ServerEightAddresses) config.parse_from_config("dns server 0 address 1::1 2::2 3::3 4::4 5::5 6::6 7::7 8::8\n", nullptr); config.update_map(); DnsOptionsParser dns(config, false); - ASSERT_EQ(dns.servers.size(), 1u); - ASSERT_EQ(dns.servers[0].addresses.size(), 8u); + ASSERT_EQ(dns.servers.size(), 1U); + ASSERT_EQ(dns.servers[0].addresses.size(), 8U); } TEST(Dns, ServerTooManyAddresses) @@ -288,7 +288,7 @@ TEST(Dns, ServerInvalidTransport) } } -TEST(Dns, dhcp_options) +TEST(Dns, DhcpOptions) { OptionList config; config.parse_from_config( @@ -305,21 +305,21 @@ TEST(Dns, dhcp_options) ASSERT_TRUE(dns.from_dhcp_options); - ASSERT_EQ(dns.search_domains.size(), 3u); + ASSERT_EQ(dns.search_domains.size(), 3U); ASSERT_EQ(dns.search_domains[0].to_string(), "ads"); ASSERT_EQ(dns.search_domains[1].to_string(), "domain0"); ASSERT_EQ(dns.search_domains[2].to_string(), "domain1"); - ASSERT_EQ(dns.servers.size(), 1u); - ASSERT_TRUE(dns.servers[0].addresses.size() == 2u); + ASSERT_EQ(dns.servers.size(), 1U); + ASSERT_TRUE(dns.servers[0].addresses.size() == 2U); ASSERT_EQ(dns.servers[0].addresses[0].address, "1.1.1.1"); - ASSERT_EQ(dns.servers[0].addresses[0].port, 0u); + ASSERT_EQ(dns.servers[0].addresses[0].port, 0U); ASSERT_EQ(dns.servers[0].addresses[1].address, "1::1"); - ASSERT_EQ(dns.servers[0].addresses[1].port, 0u); + ASSERT_EQ(dns.servers[0].addresses[1].port, 0U); } -TEST(Dns, dhcp_options_with_split_domains) +TEST(Dns, DhcpOptionsWithSplitDomains) { OptionList config; config.parse_from_config( @@ -336,23 +336,23 @@ TEST(Dns, dhcp_options_with_split_domains) ASSERT_TRUE(dns.from_dhcp_options); - ASSERT_EQ(dns.search_domains.size(), 1u); + ASSERT_EQ(dns.search_domains.size(), 1U); ASSERT_EQ(dns.search_domains[0].to_string(), "ads"); - ASSERT_EQ(dns.servers.size(), 1u); + ASSERT_EQ(dns.servers.size(), 1U); - ASSERT_TRUE(dns.servers[0].addresses.size() == 2u); + ASSERT_TRUE(dns.servers[0].addresses.size() == 2U); ASSERT_EQ(dns.servers[0].addresses[0].address, "1.1.1.1"); - ASSERT_EQ(dns.servers[0].addresses[0].port, 0u); + ASSERT_EQ(dns.servers[0].addresses[0].port, 0U); ASSERT_EQ(dns.servers[0].addresses[1].address, "1::1"); - ASSERT_EQ(dns.servers[0].addresses[1].port, 0u); + ASSERT_EQ(dns.servers[0].addresses[1].port, 0U); - ASSERT_TRUE(dns.servers[0].domains.size() == 2u); + ASSERT_TRUE(dns.servers[0].domains.size() == 2U); ASSERT_EQ(dns.servers[0].domains[0].domain, "domain0"); ASSERT_EQ(dns.servers[0].domains[1].domain, "domain1"); } -TEST(Dns, dhcp_options_ignored) +TEST(Dns, DhcpOptionsIgnored) { OptionList config; config.parse_from_config( @@ -370,12 +370,12 @@ TEST(Dns, dhcp_options_ignored) ASSERT_FALSE(dns.from_dhcp_options); ASSERT_TRUE(dns.search_domains.empty()); - ASSERT_EQ(dns.servers.size(), 1u); + ASSERT_EQ(dns.servers.size(), 1U); ASSERT_TRUE(dns.servers[123].domains.empty()); - ASSERT_TRUE(dns.servers[123].addresses.size() == 1u); + ASSERT_TRUE(dns.servers[123].addresses.size() == 1U); ASSERT_EQ(dns.servers[123].addresses[0].address, "123::123"); - ASSERT_EQ(dns.servers[123].addresses[0].port, 0u); + ASSERT_EQ(dns.servers[123].addresses[0].port, 0U); } TEST(Dns, ToStringMinValuesSet) @@ -383,7 +383,7 @@ TEST(Dns, ToStringMinValuesSet) OptionList config; config.parse_from_config("dns server 10 address 1::1\n", nullptr); config.update_map(); - DnsOptionsParser dns(config, false); + const DnsOptionsParser dns(config, false); ASSERT_EQ(dns.to_string(), "DNS Servers:\n" " Priority: 10\n" @@ -397,7 +397,7 @@ TEST(Dns, ToStringValuesFromDhcpOptions) OptionList config; config.parse_from_config("dhcp-option DNS6 1::1\n", nullptr); config.update_map(); - DnsOptionsParser dns(config, false); + const DnsOptionsParser dns(config, false); ASSERT_EQ(dns.to_string(), "DNS Servers:\n" " Priority: 0\n" @@ -423,7 +423,7 @@ TEST(Dns, ToStringAllValuesSet) "dns server 20 dnssec yes\n", nullptr); config.update_map(); - DnsOptionsParser dns(config, false); + const DnsOptionsParser dns(config, false); ASSERT_EQ(dns.to_string(), "DNS Servers:\n" " Priority: 10\n" @@ -458,8 +458,8 @@ TEST(Dns, JsonRoundtripMinValuesSet) OptionList config; config.parse_from_config("dns server 10 address 1::1\n", nullptr); config.update_map(); - DnsOptionsParser toJson(config, false); - Json::Value json = toJson.to_json(); + const DnsOptionsParser toJson(config, false); + const Json::Value json = toJson.to_json(); Json::StreamWriterBuilder builder; builder["indentation"] = " "; ASSERT_EQ(Json::writeString(builder, json), @@ -494,8 +494,8 @@ TEST(Dns, JsonRoundtripValuesFromDhcpOption) OptionList config; config.parse_from_config("dhcp-option DNS6 1::1\n", nullptr); config.update_map(); - DnsOptionsParser toJson(config, false); - Json::Value json = toJson.to_json(); + const DnsOptionsParser toJson(config, false); + const Json::Value json = toJson.to_json(); Json::StreamWriterBuilder builder; builder["indentation"] = " "; ASSERT_EQ(Json::writeString(builder, json), @@ -542,8 +542,8 @@ TEST(Dns, JsonRoundtripAllValuesSet) "dns server 20 dnssec yes\n", nullptr); config.update_map(); - DnsOptionsParser toJson(config, false); - Json::Value json = toJson.to_json(); + const DnsOptionsParser toJson(config, false); + const Json::Value json = toJson.to_json(); Json::StreamWriterBuilder builder; builder["indentation"] = " "; ASSERT_EQ(Json::writeString(builder, json), diff --git a/test/unittests/test_format.cpp b/test/unittests/test_format.cpp index 350c02738..eb300494c 100644 --- a/test/unittests/test_format.cpp +++ b/test/unittests/test_format.cpp @@ -52,7 +52,7 @@ const std::string expected = "7\n" "EX1: bad foo\n" "EX2: this prog is done 4 U\n"; -TEST(misc, format) +TEST(Misc, Format) { std::ostringstream os; @@ -64,26 +64,26 @@ TEST(misc, format) const std::string weather = "partly cloudy"; char *nc = const_cast<char *>("non const"); - os << to_string(seven) << std::endl; - os << to_string(foo) << std::endl; - os << to_string(bar) << std::endl; - os << to_string(pi) << std::endl; - os << to_string(three) << std::endl; - os << to_string(true) << std::endl; - os << to_string(false) << std::endl; - os << prints("pi", "is", std::string("not"), 3, "nor is it", seven, ';', "it", "is", pi, "...") << std::endl; - os << printfmt("pi is %r %s nor is it %s ; it is %s... (and has %s%% less %s!)", "not", 3, seven, pi, 99, std::string("fat")) << std::endl; - os << printfmt("the year is %s and the weather is %R", 2015, weather) << std::endl; - os << printfmt("where am %s? is it still %s?", 'I', 2015) << std::endl; - os << printfmt("no, it's %s... bring out yer dedd%s", 1666) << std::endl; - os << printfmt("save 20%%!") << std::endl; - os << printfmt("no wait... save%s 99.9999%%!") << std::endl; - os << printfmt("extra argument is here", 1) << std::endl; - os << printfmt("is the question %s or %s?", true, false) << std::endl; - os << printfmt("more extra arguments are here", 1, 2, 3, 4) << std::endl; - os << printfmt("null string '%s'", static_cast<const char *>(nullptr)) << std::endl; - os << printfmt("nullptr '%s'", nullptr) << std::endl; - os << printfmt("%s=%s %s", foo, bar, nc) << std::endl; + os << to_string(seven) << '\n'; + os << to_string(foo) << '\n'; + os << to_string(bar) << '\n'; + os << to_string(pi) << '\n'; + os << to_string(three) << '\n'; + os << to_string(true) << '\n'; + os << to_string(false) << '\n'; + os << prints("pi", "is", std::string("not"), 3, "nor is it", seven, ';', "it", "is", pi, "...") << '\n'; + os << printfmt("pi is %r %s nor is it %s ; it is %s... (and has %s%% less %s!)", "not", 3, seven, pi, 99, std::string("fat")) << '\n'; + os << printfmt("the year is %s and the weather is %R", 2015, weather) << '\n'; + os << printfmt("where am %s? is it still %s?", 'I', 2015) << '\n'; + os << printfmt("no, it's %s... bring out yer dedd%s", 1666) << '\n'; + os << printfmt("save 20%%!") << '\n'; + os << printfmt("no wait... save%s 99.9999%%!") << '\n'; + os << printfmt("extra argument is here", 1) << '\n'; + os << printfmt("is the question %s or %s?", true, false) << '\n'; + os << printfmt("more extra arguments are here", 1, 2, 3, 4) << '\n'; + os << printfmt("null string '%s'", static_cast<const char *>(nullptr)) << '\n'; + os << printfmt("nullptr '%s'", nullptr) << '\n'; + os << printfmt("%s=%s %s", foo, bar, nc) << '\n'; try { const std::string exstr = "bad foo"; @@ -91,7 +91,7 @@ TEST(misc, format) } catch (const std::exception &e) { - os << prints("EX1:", e.what()) << std::endl; + os << prints("EX1:", e.what()) << '\n'; } try { @@ -99,7 +99,7 @@ TEST(misc, format) } catch (const std::exception &e) { - os << prints("EX2:", e.what()) << std::endl; + os << prints("EX2:", e.what()) << '\n'; } const std::string actual = os.str(); ASSERT_EQ(expected, actual); @@ -116,22 +116,3 @@ inline std::string pfmt(const std::string &fmt, Args... args) pf.process(args...); return pf.str(); } - -void perf() -{ - const MyObj seven(7); - // const double pi = 3.14159265; - size_t count = 0; - const std::string weather = "partly cloudy"; - for (long i = 0; i < 1000000; ++i) - { - const std::string str = pfmt("the year is %s and the weather is %r", 2015, weather); - // const std::string str = pfmt("this program is brought to you by the number %s", seven); - // const std::string str = pfmt("foo %s", 69); - // const std::string str = pfmt("foo"); - // const std::string str = pfmt("foo %s %s", 69, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - // const std::string str = pfmt("pi is %s %s nor is it %s ; it is %s... (and has %s%% less %s!)", "not", 3, seven, pi, 99, std::string("fat")); - count += str.length(); - } - std::cout << count << std::endl; -} diff --git a/test/unittests/test_generators.hpp b/test/unittests/test_generators.hpp index 911ffd0a1..376fa880e 100644 --- a/test/unittests/test_generators.hpp +++ b/test/unittests/test_generators.hpp @@ -11,6 +11,13 @@ #include <algorithm> #include <utility> +#include <string> +#include <tuple> +#include <array> +#include <string_view> +#include <bitset> +#include <sstream> +#include <vector> #include "openvpn/addr/ip.hpp" #include "openvpn/tun/builder/capture.hpp" @@ -43,6 +50,36 @@ auto atLeastOneFalse() -> Gen<std::array<bool, N>> }); } +/** + * @brief Generates an array of validity flags for component testing + * + * @tparam N Number of validity flags to generate + * @param all_valid If @c true, generates all flags as valid (@c true). + * If @c false, generates flags with at least one invalid (@c false) value. + * + * @return Generator producing an array of @p N boolean flags. + * When all_valid is @c true : returns array with all elements set to @c true + * When all_valid is @c false : returns array with at least one element set to @c false + * + * Example usage: + * @code + * // Generate flags for testing URL components (all valid) + * auto [scheme_is_valid, authority_is_valid] = *generateValidityFlags<2>(true); + * + * // Generate flags with at least one invalid component + * auto [scheme_is_valid, authority_is_valid] = *generateValidityFlags<2>(false); + * @endcode + */ +template <size_t N> +auto generateValidityFlags(const bool all_valid = true) -> Gen<std::array<bool, N>> +{ + if (all_valid) + { + return gen::container<std::array<bool, N>>(gen::just(true)); + } + return atLeastOneFalse<N>(); +} + /** * @brief Generates a valid or invalid IPv4 octet value. * @details This function generates a value that represents an IPv4 octet. If \p valid is \c true, @@ -494,5 +531,399 @@ struct Arbitrary<std::variant<T, Ts...>> } }; +static const std::string ALPHA_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const std::string DIGITS = "1234567890"; + +/** + * @brief Generates alphabetic or non-alphabetic characters. + * @details Creates a generator that produces either valid alphabetic characters (A-Z, a-z) + * or non-alphabetic characters, depending on the input parameter. When generating + * valid alphabetic characters, it selects from a predefined set of characters. + * For invalid characters, it uses a character generator with a predicate that + * ensures the character is not alphabetic. + * + * @param valid If @c true (default), generates valid alphabetic characters. + * If @c false, generates non-alphabetic characters. + * + * @return Gen<char> A generator that produces characters according to the specified criteria: + * - When valid=true: returns a generator for alphabetic characters (A-Z, a-z) + * - When valid=false: returns a generator for non-alphabetic characters + */ +inline auto alpha(const bool valid = true) -> Gen<char> +{ + if (valid) + { + return gen::elementOf(std::string_view{ALPHA_CHARACTERS}); + } + return gen::suchThat(gen::character<char>(), + [](const char character) + { return !std::isalpha(character); }); +} + +/** + * @brief Generates characters based on an allowed character set. + * @details Creates a generator that either produces characters from a specified set of allowed characters, + * or characters that are specifically not in that set, depending on the @c valid parameter. + * When @c valid is @c true, it generates only characters from the allowed set. + * When @c valid is @c false, it generates only characters that are not in the allowed set. + * + * @param allowed_chars A string_view containing the set of allowed characters + * @param valid Boolean flag to determine whether to generate characters from the allowed set (@c true) + * or characters not in the allowed set (@c false). Defaults to @c true. + * + * @return Gen<char> A character generator that produces either valid or invalid characters + * based on the @p allowed_chars set + */ +inline auto from_allowed_chars(const std::string_view &allowed_chars, const bool valid = true) -> Gen<char> +{ + if (valid) + { + return gen::elementOf(allowed_chars); + } + return gen::suchThat(gen::character<char>(), + [allowed_chars](const char character) + { return allowed_chars.find(character) == std::string::npos; }); +} + +/** + * @brief Generates strings based on allowed characters. + * @details Creates a generator that produces strings either containing only allowed characters + * or containing at least one character not in the allowed set. + * When @c valid is @c true, it generates strings using only allowed characters. + * When @c valid is @c false, it generates strings that contain at least one + * character not present in @p allowed_chars. + * + * @param allowed_chars A string_view containing the set of allowed characters + * @param valid Boolean flag to control generation mode: + * - @c true : generate strings using only allowed characters + * - @c false : generate strings containing at least one invalid character + * (defaults to @c true) + * + * @return A generator that produces @c std::string values according to the + * specified constraints + */ +inline auto string_from_allowed_chars(const std::string_view &allowed_chars, const bool valid = true) -> Gen<std::string> +{ + if (valid) + { + return gen::container<std::string>(from_allowed_chars(allowed_chars)); + } + return gen::suchThat(gen::string<std::string>(), [allowed_chars](const auto &string) + { return std::any_of(string.begin(), string.end(), [allowed_chars](const auto &character) + { return allowed_chars.find(character) == std::string::npos; }); }); +} + +/** + * @brief Generates a port number value. + * @details Creates a generator that produces either valid or invalid port numbers. + * If @c valid is @c true, generates numbers in the valid port range [0, 65535]. + * If @c valid is @c false, generates numbers outside the valid port range. + * + * @param valid Boolean flag to determine if valid (@c true) or invalid (@c false) port numbers should be generated. + * Defaults to @c true. + * @return Gen<int> A generator that produces port numbers according to the @p valid parameter. + */ +inline auto port(const bool valid = true) -> Gen<int> +{ + static constexpr int port_upper_bound = 65535; + static constexpr int port_lower_bound = 0; + if (valid) + return gen::inRange(port_lower_bound, port_upper_bound + 1); + return gen::suchThat<int>( + [](const auto port_number) + { return port_number < port_lower_bound || port_number > port_upper_bound; }); +} + +/** + * @brief Calculates the valid IP prefix range for a given IP address. + * @details This function takes an IPv4 address as a string and calculates the minimum + * and maximum valid prefix lengths. It converts the address to its integer + * representation and determines the smallest prefix that can correctly + * represent the network containing this address based on the position of + * the least significant '1' bit. + * + * For example: + * - For 192.168.1.0, the range would be {24, 32} + * - For 10.0.0.0, the range would be {7, 32} + * + * @param ipAddress An IPv4 address in dotted decimal notation (e.g., "192.168.1.0") + * @return A tuple containing: + * - First element: The minimum valid prefix length (between 0 and 32) + * - Second element: The maximum valid prefix length (always 32) + */ +inline auto calculateIPPrefixRange(const std::string &ipAddress) -> std::tuple<int, int> +{ + std::array<unsigned int, 4> addressParts{}; + std::istringstream addressStream(ipAddress); + std::string part; + size_t partIndex = 0; + + while (std::getline(addressStream, part, '.')) + { + addressParts[partIndex++] = std::stoi(part); + } + + const uint32_t addressInteger = (addressParts[0] << 24) | (addressParts[1] << 16) | (addressParts[2] << 8) | addressParts[3]; + + auto minimumPrefix = 32; + for (auto bitPosition = 0; bitPosition < 32; ++bitPosition) + { + if (addressInteger & (1U << bitPosition)) + { + minimumPrefix = 32 - bitPosition; + break; + } + } + + return {minimumPrefix, openvpn::IPv4::Addr::SIZE}; +} + +namespace helpers { + +/** + * @brief Generates a host string. + * @details Creates a string based on the input parameter. Valid hosts conform to length + * constraints (between @c HOST_MIN_LENGTH and @c HOST_MAX_LENGTH characters) and contain + * only allowed characters. Invalid hosts may exceed the maximum length or contain invalid + * characters. + * + * @param valid If @c true (default), the function will generally produce valid host strings + * If @c false, the function will deliberately generate invalid host strings. + * + * @return A generator for host strings with the specified validity characteristics. + * + * @note This generator does not produce meaningful hosts, just string with valid length and from allowed characters + */ +inline auto genHost(const bool valid = true) -> Gen<std::string> +{ + static constexpr size_t HOST_MAX_LENGTH = 256; + static constexpr size_t HOST_MIN_LENGTH = 1; + static constexpr size_t INVALID_MAX_LENGTH_LIMIT = 8192; + + static const std::string allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-:"; + + auto [valid_chars, valid_length] = valid ? *generateValidityFlags<2>() : *generateValidityFlags<2>(false); + const auto length = valid_length ? *gen::inRange(HOST_MIN_LENGTH, HOST_MAX_LENGTH + 1) : *gen::inRange(HOST_MAX_LENGTH + 1, INVALID_MAX_LENGTH_LIMIT); + + return gen::container<std::string>(length, from_allowed_chars(allowed_chars, valid_chars)); +} + +/** + * @brief Generates random DNS server security settings. + * @details Creates a generator that produces random values from the @c openvpn::DnsServer::Security + * enumeration. The generated values can be one of: @c Unset, @c No, @c Yes, or @c Optional. + * @return A generator that yields random @c openvpn::DnsServer::Security enum values. + */ +inline auto genDnsServerSecurity() -> Gen<openvpn::DnsServer::Security> +{ + return gen::element( + openvpn::DnsServer::Security::Unset, + openvpn::DnsServer::Security::No, + openvpn::DnsServer::Security::Yes, + openvpn::DnsServer::Security::Optional); +} + +/** + * @brief Generates random DNS server transport. + * @details Creates a generator that produces random values from the @c openvpn::DnsServer::Transport + * enumeration. The generator yields one of: @c Unset, @c Plain, @c HTTPS, or @c TLS. + * @return A generator that yields random @c openvpn::DnsServer::Transport enum values. + */ +inline auto genDnsServerTransport() -> Gen<openvpn::DnsServer::Transport> +{ + return gen::element( + openvpn::DnsServer::Transport::Unset, + openvpn::DnsServer::Transport::Plain, + openvpn::DnsServer::Transport::HTTPS, + openvpn::DnsServer::Transport::TLS); +} + +} // namespace helpers + +/** + * @brief Generates a DnsDomain. + * @details Creates a generator that produces instances of the @c openvpn::DnsDomain class. + * The generator can create either valid or invalid DNS domain names based on the + * provided parameter. It uses the @c helpers::genHost function to generate + * appropriate domain strings. + * @param valid A boolean flag indicating whether to generate valid (@c true ) or + * invalid (@c false ) domain names. Defaults to @c true. + * @return A generator that produces @c openvpn::DnsDomain objects with either valid or + * invalid domain values. + * + * Example usage: + * @code + * // Generate a valid DNS domain + * auto validDomain = *genDnsDomain(); + * + * // Generate an invalid DNS domain + * auto invalidDomain = *genDnsDomain(false); + * @endcode + */ +inline auto genDnsDomain(const bool valid = true) -> Gen<openvpn::DnsDomain> +{ + return gen::build( + gen::construct<openvpn::DnsDomain>(), + gen::set(&openvpn::DnsDomain::domain, helpers::genHost(valid))); +} + +/** + * @brief Generates a DNS address. + * @details Creates a generator that produces instances of the @c openvpn::DnsAddress class. + * The generator can create either valid or invalid DNS addresses based on the + * provided parameter. It combines an IP address (either IPv4 or IPv6) with an + * optional port number. The port is randomly included or excluded, and its value + * is not validated during DnsAddress validation. + * + * @param valid A boolean flag indicating whether to generate a valid (@c true ) or + * invalid (@c false ) DNS address. Defaults to @c true. + * @return A generator that produces @c openvpn::DnsAddress objects with either valid or + * invalid address values. + * + * Example usage: + * @code + * // Generate a valid DNS address + * auto validDnsAddr = *genDnsAddress(); + * + * // Generate an invalid DNS address + * auto invalidDnsAddr = *genDnsAddress(false); + * @endcode + */ +inline auto genDnsAddress(const bool valid = true) -> Gen<openvpn::DnsAddress> +{ + return gen::map( + gen::tuple( + gen::oneOf(IPv4Address(valid), IPv6Address(valid)), + gen::maybe(port(*rc::gen::arbitrary<bool>()))), // port is not checked during DnsAddress validation + [](const auto ¶ms) -> openvpn::DnsAddress + { + const auto &[address, maybe_port] = params; + openvpn::DnsAddress result; + result.address = address; + if (maybe_port) + { + result.port = *maybe_port; + } + return result; + }); +} + +/** + @brief Generates a DNS address as a string. + @details This function creates a generator that produces instances of the @c openvpn::DnsAddress class, + where the address is represented as a string. The generator can create either valid or invalid + DNS addresses based on the provided parameter. It combines an IP address (either IPv4 or IPv6) + with an optional port number. The port is randomly included or excluded. + @param valid Flag indicating the address should be constrained to valid values. + @return Gen<openvpn::DnsAddress> A generator that produces std::string objects with either + valid or invalid address values. +*/ +inline auto genDnsAddressAsStr(const bool valid = true) -> Gen<std::string> +{ + return gen::map( + gen::tuple( + gen::oneOf(IPv4Address(valid), IPv6Address(valid)), + gen::maybe(port(valid))), + [](const auto ¶ms) -> std::string + { + const auto &[address, maybe_port] = params; + openvpn::DnsAddress result; + result.address = address; + if (maybe_port) + { + result.port = *maybe_port; + } + return result.to_string(); + }); +} + +/** + * @brief Generates a DNS server. + * @details Creates a generator that produces random @c openvpn::DnsServer instances with populated fields. + * The generator creates: + * - A list of DNS addresses (using @c genDnsAddress ) + * - A list of DNS domains (using @c genDnsDomain ) + * - A DNSSEC security setting (using @c helpers::genDnsServerSecurity ) + * - A transport setting (using @c helpers::genDnsServerTransport ) + * - A random SNI string + * + * The vector sizes for addresses and domains are limited to a maximum of 100 elements. + * + * @return A generator that produces random @c openvpn::DnsServer instances. + */ +inline auto genDnsServer() -> Gen<openvpn::DnsServer> +{ + static constexpr auto MAX_VECTOR_SIZE = 100; + return gen::build( + gen::construct<openvpn::DnsServer>(), + gen::set(&openvpn::DnsServer::addresses, + gen::container<std::vector<openvpn::DnsAddress>>( + *gen::inRange<size_t>(0, MAX_VECTOR_SIZE), + genDnsAddress())), + gen::set(&openvpn::DnsServer::domains, + gen::container<std::vector<openvpn::DnsDomain>>( + *gen::inRange<size_t>(0, MAX_VECTOR_SIZE), + genDnsDomain())), + gen::set(&openvpn::DnsServer::dnssec, helpers::genDnsServerSecurity()), + gen::set(&openvpn::DnsServer::transport, helpers::genDnsServerTransport()), + gen::set(&openvpn::DnsServer::sni, gen::string<std::string>())); +} + +/** + * @brief Generates random DNS options. + * @details This function creates a generator for @c openvpn::DnsOptions objects with randomized values. + * It generates random DNS servers with priorities, search domains, and a boolean flag indicating + * whether the options should be derived from DHCP options. + * + * The generator uses helper functions to create components of the DnsOptions structure including + * - A random boolean for the @c from_dhcp_options flag + * - A vector of @c DnsDomain objects for search domains + * - A map of DNS servers with integer priorities + * + * @return A generator for random @c openvpn::DnsOptions. + */ +inline auto genDNSOptions() -> Gen<openvpn::DnsOptions> +{ + static constexpr auto MAX_CONTAINER_SIZE = 100; + auto generateDnsServerMap = []() -> Gen<std::map<int, openvpn::DnsServer>> + { + return gen::map( + gen::tuple( + gen::container<std::vector<openvpn::DnsServer>>( + *gen::inRange<size_t>(0, MAX_CONTAINER_SIZE), + genDnsServer()), + gen::unique<std::vector<int>>(*gen::inRange<size_t>(0, MAX_CONTAINER_SIZE), gen::nonNegative<int>())), + [](const auto ¶ms) -> std::map<int, openvpn::DnsServer> + { + const auto &[servers, priorities] = params; + std::map<int, openvpn::DnsServer> result; + + for (size_t i = 0; i < std::min(servers.size(), priorities.size()); ++i) + { + result[priorities[i]] = servers[i]; + } + + return result; + }); + }; + + return gen::build( + gen::construct<openvpn::DnsOptions>(), + gen::set(&openvpn::DnsOptions::from_dhcp_options, gen::arbitrary<bool>()), + gen::set(&openvpn::DnsOptions::search_domains, + gen::container<std::vector<openvpn::DnsDomain>>( + *gen::inRange<size_t>(0, MAX_CONTAINER_SIZE), + genDnsDomain())), + gen::set(&openvpn::DnsOptions::servers, generateDnsServerMap())); +} + +inline auto genIPAddr() -> Gen<openvpn::IP::Addr> +{ + return gen::map(gen::oneOf(IPv4Address(), IPv6Address()), + [](const std::string &ip) + { + return openvpn::IP::Addr::from_string(ip); + }); +} } // namespace rc #endif // TEST_GENERATORS_HPP diff --git a/test/unittests/test_header_deps.cpp b/test/unittests/test_header_deps.cpp index 9af883461..b0b23929c 100644 --- a/test/unittests/test_header_deps.cpp +++ b/test/unittests/test_header_deps.cpp @@ -6,7 +6,7 @@ using namespace openvpn; -TEST(misc, header_deps) +TEST(Misc, HeaderDeps) { // this is a compile test, no runtime value ASSERT_TRUE(true); diff --git a/test/unittests/test_headredact.cpp b/test/unittests/test_headredact.cpp index 7eeb744c8..e19a208e0 100644 --- a/test/unittests/test_headredact.cpp +++ b/test/unittests/test_headredact.cpp @@ -46,13 +46,13 @@ static const std::string out2 = "HEADERS: POST /pg HTTP/1.1\r\n" " Accept: */*\r\n" " \r\n"; -TEST(http, headredact1) +TEST(Http, Headredact1) { const std::string out = HTTP::headers_redact(in1); ASSERT_EQ(out, out1); } -TEST(http, headredact2) +TEST(Http, Headredact2) { const std::string out = HTTP::headers_redact(in2); ASSERT_EQ(out, out2); diff --git a/test/unittests/test_helper.hpp b/test/unittests/test_helper.hpp index 90e0f59be..5b4afa2fd 100644 --- a/test/unittests/test_helper.hpp +++ b/test/unittests/test_helper.hpp @@ -35,7 +35,7 @@ class LogOutputCollector : public LogBase void log(const std::string &l) override { - std::lock_guard<std::mutex> lock(mutex); + const std::lock_guard<std::mutex> lock(mutex); if (output_log) std::cout << l; @@ -151,7 +151,7 @@ extern openvpn::LogOutputCollector *testLog; */ inline void override_logOutput(bool doLogOutput, void (*test_func)()) { - bool previousOutputState = testLog->isStdoutEnabled(); + const bool previousOutputState = testLog->isStdoutEnabled(); testLog->setPrintOutput(doLogOutput); test_func(); testLog->setPrintOutput(previousOutputState); @@ -251,8 +251,8 @@ inline std::string getSortedString(const std::string &output) { std::stringstream ss{output}; - std::istream_iterator<detail::line> begin{ss}; - std::istream_iterator<detail::line> end; + const std::istream_iterator<detail::line> begin{ss}; + const std::istream_iterator<detail::line> end; std::vector<std::string> lines{begin, end}; // sort lines @@ -292,7 +292,7 @@ class FakeAsyncResolvable : public RESOLVABLE EndpointList endpoints; for (const auto &result : results) { - EndpointType ep(openvpn_io::ip::make_address(result.first), result.second); + const EndpointType ep(openvpn_io::ip::make_address(result.first), result.second); endpoints.push_back(ep); } results_[host + ":" + service] = std::move(endpoints); @@ -339,18 +339,18 @@ class FakeSecureRand : public openvpn::StrongRandomAPI { } - virtual std::string name() const override + std::string name() const override { return "FakeRNG"; } - virtual void rand_bytes(unsigned char *buf, size_t size) override + void rand_bytes(unsigned char *buf, size_t size) override { rand_bytes_(buf, size); // OPENVPN_LOG("RAND: " << openvpn::render_hex(buf, size)); } - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) override + bool rand_bytes_noexcept(unsigned char *buf, size_t size) override { rand_bytes(buf, size); return true; @@ -382,7 +382,7 @@ class unit_test_uniform_int_distribution uint32_t operator()(generator &prng) { /* Get random number in (0, range) first */ - uint32_t range = B - A + 1; + const uint32_t range = B - A + 1; uint64_t product = uint64_t{prng()} * uint64_t{range}; @@ -390,14 +390,14 @@ class unit_test_uniform_int_distribution if (low < range) { - uint32_t threshold = -range % range; + const uint32_t threshold = -range % range; while (low < threshold) { product = uint64_t{prng()} * uint64_t{range}; low = static_cast<uint32_t>(product); } } - return A + (product >> 32u); + return A + (product >> 32U); } explicit unit_test_uniform_int_distribution(uint32_t low = 0, uint32_t high = std::numeric_limits<uint32_t>::max()) diff --git a/test/unittests/test_hostport.cpp b/test/unittests/test_hostport.cpp index 6c0ff97cc..04ca9be23 100644 --- a/test/unittests/test_hostport.cpp +++ b/test/unittests/test_hostport.cpp @@ -35,7 +35,7 @@ static void test(const std::string &str, } } -TEST(misc, host_port) +TEST(Misc, HostPort) { test("foo.bar.gov", "", false, "", "", 0, false); test("foo.bar.gov", "1234", false, "foo.bar.gov", "1234", 1234, true); diff --git a/test/unittests/test_http_proxy.cpp b/test/unittests/test_http_proxy.cpp index d619acfd5..b35552fe7 100644 --- a/test/unittests/test_http_proxy.cpp +++ b/test/unittests/test_http_proxy.cpp @@ -37,7 +37,7 @@ TEST(HttpProxyClient, Options) ASSERT_EQ(po->password, "pazzword"); ASSERT_EQ(po->http_version, "1.1"); ASSERT_EQ(po->user_agent, "Mosaic/0.9"); - ASSERT_EQ(po->headers.size(), 1u); + ASSERT_EQ(po->headers.size(), 1U); ASSERT_EQ(po->headers.at(0)->p1, "X-Greeting"); ASSERT_EQ(po->headers.at(0)->p2, "Hi mom!"); diff --git a/test/unittests/test_intrinsic_type.cpp b/test/unittests/test_intrinsic_type.cpp new file mode 100644 index 000000000..ee76653c2 --- /dev/null +++ b/test/unittests/test_intrinsic_type.cpp @@ -0,0 +1,251 @@ + +#include "test_common.hpp" + +#include <openvpn/common/intrinsic_type.hpp> + +using namespace openvpn; + +template <typename BaseT> +using IntrinsicInt = IntrinsicType<BaseT, int>; + +// clang-format off +struct Thing1 : IntrinsicType<Thing1, int> { using IntrinsicType<Thing1, int>::IntrinsicType; }; +struct Thing2 : IntrinsicInt<Thing2> { using IntrinsicInt<Thing2>::IntrinsicInt; }; +// clang-format on + +inline auto f(const Thing1 t) +{ + return Thing1(t.get() * 2); +} + +inline auto f(const Thing2 t) +{ + return Thing2(t * 3); +} + +template <typename ThingT> +auto g(const ThingT &t) +{ + return ThingT(t * 4); +} + +TEST(IntrinsicType, Overload1) +{ + // EXPECT_EQ(f(2), 4); // fails, no match + // EXPECT_EQ(f(int(2)), int(4)); // fails, no match + EXPECT_EQ(f(Thing1(2)), Thing1(4)); + EXPECT_EQ(f(Thing2(2)), Thing2(6)); +} + +TEST(IntrinsicType, TemplateInst) +{ + EXPECT_EQ(g(2), 8); + EXPECT_EQ(g(Thing1(2)), Thing1(8)); + EXPECT_EQ(g(Thing2(2)), Thing2(8)); +} + +inline auto f(const int t) +{ + return t; +} + +TEST(IntrinsicType, Overload2) +{ + EXPECT_EQ(f(2), 2); // now it's fine + EXPECT_EQ(f(f(Thing1(1))), Thing1(4)); + EXPECT_EQ(f(f(Thing2(1))), Thing2(9)); +} + +TEST(IntrinsicType, LogicNot) +{ + auto a = Thing1(1); + + a = ~a; + + EXPECT_TRUE(a == Thing1(~1)); +} + +TEST(IntrinsicType, LogicOr0) +{ + auto a = Thing1(1); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a |= b; + + EXPECT_TRUE(a == Thing1(3)); + EXPECT_TRUE(b == Thing1(2)); +} + +TEST(IntrinsicType, LogicOr1) +{ + auto a = Thing1(1); + const Thing1 b(2); + constexpr Thing1 c(3); + const Thing1 d(4); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a | b), Thing1>)); + + EXPECT_TRUE((a | b) == Thing1(3)); + EXPECT_TRUE((a | b | c) == Thing1(3)); + EXPECT_TRUE((a | b | c | d) == Thing1(7)); + + EXPECT_EQ(f(a | b), Thing1(6)); +} + +TEST(IntrinsicType, LogicAnd0) +{ + auto a = Thing1(1); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a &= b; + + EXPECT_TRUE(a == Thing1(0)); + EXPECT_TRUE(b == Thing1(2)); +} + +TEST(IntrinsicType, LogicAnd1) +{ + const Thing1 a(1); + const Thing1 b(2); + constexpr Thing1 c(3); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a & b), Thing1>)); + + EXPECT_TRUE((a & b) == Thing1(0)); + EXPECT_TRUE((a & c) == Thing1(1)); + EXPECT_TRUE((b & c) == Thing1(2)); + + EXPECT_EQ(f(a & c), Thing1(2)); +} + +TEST(IntrinsicType, MathAdd0) +{ + auto a = Thing1(1); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a += b; + + EXPECT_TRUE(a == Thing1(3)); + EXPECT_TRUE(b == Thing1(2)); +} + +TEST(IntrinsicType, MathAdd1) +{ + const Thing1 a(1); + const Thing1 b(2); + constexpr Thing1 c(3); + const Thing1 d(4); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a + b), Thing1>)); + + EXPECT_EQ((a + b), Thing1(3)); + EXPECT_EQ((a + b + c), Thing1(6)); + EXPECT_EQ((a + b + c + d), Thing1(10)); + + EXPECT_EQ(f(a + c), Thing1(8)); +} + +TEST(IntrinsicType, MathSub0) +{ + auto a = Thing1(1); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a -= b; + + EXPECT_TRUE(a == Thing1(-1)); + EXPECT_TRUE(b == Thing1(2)); +} + +TEST(IntrinsicType, MathSub1) +{ + const Thing1 a(1); + const Thing1 b(2); + constexpr Thing1 c(3); + const Thing1 d(4); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a - b), Thing1>)); + + EXPECT_EQ(Thing1(a - b), Thing1(-1)); + EXPECT_TRUE((a - b - c) == Thing1(-4)); + EXPECT_TRUE((a - b - c - d) == Thing1(-8)); + + EXPECT_EQ(f(a - c), Thing1(-4)); +} + +TEST(IntrinsicType, MathMul0) +{ + auto a = Thing1(1); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a *= b; + + EXPECT_EQ(a, Thing1(2)); + EXPECT_EQ(b, Thing1(2)); +} + +TEST(IntrinsicType, MathMul1) +{ + const Thing1 a(1); + const Thing1 b(2); + constexpr Thing1 c(3); + const Thing1 d(4); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a * b), Thing1>)); + + EXPECT_EQ((a * b), Thing1(2)); + EXPECT_EQ((a * b * c), Thing1(6)); + EXPECT_EQ((a * b * c * d), Thing1(24)); + + EXPECT_EQ(f(a * c), Thing1(6)); +} + +TEST(IntrinsicType, MathDiv0) +{ + auto a = Thing1(4); + const Thing1 b(2); + + EXPECT_FALSE(a == b); + + a /= b; + + EXPECT_EQ(a, Thing1(2)); + EXPECT_EQ(b, Thing1(2)); +} + +TEST(IntrinsicType, MathDiv1) +{ + const Thing1 a(120); + const Thing1 b(2); + constexpr Thing1 c(3); + const Thing1 d(4); + + EXPECT_FALSE(a == b); + + EXPECT_TRUE((std::is_same_v<decltype(a / b), Thing1>)); + + EXPECT_EQ((a / b), Thing1(60)); + EXPECT_EQ((a / b / c), Thing1(20)); + EXPECT_EQ((a / b / c / d), Thing1(5)); + + EXPECT_EQ(f(a / c), Thing1(80)); +} diff --git a/test/unittests/test_ip.cpp b/test/unittests/test_ip.cpp index 1845284fc..b977033b4 100644 --- a/test/unittests/test_ip.cpp +++ b/test/unittests/test_ip.cpp @@ -30,25 +30,25 @@ static const uint8_t icmp6_packet[] = { static bool verbose = false; -TEST(IPAddr, icmp6csum) +TEST(IPAddr, Icmp6csum) { const ICMPv6 *icmp = (const ICMPv6 *)icmp6_packet; const size_t len = sizeof(icmp6_packet); if (verbose) { - std::cout << "From : " << IPv6::Addr::from_in6_addr(&icmp->head.saddr).to_string() << std::endl; - std::cout << "To : " << IPv6::Addr::from_in6_addr(&icmp->head.daddr).to_string() << std::endl; + std::cout << "From : " << IPv6::Addr::from_in6_addr(&icmp->head.saddr).to_string() << '\n'; + std::cout << "To : " << IPv6::Addr::from_in6_addr(&icmp->head.daddr).to_string() << '\n'; } const std::uint16_t csum = Ping6::csum_icmp(icmp, len); if (verbose) { - std::cout << "Checksum: " << csum << std::endl; + std::cout << "Checksum: " << csum << '\n'; } ASSERT_TRUE(csum == 0) << "checksum=" << csum << " but should be zero"; } -TEST(IPAddr, pool) +TEST(IPAddr, Pool) { IP::Pool pool; pool.add_range(IP::Range(IP::Addr::from_string("1.2.3.4"), 16)); @@ -74,7 +74,7 @@ TEST(IPAddr, pool) { if (pool.acquire_addr(addr)) { - s << addr << " (" << pool.n_in_use() << ")" << std::endl; + s << addr << " (" << pool.n_in_use() << ")\n"; } else break; @@ -163,7 +163,7 @@ void do_shift_tests(const std::vector<test_case> &test_vectors, bool leftshift) } if (memcmp(&cmp, &ret, sizeof(sockaddr_in6)) != 0) - std::cout << "BROKEN " << std::to_string(t.shift) << std::endl; + std::cout << "BROKEN " << std::to_string(t.shift) << '\n'; EXPECT_EQ(memcmp(&cmp, &ret, sizeof(sockaddr_in6)), 0); } @@ -171,87 +171,100 @@ void do_shift_tests(const std::vector<test_case> &test_vectors, bool leftshift) /* test vectors are generated with gen_ip_shifts.py */ -TEST(IPAddr, left_shift) +TEST(IPAddr, LeftShift) { - std::vector<test_case> tests{{0, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, - {1, {0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77, 0x99, 0xbb, 0xdd, 0xfe}}, - {31, {0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f, 0x80, 0x0, 0x0, 0x0}}, - {32, {0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0}}, - {33, {0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77, 0x99, 0xbb, 0xdd, 0xfe, 0x0, 0x0, 0x0, 0x0}}, - {45, {0xce, 0xf1, 0x13, 0x20, 0x15, 0x57, 0x79, 0x9b, 0xbd, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {63, {0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {64, {0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {67, {0xc8, 0x5, 0x55, 0xde, 0x66, 0xef, 0x77, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {80, {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {97, {0x99, 0xbb, 0xdd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {127, {0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {128, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}; + // clang-format off + const std::vector<test_case> tests{ + {.shift = 0, .ip = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, + {.shift = 1, .ip = {0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77, 0x99, 0xbb, 0xdd, 0xfe}}, + {.shift = 31, .ip = {0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f, 0x80, 0x0, 0x0, 0x0} }, + {.shift = 32, .ip = {0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 33, .ip = {0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77, 0x99, 0xbb, 0xdd, 0xfe, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 45, .ip = {0xce, 0xf1, 0x13, 0x20, 0x15, 0x57, 0x79, 0x9b, 0xbd, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 63, .ip = {0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 64, .ip = {0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 67, .ip = {0xc8, 0x5, 0x55, 0xde, 0x66, 0xef, 0x77, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 80, .ip = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 97, .ip = {0x99, 0xbb, 0xdd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 127, .ip = {0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 128, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} } + }; + // clang-format on do_shift_tests(tests, true); } -TEST(IPAddr, left_shift_random) +TEST(IPAddr, LeftShiftRandom) { - std::vector<test_case> tests{ - {0, {0xbc, 0x46, 0xc, 0xcb, 0x8f, 0x85, 0x25, 0x9a, 0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0}}, - {1, {0x78, 0x8c, 0x19, 0x97, 0x1f, 0xa, 0x4b, 0x34, 0xe9, 0x23, 0xa9, 0x1, 0xda, 0x5b, 0xd1, 0xc0}}, - {31, {0xc7, 0xc2, 0x92, 0xcd, 0x3a, 0x48, 0xea, 0x40, 0x76, 0x96, 0xf4, 0x70, 0x0, 0x0, 0x0, 0x0}}, - {32, {0x8f, 0x85, 0x25, 0x9a, 0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0}}, - {33, {0x1f, 0xa, 0x4b, 0x34, 0xe9, 0x23, 0xa9, 0x1, 0xda, 0x5b, 0xd1, 0xc0, 0x0, 0x0, 0x0, 0x0}}, - {45, {0xa4, 0xb3, 0x4e, 0x92, 0x3a, 0x90, 0x1d, 0xa5, 0xbd, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {63, {0x3a, 0x48, 0xea, 0x40, 0x76, 0x96, 0xf4, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {64, {0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {67, {0xa4, 0x8e, 0xa4, 0x7, 0x69, 0x6f, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {80, {0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {97, {0xda, 0x5b, 0xd1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {127, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {128, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}; + // clang-format off + const std::vector<test_case> tests{ + {.shift = 0, .ip = {0xbc, 0x46, 0xc, 0xcb, 0x8f, 0x85, 0x25, 0x9a, 0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0}}, + {.shift = 1, .ip = {0x78, 0x8c, 0x19, 0x97, 0x1f, 0xa, 0x4b, 0x34, 0xe9, 0x23, 0xa9, 0x1, 0xda, 0x5b, 0xd1, 0xc0} }, + {.shift = 31, .ip = {0xc7, 0xc2, 0x92, 0xcd, 0x3a, 0x48, 0xea, 0x40, 0x76, 0x96, 0xf4, 0x70, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 32, .ip = {0x8f, 0x85, 0x25, 0x9a, 0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 33, .ip = {0x1f, 0xa, 0x4b, 0x34, 0xe9, 0x23, 0xa9, 0x1, 0xda, 0x5b, 0xd1, 0xc0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 45, .ip = {0xa4, 0xb3, 0x4e, 0x92, 0x3a, 0x90, 0x1d, 0xa5, 0xbd, 0x1c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 63, .ip = {0x3a, 0x48, 0xea, 0x40, 0x76, 0x96, 0xf4, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 64, .ip = {0x74, 0x91, 0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 67, .ip = {0xa4, 0x8e, 0xa4, 0x7, 0x69, 0x6f, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 80, .ip = {0xd4, 0x80, 0xed, 0x2d, 0xe8, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 97, .ip = {0xda, 0x5b, 0xd1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 127, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 128, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} } + }; + // clang-format on do_shift_tests(tests, true); } -TEST(IPAddr, right_shift) +TEST(IPAddr, RightShift) { - std::vector<test_case> tests{ - {0, {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, - {1, {0x8, 0x91, 0x19, 0xa2, 0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f}}, - {31, {0x0, 0x0, 0x0, 0x0, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77}}, - {32, {0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb}}, - {33, {0x0, 0x0, 0x0, 0x0, 0x8, 0x91, 0x19, 0xa2, 0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d}}, - {45, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x89, 0x11, 0x9a, 0x22, 0xab, 0x33, 0xbc, 0x44, 0xc8, 0x5}}, - {63, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11}}, - {64, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}}, - {67, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x24, 0x46, 0x68, 0x8a, 0xac, 0xce, 0xf1}}, - {80, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}, - {97, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x91, 0x19, 0xa2}}, - {127, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {128, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}; + // clang-format off + const std::vector<test_case> tests{ + {.shift = 0, .ip = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, + {.shift = 1, .ip = {0x8, 0x91, 0x19, 0xa2, 0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d, 0xe6, 0x6e, 0xf7, 0x7f}}, + {.shift = 31, .ip = {0x0, 0x0, 0x0, 0x0, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11, 0x32, 0x1, 0x55, 0x77}}, + {.shift = 32, .ip = {0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x0, 0xaa, 0xbb}}, + {.shift = 33, .ip = {0x0, 0x0, 0x0, 0x0, 0x8, 0x91, 0x19, 0xa2, 0x2a, 0xb3, 0x3b, 0xc4, 0x4c, 0x80, 0x55, 0x5d}}, + {.shift = 45, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x89, 0x11, 0x9a, 0x22, 0xab, 0x33, 0xbc, 0x44, 0xc8, 0x5}}, + {.shift = 63, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xef, 0x11}}, + {.shift = 64, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}}, + {.shift = 67, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x24, 0x46, 0x68, 0x8a, 0xac, 0xce, 0xf1}}, + {.shift = 80, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}, + {.shift = 97, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x91, 0x19, 0xa2}}, + {.shift = 127, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, + {.shift = 128, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}; + // clang-format on do_shift_tests(tests, false); } -TEST(IPAddr, right_shift_random) +TEST(IPAddr, RightShiftRandom) { - std::vector<test_case> tests{{0, {0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25, 0x42, 0x83, 0x27, 0x83, 0xa9, 0x27, 0x2d, 0x3}}, - {1, {0x36, 0xfd, 0xa5, 0xa, 0xd9, 0xb5, 0x6c, 0x12, 0xa1, 0x41, 0x93, 0xc1, 0xd4, 0x93, 0x96, 0x81}}, - {31, {0x0, 0x0, 0x0, 0x0, 0xdb, 0xf6, 0x94, 0x2b, 0x66, 0xd5, 0xb0, 0x4a, 0x85, 0x6, 0x4f, 0x7}}, - {32, {0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25, 0x42, 0x83, 0x27, 0x83}}, - {33, {0x0, 0x0, 0x0, 0x0, 0x36, 0xfd, 0xa5, 0xa, 0xd9, 0xb5, 0x6c, 0x12, 0xa1, 0x41, 0x93, 0xc1}}, - {45, {0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x6f, 0xda, 0x50, 0xad, 0x9b, 0x56, 0xc1, 0x2a, 0x14, 0x19}}, - {63, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdb, 0xf6, 0x94, 0x2b, 0x66, 0xd5, 0xb0, 0x4a}}, - {64, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25}}, - {67, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xbf, 0x69, 0x42, 0xb6, 0x6d, 0x5b, 0x4}}, - {80, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a}}, - {97, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0xfd, 0xa5, 0xa}}, - {127, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, - {128, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}; + // clang-format off + const std::vector<test_case> tests{ + {.shift = 0, .ip = {0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25, 0x42, 0x83, 0x27, 0x83, 0xa9, 0x27, 0x2d, 0x3}}, + {.shift = 1, .ip = {0x36, 0xfd, 0xa5, 0xa, 0xd9, 0xb5, 0x6c, 0x12, 0xa1, 0x41, 0x93, 0xc1, 0xd4, 0x93, 0x96, 0x81}}, + {.shift = 31, .ip = {0x0, 0x0, 0x0, 0x0, 0xdb, 0xf6, 0x94, 0x2b, 0x66, 0xd5, 0xb0, 0x4a, 0x85, 0x6, 0x4f, 0x7} }, + {.shift = 32, .ip = {0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25, 0x42, 0x83, 0x27, 0x83} }, + {.shift = 33, .ip = {0x0, 0x0, 0x0, 0x0, 0x36, 0xfd, 0xa5, 0xa, 0xd9, 0xb5, 0x6c, 0x12, 0xa1, 0x41, 0x93, 0xc1} }, + {.shift = 45, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x6f, 0xda, 0x50, 0xad, 0x9b, 0x56, 0xc1, 0x2a, 0x14, 0x19} }, + {.shift = 63, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdb, 0xf6, 0x94, 0x2b, 0x66, 0xd5, 0xb0, 0x4a} }, + {.shift = 64, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a, 0xd8, 0x25} }, + {.shift = 67, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xbf, 0x69, 0x42, 0xb6, 0x6d, 0x5b, 0x4} }, + {.shift = 80, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6d, 0xfb, 0x4a, 0x15, 0xb3, 0x6a} }, + {.shift = 97, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0xfd, 0xa5, 0xa} }, + {.shift = 127, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }, + {.shift = 128, .ip = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} } + }; + // clang-format on do_shift_tests(tests, false); } -TEST(IPAddr, mapped_v4) +TEST(IPAddr, MappedV4) { - IP::Addr v6mapped{"::ffff:2332:123a"}; + const IP::Addr v6mapped{"::ffff:2332:123a"}; EXPECT_TRUE(v6mapped.is_mapped_address()); - IP::Addr notMapped = v6mapped.to_v4_addr(); + const IP::Addr notMapped = v6mapped.to_v4_addr(); EXPECT_EQ(v6mapped.to_string(), "::ffff:35.50.18.58"); EXPECT_EQ(notMapped.to_string(), "35.50.18.58"); diff --git a/test/unittests/test_iphelper.cpp b/test/unittests/test_iphelper.cpp index f79b6c7a4..1b8899b94 100644 --- a/test/unittests/test_iphelper.cpp +++ b/test/unittests/test_iphelper.cpp @@ -34,7 +34,7 @@ class IpHelperTest : public testing::Test ::GetBestInterface(addr, &tap.index); } - virtual void TearDown() override + void TearDown() override { remove_cmds.execute(os); remove_cmds.clear(); diff --git a/test/unittests/test_log.cpp b/test/unittests/test_log.cpp index 49409520a..c0a030a4d 100644 --- a/test/unittests/test_log.cpp +++ b/test/unittests/test_log.cpp @@ -31,8 +31,8 @@ namespace unittests { TEST(LogInfoTest, TestLogInfo) { - std::string msg("logMessage"); - openvpn::ClientAPI::LogInfo logInfo(msg); + const std::string msg("logMessage"); + const openvpn::ClientAPI::LogInfo logInfo(msg); ASSERT_EQ(logInfo.text, msg); } diff --git a/test/unittests/test_loggingmixin.cpp b/test/unittests/test_loggingmixin.cpp index 2c74dbae1..68998ed59 100644 --- a/test/unittests/test_loggingmixin.cpp +++ b/test/unittests/test_loggingmixin.cpp @@ -6,7 +6,7 @@ using namespace openvpn; using namespace openvpn::logging; -TEST(LoggingMixin, is_shared) +TEST(LoggingMixin, IsShared) { auto lm1 = LoggingMixin<1>(); auto lm2 = LoggingMixin<1>(); @@ -16,7 +16,7 @@ TEST(LoggingMixin, is_shared) EXPECT_EQ(lm1.log_level(), lm2.log_level()); } -TEST(LoggingMixin, is_not_shared) +TEST(LoggingMixin, IsNotShared) { auto lm1 = LoggingMixin<1, 1, int>(); auto lm2 = LoggingMixin<1, 1, float>(); diff --git a/test/unittests/test_make_rc.cpp b/test/unittests/test_make_rc.cpp index 2b43a976b..5eb5b2178 100644 --- a/test/unittests/test_make_rc.cpp +++ b/test/unittests/test_make_rc.cpp @@ -32,21 +32,21 @@ void f_val(test1 t1, int i) } // The `direct_enable` test verifies that an RcEnable object can be created directly. -TEST(make_rc, direct_enable) +TEST(MakeRc, DirectEnable) { auto rct1 = RcEnable<test1>::Create(); EXPECT_EQ(rct1->i, 0); } // The `simple` test verifies that a reference-counted object can be created using `make_rc`. -TEST(make_rc, simple) +TEST(MakeRc, Simple) { auto rct1 = make_rc<test1>(); EXPECT_EQ(rct1->i, 0); } // The `move_init` test verifies that a reference-counted object can be created by moving an existing object. -TEST(make_rc, move_init) +TEST(MakeRc, MoveInit) { auto t = test1(); EXPECT_EQ(t.i, 0); @@ -57,7 +57,7 @@ TEST(make_rc, move_init) // The `move_init_call` test verifies that a reference-counted object can be created by moving an existing object // and passed to a function. -TEST(make_rc, move_init_call) +TEST(MakeRc, MoveInitCall) { auto t = test1(); EXPECT_EQ(t.i, 0); @@ -66,21 +66,21 @@ TEST(make_rc, move_init_call) } // Calls using ref -TEST(make_rc, call_value) +TEST(MakeRc, CallValue) { auto rct1 = RcEnable<test1>::Create(); f_ref(*rct1, 0); } // Calls using sliced value -TEST(make_rc, call_slice) +TEST(MakeRc, CallSlice) { auto rct1 = RcEnable<test1>::Create(); f_val(*rct1, 0); } // make_rc TS -TEST(make_rc, simple_ts) +TEST(MakeRc, SimpleTs) { auto rct1 = make_rc<test1, RC<thread_safe_refcount>>(); EXPECT_EQ(rct1->i, 0); diff --git a/test/unittests/test_mbedtls_authcert.cpp b/test/unittests/test_mbedtls_authcert.cpp index 4019437dd..193ea3e2d 100644 --- a/test/unittests/test_mbedtls_authcert.cpp +++ b/test/unittests/test_mbedtls_authcert.cpp @@ -90,7 +90,7 @@ vCM9eK5hz+PSFYduNlEvWDTwdO0BuDBT0iyL1y220jlZf0KCFQmRXD2rJazIvsaM\n\ -----END CERTIFICATE-----\n\ "; -TEST(authcert_mbedtls, ca) +TEST(AuthcertMbedtls, Ca) { AuthCert ac; MbedTLSContext::load_cert_info_into_authcert(ac, ca_str); @@ -100,7 +100,7 @@ TEST(authcert_mbedtls, ca) ASSERT_EQ(ac.to_string(), "CN=PG-MT-Test SN=7c:b8:49:01:03:b5:ed:06:ae:4f:24:c4:0c:ee:75:f3:34:9f:e3:2d ISSUER_FP=1d7dad803066f6d18771fb42b45a21618bb261cc"); } -TEST(authcert_mbedtls, cert) +TEST(AuthcertMbedtls, Cert) { AuthCert ac; MbedTLSContext::load_cert_info_into_authcert(ac, cert_str); @@ -110,7 +110,7 @@ TEST(authcert_mbedtls, cert) ASSERT_EQ(ac.to_string(), "CN=test-server SN=01 ISSUER_FP=d79cbf8db337fdb401d63a3a905a7bf712f693c1"); } -TEST(authcert_mbedtls, cert64) +TEST(AuthcertMbedtls, Cert64) { AuthCert ac; MbedTLSContext::load_cert_info_into_authcert(ac, cert64_str); @@ -120,7 +120,7 @@ TEST(authcert_mbedtls, cert64) ASSERT_EQ(ac.to_string(), "CN=test-server-64-bit-serial SN=01:23:45:67:89:ab:cd:ef ISSUER_FP=c62493563a3c04f6fbd839ef499394400a60ac55"); } -TEST(authcert_mbedtls, sn_0) +TEST(AuthcertMbedtls, Sn0) { AuthCert ac("sn_0", 0); ASSERT_TRUE(ac.defined()); @@ -129,7 +129,7 @@ TEST(authcert_mbedtls, sn_0) ASSERT_EQ(ac.to_string(), "CN=sn_0 SN=00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_1) +TEST(AuthcertMbedtls, Sn1) { AuthCert ac("sn_1", 1); ASSERT_TRUE(ac.defined()); @@ -138,7 +138,7 @@ TEST(authcert_mbedtls, sn_1) ASSERT_EQ(ac.to_string(), "CN=sn_1 SN=01 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_255) +TEST(AuthcertMbedtls, Sn255) { AuthCert ac("sn_255", 255); ASSERT_TRUE(ac.defined()); @@ -147,7 +147,7 @@ TEST(authcert_mbedtls, sn_255) ASSERT_EQ(ac.to_string(), "CN=sn_255 SN=ff ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_256) +TEST(AuthcertMbedtls, Sn256) { AuthCert ac("sn_256", 256); ASSERT_TRUE(ac.defined()); @@ -156,7 +156,7 @@ TEST(authcert_mbedtls, sn_256) ASSERT_EQ(ac.to_string(), "CN=sn_256 SN=01:00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_32bit_pre) +TEST(AuthcertMbedtls, Sn32bitPre) { AuthCert ac("sn_32bit_pre", 4294967295ll); ASSERT_TRUE(ac.defined()); @@ -165,7 +165,7 @@ TEST(authcert_mbedtls, sn_32bit_pre) ASSERT_EQ(ac.to_string(), "CN=sn_32bit_pre SN=ff:ff:ff:ff ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_32bit_post) +TEST(AuthcertMbedtls, Sn32bitPost) { AuthCert ac("sn_32bit_post", 4294967296ll); ASSERT_TRUE(ac.defined()); @@ -174,7 +174,7 @@ TEST(authcert_mbedtls, sn_32bit_post) ASSERT_EQ(ac.to_string(), "CN=sn_32bit_post SN=01:00:00:00:00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, sn_64bit) +TEST(AuthcertMbedtls, Sn64bit) { AuthCert ac("sn_64bit", 81985529216486895ll); ASSERT_TRUE(ac.defined()); @@ -183,7 +183,7 @@ TEST(authcert_mbedtls, sn_64bit) ASSERT_EQ(ac.to_string(), "CN=sn_64bit SN=01:23:45:67:89:ab:cd:ef ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_mbedtls, empty) +TEST(AuthcertMbedtls, Empty) { AuthCert ac; ASSERT_FALSE(ac.defined()); diff --git a/test/unittests/test_mbedtls_x509certinfo.cpp b/test/unittests/test_mbedtls_x509certinfo.cpp index d2a1aa4bd..d925bb70a 100644 --- a/test/unittests/test_mbedtls_x509certinfo.cpp +++ b/test/unittests/test_mbedtls_x509certinfo.cpp @@ -57,7 +57,7 @@ std::string test_cert = "-----BEGIN CERTIFICATE-----\n" "fYFKjF0w1F5ftfpCbucSMbqt\n" "-----END CERTIFICATE-----\n"; -TEST(mbedTLS_x509_get_subject, old_format) +TEST(MbedTLSX509GetSubject, OldFormat) { MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); std::string expect( @@ -68,7 +68,7 @@ TEST(mbedTLS_x509_get_subject, old_format) ASSERT_EQ(MbedTLSPKI::x509_get_subject(x509crt.get(), false), expect); } -TEST(mbesTLS_x509_get_subject, new_format) +TEST(MbesTLSX509GetSubject, NewFormat) { MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); std::string expect( @@ -78,7 +78,7 @@ TEST(mbesTLS_x509_get_subject, new_format) ASSERT_EQ(MbedTLSPKI::x509_get_subject(x509crt.get(), true), expect); } -TEST(mbedTLS_x509_get_common_name, basic_check) +TEST(MbedTLSX509GetCommonName, BasicCheck) { MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); diff --git a/test/unittests/test_misc_unix.cpp b/test/unittests/test_misc_unix.cpp index 8590bf233..572e801df 100644 --- a/test/unittests/test_misc_unix.cpp +++ b/test/unittests/test_misc_unix.cpp @@ -13,7 +13,7 @@ std::string content1 = "It was a bright cold day in April, and the clocks\n" std::string content2 = "To be or not to be, that is the question?\n"; -TEST(misc, tempfile) +TEST(Misc, Tempfile) { TempFile tf(getTempDirPath("tempfile-XXXXXX"), true); @@ -29,35 +29,35 @@ TEST(misc, tempfile) ASSERT_EQ(s2, content2); } -TEST(misc, tempfile_name) +TEST(Misc, TempfileName) { - TempFile tf(getTempDirPath("tempfile-XXXXXX"), true); + const TempFile tf(getTempDirPath("tempfile-XXXXXX"), true); auto fn = tf.filename(); ASSERT_NE(std::string::npos, fn.find("tempfile-")); ASSERT_EQ(std::string::npos, fn.find("XXXXXX")); } -TEST(misc, tempfile_name_6Xs) +TEST(Misc, TempfileName6Xs) { - TempFile tf(getTempDirPath("tempXXXXXXfile"), true); + const TempFile tf(getTempDirPath("tempXXXXXXfile"), true); auto fn = tf.filename(); ASSERT_NE(std::string::npos, fn.find("temp")); ASSERT_NE(std::string::npos, fn.find("file")); ASSERT_EQ(std::string::npos, fn.find("XXXXXX")); } -TEST(misc, tempfile_name_7Xs) +TEST(Misc, TempfileName7Xs) { - TempFile tf(getTempDirPath("tempXXXXXXXfile"), true); + const TempFile tf(getTempDirPath("tempXXXXXXXfile"), true); auto fn = tf.filename(); ASSERT_NE(std::string::npos, fn.find("temp")); ASSERT_NE(std::string::npos, fn.find("file")); ASSERT_EQ(std::string::npos, fn.find("XXXXXX")); } -TEST(misc, tempfile_name_6X6X) +TEST(Misc, TempfileName6X6X) { - TempFile tf(getTempDirPath("tempXXXXXXfile-XXXXXX"), true); + const TempFile tf(getTempDirPath("tempXXXXXXfile-XXXXXX"), true); auto fn = tf.filename(); ASSERT_NE(std::string::npos, fn.find("temp")); ASSERT_NE(std::string::npos, fn.find("file")); diff --git a/test/unittests/test_numeric_cast.cpp b/test/unittests/test_numeric_cast.cpp index e4250d682..831b3dff5 100644 --- a/test/unittests/test_numeric_cast.cpp +++ b/test/unittests/test_numeric_cast.cpp @@ -22,74 +22,74 @@ using namespace openvpn::numeric_util; -TEST(numeric_cast, same_type_nocast1) +TEST(NumericCast, SameTypeNocast1) { - int32_t i32 = -1; + const int32_t i32 = -1; auto result = numeric_cast<int32_t>(i32); EXPECT_EQ(result, i32); } -TEST(numeric_cast, sign_mismatch_32_1) +TEST(NumericCast, SignMismatch321) { - int32_t i32 = -1; + const int32_t i32 = -1; EXPECT_THROW(numeric_cast<uint32_t>(i32), numeric_out_of_range); } -TEST(numeric_cast, sign_mismatch_32_2) +TEST(NumericCast, SignMismatch322) { - uint32_t u32 = std::numeric_limits<uint32_t>::max(); + const uint32_t u32 = std::numeric_limits<uint32_t>::max(); EXPECT_THROW(numeric_cast<int32_t>(u32), numeric_out_of_range); } -TEST(numeric_cast, sign_mismatch_32_3) +TEST(NumericCast, SignMismatch323) { - uint32_t u32 = 0; + const uint32_t u32 = 0; auto result = numeric_cast<int32_t>(u32); EXPECT_EQ(result, 0); } -TEST(numeric_cast, sign_mismatch_32_4) +TEST(NumericCast, SignMismatch324) { - uint32_t u32 = 42; + const uint32_t u32 = 42; auto result = numeric_cast<int32_t>(u32); EXPECT_EQ(result, 42); } -TEST(numeric_cast, sign_mismatch_32_5) +TEST(NumericCast, SignMismatch325) { - uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); + const uint32_t u32 = uint32_t(std::numeric_limits<int32_t>::max()); auto result = numeric_cast<int32_t>(u32); EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); } -TEST(numeric_cast, sign_mismatch_32_6) +TEST(NumericCast, SignMismatch326) { - int32_t s32 = std::numeric_limits<int32_t>::max(); + const int32_t s32 = std::numeric_limits<int32_t>::max(); EXPECT_THROW(numeric_cast<uint8_t>(s32), numeric_out_of_range); } -TEST(numeric_cast, sign_mismatch_32_7) +TEST(NumericCast, SignMismatch327) { - int32_t s32 = 42; + const int32_t s32 = 42; auto result = numeric_cast<uint8_t>(s32); EXPECT_EQ(result, 42); } -TEST(numeric_cast, s_range_mismatch_16_64_1) +TEST(NumericCast, SRangeMismatch16641) { - int64_t s64 = std::numeric_limits<int64_t>::max(); + const int64_t s64 = std::numeric_limits<int64_t>::max(); EXPECT_THROW(numeric_cast<int16_t>(s64), numeric_out_of_range); } -TEST(numeric_cast, s_range_match_16_64_1) +TEST(NumericCast, SRangeMatch16641) { - int64_t s64 = 0; + const int64_t s64 = 0; auto result = numeric_cast<int16_t>(s64); EXPECT_EQ(result, 0); } -TEST(numeric_cast, u_range_mismatch_16_64_1) +TEST(NumericCast, URangeMismatch16641) { - uint64_t u64 = std::numeric_limits<uint64_t>::max(); + const uint64_t u64 = std::numeric_limits<uint64_t>::max(); EXPECT_THROW(numeric_cast<uint16_t>(u64), numeric_out_of_range); } diff --git a/test/unittests/test_openssl_authcert.cpp b/test/unittests/test_openssl_authcert.cpp index 4f2a371e7..6a27e36a3 100644 --- a/test/unittests/test_openssl_authcert.cpp +++ b/test/unittests/test_openssl_authcert.cpp @@ -124,7 +124,7 @@ nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=\n\ -----END CERTIFICATE-----\n\ "; -TEST(authcert_openssl, ca) +TEST(AuthcertOpenssl, Ca) { AuthCert ac; OpenSSLContext::load_cert_info_into_authcert(ac, ca_str); @@ -134,7 +134,7 @@ TEST(authcert_openssl, ca) ASSERT_EQ(ac.to_string(), "CN=PG-MT-Test SN=7c:b8:49:01:03:b5:ed:06:ae:4f:24:c4:0c:ee:75:f3:34:9f:e3:2d ISSUER_FP=1d7dad803066f6d18771fb42b45a21618bb261cc"); } -TEST(authcert_openssl, cert) +TEST(AuthcertOpenssl, Cert) { AuthCert ac; OpenSSLContext::load_cert_info_into_authcert(ac, cert_str); @@ -144,7 +144,7 @@ TEST(authcert_openssl, cert) ASSERT_EQ(ac.to_string(), "CN=test-server SN=01 ISSUER_FP=d79cbf8db337fdb401d63a3a905a7bf712f693c1"); } -TEST(authcert_openssl, cert64) +TEST(AuthcertOpenssl, Cert64) { AuthCert ac; OpenSSLContext::load_cert_info_into_authcert(ac, cert64_str); @@ -154,77 +154,77 @@ TEST(authcert_openssl, cert64) ASSERT_EQ(ac.to_string(), "CN=test-server-64-bit-serial SN=01:23:45:67:89:ab:cd:ef ISSUER_FP=c62493563a3c04f6fbd839ef499394400a60ac55"); } -TEST(authcert_openssl, sn_0) +TEST(AuthcertOpenssl, Sn0) { - AuthCert ac("sn_0", 0); + const AuthCert ac("sn_0", 0); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); ASSERT_EQ(ac.serial_number_as_int64(), 0); ASSERT_EQ(ac.to_string(), "CN=sn_0 SN=00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_1) +TEST(AuthcertOpenssl, Sn1) { - AuthCert ac("sn_1", 1); + const AuthCert ac("sn_1", 1); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); ASSERT_EQ(ac.serial_number_as_int64(), 1); ASSERT_EQ(ac.to_string(), "CN=sn_1 SN=01 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_255) +TEST(AuthcertOpenssl, Sn255) { - AuthCert ac("sn_255", 255); + const AuthCert ac("sn_255", 255); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); ASSERT_EQ(ac.serial_number_as_int64(), 255); ASSERT_EQ(ac.to_string(), "CN=sn_255 SN=ff ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_256) +TEST(AuthcertOpenssl, Sn256) { - AuthCert ac("sn_256", 256); + const AuthCert ac("sn_256", 256); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); ASSERT_EQ(ac.serial_number_as_int64(), 256); ASSERT_EQ(ac.to_string(), "CN=sn_256 SN=01:00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_32bit_pre) +TEST(AuthcertOpenssl, Sn32bitPre) { - AuthCert ac("sn_32bit_pre", 4294967295ll); + const AuthCert ac("sn_32bit_pre", 4294967295LL); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); - ASSERT_EQ(ac.serial_number_as_int64(), 4294967295ll); + ASSERT_EQ(ac.serial_number_as_int64(), 4294967295LL); ASSERT_EQ(ac.to_string(), "CN=sn_32bit_pre SN=ff:ff:ff:ff ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_32bit_post) +TEST(AuthcertOpenssl, Sn32bitPost) { - AuthCert ac("sn_32bit_post", 4294967296ll); + const AuthCert ac("sn_32bit_post", 4294967296LL); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); - ASSERT_EQ(ac.serial_number_as_int64(), 4294967296ll); + ASSERT_EQ(ac.serial_number_as_int64(), 4294967296LL); ASSERT_EQ(ac.to_string(), "CN=sn_32bit_post SN=01:00:00:00:00 ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, sn_64bit) +TEST(AuthcertOpenssl, Sn64bit) { - AuthCert ac("sn_64bit", 81985529216486895ll); + const AuthCert ac("sn_64bit", 81985529216486895LL); ASSERT_TRUE(ac.defined()); ASSERT_TRUE(ac.sn_defined()); - ASSERT_EQ(ac.serial_number_as_int64(), 81985529216486895ll); + ASSERT_EQ(ac.serial_number_as_int64(), 81985529216486895LL); ASSERT_EQ(ac.to_string(), "CN=sn_64bit SN=01:23:45:67:89:ab:cd:ef ISSUER_FP=0000000000000000000000000000000000000000"); } -TEST(authcert_openssl, empty) +TEST(AuthcertOpenssl, Empty) { - AuthCert ac; + const AuthCert ac; ASSERT_FALSE(ac.defined()); ASSERT_FALSE(ac.sn_defined()); } -TEST(authcert_openssl, neg) +TEST(AuthcertOpenssl, Neg) { AuthCert ac; OpenSSLContext::load_cert_info_into_authcert(ac, cert_neg_str); @@ -246,7 +246,7 @@ static void verify_serial_parse(const std::string &parse, const std::string &exp THROW_FMT("verify_serial_parse: roundtrip failed (to_string) parse=%s expected=%s actual=[%s,%s]", parse, expected, ser.to_string(), ser1.to_string()); } -TEST(authcert_openssl, serial_parse) +TEST(AuthcertOpenssl, SerialParse) { // successful cases verify_serial_parse("0", "00"); @@ -325,21 +325,21 @@ TEST(authcert_openssl, serial_parse) #ifdef OPENVPN_JSON_INTERNAL -TEST(authcert_openssl, sn_json_1) +TEST(AuthcertOpenssl, SnJson1) { const Json::Value jv(81985529216486895ll); const AuthCert::Serial ser(jv); ASSERT_EQ(ser.to_string(), "01:23:45:67:89:ab:cd:ef"); } -TEST(authcert_openssl, sn_json_2) +TEST(AuthcertOpenssl, SnJson2) { const Json::Value jv("01:23:45:67:89:ab:cd:ef"); const AuthCert::Serial ser(jv); ASSERT_EQ(ser.to_string(), "01:23:45:67:89:ab:cd:ef"); } -TEST(authcert_openssl, sn_json_type_err) +TEST(AuthcertOpenssl, SnJsonTypeErr) { JY_EXPECT_THROW( { diff --git a/test/unittests/test_openssl_misc.cpp b/test/unittests/test_openssl_misc.cpp index 8fa2f11a2..57afa7741 100644 --- a/test/unittests/test_openssl_misc.cpp +++ b/test/unittests/test_openssl_misc.cpp @@ -90,7 +90,7 @@ constexpr const char *laterne_signd = "-----BEGIN PKCS7-----\n" "-----END PKCS7-----"; -TEST(OpenSSL, verify_broken_pkcs7) +TEST(OpenSSL, VerifyBrokenPkcs7) { std::list<OpenSSLPKI::X509> certs; @@ -104,7 +104,7 @@ TEST(OpenSSL, verify_broken_pkcs7) "OpenSSLSign::verify_pkcs7: verification failed"); } -TEST(OpenSSL, verify_valid_pkcs7) +TEST(OpenSSL, VerifyValidPkcs7) { std::list<OpenSSLPKI::X509> certs; @@ -113,7 +113,7 @@ TEST(OpenSSL, verify_valid_pkcs7) EXPECT_NO_THROW(OpenSSLSign::verify_pkcs7(certs, laterne_sig, laterne)); } -TEST(OpenSSL, verify_nodetach_pkcs7) +TEST(OpenSSL, VerifyNodetachPkcs7) { std::list<OpenSSLPKI::X509> certs; diff --git a/test/unittests/test_openssl_x509certinfo.cpp b/test/unittests/test_openssl_x509certinfo.cpp index 4d84ecd33..70d248d22 100644 --- a/test/unittests/test_openssl_x509certinfo.cpp +++ b/test/unittests/test_openssl_x509certinfo.cpp @@ -57,10 +57,10 @@ std::string test_cert = "-----BEGIN CERTIFICATE-----\n" "fYFKjF0w1F5ftfpCbucSMbqt\n" "-----END CERTIFICATE-----\n"; -TEST(OpenSSL_X509_get_subject, old_format) +TEST(OpenSSLX509GetSubject, OldFormat) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect( + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const std::string expect( "/C=US/ST=CA/O=OpenVPN-TEST/CN=server-1.example.net/" "emailAddress=example-server@example.net"); @@ -68,35 +68,35 @@ TEST(OpenSSL_X509_get_subject, old_format) ASSERT_EQ(OpenSSLPKI::x509_get_subject(x509crt.obj(), false), expect); } -TEST(OpenSSL_X509_get_subject, new_format) +TEST(OpenSSLX509GetSubject, NewFormat) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect( + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const std::string expect( "C=US, ST=CA, O=OpenVPN-TEST, CN=server-1.example.net, " "emailAddress=example-server@example.net"); ASSERT_EQ(OpenSSLPKI::x509_get_subject(x509crt.obj(), true), expect); } -TEST(OpenSSL_X509_get_serial, numeric) +TEST(OpenSSLX509GetSerial, Numeric) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect("395452524166311612932"); + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const std::string expect("395452524166311612932"); ASSERT_EQ(OpenSSLPKI::x509_get_serial(x509crt.obj()), expect); } -TEST(OpenSSL_X509_get_serial, hexadecimal) +TEST(OpenSSLX509GetSerial, Hexadecimal) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect("15:70:01:97:88:30:94:92:04"); + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const std::string expect("15:70:01:97:88:30:94:92:04"); ASSERT_EQ(OpenSSLPKI::x509_get_serial_hex(x509crt.obj()), expect); } -TEST(OpenSSL_X509_get_field, basic_checks) +TEST(OpenSSLX509GetField, BasicChecks) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_commonName), "server-1.example.net"); @@ -115,16 +115,16 @@ TEST(OpenSSL_X509_get_field, basic_checks) ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_countryName), "US"); } -TEST(OpenSSL_X509_get_field, signature) +TEST(OpenSSLX509GetField, Signature) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); ASSERT_EQ(OpenSSLPKI::x509_get_signature_algorithm(x509crt.obj()), "RSA-SHA256"); } -TEST(x509_get_fingerprint, output) +TEST(X509GetFingerprint, Output) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); + const OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); const std::vector<uint8_t> fingerprint = { // clang-format off 0x44, 0xF5, 0xA6, 0x4D, 0x4A, 0xCB, 0x65, 0xE1, diff --git a/test/unittests/test_opensslpki.cpp b/test/unittests/test_opensslpki.cpp index 3e9a3381d..6dc955fc8 100644 --- a/test/unittests/test_opensslpki.cpp +++ b/test/unittests/test_opensslpki.cpp @@ -12,7 +12,7 @@ using namespace openvpn; -typedef CertCRLListTemplate<OpenSSLPKI::X509List, OpenSSLPKI::CRLList> CertCRLList; +using CertCRLList = CertCRLListTemplate<OpenSSLPKI::X509List, OpenSSLPKI::CRLList>; template <typename VEC> VEC move_contents(VEC &src) @@ -33,23 +33,23 @@ void move_contents(CertCRLList &dest, CertCRLList &src) void test_cert_crl() { - std::string cert_crl_txt = read_text(CERTDIR "/certcrl.pem"); + const std::string cert_crl_txt = read_text(CERTDIR "/certcrl.pem"); CertCRLList ccl, ccl2; ccl.parse_pem(cert_crl_txt, "TEST1"); - CertCRLList ccl1(ccl); + const CertCRLList ccl1(ccl); ccl2 = ccl1; ccl2 = ccl1; std::string rend2 = ccl2.render_pem(); CertCRLList ccl3; ccl3.parse_pem_file(CERTDIR "/certcrl.pem"); - std::string rend3 = ccl3.render_pem(); + const std::string rend3 = ccl3.render_pem(); ASSERT_EQ(rend2, rend3); CertCRLList ccl4(rend3, "TEST2"); - CertCRLList ccl5(std::move(ccl4)); + const CertCRLList ccl5(std::move(ccl4)); ccl2 = ccl5; rend2 = ccl2.render_pem(); ASSERT_EQ(rend2, rend3); @@ -59,7 +59,7 @@ void test_cert_crl() rend2 = ccl2.render_pem(); ASSERT_EQ(rend2, rend3); - OpenSSLPKI::X509Store xs(ccl2); + const OpenSSLPKI::X509Store xs(ccl2); // std::cout << rend2; } @@ -85,7 +85,7 @@ void test_output_pem() ASSERT_TRUE(cert); - std::string pem_out = OpenSSLPKI::X509_get_pem_encoding(cert); + const std::string pem_out = OpenSSLPKI::X509_get_pem_encoding(cert); EXPECT_EQ(pem_out, testcert); @@ -95,22 +95,22 @@ void test_output_pem() void test_pkey() { - std::string pkey_txt = read_text(CERTDIR "/key.pem"); + const std::string pkey_txt = read_text(CERTDIR "/key.pem"); OpenSSLPKI::PKey pkey, pkey2; pkey.parse_pem(pkey_txt, "TEST0", nullptr); - OpenSSLPKI::PKey pkey1(pkey); + const OpenSSLPKI::PKey pkey1(pkey); pkey2 = pkey1; pkey2 = pkey1; std::string rend2 = pkey2.render_pem(); - OpenSSLPKI::PKey pkey3(pkey_txt, "TEST2", nullptr); - std::string rend3 = pkey3.render_pem(); + const OpenSSLPKI::PKey pkey3(pkey_txt, "TEST2", nullptr); + const std::string rend3 = pkey3.render_pem(); ASSERT_EQ(rend2, rend3); OpenSSLPKI::PKey pkey4(rend3, "TEST3", nullptr); - OpenSSLPKI::PKey pkey5(std::move(pkey4)); + const OpenSSLPKI::PKey pkey5(std::move(pkey4)); pkey2 = pkey5; rend2 = pkey2.render_pem(); ASSERT_EQ(rend2, rend3); @@ -120,22 +120,22 @@ void test_pkey() void test_dh() { - std::string dh_txt = read_text(CERTDIR "/dh2048.pem"); + const std::string dh_txt = read_text(CERTDIR "/dh2048.pem"); OpenSSLPKI::DH dh, dh2; dh.parse_pem(dh_txt); - OpenSSLPKI::DH dh1(dh); + const OpenSSLPKI::DH dh1(dh); dh2 = dh1; dh2 = dh1; std::string rend2 = dh2.render_pem(); - OpenSSLPKI::DH dh3(dh_txt); - std::string rend3 = dh3.render_pem(); + const OpenSSLPKI::DH dh3(dh_txt); + const std::string rend3 = dh3.render_pem(); ASSERT_EQ(rend2, rend3); OpenSSLPKI::DH dh4(rend3); - OpenSSLPKI::DH dh5(std::move(dh4)); + const OpenSSLPKI::DH dh5(std::move(dh4)); dh2 = dh5; rend2 = dh2.render_pem(); ASSERT_EQ(rend2, rend3); @@ -145,17 +145,17 @@ void test_dh() static bool verbose_output = false; -TEST(PKI, crl) +TEST(PKI, Crl) { override_logOutput(verbose_output, test_cert_crl); } -TEST(PKI, pkey) +TEST(PKI, Pkey) { override_logOutput(verbose_output, test_pkey); } -TEST(PKI, dh) +TEST(PKI, Dh) { override_logOutput(verbose_output, test_dh); } \ No newline at end of file diff --git a/test/unittests/test_optfilt.cpp b/test/unittests/test_optfilt.cpp index 5cd0c9b51..b2ce24a63 100644 --- a/test/unittests/test_optfilt.cpp +++ b/test/unittests/test_optfilt.cpp @@ -63,22 +63,22 @@ TEST(PushedOptionsFilter, RouteNopullEnabled) testLog->startCollecting(); src.parse_from_config(nopull_options + extra_option, nullptr); dst.extend(src, &route_nopull_enabled); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(1u, dst.size()) - << "Too few options have been filtered by --route-nopull" << std::endl + ASSERT_EQ(1U, dst.size()) + << "Too few options have been filtered by --route-nopull\n" << filter_output; dst.update_map(); ASSERT_TRUE(dst.exists(extra_option)) - << "The wrong options have been filtered by --route-nopull:" << std::endl - << "expected: " << extra_option << " got: " << dst[0].ref(0) << std::endl + << "The wrong options have been filtered by --route-nopull:\n" + << "expected: " << extra_option << " got: " << dst[0].ref(0) << '\n' << filter_output; } TEST(PushedOptionsFilter, RouteNopullDisabled) { - OptionList cfg; + const OptionList cfg; PushedOptionsFilter route_nopull_disabled(cfg); const std::string extra_option("unfiltered-option"); @@ -89,10 +89,10 @@ TEST(PushedOptionsFilter, RouteNopullDisabled) testLog->startCollecting(); src.parse_from_config(nopull_options + extra_option, nullptr); dst.extend(src, &route_nopull_disabled); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); ASSERT_EQ(src.size(), dst.size()) - << "Too many options have been filtered by --route-nopull" << std::endl + << "Too many options have been filtered by --route-nopull\n" << filter_output; } @@ -110,10 +110,10 @@ TEST(PushedOptionsFilter, PullFilterAcceptAll) testLog->startCollecting(); src.parse_from_config(pull_filter_options, nullptr); dst.extend(src, &filter_none); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); ASSERT_EQ(src.size(), dst.size()) - << "Not all options have been accepted by --pull-filter" << std::endl + << "Not all options have been accepted by --pull-filter\n" << filter_output; } @@ -159,10 +159,10 @@ TEST(PushedOptionsFilter, PullFilterSingleQuote) testLog->startCollecting(); src.parse_from_config("route 1.1.1.1\nroute 2.2.2.2\nroute 1.2.3.4", nullptr); dst.extend(src, &filter); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(2u, dst.size()) - << "Too many options have been accepted by --pull-filter" << std::endl + ASSERT_EQ(2U, dst.size()) + << "Too many options have been accepted by --pull-filter\n" << filter_output; } @@ -189,10 +189,10 @@ TEST(PushedOptionsFilter, PullFilterIgnoreAll) testLog->startCollecting(); src.parse_from_config(pull_filter_options, nullptr); dst.extend(src, &filter_all); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(0u, dst.size()) - << "Not all options have been ignored by --pull-filter" << std::endl + ASSERT_EQ(0U, dst.size()) + << "Not all options have been ignored by --pull-filter\n" << filter_output; } @@ -230,10 +230,10 @@ TEST(PushedOptionsFilter, PullFilterAcceptWhitespace) testLog->startCollecting(); src.parse_from_config(pull_filter_options, nullptr); dst.extend(src, &accept_opt3); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(2u, dst.size()) - << "Not all option3's have been accepted by --pull-filter" << std::endl + ASSERT_EQ(2U, dst.size()) + << "Not all option3's have been accepted by --pull-filter\n" << filter_output; } @@ -254,15 +254,15 @@ TEST(PushedOptionsFilter, PullFilterIgnoreQuotedWhitespace) testLog->startCollecting(); src.parse_from_config(pull_filter_options, nullptr); dst.extend(src, &accept_opt2_single_space); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(1u, dst.size()) - << "Too many options have been accepted by --pull-filter" << std::endl + ASSERT_EQ(1U, dst.size()) + << "Too many options have been accepted by --pull-filter\n" << filter_output; dst.update_map(); ASSERT_EQ(dst[0].ref(1), "arg with space") - << "Too many options have been accepted by --pull-filter" << std::endl + << "Too many options have been accepted by --pull-filter\n" << filter_output; } @@ -285,30 +285,30 @@ TEST(PushedOptionsFilter, PullFilterOverrideRouteNopull) testLog->startCollecting(); src.parse_from_config(nopull_options, nullptr); dst.extend(src, &override_route_nopull); - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); - ASSERT_EQ(2u, dst.size()) - << "Expected two route option to be accepted" << std::endl + ASSERT_EQ(2U, dst.size()) + << "Expected two route option to be accepted\n" << filter_output; dst.update_map(); ASSERT_EQ(dst[0].ref(0), "route") - << dst[0].ref(0) << " instead of route option has been accepted" << std::endl + << dst[0].ref(0) << " instead of route option has been accepted\n" << filter_output; ASSERT_EQ(dst[1].ref(0), "route") - << dst[1].ref(0) << " instead of route option has been accepted" << std::endl + << dst[1].ref(0) << " instead of route option has been accepted\n" << filter_output; - ASSERT_EQ(3u, dst[0].size()) - << "The host route option has been accepted, expected network route" << std::endl + ASSERT_EQ(3U, dst[0].size()) + << "The host route option has been accepted, expected network route\n" << filter_output; - ASSERT_EQ(3u, dst[1].size()) - << "The host route option has been accepted, expected network route" << std::endl + ASSERT_EQ(3U, dst[1].size()) + << "The host route option has been accepted, expected network route\n" << filter_output; } TEST(PushedOptionsFilter, RejectDnsServerPrioNegative) { - OptionList cfg; + const OptionList cfg; PushedOptionsFilter filter_static(cfg); const std::string opt = "dns server -1 address ::1"; @@ -320,5 +320,5 @@ TEST(PushedOptionsFilter, RejectDnsServerPrioNegative) testLog->startCollecting(); JY_EXPECT_THROW(dst.extend(src, &filter_static), option_error, opt) - std::string filter_output(testLog->stopCollecting()); + const std::string filter_output(testLog->stopCollecting()); } diff --git a/test/unittests/test_optional_ref.cpp b/test/unittests/test_optional_ref.cpp new file mode 100644 index 000000000..1c56609c9 --- /dev/null +++ b/test/unittests/test_optional_ref.cpp @@ -0,0 +1,151 @@ + +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2024- OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see <http://www.gnu.org/licenses/>. +// +// +// Basic unit test for the openvpn/openssl/pki/x509certinfo.hpp functions +// + +#include "test_common.hpp" + +#include <openvpn/common/optional_ref.hpp> + + +struct test_optional +{ + int i = 0; +}; + +TEST(OptionalRefSuite, Simple) +{ + int i = 42; + auto o = openvpn::optional<int &>(i); + EXPECT_TRUE(o); + EXPECT_EQ(o.value(), i); + EXPECT_EQ(*o, i); +} + +TEST(OptionalRefSuite, SimpleConst) +{ + const int i = 42; + auto o = openvpn::optional<const int &>(i); + EXPECT_TRUE(o); + EXPECT_EQ(o.value(), i); + EXPECT_EQ(*o, i); +} + +TEST(OptionalRefSuite, AssignTo) +{ + int i = 42; + auto o = openvpn::optional<int &>(i); + int j = 0; + o = openvpn::optional<int &>(j); + j = 96; + EXPECT_TRUE(o); + EXPECT_EQ(o.value(), j); + EXPECT_EQ(*o, j); +} + +TEST(OptionalRefSuite, AssignThru) +{ + int i = 42; + auto o = openvpn::optional<int &>(i); + EXPECT_TRUE(o); + EXPECT_EQ(42, *o); + *o = 96; + EXPECT_EQ(i, 96); +} + +TEST(OptionalRefSuite, AssignPtrThru) +{ + int i = 42; + auto o = openvpn::optional<int &>(&i); + EXPECT_TRUE(o); + EXPECT_EQ(42, *o); + *o = 96; + EXPECT_EQ(i, 96); +} + +TEST(OptionalRefSuite, Invalid) +{ + auto o = openvpn::optional<int &>(); + EXPECT_THROW(o.value(), std::runtime_error); + EXPECT_THROW(*o, std::runtime_error); +} + +TEST(OptionalRefSuite, InvalidNullopt) +{ + auto o = openvpn::optional<int &>(std::nullopt); + EXPECT_THROW(o.value(), std::runtime_error); + EXPECT_THROW(*o, std::runtime_error); +} + +TEST(OptionalRefSuite, AssignNullopt) +{ + int i = 42; + auto o = openvpn::optional<int &>(i); + EXPECT_TRUE(o); + EXPECT_EQ(o.value(), i); + EXPECT_EQ(*o, i); + o = std::nullopt; + EXPECT_THROW(o.value(), std::runtime_error); + EXPECT_THROW(*o, std::runtime_error); +} + + +TEST(OptionalRefSuite, ValueOr) +{ + int i = 42; + auto o = openvpn::optional<int &>(i); + EXPECT_TRUE(o); + EXPECT_EQ(o.value_or(96), 42); +} + +TEST(OptionalRefSuite, ValueOrDefault) +{ + auto o = openvpn::optional<int &>(std::nullopt); + EXPECT_FALSE(o); + EXPECT_EQ(o.value_or(42), 42); +} + +TEST(OptionalRefSuite, ValueOrDefaultLvalue) +{ + auto o = openvpn::optional<int &>(std::nullopt); + EXPECT_FALSE(o); + const int i = 42; + EXPECT_EQ(o.value_or(i), i); +} + +TEST(OptionalRefSuite, Deref) +{ + auto t = test_optional(); + auto o = openvpn::optional<test_optional &>(t); + EXPECT_EQ(o->i, 0); + o->i = 42; + EXPECT_EQ(o->i, 42); +} + +TEST(OptionalRefSuite, DerefInvalid) +{ + auto o = openvpn::optional<test_optional &>(); + EXPECT_FALSE(o); + EXPECT_ANY_THROW([[maybe_unused]] auto t = o->i); +} diff --git a/test/unittests/test_ostream_containers.cpp b/test/unittests/test_ostream_containers.cpp index 56a1ca649..6518a19f6 100644 --- a/test/unittests/test_ostream_containers.cpp +++ b/test/unittests/test_ostream_containers.cpp @@ -8,9 +8,9 @@ using namespace openvpn; // simple use case example; cases will mostly look like this -TEST(ostream_container, simple_vector_int) +TEST(OstreamContainer, SimpleVectorInt) { - std::vector<int> vi{2, 4, 6, 8}; + const std::vector<int> vi{2, 4, 6, 8}; std::ostringstream oss; oss << C2os::cast(vi); @@ -80,7 +80,7 @@ const TestItem<ssi> set_int_tests[] = { TestItem<ssi>({}, "[]"), }; -TEST(ostream_container, set_int) +TEST(OstreamContainer, SetInt) { generic_test(set_int_tests); @@ -99,7 +99,7 @@ const TestItem<sls> list_string_tests[] = { TestItem<sls>({"Institute has", "the finest", "professors"}, "[Institute has, the finest, professors]"), }; -TEST(ostream_container, list_string) +TEST(OstreamContainer, ListString) { generic_test(list_string_tests); generic_ptr_test(list_string_tests); @@ -111,7 +111,7 @@ const TestItem<svc> vector_complex_tests[] = { TestItem<svc>({{-5, 0}, {18, 500}, {1e6, 32}}, "[(-5,0), (18,500), (1e+06,32)]"), }; -TEST(ostream_container, vector_complex) +TEST(OstreamContainer, VectorComplex) { generic_test(vector_complex_tests); generic_ptr_test(vector_complex_tests); @@ -137,7 +137,7 @@ const TestItem<sdm> deque_custom_tests[] = { TestItem<sdm>({{-5, 0}, {18, 500}, {1e6, 32}}, "[-5+i0, 18+i500, 1e+06+i32]"), }; -TEST(ostream_container, deque_custom) +TEST(OstreamContainer, DequeCustom) { generic_test(deque_custom_tests); generic_ptr_test(deque_custom_tests); diff --git a/test/unittests/test_parseargv.cpp b/test/unittests/test_parseargv.cpp index 3b721cc3b..62749e78b 100644 --- a/test/unittests/test_parseargv.cpp +++ b/test/unittests/test_parseargv.cpp @@ -54,7 +54,7 @@ static const char *input[] = { // clang-format on }; -TEST(argv, parse) +TEST(Argv, Parse) { const OptionList opt = OptionList::parse_from_argv_static(string::from_argv(sizeof(input) / sizeof(char *), const_cast<char **>(input), @@ -67,7 +67,7 @@ static const char config[] = "listen 1.2.3.4 1000 tcp 2\n" "listen ::0 8000 tcp\n" "listen sock/ststrack-%s.sock unix-stream\n"; -TEST(argv, portoffset1) +TEST(Argv, Portoffset1) { const OptionList opt1 = OptionList::parse_from_config_static(config, nullptr); const Listen::List ll1(opt1, "listen", Listen::List::Nominal, 4); @@ -88,7 +88,7 @@ TEST(argv, portoffset1) EXPECT_EQ(exp2, ll2.to_string()); } -TEST(argv, portoffset2) +TEST(Argv, Portoffset2) { const OptionList opt = OptionList::parse_from_config_static(config, nullptr); const Listen::List ll(opt, "listen", Listen::List::Nominal, 4); @@ -125,13 +125,13 @@ static void extract_ifconfig(const OptionList &opt) { const Option &o = opt.get("ifconfig"); o.exact_args(3); - std::string ip = IP::Addr::validate(o.ref(1), "ifconfig-ip"); - std::string mask = IP::Addr::validate(o.ref(2), "ifconfig-net"); + const std::string ip = IP::Addr::validate(o.ref(1), "ifconfig-ip"); + const std::string mask = IP::Addr::validate(o.ref(2), "ifconfig-net"); ASSERT_EQ("5.5.8.4", ip); ASSERT_EQ("255.255.252.0", mask); } -TEST(argv, parsetest) +TEST(Argv, Parsetest) { const std::string opt_csv = "explicit-exit-notify,topology subnet,route-delay 5 30,dhcp-pre-release,dhcp-renew,dhcp-release,route-metric 101,ping 5,ping-restart 40,redirect-gateway def1,redirect-gateway bypass-dhcp,redirect-gateway autolocal,route-gateway 5.5.8.1,dhcp-option DNS 172.16.0.23,register-dns,auth-token SESS_ID_wJdhHMc7tr9GwbMNEW6b+A==,comp-lzo no,ifconfig 5.5.8.4 255.255.252.0"; OptionList opt; @@ -160,7 +160,7 @@ TEST(argv, parsetest) extract_auth_token(opt); extract_ifconfig(opt); verify_topology(opt); - ASSERT_EQ(1066u, limits.get_bytes()); + ASSERT_EQ(1066U, limits.get_bytes()); } static void csv_test(const std::string &str) @@ -221,12 +221,12 @@ static void options_csv_test(const std::string &str, const std::string &elem) if (!elem.empty()) { - OptionList::IndexMap::const_iterator e = olist.map().find(elem); + const OptionList::IndexMap::const_iterator e = olist.map().find(elem); ASSERT_TRUE(e != olist.map().end()); } } -TEST(argv, parsetest1) +TEST(Argv, Parsetest1) { csv_test("this,is,,a,\"foo,bar\",test"); space_test(R"( this is a "foo \\ bar" test of something \"rather\" grt )", "this\nis\na\nfoo \\ bar\ntest\nof\nsomething\n\"rather\"\ngrt\n"); @@ -235,7 +235,7 @@ TEST(argv, parsetest1) ""); } -TEST(argv, QuotesTest) +TEST(Argv, QuotesTest) { auto str = "\"abc,def\",\'abc,def\',\"abc',def\",\'abc\"def\',\'abc\""; std::vector<std::string> list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(str, ','); diff --git a/test/unittests/test_path.cpp b/test/unittests/test_path.cpp index 132cf91c6..e56340937 100644 --- a/test/unittests/test_path.cpp +++ b/test/unittests/test_path.cpp @@ -12,43 +12,43 @@ static std::stringstream out; void test_basename(const std::string &path) { const std::string res = path::basename(path); - out << "basename('" << path << "') = '" << res << "'" << std::endl; + out << "basename('" << path << "') = '" << res << "'\n"; } void dirname(const std::string &path) { const std::string res = path::dirname(path); - out << "dirname('" << path << "') = '" << res << "'" << std::endl; + out << "dirname('" << path << "') = '" << res << "'\n"; } void ext(const std::string &path) { const std::string res = path::ext(path); - out << "ext('" << path << "') = '" << res << "'" << std::endl; + out << "ext('" << path << "') = '" << res << "'\n"; } void is_flat(const std::string &path) { const bool res = path::is_flat(path); - out << "is_flat('" << path << "') = " << res << std::endl; + out << "is_flat('" << path << "') = " << res << '\n'; } void join(const std::string &p1, const std::string &p2) { const std::string res = path::join(p1, p2); - out << "join('" << p1 << "', '" << p2 << "') = '" << res << "'" << std::endl; + out << "join('" << p1 << "', '" << p2 << "') = '" << res << "'\n"; } void join3(const std::string &p1, const std::string &p2, const std::string &p3) { const std::string res = path::join(p1, p2, p3); - out << "join('" << p1 << "', '" << p2 << "', '" << p3 << "') = '" << res << "'" << std::endl; + out << "join('" << p1 << "', '" << p2 << "', '" << p3 << "') = '" << res << "'\n"; } void join4(const std::string &p1, const std::string &p2, const std::string &p3, const std::string &p4) { const std::string res = path::join(p1, p2, p3, p4); - out << "join('" << p1 << "', '" << p2 << "', '" << p3 << "', '" << p4 << "') = '" << res << "'" << std::endl; + out << "join('" << p1 << "', '" << p2 << "', '" << p3 << "', '" << p4 << "') = '" << res << "'\n"; } void splitjoin(const std::string &p1) @@ -56,10 +56,10 @@ void splitjoin(const std::string &p1) const std::string d = path::dirname(p1); const std::string b = path::basename(p1); const std::string p2 = path::join(d, b); - out << "splitjoin p1='" << p1 << "' dir='" << d << "' bn='" << b << "' p2='" << p2 << "'" << std::endl; + out << "splitjoin p1='" << p1 << "' dir='" << d << "' bn='" << b << "' p2='" << p2 << "'\n"; } -TEST(path, test1) +TEST(Path, Test1) { out.clear(); out.str(""); @@ -137,7 +137,7 @@ void test_contained(const std::string &path, const bool expected) ASSERT_EQ(contained, expected); } -TEST(path, test2) +TEST(Path, Test2) { test_contained("", false); test_contained(".", true); @@ -167,14 +167,3 @@ TEST(path, test2) test_contained("foo/../bar", false); test_contained("foo/.../bar", true); } - -void test_join_speed() -{ - size_t count = 0; - for (int i = 0; i < 10000000; ++i) - { - const std::string s = path::join("one", "two", "three", "four"); - count += s.length(); - } - std::cout << count << std::endl; -} \ No newline at end of file diff --git a/test/unittests/test_peer_fingerprint.cpp b/test/unittests/test_peer_fingerprint.cpp index 1218a4e99..1dd1089e5 100644 --- a/test/unittests/test_peer_fingerprint.cpp +++ b/test/unittests/test_peer_fingerprint.cpp @@ -26,7 +26,7 @@ std::vector<uint8_t> test_fingerprint = { // clang-format on }; -TEST(PeerFingerprint, parse_config) +TEST(PeerFingerprint, ParseConfig) { OptionList cfg; cfg.parse_from_config( @@ -56,19 +56,19 @@ TEST(PeerFingerprint, parse_config) }; TestPeerFingerprints fps(cfg, test_fingerprint.size()); - ASSERT_EQ(fps.size(), 5u); + ASSERT_EQ(fps.size(), 5U); for (std::size_t i = 1; i <= fps.size(); ++i) { auto fingerprint = test_fingerprint; fingerprint[0] = static_cast<unsigned char>(i); - PeerFingerprint fp(fingerprint); + const PeerFingerprint fp(fingerprint); ASSERT_EQ(fps.match(fp), true); } } -TEST(PeerFingerprint, malformed) +TEST(PeerFingerprint, Malformed) { OptionList cfg; cfg.parse_from_config( @@ -116,24 +116,24 @@ TEST(PeerFingerprint, malformed) } -TEST(PeerFingerprint, stringify) +TEST(PeerFingerprint, Stringify) { - std::string hex_fp("01:f5:a6:4d:4a:cb:65:e1:8a:9f:55:89:7f:77:a0:79:aa:fb:cc:a1:37:2f:d8:b3:47:aa:9d:e3:d0:76:b1:55"); - PeerFingerprint fp(hex_fp, test_fingerprint.size()); + const std::string hex_fp("01:f5:a6:4d:4a:cb:65:e1:8a:9f:55:89:7f:77:a0:79:aa:fb:cc:a1:37:2f:d8:b3:47:aa:9d:e3:d0:76:b1:55"); + const PeerFingerprint fp(hex_fp, test_fingerprint.size()); ASSERT_EQ(fp.str(), hex_fp); } -TEST(PeerFingerprint, match_empty) +TEST(PeerFingerprint, MatchEmpty) { - PeerFingerprint fp(test_fingerprint); + const PeerFingerprint fp(test_fingerprint); PeerFingerprints fps; ASSERT_FALSE(fps); ASSERT_EQ(fps.match(fp), false); } -TEST(PeerFingerprint, match) +TEST(PeerFingerprint, Match) { OptionList cfg; cfg.parse_from_config( @@ -144,12 +144,12 @@ TEST(PeerFingerprint, match) nullptr); cfg.update_map(); - PeerFingerprint fp(test_fingerprint); - PeerFingerprints fps(cfg, test_fingerprint.size()); + const PeerFingerprint fp(test_fingerprint); + const PeerFingerprints fps(cfg, test_fingerprint.size()); ASSERT_EQ(fps.match(fp), true); } -TEST(PeerFingerprint, no_match) +TEST(PeerFingerprint, NoMatch) { OptionList cfg; cfg.parse_from_config( @@ -157,8 +157,8 @@ TEST(PeerFingerprint, no_match) nullptr); cfg.update_map(); - PeerFingerprint fp(test_fingerprint); - PeerFingerprints fps(cfg, test_fingerprint.size()); + const PeerFingerprint fp(test_fingerprint); + const PeerFingerprints fps(cfg, test_fingerprint.size()); ASSERT_EQ(fps.match(fp), false); } diff --git a/test/unittests/test_pipe.cpp b/test/unittests/test_pipe.cpp index a14174dc9..bd7d2b1cf 100644 --- a/test/unittests/test_pipe.cpp +++ b/test/unittests/test_pipe.cpp @@ -5,7 +5,7 @@ using namespace openvpn; -TEST(misc, pipe) +TEST(Misc, Pipe) { RedirectPipe::InOut io; diff --git a/test/unittests/test_pktid_control.cpp b/test/unittests/test_pktid_control.cpp index bd4177503..c79670c60 100644 --- a/test/unittests/test_pktid_control.cpp +++ b/test/unittests/test_pktid_control.cpp @@ -27,10 +27,10 @@ void testcase(PIDRecv &pr, ASSERT_EQ(status, expected_status); } -TEST(misc, pktid_test_control) +TEST(Misc, PktidTestControl) { - typedef PacketIDControlReceiveType<3, 5> PIDRecv; - SessionStats::Ptr stats(new SessionStats()); + using PIDRecv = PacketIDControlReceiveType<3, 5>; + const SessionStats::Ptr stats(new SessionStats()); PIDRecv pr; pr.init("test", 0, stats); @@ -94,7 +94,7 @@ void perfiter(const long n, const long iter_per_step_pre, long &count) { - typedef PacketIDControlReceiveType<ORDER, EXPIRE> PIDRecv; + using PIDRecv = PacketIDControlReceiveType<ORDER, EXPIRE>; const long iter_per_step = iter_per_step_pre * step; // OPENVPN_LOG("ITER order=" << ORDER << " n=" << n << " range=" << range << " step=" << step << " iter_per_step=" @@ -105,7 +105,7 @@ void perfiter(const long n, MTRand urand; std::vector<bool> bv(n); long high = 0; - SessionStats::Ptr stats(new SessionStats()); + const SessionStats::Ptr stats(new SessionStats()); PIDRecv pr; pr.init("test", 0, stats); @@ -142,7 +142,7 @@ void perfiter(const long n, template <unsigned int ORDER, unsigned int EXPIRE> void perf(long &count) { - typedef PacketIDControlReceiveType<ORDER, EXPIRE> PIDRecv; + using PIDRecv = PacketIDControlReceiveType<ORDER, EXPIRE>; perfiter<ORDER, EXPIRE>(20000, PIDRecv::REPLAY_WINDOW_SIZE * 3, 1, 10, count); perfiter<ORDER, EXPIRE>(20000, PIDRecv::REPLAY_WINDOW_SIZE * 3, PIDRecv::REPLAY_WINDOW_SIZE / 2, 10, count); @@ -154,7 +154,7 @@ void perf(long &count) perfiter<ORDER, EXPIRE>(20000, 4, PIDRecv::REPLAY_WINDOW_SIZE / 2, 10, count); } -TEST(misc, pktid_control_perf) +TEST(Misc, PktidControlPerf) { long count = 0; perf<3, 5>(count); diff --git a/test/unittests/test_pktid_data.cpp b/test/unittests/test_pktid_data.cpp index 3b75fdbb2..1412f99f2 100644 --- a/test/unittests/test_pktid_data.cpp +++ b/test/unittests/test_pktid_data.cpp @@ -20,7 +20,7 @@ void testcase(PIDRecv &pr, const PacketIDData::data_id_t pkt_id, const Error::Type expected_status) { - bool wide = pr.length() > 4; + const bool wide = pr.length() > 4; const PacketIDDataConstruct pid(pkt_id, wide); const Error::Type status = pr.do_test_add(pid, t); // OPENVPN_LOG("[" << t << "] id=" << pkt_id << ' ' << Error::name(status)); @@ -29,8 +29,8 @@ void testcase(PIDRecv &pr, void do_packet_id_recv_test_short_ids(bool usewide) { - typedef PacketIDDataReceiveType<3, 5> PIDRecv; - SessionStats::Ptr stats(new SessionStats()); + using PIDRecv = PacketIDDataReceiveType<3, 5>; + const SessionStats::Ptr stats(new SessionStats()); PIDRecv pr; pr.init("test", 0, usewide); @@ -60,11 +60,11 @@ void do_packet_id_recv_test_short_ids(bool usewide) testcase(pr, 41, 0xffffffff, Error::SUCCESS); } -TEST(misc, do_packet_id_recv_test_long_ids) +TEST(Misc, DoPacketIdRecvTestLongIds) { - typedef PacketIDDataReceiveType<3, 5> PIDRecv; + using PIDRecv = PacketIDDataReceiveType<3, 5>; PIDRecv pr; - SessionStats::Ptr stats{new SessionStats()}; + const SessionStats::Ptr stats{new SessionStats()}; pr.init("test", 0, true); testcase(pr, 40, 0xfffffffe, Error::SUCCESS); @@ -80,12 +80,12 @@ TEST(misc, do_packet_id_recv_test_long_ids) } -TEST(misc, pktid_test_data_32bit) +TEST(Misc, PktidTestData32bit) { do_packet_id_recv_test_short_ids(false); } -TEST(misc, pktid_test_data_64bit) +TEST(Misc, PktidTestData64bit) { do_packet_id_recv_test_short_ids(true); } @@ -98,7 +98,7 @@ void perfiter(const long n, const long iter_per_step_pre, long &count) { - typedef PacketIDDataReceiveType<ORDER, EXPIRE> PIDRecv; + using PIDRecv = PacketIDDataReceiveType<ORDER, EXPIRE>; const long iter_per_step = iter_per_step_pre * step; // OPENVPN_LOG("ITER order=" << ORDER << " n=" << n << " range=" << range << " step=" << step << " iter_per_step=" @@ -109,7 +109,7 @@ void perfiter(const long n, MTRand urand; std::vector<bool> bv(n); long high = 0; - SessionStats::Ptr stats(new SessionStats()); + const SessionStats::Ptr stats(new SessionStats()); PIDRecv pr; pr.init("test", 0, false); @@ -146,7 +146,7 @@ void perfiter(const long n, template <unsigned int ORDER, unsigned int EXPIRE> void perf(long &count) { - typedef PacketIDDataReceiveType<ORDER, EXPIRE> PIDRecv; + using PIDRecv = PacketIDDataReceiveType<ORDER, EXPIRE>; perfiter<ORDER, EXPIRE>(20000, PIDRecv::REPLAY_WINDOW_SIZE * 3, 1, 10, count); perfiter<ORDER, EXPIRE>(20000, PIDRecv::REPLAY_WINDOW_SIZE * 3, PIDRecv::REPLAY_WINDOW_SIZE / 2, 10, count); @@ -169,7 +169,7 @@ class PacketIDDataSendTest : public openvpn::PacketIDDataSend } }; -TEST(misc, pktid_32_bit_overrun_32bit_counter) +TEST(Misc, Pktid32BitOverrun32bitCounter) { PacketIDDataSendTest pidsend{false, 0xfffffffc}; @@ -183,7 +183,7 @@ TEST(misc, pktid_32_bit_overrun_32bit_counter) } -TEST(misc, pktid_32_bit_overrun_64bit_counter) +TEST(Misc, Pktid32BitOverrun64bitCounter) { PacketIDDataSendTest pidsend{true, 0xfffffffd}; @@ -201,7 +201,7 @@ TEST(misc, pktid_32_bit_overrun_64bit_counter) } -TEST(misc, pktid_64_bit_overrun_64bit_counter) +TEST(Misc, Pktid64BitOverrun64bitCounter) { PacketIDDataSendTest pidsend{true, 0xfffffffffffffffc}; @@ -214,7 +214,7 @@ TEST(misc, pktid_64_bit_overrun_64bit_counter) EXPECT_THROW(ret = pidsend.next(), PacketIDDataSend::packet_id_wrap); } -TEST(misc, pktid_32_bit_warn) +TEST(Misc, Pktid32BitWarn) { PacketIDDataSendTest pidsend{false, 0xfefffffe}; @@ -232,7 +232,7 @@ TEST(misc, pktid_32_bit_warn) EXPECT_TRUE(pidsend.wrap_warning()); } -TEST(misc, pktid_64_bit_warn_32bit) +TEST(Misc, Pktid64BitWarn32bit) { // Test we are not warning at 32bit PacketIDDataSendTest pidsend{true, 0xfefffffe}; @@ -252,7 +252,7 @@ TEST(misc, pktid_64_bit_warn_32bit) } -TEST(misc, pktid_data_perf) +TEST(Misc, PktidDataPerf) { { long count = 0; diff --git a/test/unittests/test_pktstream.cpp b/test/unittests/test_pktstream.cpp index 80283885a..b46b8c6f3 100644 --- a/test/unittests/test_pktstream.cpp +++ b/test/unittests/test_pktstream.cpp @@ -23,8 +23,7 @@ static size_t rand_size(RandomAPI &prng) { if (prng.randbool()) return prng.randrange32(1, 16); - else - return prng.randrange32(1, 512); + return prng.randrange32(1, 512); } template <typename PKTSTREAM> @@ -36,8 +35,8 @@ static void do_test(const bool grow, const bool verbose) const int n_iter = 250000; #endif - const Frame::Context fc(256, 512, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : 0); - const Frame::Context fc_big(256, 4096, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : 0); + const Frame::Context fc(256, 512, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : BufAllocFlags::NO_FLAGS); + const Frame::Context fc_big(256, 4096, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : BufAllocFlags::NO_FLAGS); if (verbose) { @@ -83,14 +82,14 @@ static void do_test(const bool grow, const bool verbose) { PKTSTREAM pktstream; BufferAllocated in; - while (big.size()) + while (!big.empty()) { const size_t bytes = std::min(big.size(), rand_size(*prng)); fc.prepare(in); in.write(big.data(), bytes); big.advance(bytes); BufferAllocated out; - while (in.size()) + while (!in.empty()) { pktstream.put(in, fc); while (pktstream.ready()) @@ -116,22 +115,22 @@ static void do_test(const bool grow, const bool verbose) OPENVPN_LOG("count=" << count); } -TEST(pktstream, test_16) +TEST(Pktstream, Test16) { do_test<PacketStream<std::uint16_t>>(false, false); } -TEST(pktstream, test_32) +TEST(Pktstream, Test32) { do_test<PacketStream<std::uint32_t>>(false, false); } -TEST(pktstream, test_16_residual) +TEST(Pktstream, Test16Residual) { do_test<PacketStreamResidual<std::uint16_t>>(true, false); } -TEST(pktstream, test_32_residual) +TEST(Pktstream, Test32Residual) { do_test<PacketStreamResidual<std::uint32_t>>(true, false); } @@ -163,7 +162,7 @@ static void validate_size_test() const size_t headroom = 16; const size_t tailroom = 0; const size_t align_block = 16; - const Frame::Context fixed(headroom, payload, tailroom, 0, align_block, 0); + const Frame::Context fixed(headroom, payload, tailroom, 0, align_block, BufAllocFlags::NO_FLAGS); const Frame::Context grow(headroom, payload, tailroom, 0, align_block, BufAllocFlags::GROW); validate_size<PKTSTREAM>(fixed, 2048, false); // succeeds validate_size<PKTSTREAM>(fixed, 2049, true); // exceeded payload, throw @@ -171,12 +170,12 @@ static void validate_size_test() validate_size<PKTSTREAM>(grow, 2049, false); // exceeded payload, but okay with growable buffer } -TEST(pktstream, validate_size_16) +TEST(Pktstream, ValidateSize16) { validate_size_test<PacketStream<std::uint16_t>>(); } -TEST(pktstream, validate_size_32) +TEST(Pktstream, ValidateSize32) { validate_size_test<PacketStream<std::uint32_t>>(); } diff --git a/test/unittests/test_prefixlen.cpp b/test/unittests/test_prefixlen.cpp index aca974590..67180e5b3 100644 --- a/test/unittests/test_prefixlen.cpp +++ b/test/unittests/test_prefixlen.cpp @@ -13,20 +13,19 @@ OPENVPN_SIMPLE_EXCEPTION(ipv4_bad_netmask); inline IPv4::Addr::base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) { - return ~((1u << (32 - prefix_len)) - 1); + return ~((1U << (32 - prefix_len)) - 1); } inline IPv4::Addr::base_type prefix_len_to_netmask(const unsigned int prefix_len) { if (prefix_len >= 1 && prefix_len <= 32) return prefix_len_to_netmask_unchecked(prefix_len); - else - throw ipv4_bad_prefix_len(); + throw ipv4_bad_prefix_len(); } inline int prefix_len(const IPv4::Addr::base_type mask) { - if (mask != ~0u) + if (mask != ~0U) { unsigned int high = 32; unsigned int low = 1; @@ -36,18 +35,17 @@ inline int prefix_len(const IPv4::Addr::base_type mask) const IPv4::Addr::base_type test = prefix_len_to_netmask_unchecked(mid); if (mask == test) return mid; - else if (mask > test) + if (mask > test) low = mid; else high = mid; } return -1; } - else - return 32; + return 32; } -TEST(IPAddr, test32) +TEST(IPAddr, Test32) { for (unsigned int i = 1; i <= 32; ++i) { @@ -56,18 +54,18 @@ TEST(IPAddr, test32) ASSERT_EQ(pl, (int)i); // IPv4::Addr a = IPv4::Addr::from_uint32(mask); - // std::cout << i << ' ' << pl << ' ' << a << std::endl; + // std::cout << i << ' ' << pl << ' ' << a << "\n"; } } -TEST(IPAddr, prefixlen) +TEST(IPAddr, Prefixlen) { for (unsigned int i = 0; i <= 32; ++i) { IPv4::Addr mask = IPv4::Addr::netmask_from_prefix_len(i); const unsigned int pl = mask.prefix_len(); ASSERT_EQ(pl, i); - // std::cout << i << ' ' << pl << ' ' << mask << std::endl; + // std::cout << i << ' ' << pl << ' ' << mask << "\n"; } } @@ -78,7 +76,7 @@ void testbig() // exhaustive test of all 2^32 possible netmask values { const int pl = prefix_len(mask); if (pl != -1) - std::cout << pl << ' ' << IPv4::Addr::from_uint32(mask) << std::endl; + std::cout << pl << ' ' << IPv4::Addr::from_uint32(mask) << '\n'; if (++mask == 0) break; } diff --git a/test/unittests/test_proto.cpp b/test/unittests/test_proto.cpp index cf5c238aa..18dd11adb 100644 --- a/test/unittests/test_proto.cpp +++ b/test/unittests/test_proto.cpp @@ -173,7 +173,7 @@ #include <openvpn/crypto/cryptodcsel.hpp> -#if defined(USE_MBEDTLS_APPLE_HYBRID) +#ifdef USE_MBEDTLS_APPLE_HYBRID #define USE_MBEDTLS #endif @@ -193,12 +193,9 @@ #endif #if defined(USE_OPENSSL) || defined(USE_OPENSSL_SERVER) -#include <openvpn/openssl/util/init.hpp> - #include <openvpn/openssl/crypto/api.hpp> #include <openvpn/openssl/ssl/sslctx.hpp> #include <openvpn/openssl/util/rand.hpp> - #endif #if defined(USE_APPLE_SSL) || defined(USE_MBEDTLS_APPLE_HYBRID) @@ -219,20 +216,20 @@ using namespace openvpn; // server Crypto/SSL/Rand implementation -#if defined(USE_MBEDTLS_SERVER) +#ifdef USE_MBEDTLS_SERVER typedef MbedTLSCryptoAPI ServerCryptoAPI; typedef MbedTLSContext ServerSSLAPI; typedef MbedTLSRandom ServerRandomAPI; #elif defined(USE_OPENSSL_SERVER) -typedef OpenSSLCryptoAPI ServerCryptoAPI; -typedef OpenSSLContext ServerSSLAPI; -typedef OpenSSLRandom ServerRandomAPI; +using ServerCryptoAPI = OpenSSLCryptoAPI; +using ServerSSLAPI = OpenSSLContext; +using ServerRandomAPI = OpenSSLRandom; #else #error No server SSL implementation defined #endif // client SSL implementation can be OpenSSL, Apple SSL, or MbedTLS -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS #if defined(USE_MBEDTLS_APPLE_HYBRID) typedef AppleCryptoAPI ClientCryptoAPI; #else @@ -245,9 +242,9 @@ typedef AppleCryptoAPI ClientCryptoAPI; typedef AppleSSLContext ClientSSLAPI; typedef AppleRandom ClientRandomAPI; #elif defined(USE_OPENSSL) -typedef OpenSSLCryptoAPI ClientCryptoAPI; -typedef OpenSSLContext ClientSSLAPI; -typedef OpenSSLRandom ClientRandomAPI; +using ClientCryptoAPI = OpenSSLCryptoAPI; +using ClientSSLAPI = OpenSSLContext; +using ClientRandomAPI = OpenSSLRandom; #else #error No client SSL implementation defined #endif @@ -311,7 +308,7 @@ class DroughtMeasure { const unsigned int r = drought.raw(); #if defined(VERBOSE) - std::cout << "*** Drought " << name << " has reached " << r << std::endl; + std::cout << "*** Drought " << name << " has reached " << r << "\n"; #endif #ifdef DROUGHT_LIMIT if (r > DROUGHT_LIMIT) @@ -374,7 +371,7 @@ class TestProto : public ProtoContextCallbackInterface { proto_context.start(); const size_t msglen = std::strlen(msg) + 1; - BufferAllocated app_buf((unsigned char *)msg, msglen, 0); + BufferAllocated app_buf((unsigned char *)msg, msglen, BufAllocFlags::NO_FLAGS); copy_progress(app_buf); control_send(std::move(app_buf)); proto_context.flush(true); @@ -384,7 +381,7 @@ class TestProto : public ProtoContextCallbackInterface { proto_context.start(); const size_t msglen = std::strlen(msg) + 1; - templ = BufferAllocatedRc::Create((unsigned char *)msg, msglen, 0); + templ = BufferAllocatedRc::Create((unsigned char *)msg, msglen, BufAllocFlags::NO_FLAGS); proto_context.flush(true); } @@ -409,8 +406,7 @@ class TestProto : public ProtoContextCallbackInterface proto_context.housekeeping(); return true; } - else - return false; + return false; } void control_send(BufferPtr &&app_bp) @@ -442,7 +438,7 @@ class TestProto : public ProtoContextCallbackInterface void data_decrypt(const ProtoContext::PacketType &type, BufferAllocated &in_out) { proto_context.data_decrypt(type, in_out); - if (in_out.size()) + if (!in_out.empty()) { data_bytes_ += in_out.size(); data_drought.event(); @@ -505,7 +501,7 @@ class TestProto : public ProtoContextCallbackInterface if (disable_xmit_) return; net_bytes_ += net_buf.size(); - net_out.push_back(BufferAllocatedRc::Create(net_buf, 0)); + net_out.push_back(BufferAllocatedRc::Create(net_buf, BufAllocFlags::NO_FLAGS)); } void control_recv(BufferPtr &&app_bp) override @@ -519,7 +515,7 @@ class TestProto : public ProtoContextCallbackInterface { const ssize_t trunc = 64; const std::string show((char *)work->data(), trunc); - std::cout << now().raw() << " " << mode().str() << " " << show << std::endl; + std::cout << now().raw() << " " << mode().str() << " " << show << "\n"; } #endif #if FEEDBACK @@ -558,8 +554,7 @@ class TestProto : public ProtoContextCallbackInterface msg[i]++; break; } - else - msg[i] = '0'; + msg[i] = '0'; } } @@ -579,7 +574,7 @@ class TestProto : public ProtoContextCallbackInterface class TestProtoClient : public TestProto { - typedef TestProto Base; + using Base = TestProto; public: TestProtoClient(const ProtoContext::ProtoConfig::Ptr &config, @@ -623,7 +618,7 @@ class TestProtoServer : public TestProto const AuthCert::Ptr &auth_cert) override { #ifdef VERBOSE - std::cout << "**** AUTHENTICATE " << username << '/' << password << " PEER INFO:" << std::endl; + std::cout << "**** AUTHENTICATE " << username << '/' << password << " PEER INFO:\n"; std::cout << peer_info; #endif if (username != "foo" || password != "bar") @@ -636,7 +631,7 @@ class TestProtoServer : public TestProto class NoisyWire { public: - NoisyWire(const std::string title_arg, + NoisyWire(const std::string &title_arg, TimePtr now_arg, RandomAPI &rand_arg, const unsigned int reorder_prob_arg, @@ -664,7 +659,7 @@ class NoisyWire if (a.do_housekeeping()) { #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Housekeeping" << std::endl; + std::cout << now->raw() << " " << title << " Housekeeping\n"; #endif } @@ -683,7 +678,7 @@ class NoisyWire { BufferPtr bp = a.net_out.front(); #ifdef VERBOSE - std::cout << now->raw() << " " << title << " " << a.dump_packet(*bp) << std::endl; + std::cout << now->raw() << " " << title << " " << a.dump_packet(*bp) << "\n"; #endif a.net_out.pop_front(); wire.push_back(bp); @@ -700,7 +695,7 @@ class NoisyWire { #ifdef VERBOSE if (!b.control_net_validate(pt, *bp)) // not strictly necessary since control_net_recv will also validate - std::cout << now->raw() << " " << title << " CONTROL PACKET VALIDATION FAILED" << std::endl; + std::cout << now->raw() << " " << title << " CONTROL PACKET VALIDATION FAILED\n"; #endif b.proto_context.control_net_recv(pt, std::move(bp)); } @@ -713,21 +708,21 @@ class NoisyWire if (bp->size()) { const std::string show((char *)bp->data(), std::min(bp->size(), size_t(40))); - std::cout << now->raw() << " " << title << " DATA CHANNEL DECRYPT: " << show << std::endl; + std::cout << now->raw() << " " << title << " DATA CHANNEL DECRYPT: " << show << "\n"; } #endif } catch ([[maybe_unused]] const std::exception &e) { #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Exception on data channel decrypt: " << e.what() << std::endl; + std::cout << now->raw() << " " << title << " Exception on data channel decrypt: " << e.what() << "\n"; #endif } } else { #ifdef VERBOSE - std::cout << now->raw() << " " << title << " KEY_STATE_ERROR" << std::endl; + std::cout << now->raw() << " " << title << " KEY_STATE_ERROR\n"; #endif b.proto_context.stat().error(Error::KEY_STATE_ERROR); } @@ -737,7 +732,7 @@ class NoisyWire { b.disable_xmit(); #ifdef VERBOSE - std::cout << now->raw() << " " << title << " SIMULATE_UDP_AMPLIFY_ATTACK disable client xmit" << std::endl; + std::cout << now->raw() << " " << title << " SIMULATE_UDP_AMPLIFY_ATTACK disable client xmit\n"; #endif } #endif @@ -754,19 +749,19 @@ class NoisyWire { const size_t i = random.randrange(wire.size() - 1) + 1; #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating packet reordering " << i << " -> 0" << std::endl; + std::cout << now->raw() << " " << title << " Simulating packet reordering " << i << " -> 0\n"; #endif std::swap(wire[0], wire[i]); } #endif - if (wire.size()) + if (!wire.empty()) { BufferPtr bp = wire.front(); wire.pop_front(); #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Received packet, size=" << bp->size() << std::endl; + std::cout << now->raw() << " " << title << " Received packet, size=" << bp->size() << "\n"; #endif #ifdef SIMULATE_DROPPED @@ -774,7 +769,7 @@ class NoisyWire if (!rand(drop_prob)) { #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating a dropped packet" << std::endl; + std::cout << now->raw() << " " << title << " Simulating a dropped packet\n"; #endif return BufferPtr(); } @@ -782,10 +777,10 @@ class NoisyWire #ifdef SIMULATE_CORRUPTED // simulate corrupted packet - if (bp->size() && !rand(corrupt_prob)) + if (!bp->empty() && !rand(corrupt_prob)) { #ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating a corrupted packet" << std::endl; + std::cout << now->raw() << " " << title << " Simulating a corrupted packet\n"; #endif const size_t pos = random.randrange(bp->size()); const unsigned char value = random.randrange(std::numeric_limits<unsigned char>::max()); @@ -802,8 +797,7 @@ class NoisyWire { if (prob) return random.randrange(prob); - else - return 1; + return 1; } std::string title; @@ -820,7 +814,7 @@ class NoisyWire class MySessionStats : public SessionStats { public: - typedef RCPtr<MySessionStats> Ptr; + using Ptr = RCPtr<MySessionStats>; MySessionStats() { @@ -837,8 +831,7 @@ class MySessionStats : public SessionStats { if (type < Error::N_ERRORS) return errors[type]; - else - return 0; + return 0; } void show_error_counts() const @@ -847,7 +840,7 @@ class MySessionStats : public SessionStats { count_t c = errors[i]; if (c) - std::cerr << Error::name(i) << " : " << c << std::endl; + std::cerr << Error::name(i) << " : " << c << '\n'; } } @@ -896,7 +889,7 @@ static auto create_client_proto_context(ClientSSLAPI::Config::Ptr cc, Frame::Ptr : read_text(TEST_KEYCERT_DIR + tls_crypt_v2_key_fn); // client ProtoContext config - typedef ProtoContext ClientProtoContext; + using ClientProtoContext = ProtoContext; ClientProtoContext::ProtoConfig::Ptr cp(new ClientProtoContext::ProtoConfig); cp->ssl_factory = cc->new_factory(); CryptoAlgs::allow_default_dc_algs<ClientCryptoAPI>(cp->ssl_factory->libctx(), false, false); @@ -918,13 +911,13 @@ static auto create_client_proto_context(ClientSSLAPI::Config::Ptr cc, Frame::Ptr #ifdef USE_TLS_AUTH cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<ClientCryptoAPI>()); - cp->tls_key.parse(tls_auth_key); + cp->tls_auth_key.parse(tls_auth_key); cp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST)); cp->key_direction = 0; #endif #ifdef USE_TLS_CRYPT cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - cp->tls_key.parse(tls_auth_key); + cp->tls_crypt_key.parse(tls_auth_key); cp->set_tls_crypt_algs(); cp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V1; #endif @@ -934,12 +927,12 @@ static auto create_client_proto_context(ClientSSLAPI::Config::Ptr cc, Frame::Ptr { TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context); tls_crypt_v2_key.parse(tls_crypt_v2_client_key); - tls_crypt_v2_key.extract_key(cp->tls_key); + tls_crypt_v2_key.extract_key(cp->tls_crypt_key); tls_crypt_v2_key.extract_wkc(cp->wkc); } cp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V2; #endif -#if defined(HANDSHAKE_WINDOW) +#ifdef HANDSHAKE_WINDOW cp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW); #elif SITER > 1 cp->handshake_window = Time::Duration::seconds(30); @@ -952,7 +945,7 @@ static auto create_client_proto_context(ClientSSLAPI::Config::Ptr cc, Frame::Ptr cp->become_primary = cp->handshake_window; #endif cp->tls_timeout = Time::Duration::milliseconds(TLS_TIMEOUT_CLIENT); -#if defined(CLIENT_NO_RENEG) +#ifdef CLIENT_NO_RENEG cp->renegotiate = Time::Duration::infinite(); #else cp->renegotiate = Time::Duration::seconds(RENEG); @@ -963,20 +956,24 @@ static auto create_client_proto_context(ClientSSLAPI::Config::Ptr cc, Frame::Ptr cp->keepalive_timeout_early = cp->keepalive_timeout; #ifdef VERBOSE - std::cout << "CLIENT OPTIONS: " << cp->options_string() << std::endl; - std::cout << "CLIENT PEER INFO:" << std::endl; + std::cout << "CLIENT OPTIONS: " << cp->options_string() << "\n"; + std::cout << "CLIENT PEER INFO:\n"; std::cout << cp->peer_info_string(); #endif return cp; } // execute the unit test in one thread -int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, const std::string &tls_crypt_v2_key_fn = "") +int test(const int thread_num, + bool use_tls_ekm, + bool tls_version_mismatch, + const std::string &tls_crypt_v2_key_fn = "", + bool use_tls_auth_with_tls_crypt_v2 = false) { try { // frame - Frame::Ptr frame(new Frame(Frame::Context(128, 378, 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 378, 128, 0, 16, BufAllocFlags::NO_FLAGS))); // RNG ClientRandomAPI::Ptr prng_cli(new ClientRandomAPI()); @@ -1022,7 +1019,7 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons #endif // server ProtoContext config - typedef ProtoContext ServerProtoContext; + using ServerProtoContext = ProtoContext; ServerProtoContext::ProtoConfig::Ptr sp(new ServerProtoContext::ProtoConfig); sp->ssl_factory = sc->new_factory(); sp->dc.set_factory(new CryptoDCSelect<ServerCryptoAPI>(sp->ssl_factory->libctx(), frame, serv_stats, prng_serv)); @@ -1044,13 +1041,13 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons sp->dc.set_key_derivation(CryptoAlgs::KeyDerivation::TLS_EKM); #ifdef USE_TLS_AUTH sp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<ServerCryptoAPI>()); - sp->tls_key.parse(tls_auth_key); + sp->tls_auth_key.parse(tls_auth_key); sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST)); sp->key_direction = 1; #endif -#if defined(USE_TLS_CRYPT) +#ifdef USE_TLS_CRYPT sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - sp->tls_key.parse(tls_auth_key); + sp->tls_crypt_key.parse(tls_auth_key); sp->set_tls_crypt_algs(); cp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V1; #endif @@ -1061,7 +1058,7 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons { TLSCryptV2ServerKey tls_crypt_v2_key; tls_crypt_v2_key.parse(tls_crypt_v2_server_key); - tls_crypt_v2_key.extract_key(sp->tls_key); + tls_crypt_v2_key.extract_key(sp->tls_crypt_key); } sp->set_tls_crypt_algs(); @@ -1069,8 +1066,16 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons sp->tls_crypt_ = ProtoContext::ProtoConfig::TLSCrypt::V2; sp->tls_crypt_v2_serverkey_id = !tls_crypt_v2_key_fn.empty(); sp->tls_crypt_v2_serverkey_dir = TEST_KEYCERT_DIR; + + if (use_tls_auth_with_tls_crypt_v2) + { + sp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<ServerCryptoAPI>()); + sp->tls_auth_key.parse(tls_auth_key); + sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST)); + sp->key_direction = 1; + } #endif -#if defined(HANDSHAKE_WINDOW) +#ifdef HANDSHAKE_WINDOW sp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW); #elif SITER > 1 sp->handshake_window = Time::Duration::seconds(30); @@ -1083,7 +1088,7 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons sp->become_primary = sp->handshake_window; #endif sp->tls_timeout = Time::Duration::milliseconds(TLS_TIMEOUT_SERVER); -#if defined(SERVER_NO_RENEG) +#ifdef SERVER_NO_RENEG sp->renegotiate = Time::Duration::infinite(); #else // NOTE: if we don't add sp->handshake_window, both client and server reneg-sec (RENEG) @@ -1100,8 +1105,8 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons sp->keepalive_timeout_early = Time::Duration::seconds(10); #ifdef VERBOSE - std::cout << "SERVER OPTIONS: " << sp->options_string() << std::endl; - std::cout << "SERVER PEER INFO:" << std::endl; + std::cout << "SERVER OPTIONS: " << sp->options_string() << "\n"; + std::cout << "SERVER PEER INFO:\n"; std::cout << sp->peer_info_string(); #endif @@ -1111,7 +1116,7 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons for (int i = 0; i < SITER; ++i) { #ifdef VERBOSE - std::cout << "***** SITER " << i << std::endl; + std::cout << "***** SITER " << i << "\n"; #endif cli_proto.reset(); serv_proto.reset(); @@ -1141,7 +1146,7 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons } catch (const std::exception &e) { - std::cerr << "Exception[" << i << '/' << j << "]: " << e.what() << std::endl; + std::cerr << "Exception[" << i << '/' << j << "]: " << e.what() << '\n'; return 1; } } @@ -1164,38 +1169,43 @@ int test(const int thread_num, bool use_tls_ekm, bool tls_version_mismatch, cons << " N=" << cli_proto.proto_context.negotiations() << '/' << serv_proto.proto_context.negotiations() << " SH=" << cli_proto.proto_context.slowest_handshake().raw() << '/' << serv_proto.proto_context.slowest_handshake().raw() << " HE=" << cli_stats->get_error_count(Error::HANDSHAKE_TIMEOUT) << '/' << serv_stats->get_error_count(Error::HANDSHAKE_TIMEOUT) - << std::endl; + << '\n'; #ifdef STATS - std::cerr << "-------- CLIENT STATS --------" << std::endl; + std::cerr << "-------- CLIENT STATS --------\n"; cli_stats->show_error_counts(); - std::cerr << "-------- SERVER STATS --------" << std::endl; + std::cerr << "-------- SERVER STATS --------\n"; serv_stats->show_error_counts(); #endif #ifdef OPENVPN_MAX_DATALIMIT_BYTES - std::cerr << "------------------------------" << std::endl; - std::cerr << "MAX_DATALIMIT_BYTES=" << DataLimit::max_bytes() << std::endl; + std::cerr << "------------------------------\n"; + std::cerr << "MAX_DATALIMIT_BYTES=" << DataLimit::max_bytes() << "\n"; #endif } catch (const std::exception &e) { - std::cerr << "Exception: " << e.what() << std::endl; + std::cerr << "Exception: " << e.what() << '\n'; return 1; } return 0; } -int test_retry(const int thread_num, const int n_retries, bool use_tls_ekm) +int test_retry(const int thread_num, + const int n_retries, + bool use_tls_ekm, + bool tls_version_mismatch = false, + const std::string &tls_crypt_v2_key_fn = "", + bool use_tls_auth_with_tls_crypt_v2 = false) { int ret = 1; for (int i = 0; i < n_retries; ++i) { - ret = test(thread_num, use_tls_ekm, false); + ret = test(thread_num, use_tls_ekm, tls_version_mismatch, tls_crypt_v2_key_fn, use_tls_auth_with_tls_crypt_v2); if (!ret) return 0; - std::cout << "Retry " << (i + 1) << '/' << n_retries << std::endl; + std::cout << "Retry " << (i + 1) << '/' << n_retries << '\n'; } - std::cout << "Failed" << std::endl; + std::cout << "Failed\n"; return ret; } @@ -1204,7 +1214,7 @@ class ProtoUnitTest : public testing::Test // Sets up the test fixture. void SetUp() override { -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS mbedtls_debug_set_threshold(1); #endif @@ -1220,7 +1230,7 @@ class ProtoUnitTest : public testing::Test // Tears down the test fixture. void TearDown() override { -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS mbedtls_debug_set_threshold(4); #endif openvpn::Compress::set_log_level(openvpn::Compress::default_log_level); @@ -1228,7 +1238,7 @@ class ProtoUnitTest : public testing::Test } }; -TEST_F(ProtoUnitTest, base_single_thread_tls_ekm) +TEST_F(ProtoUnitTest, BaseSingleThreadTlsEkm) { if (!openvpn::SSLLib::SSLAPI::support_key_material_export()) GTEST_SKIP_("our mbed TLS implementation does not support TLS EKM"); @@ -1240,7 +1250,7 @@ TEST_F(ProtoUnitTest, base_single_thread_tls_ekm) EXPECT_EQ(ret, 0); } -TEST_F(ProtoUnitTest, base_single_thread_no_tls_ekm) +TEST_F(ProtoUnitTest, BaseSingleThreadNoTlsEkm) { int ret = 0; @@ -1253,7 +1263,7 @@ TEST_F(ProtoUnitTest, base_single_thread_no_tls_ekm) // so we can't set mismatched client and server TLS versions. // For now, just test this for OPENSSL which is full-featured. #ifdef USE_OPENSSL -TEST_F(ProtoUnitTest, base_single_thread_tls_version_mismatch) +TEST_F(ProtoUnitTest, BaseSingleThreadTlsVersionMismatch) { int ret = test(1, false, true); EXPECT_NE(ret, 0); @@ -1261,20 +1271,26 @@ TEST_F(ProtoUnitTest, base_single_thread_tls_version_mismatch) #endif #ifdef USE_TLS_CRYPT_V2 -TEST_F(ProtoUnitTest, base_single_thread_tls_crypt_v2_with_embedded_serverkey) +TEST_F(ProtoUnitTest, BaseSingleThreadTlsCryptV2WithEmbeddedServerkey) { - int ret = test(1, false, false, "tls-crypt-v2-client-with-serverkey.key"); + int ret = test_retry(1, N_RETRIES, false, false, "tls-crypt-v2-client-with-serverkey.key"); EXPECT_EQ(ret, 0); } -TEST_F(ProtoUnitTest, base_single_thread_tls_crypt_v2_with_missing_embedded_serverkey) +TEST_F(ProtoUnitTest, BaseSingleThreadTlsCryptV2WithMissingEmbeddedServerkey) { int ret = test(1, false, false, "tls-crypt-v2-client-with-missing-serverkey.key"); EXPECT_NE(ret, 0); } + +TEST_F(ProtoUnitTest, BaseSingleThreadTlsCryptV2WithTlsAuthAlsoActive) +{ + int ret = test_retry(1, N_RETRIES, false, false, "tls-crypt-v2-client-with-serverkey.key", true); + EXPECT_EQ(ret, 0); +} #endif -TEST_F(ProtoUnitTest, base_multiple_thread) +TEST_F(ProtoUnitTest, BaseMultipleThread) { unsigned int num_threads = std::thread::hardware_concurrency(); #if defined(PROTO_N_THREADS) && PROTO_N_THREADS >= 1 @@ -1304,7 +1320,7 @@ TEST_F(ProtoUnitTest, base_multiple_thread) EXPECT_THAT(expected_results, ::testing::ContainerEq(results)); } -TEST(proto, iv_ciphers_aead) +TEST(Proto, IvCiphersAead) { CryptoAlgs::allow_default_dc_algs<SSLLib::CryptoAPI>(nullptr, true, false); @@ -1323,7 +1339,7 @@ TEST(proto, iv_ciphers_aead) EXPECT_EQ(ivciphers, expectedstr); } -TEST(proto, iv_ciphers_non_preferred) +TEST(Proto, IvCiphersNonPreferred) { CryptoAlgs::allow_default_dc_algs<SSLLib::CryptoAPI>(nullptr, false, false); @@ -1342,7 +1358,7 @@ TEST(proto, iv_ciphers_non_preferred) EXPECT_EQ(ivciphers, expectedstr); } -TEST(proto, iv_ciphers_legacy) +TEST(Proto, IvCiphersLegacy) { /* Need to a whole lot of things to enable legacy provider/OpenSSL context */ @@ -1388,7 +1404,7 @@ TEST(proto, iv_ciphers_legacy) EXPECT_EQ(ivciphers, expectedstr); } -TEST(proto, controlmessage_invalidchar) +TEST(Proto, ControlmessageInvalidchar) { std::string valid_auth_fail{"AUTH_FAILED: go away"}; std::string valid_auth_fail_newline_end{"AUTH_FAILED: go away\n"}; @@ -1447,11 +1463,11 @@ class EventQueueVector : public openvpn::ClientEvent::Queue std::vector<openvpn::ClientEvent::Base::Ptr> events; }; -TEST(proto, client_proto_check_cc_msg) +TEST(Proto, ClientProtoCheckCcMsg) { asio::io_context io_context; ClientRandomAPI::Ptr rng_cli(new ClientRandomAPI()); - Frame::Ptr frame(new Frame(Frame::Context(128, 378, 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 378, 128, 0, 16, BufAllocFlags::NO_FLAGS))); MySessionStats::Ptr cli_stats(new MySessionStats); Time time; diff --git a/test/unittests/test_psid_cookie.cpp b/test/unittests/test_psid_cookie.cpp index c47252b7c..2ff9e41df 100644 --- a/test/unittests/test_psid_cookie.cpp +++ b/test/unittests/test_psid_cookie.cpp @@ -5,7 +5,7 @@ using namespace openvpn; -TEST(psid_cookie, setup) +TEST(PsidCookie, Setup) { PsidCookieImpl::pre_threading_setup(); @@ -78,8 +78,8 @@ class PsidCookieTest : public testing::Test PsidCookieTest() : dummy_io_context(1), pcfg(new ProtoContext::ProtoConfig()) { - std::string tls_key_fn = UNITTEST_SOURCE_DIR "/input/psid_cookie_tls.key"; - pcfg->tls_key.parse_from_file(tls_key_fn); + const std::string tls_key_fn = UNITTEST_SOURCE_DIR "/input/psid_cookie_tls.key"; + pcfg->tls_auth_key.parse_from_file(tls_key_fn); pcfg->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>()); pcfg->set_tls_auth_digest(CryptoAlgs::lookup("SHA256")); pcfg->now = &now; @@ -118,28 +118,27 @@ class PsidCookieTest : public testing::Test }; -TEST_F(PsidCookieTest, check_setup) +TEST_F(PsidCookieTest, CheckSetup) { - PsidCookieImpl *pci_dut = pcookie_impl.get(); + const PsidCookieImpl *pci_dut = pcookie_impl.get(); ASSERT_NE(pci_dut, nullptr); // check test clock's equivalence to the PsidCookieImpl clock - Time start(set_clock(Time::now())); + const Time start(set_clock(Time::now())); EXPECT_TRUE(start == *pci_dut->now_); // spot check other aspects of successful pci_dut creation - EXPECT_TRUE(pci_dut->pcfg_.tls_key.defined()); - EXPECT_FALSE(pci_dut->not_tls_auth_mode_); + EXPECT_TRUE(pci_dut->pcfg_.tls_auth_key.defined()); } -TEST_F(PsidCookieTest, valid_time) +TEST_F(PsidCookieTest, ValidTime) { PsidCookieImpl &pci_dut(*pcookie_impl.get()); - ClientAddressMock cli_addr(*pci_dut.pcfg_.prng); + const ClientAddressMock cli_addr(*pci_dut.pcfg_.prng); ProtoSessionID cli_psid; ProtoSessionID srv_psid; // interval duplicates the computation in calculate_session_id_hmac() - uint64_t interval = (pci_dut.pcfg_.handshake_window.raw() + 1) / 2; + const uint64_t interval = (pci_dut.pcfg_.handshake_window.raw() + 1) / 2; bool hmac_ok; cli_psid.randomize(*pci_dut.pcfg_.rng); @@ -161,3 +160,217 @@ TEST_F(PsidCookieTest, valid_time) hmac_ok = pci_dut.check_session_id_hmac(srv_psid, cli_psid, cli_addr); EXPECT_FALSE(hmac_ok); } + + +// Tests that exercise PsidCookieImpl::intercept() against crafted third +// packets of the OpenVPN 3-way handshake (the client reply to the server's +// HARD_RESET). The cookie code only ever sees this packet when no peer +// state exists yet, so it must positively identify the packet as the +// handshake-completing one before letting the caller create state. +class PsidCookieInterceptTest : public PsidCookieTest +{ + protected: + // Build a complete third-packet (tls-auth path) suitable for intercept(). + // Each on-the-wire field is parameterized so that individual tests can + // perturb exactly one field while leaving everything else valid. + BufferAllocated build_third_packet_tls_auth(const ProtoSessionID &cli_psid, + const ProtoSessionID &cookie_psid, + std::uint32_t acked_pktid_be, + std::uint32_t own_pktid_be, + unsigned char ack_count, + unsigned char op_field) + { + PsidCookieImpl &pci = *pcookie_impl; + // The server validates the incoming HMAC with ta_hmac_recv_; with + // pcfg_.key_direction == 0 that key differs from ta_hmac_send_'s, so + // we must sign the synthetic client packet with the recv key here. + const size_t hmac_size = pci.ta_hmac_recv_->output_size(); + + BufferAllocated buf; + buf.reset(/*headroom=*/256, /*capacity=*/512, BufAllocFlags::GROW); + + // Fields are prepended in reverse on-the-wire order, mirroring how + // process_clients_initial_reset_tls_auth() builds the server reply. + buf.prepend(&own_pktid_be, sizeof(own_pktid_be)); + cookie_psid.prepend(buf); + buf.prepend(&acked_pktid_be, sizeof(acked_pktid_be)); + buf.push_front(ack_count); + + PacketIDControlSend pid; + pid.write_next(buf, /*prepend=*/true, pci.now_->seconds_since_epoch()); + + buf.prepend_alloc(hmac_size); + cli_psid.prepend(buf); + buf.push_front(op_field); + + pci.ta_hmac_recv_->ovpn_hmac_gen(buf.data(), + buf.size(), + PsidCookieImpl::OPCODE_SIZE + PsidCookieImpl::SID_SIZE, + hmac_size, + PacketIDControl::idsize); + return buf; + } + + struct Fixture + { + ClientAddressMock cli_addr; + ProtoSessionID cli_psid; + ProtoSessionID cookie_psid; + }; + + Fixture make_fixture() + { + PsidCookieImpl &pci = *pcookie_impl; + set_clock(Time::now()); + + Fixture f{ClientAddressMock(*pci.pcfg_.prng), {}, {}}; + f.cli_psid.randomize(*pci.pcfg_.rng); + f.cookie_psid = pci.calculate_session_id_hmac(f.cli_psid, f.cli_addr, 0); + return f; + } +}; + +TEST_F(PsidCookieInterceptTest, ThirdPacketValid) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::HANDLE_2ND); + EXPECT_TRUE(pcookie_impl->get_cookie_psid().match(f.cookie_psid)); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketAcceptsAckedPktidOne) +{ + // Both acked-pktid 0 (default) and 1 are tolerated as part of the early + // handshake; only > 1 is treated as mid-session. This mirrors OpenVPN 2. + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/htonl(1), + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::HANDLE_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsAckedPktidAboveOne) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/htonl(2), + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::DROP_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketAcceptsOwnPktidOne) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/htonl(1), + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::HANDLE_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsOwnPktidAboveOne) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/htonl(2), + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::DROP_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsAckCountNotOne) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/2, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::DROP_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketAcceptsAckV1) +{ + // P_ACK_V1 has no own message-id on the wire; intercept() must accept + // it and skip the message-id check. The packet builder still writes 4 + // bytes for own_pktid into the buffer, but the validator's reqd_size is + // 4 bytes shorter for ACK_V1 so those bytes are simply ignored. + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::ACK_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::HANDLE_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsNonZeroKeyId) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 1)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::EARLY_DROP); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsBadCookie) +{ + auto f = make_fixture(); + // Tamper with the cookie psid: still valid HMAC over the packet, but + // the embedded server psid does not match what calculate_session_id_hmac + // would produce for this client. + ProtoSessionID bogus; + bogus.randomize(*pcookie_impl->pcfg_.rng); + + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + bogus, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::DROP_2ND); +} + +TEST_F(PsidCookieInterceptTest, ThirdPacketRejectsBadHmac) +{ + auto f = make_fixture(); + BufferAllocated pkt = build_third_packet_tls_auth(f.cli_psid, + f.cookie_psid, + /*acked_pktid_be=*/0, + /*own_pktid_be=*/0, + /*ack_count=*/1, + ProtoContext::op_compose(ProtoContext::CONTROL_V1, 0)); + // Flip a byte in the HMAC field (right after the opcode + own session id). + pkt.data()[PsidCookieImpl::OPCODE_SIZE + PsidCookieImpl::SID_SIZE] ^= 0x01; + + EXPECT_EQ(pcookie_impl->intercept(pkt, f.cli_addr), PsidCookie::Intercept::DROP_2ND); +} diff --git a/test/unittests/test_pushlex.cpp b/test/unittests/test_pushlex.cpp index 855d6f61f..4e447d973 100644 --- a/test/unittests/test_pushlex.cpp +++ b/test/unittests/test_pushlex.cpp @@ -25,12 +25,11 @@ static std::string get_next(PushLex &pl) { if (pl.defined()) return pl.next(); - else - return std::string(); + return std::string(); } // parse a PUSH_UPDATE message -TEST(pushlex, test_1) +TEST(Pushlex, Test1) { const std::string csv = "PUSH_UPDATE,route 10.9.0.0 255.255.0.0,route 8.8.8.8,route-ipv6 fd69::/64"; PushLex pl(const_buf_from_string(csv), true); @@ -41,7 +40,7 @@ TEST(pushlex, test_1) } // parse a PUSH_UPDATE message with tortured StandardLex quoting -TEST(pushlex, test_2) +TEST(Pushlex, Test2) { const std::string csv = "PUSH_UPDATE,echo \"one,two,three\",,route 1.2.3.4,echo \\\",echo \"foo\",echo \\,,echo fin,"; PushLex pl(const_buf_from_string(csv), true); @@ -57,7 +56,7 @@ TEST(pushlex, test_2) } // test PushLex with discard_prefix == false -TEST(pushlex, test_3) +TEST(Pushlex, Test3) { const std::string csv = "PUSH_UPDATE,route 10.9.0.0 255.255.0.0,route 8.8.8.8,route-ipv6 fd69::/64"; PushLex pl(const_buf_from_string(csv), false); @@ -69,7 +68,7 @@ TEST(pushlex, test_3) } // test PushLex with a null message -TEST(pushlex, test_4) +TEST(Pushlex, Test4) { const std::string csv = "PUSH_UPDATE,"; PushLex pl(const_buf_from_string(csv), true); @@ -77,7 +76,7 @@ TEST(pushlex, test_4) } // test PushLex with a null buffer -TEST(pushlex, test_5) +TEST(Pushlex, Test5) { ConstBuffer cbuf; PushLex pl(cbuf, true); @@ -86,7 +85,7 @@ TEST(pushlex, test_5) // test that PushLex throws an exception when prefix // is unrecognized -TEST(pushlex, test_exception_1) +TEST(Pushlex, TestException1) { JY_EXPECT_THROW( { @@ -99,7 +98,7 @@ TEST(pushlex, test_exception_1) // test that PushLex throws an exception when prefix // is not followed by a comma (",") -TEST(pushlex, test_exception_2) +TEST(Pushlex, TestException2) { JY_EXPECT_THROW( { diff --git a/test/unittests/test_randapi.cpp b/test/unittests/test_randapi.cpp index aba5a1e8d..b9b0e92a1 100644 --- a/test/unittests/test_randapi.cpp +++ b/test/unittests/test_randapi.cpp @@ -11,7 +11,7 @@ class IntegralMin : public WeakRandomAPI public: OPENVPN_EXCEPTION(s_min_error); - typedef RCPtr<IntegralMin> Ptr; + using Ptr = RCPtr<IntegralMin>; // Random algorithm name std::string name() const override @@ -60,7 +60,7 @@ void randapi_signed_min_test(const std::string &test_name) } while (0) -TEST(misc, randapi_signed_min) +TEST(Misc, RandapiSignedMin) { RANDAPI_SIGNED_MIN_TEST(signed char); RANDAPI_SIGNED_MIN_TEST(unsigned char); diff --git a/test/unittests/test_rc.cpp b/test/unittests/test_rc.cpp index 3198d0b73..72d7f184c 100644 --- a/test/unittests/test_rc.cpp +++ b/test/unittests/test_rc.cpp @@ -11,9 +11,9 @@ template <typename BASE> class TestType : public BASE { public: - typedef RCPtr<TestType> Ptr; - typedef RCWeakPtr<TestType> WPtr; - typedef BASE Base; + using Ptr = RCPtr<TestType>; + using WPtr = RCWeakPtr<TestType>; + using Base = BASE; TestType(const std::string &name_arg) : name(name_arg) @@ -38,8 +38,8 @@ template <typename Base> class TestParentType : public TestType<Base> { public: - typedef RCPtr<TestParentType> Ptr; - typedef RCWeakPtr<TestParentType> WPtr; + using Ptr = RCPtr<TestParentType>; + using WPtr = RCWeakPtr<TestParentType>; TestParentType(const std::string &name_arg) : TestType<Base>(name_arg) @@ -80,12 +80,12 @@ template <typename Test> void test() { testLog->startCollecting(); - typedef TestParentType<typename Test::Base> TestParent; + using TestParent = TestParentType<typename Test::Base>; { OPENVPN_LOG("*** TEST1"); - typename Test::Ptr t1 = new Test("Test1"); - typename Test::Ptr t2(t1); + const typename Test::Ptr t1 = new Test("Test1"); + const typename Test::Ptr t2(t1); typename Test::Ptr t3(t2); } { @@ -95,9 +95,9 @@ void test() typename Test::WPtr w2z; { - typename Test::Ptr t1 = new Test("Test2"); + const typename Test::Ptr t1 = new Test("Test2"); typename Test::WPtr w1 = t1; - RCWeakPtr<typename Test::WPtr::element_type> w2 = t1.get(); + const RCWeakPtr<typename Test::WPtr::element_type> w2 = t1.get(); w1z.reset(t1); w2z.reset(t1.get()); @@ -128,16 +128,16 @@ void test() OPENVPN_LOG("w1z=" << w1z.use_count() << " w2z=" << w2z.use_count()); } - typename Test::Ptr x = w1z.lock(); - typename Test::Ptr y = w2z.lock(); + const typename Test::Ptr x = w1z.lock(); + const typename Test::Ptr y = w2z.lock(); ASSERT_FALSE(x || y || !w1z.expired() || !w2z.expired()) << "BUG ALERT #3"; w1z = w2z; } { OPENVPN_LOG("*** TEST3"); - typename Test::Ptr t1 = new Test("Test3"); - typename Test::Ptr t2(t1); - typename Test::Ptr t3(t2); + const typename Test::Ptr t1 = new Test("Test3"); + const typename Test::Ptr t2(t1); + const typename Test::Ptr t3(t2); t1->rc_release_notify([obj = t1.get()]() { @@ -154,20 +154,20 @@ void test() } { OPENVPN_LOG("*** TEST4"); - typename TestParent::Ptr t1 = new TestParent("Test4"); - typename Test::Ptr t2(t1); - typename TestParent::Ptr t3 = t2.template dynamic_pointer_cast<TestParent>(); + const typename TestParent::Ptr t1 = new TestParent("Test4"); + const typename Test::Ptr t2(t1); + const typename TestParent::Ptr t3 = t2.template dynamic_pointer_cast<TestParent>(); OPENVPN_LOG(t3->parent_name); } ASSERT_EQ(expected_output, testLog->stopCollecting()); } -TEST(misc, RCthreadUnsafe) +TEST(Misc, RCthreadUnsafe) { test<TestType<RCWeak<thread_unsafe_refcount>>>(); } -TEST(misc, RCthreadSafe) +TEST(Misc, RCthreadSafe) { test<TestType<RCWeak<thread_safe_refcount>>>(); } diff --git a/test/unittests/test_relack.cpp b/test/unittests/test_relack.cpp index ee63aac67..de4e400f3 100644 --- a/test/unittests/test_relack.cpp +++ b/test/unittests/test_relack.cpp @@ -18,7 +18,7 @@ using namespace openvpn; using namespace openvpn::reliable; namespace orel = openvpn::reliable; -TEST(relack, test_size_1) +TEST(Relack, TestSize1) { constexpr size_t ACK_CNT = 11; @@ -29,7 +29,7 @@ TEST(relack, test_size_1) EXPECT_EQ(ra.resend_size(), size_t{0}); } -TEST(relack, test_prepend_1) +TEST(Relack, TestPrepend1) { constexpr size_t ACK_CNT = 11; @@ -84,7 +84,7 @@ struct RelSendMck std::vector<orel::id_t> mAcks; }; -TEST(relack, test_ack_1) +TEST(Relack, TestAck1) { constexpr size_t ACK_CNT = 9; @@ -111,7 +111,7 @@ TEST(relack, test_ack_1) } } -TEST(relack, test_ack_2) +TEST(Relack, TestAck2) { constexpr size_t ACK_CNT = 9; diff --git a/test/unittests/test_reliable.cpp b/test/unittests/test_reliable.cpp index ec5137b87..cd01cad7a 100644 --- a/test/unittests/test_reliable.cpp +++ b/test/unittests/test_reliable.cpp @@ -26,7 +26,7 @@ namespace PacketID { using id_t = openvpn::reliable::id_t; } -TEST(reliable, ack) +TEST(Reliable, Ack) { std::string expected{"0400000021000000160000000b00000001\n"}; std::ostringstream actual; @@ -45,24 +45,24 @@ TEST(reliable, ack) ack.push_back(0x99); ack.push_back(0x100); - BufferAllocated buf(256, 0); + BufferAllocated buf(256); buf.init_headroom(128); ack.prepend(buf, false); - actual << render_hex_generic(buf) << std::endl; + actual << render_hex_generic(buf) << '\n'; EXPECT_EQ(actual.str(), expected); std::string expected2{"080000002100000100000000990000008800000077000000660000005500000044\n"}; std::ostringstream actual2; - BufferAllocated buf2(256, 0); + BufferAllocated buf2(256); buf2.init_headroom(128); ack.prepend(buf2, true); - actual2 << render_hex_generic(buf2) << std::endl; + actual2 << render_hex_generic(buf2) << '\n'; EXPECT_EQ(actual2.str(), expected2); } -TEST(reliable, ack_dup) +TEST(Reliable, AckDup) { std::ostringstream actual; ReliableAck ack{}; @@ -74,12 +74,12 @@ TEST(reliable, ack_dup) std::string expected{"0400000004000000030000000200000001\n"}; - BufferAllocated buf(256, 0); + BufferAllocated buf(256); buf.init_headroom(128); ack.prepend(buf, false); - actual << render_hex_generic(buf) << std::endl; + actual << render_hex_generic(buf) << '\n'; EXPECT_EQ(actual.str(), expected); - EXPECT_EQ(ack.resend_size(), 4u); + EXPECT_EQ(ack.resend_size(), 4U); ack.push_back(3); ack.push_back(6); @@ -87,39 +87,37 @@ TEST(reliable, ack_dup) actual.str(""); std::string expected2{"0400000002000000040000000600000003\n"}; - BufferAllocated buf2(256, 0); + BufferAllocated buf2(256); buf2.init_headroom(128); ack.prepend(buf2, false); - actual << render_hex_generic(buf2) << std::endl; + actual << render_hex_generic(buf2) << '\n'; EXPECT_EQ(actual.str(), expected2); /* The duplicate 3 should have be there only once */ - EXPECT_EQ(ack.resend_size(), 5u); + EXPECT_EQ(ack.resend_size(), 5U); actual.str(""); - BufferAllocated buf3(256, 0); + BufferAllocated buf3(256, BufAllocFlags::NO_FLAGS); buf3.init_headroom(128); ack.prepend(buf3, false); - actual << render_hex_generic(buf3) << std::endl; + actual << render_hex_generic(buf3) << '\n'; std::string expected3{"0400000002000000040000000300000006\n"}; EXPECT_EQ(actual.str(), expected3); } -TEST(reliable, simple_packet) +TEST(Reliable, SimplePacket) { - std::ostringstream actual; ReliableAck ack{}; - BufferAllocated buf(256, 0); + BufferAllocated buf(256); buf.init_headroom(128); ack.push_back(0); ack.prepend(buf, false); - ack.push_back(1); ack.push_back(2); ack.push_back(3); @@ -130,9 +128,8 @@ OPENVPN_SIMPLE_EXCEPTION(receive_sequence); struct Packet { - Packet() - { - } + Packet() = default; + explicit Packet(const BufferPtr &buf_arg) : buf(buf_arg) { @@ -149,8 +146,8 @@ struct Packet BufferPtr buf; }; -typedef ReliableSendTemplate<Packet> ReliableSend; -typedef ReliableRecvTemplate<Packet> ReliableRecv; +using ReliableSend = ReliableSendTemplate<Packet>; +using ReliableRecv = ReliableRecvTemplate<Packet>; struct Message { @@ -166,7 +163,7 @@ void print_msg(const Time::Duration t, { case_detail << t.raw() << ' ' << title << '[' << id << "] " << (char *)buf->data() - << std::endl; + << '\n'; } @@ -209,12 +206,12 @@ void test(MTRand &rand, if (rand.randrange(40)) // with small probability, simulate a dropped ACK // JMD_TODO: why wouldn't this have drop_prob probability { - case_detail << t.raw() << " ACK [" << id << "]" << std::endl; + case_detail << t.raw() << " ACK [" << id << "]\n"; send.ack(id); } else { - case_detail << t.raw() << " Simulate dropped ACK [" << id << "]" << std::endl; + case_detail << t.raw() << " Simulate dropped ACK [" << id << "]\n"; } } @@ -248,7 +245,7 @@ void test(MTRand &rand, std::ostringstream os; os << "Test packet #" << count; const std::string s = os.str(); - auto buffer = BufferAllocatedRc::Create((unsigned char *)s.c_str(), s.length() + 1, 0); + auto buffer = BufferAllocatedRc::Create((unsigned char *)s.c_str(), s.length() + 1, BufAllocFlags::NO_FLAGS); ReliableSend::Message &m = send.send(now, Time::Duration()); m.packet.buf = buffer; Message msg; @@ -269,7 +266,7 @@ void test(MTRand &rand, { case_detail << t.raw() << " Simulate packet reordering " - << i1 << " <-> " << i2 << std::endl; + << i1 << " <-> " << i2 << '\n'; std::swap(wire[i1], wire[i2]); } } @@ -281,7 +278,7 @@ void test(MTRand &rand, Message msg = wire.front(); wire.pop_front(); - case_detail << t.raw() << " Received packet [" << msg.id << "]" << std::endl; + case_detail << t.raw() << " Received packet [" << msg.id << "]\n"; // simulate dropped packet if (rand.randrange(drop_prob)) @@ -294,7 +291,7 @@ void test(MTRand &rand, else { case_detail << t.raw() - << " Simulate dropped packet [" << msg.id << "]" << std::endl; + << " Simulate dropped packet [" << msg.id << "]\n"; } } @@ -305,8 +302,7 @@ void test(MTRand &rand, print_msg(t, "RECV", m.packet.buf, m.id(), case_detail); if (m.id() != rec_id) throw receive_sequence(); - else - rec_id = m.id() + 1; + rec_id = m.id() + 1; recv.advance(); } @@ -318,8 +314,7 @@ void test(MTRand &rand, << " final_t=" << t.raw() << " iterations=" << iterations << " count=" << count - << " [" << send_id << '/' << (rec_id ? rec_id - 1 : 0) << ']' - << std::endl; + << " [" << send_id << '/' << (rec_id ? rec_id - 1 : 0) << "]\n"; if (send_id != (rec_id ? rec_id - 1 : 0)) throw receive_sequence(); } @@ -333,14 +328,14 @@ struct test_params unsigned int drop_prob; }; -TEST(reliable, simulation) +TEST(Reliable, Simulation) { MTRand rand; std::vector<test_params> sim_cases = { - {1, 4, 4, 10, 16}, - {2, 2, 4, 10, 16}, - {3, 4, 8, 10, 16}, - {4, 4, 4, 2, 2}, + {.test_case = 1, .relsize = 4, .wiresize = 4, .reorder_prob = 10, .drop_prob = 16}, + {.test_case = 2, .relsize = 2, .wiresize = 4, .reorder_prob = 10, .drop_prob = 16}, + {.test_case = 3, .relsize = 4, .wiresize = 8, .reorder_prob = 10, .drop_prob = 16}, + {.test_case = 4, .relsize = 4, .wiresize = 4, .reorder_prob = 2, .drop_prob = 2}, }; const Time::Duration end = Time::Duration::seconds(1000); const Time::Duration step = Time::Duration::binary_ms(100); @@ -351,7 +346,7 @@ TEST(reliable, simulation) std::stringstream case_detail; try { - case_detail << "Test case " << sim_case.test_case << std::endl; + case_detail << "Test case " << sim_case.test_case << '\n'; test(rand, base, end, @@ -376,7 +371,7 @@ TEST(reliable, simulation) // to show the ranges of test parameters, relsize, wiresize, reorder_prob, and // drop_prob that the original author inttended -TEST(reliable, test1) +TEST(Reliable, Test1) { MTRand rand; const Time base = Time::now(); @@ -386,7 +381,7 @@ TEST(reliable, test1) test(rand, base, end, step, end_sends, 4, 4, 10, 16); } -TEST(reliable, test2) +TEST(Reliable, Test2) { MTRand rand; const Time base = Time::now(); diff --git a/test/unittests/test_remotelist.cpp b/test/unittests/test_remotelist.cpp index 0dc842bb6..09efb505f 100644 --- a/test/unittests/test_remotelist.cpp +++ b/test/unittests/test_remotelist.cpp @@ -58,7 +58,7 @@ TEST(RemoteList, CtorRemoteOverride) }; TestOverride test_ovr("1.1.1.1", "1111", Protocol(Protocol::UDPv4)); - RemoteList rl(&test_ovr); + const RemoteList rl(&test_ovr); ASSERT_EQ(rl.defined(), true); ASSERT_EQ(rl.size(), 1UL); @@ -71,7 +71,7 @@ TEST(RemoteList, CtorRemoteOverride) TEST(RemoteList, CtorSingleHost) { - RemoteList rl("1.1.1.1", "1111", Protocol(Protocol::TCPv6), ""); + const RemoteList rl("1.1.1.1", "1111", Protocol(Protocol::TCPv6), ""); ASSERT_EQ(rl.defined(), true); ASSERT_EQ(rl.size(), 1UL); ASSERT_EQ(rl.get_item(0)->server_host, "1.1.1.1"); @@ -106,8 +106,8 @@ TEST(RemoteList, CtorRemoteList) nullptr); cfg.update_map(); - RandomAPI::Ptr rng; - RemoteList rl(cfg, "", 0, nullptr, rng); + const RandomAPI::Ptr rng; + const RemoteList rl(cfg, "", 0, nullptr, rng); ASSERT_EQ(rl.defined(), true); ASSERT_EQ(rl.size(), 4UL); ASSERT_EQ(rl.get_item(0)->server_host, "0.default.invalid"); @@ -134,8 +134,8 @@ TEST(RemoteList, CtorRemoteListConnBlockOnly) nullptr); cfg.update_map(); - RandomAPI::Ptr rng; - RemoteList rl(cfg, "", RemoteList::CONN_BLOCK_ONLY, nullptr, rng); + const RandomAPI::Ptr rng; + const RemoteList rl(cfg, "", RemoteList::CONN_BLOCK_ONLY, nullptr, rng); ASSERT_EQ(rl.defined(), true); ASSERT_EQ(rl.size(), 1UL); ASSERT_EQ(rl.get_item(0)->server_host, "2.block.invalid"); @@ -146,9 +146,9 @@ TEST(RemoteList, CtorRemoteListEmpty) cfg.parse_from_config("", nullptr); cfg.update_map(); - RandomAPI::Ptr rng; + const RandomAPI::Ptr rng; ASSERT_THROW(RemoteList(cfg, "", 0, nullptr, rng), option_error); - RemoteList rl(cfg, "", RemoteList::ALLOW_EMPTY, nullptr, rng); + const RemoteList rl(cfg, "", RemoteList::ALLOW_EMPTY, nullptr, rng); } TEST(RemoteList, CtorRemoteListConnBlockFactory) { @@ -183,16 +183,16 @@ TEST(RemoteList, CtorRemoteListConnBlockFactory) cfg.update_map(); TestConnBlockFactory tcbf; - RandomAPI::Ptr rng; + const RandomAPI::Ptr rng; testLog->startCollecting(); - RemoteList rl1(cfg, "block", 0, &tcbf, rng); - std::string output1(testLog->stopCollecting()); + const RemoteList rl1(cfg, "block", 0, &tcbf, rng); + const std::string output1(testLog->stopCollecting()); ASSERT_NE(output1.find("TestConnBlock"), std::string::npos); ASSERT_EQ(rl1.size(), 2UL); testLog->startCollecting(); - RemoteList rl2(cfg, "block", RemoteList::CONN_BLOCK_OMIT_UNDEF, &tcbf, rng); - std::string output2(testLog->stopCollecting()); + const RemoteList rl2(cfg, "block", RemoteList::CONN_BLOCK_OMIT_UNDEF, &tcbf, rng); + const std::string output2(testLog->stopCollecting()); ASSERT_NE(output2.find("TestConnBlock"), std::string::npos); ASSERT_EQ(rl2.size(), 1UL); } @@ -209,10 +209,10 @@ TEST(RemoteList, CtorRemoteListWarnUnsupported) nullptr); cfg.update_map(); - RandomAPI::Ptr rng; + const RandomAPI::Ptr rng; testLog->startCollecting(); - RemoteList rl(cfg, "", RemoteList::WARN_UNSUPPORTED, nullptr, rng); - std::string output(testLog->stopCollecting()); + const RemoteList rl(cfg, "", RemoteList::WARN_UNSUPPORTED, nullptr, rng); + const std::string output(testLog->stopCollecting()); ASSERT_NE(output.find(" http-proxy "), std::string::npos); ASSERT_NE(output.find(" http-proxy-option "), std::string::npos); @@ -229,7 +229,7 @@ TEST(RemoteList, CtorRemoteListBlockLimit) nullptr); cfg.update_map(); - RandomAPI::Ptr rng; + const RandomAPI::Ptr rng; JY_EXPECT_THROW(RemoteList(cfg, "", 0, nullptr, rng), option_error, "connection_block"); } @@ -251,7 +251,7 @@ TEST(RemoteList, ListTraversal) std::string port; Protocol proto; - RemoteList::Ptr rl(new RemoteList(cfg, "", 0, nullptr, nullptr)); + const RemoteList::Ptr rl(new RemoteList(cfg, "", 0, nullptr, nullptr)); bool available = rl->endpoint_available(&addr, &port, &proto); ASSERT_EQ(available, false); ASSERT_EQ(addr, "1.domain.tld"); @@ -304,12 +304,12 @@ TEST(RemoteList, RemoteListBulkResolve) nullptr); cfg.update_map(); - RandomAPI::Ptr rng(new MTRand(3735928559)); - RemoteList::Ptr rl(new RemoteList(cfg, "", 0, nullptr, rng)); + const RandomAPI::Ptr rng(new MTRand(3735928559)); + const RemoteList::Ptr rl(new RemoteList(cfg, "", 0, nullptr, rng)); rl->set_enable_cache(true); openvpn_io::io_context ioctx; - SessionStats::Ptr stats(new SessionStats()); + const SessionStats::Ptr stats(new SessionStats()); FakeAsyncResolvable< RemoteList::BulkResolve, openvpn_io::io_context &, @@ -329,7 +329,7 @@ TEST(RemoteList, RemoteListBulkResolve) ASSERT_NE(output.find("<<<RemoteListBulkResolve>>>"), std::string::npos); ASSERT_EQ(5UL, rl->size()) - << "Unexpected remote list item count" << std::endl + << "Unexpected remote list item count\n" << output; ASSERT_EQ(rl->get_item(0)->res_addr_list_defined(), true); @@ -379,7 +379,7 @@ TEST(RemoteList, RemoteListBulkResolve) output = testLog->stopCollecting(); ASSERT_EQ(5UL, rl->size()) - << "Unexpected remote list item count" << std::endl + << "Unexpected remote list item count\n" << output; ASSERT_EQ(rl->get_item(0)->res_addr_list_defined(), true); @@ -418,7 +418,7 @@ TEST(RemoteList, RemoteListBulkResolve) // Cache was still be good, i.e. no updated 3 and 4 ASSERT_EQ(5UL, rl->size()) - << "Unexpected remote list item count" << std::endl + << "Unexpected remote list item count\n" << output; ASSERT_EQ(rl->get_item(2)->res_addr_list_defined(), true); @@ -444,7 +444,7 @@ TEST(RemoteList, RemoteListBulkResolve) output = testLog->stopCollecting(); ASSERT_EQ(5UL, rl->size()) - << "Unexpected remote list item count" << std::endl + << "Unexpected remote list item count\n" << output; for (size_t i = 0; i < rl->size(); ++i) @@ -524,7 +524,7 @@ TEST(RemoteList, RemoteRandomHostname) nullptr); cfg.update_map(); - RandomAPI::Ptr rng(new FakeSecureRand(0xf7)); + const RandomAPI::Ptr rng(new FakeSecureRand(0xf7)); RemoteList rl(cfg, "", 0, nullptr, rng); ASSERT_EQ(rl.size(), 4UL); @@ -557,8 +557,8 @@ TEST(RemoteList, RemoteRandomHostnameNoRNG) nullptr); cfg.update_map(); - RandomAPI::Ptr no_rng; - RemoteList rl(cfg, "", 0, nullptr, no_rng); + const RandomAPI::Ptr no_rng; + const RemoteList rl(cfg, "", 0, nullptr, no_rng); ASSERT_EQ(rl.current_server_host(), "domain.invalid"); } @@ -574,7 +574,7 @@ TEST(RemoteList, OverrideFunctions) nullptr); cfg.update_map(); - RandomAPI::Ptr rng(new FakeSecureRand(0xf7)); + const RandomAPI::Ptr rng(new FakeSecureRand(0xf7)); RemoteList rl(cfg, "", 0, nullptr, rng); ASSERT_EQ(rl.size(), 3UL); diff --git a/test/unittests/test_route.cpp b/test/unittests/test_route.cpp index 88754d480..0f9e688e8 100644 --- a/test/unittests/test_route.cpp +++ b/test/unittests/test_route.cpp @@ -26,7 +26,7 @@ void test_route_parse(const std::string &rstr, const std::string &expected, bool } } -TEST(IPAddr, routeSet) +TEST(IPAddr, RouteSet) { std::set<IP::Route> routes; routes.emplace("1.2.3.4/24"); @@ -39,7 +39,7 @@ TEST(IPAddr, routeSet) std::stringstream out; for (const auto &r : routes) - out << r.to_string() << std::endl; + out << r.to_string() << '\n'; ASSERT_EQ("128.0.0.0/1\n" "1.2.3.0/24\n" @@ -54,20 +54,20 @@ TEST(IPAddr, routeSet) template <typename LIST> void test_split(const LIST &rtlist, const std::string &expected) { - typedef typename LIST::value_type RT; + using RT = typename LIST::value_type; std::stringstream out; for (const auto &r : rtlist) { RT r1, r2; if (r.is_canonical() && r.split(r1, r2)) { - out << r << ' ' << r1 << ' ' << r2 << std::endl; + out << r << ' ' << r1 << ' ' << r2 << "\n"; } } ASSERT_EQ(expected, out.str()); } -TEST(IPAddr, routeList4) +TEST(IPAddr, RouteList4) { IP::Route4List routes; routes.emplace_back("1.2.3.4/24"); @@ -82,7 +82,7 @@ TEST(IPAddr, routeList4) test_split(routes, "1.2.3.0/24 1.2.3.0/25 1.2.3.128/25\n128.0.0.0/1 128.0.0.0/2 192.0.0.0/2\n"); } -TEST(IPAddr, routeList6) +TEST(IPAddr, RouteList6) { IP::Route6List routes; routes.emplace_back("1:2:3:4:5:6:dead:beef/64"); @@ -93,7 +93,7 @@ TEST(IPAddr, routeList6) test_split(routes, "cafe:babe::/64 cafe:babe::/65 cafe:babe:0:0:8000::/65\n"); } -TEST(IPAddr, routeList) +TEST(IPAddr, RouteList) { IP::RouteList routes; routes.emplace_back("1.2.3.4/24"); @@ -114,7 +114,7 @@ TEST(IPAddr, routeList) "cafe:babe::/64 cafe:babe::/65 cafe:babe:0:0:8000::/65\n"); } -TEST(IPAddr, parseRoutes) +TEST(IPAddr, ParseRoutes) { test_route_parse("1.2.3.4", "1.2.3.4/32", false); test_route_parse("192.168.4.0/24", "192.168.4.0/24", false); diff --git a/test/unittests/test_route_emulation.cpp b/test/unittests/test_route_emulation.cpp index 9841e0420..4606ebf56 100644 --- a/test/unittests/test_route_emulation.cpp +++ b/test/unittests/test_route_emulation.cpp @@ -20,7 +20,7 @@ namespace unittests { #define DEBUG_PRINT_ROUTES \ for (auto &rt : tb->routes) \ - std::cout << rt << std::endl; + std::cout << rt << "\n"; /* Helper function for quick result comparision */ std::string join_string_vector_sorted(std::vector<std::string> vec, const char *const delim = ", ") @@ -62,7 +62,7 @@ class TunBuilderMock : public openvpn::TunBuilderBase std::vector<std::string> routes; std::vector<openvpn::IP::Route> routesAddr; - bool containsIP(std::string ipaddr) + bool containsIP(const std::string &ipaddr) { return containsIP(openvpn::IP::Addr(ipaddr)); } @@ -108,7 +108,7 @@ class RouteEmulationTest : public testing::Test if (!keepEmu) { - openvpn::EmulateExcludeRouteFactory::Ptr factory( + const openvpn::EmulateExcludeRouteFactory::Ptr factory( new openvpn::EmulateExcludeRouteFactoryImpl(excludeServer)); emu = factory->new_obj(); @@ -127,12 +127,12 @@ class RouteEmulationTest : public testing::Test void addRoute(bool include, const std::string &route) { - std::string ipstr = route.substr(0, route.find('/')); - std::string mask = route.substr(route.find('/') + 1); + const std::string ipstr = route.substr(0, route.find('/')); + const std::string mask = route.substr(route.find('/') + 1); emu->add_route(include, openvpn::IP::Addr(ipstr), std::stoi(mask)); } - void doEmulate(std::string serverip = "1.2.3.4") + void doEmulate(const std::string &serverip = "1.2.3.4") { emu->emulate(this->tb, *this->ipflags, openvpn::IP::Addr(serverip)); } @@ -153,7 +153,7 @@ TEST_F(RouteEmulationTest, ExcludeOneSubnet) doEmulate(); - ASSERT_EQ(tb->routes.size(), 24u); + ASSERT_EQ(tb->routes.size(), 24U); } TEST_F(RouteEmulationTest, ExcludeSubnetsNoDefault) @@ -167,7 +167,7 @@ TEST_F(RouteEmulationTest, ExcludeSubnetsNoDefault) doEmulate(); - ASSERT_EQ(tb->routes.size(), 1u); + ASSERT_EQ(tb->routes.size(), 1U); ASSERT_EQ(tb->routes.at(0), "10.20.128.0/17"); setup(true, false); @@ -178,17 +178,17 @@ TEST_F(RouteEmulationTest, ExcludeSubnetsNoDefault) doEmulate(); - ASSERT_EQ(tb->routes.size(), 1u); + ASSERT_EQ(tb->routes.size(), 1U); ASSERT_EQ(tb->routes.at(0), "2500:1000::/33"); } -TEST_F(RouteEmulationTest, excludeServer) +TEST_F(RouteEmulationTest, ExcludeServer) { setup(false, true); emu->add_default_routes(true, true); doEmulate("1.2.3.4"); - ASSERT_EQ(tb->routes.size(), 32u); + ASSERT_EQ(tb->routes.size(), 32U); ASSERT_FALSE(tb->containsIP("1.2.3.4")); ASSERT_TRUE(tb->containsIP("1.2.3.5")); ASSERT_TRUE(tb->containsIP("1.2.3.3")); @@ -198,14 +198,14 @@ TEST_F(RouteEmulationTest, excludeServer) emu->add_default_routes(true, true); doEmulate("::1.2.3.4"); - ASSERT_EQ(tb->routes.size(), 128u); + ASSERT_EQ(tb->routes.size(), 128U); ASSERT_FALSE(tb->containsIP("::1.2.3.4")); ASSERT_TRUE(tb->containsIP("::1.2.3.5")); ASSERT_TRUE(tb->containsIP("::1.2.3.3")); ASSERT_TRUE(tb->containsIP("::4.3.2.1")); } -TEST_F(RouteEmulationTest, nestedIPRoutes) +TEST_F(RouteEmulationTest, NestedIPRoutes) { // This sets up a number of routes that are all included in each @@ -270,7 +270,7 @@ TEST_F(RouteEmulationTest, DefaultRoute) doEmulate(); - ASSERT_EQ(tb->routes.size(), 1u); + ASSERT_EQ(tb->routes.size(), 1U); ASSERT_EQ(tb->routes.at(0), "0.0.0.0/0"); // Now something more tricky add unnecessary extra route @@ -281,7 +281,7 @@ TEST_F(RouteEmulationTest, DefaultRoute) doEmulate(); - ASSERT_EQ(tb->routes.size(), 2u); + ASSERT_EQ(tb->routes.size(), 2U); ASSERT_EQ(tb->routes.at(0), "0.0.0.0/0"); } diff --git a/test/unittests/test_safestr.cpp b/test/unittests/test_safestr.cpp index 8d210a45e..c3f266e0c 100644 --- a/test/unittests/test_safestr.cpp +++ b/test/unittests/test_safestr.cpp @@ -24,12 +24,12 @@ static void compare(const SafeString &s1, const SafeString &s2, const bool expec ASSERT_NE(s1 != s2.to_string(), expect_eq); } -TEST(safestr, test_1) +TEST(Safestr, Test1) { - SafeString a("mybigsecret"); - SafeString b("mybigsekret"); - SafeString c("mybigsekrets"); - SafeString a2("mybigsecret"); + const SafeString a("mybigsecret"); + const SafeString b("mybigsekret"); + const SafeString c("mybigsekrets"); + const SafeString a2("mybigsecret"); compare(a, a2, true); compare(a2, a, true); diff --git a/test/unittests/test_session_id.cpp b/test/unittests/test_session_id.cpp index fe878c1b3..108ed1b2b 100644 --- a/test/unittests/test_session_id.cpp +++ b/test/unittests/test_session_id.cpp @@ -7,14 +7,14 @@ using namespace openvpn; -TEST(sessid, test1) +TEST(Sessid, Test1) { SSLLib::RandomAPI rng; // test 1 { const SessionID64 sid1(rng); - // std::cout << "SID1: " << sid1 << std::endl; + // std::cout << "SID1: " << sid1 << "\n"; const SessionID64 sid2(sid1.to_string()); ASSERT_TRUE(sid1.defined() && sid2.defined()) << "FAIL sid1 or sid2 is undefined"; @@ -26,41 +26,40 @@ TEST(sessid, test1) for (int i = 1; i <= 4; ++i) { - // std::cout << "---- " << i << " ----" << std::endl; + // std::cout << "---- " << i << " ----\n"; const TokenEncrypt::Key key(rng); TokenEncryptDecrypt ted(key); const SessionID128 sid3_enc(sid3, ted.encrypt); - // std::cout << "SID3 (enc): " << sid3_enc << std::endl; + // std::cout << "SID3 (enc): " << sid3_enc << "\n"; const SessionID128 sid3_dec(sid3_enc, ted.decrypt); - // std::cout << "SID3 (dec): " << sid3_dec << std::endl; + // std::cout << "SID3 (dec): " << sid3_dec << "\n"; } } } -TEST(sessid, test2) +TEST(Sessid, Test2) { SSLLib::RandomAPI rng; { const SessionID64 sid1(rng); - // std::cout << "SID1: " << sid1 << std::endl; + // std::cout << "SID1: " << sid1 << "\n"; const SessionID128 sid2(rng); - // std::cout << "SID2: " << sid2 << std::endl; + // std::cout << "SID2: " << sid2 << "\n"; const SessionID128 sid1_exp(sid1); - // std::cout << "SID1_EXP: " << sid1_exp << std::endl; + // std::cout << "SID1_EXP: " << sid1_exp << "\n"; const SessionID64 sid2_trunc(sid2); - // std::cout << "SID2_TRUNC: " << sid2_trunc << std::endl; + // std::cout << "SID2_TRUNC: " << sid2_trunc << "\n"; } } -TEST(sessid, test3) +TEST(Sessid, Test3) { const SessionID64 ns; ASSERT_FALSE(ns.defined()) << "FAIL default constructed SessionID is defined"; } -TEST(sessid, test4) +TEST(Sessid, Test4) { - SSLLib::RandomAPI rng; const SessionID128 x; const SessionID128 a("YmtN7B2edrDRlefk3vQ_YQ.."); const SessionID128 b("YmtN7B2edrDRlefk3vQ_YA.."); @@ -95,7 +94,7 @@ TEST(sessid, test4) ASSERT_FALSE(s2) << "test4: shouldn't have found s2"; } -TEST(sessid, speed) +TEST(Sessid, Speed) { SSLLib::RandomAPI rng; @@ -130,7 +129,7 @@ struct SessionID : public SessionID128 void dump(const char *prefix) const { - std::cout << prefix << " : " << to_string() << std::endl; + std::cout << prefix << " : " << to_string() << '\n'; } }; @@ -158,7 +157,7 @@ std::string test(Session *session) return "Name: " + nam + " SessID: " + sid.to_string(); } -TEST(sessid, refscope1) +TEST(Sessid, Refscope1) { FakeSecureRand fake_rng(0x42); Session sess(fake_rng); @@ -182,9 +181,9 @@ static void tryit(RandomAPI &rng, TokenEncryptDecrypt &encdec) ASSERT_TRUE(::memcmp(data1, data3, TokenEncrypt::Key::SIZE) == 0); } -TEST(sessid, tokenEncrypt) +TEST(Sessid, TokenEncrypt) { - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); const TokenEncrypt::Key key(*rng); TokenEncryptDecrypt encdec(key); diff --git a/test/unittests/test_sitnl.cpp b/test/unittests/test_sitnl.cpp index 9d39655a1..790191d05 100644 --- a/test/unittests/test_sitnl.cpp +++ b/test/unittests/test_sitnl.cpp @@ -60,10 +60,10 @@ class SitnlTest : public testing::Test static void SetUpTestSuite() { // different distros have ip tool in different places - std::vector<std::string> paths{"/bin/ip", "/sbin/ip", "/usr/bin/ip", "/usr/sbin/ip"}; + const std::vector<std::string> paths{"/bin/ip", "/sbin/ip", "/usr/bin/ip", "/usr/sbin/ip"}; for (const auto &path : paths) { - std::ifstream f(path); + const std::ifstream f(path); if (f) { path_to_ip = path; @@ -126,7 +126,6 @@ class SitnlTest : public testing::Test void ip_a_show_dev(CALLBACK cb) { // get addrs with "ip a show dev" - RedirectPipe::InOut pipe; Argv argv; argv.emplace_back(path_to_ip); argv.emplace_back("a"); @@ -140,7 +139,6 @@ class SitnlTest : public testing::Test void ip_route_get(std::string dst, CALLBACK cb) { // get route with "ip route get" - RedirectPipe::InOut pipe; Argv argv; argv.emplace_back(path_to_ip); argv.emplace_back("route"); @@ -253,7 +251,7 @@ TEST_F(SitnlTest, TestAddRoute6) { if (v1[0] == dst || v1[0] == dst_trunc) { - std::string dst_out = (v1[0] == dst) ? dst : dst_trunc; + const std::string dst_out = (v1[0] == dst) ? dst : dst_trunc; called = true; v1.resize(7); // iproute 4.15 (Ubuntu 18) diff --git a/test/unittests/test_splitlines.cpp b/test/unittests/test_splitlines.cpp index feff0f041..15a0ad581 100644 --- a/test/unittests/test_splitlines.cpp +++ b/test/unittests/test_splitlines.cpp @@ -20,7 +20,7 @@ const std::string short_text = "Lorem\nipsum\r\ndolor\n\r\nsit"; const std::vector<std::string> short_lines{"Lorem\n", "ipsum\r\n", "dolor\n", "\r\n", "sit"}; const std::vector<std::string> short_lines_trim{"Lorem", "ipsum", "dolor", "", "sit"}; -TEST(SplitLines, no_max_length_no_trim) +TEST(SplitLines, NoMaxLengthNoTrim) { SplitLines in(short_text, 0); size_t index = 0; @@ -30,7 +30,7 @@ TEST(SplitLines, no_max_length_no_trim) } } -TEST(SplitLines, next_no_max_length_no_trim) +TEST(SplitLines, NextNoMaxLengthNoTrim) { SplitLines in(short_text, 0); size_t index = 0; @@ -43,7 +43,7 @@ TEST(SplitLines, next_no_max_length_no_trim) } } -TEST(SplitLines, no_max_length_trim) +TEST(SplitLines, NoMaxLengthTrim) { SplitLines in(short_text, 0); size_t index = 0; @@ -54,7 +54,7 @@ TEST(SplitLines, no_max_length_trim) } } -TEST(SplitLines, next_no_max_length_trim) +TEST(SplitLines, NextNoMaxLengthTrim) { SplitLines in(short_text, 0); size_t index = 0; @@ -67,7 +67,7 @@ TEST(SplitLines, next_no_max_length_trim) } } -TEST(SplitLines, max_length) +TEST(SplitLines, MaxLength) { SplitLines in(short_text, 24); size_t index = 0; @@ -78,7 +78,7 @@ TEST(SplitLines, max_length) } } -TEST(SplitLines, next_max_length) +TEST(SplitLines, NextMaxLength) { SplitLines in(short_text, 24); size_t index = 0; @@ -91,7 +91,7 @@ TEST(SplitLines, next_max_length) } } -TEST(SplitLines, max_length_overflow) +TEST(SplitLines, MaxLengthOverflow) { SplitLines in(short_text, 3); ASSERT_TRUE(in(true)); @@ -99,18 +99,18 @@ TEST(SplitLines, max_length_overflow) ASSERT_THROW(in.line_ref(), SplitLines::overflow_error); } -TEST(SplitLines, next_max_length_overflow) +TEST(SplitLines, NextMaxLengthOverflow) { SplitLines in(short_text, 3); std::string line; ASSERT_EQ(in.next(line, true), SplitLines::S_ERROR); } -TEST(SplitLines, moved_error) +TEST(SplitLines, MovedError) { SplitLines in(short_text); ASSERT_TRUE(in(true)); ASSERT_FALSE(in.line_overflow()); - std::string line = in.line_move(); + const std::string line = in.line_move(); ASSERT_THROW(in.line_ref(), SplitLines::moved_error); } diff --git a/test/unittests/test_ssl.cpp b/test/unittests/test_ssl.cpp index 35d61c9ac..d1af99e5f 100644 --- a/test/unittests/test_ssl.cpp +++ b/test/unittests/test_ssl.cpp @@ -18,10 +18,14 @@ using namespace openvpn; #include <openvpn/ssl/sslchoose.hpp> #include <openvpn/ssl/sslapi.hpp> -TEST(ssl, sslciphersuites) +#ifdef USE_OPENSSL +#include <openssl/opensslv.h> +#endif + +TEST(Ssl, Sslciphersuites) { SSLFactoryAPI::Ptr sslfact; - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); + const SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); sslcfg->set_local_cert_enabled(false); sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); @@ -31,7 +35,7 @@ TEST(ssl, sslciphersuites) sslcfg->set_tls_ciphersuite_list("TLS_CHACHA2000"); -#if defined(USE_MBEDTLS) +#ifdef USE_MBEDTLS /* Ignored on non TLS 1.3 implementations */ sslfact = sslcfg->new_factory(); #else @@ -40,14 +44,14 @@ TEST(ssl, sslciphersuites) #endif } -TEST(ssl, sslciphers) +TEST(Ssl, Sslciphers) { - StrongRandomAPI::Ptr rng(new FakeSecureRand); + const StrongRandomAPI::Ptr rng(new FakeSecureRand); - bool previousLogOutput = testLog->isStdoutEnabled(); + const bool previousLogOutput = testLog->isStdoutEnabled(); testLog->setPrintOutput(false); SSLFactoryAPI::Ptr sslfact; - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); + const SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); sslcfg->set_local_cert_enabled(false); sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); sslcfg->set_rng(rng); @@ -61,13 +65,13 @@ TEST(ssl, sslciphers) testLog->setPrintOutput(previousLogOutput); } -TEST(ssl, tls_groups) +TEST(Ssl, TlsGroups) { - StrongRandomAPI::Ptr rng(new FakeSecureRand); + const StrongRandomAPI::Ptr rng(new FakeSecureRand); - SSLFactoryAPI::Ptr sslfact; + const SSLFactoryAPI::Ptr sslfact; - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); + const SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); sslcfg->set_local_cert_enabled(false); sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); sslcfg->set_rng(rng); @@ -82,20 +86,28 @@ TEST(ssl, tls_groups) sslcfg->set_tls_groups("secp521r1:secp384r1:greenhell"); testLog->startCollecting(); +#if defined(USE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L + OVPN_EXPECT_THROW( + f = sslcfg->new_factory(), + openvpn::SSLFactoryAPI::ssl_context_error, + "OpenSSLContext: SSL_CTX_set1_groups_list failed"); +#else f = sslcfg->new_factory(); f->set_log_level(logging::LOG_LEVEL_INFO); f->ssl(); + #ifdef USE_OPENSSL EXPECT_EQ("OpenSSL -- warning ignoring unknown group 'greenhell' in tls-groups\n", testLog->stopCollecting()); #else EXPECT_EQ("mbed TLS -- warning ignoring unknown group 'greenhell' in tls-groups\n", testLog->stopCollecting()); #endif +#endif } -#if defined(USE_OPENSSL) -TEST(ssl, translate_ciphers_openssl) +#ifdef USE_OPENSSL +TEST(Ssl, TranslateCiphersOpenssl) { - bool previousLogOutput = testLog->isStdoutEnabled(); + const bool previousLogOutput = testLog->isStdoutEnabled(); testLog->setPrintOutput(false); EXPECT_EQ("ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:AES256-SHA", OpenSSLContext::translate_cipher_list("TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:AES256-SHA")); @@ -107,11 +119,11 @@ TEST(ssl, translate_ciphers_openssl) #endif #if defined(USE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L -TEST(ssl, enablelegacyProvider) +TEST(Ssl, EnablelegacyProvider) { - StrongRandomAPI::Ptr rng(new FakeSecureRand); + const StrongRandomAPI::Ptr rng(new FakeSecureRand); - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); + const SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); sslcfg->set_local_cert_enabled(false); sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); sslcfg->set_rng(rng); @@ -120,7 +132,7 @@ TEST(ssl, enablelegacyProvider) EXPECT_EQ(SSLLib::CryptoAPI::CipherContext::is_supported(f_nolegacy->libctx(), openvpn::CryptoAlgs::BF_CBC), false); - SSLLib::SSLAPI::Config::Ptr sslcfg_legacy(new SSLLib::SSLAPI::Config); + const SSLLib::SSLAPI::Config::Ptr sslcfg_legacy(new SSLLib::SSLAPI::Config); sslcfg_legacy->set_local_cert_enabled(false); sslcfg_legacy->set_flags(SSLConst::NO_VERIFY_PEER); sslcfg_legacy->set_rng(rng); diff --git a/test/unittests/test_sslctx.cpp b/test/unittests/test_sslctx.cpp index da32df747..cf067c66f 100644 --- a/test/unittests/test_sslctx.cpp +++ b/test/unittests/test_sslctx.cpp @@ -236,20 +236,20 @@ I/+4kAlXuAKdhsXohHeBhC2ijg/kTOMDxEbEVv+SkCIUyM+dB8UtlPKOH9HEL5Xi +BpDSqO6Bha5+NAVUU7OdDsnzRwSWaD6lwIBAgICAOE= -----END DH PARAMETERS-----)"; -TEST(sslctx_ut, create_config) +TEST(SslctxUt, CreateConfig) { - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + const SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; // Do not log extra data during unit test config->set_debug_level(0); EXPECT_TRUE(config); } -TEST(sslctx_ut, config_new_factory_server) +TEST(SslctxUt, ConfigNewFactoryServer) { - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + const SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; EXPECT_TRUE(config); - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); config->set_rng(rng); config->set_mode(Mode(Mode::SERVER)); @@ -267,12 +267,12 @@ TEST(sslctx_ut, config_new_factory_server) EXPECT_TRUE(server); } -TEST(sslctx_ut, config_new_factory_client) +TEST(SslctxUt, ConfigNewFactoryClient) { - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + const SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; EXPECT_TRUE(config); - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); config->set_rng(rng); config->set_mode(Mode(Mode::CLIENT)); @@ -301,7 +301,7 @@ inline void do_write(T &obj, const bool server, char *msg, const size_t len, lon if (status > 0) count += status; #if ITER <= ITER_OUT_LIMIT - std::cout << (server ? "SERVER" : "CLIENT") << " WRITE #" << iter << " status=" << status << std::endl; + std::cout << (server ? "SERVER" : "CLIENT") << " WRITE #" << iter << " status=" << status << '\n'; #endif } @@ -314,22 +314,22 @@ inline void do_read(T &obj, const bool server, char *msg, const size_t len, long #if ITER <= ITER_OUT_LIMIT const ssize_t trunc = 64; - std::cout << (server ? "SERVER" : "CLIENT") << " READ #" << iter << " status=" << status << std::endl; + std::cout << (server ? "SERVER" : "CLIENT") << " READ #" << iter << " status=" << status << '\n'; if (status >= trunc) { msg[trunc] = 0; - std::cout << "GOT IT: " << msg << std::endl; + std::cout << "GOT IT: " << msg << '\n'; } #endif } -static inline bool xfer_oneway(SSLAPI &sender, SSLAPI &recv, std::string out) +static inline bool xfer_oneway(SSLAPI &sender, SSLAPI &recv, const std::string &out) { if (sender.read_ciphertext_ready()) { - BufferPtr buf = sender.read_ciphertext(); + const BufferPtr buf = sender.read_ciphertext(); recv.write_ciphertext(buf); - std::cout << out << buf->size() << " bytes" << std::endl; + std::cout << out << buf->size() << " bytes\n"; return true; } @@ -338,9 +338,9 @@ static inline bool xfer_oneway(SSLAPI &sender, SSLAPI &recv, std::string out) /* this can also indicate an error */ uint8_t cleartext[1024]; - std::cout << out << " read ready?" << std::endl; + std::cout << out << " read ready?\n"; auto ctsize = sender.read_cleartext(cleartext, sizeof(cleartext)); - std::cout << ctsize << std::endl; + std::cout << ctsize << '\n'; EXPECT_FALSE(ctsize > 0); /* TODO: capture output for tests with data */ @@ -362,10 +362,10 @@ static inline auto MakeClient(Frame::Ptr frame, const std::string &cert, const std::string &ca = "") { - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + const SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; EXPECT_TRUE(config); - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); config->set_rng(rng); config->set_mode(Mode(Mode::CLIENT)); @@ -391,11 +391,11 @@ static inline auto MakeClient(Frame::Ptr frame, static inline auto MakeServer(Frame::Ptr frame, const std::string &pvt_key, const std::string &cert) { - SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; + const SSLLib::SSLAPI::Config::Ptr config = new SSLLib::SSLAPI::Config; config->enable_legacy_algorithms(false); EXPECT_TRUE(config); - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); config->set_rng(rng); config->set_mode(Mode(Mode::SERVER)); @@ -414,9 +414,9 @@ static inline auto MakeServer(Frame::Ptr frame, const std::string &pvt_key, cons return std::make_tuple(config, factory_server, server); } -TEST(sslctx_ut, handshake) +TEST(SslctxUt, Handshake) { - Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS))); auto [serverconfig, serverfactory, server] = MakeServer(frame, pvt_key_txt, cert_txt); auto [clientconfig, clientfactory, client] = MakeClient(std::move(frame), pvt_key_txt, cert_txt); @@ -430,7 +430,7 @@ TEST(sslctx_ut, handshake) try { - for (auto i = 0u; i < ITER; ++i) + for (auto i = 0U; i < ITER; ++i) { xfer(*client, *server); } @@ -441,9 +441,9 @@ TEST(sslctx_ut, handshake) } } -TEST(sslctx_ut, ca_handshake) +TEST(SslctxUt, CaHandshake) { - Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS))); auto [serverconfig, serverfactory, server] = MakeServer(frame, pvt_key_txt, cert_txt); auto [clientconfig, clientfactory, client] = MakeClient(std::move(frame), pvt_key_txt, cert_txt, cert_txt); @@ -457,7 +457,7 @@ TEST(sslctx_ut, ca_handshake) try { - for (auto i = 0u; i < ITER; ++i) + for (auto i = 0U; i < ITER; ++i) { xfer(*client, *server); } @@ -468,9 +468,9 @@ TEST(sslctx_ut, ca_handshake) } } -TEST(sslctx_ut, handshake_fail) +TEST(SslctxUt, HandshakeFail) { - Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS))); auto [serverconfig, serverfactory, server] = MakeServer(frame, fail_pvt_key_txt, fail_cert_txt); auto [clientconfig, clientfactory, client] = MakeClient(std::move(frame), pvt_key_txt, cert_txt); @@ -478,7 +478,7 @@ TEST(sslctx_ut, handshake_fail) try { - for (auto i = 0u; i < ITER; ++i) + for (auto i = 0U; i < ITER; ++i) { xfer(*client, *server); } @@ -493,13 +493,13 @@ TEST(sslctx_ut, handshake_fail) FAIL(); } -TEST(sslctx_ut, clienthello) +TEST(SslctxUt, Clienthello) { /* Checks that a server context correctly responds to a TLS 1.3 client hello */ uint8_t clienthello[] = { 0x16, 0x03, 0x01, 0x01, 0x10, 0x01, 0x00, 0x01, 0x0c, 0x03, 0x03, 0x0a, 0xef, 0xce, 0xc6, 0xe3, 0xcc, 0xb7, 0x7c, 0x38, 0xb2, 0x0e, 0xac, 0x12, 0xb5, 0xfa, 0x6d, 0x98, 0xc7, 0x76, 0xd1, 0x96, 0x22, 0x97, 0xf5, 0x57, 0xc5, 0x12, 0xf7, 0x01, 0xfc, 0xbe, 0x7d, 0x20, 0x64, 0xbd, 0xb5, 0x68, 0x06, 0x55, 0xb1, 0xf3, 0xf3, 0xc7, 0xb4, 0x1b, 0xbe, 0x83, 0x89, 0xab, 0xa5, 0xa0, 0x55, 0xa5, 0x6d, 0xca, 0xb1, 0x21, 0x5f, 0x2c, 0x71, 0xf5, 0x13, 0x4d, 0xeb, 0x68, 0x00, 0x32, 0x13, 0x02, 0x13, 0x03, 0x13, 0x01, 0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x2b, 0xc0, 0x2f, 0x00, 0x9e, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x6b, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x67, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x39, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x33, 0x00, 0xff, 0x01, 0x00, 0x00, 0x91, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x14, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x19, 0x00, 0x18, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x2a, 0x00, 0x28, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x08, 0x07, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0a, 0x08, 0x0b, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x00, 0x2b, 0x00, 0x05, 0x04, 0x03, 0x04, 0x03, 0x03, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x6e, 0x11, 0xc2, 0x45, 0x19, 0x7c, 0x68, 0x45, 0xf8, 0x4f, 0xa4, 0x26, 0xa2, 0x39, 0xce, 0xf1, 0x38, 0x8d, 0x83, 0x35, 0xee, 0x45, 0x74, 0x08, 0x83, 0x08, 0x44, 0x15, 0xf7, 0xd4, 0x38, 0x13}; - Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, 0))); + Frame::Ptr frame(new Frame(Frame::Context(128, 4096, 4096 - 128, 0, 16, BufAllocFlags::NO_FLAGS))); auto [serverconfig, serverfactory, server] = MakeServer(std::move(frame), pvt_key_txt, cert_txt); server->start_handshake(); @@ -511,9 +511,9 @@ TEST(sslctx_ut, clienthello) uint8_t cleartext[1024]; auto ctsize = server->read_cleartext(cleartext, sizeof(cleartext)); - std::cout << ctsize << std::endl; + std::cout << ctsize << '\n'; EXPECT_TRUE(server->read_ciphertext_ready()); auto buf = server->read_ciphertext(); ASSERT_TRUE(buf->length() > 1); -} \ No newline at end of file +} diff --git a/test/unittests/test_statickey.cpp b/test/unittests/test_statickey.cpp index fcc37cc7b..a4df1b241 100644 --- a/test/unittests/test_statickey.cpp +++ b/test/unittests/test_statickey.cpp @@ -27,17 +27,17 @@ const char key_text[] = "-----BEGIN OpenVPN Static key V1-----\n" "f7591ead4710bd0e74c0b37e37c84374\n" "-----END OpenVPN Static key V1-----\n"; -TEST(statickey, key1) +TEST(Statickey, Key1) { // This test only tests if loading a static key works OpenVPNStaticKey sk; sk.parse(std::string(key_text)); - std::string rend = sk.render(); + const std::string rend = sk.render(); } -TEST(statickey, key2) +TEST(Statickey, Key2) { - StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); + const StrongRandomAPI::Ptr rng(new SSLLib::RandomAPI()); const size_t key_len = 16; StaticKey sk1; sk1.init_from_rng(*rng, key_len); @@ -51,7 +51,7 @@ TEST(statickey, key2) class StaticSinkBase : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<StaticSinkBase> Ptr; + using Ptr = RCPtr<StaticSinkBase>; virtual void init(StaticKey &&key) = 0; virtual std::string dump() = 0; @@ -74,12 +74,12 @@ class StaticSink : public StaticSinkBase StaticKey k; }; -TEST(statickey, move) +TEST(Statickey, Move) { OpenVPNStaticKey sk; sk.parse(std::string(key_text)); - StaticSinkBase::Ptr ss(new StaticSink()); + const StaticSinkBase::Ptr ss(new StaticSink()); ss->init(sk.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | OpenVPNStaticKey::INVERSE)); ASSERT_EQ( "a2a54bd892fa20edbcfe4fe1fa8a786c5c1102a3b53e294c729b37a24842f9c9b72018b990aff058bbeeaf18f586cd5cd70475328caed6d9662937a3c970f253", diff --git a/test/unittests/test_streq.cpp b/test/unittests/test_streq.cpp index 6b410ae56..cd65a9705 100644 --- a/test/unittests/test_streq.cpp +++ b/test/unittests/test_streq.cpp @@ -15,7 +15,7 @@ void test(const std::string &s1, const std::string &s2, const bool should_eq) ASSERT_NE(neq, should_eq); } -TEST(misc, streq) +TEST(Misc, Streq) { test("", "", true); test("x", "", false); diff --git a/test/unittests/test_string.cpp b/test/unittests/test_string.cpp new file mode 100644 index 000000000..b5b85b1ad --- /dev/null +++ b/test/unittests/test_string.cpp @@ -0,0 +1,105 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012- OpenVPN Inc. +// +// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception +// + +#include "test_common.hpp" + +#include <openvpn/common/string.hpp> + +using namespace openvpn; + +TEST(OvpnStringSuite, TestArgsToStringEmpty) +{ + const auto str = string::args_to_string(", "); + EXPECT_EQ(str, ""); +} + +TEST(OvpnStringSuite, TestArgsToStringOne) +{ + const auto str = string::args_to_string(", ", "a"); + EXPECT_EQ(str, "a"); +} + +TEST(OvpnStringSuite, TestArgsToStringTwo) +{ + const auto str = string::args_to_string(", ", "a", "b"); + EXPECT_EQ(str, "a, b"); +} + +TEST(OvpnStringSuite, TestArgsToStringThree) +{ + const auto str = string::args_to_string(", ", "a", "b", "c"); + EXPECT_EQ(str, "a, b, c"); +} + +TEST(OvpnStringSuite, TestArgsToStringFour) +{ + const auto str = string::args_to_string(", ", "a", "b", "c", "d"); + EXPECT_EQ(str, "a, b, c, d"); +} + +TEST(OvpnStringSuite, TestArgsToStringTwoMixed) +{ + const auto str = string::args_to_string(", ", "a", 1); + EXPECT_EQ(str, "a, 1"); +} + +TEST(OvpnStringSuite, TestArgsToStringThreeMixed) +{ + const auto str = string::args_to_string("", "a", 1, "b"); + EXPECT_EQ(str, "a1b"); +} + +TEST(OvpnStringSuite, TestFormatSafeEmpty) +{ + const auto str = string::format_safe(""); + EXPECT_TRUE(str); + EXPECT_EQ(*str, ""); +} + +TEST(OvpnStringSuite, TestFormatSafeZero) +{ + const auto str = string::format_safe("a"); + EXPECT_TRUE(str); + EXPECT_EQ(*str, "a"); +} + +TEST(OvpnStringSuite, TestFormatSafeOne) +{ + const auto str = string::format_safe("a {}", 1); + EXPECT_TRUE(str); + EXPECT_EQ(*str, "a 1"); +} + +TEST(OvpnStringSuite, TestFormatSafeTwo) +{ + const auto str = string::format_safe("a {} {}", 1, 2); + EXPECT_TRUE(str); + EXPECT_EQ(*str, "a 1 2"); +} + +TEST(OvpnStringSuite, TestFormatSafeThree) +{ + const auto str = string::format_safe("a {} {} {}", 1, "2", 3); + EXPECT_TRUE(str); + EXPECT_EQ(*str, "a 1 2 3"); +} + +TEST(OvpnStringSuite, TestFormatSafeMalformed) +{ + const auto str = string::format_safe("a } {} {} {}", 1, "2", 3); + EXPECT_FALSE(str); +} + +TEST(OvpnStringSuite, TestFormatSafeMalformed2) +{ + const auto str = string::format_safe("a {} {} {} {}", 1, "2", 3); + EXPECT_FALSE(str); +} diff --git a/test/unittests/test_time.cpp b/test/unittests/test_time.cpp index 9bd628dc9..7fe1b0815 100644 --- a/test/unittests/test_time.cpp +++ b/test/unittests/test_time.cpp @@ -13,8 +13,7 @@ int my_abs(const int value) { if (value >= 0) return value; - else - return -value; + return -value; } class Mean @@ -76,7 +75,7 @@ void test_skew(const Time::Duration &dur, OPENVPN_LOG("BEFORE=" << dur.to_binary_ms() << " AFTER=" << after.to_binary_ms()); } -TEST(time, timeskew) +TEST(Time, Timeskew) { MTRand::Ptr prng(new MTRand()); MeanDev md; @@ -89,7 +88,7 @@ TEST(time, timeskew) md.dev.check_mean_range("dev", 1250, 1350); } -TEST(time, test1) +TEST(Time, Test1) { Time::reset_base(); @@ -107,7 +106,7 @@ TEST(time, test1) const Time::type frac = t.fractional_binary_ms(); if (sec != last_sec || frac != last_frac) { - // std::cout << sec << ' ' << frac << std::endl; + // std::cout << sec << ' ' << frac << "\n"; last_sec = sec; last_frac = frac; } @@ -117,17 +116,17 @@ TEST(time, test1) static void sub(const Time &t1, const Time &t2, bool large) { const Time::Duration d = t1 - t2; - // std::cout << "T-T " << t1.raw() << " - " << t2.raw() << " = " << d.raw() << std::endl; + // std::cout << "T-T " << t1.raw() << " - " << t2.raw() << " = " << d.raw() << "\n"; if (large) - ASSERT_GE(d.raw(), 100000u); + ASSERT_GE(d.raw(), 100000U); else - ASSERT_EQ(d.raw(), 0u); + ASSERT_EQ(d.raw(), 0U); } static void sub(const Time::Duration &d1, const Time::Duration &d2) { const Time::Duration d = d1 - d2; - // std::cout << "D-D " << d1.raw() << " - " << d2.raw() << " = " << d.raw() << std::endl; + // std::cout << "D-D " << d1.raw() << " - " << d2.raw() << " = " << d.raw() << "\n"; Time::Duration x = d1; x -= d2; ASSERT_EQ(x, d) << "D-D INCONSISTENCY DETECTED"; @@ -136,7 +135,7 @@ static void sub(const Time::Duration &d1, const Time::Duration &d2) static void add(const Time &t1, const Time::Duration &d1) { const Time t = t1 + d1; - // std::cout << "T+D " << t1.raw() << " + " << d1.raw() << " = " << t.raw() << std::endl; + // std::cout << "T+D " << t1.raw() << " + " << d1.raw() << " = " << t.raw() << "\n"; Time x = t1; x += d1; ASSERT_EQ(x, t) << "T+D INCONSISTENCY DETECTED"; @@ -145,13 +144,13 @@ static void add(const Time &t1, const Time::Duration &d1) static void add(const Time::Duration &d1, const Time::Duration &d2) { const Time::Duration d = d1 + d2; - // std::cout << "D+D " << d1.raw() << " + " << d2.raw() << " = " << d.raw() << std::endl; + // std::cout << "D+D " << d1.raw() << " + " << d2.raw() << " = " << d.raw() << "\n"; Time::Duration x = d1; x += d2; ASSERT_EQ(x, d) << "D+D INCONSISTENCY DETECTED"; } -TEST(time, timeaddsub) +TEST(Time, Timeaddsub) { { const Time now = Time::now(); diff --git a/test/unittests/test_tun_builder.cpp b/test/unittests/test_tun_builder.cpp index 6b0a2564b..ad5d5df4a 100644 --- a/test/unittests/test_tun_builder.cpp +++ b/test/unittests/test_tun_builder.cpp @@ -3,7 +3,7 @@ #include <openvpn/tun/builder/capture.hpp> -TEST(tun_builder, to_string_zero) +TEST(TunBuilder, ToStringZero) { auto rb = openvpn::TunBuilderCapture::RouteBase(); diff --git a/test/unittests/test_typeindex.cpp b/test/unittests/test_typeindex.cpp index bdf871ea4..4964d89c4 100644 --- a/test/unittests/test_typeindex.cpp +++ b/test/unittests/test_typeindex.cpp @@ -17,7 +17,7 @@ namespace { struct Base : public RC<thread_unsafe_refcount> { public: - typedef RCPtr<Base> Ptr; + using Ptr = RCPtr<Base>; virtual std::string to_string() const = 0; @@ -51,11 +51,10 @@ class Wrapper : public Base { if (maybe_my_type->type() == static_type()) return static_cast<const Wrapper *>(maybe_my_type); - else - return nullptr; + return nullptr; } - virtual std::string to_string() const override + std::string to_string() const override { return "value=" + StringTempl::to_string(obj) + " obj_size=" + std::to_string(sizeof(obj)); } @@ -103,9 +102,9 @@ static Vec create_vec() } // namespace // simple test of self() -TEST(typeindex, test) +TEST(Typeindex, Test) { - typedef Wrapper<std::string> StringWrap; + using StringWrap = Wrapper<std::string>; const Vec vec = create_vec(); @@ -124,9 +123,9 @@ TEST(typeindex, test) #ifndef INSTRUMENTATION_SLOWDOWN // test performance of self() as alternative to dynamic_cast -TEST(typeindex, perf_test_fast) +TEST(Typeindex, PerfTestFast) { - typedef Wrapper<std::string> StringWrap; + using StringWrap = Wrapper<std::string>; const size_t N = 100000000; @@ -143,13 +142,13 @@ TEST(typeindex, perf_test_fast) i = 0; } OPENVPN_LOG("PERF " << n_strings << '/' << N); - ASSERT_EQ(n_strings, 28571428u); + ASSERT_EQ(n_strings, 28571428U); } // as a control, test performance of dynamic_cast -TEST(typeindex, perf_test_dynamic) +TEST(Typeindex, PerfTestDynamic) { - typedef Wrapper<std::string> StringWrap; + using StringWrap = Wrapper<std::string>; const size_t N = 100000000; @@ -166,7 +165,7 @@ TEST(typeindex, perf_test_dynamic) i = 0; } OPENVPN_LOG("PERF " << n_strings << '/' << N); - ASSERT_EQ(n_strings, 28571428u); + ASSERT_EQ(n_strings, 28571428U); } #endif diff --git a/test/unittests/test_userpass.cpp b/test/unittests/test_userpass.cpp index f71578df8..97d2625a9 100644 --- a/test/unittests/test_userpass.cpp +++ b/test/unittests/test_userpass.cpp @@ -23,8 +23,9 @@ const std::string user_tag( "<auth>\n" "username\n" "</auth>\n"); +const std::string user_file_fn(UNITTEST_SOURCE_DIR "/userpass/user.txt"); const std::string user_file( - "auth " UNITTEST_SOURCE_DIR "/userpass/user.txt\n"); + "auth " + user_file_fn + "\n"); const std::vector<std::string> user_only{ user_simple, user_tag, @@ -34,8 +35,10 @@ const std::string userpass_tag( "username\n" "password\n" "</auth>\n"); +const std::string userpass_file_fn( + UNITTEST_SOURCE_DIR "/userpass/userpass.txt"); const std::string userpass_file( - "auth " UNITTEST_SOURCE_DIR "/userpass/userpass.txt\n"); + "auth " + userpass_file_fn + "\n"); const std::vector<std::string> user_pass{ userpass_tag, userpass_file, @@ -94,7 +97,7 @@ const std::vector<unsigned int> flag_combos_nofile{ UserPass::OPT_REQUIRED | UserPass::USERNAME_REQUIRED | UserPass::PASSWORD_REQUIRED, }; -TEST(UserPass, missing) +TEST(UserPass, Missing) { for (auto flags : flag_combos_missing_okay) { @@ -112,7 +115,7 @@ TEST(UserPass, missing) UserPass::parse(cfg, optname, flags, user, pass); ASSERT_TRUE(user.empty()) << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags, &userpass); ASSERT_FALSE(ret) << "flags: " << flags; ASSERT_EQ(userpass.size(), 0) << "flags: " << flags; } @@ -146,7 +149,7 @@ TEST(UserPass, missing) } } -TEST(UserPass, noargs) +TEST(UserPass, NoArgs) { for (auto flags : flag_combos_noargs_okay) { @@ -164,7 +167,7 @@ TEST(UserPass, noargs) UserPass::parse(cfg, optname, flags, user, pass); ASSERT_TRUE(user.empty()) << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags, &userpass); ASSERT_TRUE(ret) << "flags: " << flags; ASSERT_EQ(userpass.size(), 0) << "flags: " << flags; } @@ -198,7 +201,7 @@ TEST(UserPass, noargs) } } -TEST(UserPass, user_only) +TEST(UserPass, UserOnly) { for (auto flags : flag_combos_pw_not_required) { @@ -218,7 +221,7 @@ TEST(UserPass, user_only) UserPass::parse(cfg, optname, flags, user, pass); ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "config: " << config_text << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags, &userpass); ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags; ASSERT_EQ(userpass.size(), 1) << "config: " << config_text << "flags: " << flags; ASSERT_EQ(userpass[0], "username") << "config: " << config_text << "flags: " << flags; @@ -232,17 +235,17 @@ TEST(UserPass, user_only) cfg.parse_from_config(userpass_file, nullptr); cfg.update_map(); UserPass::parse(cfg, optname, flags, user, pass); - ASSERT_EQ(user, UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags; + ASSERT_EQ(user, userpass_file_fn) << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; user = "otheruser"; pass = "otherpass"; UserPass::parse(cfg, optname, flags, user, pass); - ASSERT_EQ(user, UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags; + ASSERT_EQ(user, userpass_file_fn) << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags, &userpass); ASSERT_TRUE(ret) << "flags: " << flags; ASSERT_EQ(userpass.size(), 1) << "flags: " << flags; - ASSERT_EQ(userpass[0], UNITTEST_SOURCE_DIR "/userpass/userpass.txt") << "flags: " << flags; + ASSERT_EQ(userpass[0], userpass_file_fn) << "flags: " << flags; } } for (auto flags : flag_combos_pw_required) @@ -265,14 +268,14 @@ TEST(UserPass, user_only) UserPass::parse(cfg, optname, flags, user, pass), UserPass::creds_error) << "config: " << config_text << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags, &userpass); // FIXME? ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags; } } } -TEST(UserPass, user_pass) +TEST(UserPass, UserPass) { for (auto flags : flag_combos_nofile) { @@ -293,7 +296,7 @@ TEST(UserPass, user_pass) UserPass::parse(cfg, optname, flags_try_file, user, pass); ASSERT_EQ(user, "username") << "config: " << config_text << "flags: " << flags; ASSERT_EQ(pass, "password") << "config: " << config_text << "flags: " << flags; - bool ret = UserPass::parse(cfg, optname, flags_try_file, &userpass); + const bool ret = UserPass::parse(cfg, optname, flags_try_file, &userpass); ASSERT_TRUE(ret) << "config: " << config_text << "flags: " << flags; ASSERT_EQ(userpass.size(), 2) << "config: " << config_text << "flags: " << flags; ASSERT_EQ(userpass[0], "username") << "config: " << config_text << "flags: " << flags; @@ -302,18 +305,18 @@ TEST(UserPass, user_pass) } } -TEST(UserPass, parse_file_user_only) +TEST(UserPass, ParseFileUserOnly) { for (auto flags : flag_combos_pw_not_required) { std::string user; std::string pass; - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass); + UserPass::parse_file(user_file_fn, flags, user, pass); ASSERT_EQ(user, "username") << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; user = "otheruser"; pass = "otherpass"; - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass); + UserPass::parse_file(user_file_fn, flags, user, pass); ASSERT_EQ(user, "username") << "flags: " << flags; ASSERT_TRUE(pass.empty()) << "flags: " << flags; } @@ -324,37 +327,37 @@ TEST(UserPass, parse_file_user_only) std::string user; std::string pass; ASSERT_THROW( - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass), + UserPass::parse_file(user_file_fn, flags, user, pass), UserPass::creds_error) << "config: " << config_text << "flags: " << flags; user = "otheruser"; pass = "otherpass"; ASSERT_THROW( - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/user.txt", flags, user, pass), + UserPass::parse_file(user_file_fn, flags, user, pass), UserPass::creds_error) << "config: " << config_text << "flags: " << flags; } } } -TEST(UserPass, parse_file_user_pass) +TEST(UserPass, ParseFileUserPass) { for (auto flags : flag_combos_nofile) { std::string user; std::string pass; - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/userpass.txt", flags, user, pass); + UserPass::parse_file(userpass_file_fn, flags, user, pass); ASSERT_EQ(user, "username") << "flags: " << flags; ASSERT_EQ(pass, "password") << "flags: " << flags; user = "otheruser"; pass = "otherpass"; - UserPass::parse_file(UNITTEST_SOURCE_DIR "/userpass/userpass.txt", flags, user, pass); + UserPass::parse_file(userpass_file_fn, flags, user, pass); ASSERT_EQ(user, "username") << "flags: " << flags; ASSERT_EQ(pass, "password") << "flags: " << flags; } } -TEST(UserPass, parse_file_overflow) +TEST(UserPass, ParseFileOverflow) { for (auto flags : flag_combos_nofile) { @@ -369,7 +372,7 @@ TEST(UserPass, parse_file_overflow) ASSERT_ANY_THROW(UserPass::parse_file(filename, flags, user, pass)) << "file: " << filename << "flags: " << flags; auto flags_try_file = flags | UserPass::TRY_FILE; - std::string config_text = std::string("auth ") + filename; + const std::string config_text = std::string("auth ") + filename; std::vector<std::string> userpass; OptionList cfg; cfg.parse_from_config(config_text, nullptr); diff --git a/test/unittests/test_validatecreds.cpp b/test/unittests/test_validatecreds.cpp index f2a96b243..e466722ef 100644 --- a/test/unittests/test_validatecreds.cpp +++ b/test/unittests/test_validatecreds.cpp @@ -21,7 +21,7 @@ void validate(const ValidateCreds::Type type, const bool expected_result, const EXPECT_EQ(actual_result, expected_result); } -TEST(misc, creds1) +TEST(Misc, Creds1) { validate(ValidateCreds::USERNAME, true, "foobar", true); validate(ValidateCreds::PASSWORD, true, "xxx\nyyy", false); @@ -39,7 +39,7 @@ TEST(misc, creds1) validate(ValidateCreds::USERNAME, false, "\xFF\xFF\xFF\xFF", true); } -void validate_creds(std::string username, std::string password, const bool expected_result, const bool strict) +void validate_creds(std::string username, const std::string &password, const bool expected_result, const bool strict) { if (verbose) OPENVPN_LOG("VALIDATE username='" << username << "' password='" << password << "' expected res=" << expected_result); @@ -49,7 +49,7 @@ void validate_creds(std::string username, std::string password, const bool expec EXPECT_EQ(actual_result, expected_result); } -TEST(misc, creds2) +TEST(Misc, Creds2) { validate_creds("foo", "bar", true, true); validate_creds("", "bar", false, true); @@ -70,7 +70,7 @@ void validate_utf8(const std::string &str, const size_t max_len_flags, const boo EXPECT_EQ(actual_result, expected_result); } -TEST(misc, creds3) +TEST(Misc, Creds3) { validate_utf8("", 0, true); validate_utf8("test", 0, true); @@ -82,4 +82,4 @@ TEST(misc, creds3) validate_utf8("\xFF\xFF\xFF\xFF", 0, false); validate_utf8("hello there", 0, true); validate_utf8("hello there", Unicode::UTF8_NO_SPACE, false); -} \ No newline at end of file +} diff --git a/test/unittests/test_verify_x509_name.cpp b/test/unittests/test_verify_x509_name.cpp index b79a4c482..158f2909d 100644 --- a/test/unittests/test_verify_x509_name.cpp +++ b/test/unittests/test_verify_x509_name.cpp @@ -37,14 +37,14 @@ OptionList parse_testcfg(std::string &config) return opts; } -TEST(VerifyX509Name, config_missing_args) +TEST(VerifyX509Name, ConfigMissingArgs) { // Missing both needed arguments std::string config = "verify-x509-name"; EXPECT_THROW(VerifyX509Name err_no_args(parse_testcfg(config)), option_error); } -TEST(VerifyX509Name, config_incorrect_type) +TEST(VerifyX509Name, ConfigIncorrectType) { // Incorrect type std::string config = "verify-x509-name localhost nonsense-arg"; @@ -52,49 +52,49 @@ TEST(VerifyX509Name, config_incorrect_type) option_error); } -TEST(VerifyX509Name, config_correct_default_type) +TEST(VerifyX509Name, ConfigCorrectDefaultType) { // Missing type argument - defaults to complete subject DN std::string config = "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " "emailAddress=me@myhost.mydomain\""; - VerifyX509Name ok_default_subj(parse_testcfg(config)); + const VerifyX509Name ok_default_subj(parse_testcfg(config)); } -TEST(VerifyX509Name, config_correct_subject) +TEST(VerifyX509Name, ConfigCorrectSubject) { // Correct - type: subject std::string config = "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " "emailAddress=me@myhost.mydomain\" subject"; - VerifyX509Name ok_subj(parse_testcfg(config)); + const VerifyX509Name ok_subj(parse_testcfg(config)); } -TEST(VerifyX509Name, config_correct_name) +TEST(VerifyX509Name, ConfigCorrectName) { // Correct - type: name std::string config = "verify-x509-name localhost name"; - VerifyX509Name ok_name(parse_testcfg(config)); + const VerifyX509Name ok_name(parse_testcfg(config)); } -TEST(VerifyX509Name, config_squote) +TEST(VerifyX509Name, ConfigSquote) { // ensure that single quote is not treated as name part std::string config = "verify-x509-name 'server.example.org'"; - VerifyX509Name verify(parse_testcfg(config)); + const VerifyX509Name verify(parse_testcfg(config)); ASSERT_TRUE(verify.verify("server.example.org")); } -TEST(VerifyX509Name, config_correct_name_prefix) +TEST(VerifyX509Name, ConfigCorrectNamePrefix) { // Correct - type: name-prefix std::string config = "verify-x509-name Server- name-prefix"; - VerifyX509Name ok_name_prefix(parse_testcfg(config)); + const VerifyX509Name ok_name_prefix(parse_testcfg(config)); } -TEST(VerifyX509Name, test_subject) +TEST(VerifyX509Name, TestSubject) { std::string config = "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " "emailAddress=me@myhost.mydomain\""; - VerifyX509Name verify_def(parse_testcfg(config)); + const VerifyX509Name verify_def(parse_testcfg(config)); ASSERT_TRUE(verify_def.verify( "C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " @@ -108,7 +108,7 @@ TEST(VerifyX509Name, test_subject) // just with the 'subject' type defined explicitly config = "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " "emailAddress=me@myhost.mydomain\" subject"; - VerifyX509Name verify_subj(parse_testcfg(config)); + const VerifyX509Name verify_subj(parse_testcfg(config)); ASSERT_TRUE(verify_subj.verify( "C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " @@ -119,20 +119,20 @@ TEST(VerifyX509Name, test_subject) ASSERT_FALSE(verify_subj.verify("server-1.example.org")); } -TEST(VerifyX509Name, test_name) +TEST(VerifyX509Name, TestName) { std::string config = "verify-x509-name server-1.example.org name"; - VerifyX509Name verify(parse_testcfg(config)); + const VerifyX509Name verify(parse_testcfg(config)); ASSERT_TRUE(verify.verify("server-1.example.org")); ASSERT_FALSE(verify.verify("server-2.example.org")); ASSERT_FALSE(verify.verify("server")); } -TEST(VerifyX509Name, test_name_prefix) +TEST(VerifyX509Name, TestNamePrefix) { std::string config = "verify-x509-name server name-prefix"; - VerifyX509Name verify(parse_testcfg(config)); + const VerifyX509Name verify(parse_testcfg(config)); ASSERT_TRUE(verify.verify("server-1.example.org")); ASSERT_TRUE(verify.verify("server-2.sub.example.net")); diff --git a/test/unittests/test_weak.cpp b/test/unittests/test_weak.cpp index b950bb04d..baeb0544d 100644 --- a/test/unittests/test_weak.cpp +++ b/test/unittests/test_weak.cpp @@ -62,8 +62,8 @@ template <typename PARENT> class RefType : public RCWeak<thread_unsafe_refcount> { public: - typedef RCPtr<RefType> Ptr; - typedef RCWeakPtr<RefType> WPtr; + using Ptr = RCPtr<RefType>; + using WPtr = RCWeakPtr<RefType>; RefType(std::string name, typename PARENT::Ptr parent) @@ -82,8 +82,7 @@ class RefType : public RCWeak<thread_unsafe_refcount> auto p = parent(); if (p) return "I am " + name() + " whose parent is " + p->name(); - else - return "I am " + name() + ", an orphan"; + return "I am " + name() + ", an orphan"; } std::string name() const @@ -100,9 +99,9 @@ class RefType : public RCWeak<thread_unsafe_refcount> class Object : public RCWeak<thread_unsafe_refcount> { public: - typedef RCPtr<Object> Ptr; - typedef RCWeakPtr<Object> WPtr; - typedef RefType<Object> Ref; + using Ptr = RCPtr<Object>; + using WPtr = RCWeakPtr<Object>; + using Ref = RefType<Object>; std::string name() const { @@ -126,7 +125,7 @@ class Object : public RCWeak<thread_unsafe_refcount> StaticCounter sc_; }; -typedef Object::Ref Ref; +using Ref = Object::Ref; } // namespace A // Strategy B -- Ref declared inside Object, so Ref can make use @@ -136,14 +135,14 @@ namespace B { class Object : public RCWeak<thread_unsafe_refcount> { public: - typedef RCPtr<Object> Ptr; - typedef RCWeakPtr<Object> WPtr; + using Ptr = RCPtr<Object>; + using WPtr = RCWeakPtr<Object>; class Ref : public RCWeak<thread_unsafe_refcount> { public: - typedef RCPtr<Ref> Ptr; - typedef RCWeakPtr<Ref> WPtr; + using Ptr = RCPtr<Ref>; + using WPtr = RCWeakPtr<Ref>; Ref(std::string name, typename Object::Ptr parent) @@ -162,8 +161,7 @@ class Object : public RCWeak<thread_unsafe_refcount> auto p = parent(); if (p) return "I am " + name() + " whose parent is " + p->name(); - else - return "I am " + name() + ", an orphan"; + return "I am " + name() + ", an orphan"; } std::string name() const @@ -199,7 +197,7 @@ class Object : public RCWeak<thread_unsafe_refcount> StaticCounter sc_; }; -typedef Object::Ref Ref; +using Ref = Object::Ref; } // namespace B /// @endcond @@ -209,8 +207,6 @@ void test() { ASSERT_EQ(StaticCounter::count(), 0); - std::string result; - // create new Ref objects that point back to their parent (Object) typename Object::Ptr obj(new Object); obj->vec.emplace_back(new Ref("One", obj)); @@ -218,7 +214,7 @@ void test() obj->vec.emplace_back(new Ref("Three", obj)); // verify obj - ASSERT_EQ(obj->vec.size(), 3u); + ASSERT_EQ(obj->vec.size(), 3U); ASSERT_EQ(obj->vec.at(0)->to_string(), "I am One whose parent is Regular Joe"); ASSERT_EQ(obj->vec.at(1)->to_string(), "I am Two whose parent is Regular Joe"); ASSERT_EQ(obj->vec.at(2)->to_string(), "I am Three whose parent is Regular Joe"); @@ -235,13 +231,13 @@ void test() } // strategy A -TEST(misc, weak_a) +TEST(Misc, WeakA) { test<A::Object, A::Ref>(); } // strategy B -TEST(misc, weak_b) +TEST(Misc, WeakB) { test<B::Object, B::Ref>(); } diff --git a/test/unittests/test_wstring.cpp b/test/unittests/test_wstring.cpp index ee201ad76..5a81ef4fe 100644 --- a/test/unittests/test_wstring.cpp +++ b/test/unittests/test_wstring.cpp @@ -66,14 +66,6 @@ TEST_F(WStringTest, ToUtf8) EXPECT_TRUE(utf8_shigeru == shigeru); } -TEST_F(WStringTest, ToCArray) -{ - auto array_ptr = wstring::to_wchar_t(wide_jojo); - EXPECT_TRUE(::wcslen(array_ptr.get()) == wide_jojo.size()); - EXPECT_TRUE(::wcscmp(array_ptr.get(), wide_jojo.c_str()) == 0); - EXPECT_TRUE(std::wstring(array_ptr.get()) == wide_jojo); -} - TEST_F(WStringTest, MultiSzFromVector) { std::vector<std::string> names{jojo, lev, shigeru}; @@ -85,5 +77,4 @@ TEST_F(WStringTest, MultiSzFromVector) EXPECT_TRUE(std::memcmp(jojo_ptr, wide_jojo.c_str(), raw_jojo.size()) == 0); EXPECT_TRUE(std::memcmp(lev_ptr, wide_lev.c_str(), raw_lev.size()) == 0); EXPECT_TRUE(std::memcmp(shigeru_ptr, wide_shigeru.c_str(), raw_shigeru.size()) == 0); - EXPECT_EQ(multi_names[multi_names.size()], L'\0'); } diff --git a/vars/o3 b/vars/o3 deleted file mode 100644 index 54c9fb605..000000000 --- a/vars/o3 +++ /dev/null @@ -1 +0,0 @@ -export O3="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" diff --git a/vars/setlibpath b/vars/setlibpath deleted file mode 100644 index e8245c0fa..000000000 --- a/vars/setlibpath +++ /dev/null @@ -1 +0,0 @@ -export LD_LIBRARY_PATH=".:$DEP_DIR/so" diff --git a/vars/setpath b/vars/setpath deleted file mode 100644 index a5292f78c..000000000 --- a/vars/setpath +++ /dev/null @@ -1 +0,0 @@ -export PATH="$O3/core/scripts:$PATH" diff --git a/vars/vars-arm-cross b/vars/vars-arm-cross deleted file mode 100644 index d10fe28ae..000000000 --- a/vars/vars-arm-cross +++ /dev/null @@ -1,5 +0,0 @@ -export PLATFORM=linux-arm -export GPP_CMD=arm-linux-gnueabi-g++-4.6 -export STRIP_CMD=arm-linux-gnueabi-strip -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" diff --git a/vars/vars-linux b/vars/vars-linux deleted file mode 100644 index de073e104..000000000 --- a/vars/vars-linux +++ /dev/null @@ -1,21 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=0 -export OTHER_COMPILER_FLAGS="-Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" -export GPP_CMD=g++ -export GCC_CMD=gcc -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib -# For Ubuntu 18 -if g++ --version |grep 7.5.0 > /dev/null ; then - if [ -e /usr/bin/g++-8 ]; then - export GPP_CMD=g++-8 - export GCC_CMD=gcc-8 - export AR_CMD="gcc-ar-8 rc" - export RANLIB_CMD=gcc-ranlib-8 - fi -fi diff --git a/vars/vars-linux-clang b/vars/vars-linux-clang deleted file mode 100644 index 96eb8d50b..000000000 --- a/vars/vars-linux-clang +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux-clang -export PLATFORM=linux -export DEBUG_BUILD=0 -export OTHER_COMPILER_FLAGS="-Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib diff --git a/vars/vars-linux-clang-dbg b/vars/vars-linux-clang-dbg deleted file mode 100644 index 935abb1f6..000000000 --- a/vars/vars-linux-clang-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux-clang -export PLATFORM=linux -export DEBUG_BUILD=1 -export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17 -stdlib=libc++" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib diff --git a/vars/vars-linux-dbg b/vars/vars-linux-dbg deleted file mode 100644 index 5f404a375..000000000 --- a/vars/vars-linux-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=1 -export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="-fPIC" -export GPP_CMD=g++ -export GCC_CMD=gcc -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib diff --git a/vars/vars-linux-libcpp b/vars/vars-linux-libcpp deleted file mode 100644 index cb567f58a..000000000 --- a/vars/vars-linux-libcpp +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=0 -export OTHER_COMPILER_FLAGS="-Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib diff --git a/vars/vars-linux-libcpp-dbg b/vars/vars-linux-libcpp-dbg deleted file mode 100644 index 9a1b29c4a..000000000 --- a/vars/vars-linux-libcpp-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=1 -export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++17 -stdlib=libc++" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD="gcc-ar rc" -export RANLIB_CMD=gcc-ranlib diff --git a/vars/vars-reset b/vars/vars-reset deleted file mode 100644 index e82f17920..000000000 --- a/vars/vars-reset +++ /dev/null @@ -1,21 +0,0 @@ -unset PLATFORM -unset PLATFORM_FLAGS -unset MIN_DEPLOY_TARGET -unset OTHER_COMPILER_FLAGS -unset IOS_SDK -unset BOOST_DIR -unset BOOST_STAGE -unset OPENSSL_DIR -unset SNAPPY_DIR -unset LZ4_DIR -unset JAVA_DIR -unset GPP_CMD -unset GCC_CMD -unset STRIP_CMD -unset LD_LIBRARY_PATH -unset APPLE_FAMILY -unset LIB_OPT_LEVEL -unset LIB_FPIC -unset DEBUG_BUILD -unset LINK_MODE -unset CXX_COMPILER_FLAGS diff --git a/vars/vars-win b/vars/vars-win deleted file mode 100644 index 28e0d9549..000000000 --- a/vars/vars-win +++ /dev/null @@ -1 +0,0 @@ -alias build="python ~/ovpn3/win/build.py" diff --git a/vcpkg.json b/vcpkg.json index 634eeb925..67563f205 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,9 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "openvpn3", - "version-string": "3.8", + "version-string": "3.11", "dependencies": [ "asio", + "fmt", "jsoncpp", "lz4", "openssl",