Repository: OpenVPN/openvpn Branch: master Commit: a04a3cedd41a Files: 522 Total size: 5.4 MB Directory structure: gitextract_yqj5celu/ ├── .clang-format ├── .git-blame-ignore-revs ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── bug_report.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ ├── build.yaml │ ├── coverity-scan.yml │ └── doxygen.yml ├── .gitignore ├── .mailmap ├── .pre-commit-config.yaml ├── .svncommitters ├── AUTHORS ├── CMakeLists.txt ├── CMakePresets.json ├── CONTRIBUTING.rst ├── COPYING ├── COPYRIGHT.GPL ├── ChangeLog ├── Changes.rst ├── INSTALL ├── Makefile.am ├── NEWS ├── PORTS ├── README ├── README.awslc ├── README.cmake.md ├── README.dco.md ├── README.ec ├── README.mbedtls ├── README.wolfssl ├── compat.m4 ├── config.h.cmake.in ├── configure.ac ├── contrib/ │ ├── OCSP_check/ │ │ └── OCSP_check.sh │ ├── README │ ├── cmake/ │ │ ├── git-version.py │ │ └── parse-version.m4.py │ ├── extract-crl/ │ │ └── extractcrl.py │ ├── multilevel-init.patch │ ├── openvpn-fwmarkroute-1.00/ │ │ ├── README │ │ ├── fwmarkroute.down │ │ └── fwmarkroute.up │ ├── vcpkg-manifests/ │ │ ├── mingw/ │ │ │ └── vcpkg.json │ │ └── windows/ │ │ └── vcpkg.json │ ├── vcpkg-ports/ │ │ └── pkcs11-helper/ │ │ ├── config-w32-vc.h.in-indicate-OpenSSL.patch │ │ ├── nmake-compatibility-with-vcpkg-nmake.patch │ │ ├── pkcs11-helper-001-RFC7512.patch │ │ ├── portfile.cmake │ │ └── vcpkg.json │ └── vcpkg-triplets/ │ ├── arm64-windows-ovpn.cmake │ ├── x64-mingw-ovpn.cmake │ ├── x64-windows-ovpn.cmake │ ├── x86-mingw-ovpn.cmake │ └── x86-windows-ovpn.cmake ├── debug/ │ ├── doval │ ├── dovalns │ └── valgrind-suppress ├── dev-tools/ │ ├── gen-release-tarballs.sh │ ├── gerrit-send-mail.py │ ├── git-pre-commit-format.sh │ └── update-copyright.sh ├── distro/ │ ├── Makefile.am │ ├── dns-scripts/ │ │ ├── Makefile.am │ │ ├── haikuos_file-dns-updown.sh │ │ ├── macos-dns-updown.sh │ │ ├── openresolv-dns-updown.sh │ │ ├── resolvconf_file-dns-updown.sh │ │ └── systemd-dns-updown.sh │ └── systemd/ │ ├── Makefile.am │ ├── README.systemd │ ├── openvpn-client@.service.in │ ├── openvpn-server@.service.in │ └── tmpfiles-openvpn.conf ├── doc/ │ ├── CMakeLists.txt │ ├── Makefile.am │ ├── README.man │ ├── README.plugins │ ├── android.txt │ ├── doxygen/ │ │ ├── Makefile.am │ │ ├── doc_compression.h │ │ ├── doc_control_processor.h │ │ ├── doc_control_tls.h │ │ ├── doc_data_control.h │ │ ├── doc_data_crypto.h │ │ ├── doc_eventloop.h │ │ ├── doc_external_multiplexer.h │ │ ├── doc_fragmentation.h │ │ ├── doc_internal_multiplexer.h │ │ ├── doc_key_generation.h │ │ ├── doc_mainpage.h │ │ ├── doc_memory_management.h │ │ ├── doc_protocol_overview.h │ │ ├── doc_reliable.h │ │ ├── doc_tunnel_state.h │ │ └── openvpn.doxyfile.in │ ├── gui-notes.txt │ ├── interactive-service-notes.rst │ ├── keying-material-exporter.txt │ ├── man-sections/ │ │ ├── advanced-options.rst │ │ ├── cipher-negotiation.rst │ │ ├── client-options.rst │ │ ├── connection-profiles.rst │ │ ├── encryption-options.rst │ │ ├── example-fingerprint.rst │ │ ├── examples.rst │ │ ├── generic-options.rst │ │ ├── inline-files.rst │ │ ├── link-options.rst │ │ ├── log-options.rst │ │ ├── management-options.rst │ │ ├── network-config.rst │ │ ├── pkcs11-options.rst │ │ ├── plugin-options.rst │ │ ├── protocol-options.rst │ │ ├── proxy-options.rst │ │ ├── renegotiation.rst │ │ ├── script-options.rst │ │ ├── server-options.rst │ │ ├── signals.rst │ │ ├── tls-options.rst │ │ ├── unsupported-options.rst │ │ ├── virtual-routing-and-forwarding.rst │ │ ├── vpn-network-options.rst │ │ └── windows-options.rst │ ├── management-notes.txt │ ├── openvpn-examples.5.rst │ ├── openvpn.8.rst │ ├── t_server_null.rst │ ├── tests/ │ │ └── authentication-plugins.md │ └── tls-crypt-v2.txt ├── forked-test-driver ├── include/ │ ├── Makefile.am │ ├── openvpn-msg.h │ └── openvpn-plugin.h.in ├── ltrc.inc ├── m4/ │ ├── .keep │ ├── ax_socklen_t.m4 │ └── pkg.m4 ├── renovate.json ├── sample/ │ ├── Makefile.am │ ├── sample-config-files/ │ │ ├── README │ │ ├── client.conf │ │ ├── firewall.sh │ │ ├── loopback-client │ │ ├── loopback-server │ │ ├── openvpn-shutdown.sh │ │ ├── openvpn-startup.sh │ │ └── server.conf │ ├── sample-keys/ │ │ ├── README │ │ ├── ca.crt │ │ ├── ca.key │ │ ├── client-ec.crt │ │ ├── client-ec.key │ │ ├── client-pass.key │ │ ├── client.crt │ │ ├── client.key │ │ ├── client.p12 │ │ ├── ffdhe2048.pem │ │ ├── gen-sample-keys.sh │ │ ├── openssl.cnf │ │ ├── server-ec.crt │ │ ├── server-ec.key │ │ ├── server.crt │ │ ├── server.key │ │ └── ta.key │ ├── sample-plugins/ │ │ ├── Makefile.am │ │ ├── Makefile.plugins │ │ ├── README │ │ ├── client-connect/ │ │ │ ├── README │ │ │ └── sample-client-connect.c │ │ ├── defer/ │ │ │ ├── multi-auth.c │ │ │ └── winbuild │ │ ├── keying-material-exporter-demo/ │ │ │ ├── README │ │ │ ├── client.ovpn │ │ │ ├── http-client.py │ │ │ ├── http-server.py │ │ │ ├── keyingmaterialexporter.c │ │ │ └── server.ovpn │ │ ├── log/ │ │ │ ├── log.c │ │ │ ├── log_v3.c │ │ │ └── winbuild │ │ └── simple/ │ │ ├── base64.c │ │ ├── simple.c │ │ ├── simple.def │ │ └── winbuild │ └── sample-scripts/ │ ├── auth-pam.pl │ ├── bridge-start │ ├── bridge-stop │ ├── totpauth.py │ ├── ucn.pl │ └── verify-cn ├── src/ │ ├── Makefile.am │ ├── compat/ │ │ ├── Makefile.am │ │ ├── compat-basename.c │ │ ├── compat-daemon.c │ │ ├── compat-dirname.c │ │ ├── compat-gettimeofday.c │ │ ├── compat-strsep.c │ │ └── compat.h │ ├── openvpn/ │ │ ├── Makefile.am │ │ ├── argv.c │ │ ├── argv.h │ │ ├── auth_token.c │ │ ├── auth_token.h │ │ ├── base64.c │ │ ├── base64.h │ │ ├── basic.h │ │ ├── buffer.c │ │ ├── buffer.h │ │ ├── circ_list.h │ │ ├── clinat.c │ │ ├── clinat.h │ │ ├── common.h │ │ ├── comp-lz4.c │ │ ├── comp-lz4.h │ │ ├── comp.c │ │ ├── comp.h │ │ ├── compstub.c │ │ ├── console.c │ │ ├── console.h │ │ ├── console_builtin.c │ │ ├── console_systemd.c │ │ ├── crypto.c │ │ ├── crypto.h │ │ ├── crypto_backend.h │ │ ├── crypto_epoch.c │ │ ├── crypto_epoch.h │ │ ├── crypto_mbedtls.c │ │ ├── crypto_mbedtls.h │ │ ├── crypto_mbedtls_legacy.c │ │ ├── crypto_mbedtls_legacy.h │ │ ├── crypto_openssl.c │ │ ├── crypto_openssl.h │ │ ├── cryptoapi.c │ │ ├── cryptoapi.h │ │ ├── dco.c │ │ ├── dco.h │ │ ├── dco_freebsd.c │ │ ├── dco_freebsd.h │ │ ├── dco_internal.h │ │ ├── dco_linux.c │ │ ├── dco_linux.h │ │ ├── dco_win.c │ │ ├── dco_win.h │ │ ├── dhcp.c │ │ ├── dhcp.h │ │ ├── dns.c │ │ ├── dns.h │ │ ├── domain_helper.h │ │ ├── env_set.c │ │ ├── env_set.h │ │ ├── errlevel.h │ │ ├── error.c │ │ ├── error.h │ │ ├── event.c │ │ ├── event.h │ │ ├── fdmisc.c │ │ ├── fdmisc.h │ │ ├── forward.c │ │ ├── forward.h │ │ ├── fragment.c │ │ ├── fragment.h │ │ ├── gremlin.c │ │ ├── gremlin.h │ │ ├── helper.c │ │ ├── helper.h │ │ ├── httpdigest.c │ │ ├── httpdigest.h │ │ ├── init.c │ │ ├── init.h │ │ ├── integer.h │ │ ├── interval.c │ │ ├── interval.h │ │ ├── list.c │ │ ├── list.h │ │ ├── lladdr.c │ │ ├── lladdr.h │ │ ├── lzo.c │ │ ├── lzo.h │ │ ├── manage.c │ │ ├── manage.h │ │ ├── mbedtls_compat.h │ │ ├── mbuf.c │ │ ├── mbuf.h │ │ ├── memdbg.h │ │ ├── misc.c │ │ ├── misc.h │ │ ├── mroute.c │ │ ├── mroute.h │ │ ├── mss.c │ │ ├── mss.h │ │ ├── mtcp.c │ │ ├── mtcp.h │ │ ├── mtu.c │ │ ├── mtu.h │ │ ├── mudp.c │ │ ├── mudp.h │ │ ├── multi.c │ │ ├── multi.h │ │ ├── multi_io.c │ │ ├── multi_io.h │ │ ├── networking.h │ │ ├── networking_freebsd.c │ │ ├── networking_iproute2.c │ │ ├── networking_iproute2.h │ │ ├── networking_sitnl.c │ │ ├── networking_sitnl.h │ │ ├── occ.c │ │ ├── occ.h │ │ ├── openssl_compat.h │ │ ├── openvpn.c │ │ ├── openvpn.h │ │ ├── openvpn.manifest │ │ ├── openvpn_win32_resources.rc │ │ ├── options.c │ │ ├── options.h │ │ ├── options_parse.c │ │ ├── options_util.c │ │ ├── options_util.h │ │ ├── otime.c │ │ ├── otime.h │ │ ├── ovpn_dco_freebsd.h │ │ ├── ovpn_dco_linux.h │ │ ├── ovpn_dco_win.h │ │ ├── packet_id.c │ │ ├── packet_id.h │ │ ├── ping.c │ │ ├── ping.h │ │ ├── pkcs11.c │ │ ├── pkcs11.h │ │ ├── pkcs11_backend.h │ │ ├── pkcs11_mbedtls.c │ │ ├── pkcs11_openssl.c │ │ ├── platform.c │ │ ├── platform.h │ │ ├── plugin.c │ │ ├── plugin.h │ │ ├── pool.c │ │ ├── pool.h │ │ ├── proto.c │ │ ├── proto.h │ │ ├── proxy.c │ │ ├── proxy.h │ │ ├── ps.c │ │ ├── ps.h │ │ ├── push.c │ │ ├── push.h │ │ ├── push_util.c │ │ ├── pushlist.h │ │ ├── reflect_filter.c │ │ ├── reflect_filter.h │ │ ├── reliable.c │ │ ├── reliable.h │ │ ├── ring_buffer.h │ │ ├── route.c │ │ ├── route.h │ │ ├── run_command.c │ │ ├── run_command.h │ │ ├── schedule.c │ │ ├── schedule.h │ │ ├── session_id.c │ │ ├── session_id.h │ │ ├── shaper.c │ │ ├── shaper.h │ │ ├── sig.c │ │ ├── sig.h │ │ ├── siphash.h │ │ ├── siphash_reference.c │ │ ├── socket.c │ │ ├── socket.h │ │ ├── socket_util.c │ │ ├── socket_util.h │ │ ├── socks.c │ │ ├── socks.h │ │ ├── ssl.c │ │ ├── ssl.h │ │ ├── ssl_backend.h │ │ ├── ssl_common.h │ │ ├── ssl_mbedtls.c │ │ ├── ssl_mbedtls.h │ │ ├── ssl_ncp.c │ │ ├── ssl_ncp.h │ │ ├── ssl_openssl.c │ │ ├── ssl_openssl.h │ │ ├── ssl_pkt.c │ │ ├── ssl_pkt.h │ │ ├── ssl_util.c │ │ ├── ssl_util.h │ │ ├── ssl_verify.c │ │ ├── ssl_verify.h │ │ ├── ssl_verify_backend.h │ │ ├── ssl_verify_mbedtls.c │ │ ├── ssl_verify_mbedtls.h │ │ ├── ssl_verify_openssl.c │ │ ├── ssl_verify_openssl.h │ │ ├── status.c │ │ ├── status.h │ │ ├── syshead.h │ │ ├── tls_crypt.c │ │ ├── tls_crypt.h │ │ ├── tun.c │ │ ├── tun.h │ │ ├── tun_afunix.c │ │ ├── tun_afunix.h │ │ ├── vlan.c │ │ ├── vlan.h │ │ ├── wfp_block.c │ │ ├── wfp_block.h │ │ ├── win32-util.c │ │ ├── win32-util.h │ │ ├── win32.c │ │ ├── win32.h │ │ ├── xkey_common.h │ │ ├── xkey_helper.c │ │ └── xkey_provider.c │ ├── openvpnmsica/ │ │ ├── CMakeLists.txt │ │ ├── Makefile.am │ │ ├── dllmain.c │ │ ├── msica_arg.c │ │ ├── msica_arg.h │ │ ├── msiex.c │ │ ├── msiex.h │ │ ├── openvpnmsica.c │ │ ├── openvpnmsica.h │ │ └── openvpnmsica_resources.rc │ ├── openvpnserv/ │ │ ├── CMakeLists.txt │ │ ├── Makefile.am │ │ ├── common.c │ │ ├── eventmsg.mc │ │ ├── interactive.c │ │ ├── openvpnserv_resources.rc │ │ ├── service.c │ │ ├── service.h │ │ ├── validate.c │ │ └── validate.h │ ├── plugins/ │ │ ├── Makefile.am │ │ ├── auth-pam/ │ │ │ ├── Makefile.am │ │ │ ├── README.auth-pam │ │ │ ├── auth-pam.c │ │ │ ├── auth-pam.exports │ │ │ ├── pamdl.c │ │ │ ├── pamdl.h │ │ │ ├── utils.c │ │ │ └── utils.h │ │ └── down-root/ │ │ ├── Makefile.am │ │ ├── README.down-root │ │ ├── down-root.c │ │ └── down-root.exports │ └── tapctl/ │ ├── CMakeLists.txt │ ├── Makefile.am │ ├── basic.h │ ├── error.c │ ├── error.h │ ├── main.c │ ├── tap.c │ ├── tap.h │ └── tapctl_resources.rc ├── tests/ │ ├── Makefile.am │ ├── lwip_client_up.sh │ ├── ntlm_support.c │ ├── null_client_up.sh │ ├── t_client.rc-sample │ ├── t_client.sh.in │ ├── t_cltsrv-down.sh │ ├── t_cltsrv.sh │ ├── t_lpback.sh │ ├── t_net.sh │ ├── t_server_null.rc-sample │ ├── t_server_null.sh │ ├── t_server_null_client.sh │ ├── t_server_null_default.rc │ ├── t_server_null_server.sh │ ├── t_server_null_stress.sh │ ├── unit_tests/ │ │ ├── Makefile.am │ │ ├── README.md │ │ ├── example_test/ │ │ │ ├── Makefile.am │ │ │ ├── README.md │ │ │ ├── test.c │ │ │ └── test2.c │ │ ├── openvpn/ │ │ │ ├── Makefile.am │ │ │ ├── cert_data.h │ │ │ ├── input/ │ │ │ │ ├── appears_empty.txt │ │ │ │ ├── empty.txt │ │ │ │ ├── leak_suppr.txt │ │ │ │ ├── user_only.txt │ │ │ │ └── user_pass.txt │ │ │ ├── mock_get_random.c │ │ │ ├── mock_management.c │ │ │ ├── mock_msg.c │ │ │ ├── mock_msg.h │ │ │ ├── mock_ssl_dependencies.c │ │ │ ├── mock_win32_execve.c │ │ │ ├── pkey_test_utils.c │ │ │ ├── test_argv.c │ │ │ ├── test_auth_token.c │ │ │ ├── test_buffer.c │ │ │ ├── test_common.h │ │ │ ├── test_crypto.c │ │ │ ├── test_cryptoapi.c │ │ │ ├── test_dhcp.c │ │ │ ├── test_mbuf.c │ │ │ ├── test_misc.c │ │ │ ├── test_ncp.c │ │ │ ├── test_networking.c │ │ │ ├── test_options_parse.c │ │ │ ├── test_packet_id.c │ │ │ ├── test_pkcs11.c │ │ │ ├── test_pkt.c │ │ │ ├── test_provider.c │ │ │ ├── test_push_update_msg.c │ │ │ ├── test_socket.c │ │ │ ├── test_ssl.c │ │ │ ├── test_tls_crypt.c │ │ │ └── test_user_pass.c │ │ ├── openvpnserv/ │ │ │ ├── Makefile.am │ │ │ └── test_openvpnserv.c │ │ └── plugins/ │ │ ├── Makefile.am │ │ └── auth-pam/ │ │ ├── Makefile.am │ │ └── test_search_and_replace.c │ └── update_t_client_ips.sh └── version.m4 ================================================ FILE CONTENTS ================================================ ================================================ FILE: .clang-format ================================================ --- BasedOnStyle: Mozilla AccessModifierOffset: '-4' AlignAfterOpenBracket: Align AlignConsecutiveMacros: Enabled: true AcrossEmptyLines: false AcrossComments: true AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: Kind: Always OverEmptyLines: 1 AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false BinPackArguments: true BinPackParameters: true BreakAfterReturnType: AllDefinitions BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Allman BreakBeforeTernaryOperators: true BreakStringLiterals: false ColumnLimit: '0' ContinuationIndentWidth: '4' DerivePointerAlignment: false IndentCaseLabels: true IndentGotoLabels: false IndentWidth: '4' IndentWrappedFunctionNames: false InsertBraces: true KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: '2' PointerAlignment: Right ReflowComments: true SortIncludes: false SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpacesBeforeTrailingComments: '2' SpacesInParens: Never TabWidth: '4' TypeNames: [DWORD] UseTab: Never WhitespaceSensitiveMacros: [_STRINGIFY] --- Language: C --- Language: Cpp ================================================ FILE: .git-blame-ignore-revs ================================================ # This FILE allows git blame to ignore reformatting changes and instead # shows the previous commit that changed the line. # # To avoid manually building the list of commits this commit # adds a file with a list of reformatting commits. TO use: # # git blame --ignore-revs-file=.git-blame-ignore-revs file # # or to automatically always use the file # # git config blame.ignoreRevsFile .git-blame-ignore-revs # Uncrustify 2020/06... (engine, pool, SSO) c1ff8f247f91c88a2df5502eeedf42857f9a6831 # Uncrustify the tests/unit_tests/ part of our tree. da1574ef7826d73f01e120cbd1ba40ce39a305b7 # Another round of uncrustify code cleanup. 9cf7b4925a54d93fbea1cadcf3dc0e11f3ce358f # networking_sitnl.c: uncrustify file 2c45d268ca65c522fbabb7c4dab5e721296b4623 # Uncrustify tapctl and openvpnmsica 6280d3d5536174934ee22d3840457d61896e0e3a # tun.c: uncrustify baef44fc8769bbd99f4d699ce9f63180c29a5455 # networking_sitnl.c: uncrustify file 2c45d268ca65c522fbabb7c4dab5e721296b4623 # uncrustify openvpn sources f57431cdc88f22fa4d7962946f0d3187fe058539 # More broadly enforce Allman style and braces-around-conditionals 4cd4899e8e80efae03c584a760fd107251735723 # The Great Reformatting - first phase 81d882d5302b8b647202a6893b57dfdc61fd6df2 # Fix trailing-whitespace errors in last patch. 3282632d9325267c850072db7545a884a1637f51 # The Great Reformatting of 2022 abe49856d81f51136d543539202a0bf8fb946474 # Reformat for sp_after_comma=add e51d9a73693ee742b36e19fb1718e5e27167831d # The Great Reformatting of 2025, switching to clang-format 3cca3367e6e0ffeccb8e39cb2c739d1dcb086701 # Switching to ColumnLimit 0 for clang-format 21f7d6e1ad65b1f7db673bc98764dc7325858e0b ================================================ FILE: .gitattributes ================================================ *.c eol=lf *.h eol=lf *.rc eol=lf *.txt eol=lf *.bat eol=lf *.vc*proj* eol=crlf *.sln eol=crlf ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **IMPORTANT NOTE** Bugs about OpenVPN Access Server, OpenVPN Connect or any other product by OpenVPN Inc. should be directly reported to OpenVPN Inc. at https://support.openvpn.net **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior. Please make sure to not post any secrets like keys and passwords. **Expected behavior** A clear and concise description of what you expected to happen. **Version information (please complete the following information):** - OS: [e.g. Ubuntu 22.04] - OpenVPN version: [e.g. 2.5.8] - Repeat for peer if relevant **Additional context** Add any other context about the problem here. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ # Thank you for your contribution You are welcome to open PR, but they are used for discussion only. All patches must eventually go to the openvpn-devel mailing list for review: * https://lists.sourceforge.net/lists/listinfo/openvpn-devel Please send your patch using [git-send-email](https://git-scm.com/docs/git-send-email). For example to send your latest commit to the list: $ git send-email --to=openvpn-devel@lists.sourceforge.net HEAD~1 For details, see these Wiki articles: * https://community.openvpn.net/openvpn/wiki/DeveloperDocumentation * https://community.openvpn.net/openvpn/wiki/Contributing ================================================ FILE: .github/workflows/build.yaml ================================================ # The name of our workflow name: Build on: push: pull_request: jobs: clang-format: name: Check code style with clang-format runs-on: ubuntu-24.04 steps: - name: Install dependencies run: | sudo apt update && sudo apt install -y python3-pip pip3 install pre-commit - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run clang-format run: pre-commit run -a --show-diff-on-failure || true - name: Check for changes run: git diff --output=format-changes.patch - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: format-changes.patch path: format-changes.patch - name: Set job status run: test ! -s format-changes.patch android: strategy: fail-fast: false matrix: abi: [ arm64-v8a ] include: - abi: arm64-v8a vcpkg_triplet: arm64-android runs-on: ubuntu-24.04 name: "Android - ${{ matrix.abi }}" # Github images already setup NDK with ANDROID_NDK_ROOT pointing to the root # of the SDK env: VCPKG_DEFAULT_TRIPLET: ${{ matrix.vcpkg_triplet }} VCPKG_ROOT: ${{ github.workspace }}/vcpkg VCPKG_INSTALLED_DIR: ${{ github.workspace }}/vcpkg/installed steps: - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 - name: Install vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: e5a1490e1409d175932ef6014519e9ae149ddb7c - name: Install dependencies run: ${VCPKG_ROOT}/vcpkg install openssl lz4 cmocka - name: configure OpenVPN with cmake run: | cmake -S . -B openvpn-build -DUNSUPPORTED_BUILDS=yes \ -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=28 \ -DCMAKE_ANDROID_ARCH_ABI=${{ matrix.abi }} \ -DOPENSSL_ROOT_DIR=${VCPKG_INSTALLED_DIR}/${{ matrix.vcpkg_triplet }} \ -DENABLE_PKCS11=false -DBUILD_TESTING=true -DENABLE_LZO=false - name: Build OpenVPN Android binary with cmake run: cmake --build openvpn-build mingw: strategy: fail-fast: false matrix: arch: [x86, x64] build: [Release, Debug] name: "gcc-mingw - ${{ matrix.arch }} - ${{matrix.build }} - OSSL" runs-on: ubuntu-24.04 env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg steps: - name: Install dependencies run: sudo apt update && sudo apt install -y mingw-w64 unzip build-essential wget python3-docutils man2html-base - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 - name: Restore from cache and install vcpkg uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: e5a1490e1409d175932ef6014519e9ae149ddb7c vcpkgJsonGlob: '**/mingw/vcpkg.json' - name: Run CMake with vcpkg.json manifest uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 with: configurePreset: mingw-${{ matrix.arch }} buildPreset: mingw-${{ matrix.arch }} buildPresetAdditionalArgs: "['--config ${{ matrix.build }}']" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: openvpn-mingw-${{ matrix.arch }}-${{ matrix.build }} path: | ${{ github.workspace }}/out/build/mingw/${{ matrix.arch }}/**/${{ matrix.build }}/*.exe ${{ github.workspace }}/out/build/mingw/${{ matrix.arch }}/**/${{ matrix.build }}/*.dll !${{ github.workspace }}/out/build/mingw/${{ matrix.arch }}/**/${{ matrix.build }}/test_*.exe - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: openvpn-mingw-${{ matrix.arch }}-${{ matrix.build }}-tests path: | ${{ github.workspace }}/out/build/mingw/${{ matrix.arch }}/**/${{ matrix.build }}/test_*.exe ${{ github.workspace }}/out/build/mingw/${{ matrix.arch }}/${{ matrix.build }}/*.dll mingw-unittest: needs: [ mingw ] strategy: fail-fast: false matrix: arch: [x86, x64] test: [argv, auth_token, buffer, cryptoapi, crypto, misc, options_parse, ncp, openvpnserv, packet_id, pkt, provider, ssl, tls_crypt, user_pass] build: [Release, Debug] runs-on: windows-2025 name: "mingw unittest ${{ matrix.test }} - ${{ matrix.arch }} - ${{ matrix.build }} - OSSL" steps: - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Retrieve mingw unittest uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: openvpn-mingw-${{ matrix.arch }}-${{ matrix.build }}-tests path: unittests - name: Run ${{ matrix.test }} unit test run: | $test_file=(Get-ChildItem -Path unittests -Filter test_${{ matrix.test }}.exe -Recurse).fullname & $test_file env: srcdir: "${{ github.workspace }}/tests/unit_tests/openvpn" ubuntu: strategy: fail-fast: false matrix: os: [ubuntu-22.04, ubuntu-24.04] sslpkg: [libssl-dev] ssllib: [openssl] include: - os: ubuntu-22.04 libname: OpenSSL 3.0.2 pkcs11pkg: "libpkcs11-helper1-dev softhsm2 gnutls-bin" extraconf: --enable-pkcs11 - os: ubuntu-24.04 libname: OpenSSL 3.0.13 pkcs11pkg: "libpkcs11-helper1-dev softhsm2 gnutls-bin" extraconf: --enable-pkcs11 name: "gcc - ${{matrix.os}} - ${{matrix.libname}} ${{matrix.extraconf}}" env: SSLPKG: "${{matrix.sslpkg}}" PKCS11PKG: "${{matrix.pkcs11pkg}}" runs-on: ${{matrix.os}} steps: - name: Install dependencies run: sudo apt update && sudo apt install -y liblzo2-dev libpam0g-dev liblz4-dev libcap-ng-dev libnl-genl-3-dev linux-libc-dev man2html libcmocka-dev python3-docutils libtool automake autoconf ${SSLPKG} ${PKCS11PKG} - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: autoconf run: autoreconf -fvi - name: configure run: ./configure --with-crypto-library=${{matrix.ssllib}} ${{matrix.extraconf}} --enable-werror - name: make all run: make -j3 - name: configure checks if: ${{ matrix.extraconf != '--disable-management' }} run: echo 'RUN_SUDO="sudo -E"' >tests/t_server_null.rc - name: make check run: make -j3 check VERBOSE=1 ubuntu-clang-asan: strategy: fail-fast: false matrix: os: [ubuntu-22.04, ubuntu-24.04] ssllib: [openssl] name: "clang-asan - ${{matrix.os}} - ${{matrix.ssllib}}" env: UBSAN_OPTIONS: print_stacktrace=1 runs-on: ${{matrix.os}} steps: - name: Install dependencies run: sudo apt update && sudo apt install -y liblzo2-dev libpam0g-dev liblz4-dev libcap-ng-dev libnl-genl-3-dev linux-libc-dev man2html clang libcmocka-dev python3-docutils libtool automake autoconf - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: autoconf run: autoreconf -fvi - name: configure run: CFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer -O2" CC=clang ./configure --with-crypto-library=${{matrix.ssllib}} --enable-werror - name: make all run: make -j3 - name: configure checks run: echo 'RUN_SUDO="sudo -E"' >tests/t_server_null.rc - name: make check run: make -j3 check VERBOSE=1 macos: strategy: fail-fast: false matrix: ssllib: [openssl@3, libressl] build: [normal, asan] os: [macos-14, macos-15, macos-26] include: - build: asan cflags: "-fsanitize=address,undefined -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" ldflags: -fsanitize=address,undefined -fno-sanitize-recover=all # Our build system ignores LDFLAGS for plugins configureflags: --disable-plugin-auth-pam --disable-plugin-down-root - build: normal cflags: "-O2 -g" ldflags: "" configureflags: "" runs-on: ${{matrix.os}} name: "${{matrix.os}} - ${{matrix.ssllib}} - ${{matrix.build}}" env: CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} UBSAN_OPTIONS: print_stacktrace=1 steps: - name: Install dependencies run: brew install ${{matrix.ssllib}} lzo lz4 man2html cmocka libtool automake autoconf - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set environment run: | cat >>$GITHUB_ENV <tests/t_server_null.rc - name: make check run: make -j4 check VERBOSE=1 msvc: strategy: fail-fast: false matrix: arch: [amd64, x86, arm64, amd64-clang, x86-clang] name: "msbuild - ${{ matrix.arch }} - openssl" env: BUILD_CONFIGURATION: Release runs-on: windows-2025 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 - name: Install rst2html run: python -m pip install --upgrade pip docutils - name: Restore artifacts, or setup vcpkg (do not install any package) uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5 with: vcpkgGitCommitId: e5a1490e1409d175932ef6014519e9ae149ddb7c vcpkgJsonGlob: '**/windows/vcpkg.json' - name: Run CMake with vcpkg.json manifest (NO TESTS) uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 if: ${{ matrix.arch == 'arm64' }} with: configurePreset: win-${{ matrix.arch }}-release buildPreset: win-${{ matrix.arch }}-release - name: Run CMake with vcpkg.json manifest uses: lukka/run-cmake@af1be47fd7c933593f687731bc6fdbee024d3ff4 # v10.8 if: ${{ matrix.arch != 'arm64' }} with: configurePreset: win-${{ matrix.arch }}-release buildPreset: win-${{ matrix.arch }}-release testPreset: win-${{ matrix.arch }}-release testPresetAdditionalArgs: "['--output-on-failure']" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: openvpn-msvc-${{ matrix.arch }} path: | ${{ github.workspace }}/out/**/*.exe ${{ github.workspace }}/out/**/*.dll !${{ github.workspace }}/out/**/test_*.exe !${{ github.workspace }}/out/**/CMakeFiles/** !${{ github.workspace }}/out/**/vcpkg_installed/** libressl: strategy: fail-fast: false matrix: os: [ubuntu-24.04] ssllib: [libressl] build: [ normal, asan ] configureflags: ["--with-openssl-engine=no"] include: - build: asan cflags: "-fsanitize=address -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" ldflags: -fsanitize=address -fno-sanitize-recover=all cc: clang - build: normal cflags: "-O2 -g" ldflags: "" cc: gcc name: "${{matrix.cc}} ${{matrix.build}} - ${{matrix.os}} - ${{matrix.ssllib}}" runs-on: ${{matrix.os}} env: CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} CC: ${{matrix.cc}} UBSAN_OPTIONS: print_stacktrace=1 steps: - name: Install dependencies run: sudo apt update && sudo apt install -y liblzo2-dev libpam0g-dev liblz4-dev linux-libc-dev man2html clang libcmocka-dev python3-docutils libtool automake autoconf pkg-config libcap-ng-dev libnl-genl-3-dev - name: "libressl: checkout" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: libressl # versioning=semver-coerced repository: libressl/portable ref: v4.2.1 - name: "libressl: autogen.sh" env: LIBRESSL_GIT_OPTIONS: "--no-single-branch" run: ./autogen.sh working-directory: libressl - name: "libressl: configure" run: ./configure working-directory: libressl - name: "libressl: make all" run: make -j3 working-directory: libressl - name: "libressl: make install" run: sudo make install working-directory: libressl - name: "ldconfig" run: sudo ldconfig - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: autoconf run: autoreconf -fvi - name: configure run: ./configure --with-crypto-library=openssl ${{matrix.configureflags}} --enable-werror - name: make all run: make -j3 - name: Ensure the build uses LibreSSL run: | ./src/openvpn/openvpn --version ./src/openvpn/openvpn --version | grep -q "library versions: LibreSSL" - name: configure checks run: echo 'RUN_SUDO="sudo -E"' >tests/t_server_null.rc - name: make check run: make -j3 check VERBOSE=1 mbedtls4: strategy: fail-fast: false matrix: os: [ubuntu-24.04] ssllib: [mbedtls4] build: [ normal, asan ] include: - build: asan cflags: "-fsanitize=address -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" ldflags: -fsanitize=address -fno-sanitize-recover=all cc: clang - build: normal cflags: "-O2 -g" ldflags: "" cc: gcc name: "${{matrix.cc}} ${{matrix.build}} - ${{matrix.os}} - ${{matrix.ssllib}}" runs-on: ${{matrix.os}} env: CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} CC: ${{matrix.cc}} UBSAN_OPTIONS: print_stacktrace=1 steps: - name: Install dependencies run: sudo apt update && sudo apt install -y liblzo2-dev libpam0g-dev liblz4-dev linux-libc-dev man2html clang libcmocka-dev python3-docutils python3-jinja2 python3-jsonschema libtool automake autoconf pkg-config libcap-ng-dev libnl-genl-3-dev - name: "mbedtls: checkout" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: mbedtls submodules: recursive # versioning=semver-coerced repository: Mbed-TLS/mbedtls ref: v4.0.0 - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 - name: "mbedtls: cmake" run: cmake -B build working-directory: mbedtls - name: "mbedtls: cmake --build" run: cmake --build build working-directory: mbedtls - name: "mbedtls: cmake --install" run: sudo cmake --install build --prefix /usr working-directory: mbedtls - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: autoconf run: autoreconf -fvi - name: configure run: ./configure --with-crypto-library=mbedtls --enable-werror - name: make all run: make -j3 - name: Ensure the build uses mbed TLS 4.x run: | ./src/openvpn/openvpn --version ./src/openvpn/openvpn --version | grep -q "library versions: mbed TLS 4." - name: configure checks run: echo 'RUN_SUDO="sudo -E"' >tests/t_server_null.rc - name: make check run: make -j3 check VERBOSE=1 aws-lc: strategy: fail-fast: false matrix: os: [ubuntu-24.04] ssllib: [ awslc ] build: [ normal, asan ] include: - build: asan cflags: "-fsanitize=address -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" ldflags: -fsanitize=address -fno-sanitize-recover=all cc: clang cxx: clang++ - build: normal cflags: "-O2 -g" ldflags: "" cc: gcc cxx: c++ name: "${{matrix.cc}} ${{matrix.build}} - ${{matrix.os}} - ${{matrix.ssllib}}" runs-on: ${{matrix.os}} env: CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} CC: ${{matrix.cc}} CXX: ${{matrix.cxx}} UBSAN_OPTIONS: print_stacktrace=1 AWS_LC_INSTALL: /opt/aws-lc steps: - name: Install dependencies run: sudo apt update && sudo apt install -y gcc golang make liblzo2-dev libpam0g-dev liblz4-dev linux-libc-dev man2html clang libcmocka-dev python3-docutils python3-jinja2 python3-jsonschema libtool automake autoconf pkg-config libcap-ng-dev libnl-genl-3-dev - name: "AWS-LC: checkout" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: aws-lc # versioning=semver-coerced repository: aws/aws-lc ref: v1.70.0 - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 - name: "AWS-LC: build" run: | mkdir build cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${{ env.AWS_LC_INSTALL }}" -DBUILD_SHARED_LIBS=1 ../ ninja install working-directory: aws-lc - name: Checkout OpenVPN uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: autoconf run: autoreconf -fvi - name: configure with AWS-LC run: | OPENSSL_CFLAGS="-I${{ env.AWS_LC_INSTALL }}/include" \ OPENSSL_LIBS="-L${{ env.AWS_LC_INSTALL }}/lib -lssl -lcrypto" \ LDFLAGS="-Wl,-rpath=${{ env.AWS_LC_INSTALL }}/lib" \ ./configure --with-crypto-library=openssl - name: make all run: make -j3 - name: Ensure the build uses AWS-LC run: | ./src/openvpn/openvpn --version ./src/openvpn/openvpn --version | grep -q "library versions: AWS-LC" - name: configure checks run: echo 'RUN_SUDO="sudo -E"' >tests/t_server_null.rc - name: make check run: make -j3 check VERBOSE=1 ================================================ FILE: .github/workflows/coverity-scan.yml ================================================ name: coverity-scan on: schedule: - cron: '0 20 * * *' # Daily at 20:00 UTC workflow_dispatch: jobs: latest: # Running coverity requires the secrets.COVERITY_SCAN_TOKEN token # which is only available on the main repository if: github.repository_owner == 'OpenVPN' runs-on: ubuntu-24.04 steps: - name: Check submission cache id: check_submit uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: | cov-int key: check-submit-${{ github.sha }} - name: Install dependencies if: steps.check_submit.outputs.cache-hit != 'true' run: sudo apt update && sudo apt install -y liblzo2-dev libpam0g-dev liblz4-dev libcap-ng-dev libnl-genl-3-dev linux-libc-dev man2html libcmocka-dev python3-docutils libtool automake autoconf libssl-dev libpkcs11-helper1-dev softhsm2 gnutls-bin - name: Checkout OpenVPN if: steps.check_submit.outputs.cache-hit != 'true' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download Coverity Build Tool if: steps.check_submit.outputs.cache-hit != 'true' run: | wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=OpenVPN%2Fopenvpn" -O cov-analysis-linux64.tar.gz mkdir cov-analysis-linux64 tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64 env: TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} - name: autoconf if: steps.check_submit.outputs.cache-hit != 'true' run: autoreconf -fvi - name: configure if: steps.check_submit.outputs.cache-hit != 'true' run: ./configure --enable-pkcs11 - name: Build with cov-build if: steps.check_submit.outputs.cache-hit != 'true' run: | PATH=`pwd`/cov-analysis-linux64/bin:$PATH cov-build --dir cov-int make - name: Submit the result to Coverity Scan if: steps.check_submit.outputs.cache-hit != 'true' run: | tar czvf openvpn.tgz cov-int curl --form token=$TOKEN \ --form email=$EMAIL \ --form file=@openvpn.tgz \ --form version="$GITHUB_SHA" \ --form description="master" \ https://scan.coverity.com/builds?project=OpenVPN%2Fopenvpn env: TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }} - name: Cache submission if: steps.check_submit.outputs.cache-hit != 'true' uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: | cov-int key: ${{ steps.check_submit.outputs.cache-primary-key }} ================================================ FILE: .github/workflows/doxygen.yml ================================================ name: Deploy Doxygen documentation to Pages on: push: branches: ["master"] workflow_dispatch: concurrency: group: "pages" cancel-in-progress: false jobs: build: runs-on: ubuntu-24.04 if: ${{ github.repository_owner == 'openvpn' || github.event_name == 'workflow_dispatch' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: openvpn - name: Install dependencies run: | sudo apt update sudo apt install -y --no-install-recommends \ build-essential doxygen graphviz \ liblzo2-dev libpam0g-dev liblz4-dev libcap-ng-dev libnl-genl-3-dev linux-libc-dev man2html libcmocka-dev python3-docutils libtool automake autoconf libssl-dev - name: Build Doxygen documentation id: build run: | cd openvpn autoreconf -f -i cd .. mkdir doxygen cd doxygen ../openvpn/configure make doxygen touch doc/doxygen/html/.nojekyll - name: Upload static files as artifact id: deployment uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 with: path: doxygen/doc/doxygen/html/ deploy: needs: build permissions: pages: write # to deploy to Pages id-token: write # to verify the deployment originates from an appropriate source environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-24.04 steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 ================================================ FILE: .gitignore ================================================ *.[oa] *.l[oa] *.dll *.exe *.exe.* *.obj *.pyc *.so *~ *.idb *.suo *.ncb *.log out .vs .deps .libs Makefile Makefile.in aclocal.m4 autodefs.h autom4te.cache config.guess config.h config.h.in config.log config.status config.sub configure configure.h depcomp stamp-h1 install-sh missing ltmain.sh libtool m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 build doc/openvpn-examples.5 doc/openvpn-examples.5.html doc/openvpn.8 doc/openvpn.8.html /doc/doxygen/html/ /doc/doxygen/latex/ /doc/doxygen/openvpn.doxyfile distro/systemd/*.service distro/dns-scripts/dns-updown sample/sample-keys/sample-ca/ vendor/cmocka_build vendor/dist tests/t_client.sh tests/t_client-*-20??????-??????/ tests/t_server_null.rc t_client.rc t_client_ips.rc tests/unit_tests/**/*_testdriver src/openvpn/openvpn include/openvpn-plugin.h config-version.h nbproject test-driver compile stamp-h2 ================================================ FILE: .mailmap ================================================ Adriaan de Jong David Sommerseth Gert Doering Gert Doering Gert Doering Gert Doering James Yonan Jan Just Keijser JuanJo Ciarlante Karl O. Pinc Robert Fischer Samuli Seppänen Seth Mos ================================================ FILE: .pre-commit-config.yaml ================================================ repos: - repo: https://github.com/pre-commit/mirrors-clang-format rev: 'v21.1.8' hooks: - id: clang-format files: \.[ch]$ # preserve upstream formatting exclude: ^(src/compat/compat-lz4\.[ch]|src/openvpn/ovpn_dco_(linux|win)\.h)$ ================================================ FILE: .svncommitters ================================================ james = James Yonan ================================================ FILE: AUTHORS ================================================ James Yonan ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.14) set(CMAKE_CONFIGURATION_TYPES "Release;Debug;ASAN") project(openvpn) # This CMake file implements building OpenVPN with CMAKE # # Note that this is *NOT* the official way to build openvpn on anything # other than Windows/mingw despite working on other platforms too. You will need # to add -DUNSUPPORTED_BUILDS=true to build on non Windows platforms. # # This cmake also makes a few assertions like lzo, lz4 being used # and OpenSSL having version 1.1.1+ and generally does not offer the same # configurability like autoconf find_package(PkgConfig REQUIRED) include(CheckSymbolExists) include(CheckIncludeFiles) include(CheckCCompilerFlag) include(CheckLinkerFlag OPTIONAL) include(CheckTypeSize) include(CheckStructHasMember) include(CTest) option(UNSUPPORTED_BUILDS "Allow unsupported builds" OFF) if (NOT WIN32 AND NOT ${UNSUPPORTED_BUILDS}) message(FATAL_ERROR "Note: on Unix platform the official and supported build method is using autoconfig. CMake based build should be only used for Windows and internal testing/development.") endif() if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h") message(FATAL_ERROR "The top level source directory has a config.h file. Note that you can't mix in-tree autoconfig builds with out-of-tree cmake builds.") endif () option(MBED "BUILD with mbed" OFF) set(MBED_INCLUDE_PATH "" CACHE STRING "Path to mbed TLS include directory") set(MBED_LIBRARY_PATH "" CACHE STRING "Path to mbed library directory") option(WOLFSSL "BUILD with wolfSSL" OFF) option(ENABLE_LZ4 "BUILD with lz4" ON) option(ENABLE_LZO "BUILD with lzo" ON) option(ENABLE_PKCS11 "BUILD with pkcs11-helper" ON) option(USE_WERROR "Treat compiler warnings as errors (-Werror)" ON) option(FAKE_ANDROID "Target Android but do not use actual cross compile/Android cmake to build for simple compile checks on Linux") option(ENABLE_DNS_UPDOWN_BY_DEFAULT "Run --dns-updown hook by default" ON) set(DNS_UPDOWN_PATH "${CMAKE_INSTALL_PREFIX}/libexec/openvpn/dns-updown" CACHE STRING "Default location for the DNS up/down script") set(PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/lib/openvpn/plugins" CACHE FILEPATH "Location of the plugin directory") # Create machine readable compile commands option(ENABLE_COMPILE_COMMANDS "Generate compile_commands.json and a symlink for clangd to find it" OFF) if (ENABLE_COMPILE_COMMANDS) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build AND NOT IS_SYMLINK ${CMAKE_CURRENT_SOURCE_DIR}/build) message(FATAL_ERROR "The top level source directory contains a 'build' file or directory. Please remove or rename it. CMake creates a symlink with that name during build.") endif() set(CMAKE_EXPORT_COMPILE_COMMANDS 1) add_custom_target( symlink-build-dir ALL ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/build ) endif () # AddressSanitize - use CXX=clang++ CC=clang cmake -DCMAKE_BUILD_TYPE=asan to build with ASAN set(CMAKE_C_FLAGS_ASAN "-fsanitize=address,undefined -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" CACHE STRING "Flags used by the C compiler during AddressSanitizer builds." FORCE) set(CMAKE_CXX_FLAGS_ASAN "-fsanitize=address,undefined -fno-sanitize-recover=all -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1" CACHE STRING "Flags used by the C++ compiler during AddressSanitizer builds." FORCE) function(check_and_add_compiler_flag flag variable) check_c_compiler_flag(${flag} ${variable}) if (${variable}) add_compile_options(${flag}) endif() endfunction() if (MSVC) add_compile_definitions( _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _WINSOCK_DEPRECATED_NO_WARNINGS ) if (USE_WERROR) add_compile_options(/WX) endif () # C4018: signed/unsigned mismatch # C4244: conversion from 'type1' to 'type2', possible loss of data # C4267: conversion from 'size_t' to 'type', possible loss of data add_compile_options( /MP /W3 /wd4018 /wd4267 /wd4244 /sdl /Qspectre /guard:cf /FC /ZH:SHA_256 "$<$:/GL>" "$<$:/Oi>" "$<$:/Gy>" "$<$:/Zi>" ) add_link_options( /Brepro "$<$:/LTCG:incremental>" "$<$:/DEBUG:FULL>" "$<$:/OPT:REF>" "$<$:/OPT:ICF>" ) if (${CMAKE_GENERATOR_PLATFORM} STREQUAL "x64" OR ${CMAKE_GENERATOR_PLATFORM} STREQUAL "x86") add_link_options("$<$:/CETCOMPAT>") endif() else () add_compile_options(-Wall -Wuninitialized) check_and_add_compiler_flag(-Wno-stringop-truncation NoStringOpTruncation) check_and_add_compiler_flag(-Wstrict-prototypes StrictPrototypes) check_and_add_compiler_flag(-Wold-style-definition OldStyleDefinition) add_compile_options(-Wconversion -Wno-sign-conversion) add_compile_options(-Wextra -Wno-unused-parameter) # clang doesn't have the different levels but also doesn't include it in -Wextra check_and_add_compiler_flag(-Wimplicit-fallthrough=2 GCCImplicitFallthrough) if (WIN32) # Not sure how to deal with GetProcAddress add_compile_options(-Wno-cast-function-type) endif () if (USE_WERROR) add_compile_options(-Werror) endif () endif () find_package(Python3 REQUIRED COMPONENTS Interpreter) execute_process( COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/contrib/cmake/parse-version.m4.py ${CMAKE_CURRENT_SOURCE_DIR}/version.m4 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) include(${CMAKE_CURRENT_BINARY_DIR}/version.cmake) set(OPENVPN_VERSION_MAJOR ${PRODUCT_VERSION_MAJOR}) set(OPENVPN_VERSION_MINOR ${PRODUCT_VERSION_MINOR}) set(OPENVPN_VERSION_PATCH ${PRODUCT_VERSION_PATCH}) set(OPENVPN_VERSION_RESOURCE ${PRODUCT_VERSION_RESOURCE}) set(CMAKE_C_STANDARD 11) # Set the various defines for config.h.cmake.in if (${CMAKE_SYSTEM_NAME} STREQUAL "Android" OR ${FAKE_ANDROID}) set(TARGET_ANDROID YES) set(ENABLE_ASYNC_PUSH YES) set(ENABLE_SITNL YES) # Wacky workaround as OpenSSL package detection is otherwise broken (https://stackoverflow.com/questions/45958214/android-cmake-could-not-find-openssl) list(APPEND CMAKE_FIND_ROOT_PATH ${OPENSSL_ROOT_DIR}) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(TARGET_LINUX YES) set(ENABLE_ASYNC_PUSH YES) set(ENABLE_LINUXDCO YES) set(ENABLE_SITNL YES) set(ENABLE_DCO YES) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(TARGET_FREEBSD YES) set(ENABLE_DCO YES) link_libraries(-lnv) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") set(TARGET_OPENBSD YES) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS") set(TARGET_SOLARIS YES) set(HAVE_SYS_SOCKIO_H 1) link_libraries(-lnsl -lsocket -lresolv) elseif (WIN32) set(ENABLE_DCO YES) elseif (APPLE) set(TARGET_DARWIN YES) else() message(FATAL_ERROR "Unknown system name: \"${CMAKE_SYSTEM_NAME}\"") endif () if (UNIX) set(PATH_SEPARATOR /) set(ENABLE_PORT_SHARE YES) set(HAVE_SA_FAMILY_T YES) elseif (WIN32) set(PATH_SEPARATOR \\\\) set(TARGET_WIN32 YES) endif () check_include_files(unistd.h HAVE_UNISTD_H) if (HAVE_UNISTD_H) check_symbol_exists(chroot unistd.h HAVE_CHROOT) check_symbol_exists(chdir unistd.h HAVE_CHDIR) check_symbol_exists(dup unistd.h HAVE_DUP) check_symbol_exists(dup2 unistd.h HAVE_DUP2) check_symbol_exists(fork unistd.h HAVE_FORK) check_symbol_exists(execve unistd.h HAVE_EXECVE) check_symbol_exists(ftruncate unistd.h HAVE_FTRUNCATE) check_symbol_exists(nice unistd.h HAVE_NICE) check_symbol_exists(setgid unistd.h HAVE_SETGID) check_symbol_exists(setuid unistd.h HAVE_SETUID) check_symbol_exists(setsid unistd.h HAVE_SETSID) check_symbol_exists(daemon "unistd.h;stdlib.h" HAVE_DAEMON) check_symbol_exists(getpeereid "unistd.h;sys/socket.h" HAVE_GETPEEREID) endif() check_include_files(grp.h HAVE_GRP_H) if (HAVE_GRP_H) check_symbol_exists(getgrnam grp.h HAVE_GETGRNAM) endif() check_include_files(libgen.h HAVE_LIBGEN_H) if (HAVE_LIBGEN_H) check_symbol_exists(basename libgen.h HAVE_BASENAME) check_symbol_exists(dirname libgen.h HAVE_DIRNAME) endif() check_include_files(pwd.h HAVE_PWD_H) if (HAVE_PWD_H) check_symbol_exists(getpwnam pwd.h HAVE_GETPWNAM) endif() check_include_files(sys/epoll.h HAVE_SYS_EPOLL_H) if (HAVE_SYS_EPOLL_H) check_symbol_exists(epoll_create sys/epoll.h HAVE_EPOLL_CREATE) endif() check_include_files(syslog.h HAVE_SYSLOG_H) if (HAVE_SYSLOG_H) check_symbol_exists(openlog syslog.h HAVE_OPENLOG) check_symbol_exists(syslog syslog.h HAVE_SYSLOG) endif() check_include_files(sys/mman.h HAVE_SYS_MMAN_H) if (HAVE_SYS_MMAN_H) check_symbol_exists(mlockall sys/mman.h HAVE_MLOCKALL) endif() check_include_files(sys/socket.h HAVE_SYS_SOCKET_H) if (HAVE_SYS_SOCKET_H) check_symbol_exists(sendmsg sys/socket.h HAVE_SENDMSG) check_symbol_exists(recvmsg sys/socket.h HAVE_RECVMSG) check_symbol_exists(getsockname sys/socket.h HAVE_GETSOCKNAME) # Checking for existence of structs with check_symbol_exists does not work, # so we use check_struct_hash_member with a member instead check_struct_has_member("struct cmsghdr" cmsg_len sys/socket.h HAVE_CMSGHDR) endif() check_include_files(sys/time.h HAVE_SYS_TIME_H) if (HAVE_SYS_TIME_H) check_symbol_exists(gettimeofday sys/time.h HAVE_GETTIMEOFDAY) check_symbol_exists(getrlimit "sys/time.h;sys/resource.h" HAVE_GETRLIMIT) endif() check_symbol_exists(chsize io.h HAVE_CHSIZE) check_symbol_exists(getrlimit sys/resource.h HAVE_GETRLIMIT) check_symbol_exists(strsep string.h HAVE_STRSEP) # Some OS (e.g. FreeBSD) need some basic headers to allow # including network headers set(NETEXTRA sys/types.h) check_include_files("${NETEXTRA};netinet/in.h" HAVE_NETINET_IN_H) if (HAVE_NETINET_IN_H) list(APPEND NETEXTRA netinet/in.h) endif () check_include_files(arpa/inet.h HAVE_ARPA_INET_H) check_include_files(dlfcn.h HAVE_DLFCN_H) check_include_files(dmalloc.h HAVE_DMALLOC_H) check_include_files(fcntl.h HAVE_FCNTL_H) check_include_files(err.h HAVE_ERR_H) check_include_files(netdb.h HAVE_NETDB_H) check_include_files("${NETEXTRA};netinet/in6.h" HAVE_NETINET_IN_H) check_include_files(net/if.h HAVE_NET_IF_H) check_include_files("${NETEXTRA};net/if_tun.h" HAVE_NET_IF_TUN_H) check_include_files(poll.h HAVE_POLL_H) check_include_files("${NETEXTRA};resolv.h" HAVE_RESOLV_H) check_include_files(sys/ioctl.h HAVE_SYS_IOCTL_H) check_include_files(sys/inotify.h HAVE_SYS_INOTIFY_H) check_include_files("${NETEXTRA};sys/uio.h" HAVE_SYS_UIO_H) check_include_files(sys/un.h HAVE_SYS_UN_H) check_include_files(sys/wait.h HAVE_SYS_WAIT_H) check_include_files("${NETEXTRA};netinet/ip.h" HAVE_NETINET_IP_H) if (HAVE_NETINET_IP_H) set(CMAKE_EXTRA_INCLUDE_FILES netinet/ip.h) check_type_size("struct in_pktinfo" IN_PKTINFO) check_struct_has_member("struct in_pktinfo" ipi_spec_dst netinet/ip.h HAVE_IPI_SPEC_DST) check_type_size("struct msghdr" MSGHDR) set(CMAKE_EXTRA_INCLUDE_FILES) endif() find_program(IFCONFIG_PATH ifconfig) find_program(IPROUTE_PATH ip) find_program(ROUTE_PATH route) if (${ENABLE_LZ4}) pkg_search_module(liblz4 liblz4 REQUIRED IMPORTED_TARGET) endif () if (${ENABLE_LZO}) pkg_search_module(lzo2 lzo2 REQUIRED IMPORTED_TARGET) endif () if (${ENABLE_PKCS11}) pkg_search_module(pkcs11-helper libpkcs11-helper-1 REQUIRED IMPORTED_TARGET) endif () function(check_mbed_configuration) if (NOT (MBED_INCLUDE_PATH STREQUAL "") ) set(CMAKE_REQUIRED_INCLUDES ${MBED_INCLUDE_PATH}) endif () if (NOT (MBED_LIBRARY_PATH STREQUAL "")) set(CMAKE_REQUIRED_LINK_OPTIONS "-L${MBED_LIBRARY_PATH}") endif () set(CMAKE_REQUIRED_LIBRARIES "mbedtls;mbedx509;mbedcrypto") check_include_files(psa/crypto.h HAVE_PSA_CRYPTO_H) endfunction() if (${MBED}) check_mbed_configuration() endif() function(add_library_deps target) if (${MBED}) if (NOT (MBED_INCLUDE_PATH STREQUAL "") ) target_include_directories(${target} PRIVATE ${MBED_INCLUDE_PATH}) endif () if(NOT (MBED_LIBRARY_PATH STREQUAL "")) target_link_directories(${target} PRIVATE ${MBED_LIBRARY_PATH}) endif () target_link_libraries(${target} PRIVATE -lmbedtls -lmbedx509 -lmbedcrypto) elseif (${WOLFSSL}) pkg_search_module(wolfssl wolfssl REQUIRED) target_link_libraries(${target} PUBLIC ${wolfssl_LINK_LIBRARIES}) target_include_directories(${target} PRIVATE ${wolfssl_INCLUDE_DIRS}/wolfssl) else () find_package(OpenSSL REQUIRED) target_link_libraries(${target} PUBLIC OpenSSL::SSL OpenSSL::Crypto) if (WIN32) target_link_libraries(${target} PUBLIC ws2_32.lib crypt32.lib fwpuclnt.lib iphlpapi.lib wininet.lib setupapi.lib rpcrt4.lib wtsapi32.lib ncrypt.lib bcrypt.lib) endif () endif () if (MINGW) target_compile_definitions(${target} PRIVATE WIN32_LEAN_AND_MEAN NTDDI_VERSION=NTDDI_VISTA _WIN32_WINNT=_WIN32_WINNT_VISTA ) endif() # optional dependencies target_link_libraries(${target} PUBLIC $ $ $ ) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") pkg_search_module(libcapng REQUIRED libcap-ng IMPORTED_TARGET) pkg_search_module(libnl REQUIRED libnl-genl-3.0 IMPORTED_TARGET) target_link_libraries(${target} PUBLIC PkgConfig::libcapng PkgConfig::libnl) endif () endfunction() if (${MBED}) set(ENABLE_CRYPTO_MBEDTLS YES) elseif (${WOLFSSL}) set(ENABLE_CRYPTO_OPENSSL YES) set(ENABLE_CRYPTO_WOLFSSL YES) else () set(ENABLE_CRYPTO_OPENSSL YES) endif () include_directories(${CMAKE_CURRENT_SOURCE_DIR} src/compat include) add_custom_command( OUTPUT always_rebuild config-version.h COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/contrib/cmake/git-version.py ) set(HAVE_CONFIG_VERSION_H YES) if (BUILD_TESTING) find_package(cmocka CONFIG) if (TARGET cmocka::cmocka) set(CMOCKA_LIBRARIES cmocka::cmocka) else () pkg_search_module(cmocka cmocka REQUIRED IMPORTED_TARGET) set(CMOCKA_LIBRARIES PkgConfig::cmocka) endif () set(CMAKE_REQUIRED_LIBRARIES ${CMOCKA_LIBRARIES}) check_include_files(cmocka_version.h HAVE_CMOCKA_VERSION_H) endif () configure_file(config.h.cmake.in config.h) configure_file(include/openvpn-plugin.h.in openvpn-plugin.h) # TODO we should remove the need for this, and always include config.h add_compile_definitions(HAVE_CONFIG_H) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(doc) add_subdirectory(src/openvpnmsica) add_subdirectory(src/openvpnserv) add_subdirectory(src/tapctl) set(SOURCE_FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h ${CMAKE_CURRENT_BINARY_DIR}/config-version.h ${CMAKE_CURRENT_BINARY_DIR}/openvpn-plugin.h src/compat/compat-basename.c src/compat/compat-daemon.c src/compat/compat-dirname.c src/compat/compat-gettimeofday.c src/compat/compat-strsep.c src/openvpn/argv.c src/openvpn/argv.h src/openvpn/base64.c src/openvpn/base64.h src/openvpn/basic.h src/openvpn/buffer.c src/openvpn/buffer.h src/openvpn/circ_list.h src/openvpn/clinat.c src/openvpn/clinat.h src/openvpn/common.h src/openvpn/comp-lz4.c src/openvpn/comp-lz4.h src/openvpn/comp.c src/openvpn/comp.h src/openvpn/compstub.c src/openvpn/console.c src/openvpn/console_builtin.c src/openvpn/console.h src/openvpn/crypto.c src/openvpn/crypto.h src/openvpn/crypto_backend.h src/openvpn/crypto_epoch.c src/openvpn/crypto_epoch.h src/openvpn/crypto_openssl.c src/openvpn/crypto_openssl.h src/openvpn/crypto_mbedtls.c src/openvpn/crypto_mbedtls.h src/openvpn/cryptoapi.c src/openvpn/cryptoapi.h src/openvpn/dco.c src/openvpn/dco.h src/openvpn/dco_win.c src/openvpn/dco_win.h src/openvpn/dco_linux.c src/openvpn/dco_linux.h src/openvpn/dco_freebsd.c src/openvpn/dco_freebsd.h src/openvpn/dhcp.c src/openvpn/dhcp.h src/openvpn/dns.c src/openvpn/dns.h src/openvpn/errlevel.h src/openvpn/env_set.c src/openvpn/env_set.h src/openvpn/error.c src/openvpn/error.h src/openvpn/event.c src/openvpn/event.h src/openvpn/fdmisc.c src/openvpn/fdmisc.h src/openvpn/forward.c src/openvpn/forward.h src/openvpn/fragment.c src/openvpn/fragment.h src/openvpn/gremlin.c src/openvpn/gremlin.h src/openvpn/helper.c src/openvpn/helper.h src/openvpn/httpdigest.c src/openvpn/httpdigest.h src/openvpn/init.c src/openvpn/init.h src/openvpn/integer.h src/openvpn/interval.c src/openvpn/interval.h src/openvpn/list.c src/openvpn/list.h src/openvpn/lladdr.c src/openvpn/lladdr.h src/openvpn/lzo.c src/openvpn/lzo.h src/openvpn/manage.c src/openvpn/manage.h src/openvpn/mbuf.c src/openvpn/mbuf.h src/openvpn/memdbg.h src/openvpn/misc.c src/openvpn/misc.h src/openvpn/mroute.c src/openvpn/mroute.h src/openvpn/mss.c src/openvpn/mss.h src/openvpn/mtcp.c src/openvpn/mtcp.h src/openvpn/mtu.c src/openvpn/mtu.h src/openvpn/mudp.c src/openvpn/mudp.h src/openvpn/multi.c src/openvpn/multi.h src/openvpn/multi_io.h src/openvpn/multi_io.c src/openvpn/occ.c src/openvpn/occ.h src/openvpn/openvpn.c src/openvpn/openvpn.h src/openvpn/openvpn_win32_resources.rc src/openvpn/options.c src/openvpn/options.h src/openvpn/options_util.c src/openvpn/options_util.h src/openvpn/options_parse.c src/openvpn/otime.c src/openvpn/otime.h src/openvpn/ovpn_dco_win.h src/openvpn/packet_id.c src/openvpn/packet_id.h src/openvpn/ping.c src/openvpn/ping.h src/openvpn/pkcs11.c src/openvpn/pkcs11.h src/openvpn/pkcs11_backend.h src/openvpn/pkcs11_openssl.c src/openvpn/pkcs11_mbedtls.c src/openvpn/platform.c src/openvpn/platform.h src/openvpn/plugin.c src/openvpn/plugin.h src/openvpn/pool.c src/openvpn/pool.h src/openvpn/proto.c src/openvpn/proto.h src/openvpn/proxy.c src/openvpn/proxy.h src/openvpn/ps.c src/openvpn/ps.h src/openvpn/push.c src/openvpn/push_util.c src/openvpn/push.h src/openvpn/pushlist.h src/openvpn/reflect_filter.c src/openvpn/reflect_filter.h src/openvpn/reliable.c src/openvpn/reliable.h src/openvpn/route.c src/openvpn/route.h src/openvpn/run_command.c src/openvpn/run_command.h src/openvpn/schedule.c src/openvpn/schedule.h src/openvpn/session_id.c src/openvpn/session_id.h src/openvpn/shaper.c src/openvpn/shaper.h src/openvpn/sig.c src/openvpn/sig.h src/openvpn/socket.c src/openvpn/socket.h src/openvpn/socket_util.c src/openvpn/socket_util.h src/openvpn/socks.c src/openvpn/socks.h src/openvpn/ssl.c src/openvpn/ssl.h src/openvpn/ssl_backend.h src/openvpn/ssl_common.h src/openvpn/ssl_openssl.c src/openvpn/ssl_openssl.h src/openvpn/ssl_mbedtls.c src/openvpn/ssl_mbedtls.h src/openvpn/ssl_verify.c src/openvpn/ssl_verify.h src/openvpn/ssl_verify_backend.h src/openvpn/ssl_verify_openssl.c src/openvpn/ssl_verify_openssl.h src/openvpn/ssl_verify_mbedtls.c src/openvpn/ssl_verify_mbedtls.h src/openvpn/status.c src/openvpn/status.h src/openvpn/syshead.h src/openvpn/tls_crypt.c src/openvpn/tun.c src/openvpn/tun.h src/openvpn/tun_afunix.c src/openvpn/tun_afunix.h src/openvpn/networking_sitnl.c src/openvpn/networking_freebsd.c src/openvpn/auth_token.c src/openvpn/auth_token.h src/openvpn/ssl_ncp.c src/openvpn/ssl_ncp.h src/openvpn/ssl_pkt.c src/openvpn/ssl_pkt.h src/openvpn/ssl_util.c src/openvpn/ssl_util.h src/openvpn/vlan.c src/openvpn/vlan.h src/openvpn/wfp_block.c src/openvpn/wfp_block.h src/openvpn/win32.c src/openvpn/win32-util.c src/openvpn/win32.h src/openvpn/win32-util.h src/openvpn/xkey_helper.c src/openvpn/xkey_provider.c ) add_executable(openvpn ${SOURCE_FILES}) add_library_deps(openvpn) target_compile_options(openvpn PRIVATE -DDEFAULT_DNS_UPDOWN=\"${DNS_UPDOWN_PATH}\") if(MINGW) target_compile_options(openvpn PRIVATE -municode -UUNICODE) target_link_options(openvpn PRIVATE -municode) endif() if (MSVC) # we have our own manifest target_link_options(openvpn PRIVATE /MANIFEST:NO) endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_link_libraries(openvpn PUBLIC -ldl) endif () if (NOT WIN32) target_compile_options(openvpn PRIVATE -DPLUGIN_LIBDIR=\"${PLUGIN_DIR}\") find_library(resolv resolv) # some platform like BSDs already include resolver functionality in the libc # and do not have an extra resolv library if (${resolv} OR APPLE) set(RESOLV_LIBRARIES resolv) target_link_libraries(openvpn PUBLIC ${RESOLV_LIBRARIES}) endif () endif () option(UT_ALLOW_BIG_ALLOC "Allow unit-tests to use > 1 GB of memory" ON) if (BUILD_TESTING) set(unit_tests "test_argv" "test_auth_token" "test_buffer" "test_crypto" "test_dhcp" "test_mbuf" "test_misc" "test_ncp" "test_options_parse" "test_packet_id" "test_pkt" "test_provider" "test_socket" "test_ssl" "test_user_pass" "test_push_update_msg" ) if (WIN32) list(APPEND unit_tests "test_cryptoapi" ) endif () # MSVC and Apple's LLVM ld do not support --wrap # This test requires cmake >= 3.18, so check if check_linker_flag is # available if (COMMAND check_linker_flag) check_linker_flag(C -Wl,--wrap=parse_line LD_SUPPORTS_WRAP) endif() # Clang-cl (which is also MSVC) is wrongly detected to support wrap if (NOT MSVC AND "${LD_SUPPORTS_WRAP}") list(APPEND unit_tests "test_tls_crypt" ) endif () # These tests work on only on Linux since they depend on special Linux features if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") list(APPEND unit_tests "test_networking" ) endif () if (NOT WIN32 AND ${ENABLE_PKCS11}) set(_HAVE_SOFTHSM2 YES) find_program(P11TOOL p11tool) find_program(SOFTHSM2_UTIL softhsm2-util) find_library(SOFTHSM2_MODULE softhsm2 PATH_SUFFIXES softhsm) if (P11TOOL STREQUAL "P11TOOL-NOTFOUND") message(STATUS "p11tool not found, pkcs11 UT disabled") set(_HAVE_SOFTHSM2 NO) elseif (SOFTHSM2_UTIL STREQUAL "SOFTHSM2_UTIL-NOTFOUND") message(STATUS "softhsm2-util not found, pkcs11 UT disabled") set(_HAVE_SOFTHSM2 NO) elseif (SOFTHSM2_MODULE STREQUAL "SOFTHSM2_MODULE-NOTFOUND") message(STATUS "softhsm2 module not found, pkcs11 UT disabled") set(_HAVE_SOFTHSM2 NO) endif () if (_HAVE_SOFTHSM2) message(VERBOSE "pkcs11 UT enabled") list(APPEND unit_tests "test_pkcs11" ) endif () endif () foreach (test_name ${unit_tests}) cmake_path(SET _UT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests/unit_tests/openvpn) # test_networking needs special environment if (NOT ${test_name} STREQUAL "test_networking") add_test(${test_name} ${test_name}) # for compat with autotools make check set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "srcdir=${_UT_SOURCE_DIR};LSAN_OPTIONS=suppressions=${_UT_SOURCE_DIR}/input/leak_suppr.txt") endif () add_executable(${test_name} tests/unit_tests/openvpn/${test_name}.c tests/unit_tests/openvpn/mock_msg.c tests/unit_tests/openvpn/mock_msg.h src/openvpn/platform.c src/openvpn/win32-util.c src/compat/compat-gettimeofday.c ) add_library_deps(${test_name}) target_link_libraries(${test_name} PUBLIC ${CMOCKA_LIBRARIES}) target_include_directories(${test_name} PRIVATE src/openvpn) # for compat with IDEs like Clion that ignore the tests properties # for the environment variable srcdir when running tests as fallback target_compile_definitions(${test_name} PRIVATE "UNIT_TEST_SOURCEDIR=\"${_UT_SOURCE_DIR}\"") if (UT_ALLOW_BIG_ALLOC) target_compile_definitions(${test_name} PRIVATE UNIT_TEST_ALLOW_BIG_ALLOC) endif () if (NOT ${test_name} STREQUAL "test_buffer") target_sources(${test_name} PRIVATE src/openvpn/buffer.c ) endif () endforeach() target_sources(test_auth_token PRIVATE src/openvpn/base64.c src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/otime.c src/openvpn/packet_id.c ) target_sources(test_buffer PRIVATE tests/unit_tests/openvpn/mock_get_random.c ) target_sources(test_crypto PRIVATE src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto_epoch.c src/openvpn/crypto.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/mtu.c src/openvpn/mss.c ) target_sources(test_ssl PRIVATE tests/unit_tests/openvpn/mock_management.c tests/unit_tests/openvpn/mock_ssl_dependencies.c tests/unit_tests/openvpn/mock_win32_execve.c src/openvpn/argv.c src/openvpn/base64.c src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/cryptoapi.c src/openvpn/env_set.c src/openvpn/mss.c src/openvpn/mtu.c src/openvpn/options_util.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/run_command.c src/openvpn/ssl_mbedtls.c src/openvpn/ssl_openssl.c src/openvpn/ssl_util.c src/openvpn/ssl_verify_mbedtls.c src/openvpn/ssl_verify_openssl.c src/openvpn/xkey_helper.c src/openvpn/xkey_provider.c ) target_sources(test_mbuf PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/buffer.c src/openvpn/mbuf.c ) target_sources(test_misc PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/options_util.c src/openvpn/ssl_util.c src/openvpn/list.c ) target_sources(test_ncp PRIVATE src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/ssl_util.c src/compat/compat-strsep.c ) target_sources(test_options_parse PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/options_parse.c src/openvpn/options_util.c ) target_sources(test_packet_id PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/reliable.c src/openvpn/session_id.c ) target_sources(test_pkt PRIVATE tests/unit_tests/openvpn/mock_win32_execve.c src/openvpn/argv.c src/openvpn/base64.c src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/env_set.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/reliable.c src/openvpn/run_command.c src/openvpn/session_id.c src/openvpn/ssl_pkt.c src/openvpn/tls_crypt.c ) target_sources(test_provider PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/xkey_provider.c src/openvpn/xkey_helper.c src/openvpn/base64.c ) target_link_libraries(test_socket PUBLIC ${RESOLV_LIBRARIES}) target_sources(test_socket PRIVATE tests/unit_tests/openvpn/mock_get_random.c tests/unit_tests/openvpn/mock_management.c tests/unit_tests/openvpn/mock_win32_execve.c src/openvpn/env_set.c src/openvpn/run_command.c src/openvpn/socket_util.c ) target_sources(test_user_pass PRIVATE tests/unit_tests/openvpn/mock_get_random.c tests/unit_tests/openvpn/mock_win32_execve.c src/openvpn/base64.c src/openvpn/console.c src/openvpn/env_set.c src/openvpn/run_command.c ) target_sources(test_push_update_msg PRIVATE tests/unit_tests/openvpn/mock_msg.c tests/unit_tests/openvpn/mock_get_random.c src/openvpn/options_util.c src/openvpn/otime.c src/openvpn/list.c ) target_sources(test_argv PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/argv.c ) if (TARGET test_cryptoapi) target_sources(test_cryptoapi PRIVATE tests/unit_tests/openvpn/mock_get_random.c tests/unit_tests/openvpn/cert_data.h tests/unit_tests/openvpn/pkey_test_utils.c src/openvpn/xkey_provider.c src/openvpn/xkey_helper.c src/openvpn/base64.c ) endif () target_compile_definitions(test_dhcp PRIVATE DHCP_UNIT_TEST) target_sources(test_dhcp PRIVATE tests/unit_tests/openvpn/mock_get_random.c ) if (TARGET test_networking) target_link_options(test_networking PRIVATE -Wl,--wrap=parse_line) target_compile_options(test_networking PRIVATE -UNDEBUG) target_sources(test_networking PRIVATE src/openvpn/networking_sitnl.c src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/crypto_epoch.c src/openvpn/fdmisc.c src/openvpn/otime.c src/openvpn/packet_id.c ) endif () if (TARGET test_tls_crypt) target_link_options(test_tls_crypt PRIVATE -Wl,--wrap=parse_line) target_link_options(test_tls_crypt PRIVATE -Wl,--wrap=buffer_read_from_file -Wl,--wrap=buffer_write_file -Wl,--wrap=rand_bytes) target_sources(test_tls_crypt PRIVATE tests/unit_tests/openvpn/mock_win32_execve.c src/openvpn/argv.c src/openvpn/base64.c src/openvpn/crypto_epoch.c src/openvpn/crypto_mbedtls.c src/openvpn/crypto_openssl.c src/openvpn/crypto.c src/openvpn/env_set.c src/openvpn/otime.c src/openvpn/packet_id.c src/openvpn/run_command.c ) endif () if (TARGET test_pkcs11) target_compile_options(test_pkcs11 PRIVATE -DP11TOOL_PATH=\"${P11TOOL}\" -DSOFTHSM2_MODULE_PATH=\"${SOFTHSM2_MODULE}\" -DSOFTHSM2_UTIL_PATH=\"${SOFTHSM2_UTIL}\" ) target_sources(test_pkcs11 PRIVATE tests/unit_tests/openvpn/mock_get_random.c tests/unit_tests/openvpn/pkey_test_utils.c src/openvpn/argv.c src/openvpn/base64.c src/openvpn/env_set.c src/openvpn/otime.c src/openvpn/pkcs11.c src/openvpn/pkcs11_openssl.c src/openvpn/run_command.c src/openvpn/xkey_helper.c src/openvpn/xkey_provider.c ) endif () endif (BUILD_TESTING) ================================================ FILE: CMakePresets.json ================================================ { "version": 3, "configurePresets": [ { "name": "base", "hidden": true, "cacheVariables": { "CMAKE_TOOLCHAIN_FILE": { "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", "type": "FILEPATH" }, "VCPKG_OVERLAY_TRIPLETS": { "value": "${sourceDir}/contrib/vcpkg-triplets", "type": "FILEPATH" }, "VCPKG_OVERLAY_PORTS": { "value": "${sourceDir}/contrib/vcpkg-ports", "type": "FILEPATH" } } }, { "name": "base-windows", "hidden": true, "binaryDir": "${sourceDir}/out/build/${presetName}", "generator": "Visual Studio 17 2022", "cacheVariables": { "VCPKG_MANIFEST_DIR": "${sourceDir}/contrib/vcpkg-manifests/windows", "VCPKG_HOST_TRIPLET": "x64-windows" }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Windows" ] } } }, { "name": "base-mingw", "hidden": true, "generator": "Ninja Multi-Config", "cacheVariables": { "CMAKE_SYSTEM_NAME": { "value": "Windows", "type": "STRING" }, "VCPKG_MANIFEST_DIR": "${sourceDir}/contrib/vcpkg-manifests/mingw" } }, { "name": "x64", "hidden": true, "architecture": { "value": "x64", "strategy": "set" }, "cacheVariables": { "VCPKG_TARGET_TRIPLET": "x64-windows-ovpn" } }, { "name": "x64-mingw", "hidden": true, "binaryDir": "out/build/mingw/x64", "cacheVariables": { "CMAKE_C_COMPILER": { "value": "x86_64-w64-mingw32-gcc", "type": "STRING" }, "CMAKE_CXX_COMPILER": { "value": "x86_64-w64-mingw32-g++", "type": "STRING" }, "VCPKG_TARGET_TRIPLET": "x64-mingw-ovpn" } }, { "name": "arm64", "hidden": true, "architecture": { "value": "arm64", "strategy": "set" }, "cacheVariables": { "VCPKG_TARGET_TRIPLET": "arm64-windows-ovpn" } }, { "name": "x86", "hidden": true, "architecture": { "value": "Win32", "strategy": "set" }, "cacheVariables": { "VCPKG_TARGET_TRIPLET": "x86-windows-ovpn" } }, { "name": "i686-mingw", "hidden": true, "binaryDir": "out/build/mingw/x86", "cacheVariables": { "CMAKE_C_COMPILER": { "value": "i686-w64-mingw32-gcc", "type": "STRING" }, "CMAKE_CXX_COMPILER": { "value": "i686-w64-mingw32-g++", "type": "STRING" }, "VCPKG_TARGET_TRIPLET": "x86-mingw-ovpn" } }, { "name": "debug", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } }, { "name": "release", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, { "name": "clangtoolset", "toolset": "ClangCL" }, { "name": "mingw-x64", "inherits": [ "base", "base-mingw", "x64-mingw" ] }, { "name": "mingw-x86", "inherits": [ "base", "base-mingw", "i686-mingw" ] }, { "name": "win-amd64-release", "inherits": [ "base", "base-windows", "x64", "release" ] }, { "name": "win-amd64-clang-release", "inherits": [ "base", "base-windows", "clangtoolset", "x64", "release" ] }, { "name": "win-arm64-release", "inherits": [ "base", "base-windows", "arm64", "release" ] }, { "name": "win-x86-release", "inherits": [ "base", "base-windows", "x86", "release" ] }, { "name": "win-x86-clang-release", "inherits": [ "base", "base-windows", "clangtoolset", "x86", "release" ] }, { "name": "win-amd64-debug", "inherits": [ "base", "base-windows", "x64", "debug" ] }, { "name": "win-amd64-clang-debug", "inherits": [ "base", "base-windows", "clangtoolset", "x64", "debug" ] }, { "name": "win-arm64-debug", "inherits": [ "base", "base-windows", "arm64", "debug" ] }, { "name": "win-x86-debug", "inherits": [ "base", "base-windows", "x86", "debug" ] }, { "name": "win-x86-clang-debug", "inherits": [ "base", "base-windows", "clangtoolset", "x86", "debug" ] }, { "name": "unix-native", "generator": "Ninja Multi-Config", "binaryDir": "out/build/unix" } ], "buildPresets": [ { "name": "mingw-x64", "configurePreset": "mingw-x64" }, { "name": "mingw-x86", "configurePreset": "mingw-x86" }, { "name": "win-amd64-release", "configurePreset": "win-amd64-release", "configuration": "Release" }, { "name": "win-amd64-clang-release", "configurePreset": "win-amd64-clang-release", "configuration": "Release" }, { "name": "win-arm64-release", "configurePreset": "win-arm64-release", "configuration": "Release" }, { "name": "win-x86-release", "configurePreset": "win-x86-release", "configuration": "Release" }, { "name": "win-x86-clang-release", "configurePreset": "win-x86-clang-release", "configuration": "Release" }, { "name": "win-amd64-debug", "configurePreset": "win-amd64-debug", "configuration": "Debug" }, { "name": "win-amd64-clang-debug", "configurePreset": "win-amd64-clang-debug", "configuration": "Debug" }, { "name": "win-arm64-debug", "configurePreset": "win-arm64-debug", "configuration": "Debug" }, { "name": "win-x86-debug", "configurePreset": "win-x86-debug", "configuration": "Debug" }, { "name": "win-x86-clang-debug", "configurePreset": "win-x86-clang-debug", "configuration": "Debug" }, { "name": "unix-native", "configurePreset": "unix-native" } ], "testPresets": [ { "name": "win-amd64-release", "configurePreset": "win-amd64-release" }, { "name": "win-amd64-clang-release", "configurePreset": "win-amd64-clang-release" }, { "name": "win-x86-release", "configurePreset": "win-x86-release" }, { "name": "win-x86-clang-release", "configurePreset": "win-x86-clang-release" }, { "name": "win-amd64-debug", "configurePreset": "win-amd64-debug" }, { "name": "win-amd64-clang-debug", "configurePreset": "win-amd64-clang-debug" }, { "name": "win-x86-debug", "configurePreset": "win-x86-debug" }, { "name": "win-x86-clang-debug", "configurePreset": "win-x86-clang-debug" }, { "name": "unix-native", "configurePreset": "unix-native" } ] } ================================================ FILE: CONTRIBUTING.rst ================================================ CONTRIBUTING TO THE OPENVPN PROJECT =================================== Patches should be written against the Git "master" branch. Some patches may get backported to a release branch. The preferred procedure is to send patches to the "openvpn-devel" mailing list: - https://lists.sourceforge.net/lists/listinfo/openvpn-devel Instead of directly sending patches to the list you can also create an account in our instance of the Gerrit review tool: https://gerrit.openvpn.net/ See https://community.openvpn.net/Development/GerritBestPractices. While we do not merge GitHub pull requests as-is, we do allow their use for code review purposes. After the patch has been ACKed (reviewed and accepted), it must be sent to the mailing list. This last step does not necessarily need to be done by the patch author, although that is definitely recommended. When sending patches to "openvpn-devel" the subject line should be prefixed with ``[PATCH]``. To avoid merging issues the patches should be generated with git-format-patch or sent using git-send-email. Try to split large patches into small, atomic pieces to make reviews easier. Please make sure that the source code formatting follows the guidelines at https://community.openvpn.net/Development/CodeStyle. Automated checking can be done with clang-format (https://community.openvpn.net/Development/CodeStyle) and the configuration file which can be found in the git repository at ``.clang-format``. There is also a git pre-commit hook script, which runs clang-format automatically each time you commit and lets you format your code conveniently, if needed. To install the hook simply run: ``dev-tools/git-pre-commit-format.sh install`` If you want quick feedback on a patch before sending it to openvpn-devel mailing list, you can visit the #openvpn-devel channel on irc.libera.chat. Note that you need to be logged in to Libera to join the channel: - https://libera.chat/guides/registration More detailed contribution instructions are available here: - https://community.openvpn.net/Development/DeveloperDocumentation Note that the process for contributing to other OpenVPN projects such as openvpn-build, openvpn-gui, tap-windows6 and easy-rsa may differ from what was described above. Please refer to the contribution instructions of each respective project. ================================================ FILE: COPYING ================================================ OpenVPN (TM) -- An Open Source VPN daemon Copyright (C) 2002-2026 OpenVPN Inc This distribution contains multiple components, some of which fall under different licenses. By using OpenVPN or any of the bundled components enumerated below, you agree to be bound by the conditions of the license for each respective component. OpenVPN trademark ----------------- "OpenVPN" is a trademark of OpenVPN Inc OpenVPN license: ---------------- OpenVPN is distributed under the GPL license version 2. Special exception for linking OpenVPN with OpenSSL: In addition, as a special exception, OpenVPN Inc gives permission to link the code of this program with the OpenSSL library (or with modified versions of OpenSSL that use the same license as OpenSSL), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than OpenSSL. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. Apache2 linking exception: --------------------------- In addition, as a special exception, OpenVPN Inc and the contributors give permission to link the code of this program to libraries (the "Libraries") licensed under the Apache License version 2.0 (this work and any linked library the "Combined Work") and copy and distribute the Combined Work without an obligation to license the Libraries under the GNU General Public License v2 (GPL-2.0) as required by Section 2 of the GPL-2.0, and without an obligation to refrain from imposing any additional restrictions in the Apache License version 2 that are not in the GPL-2.0, as required by Section 6 of the GPL-2.0. You must comply with the GPL-2.0 in all other respects for the Combined Work, including the obligation to provide source code. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. For better understanding, in plain non-legalese English this basically says: * The intention for this license exception is to allow OpenVPN to be linked against APL-2 licensed libraries, even where the GPL-2.0 and APL-2 licenses conflict from a legal perspective. * OpenVPN itself will stay GPL-2.0 and the code belonging to the OpenVPN project must comply to the GPL-2.0 license. This is NOT dual-licensing of the OpenVPN code base. * This license exception DOES NOT require NOR expect a license change of the APL-2 based library. This exception allows using the APL-2 library as-is. However, when distributing a compiled OpenVPN binary linking against APL-2 libraries ("Combined Work"), the REQUIREMENT is that the APL-2 library MUST also be available on similar terms as in GPL-2.0, like providing the source code of the library upon request, except in the two specific ways mentioned. * If the APL-2 based library forbids such linking and distribution, this license exception DOES NOT overrule the restriction of the APL-2 based library. If the APL-2 library cannot satisfy the requirements in this license exception, you CANNOT distribute an OpenVPN binary linked with this library. LZO linking exception: ---------------------- LZO is Copyright (C) Markus F.X.J. Oberhumer, and is licensed under the GPL. Special exception for linking OpenVPN with both OpenSSL and LZO: Hereby I grant a special exception to the OpenVPN project (https://openvpn.net/) to link the LZO library with the OpenSSL library (https://www.openssl.org). Markus F.X.J. Oberhumer ================================================ FILE: COPYRIGHT.GPL ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Moe Ghoul, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: ChangeLog ================================================ OpenVPN ChangeLog Copyright (C) 2002-2026 OpenVPN Inc this marks the start of the 2.8 development cycle up to the first formal 2.8 pre-release, this file will not be maintained - please look at "git log" or "git shortlog v2.7.0..HEAD" to see what was changed. ================================================ FILE: Changes.rst ================================================ Overview of changes in 2.8 ========================== Overview of changes in 2.7 ========================== New features ------------ Multi-socket support for servers OpenVPN servers now can listen on multiple sockets at the same time. Multiple ``--local`` statements in the configuration can be used to configure this. This way the same server can e.g. listen for UDP and TCP connections at the same time, or listen on multiple addresses and/or ports. Client implementations for DNS options sent by server for Linux/BSD/macOS Linux, BSD and macOS versions of OpenVPN now ship with a per-platform default ``--dns-updown`` script that implements proper handling of DNS configuration sent by the server. The scripts should work on systems that use ``systemd`` or ``resolveconf`` to manage the DNS setup, as well as raw ``/etc/resolv.conf`` files. However, the exact features supported will depend on the configuration method. On Linux and MacOS this should usually make split-DNS configurations supported out-of-the-box now. Note that this new script will not be used by default if a ``--up`` script is already in use to reduce problems with backwards compatibility. See documentation for ``--dns-updown`` and ``--dns`` for more details. New client implementation for DNS options sent by server for Windows The Windows client now uses NRPT (Name Resolution Policy Table) to handle DNS configurations. This adds support for split-DNS and DNSSEC and improves the compatbility with local DNS resolvers. Requires the interactive service. On Windows the ``block-local`` flag is now enforced with WFP filters. The ``block-local`` flag to ``--redirect-gateway`` and ``--redirect-private`` is now also enforced via the Windows Firewall, making sure packets can't be sent to the local network. This provides stronger protection against TunnelCrack-style attacks. Windows network adapters are now generated on demand This means that on systems that run multiple OpenVPN connections at the same time the users don't need to manually create enough network adapters anymore (in addition to the ones created by the installer). Windows automatic service now runs as an unpriviledged user All tasks that need privileges are now delegated to the interactive service. **NOTE** this has the risk of breaking existing setups if the Windows certificate store is used (cryptoapi), and the certificates are not readable for ``NT SERVICE\OpenVPNService``. Support for new version of Linux DCO module OpenVPN DCO module is moving upstream and being merged into the main Linux kernel. For this process some API changes were required. OpenVPN 2.7 will only support the new API. The new module is called ``ovpn``. Out-of-tree builds for older kernels are available. Please see the release announcements for futher information. Support for server mode in win-dco driver On Windows the win-dco driver can now be used in server setups. Support for TLS client floating in DCO implementations The kernel modules will detect clients floating to a new IP address and notify userland so both data packets (kernel) and TLS packets (sent by userland) can reach the new client IP. (Actual support depends on recent-enough kernel implementation) Enforcement of AES-GCM usage limit OpenVPN will now enforce the usage limits on AES-GCM with the same confidentiality margin as TLS 1.3 does. This mean that renegotiation will be triggered after roughly 2^28 to 2^31 packets depending of the packet size. More details about usage limit of AES-GCM can be found here: https://datatracker.ietf.org/doc/draft-irtf-cfrg-aead-limits/ Epoch data keys and packet format This introduces the epoch data format for AEAD data channel ciphers in TLS mode ciphers. This new data format has a number of improvements over the standard "DATA_V2" format. - AEAD tag at the end of packet which is more hardware implementation friendly - Automatic key switchover when cipher usage limits are hit, similar to the epoch data keys in (D)TLS 1.3 - 64 bit instead of 32 bit packet ids to allow the data channel to be ready for 10 GBit/s without having frequent renegotiation - IV constructed with XOR instead of concatenation to not have (parts) of the real IV on the wire Support for Epoch data channel on Windows, using the win-dco driver (2.8.0+) Default ciphers in ``--data-ciphers`` Ciphers in ``--data-ciphers`` can contain the string DEFAULT that is replaced by the default ciphers used by OpenVPN, making it easier to add an allowed cipher without having to spell out the default ciphers. TLS alerts OpenVPN 2.7 will send out TLS alerts to peers informing them if the TLS session shuts down or when the TLS implementation informs the peer about an error in the TLS session (e.g. mismatching TLS versions). This improves the user experience as the client shows an error instead of running into a timeout when the server just stops responding completely. Support for tun/tap via unix domain socket and lwipovpn support To allow better testing and emulating a full client with a full network stack OpenVPN now allows a program executed to provide a tun/tap device instead of opening a device. The co-developed lwipovpn program based on lwIP stack allows to simulate full IP stack. An OpenVPN client using ``--dev-node unix:/path/to/lwipovpn`` can emulate a full client that can be pinged, can serve a website and more without requiring any elevated permission. This can make testing OpenVPN much easier. For more details see `lwipovpn on Github `_. Allow overriding username with ``--override-username`` This is intended to allow using ``--auth-gen-token`` in scenarios where the clients use certificates and multi-factor authentication. This will also generate a ``push "auth-token-user newusername"`` directive in push replies. ``--port-share`` now properly supports IPv6 Issues with logging of IPv6 addresses were fixed. The feature now allows IPv6 connections towards the proxy receiver. Support for Haiku OS TLS1.3 support with mbedTLS (requires mbedTLS >= 3.6.4) PUSH_UPDATE client support It is now possible to update parts of the client-side configuration (IP address, routes, MTU, DNS) by sending a new server-to-client control message, ``PUSH_UPDATE,``. See also: https://openvpn.github.io/openvpn-rfc/openvpn-wire-protocol.html NOTE: PUSH_UPDATE client support is currently disabled if DCO is active (on all platforms). PUSH_UPDATE server support (minimal) New management interface commands ``push-update-broad`` and ``push-update-cid`` to send PUSH_UPDATE option updates to all clients ("there is a new DNS server") or only a specific client ID ("privileges have changed, here's a new IP address"). See doc/management-notes.txt NOTE: PUSH_UPDATE server support is currently disabled if DCO is active (on all platforms). Support for user-defined routing tables on Linux See the ``--route-table`` option in the manpage PQE support for WolfSSL Two new environment variables have been introduced to communicate desired default gateway redirection to plugins like Network Manager, ``route_redirect_gateway_ipv4`` and ``route_redirect_gateway_ipv6``. See the "Environmental Variables" section in the man page Improved logging of service events/errors to event log on Windows. "Recursive Routing" check is now more granular, and will only drop packets-in-tunnel if destination IP, protocol and port matches with those needed to reach the VPN server. With that change, you can now use policies that direct "everything that is not OpenVPN" into the tunnel, and have IP packets to the VPN server address arrive as expected (no such policies are currently installed by OpenVPN) (GH: OpenVPN/openvpn#669). COPYING: license details only relevant to our Windows installers have been updated and moved to the openvpn-build repo Improved BYTECOUNT support - more strictly adhere to timing interval requested, correctly support client and server counters with Linux and Windows DCO offloading. Improve compatibility with OpenSSL 3.6.0 (do not fail t_lpback selftest) New option ``--tls-crypt-v2-max-age n`` to check tls-crypt-v2 timestamps (When a client is older than n days or has no timestamp, the server will reject it) mbedTLS 4 support has been added. Note that with mbedTLS 4 algorithms need to be translated to mbedTLS 4 internal IDs by OpenVPN, and some names might be missing. Deprecated features ------------------- ``secret`` support has been removed (by default). static key mode (non-TLS) is no longer considered "good and secure enough" for today's requirements. Use TLS mode instead. If deploying a PKI CA is considered "too complicated", using ``--peer-fingerprint`` makes TLS mode about as easy as using ``--secret``. This mode can still be enabled by using ``--allow-deprecated-insecure-static-crypto`` but will be removed in OpenVPN 2.8. Support for wintun Windows driver has been removed. OpenVPN 2.6 added support for the new dco-win driver, so it supported three different device drivers: dco-win, wintun, and tap-windows6. OpenVPN 2.7 now drops the support for wintun driver. By default all modern configs should be supported by dco-win driver. In all other cases OpenVPN will fall back automatically to tap-windows6 driver. NTLMv1 authentication support for HTTP proxies has been removed. This is considered an insecure method of authentication that uses obsolete crypto algorithms. NTLMv2 support is still available, but will be removed in a future release. When configured to authenticate with NTLMv1 (``ntlm`` keyword in ``--http-proxy``) OpenVPN will try NTLMv2 instead. ``persist-key`` option has been enabled by default. All the keys will be kept in memory across restart. OpenSSL 1.0.2 support has been removed. Support for building with OpenSSL 1.0.2 has been removed. The minimum supported OpenSSL version is now 1.1.0. mbedTLS 2.x support has been removed Support for building with mbedTLS 2.x has been removed (it is out of support since March 2025, and the necessary compatibility code is making maintenance and support for mbedTLS 4.x hard). The minimum supported mbedTLS version is now 3.2.1. Compression on send has been removed. OpenVPN 2.7 will never compress data before sending. Decompression of received data is still supported. ``--allow-compression yes`` is now an alias for ``--allow-compression asym``. ``--memstats`` feature removed The ``--memstats`` option was largely undocumented and there is no known user of this feature. This feature provided very limited statistics (number of users, link bytes read/written) and we do not except any usage because of this. Using ``--push`` in a mode that is not ``--mode server`` will now print a clear warning that this is an unsupported operation and might cause negotiation failures. ``--reneg-bytes`` and ``--reneg-packets`` do not work in DCO mode, and will now print an appropriate warning. On-connect resolving of ``--remote`` addresses in ``--tcp-server`` mode was not working since 2.4, so the code was completely removed. User-visible Changes -------------------- - Default for ``--topology`` changed to ``subnet`` for ``--mode server``. Previous releases always used ``net30`` as default. This only affects configs with ``--mode server`` or ``--server`` (the latter implies the former), and ``--dev tun``, and only if IPv4 is enabled. Note that this changes the semantics of ``--ifconfig``, so if you have manual settings for that in your config but not set ``--topology`` your config might fail to parse with the new version. Just adding ``--topology net30`` to the config should fix the problem. By default ``--topology`` is pushed from server to client. - ``--x509-username-field`` will no longer automatically convert fieldnames to uppercase. This was deprecated since OpenVPN 2.4, and has now been removed. - ``--dh none`` is now the default if ``--dh`` is not specified. Modern TLS implementations will prefer ECDH and other more modern algorithms anyway. And finite field Diffie Hellman is in the proces of being deprecated (see draft-ietf-tls-deprecate-obsolete-kex) - ``--lport 0`` does not imply ``--bind`` anymore. - ``--redirect-gateway`` now works correctly if the VPN remote is not reachable by the default gateway. - ``--show-gateway`` now supports querying the gateway for IPv4 addresses. - ``--static-challenge`` option now has a third parameter ``format`` that can change how password and challenge response should be combined. - ``--key`` and ``--cert`` now accept URIs implemented in OpenSSL 3 as well as optional OpenSSL 3 providers loaded using ``--providers`` option. - ``--cryptoapicert`` now supports issuer name as well as Windows CA template name or OID as selector string. - TLS handshake debugging information contains much more details now when using recent versions of OpenSSL. - The ``IV_PLAT_VER`` variable sent by Windows clients now contains the full Windows build version to make it possible to determine the Windows 10 or Windows 11 version used. - The ``--windows-driver`` option to select between various windows drivers will no longer do anything - it's kept so existing configs will not become invalid, but it is ignored with a warning. The default is now ``ovpn-dco`` if all options used are compatible with DCO, with a fallback to ``tap-windows6``. To force TAP (for example because a server pushes DCO incompatible options), use the ``--disable-dco`` option. - Apply more checks to incoming TLS handshake packets before creating new state - namely, verify message ID / acked ID for "valid range for an initial packet". This fixes a problem with clients that float very early but send control channel packet from the pre-float IP (Github: OpenVPN/openvpn#704). - Use of ``--dh dh2048.pem`` in all sample configs has been replaced with ``--dh none``. The ``dh2048.pem`` file has been removed. - The startup delay in ``t_client.sh`` has been reduced from 3s to 1s, making a noticeable difference for setups with many tests. - Changed from using ``uncrustify`` for code formatting and pre-commit checks to ``clang-format``. This reformatted quite a bit of code, and requires that regular committers change their pre-commit checks accordingly. - On Linux, on interfaces where applicable, OpenVPN explicitly configures the broadcast address again. This was dropped for 2.6.0 "because computers are smart and can do it themselves", but the kernel netlink interface isn't, and will install "0.0.0.0". This does not normally matter, but for broadcast-based applications that get the address to use from "ifconfig", this change repairs functionality (this has been backported to 2.6.15, but is not in earlier 2.6 versions). - ``max-routes-per-client 0`` used to be silently upgraded to ``1``. This now produces an error. - ``ifconfig`` and ``ifconfig-ipv6`` values are now stored in pre-connect options cache, and will be restored to pre-connect values on reconnects if the server stops pushing the respective option. - ``tapctl.exe`` helper binary on Windows has been reworked to improve help texts (making clear that it can not only do TAP-Adapters but Win-DCO as well), add printing of the hwid to all adapter outputs, and change the default adapter type created to ``ovpn-dco``. - The default for ``multihome`` egress interface handling has changed. 2.7.0 will default to ipi_ifindex=0, that is, leave the decision to the routing/policy setup of the operating system. The pre-2.7 behaviour (force egress = ingress interface) can be achieved with the new ``--multihome same-interface`` sub-option. - Windows ``openvpn.exe`` binary manifest now sets code page UTF8 - which has no direct effect on OpenVPN itself, but this repairs OpenSSL file loading for key/cert files with non-ASCII characters in their file names (GH: OpenVPN/openvpn#920). - The ``test-crypto`` option no longer requires a ``--secret`` argument and will automatically generate a random key. - The configure-time option ``--enable-x509-alt-username`` is no longer conditional, and always-on (GH: OpenVPN/openvpn#917). Deprecated features ------------------- ``--opt-verify`` feature removed This option was already deprecated and it is now being converted to a no-op. Using this option will only print a warning. Overview of changes in 2.6 ========================== Project changes --------------- We want to deprecate our old Trac bug tracking system. Please report any issues with this release in GitHub instead: https://github.com/OpenVPN/openvpn/issues New features ------------ Support unlimited number of connection entries and remote entries New management commands to enumerate and list remote entries Use ``remote-entry-count`` and ``remote-entry-get`` commands from the management interface to get the number of remote entries and the entries themselves. Keying Material Exporters (RFC 5705) based key generation As part of the cipher negotiation OpenVPN will automatically prefer the RFC5705 based key material generation to the current custom OpenVPN PRF. This feature requires OpenSSL or mbed TLS 2.18+. Compatibility with OpenSSL in FIPS mode OpenVPN will now work with OpenSSL in FIPS mode. Note, no effort has been made to check or implement all the requirements/recommendation of FIPS 140-2. This just allows OpenVPN to be run on a system that be configured OpenSSL in FIPS mode. ``mlock`` will now check if enough memlock-able memory has been reserved, and if less than 100MB RAM are available, use setrlimit() to upgrade the limit. See Trac #1390. Not available on OpenSolaris. Certificate pinning/verify peer fingerprint The ``--peer-fingerprint`` option has been introduced to give users an easy to use alternative to the ``tls-verify`` for matching the fingerprint of the peer. The option takes use a number of allowed SHA256 certificate fingerprints. See the man page section "Small OpenVPN setup with peer-fingerprint" for a tutorial on how to use this feature. This is also available online under https://github.com/openvpn/openvpn/blob/master/doc/man-sections/example-fingerprint.rst TLS mode with self-signed certificates When ``--peer-fingerprint`` is used, the ``--ca`` and ``--capath`` option become optional. This allows for small OpenVPN setups without setting up a PKI with Easy-RSA or similar software. Deferred auth support for scripts The ``--auth-user-pass-verify`` script supports now deferred authentication. Pending auth support for plugins and scripts Both auth plugin and script can now signal pending authentication to the client when using deferred authentication. The new ``client-crresponse`` script option and ``OPENVPN_PLUGIN_CLIENT_CRRESPONSE`` plugin function can be used to parse a client response to a ``CR_TEXT`` two factor challenge. See ``sample/sample-scripts/totpauth.py`` for an example. Compatibility mode (``--compat-mode``) The modernisation of defaults can impact the compatibility of OpenVPN 2.6.0 with older peers. The options ``--compat-mode`` allows UIs to provide users with an easy way to still connect to older servers. OpenSSL 3.0 support OpenSSL 3.0 has been added. Most of OpenSSL 3.0 changes are not user visible but improve general compatibility with OpenSSL 3.0. ``--tls-cert-profile insecure`` has been added to allow selecting the lowest OpenSSL security level (not recommended, use only if you must). OpenSSL 3.0 no longer supports the Blowfish (and other deprecated) algorithm by default and the new option ``--providers`` allows loading the legacy provider to renable these algorithms. Optional ciphers in ``--data-ciphers`` Ciphers in ``--data-ciphers`` can now be prefixed with a ``?`` to mark those as optional and only use them if the SSL library supports them. Improved ``--mssfix`` and ``--fragment`` calculation The ``--mssfix`` and ``--fragment`` options now allow an optional :code:`mtu` parameter to specify that different overhead for IPv4/IPv6 should taken into account and the resulting size is specified as the total size of the VPN packets including IP and UDP headers. Cookie based handshake for UDP server Instead of allocating a connection for each client on the initial packet OpenVPN server will now use an HMAC based cookie as its session id. This way the server can verify it on completing the handshake without keeping state. This eliminates the amplification and resource exhaustion attacks. For tls-crypt-v2 clients, this requires OpenVPN 2.6 clients or later because the client needs to resend its client key on completing the hand shake. The tls-crypt-v2 option allows controlling if older clients are accepted. By default the rate of initial packet responses is limited to 100 per 10s interval to avoid OpenVPN servers being abused in reflection attacks (see ``--connect-freq-initial``). Data channel offloading with ovpn-dco 2.6.0+ implements support for data-channel offloading where the data packets are directly processed and forwarded in kernel space thanks to the ovpn-dco kernel module. The userspace openvpn program acts purely as a control plane application. Note that DCO will use DATA_V2 packets in P2P mode, therefore, this implies that peers must be running 2.6.0+ in order to have P2P-NCP which brings DATA_V2 packet support. Session timeout It is now possible to terminate a session (or all) after a specified amount of seconds has passed session commencement. This behaviour can be configured using ``--session-timeout``. This option can be configured on the server, on the client or can also be pushed. Inline auth username and password Username and password can now be specified inline in the configuration file within the tags. If the password is missing OpenVPN will prompt for input via stdin. This applies to inline'd http-proxy-user-pass too. Tun MTU can be pushed The client can now also dynamically configure its MTU and the server will try to push the client MTU when the client supports it. The directive ``--tun-mtu-max`` has been introduced to increase the maximum pushable MTU size (defaults to 1600). Dynamic TLS Crypt When both peers are OpenVPN 2.6.1+, OpenVPN will dynamically create a tls-crypt key that is used for renegotiation. This ensure that only the previously authenticated peer can do trigger renegotiation and complete renegotiations. Improved control channel packet size control (``max-packet-size``) The size of control channel is no longer tied to ``--link-mtu``/``--tun-mtu`` and can be set using ``--max-packet-size``. Sending large control channel frames is also optimised by allowing 6 outstanding packets instead of just 4. ``max-packet-size`` will also set ``mssfix`` to try to limit data-channel packets as well. Deprecated features ------------------- ``inetd`` has been removed This was a very limited and not-well-tested way to run OpenVPN, on TCP and TAP mode only. ``verify-hash`` has been deprecated This option has very limited usefulness and should be replaced by either a better ``--ca`` configuration or with a ``--tls-verify`` script. ``secret`` has been deprecated static key mode (non-TLS) is no longer considered "good and secure enough" for today's requirements. Use TLS mode instead. If deploying a PKI CA is considered "too complicated", using ``--peer-fingerprint`` makes TLS mode about as easy as using ``--secret``. ``ncp-disable`` has been removed This option mainly served a role as debug option when NCP was first introduced. It should now no longer be necessary. TLS 1.0 and 1.1 are deprecated ``tls-version-min`` is set to 1.2 by default. OpenVPN 2.6.0 defaults to a minimum TLS version of 1.2 as TLS 1.0 and 1.1 should be generally avoided. Note that OpenVPN versions older than 2.3.7 use TLS 1.0 only. ``--cipher`` argument is no longer appended to ``--data-ciphers`` by default. Data cipher negotiation has been introduced in 2.4.0 and been significantly improved in 2.5.0. The implicit fallback to the cipher specified in ``--cipher`` has been removed. Effectively, ``--cipher`` is a no-op in TLS mode now, and will only have an effect in pre-shared-key mode (``--secret``). From now on ``--cipher`` should not be used in new configurations for TLS mode. Should backwards compatibility with older OpenVPN peers be required, please see the ``--compat-mode`` instead. ``--prng`` has beeen removed OpenVPN used to implement its own PRNG based on a hash. However implementing a PRNG is better left to a crypto library. So we use the PRNG mbed TLS or OpenSSL now. ``--keysize`` has been removed The ``--keysize`` option was only useful to change the key length when using the BF, CAST6 or RC2 ciphers. For all other ciphers the key size is fixed with the chosen cipher. As OpenVPN v2.6 no longer supports any of these variable length ciphers, this option was removed as well to avoid confusion. Compression no longer enabled by default Unless an explicit compression option is specified in the configuration, ``--allow-compression`` defaults to ``no`` in OpeNVPN 2.6.0. By default, OpenVPN 2.5 still allowed a server to enable compression by pushing compression related options. PF (Packet Filtering) support has been removed The built-in PF functionality has been removed from the code base. This feature wasn't really easy to use and was long unmaintained. This implies that also ``--management-client-pf`` and any other compile time or run time related option do not exist any longer. Option conflict checking is being deprecated and phased out The static option checking (OCC) is no longer useful in typical setups that negotiate most connection parameters. The ``--opt-verify`` and ``--occ-disable`` options are deprecated, and the configure option ``--enable-strict-options`` has been removed. Logging of mismatched options has been moved to debug logging (verb 7). User-visible Changes -------------------- - CHACHA20-POLY1305 is included in the default of ``--data-ciphers`` when available. - Option ``--prng`` is ignored as we rely on the SSL library random number generator. - Option ``--nobind`` is default when ``--client`` or ``--pull`` is used in the configuration - :code:`link_mtu` parameter is removed from environment or replaced with 0 when scripts are called with parameters. This parameter is unreliable and no longer internally calculated. - control channel packet maximum size is no longer influenced by ``--link-mtu``/``--tun-mtu`` and must be set by ``--max-packet-size`` now. The default is 1250 for the control channel size. - In point-to-point OpenVPN setups (no ``--server``), using ``--explict-exit-notiy`` on one end would terminate the other side at session end. This is considered a no longer useful default and has been changed to "restart on reception of explicit-exit-notify message". If the old behaviour is still desired, ``--remap-usr1 SIGTERM`` can be used. - FreeBSD tun interfaces with ``--topology subnet`` are now put into real subnet mode (IFF_BROADCAST instead of IFF_POINTOPOINT) - this might upset software that enumerates interfaces, looking for "broadcast capable?" and expecting certain results. Normal uses should not see any difference. - The default configurations will no longer allow connections to OpenVPN 2.3.x peer or earlier, use the new ``--compat-mode`` option if you need compatibility with older versions. See the manual page on the ``--compat-mode`` for details. - The ``client-pending-auth`` management command now requires also the key id. The management version has been changed to 5 to indicate this change. - (OpenVPN 2.6.2) A client will now refuse a connection if pushed compression settings will contradict the setting of allow-compression as this almost always results in a non-working connection. - The "kill" by addr management command now requires also the protocol as string e.g. "udp", "tcp". Common errors with OpenSSL 3.0 and OpenVPN 2.6 ---------------------------------------------- Both OpenVPN 2.6 and OpenSSL 3.0 tighten the security considerable, so some configuration will no longer work. This section will cover the most common causes and error message we have seen and explain their reason and temporary workarounds. You should fix the underlying problems as soon as possible since these workaround are not secure and will eventually stop working in a future update. - weak SHA1 or MD5 signature on certificates This will happen on either loading of certificates or on connection to a server:: OpenSSL: error:0A00018E:SSL routines::ca md too weak Cannot load certificate file cert.crt Exiting due to fatal error OpenSSL 3.0 no longer allows weak signatures on certificates. You can downgrade your security to allow them by using ``--tls-cert-profile insecure`` but should replace/regenerate these certificates as soon as possible. - 1024 bit RSA certificates, 1024 bit DH parameters, other weak keys This happens if you use private keys or other cryptographic material that does not meet today's cryptographic standards anymore. Messages are similar to:: OpenSSL: error:0A00018F:SSL routines::ee key too small OpenSSL: error:1408518A:SSL routines:ssl3_ctx_ctrl:dh key too small DH parameters (``--dh``) can be regenerated with ``openssl dhparam 2048``. For other cryptographic keys, these keys and certificates need to be regenerated. TLS Security level can be temporarily lowered with ``--tls-cert-profile legacy`` or even ``--tls-cert-profile insecure``. - Connecting to a OpenVPN 2.3.x server or allowing OpenVPN 2.3.x or earlier clients This will normally result in messages like:: OPTIONS ERROR: failed to negotiate cipher with server. Add the server's cipher ('AES-128-CBC') to --data-ciphers (currently 'AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305') if you want to connect to this server. or client/127.0.0.1:49954 SENT CONTROL [client]: 'AUTH_FAILED,Data channel cipher negotiation failed (no shared cipher)' (status=1) You can manually add the missing cipher to the ``--data-ciphers``. The standard ciphers should be included as well, e.g. ``--data-ciphers AES-256-GCM:AES-128-GCM:?Chacha20-Poly1305:?AES-128-CBC``. You can also use the ``--compat-mode`` option. Note that these message may also indicate other cipher configuration problems. See the data channel cipher negotiation manual section for more details. (Available online under https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/cipher-negotiation.rst) - Use of a legacy or deprecated cipher (e.g. 64bit block ciphers) OpenSSL 3.0 no longer supports a number of insecure and outdated ciphers in its default configuration. Some of these ciphers are known to be vulnerable (SWEET32 attack). This will typically manifest itself in messages like:: OpenSSL: error:0308010C:digital envelope routines::unsupported Cipher algorithm 'BF-CBC' not found Unsupported cipher in --data-ciphers: BF-CBC If your OpenSSL distribution comes with the legacy provider (see also ``man OSSL_PROVIDER-legacy``), you can load it with ``--providers legacy default``. This will re-enable the old algorithms. - OpenVPN version not supporting TLS 1.2 or later The default in OpenVPN 2.6 and also in many distributions is now TLS 1.2 or later. Connecting to a peer that does not support this will results in messages like:: TLS error: Unsupported protocol. This typically indicates that client and server have no common TLS version enabled. This can be caused by mismatched tls-version-min and tls-version-max options on client and server. If your OpenVPN client is between v2.3.6 and v2.3.2 try adding tls-version-min 1.0 to the client configuration to use TLS 1.0+ instead of TLS 1.0 only OpenSSL: error:0A000102:SSL routines::unsupported protocol This can be an OpenVPN 2.3.6 or earlier version. ``compat-version 2.3.0`` will enable TLS 1.0 support if supported by the OpenSSL distribution. Note that on some Linux distributions enabling TLS 1.1 or 1.0 is not possible. Overview of changes in 2.5 ========================== New features ------------ Client-specific tls-crypt keys (``--tls-crypt-v2``) ``tls-crypt-v2`` adds the ability to supply each client with a unique tls-crypt key. This allows large organisations and VPN providers to profit from the same DoS and TLS stack protection that small deployments can already achieve using ``tls-auth`` or ``tls-crypt``. ChaCha20-Poly1305 cipher support Added support for using the ChaCha20-Poly1305 cipher in the OpenVPN data channel. Improved Data channel cipher negotiation The option ``ncp-ciphers`` has been renamed to ``data-ciphers``. The old name is still accepted. The change in name signals that ``data-ciphers`` is the preferred way to configure data channel ciphers and the data prefix is chosen to avoid the ambiguity that exists with ``--cipher`` for the data cipher and ``tls-cipher`` for the TLS ciphers. OpenVPN clients will now signal all supported ciphers from the ``data-ciphers`` option to the server via ``IV_CIPHERS``. OpenVPN servers will select the first common cipher from the ``data-ciphers`` list instead of blindly pushing the first cipher of the list. This allows to use a configuration like ``data-ciphers ChaCha20-Poly1305:AES-256-GCM`` on the server that prefers ChaCha20-Poly1305 but uses it only if the client supports it. See the data channel negotiation section in the manual for more details. Removal of BF-CBC support in default configuration: By default OpenVPN 2.5 will only accept AES-256-GCM and AES-128-GCM as data ciphers. OpenVPN 2.4 allows AES-256-GCM,AES-128-GCM and BF-CBC when no --cipher and --ncp-ciphers options are present. Accepting BF-CBC can be enabled by adding data-ciphers AES-256-GCM:AES-128-GCM:BF-CBC and when you need to support very old peers also data-ciphers-fallback BF-CBC To offer backwards compatibility with older configs an *explicit* cipher BF-CBC in the configuration will be automatically translated into adding BF-CBC to the data-ciphers option and setting data-ciphers-fallback to BF-CBC (as in the example commands above). We strongly recommend to switching away from BF-CBC to a more secure cipher. Asynchronous (deferred) authentication support for auth-pam plugin. See src/plugins/auth-pam/README.auth-pam for details. Deferred client-connect The ``--client-connect`` option and the connect plugin API allow asynchronous/deferred return of the configuration file in the same way as the auth-plugin. Faster connection setup A client will signal in the ``IV_PROTO`` variable that it is in pull mode. This allows the server to push the configuration options to the client without waiting for a ``PULL_REQUEST`` message. The feature is automatically enabled if both client and server support it and significantly reduces the connection setup time by avoiding one extra packet round-trip and 1s of internal event delays. Netlink support On Linux, if configured without ``--enable-iproute2``, configuring IP addresses and adding/removing routes is now done via the netlink(3) kernel interface. This is much faster than calling ``ifconfig`` or ``route`` and also enables OpenVPN to run with less privileges. If configured with --enable-iproute2, the ``ip`` command is used (as in 2.4). Support for ``ifconfig`` and ``route`` is gone. Wintun support On Windows, OpenVPN can now use ``wintun`` devices. They are faster than the traditional ``tap9`` tun/tap devices, but do not provide ``--dev tap`` mode - so the official installers contain both. To use a wintun device, add ``--windows-driver wintun`` to your config (and use of the interactive service is required as wintun needs SYSTEM privileges to enable access). IPv6-only operation It is now possible to have only IPv6 addresses inside the VPN tunnel, and IPv6-only address pools (2.4 always required IPv4 config/pools and IPv6 was the "optional extra"). Improved Windows 10 detection Correctly log OS on Windows 10 now. Linux VRF support Using the new ``--bind-dev`` option, the OpenVPN outside socket can now be put into a Linux VRF. See the "Virtual Routing and Forwarding" documentation in the man page. TLS 1.3 support TLS 1.3 support has been added to OpenVPN. Currently, this requires OpenSSL 1.1.1+. The options ``--tls-ciphersuites`` and ``--tls-groups`` have been added to fine tune TLS protocol options. Most of the improvements were also backported to OpenVPN 2.4 as part of the maintainance releases. Support setting DHCP search domain A new option ``--dhcp-option DOMAIN-SEARCH my.example.com`` has been defined, and Windows support for it is implemented (tun/tap only, no wintun support yet). Other platforms need to support this via ``--up`` script (Linux) or GUI (OSX/Tunnelblick). per-client changing of ``--data-ciphers`` or ``data-ciphers-fallback`` from client-connect script/dir (NOTE: this only changes preference of ciphers for NCP, but can not override what the client announces as "willing to accept") Handle setting of tun/tap interface MTU on Windows If IPv6 is in use, MTU must be >= 1280 (Windows enforces IETF requirements) Add support for OpenSSL engines to access private key material (like TPM). HMAC based auth-token support The ``--auth-gen-token`` support has been improved and now generates HMAC based user token. If the optional ``--auth-gen-token-secret`` option is used clients will be able to seamlessly reconnect to a different server using the same secret file or to the same server after a server restart. Improved support for pending authentication The protocol has been enhanced to be able to signal that the authentication should use a secondary authentication via web (like SAML) or a two factor authentication without disconnecting the OpenVPN session with AUTH_FAILED. The session will instead be stay in a authenticated state and wait for the second factor authentication to complete. This feature currently requires usage of the managent interface on both client and server side. See the ``management-notes.txt`` ``client-pending-auth`` and ``cr-response`` commands for more details. VLAN support OpenVPN servers in TAP mode can now use 802.1q tagged VLANs on the TAP interface to separate clients into different groups that can then be handled differently (different subnets / DHCP, firewall zones, ...) further down the network. See the new options ``--vlan-tagging``, ``--vlan-accept``, ``--vlan-pvid``. 802.1q tagging on the client side TAP interface is not handled today (= tags are just forwarded transparently to the server). Support building of .msi installers for Windows Allow unicode search string in ``--cryptoapicert`` option (Windows) Support IPv4 configs with /31 netmasks now (By no longer trying to configure ``broadcast x.x.x.x`` in ifconfig calls, /31 support "just works") New option ``--block-ipv6`` to reject all IPv6 packets (ICMPv6) this is useful if the VPN service has no IPv6, but the clients might have (LAN), to avoid client connections to IPv6-enabled servers leaking "around" the IPv4-only VPN. ``--ifconfig-ipv6`` and ``--ifconfig-ipv6-push`` will now accept hostnames and do a DNS lookup to get the IPv6 address to use Deprecated features ------------------- For an up-to-date list of all deprecated options, see this wiki page: https://community.openvpn.net/openvpn/wiki/DeprecatedOptions - ``ncp-disable`` has been deprecated With the improved and matured data channel cipher negotiation, the use of ``ncp-disable`` should not be necessary anymore. - ``inetd`` has been deprecated This is a very limited and not-well-tested way to run OpenVPN, on TCP and TAP mode only, which complicates the code quite a bit for little gain. To be removed in OpenVPN 2.6 (unless users protest). - ``no-iv`` has been removed This option was made into a NOOP option with OpenVPN 2.4. This has now been completely removed. - ``--client-cert-not-required`` has been removed This option will now cause server configurations to not start. Use ``--verify-client-cert none`` instead. - ``--ifconfig-pool-linear`` has been removed This option is removed. Use ``--topology p2p`` or ``--topology subnet`` instead. - ``--compress xxx`` is considered risky and is warned against, see below. - ``--key-method 1`` has been removed User-visible Changes -------------------- - If multiple connect handlers are used (client-connect, ccd, connect plugin) and one of the handler succeeds but a subsequent fails, the client-disconnect-script is now called immediately. Previously it was called, when the VPN session was terminated. - Support for building with OpenSSL 1.0.1 has been removed. The minimum supported OpenSSL version is now 1.0.2. - The GET_CONFIG management state is omitted if the server pushes the client configuration almost immediately as result of the faster connection setup feature. - ``--compress`` is nowadays considered risky, because attacks exist leveraging compression-inside-crypto to reveal plaintext (VORACLE). So by default, ``--compress xxx`` will now accept incoming compressed packets (for compatibility with peers that have not been upgraded yet), but will not use compression outgoing packets. This can be controlled with the new option ``--allow-compression yes|no|asym``. - Stop changing ``--txlen`` aways from OS defaults unless explicitly specified in config file. OS defaults nowadays are actually larger then what we used to configure, so our defaults sometimes caused packet drops = bad performance. - remove ``--writepid`` pid file on exit now - plugin-auth-pam now logs via OpenVPN logging method, no longer to stderr (this means you'll have log messages in syslog or openvpn log file now) - use ISO 8601 time format for file based logging now (YYYY-MM-DD hh:mm:dd) (syslog is not affected, nor is ``--machine-readable-output``) - ``--clr-verify`` now loads all CRLs if more than one CRL is in the same file (OpenSSL backend only, mbedTLS always did that) - when ``--auth-user-pass file`` has no password, and the management interface is active, query management interface (instead of trying console query, which does not work on windows) - skip expired certificates in Windows certificate store (``--cryptoapicert``) - ``--socks-proxy`` + ``--proto udp*`` will now allways use IPv4, even if IPv6 is requested and available. Our SOCKS code does not handle IPv6+UDP, and before that change it would just fail in non-obvious ways. - TCP listen() backlog queue is now set to 32 - this helps TCP servers that receive lots of "invalid" connects by TCP port scanners - do no longer print OCC warnings ("option mismatch") about ``key-method``, ``keydir``, ``tls-auth`` and ``cipher`` - these are either gone now, or negotiated, and the warnings do not serve a useful purpose. - ``dhcp-option DNS`` and ``dhcp-option DNS6`` are now treated identically (= both accept an IPv4 or IPv6 address for the nameserver) Maintainer-visible changes -------------------------- - the man page is now in maintained in .rst format, so building the openvpn.8 manpage from a git checkout now requires python-docutils (if this is missing, the manpage will not be built - which is not considered an error generally, but for package builders or ``make distcheck`` it is). Release tarballs contain the openvpn.8 file, so unless some .rst is changed, doc-utils are not needed for building. - OCC support can no longer be disabled - AEAD support is now required in the crypto library - ``--disable-server`` has been removed from configure (so it is no longer possible to build a client-/p2p-only OpenVPN binary) - the saving in code size no longer outweighs the extra maintenance effort. - ``--enable-iproute2`` will disable netlink(3) support, so maybe remove that from package building configs (see above) - support building with MSVC 2019 - cmocka based unit tests are now only run if cmocka is installed externally (2.4 used to ship a local git submodule which was painful to maintain) - ``--disable-crypto`` configure option has been removed. OpenVPN is now always built with crypto support, which makes the code much easier to maintain. This does not affect ``--cipher none`` to do a tunnel without encryption. - ``--disable-multi`` configure option has been removed Overview of changes in 2.4 ========================== New features ------------ Seamless client IP/port floating Added new packet format P_DATA_V2, which includes peer-id. If both the server and client support it, the client sends all data packets in the new format. When a data packet arrives, the server identifies peer by peer-id. If peer's ip/port has changed, server assumes that client has floated, verifies HMAC and updates ip/port in internal structs. This allows the connection to be immediately restored, instead of requiring a TLS handshake before the server accepts packets from the new client ip/port. Data channel cipher negotiation Data channel ciphers (``--cipher``) are now by default negotiated. If a client advertises support for Negotiable Crypto Parameters (NCP), the server will choose a cipher (by default AES-256-GCM) for the data channel, and tell the client to use that cipher. Data channel cipher negotiation can be controlled using ``--ncp-ciphers`` and ``--ncp-disable``. A more limited version also works in client-to-server and server-to-client scenarios where one of the end points uses a v2.4 client or server and the other side uses an older version. In such scenarios the v2.4 side will change to the ``--cipher`` set by the remote side, if permitted by by ``--ncp-ciphers``. For example, a v2.4 client with ``--cipher BF-CBC`` and ``ncp-ciphers AES-256-GCM:AES-256-CBC`` can connect to both a v2.3 server with ``cipher BF-CBC`` as well as a server with ``cipher AES-256-CBC`` in its config. The other way around, a v2.3 client with either ``cipher BF-CBC`` or ``cipher AES-256-CBC`` can connect to a v2.4 server with e.g. ``cipher BF-CBC`` and ``ncp-ciphers AES-256-GCM:AES-256-CBC`` in its config. For this to work it requires that OpenVPN was built without disabling OCC support. AEAD (GCM) data channel cipher support The data channel now supports AEAD ciphers (currently only GCM). The AEAD packet format has a smaller crypto overhead than the CBC packet format, (e.g. 20 bytes per packet for AES-128-GCM instead of 36 bytes per packet for AES-128-CBC + HMAC-SHA1). ECDH key exchange The TLS control channel now supports for elliptic curve diffie-hellmann key exchange (ECDH). Improved Certificate Revocation List (CRL) processing CRLs are now handled by the crypto library (OpenSSL or mbed TLS), instead of inside OpenVPN itself. The crypto library implementations are more strict than the OpenVPN implementation was. This might reject peer certificates that would previously be accepted. If this occurs, OpenVPN will log the crypto library's error description. Dualstack round-robin DNS client connect Instead of only using the first address of each ``--remote`` OpenVPN will now try all addresses (IPv6 and IPv4) of a ``--remote`` entry. Support for providing IPv6 DNS servers A new DHCP sub-option ``DNS6`` is added alongside with the already existing ``DNS`` sub-option. This is used to provide DNS resolvers available over IPv6. This may be pushed to clients where `` --up`` scripts and ``--plugin`` can act upon it through the ``foreign_option_`` environment variables. Support for the Windows client picking up this new sub-option is added, however IPv6 DNS resolvers need to be configured via ``netsh`` which requires administrator privileges unless the new interactive services on Windows is being used. If the interactive service is used, this service will execute ``netsh`` in the background with the proper privileges. New improved Windows Background service The new OpenVPNService is based on openvpnserv2, a complete rewrite of the OpenVPN service wrapper. It is intended for launching OpenVPN instances that should be up at all times, instead of being manually launched by a user. OpenVPNService is able to restart individual OpenVPN processes if they crash, and it also works properly on recent Windows versions. OpenVPNServiceLegacy tends to work poorly, if at all, on newer Windows versions (8+) and its use is not recommended. New interactive Windows service The installer starts OpenVPNServiceInteractive automatically and configures it to start at system startup. The interactive Windows service allows unprivileged users to start OpenVPN connections in the global config directory (usually C:\\Program Files\\OpenVPN\\config) using OpenVPN GUI without any extra configuration. Users who belong to the built-in Administrator group or to the local "OpenVPN Administrator" group can also store configuration files under %USERPROFILE%\\OpenVPN\\config for use with the interactive service. redirect-gateway ipv6 OpenVPN has now feature parity between IPv4 and IPv6 for redirect gateway including the handling of overlapping IPv6 routes with IPv6 remote VPN server address. LZ4 Compression and pushable compression Additionally to LZO compression OpenVPN now also supports LZ4 compression. Compression options are now pushable from the server. Filter pulled options client-side: pull-filter New option to explicitly allow or reject options pushed by the server. May be used multiple times and is applied in the order specified. Per-client remove push options: push-remove New option to remove options on a per-client basis from the "push" list (more fine-grained than ``--push-reset``). Http proxy password inside config file Http proxy passwords can be specified with the inline file option ```` .. ```` Windows version detection Windows version is detected, logged and possibly signalled to server (IV_PLAT_VER= if ``--push-peer-info`` is set on client). Authentication tokens In situations where it is not suitable to save user passwords on the client, OpenVPN has support for pushing a --auth-token since v2.3. This option is pushed from the server to the client with a token value to be used instead of the users password. For this to work, the authentication plug-in would need to implement this support as well. In OpenVPN 2.4 --auth-gen-token is introduced, which will allow the OpenVPN server to generate a random token and push it to the client without any changes to the authentication modules. When the clients need to re-authenticate the OpenVPN server will do the authentication internally, instead of sending the re-authentication request to the authentication module . This feature is especially useful in configurations which use One Time Password (OTP) authentication schemes, as this allows the tunnel keys to be renegotiated regularly without any need to supply new OTP codes. keying-material-exporter Keying Material Exporter [RFC-5705] allow additional keying material to be derived from existing TLS channel. Android platform support Support for running on Android using Android's VPNService API has been added. See doc/android.txt for more details. This support is primarily used in the OpenVPN for Android app (https://github.com/schwabe/ics-openvpn) AIX platform support AIX platform support has been added. The support only includes tap devices since AIX does not provide tun interface. Control channel encryption (``--tls-crypt``) Use a pre-shared static key (like the ``--tls-auth`` key) to encrypt control channel packets. Provides more privacy, some obfuscation and poor-man's post-quantum security. Asynchronous push reply Plug-ins providing support for deferred authentication can benefit from a more responsive authentication where the server sends PUSH_REPLY immediately once the authentication result is ready, instead of waiting for the client to to send PUSH_REQUEST once more. This requires OpenVPN to be built with ``./configure --enable-async-push``. This is a compile-time only switch. Deprecated features ------------------- For an up-to-date list of all deprecated options, see this wiki page: https://community.openvpn.net/openvpn/wiki/DeprecatedOptions - ``--key-method 1`` is deprecated in OpenVPN 2.4 and will be removed in v2.5. Migrate away from ``--key-method 1`` as soon as possible. The recommended approach is to remove the ``--key-method`` option from the configuration files, OpenVPN will then use ``--key-method 2`` by default. Note that this requires changing the option in both the client and server side configs. - ``--tls-remote`` is removed in OpenVPN 2.4, as indicated in the v2.3 man-pages. Similar functionality is provided via ``--verify-x509-name``, which does the same job in a better way. - ``--compat-names`` and ``--no-name-remapping`` were deprecated in OpenVPN 2.3 and will be removed in v2.5. All scripts and plug-ins depending on the old non-standard X.509 subject formatting must be updated to the standardized formatting. See the man page for more information. - ``--no-iv`` is deprecated in OpenVPN 2.4 and will be removed in v2.5. - ``--keysize`` is deprecated in OpenVPN 2.4 and will be removed in v2.6 together with the support of ciphers with cipher block size less than 128-bits. - ``--comp-lzo`` is deprecated in OpenVPN 2.4. Use ``--compress`` instead. - ``--ifconfig-pool-linear`` has been deprecated since OpenVPN 2.1 and will be removed in v2.5. Use ``--topology p2p`` instead. - ``--client-cert-not-required`` is deprecated in OpenVPN 2.4 and will be removed in v2.5. Use ``--verify-client-cert none`` for a functional equivalent. - ``--ns-cert-type`` is deprecated in OpenVPN 2.3.18 and v2.4. It will be removed in v2.5. Use the far better ``--remote-cert-tls`` option which replaces this feature. User-visible Changes -------------------- - When using ciphers with cipher blocks less than 128-bits, OpenVPN will complain loudly if the configuration uses ciphers considered weak, such as the SWEET32 attack vector. In such scenarios, OpenVPN will by default renegotiate for each 64MB of transported data (``--reneg-bytes``). This renegotiation can be disabled, but is HIGHLY DISCOURAGED. - For certificate DNs with duplicate fields, e.g. "OU=one,OU=two", both fields are now exported to the environment, where each second and later occurrence of a field get _$N appended to it's field name, starting at N=1. For the example above, that would result in e.g. X509_0_OU=one, X509_0_OU_1=two. Note that this breaks setups that rely on the fact that OpenVPN would previously (incorrectly) only export the last occurrence of a field. - ``proto udp`` and ``proto tcp`` now use both IPv4 and IPv6. The new options ``proto udp4`` and ``proto tcp4`` use IPv4 only. - ``--sndbuf`` and ``--recvbuf`` default now to OS defaults instead of 64k - OpenVPN exits with an error if an option has extra parameters; previously they were silently ignored - ``--tls-auth`` always requires OpenVPN static key files and will no longer work with free form files - ``--proto udp6/tcp6`` in server mode will now try to always listen to both IPv4 and IPv6 on platforms that allow it. Use ``--bind ipv6only`` to explicitly listen only on IPv6. - Removed ``--enable-password-save`` from configure. This option is now always enabled. - Stricter default TLS cipher list (override with ``--tls-cipher``), that now also disables: * Non-ephemeral key exchange using static (EC)DH keys * DSS private keys - mbed TLS builds: changed the tls_digest_N values exported to the script environment to be equal to the ones exported by OpenSSL builds, namely the certificate fingerprint (was the hash of the 'to be signed' data). - mbed TLS builds: minimum RSA key size is now 2048 bits. Shorter keys will not be accepted, both local and from the peer. - ``--connect-timeout`` now specifies the timeout until the first TLS packet is received (identical to ``--server-poll-timeout``) and this timeout now includes the removed socks proxy timeout and http proxy timeout. In ``--static`` mode ``connect-timeout`` specifies the timeout for TCP and proxy connection establishment - ``--connect-retry-max`` now specifies the maximum number of unsuccessful attempts of each remote/connection entry before exiting. - ``--http-proxy-timeout`` and the static non-changeable socks timeout (5s) have been folded into a "unified" ``--connect-timeout`` which covers all steps needed to connect to the server, up to the start of the TLS exchange. The default value has been raised to 120s, to handle slow http/socks proxies graciously. The old "fail TCP fast" behaviour can be achieved by adding "``--connect-timeout 10``" to the client config. - ``--http-proxy-retry`` and ``--sock-proxy-retry`` have been removed. Proxy connections will now behave like regular connection entries and generate a USR1 on failure. - ``--connect-retry`` gets an optional second argument that specifies the maximum time in seconds to wait between reconnection attempts when an exponential backoff is triggered due to repeated retries. Default = 300 seconds. - Data channel cipher negotiation (see New features section) can override ciphers configured in the config file. Use ``--ncp-disable`` if you do not want this behavior. - All tun devices on all platforms are always considered to be IPv6 capable. The ``--tun-ipv6`` option is ignored (behaves like it is always on). - On the client side recursively routed packets, which have the same destination as the VPN server, are dropped. This can be disabled with --allow-recursive-routing option. - On Windows, when the ``--register-dns`` option is set, OpenVPN no longer restarts the ``dnscache`` service - this had unwanted side effects, and seems to be no longer necessary with currently supported Windows versions. - If no flags are given, and the interactive Windows service is used, "def1" is implicitly set (because "delete and later reinstall the existing default route" does not work well here). If not using the service, the old behaviour is kept. - OpenVPN now reloads a CRL only if the modication time or file size has changed, instead of for each new connection. This reduces the connection setup time, in particular when using large CRLs. - OpenVPN now ships with more up-to-date systemd unit files which take advantage of the improved service management as well as some hardening steps. The configuration files are picked up from the /etc/openvpn/server/ and /etc/openvpn/client/ directories (depending on unit file). This also avoids these new unit files and how they work to collide with older pre-existing unit files. - Using ``--no-iv`` (which is generally not a recommended setup) will require explicitly disabling NCP with ``--disable-ncp``. This is intentional because NCP will by default use AES-GCM, which requires an IV - so we want users of that option to consciously reconsider. Maintainer-visible changes -------------------------- - OpenVPN no longer supports building with crypto support, but without TLS support. As a consequence, OPENSSL_CRYPTO_{CFLAGS,LIBS} and OPENSSL_SSL_{CFLAGS,LIBS} have been merged into OPENSSL_{CFLAGS,LIBS}. This is particularly relevant for maintainers who build their own OpenSSL library, e.g. when cross-compiling. - Linux distributions using systemd is highly encouraged to ship these new unit files instead of older ones, to provide a unified behaviour across systemd based Linux distributions. - With OpenVPN 2.4, the project has moved over to depend on and actively use the official C99 standard (-std=c99). This may fail on some older compiler/libc header combinations. In most of these situations it is recommended to use -std=gnu99 in CFLAGS. This is known to be needed when doing i386/i686 builds on RHEL5. Version 2.4.5 ============= New features ------------ - The new option ``--tls-cert-profile`` can be used to restrict the set of allowed crypto algorithms in TLS certificates in mbed TLS builds. The default profile is 'legacy' for now, which allows SHA1+, RSA-1024+ and any elliptic curve certificates. The default will be changed to the 'preferred' profile in the future, which requires SHA2+, RSA-2048+ and any curve. Version 2.4.3 ============= New features ------------ - Support building with OpenSSL 1.1 now (in addition to older versions) - On Win10, set low interface metric for TAP adapter when block-outside-dns is in use, to make Windows prefer the TAP adapter for DNS queries (avoiding large delays) Security -------- - CVE-2017-7522: Fix ``--x509-track`` post-authentication remote DoS A client could crash a v2.4+ mbedtls server, if that server uses the ``--x509-track`` option and the client has a correct, signed and unrevoked certificate that contains an embedded NUL in the certificate subject. Discovered and reported to the OpenVPN security team by Guido Vranken. - CVE-2017-7521: Fix post-authentication remote-triggerable memory leaks A client could cause a server to leak a few bytes each time it connects to the server. That can eventually cause the server to run out of memory, and thereby causing the server process to terminate. Discovered and reported to the OpenVPN security team by Guido Vranken. (OpenSSL builds only.) - CVE-2017-7521: Fix a potential post-authentication remote code execution attack on servers that use the ``--x509-username-field`` option with an X.509 extension field (option argument prefixed with ``ext:``). A client that can cause a server to run out-of-memory (see above) might be able to cause the server to double free, which in turn might lead to remote code execution. Discovered and reported to the OpenVPN security team by Guido Vranken. (OpenSSL builds only.) - CVE-2017-7520: Pre-authentication remote crash/information disclosure for clients. If clients use a HTTP proxy with NTLM authentication (i.e. ``--http-proxy [|'auto'|'auto-nct'] ntlm2``), a man-in-the-middle attacker between the client and the proxy can cause the client to crash or disclose at most 96 bytes of stack memory. The disclosed stack memory is likely to contain the proxy password. If the proxy password is not reused, this is unlikely to compromise the security of the OpenVPN tunnel itself. Clients who do not use the ``--http-proxy`` option with ntlm2 authentication are not affected. - CVE-2017-7508: Fix remotely-triggerable ASSERT() on malformed IPv6 packet. This can be used to remotely shutdown an openvpn server or client, if IPv6 and ``--mssfix`` are enabled and the IPv6 networks used inside the VPN are known. - Fix null-pointer dereference when talking to a malicious http proxy that returns a malformed ``Proxy-Authenticate:`` headers for digest auth. - Fix overflow check for long ``--tls-cipher`` option - Windows: Pass correct buffer size to ``GetModuleFileNameW()`` (OSTIF/Quarkslabs audit, finding 5.6) User-visible Changes -------------------- - ``--verify-hash`` can now take an optional flag which changes the hashing algorithm. It can be either SHA1 or SHA256. The default if not provided is SHA1 to preserve backwards compatibility with existing configurations. - Restrict the supported ``--x509-username-field`` extension fields to subjectAltName and issuerAltName. Other extensions probably didn't work anyway, and would cause OpenVPN to crash when a client connects. Bugfixes -------- - Fix fingerprint calculation in mbed TLS builds. This means that mbed TLS users of OpenVPN 2.4.0, v2.4.1 and v2.4.2 that rely on the values of the ``tls_digest_*`` env vars, or that use ``--verify-hash`` will have to change the fingerprint values they check against. The security impact of the incorrect calculation is very minimal; the last few bytes (max 4, typically 4) are not verified by the fingerprint. We expect no real-world impact, because users that used this feature before will notice that it has suddenly stopped working, and users that didn't will notice that connection setup fails if they specify correct fingerprints. - Fix edge case with NCP when the server sends an empty PUSH_REPLY message back, and the client would not initialize it's data channel crypto layer properly (trac #903) - Fix SIGSEGV on unaligned buffer access on OpenBSD/Sparc64 - Fix TCP_NODELAY on OpenBSD - Remove erroneous limitation on max number of args for ``--plugin`` - Fix NCP behaviour on TLS reconnect (Server would not send a proper "cipher ..." message back to the client, leading to client and server using different ciphers) (trac #887) Version 2.4.2 ============= Bugfixes -------- - Fix memory leak introduced in OpenVPN 2.4.1: if ``--remote-cert-tls`` is used, we leaked some memory on each TLS (re)negotiation. Security -------- - Fix a pre-authentication denial-of-service attack on both clients and servers. By sending a too-large control packet, OpenVPN 2.4.0 or v2.4.1 can be forced to hit an ASSERT() and stop the process. If ``--tls-auth`` or ``--tls-crypt`` is used, only attackers that have the ``--tls-auth`` or ``--tls-crypt`` key can mount an attack. (OSTIF/Quarkslab audit finding 5.1, CVE-2017-7478) - Fix an authenticated remote DoS vulnerability that could be triggered by causing a packet id roll over. An attack is rather inefficient; a peer would need to get us to send at least about 196 GB of data. (OSTIF/Quarkslab audit finding 5.2, CVE-2017-7479) Version 2.4.1 ============= - ``--remote-cert-ku`` now only requires the certificate to have at least the bits set of one of the values in the supplied list, instead of requiring an exact match to one of the values in the list. - ``--remote-cert-tls`` now only requires that a keyUsage is present in the certificate, and leaves the verification of the value up to the crypto library, which has more information (i.e. the key exchange method in use) to verify that the keyUsage is correct. - ``--ns-cert-type`` is deprecated. Use ``--remote-cert-tls`` instead. The nsCertType x509 extension is very old, and barely used. ``--remote-cert-tls`` uses the far more common keyUsage and extendedKeyUsage extension instead. Make sure your certificates carry these to be able to use ``--remote-cert-tls``. ================================================ FILE: INSTALL ================================================ Installation instructions for OpenVPN, a Secure Tunneling Daemon Copyright (C) 2002-2022 OpenVPN Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. ************************************************************************* QUICK START: Unix: ./configure && make && make install ************************************************************************* To download OpenVPN source code of releases, go to: https://openvpn.net/community-downloads/ OpenVPN releases are also available as Debian/RPM packages: https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos OpenVPN development versions can be found here: https://github.com/OpenVPN/openvpn https://gitlab.com/OpenVPN/openvpn https://sourceforge.net/p/openvpn/openvpn/ci/master/tree/ They should all be in sync at any time. To download easy-rsa go to: https://github.com/OpenVPN/easy-rsa To download tap-windows (NDIS 6) driver source code go to: https://github.com/OpenVPN/tap-windows6 To download ovpn-dco Windows driver source code go to: https://github.com/OpenVPN/ovpn-dco-win To get the cross-compilation environment go to: https://github.com/OpenVPN/openvpn-build For step-by-step instructions with real-world examples see: https://community.openvpn.net/openvpn/wiki/GettingStartedwithOVPN https://community.openvpn.net/openvpn/wiki https://openvpn.net/community-resources/ Also see the man page for more information. ************************************************************************* For a list of supported platforms and architectures, and for instructions how to port OpenVPN to a yet-unsupported architecture, see the file "PORTS". ************************************************************************* SYSTEM REQUIREMENTS: (1) TUN and/or TAP driver to allow user-space programs to control a virtual point-to-point IP or Ethernet device. See TUN/TAP Driver References section below for more info. (2a) OpenSSL library, necessary for encryption, version 1.1.0 or higher required, available from https://www.openssl.org/ or (2b) mbed TLS library, an alternative for encryption, version 2.0 or higher required, available from https://tls.mbed.org/ (3) on Linux, "libnl-gen" is required for kernel netlink support (4) on Linux, "libcap-ng" is required for Linux capability handling OPTIONAL: (5) LZO real-time compression library, required for link compression, available from https://www.oberhumer.com/opensource/lzo/ (most supported operating systems have LZO in their installable packages repository. It might be necessary to add LZO_CFLAGS= and LZO_LIBS= to the configure call to make it find the LZO pieces) (6) LZ4 compression library OPTIONAL (for developers only): (1) Autoconf 2.59 or higher Automake 1.9 or higher Libtool Git (2) cmocka test framework (https://cmocka.org) (3) If using t_client.sh test framework, fping/fping6 is needed Note: t_client.sh needs an external configured OpenVPN server. See t_client.rc-sample for more info. ************************************************************************* CHECK OUT SOURCE FROM SOURCE REPOSITORY: Clone the repository: git clone https://github.com/OpenVPN/openvpn git clone https://gitlab.com/OpenVPN/openvpn git clone git://openvpn.git.sourceforge.net/gitroot/openvpn/openvpn Check out stable version: git checkout release/2.6 Check out master (unstable) branch: git checkout master ************************************************************************* BUILD COMMANDS FROM TARBALL: ./configure make sudo make install ************************************************************************* BUILD COMMANDS FROM SOURCE REPOSITORY CHECKOUT: autoreconf -i -v -f ./configure make sudo make install ************************************************************************* BUILD A TARBALL FROM SOURCE REPOSITORY CHECKOUT: autoreconf -i -v -f ./configure make distcheck ************************************************************************* TESTS (after BUILD): make check (Run all tests below) Test Crypto: ./openvpn --genkey secret key ./openvpn --test-crypto --secret key Test SSL/TLS negotiations (runs for 2 minutes): ./openvpn --config sample/sample-config-files/loopback-client (In one window) ./openvpn --config sample/sample-config-files/loopback-server (Simultaneously in another window) For more thorough client-server tests you can configure your own, private test environment. See tests/t_client.rc-sample for details. To do the C unit tests, you need to have the "cmocka" test framework installed on your system. More recent distributions already ship this as part of their packages/ports. If your system does not have it, you can install cmocka with these commands: $ git clone https://git.cryptomilk.org/projects/cmocka.git $ cd cmocka $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug .. $ make $ sudo make install ************************************************************************* OPTIONS for ./configure: To get an overview of all the configure options, run "./configure --help" ENVIRONMENT for ./configure: For more fine-grained control on include + library paths for external components etc., configure can be called with environment variables on the command line, e.g. ./configure OPENSSL_CFLAGS="-I/usr/local/include" ... these are also explained in "./configure --help", so not repeated here. ************************************************************************* Linux distribution packaging: Each Linux distribution has their own way of doing packaging and their own set of guidelines of how proper packaging should be done. It is therefore recommended to reach out to the Linux distributions you want to have OpenVPN packaged for directly. The OpenVPN project wants to focus more on the OpenVPN development and less on the packaging and how packaging is done in all various distributions. For more details: * Arch Linux https://www.archlinux.org/packages/?name=openvpn * Debian https://packages.debian.org/search?keywords=openvpn&searchon=names https://tracker.debian.org/pkg/openvpn * Fedora / Fedora EPEL (Red Hat Enterprise Linux/CentOS/Scientific Linux) https://apps.fedoraproject.org/packages/openvpn/overview/ https://src.fedoraproject.org/rpms/openvpn * Gentoo https://packages.gentoo.org/packages/net-vpn/openvpn https://gitweb.gentoo.org/repo/gentoo.git/tree/net-vpn/openvpn * openSUSE https://build.opensuse.org/package/show/network:vpn/openvpn * Ubuntu https://packages.ubuntu.com/search?keywords=openvpn In addition, the OpenVPN community provides best-effort package repositories for CentOS/Fedora, Debian and Ubuntu: https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos ************************************************************************* TUN/TAP Driver References: * Linux 2.6 or higher (with integrated TUN/TAP driver): (1) load driver: modprobe tun (2) enable routing: echo 1 > /proc/sys/net/ipv4/ip_forward Note that (1) needs to be done once per reboot. If you install from RPM (see above) and use the openvpn.init script, these steps are taken care of for you. * FreeBSD: FreeBSD ships with the TUN/TAP driver, and the device nodes for tap0, tap1, tap2, tap3, tun0, tun1, tun2 and tun3 are made by default. On FreeBSD versions prior to 12.0-RELEASE, there were independent TUN and TAP drivers, and the TAP driver needed to be loaded manually, using the command: # kldload if_tap For recent FreeBSD versions, TUN/TAP are integrated and always loaded. FreeBSD 14 contains the ovpn(4) for kernel-level OpenVPN acceleration (DCO) which will be used by OpenVPN 2.6 and up if available. * OpenBSD: OpenBSD has dynamically created tun* devices so you only need to create an empty /etc/hostname.tun0 (tun1, tun2 and so on) for each tun you plan to use to create the device(s) at boot. * Solaris: You need a TUN/TAP kernel driver for OpenVPN to work: https://web.archive.org/web/20250504214754/http://www.whiteboard.ne.jp/~admin2/tuntap/ * Haiku: Haiku can't yet dynamically create TUN/TAP devices, so you need to manually create one before running openvpn: # ifconfig tun/0 up A standard reference the dev as "tun" in your config is all that's needed to use the tunnel device. * Windows OpenVPN on Windows needs a TUN/TAP kernel driver to work. OpenVPN installers include this driver, so installing it separately is not usually required. Starting from Windows 10 2004 / Windows Server 2022, OpenVPN can use the dco-win driver for kernel-level acceleration for OpenVPN client setups. This driver is also included in the community-provided OpenVPN installers. ************************************************************************* CAVEATS & BUGS: * See the bug tracker on https://github.com/OpenVPN/openvpn/issues and the wiki on https://community.openvpn.net/wiki for more detailed caveats on operating systems, and for open and resolved bug reports. * Note: We only recently switched to GitHub for reporting new issues, old issues can be found at https://community.openvpn.net/openvpn/report ================================================ FILE: Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2002-2026 OpenVPN Inc # Copyright (C) 2010-2026 David Sommerseth # Copyright (C) 2006-2012 Alon Bar-Lev # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, see . # ACLOCAL_AMFLAGS = -I m4 MAINTAINERCLEANFILES = \ config.log config.status \ $(srcdir)/Makefile.in \ $(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \ $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \ $(srcdir)/m4/libtool.m4 $(srcdir)/m4/lt~obsolete.m4 \ $(srcdir)/m4/ltoptions.m4 $(srcdir)/m4/ltsugar.m4 \ $(srcdir)/m4/ltversion.m4 \ $(srcdir)/depcomp $(srcdir)/aclocal.m4 \ $(srcdir)/config.guess $(srcdir)/config.sub CLEANFILES = \ config-version.h tests/t_client.sh EXTRA_DIST = \ contrib \ debug \ ltrc.inc \ CMakeLists.txt \ CMakePresets.json \ config.h.cmake.in \ forked-test-driver .PHONY: config-version.h doxygen if GIT_CHECKOUT BUILT_SOURCES = \ config-version.h endif SUBDIRS = distro include src sample doc tests dist_doc_DATA = \ README \ README.mbedtls \ Changes.rst \ COPYRIGHT.GPL \ COPYING dist_noinst_DATA = \ .gitignore \ .gitattributes \ CONTRIBUTING.rst \ PORTS \ README.cmake.md \ README.dco.md \ README.ec \ README.wolfssl config-version.h: @CONFIGURE_GIT_CHFILES="`$(GIT) -C \"$(top_srcdir)\" diff-files --name-status -r --ignore-submodules --quiet -- || echo \"+\"`"; \ CONFIGURE_GIT_UNCOMMITTED="`$(GIT) -C \"$(top_srcdir)\" diff-index --cached --quiet --ignore-submodules HEAD || echo \"*\"`"; \ CONFIGURE_GIT_REVISION="`$(GIT) -C \"$(top_srcdir)\" rev-parse --symbolic-full-name HEAD | cut -d/ -f3-`/`$(GIT) -C \"$(top_srcdir)\" rev-parse --short=16 HEAD`"; \ echo "#define CONFIGURE_GIT_REVISION \"$${CONFIGURE_GIT_REVISION}\"" > config-version.h.tmp; \ echo "#define CONFIGURE_GIT_FLAGS \"$${CONFIGURE_GIT_CHFILES}$${CONFIGURE_GIT_UNCOMMITTED}\"" >> config-version.h.tmp @if ! [ -f config-version.h ] || ! cmp -s config-version.h.tmp config-version.h; then \ echo "replacing config-version.h"; \ mv config-version.h.tmp config-version.h; \ else \ rm -f config-version.h.tmp; \ fi doxygen: $(MAKE) -C doc/doxygen doxygen ================================================ FILE: NEWS ================================================ ================================================ FILE: PORTS ================================================ OpenVPN Copyright (C) 2002-2026 OpenVPN Inc OpenVPN has been written to try to avoid features that are not standardized well across different OSes, so porting OpenVPN itself will probably be straightforward if a tun or tap driver already exists. Where special OS features are used, they are usually bracketed with #ifdef HAVE_SOME_FUNCTION. PLATFORM STATUS: Tier 1 platforms - actively tested for every source commit, across multiple operating system versions * Windows 7 and newer * Windows Server 2012 and newer * Linux * FreeBSD * macOS Tier 2 platforms - it worked at some point, but is not actively tested on "latest OS, latest OS libraries" so might break if larger changes are done on the platform side * OpenBSD * NetBSD * DragonFly BSD * Solaris * AIX For underlying CPU architecture, everything 32 bit or 64 bit (Intel, AMD, ARM, PowerPC, SPARC*) should work fine. 16 bit Architectures are unlikely to work. PORTING GUIDELINE TO A NEW PLATFORM: * Make sure that OpenSSL will build on your platform. * Make sure that a tun or tap virtual device driver exists for your platform. See https://vtun.sourceforge.net/tun/ for examples of tun and tap drivers that have been written for Linux, Solaris, and FreeBSD. * Make sure you have autoconf 2.50+ and automake 1.6+. * Edit configure.ac, adding platform specific config code, and a TARGET_YOUROS define. * Add platform-specific includes to syshead.h. * Add an #ifdef TARGET_YOUROS to the do_ifconfig() function in tun.c to generate a correct "ifconfig" command for your platform. Note that OpenVPN determines the ifconfig path at ./configure time. * Possibly add an ifconfig_order() variant for your OS so openvpn knows whether to call ifconfig before or after tun/tap dev open. * Add an #ifdef TARGET_YOUROS block in tun.c and define the open_tun, close_tun, read_tun, and write_tun functions. If your tun/tap virtual device is sufficiently generic, you may be able to use the default case. * Add appropriate code to route.c to handle the route command on your platform. This is necessary for the --route option to work correctly. * After you successfully build OpenVPN, run the loopback tests as described in INSTALL. * For the next test, confirm that the UDP socket functionality is working independently of the tun device, by doing something like: ./openvpn --remote localhost --verb 9 --ping 1 --dev null * Now try with --remote [a real host] * Now try with a real tun/tap device, you will need to figure out the appropriate ifconfig command to use once openvpn has opened the tun/tap device. * Once you have simple tests working on the tun device, try more complex tests such as using TLS mode. * Stress test the link by doing ping -f across it. * Make sure that packet fragmenting is happening correctly by doing a ping -s 2000 or higher. * Ensure that OpenVPN on your platform will talk to OpenVPN on other platforms such as Linux. Some tun/tap driver implementations will prepend unnecessary stuff onto the datagram that must be disabled with an explicit ioctl call if cross-platform compatibility is to be preserved. You can see some examples of this in tun.c. * Try the ultimate stress test which is --gremlin --reneg-sec 10 in TLS mode then do a flood ping across the tunnel (ping -f remote-endpoint) in both directions and let it run overnight. --gremlin will induce massive corruption and packet loss, but you win if you wake up the next morning and both peers are still running and occasionally even succeeding in their attempted once-per-10-seconds TLS handshake. * When it's working, submit your patch to and rejoice :) ================================================ FILE: README ================================================ OpenVPN -- A Secure tunneling daemon Copyright (C) 2002-2022 OpenVPN Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. ************************************************************************* To get the latest release of OpenVPN, go to: https://openvpn.net/community-downloads/ To Build and Install, tar -zxf openvpn-.tar.gz cd openvpn- ./configure make make install or see the file INSTALL for more info. For information on how to build OpenVPN on/for Windows with MinGW or MSVC see README.cmake.md. ************************************************************************* For detailed information on OpenVPN, including examples, see the man page http://openvpn.net/man.html For a sample VPN configuration, see http://openvpn.net/howto.html To report an issue, see https://github.com/OpenVPN/openvpn/issues/new For a description of OpenVPN's underlying protocol, see the file ssl.h included in the source distribution. ************************************************************************* Other Files & Directories: * configure.ac -- script to rebuild our configure script and makefile. * sample/sample-scripts/verify-cn A sample perl script which can be used with OpenVPN's --tls-verify option to provide a customized authentication test on embedded X509 certificate fields. * sample/sample-keys/ Sample RSA keys and certificates. DON'T USE THESE FILES FOR ANYTHING OTHER THAN TESTING BECAUSE THEY ARE TOTALLY INSECURE. * sample/sample-config-files/ A collection of OpenVPN config files and scripts from the HOWTO at http://openvpn.net/howto.html ************************************************************************* Note that easy-rsa and tap-windows are now maintained in their own subprojects. Their source code is available here: https://github.com/OpenVPN/easy-rsa https://github.com/OpenVPN/tap-windows6 Community-provided Windows installers (MSI) and Debian packages are built from https://github.com/OpenVPN/openvpn-build See the INSTALL file for usage information. ================================================ FILE: README.awslc ================================================ This version of OpenVPN supports AWS-LC (AWS Libcrypto), AWS's open-source cryptographic library. If you encounter bugs in OpenVPN while using AWS-LC: 1. Try compiling OpenVPN with OpenSSL to determine if the issue is specific to AWS-LC 2. For AWS-LC-specific issues, please report them at: https://github.com/aws/aws-lc To build and install OpenVPN with AWS-LC: OPENSSL_CFLAGS="-I/${AWS_LC_INSTALL_FOLDER}/include" \ OPENSSL_LIBS="-L/${AWS_LC_INSTALL_FOLDER}/lib -lssl -lcrypto" \ LDFLAGS="-Wl,-rpath=${AWS_LC_INSTALL_FOLDER}/lib" \ ./configure --with-crypto-library=openssl make make install ************************************************************************* Due to limitations in AWS-LC, the following features are missing * Windows CryptoAPI support ================================================ FILE: README.cmake.md ================================================ OpenVPN Builds with CMake ========================= For Windows builds we do not use the autotools-based buildsystem that we use for our Unix-like (Linux, BSDs, macOS, etc.) builds. Instead we added a separate (CMake)[https://cmake.org/]-based buildsystem. This buildsystem supports building for Windows both with MSVC (i.e. Visual Studio) and MinGW. MinGW builds are also supported as cross-compile from Linux. The official builds, which are also available as CMake presets (see `cmake --list-presets` and `CMakePresets.json`) all use (VCPKG)[https://github.com/microsoft/vcpkg/#vcpkg-overview] for dependency management. This allows us to do proper supply-chain management and also makes cross-building with MinGW on Linux much simpler. However, builds are also possible by providing the build dependencies manually, but that might require specifying more information to CMake. You need at least CMake version 3.21 or newer for the `CMakePreset.json` file to be supported. Manual builds might be possible with older CMake versions, see `cmake_minimum_required` in `CMakeLists.txt`. If you're looking to build the full Windows installer MSI, take a look at https://github.com/OpenVPN/openvpn-build.git . MSVC builds ----------- The following tools are expected to be present on the system, you can install them with a package manager of your choice (e.g. chocolatey, winget) or manually: * CMake (>= 3.21) * Git * Python (3.x), plus the Python module `docutils` * Visual Studion 17 (2022), C/C++ Enviroment For example, to prepare the required tools with chocolatey, you can use the following commands (Powershell): # Installing Chocolatey Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) & choco.exe install -y git --params "/GitAndUnixToolsOnPath" & choco.exe install -y python & python.exe -m ensurepip & python.exe -m pip install --upgrade pip & python.exe -m pip install docutils & choco.exe install -y cmake --installargs 'ADD_CMAKE_TO_PATH=System' & choco.exe install -y "visualstudio2022buildtools" & choco.exe install -y "visualstudio2022-workload-vctools" --params "--add Microsoft.VisualStudio.Component.UWP.VC.ARM64 --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --add Microsoft.VisualStudio.Component.VC.ATL.Spectre --add Microsoft.VisualStudio.Component.VC.ATLMFC.Spectre --add Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre --add Microsoft.VisualStudio.Component.VC.MFC.ARM64.Spectre --add Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre --add Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre --quiet" & choco.exe install -y windows-sdk-10-version-2004-windbg One or more restarts of Powershell might be required to pick up new additions to `PATH` between steps. A Windows restart is probably required after installing Visual Studio before being able to use it. You can find the exact commands we use to set up the community build machines at https://github.com/OpenVPN/openvpn-buildbot/blob/master/jenkins/windows-server/msibuild.pkr.hcl To do a default build, assuming you are in a MSVC 17 2022 environment: mkdir C:\OpenVPN cd C:\OpenVPN git clone https://github.com/microsoft/vcpkg.git git clone https://github.com/OpenVPN/openvpn.git set VCPKG_ROOT=C:\OpenVPN\vcpkg cd openvpn cmake --preset win-amd64-release cmake --build --preset win-amd64-release ctest --preset win-amd64-release When using the presets, the build directory is `out/build//`, you can find the output files there. No install support is provided directly in OpenVPN build, take a look at https://github.com/OpenVPN/openvpn-build.git instead. MinGW builds (cross-compile on Linux) ------------------------------------- To build the Windows executables on a Linux system: # install mingw with the package manager of your choice, e.g. sudo apt-get install -y mingw-w64 # in addition to mingw we also need a toolchain for host builds, e.g. sudo apt-get install -y build-essential # minimum required tools for vcpkg bootstrap: curl, zip, unzip, tar, e.g. sudo apt-get install -y curl zip unzip tar # additionally vcpkg requires powershell when building Windows binaries. # See https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux # e.g. sudo apt-get install -y wget apt-transport-https software-properties-common wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" sudo dpkg -i packages-microsoft-prod.deb sudo apt-get update sudo apt-get install -y powershell # minimum required tools for build: cmake, docutils, git, ninja, # pkg-config, python e.g. sudo apt-get install -y cmake git ninja-build pkg-config python3 python3-docutils # additionally required to build pkcs11-helper: automake, autoconf, # man2html, e.g. sudo apt-get install -y automake autoconf man2html-base mkdir mingw cd mingw git clone https://github.com/microsoft/vcpkg.git git clone https://github.com/OpenVPN/openvpn.git export VCPKG_ROOT=$PWD/vcpkg cd openvpn # requires CMake 3.21 or newer cmake --preset mingw-x64 cmake --build --preset mingw-x64 # unit tests are built, but no testPreset is provided. You need to copy # them to a Windows system manually The instructions have been verified on a Ubuntu 22.04 LTS system in a bash shell, and might need adaptions to other Linux distributions/versions. Note that the MinGW preset builds use the `Ninja multi-config` generator, so if you want to build the Debug binaries, use cmake --build --preset mingw-x64 --config Debug The default build is equivalent to specifying `--config Release`. When using the presets, the build directory is `out/build/mingw/`, you can find the actual output files in sub-directories called ``. No install support is provided directly in OpenVPN build, take a look at https://github.com/OpenVPN/openvpn-build.git instead. Unsupported builds ------------------ The CMake buildsystem also supports builds on Unix-like platforms. These builds are sometimes useful for OpenVPN developers (e.g. when they use IDEs with integrated CMake support). However, they are not officially supported, do not include any install support and should not be used to distribute/package OpenVPN. To emphasize this fact, you need to specify `-DUNSUPPORTED_BUILDS=ON` to cmake to be able to use these builds. The `unix-native` CMake preset is available for these builds. This preset does not require VCPKG and instead assumes all build-dependencies are provided by the system natively. Generating compile_commands.json -------------------------------- To have the CMake buildsystem generate compile_commands.json you can specify `-DENABLE_COMPILE_COMMANDS=ON` on the command line or enable the CMake option another way you like. For supported generators the file will then be created. Additionally, the buildsystem will create a symlink `build/` to the --preset build directory that contains the generated JSON file. This is done so that clangd is able to find it. Enabling this option may cause an error on Windows, since creating a symlink is a privileged operation there. If you enable Developer Mode for the system, symlinks can be created by regular users. ================================================ FILE: README.dco.md ================================================ OpenVPN data channel offload ============================ 2.6.0+ implements support for data-channel offloading where the data packets are directly processed and forwarded in kernel space thanks to the ovpn-dco kernel module. The userspace openvpn program acts purely as a control plane application. Overview of current release --------------------------- - See the "Limitations by design" and "Current limitations" sections for features that are not and/or will not be supported by OpenVPN + ovpn-dco. Getting started (Linux) ----------------------- The new DCO linux kernel module (namely `ovpn`) 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. NOTE: the new `ovpn` Linux kernel module is compatible only with OpenVPN 2.7 and greater. 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 Then clone and build OpenVPN (or use OpenVPN 2.7+). For example: git clone https://github.com/openvpn/openvpn.git cd openvpn autoreconf -vi ./configure --enable-dco make sudo make install # Or just run src/openvpn/openvpn When starting openvpn it will automatically detect DCO support and use the kernel module. Add the option `--disable-dco` to disable data channel offload support. If the configuration contains an option that is incompatible with data channel offloading, OpenVPN will automatically disable DCO support and warn the user. Should OpenVPN be configured to use a feature that is not supported by ovpn or should the ovpn kernel module not be available on the system, you will see a message like Note: Kernel support for ovpn-dco missing, disabling data channel offload. in your log. Getting started (Windows) ------------------------- Official releases published at https://openvpn.net/community-downloads/ include ovpn-dco-win driver since 2.6.0. There are also snapshot releases available at https://build.openvpn.net/downloads/snapshots/github-actions/openvpn2/ . This installer contains the latest OpenVPN code and the ovpn-dco-win driver. DCO and P2P mode ---------------- DCO is also available when running OpenVPN in P2P mode without `--pull` / `--client` option. P2P mode is useful for scenarios when the OpenVPN tunnel should not interfere with overall routing and behave more like a "dumb" tunnel, like GRE. However, DCO requires DATA_V2 to be enabled, which is available for P2P mode only in OpenVPN 2.6 and later. OpenVPN prints a diagnostic message for the P2P NCP result when running in P2P mode: P2P mode NCP negotiation result: TLS_export=1, DATA_v2=1, peer-id 9484735, cipher=AES-256-GCM Double check that you have `DATA_v2=1` in your output and a supported AEAD cipher (AES-XXX-GCM or CHACHA20POLY1305). Routing with ovpn-dco --------------------- The ovpn-dco kernel module implements a more transparent approach to configuring routes to clients (aka "iroutes") and consults the main kernel routing tables for forwarding decisions. - Each client has a VPN IPv4 and/or a VPN IPv6 assigned to it; - additional IP ranges can be routed to a client by adding a route with a client VPN IP as the gateway/nexthop (i.e. ip route add a.b.c.d/24 via $VPNIP); - due to the point above, there is no real need to add a companion `--route` for each `--iroute` directive, unless you want to blackhole traffic when the specific client is not connected; - no internal routing is available. If you need truly internal routes, this can be achieved either with filtering using `iptables` or using `ip rule`; - client-to-client behaviour, as implemented in userspace, does not exist: packets always reach the tunnel interface and are then re-routed to the destination peer based on the system routing table. Limitations by design ---------------------- - Layer 3 (dev tun) only; - only the following AEAD ciphers are currently supported: Chacha20-Poly1305 and AES-GCM-128/192/256; - no support for compression or compression framing: - see also the `--compress migrate` option to move to a setup without compression; - various features not implemented since they have better replacements: - `--shaper`, use tc instead; - packet manipulation, use nftables/iptables instead; - OpenVPN 2.4.0 is the minimum version required for peers to connect: - older versions are missing support for the AEAD ciphers; - topology subnet is the only supported `--topology` for servers; - iroute directives install routes on the host operating system, see also Routing with ovpn-dco; - (ovpn-dco-win) client and p2p mode only; - (ovpn-dco-win) Chacha20-Poly1305 support available starting with Windows 11. Current implementation limitations ------------------- - `--persist-tun` not tested; - IPv6 mapped IPv4 addresses need Linux 5.4.189+/5.10.110+/5.12+ to work; - some incompatible options may not properly fallback to non-dco; ================================================ FILE: README.ec ================================================ Since 2.4.0, OpenVPN has official support for elliptic curve crypto. Elliptic curves are an alternative to RSA for asymmetric encryption. Elliptic curve crypto ('ECC') can be used for the ('TLS') control channel only in OpenVPN; the data channel (encrypting the actual network traffic) uses symmetric encryption. ECC can be used in TLS for authentication (ECDSA) and key exchange (ECDH). Key exchange (ECDH) ------------------- OpenVPN 2.4.0 and newer automatically initialize ECDH parameters. When ECDSA is used for authentication, the curve used for the server certificate will be used for ECDH too. When autodetection fails (e.g. when using RSA certificates) OpenVPN lets the crypto library decide if possible, or falls back to the secp384r1 curve. The list of groups/curves that the crypto library will choose from can be set with the --tls-groups option. An administrator can force an OpenVPN/OpenSSL server to use a specific curve using the --ecdh-curve option with one of the curves listed as available by the --show-groups option. Clients will use the same curve as selected by the server. Note that not all curves listed by --show-groups are available for use with TLS; in that case connecting will fail with a 'no shared cipher' TLS error. Authentication (ECDSA) ---------------------- Since OpenVPN 2.4.0, using ECDSA certificates works 'out of the box'. Which specific curves and cipher suites are available depends on your version and configuration of the crypto library. The crypto library will automatically select a cipher suite for the TLS control channel. Support for generating an ECDSA certificate chain is available in EasyRSA (in spite of it's name) since EasyRSA 3.0. The parameters you're looking for are '--use-algo=ec' and '--curve='. See the EasyRSA documentation for more details on generating ECDSA certificates. ================================================ FILE: README.mbedtls ================================================ This version of OpenVPN has mbed TLS support. To enable, follow the instructions below: To build and install, ./configure --with-crypto-library=mbedtls make make install This version requires mbed TLS version >= 3.2.1. Support for TLS 1.3 requires an Mbed TLS version >= 3.6.4. ************************************************************************* Due to limitations in the mbed TLS library, the following features are missing in the mbed TLS version of OpenVPN: * PKCS#12 file support * --capath support - Loading certificate authorities from a directory * Windows CryptoAPI support * X.509 alternative username fields (must be "CN") Plugin/Script features: * X.509 subject line has a different format than the OpenSSL subject line * X.509 certificate tracking ================================================ FILE: README.wolfssl ================================================ Support for wolfSSL is implemented and maintained by wolfSSL Inc. The support is implemented using wolfSSL's compatibility layer. The wolfSSL support in OpenVPN receives very limited testing/support from the OpenVPN community itself. If bugs in OpenVPN when using wolfSSL are encountered, the user should try to also compile OpenVPN with OpenSSL to determine if these are bugs in the wolfSSL TLS implementation or OpenVPN itself. If bugs are caused by compiling with wolfSSL, please contact support@wolfssl.com directly. To Build and Install, ./configure --with-crypto-library=wolfssl make make install The wolfSSL library will include the installed options.h file by default. To include a custom user_settings.h file for wolfSSL, ./configure --with-crypto-library=wolfssl --disable-wolfssl-options-h make make install ************************************************************************* Due to limitations in the wolfSSL TLS library or its compatibility layer, the following features are missing * blowfish support (BF-CBC), you must use something like cipher AES-128-CBC to avoid trying to use BF-CBC * Windows CryptoAPI support * No TLS1.0 PRF support (No compaitbility with OpenVPN 2.5 or older or other build that do not support TLS EKM) ************************************************************************* Newer wolfSSL versions (5.8.2 and newer) are GPLv3 licensed and this license is not compatible with OpenVPN's GPLv2 license. However wolfSSL Inc has granted an exception to combine the wolfSSL library with OpenVPN and OpenVPN-NL (https://github.com/wolfSSL/wolfssl/blob/master/LICENSING) with version 5.8.4 and later. ************************************************************************* To build WolfSSL with post-quantum KEMs built in, the following command is used: ./configure --enable-openvpn --enable-kyber=all --enable-curve25519 WolfSSL supports the following post-quantum KEMs and post-quantum hybrid KEMs which must be specified using the tls-groups option in an OpenVPN config. Unlike OpenSSL, which includes X25519MLKEM768 in the default config, WolfSSL requires explicit configuration of tls-groups to include at least one post-quantum KEM. ML_KEM_512 ML_KEM_768 ML_KEM_1024 P256_ML_KEM_512 X25519_ML_KEM_512 P384_ML_KEM_768 P256_ML_KEM_768 X448_ML_KEM_768 X25519_ML_KEM_768 P384_ML_KEM_1024 P521_ML_KEM_1024 The naming conventions of algorithms differ between WolfSSL and OpenSSL. An example is that OpenSSL omits underscores for their naming notation whereas WolfSSL expects them. Additionally, OpenSSL does not accept the P curve notation and instead uses the equivalent secp notation. A specific example is that WolfSSL expects P384_ML_KEM_1024, while OpenSSL expects secp384r1MLKEM1024. ================================================ FILE: compat.m4 ================================================ dnl OpenVPN -- An application to securely tunnel IP networks dnl over a single UDP port, with support for SSL/TLS-based dnl session authentication and key exchange, dnl packet encryption, packet authentication, and dnl packet compression. dnl dnl Copyright (C) 2008-2012 Alon Bar-Lev dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, see . dnl Compatibility layer for =4) */ #define ENABLE_DEBUG 1 /* Enable internal fragmentation support */ #define ENABLE_FRAGMENT 1 /* Enable linux data channel offload */ #cmakedefine ENABLE_LINUXDCO /* Enable LZ4 compression library */ #cmakedefine ENABLE_LZ4 /* Enable LZO compression library */ #cmakedefine ENABLE_LZO /* Enable dns-updown script hook */ #cmakedefine ENABLE_DNS_UPDOWN /* Enable management server capability */ #define ENABLE_MANAGEMENT 1 /* Enable OFB and CFB cipher modes */ #define ENABLE_OFB_CFB_MODE /* Enable PKCS11 */ #cmakedefine ENABLE_PKCS11 /* Enable plug-in support */ #define ENABLE_PLUGIN 1 /* Enable TCP Server port sharing */ #cmakedefine ENABLE_PORT_SHARE /* SELinux support */ #cmakedefine ENABLE_SELINUX /* enable sitnl support */ #cmakedefine ENABLE_SITNL /* Enable systemd integration */ /* #undef ENABLE_SYSTEMD */ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ARPA_INET_H 1 /* Define to 1 if you have the `basename' function. */ #cmakedefine HAVE_BASENAME /* Define to 1 if you have the `chdir' function. */ #cmakedefine HAVE_CHDIR /* Define to 1 if you have the `chroot' function. */ #cmakedefine HAVE_CHROOT /* Define to 1 if you have the `chsize' function. */ #cmakedefine HAVE_CHSIZE /* struct cmsghdr needed for extended socket error support */ #cmakedefine HAVE_CMSGHDR /* git version information in config-version.h */ #cmakedefine HAVE_CONFIG_VERSION_H /* cmocka version information available in cmocka_version.h (>= 2.0.0) */ #cmakedefine HAVE_CMOCKA_VERSION_H /* Define to 1 if you have the `daemon' function. */ #cmakedefine HAVE_DAEMON /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DIRECT_H /* Define to 1 if you have the `dirname' function. */ #cmakedefine HAVE_DIRNAME /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DMALLOC_H /* Define to 1 if you have the `dup' function. */ #cmakedefine HAVE_DUP /* Define to 1 if you have the `dup2' function. */ #cmakedefine HAVE_DUP2 /* Define to 1 if you have the `epoll_create' function. */ #cmakedefine HAVE_EPOLL_CREATE /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ERR_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FCNTL_H /* Define to 1 if you have the `fork' function. */ #cmakedefine HAVE_FORK #cmakedefine HAVE_EXECVE /* Define to 1 if you have the `ftruncate' function. */ #cmakedefine HAVE_FTRUNCATE /* Define to 1 if you have the `getgrnam' function. */ #cmakedefine HAVE_GETGRNAM /* Define to 1 if you have the `getpeereid' function. */ #cmakedefine HAVE_GETPEEREID /* Define to 1 if you have the `getpwnam' function. */ #cmakedefine HAVE_GETPWNAM /* Define to 1 if you have the `getrlimit' function. */ #cmakedefine HAVE_GETRLIMIT /* Define to 1 if you have the `getsockname' function. */ #cmakedefine HAVE_GETSOCKNAME /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #cmakedefine HAVE_GRP_H /* struct in_pktinfo needed for IP_PKTINFO support */ #cmakedefine HAVE_IN_PKTINFO /* Define to 1 if you have the header file. */ #cmakedefine HAVE_IO_H /* struct in_pktinfo.ipi_spec_dst needed for IP_PKTINFO support */ #cmakedefine HAVE_IPI_SPEC_DST /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LIBGEN_H /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LZO1X_H 1 /* Define to 1 if you have the `mlockall' function. */ #cmakedefine HAVE_MLOCKALL /* struct msghdr needed for extended socket error support */ #cmakedefine HAVE_MSGHDR /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETDB_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IP_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NET_IF_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NET_IF_TUN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NET_TUN_IF_TUN_H /* Define to 1 if you have the `nice' function. */ #cmakedefine HAVE_NICE /* Define to 1 if you have the `openlog' function. */ #cmakedefine HAVE_OPENLOG /* OpenSSL engine support available */ #undef HAVE_OPENSSL_ENGINE /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define to 1 if you have the header file. */ #cmakedefine HAVE_POLL_H /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PWD_H /* Define to 1 if you have the `recvmsg' function. */ #cmakedefine HAVE_RECVMSG #cmakedefine HAVE_SENDMSG /* Define to 1 if you have the header file. */ #cmakedefine HAVE_RESOLV_H /* sa_family_t, needed to hold AF_* info */ #cmakedefine HAVE_SA_FAMILY_T /* Define to 1 if you have the `sd_booted' function. */ #undef HAVE_SD_BOOTED /* Define to 1 if you have the `setgid' function. */ #cmakedefine HAVE_SETGID /* Define to 1 if you have the `setgroups' function. */ #undef HAVE_SETGROUPS /* Define to 1 if you have the `setsid' function. */ #cmakedefine HAVE_SETSID /* Define to 1 if you have the `setsockopt' function. */ #define HAVE_SETSOCKOPT 1 /* Define to 1 if you have the `setuid' function. */ #cmakedefine HAVE_SETUID /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* struct sock_extended_err needed for extended socket error support */ #undef HAVE_SOCK_EXTENDED_ERR /* Define to 1 if you have the `stat' function. */ #define HAVE_STAT 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `syslog' function. */ #cmakedefine HAVE_SYSLOG /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_EPOLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_INOTIFY_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_KERN_CONTROL_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_TAP_WINDOWS_H /* Define to 1 if you have the header file. */ #undef HAVE_UAPI_H /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_VALGRIND_MEMCHECK_H /* Availability of different mbed TLS features and APIs */ #cmakedefine HAVE_PSA_CRYPTO_H /* Path to ifconfig tool */ #define IFCONFIG_PATH "@IFCONFIG_PATH@" /* Path to iproute tool */ #define IPROUTE_PATH "@IPROUTE_PATH@" /* Path to route tool */ #define ROUTE_PATH "@ROUTE_PATH@" /* OpenVPN version in Windows resource format - string */ #define OPENVPN_VERSION_RESOURCE @OPENVPN_VERSION_RESOURCE@ /* Name of package */ #define PACKAGE "openvpn" /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #define PACKAGE_NAME "OpenVPN" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "OpenVPN @OPENVPN_VERSION_MAJOR@.@OPENVPN_VERSION_MINOR@@OPENVPN_VERSION_PATCH@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@OPENVPN_VERSION_MAJOR@.@OPENVPN_VERSION_MINOR@@OPENVPN_VERSION_PATCH@" /* Path to systemd-ask-password tool */ #undef SYSTEMD_ASK_PASSWORD_PATH /* The tap-windows id */ #define TAP_WIN_COMPONENT_ID "tap0901" /* The tap-windows version number is required for OpenVPN */ #define TAP_WIN_MIN_MAJOR 9 /* The tap-windows version number is required for OpenVPN */ #define TAP_WIN_MIN_MINOR 9 /* Are we running on Mac OS X? */ #cmakedefine TARGET_DARWIN /* Are we running on FreeBSD? */ #cmakedefine TARGET_FREEBSD /* Are we running on Linux? */ #cmakedefine TARGET_LINUX /* Are we running on Solaris/OpenIndiana? */ #cmakedefine TARGET_SOLARIS /* Are we running WIN32? */ #cmakedefine TARGET_WIN32 /* Are we targeting Android? */ #cmakedefine TARGET_ANDROID #define TARGET_ALIAS "@CMAKE_SYSTEM_NAME@" /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif ================================================ FILE: configure.ac ================================================ dnl OpenVPN -- An application to securely tunnel IP networks dnl over a single UDP port, with support for SSL/TLS-based dnl session authentication and key exchange, dnl packet encryption, packet authentication, and dnl packet compression. dnl dnl Copyright (C) 2002-2026 OpenVPN Inc dnl Copyright (C) 2006-2012 Alon Bar-Lev dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, see . dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.60) m4_include(version.m4) AC_INIT([PRODUCT_NAME], [PRODUCT_VERSION], [PRODUCT_BUGREPORT], [PRODUCT_TARNAME]) m4_include(compat.m4) AC_DEFINE([OPENVPN_VERSION_RESOURCE], [PRODUCT_VERSION_RESOURCE], [Version in windows resource format]) AC_SUBST([OPENVPN_VERSION_MAJOR], [PRODUCT_VERSION_MAJOR], [OpenVPN major version]) AC_SUBST([OPENVPN_VERSION_MINOR], [PRODUCT_VERSION_MINOR], [OpenVPN minor version]) AC_SUBST([OPENVPN_VERSION_PATCH], [PRODUCT_VERSION_PATCH], [OpenVPN patch level - may be a string or integer]) AC_DEFINE([OPENVPN_VERSION_MAJOR], [PRODUCT_VERSION_MAJOR], [OpenVPN major version - integer]) AC_DEFINE([OPENVPN_VERSION_MINOR], [PRODUCT_VERSION_MINOR], [OpenVPN minor version - integer]) AC_DEFINE([OPENVPN_VERSION_PATCH], ["PRODUCT_VERSION_PATCH"], [OpenVPN patch level - may be a string or integer]) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_HEADERS([config.h include/openvpn-plugin.h]) AC_CONFIG_SRCDIR([src/openvpn/syshead.h]) AC_CONFIG_MACRO_DIR([m4]) dnl Automake 1.14+ warns if sources are in sub-directories but subdir-objects dnl options is not enabled. However, automake before 1.15a has a bug that causes dnl variable expansion to fail in foo_SOURCES when this option is used. dnl As most of our build systems are now likely to use automake 1.16+ add a dnl work around to conditionally add subdir-objects option. m4_define([subdir_objects], [ m4_esyscmd([automake --version | head -1 | awk '{split ($NF,a,"."); if (a[1] == 1 && a[2] >= 16) { print "subdir-objects" }}' ]) ]) # This foreign option prevents autoreconf from overriding our COPYING and # INSTALL targets: AM_INIT_AUTOMAKE(foreign subdir_objects 1.9) dnl NB: Do not [quote] this parameter. AM_SILENT_RULES([yes]) AC_CANONICAL_HOST AC_USE_SYSTEM_EXTENSIONS AC_ARG_ENABLE( [lzo], [AS_HELP_STRING([--disable-lzo], [disable LZO compression support @<:@default=yes@:>@])], , [enable_lzo="yes"] ) AC_ARG_ENABLE( [lz4], [AS_HELP_STRING([--disable-lz4], [disable LZ4 compression support @<:@default=yes@:>@])], [enable_lz4="$enableval"], [enable_lz4="yes"] ) AC_ARG_ENABLE( [comp-stub], [AS_HELP_STRING([--enable-comp-stub], [disable compression support but still allow limited interoperability with compression-enabled peers @<:@default=no@:>@])], [enable_comp_stub="$enableval"], [enable_comp_stub="no"] ) AC_ARG_ENABLE( [ofb-cfb], [AS_HELP_STRING([--disable-ofb-cfb], [disable support for OFB and CFB cipher modes @<:@default=yes@:>@])], , [enable_crypto_ofb_cfb="yes"] ) AC_ARG_ENABLE( [dns-updown-by-default], [AS_HELP_STRING([--disable-dns-updown-by-default], [disable running --dns-updown by default @<:@default=yes@:>@])], , [enable_dns_updown_by_default="yes"] ) AC_ARG_ENABLE( [plugins], [AS_HELP_STRING([--disable-plugins], [disable plug-in support @<:@default=yes@:>@])], , [enable_plugins="yes"] ) AC_ARG_ENABLE( [management], [AS_HELP_STRING([--disable-management], [disable management server support @<:@default=yes@:>@])], , [enable_management="yes"] ) AC_ARG_ENABLE( [pkcs11], [AS_HELP_STRING([--enable-pkcs11], [enable pkcs11 support @<:@default=no@:>@])], , [enable_pkcs11="no"] ) AC_ARG_ENABLE( [fragment], [AS_HELP_STRING([--disable-fragment], [disable internal fragmentation support (--fragment) @<:@default=yes@:>@])], , [enable_fragment="yes"] ) AC_ARG_ENABLE( [port-share], [AS_HELP_STRING([--disable-port-share], [disable TCP server port-share support (--port-share) @<:@default=yes@:>@])], , [enable_port_share="yes"] ) AC_ARG_ENABLE( [debug], [AS_HELP_STRING([--disable-debug], [disable debugging support (disable gremlin and verb 7+ messages) @<:@default=yes@:>@])], , [enable_debug="yes"] ) AC_ARG_ENABLE( [small], [AS_HELP_STRING([--enable-small], [enable smaller executable size (disable OCC, usage message, and verb 4 parm list) @<:@default=no@:>@])], , [enable_small="no"] ) AC_ARG_ENABLE( [dco], [AS_HELP_STRING([--disable-dco], [disable data channel offload support using the ovpn-dco kernel module @<:@default=yes@:>@ on Linux/FreeBSD, can't disable on Windows])], , [ case "$host" in *-*-linux*) enable_dco="auto" ;; *-*-freebsd*) enable_dco="auto" ;; *) # note that this does not disable it for Windows enable_dco="no" ;; esac ] ) AC_ARG_ENABLE( [iproute2], [AS_HELP_STRING([--enable-iproute2], [enable support for iproute2 (disables DCO) @<:@default=no@:>@])], , [enable_iproute2="no"] ) AC_ARG_ENABLE( [plugin-auth-pam], [AS_HELP_STRING([--disable-plugin-auth-pam], [disable auth-pam plugin @<:@default=platform specific@:>@])], , [ case "$host" in *-*-openbsd*) enable_plugin_auth_pam="no";; *-mingw*) enable_plugin_auth_pam="no";; *) enable_plugin_auth_pam="yes";; esac ] ) AC_ARG_ENABLE( [plugin-down-root], [AS_HELP_STRING([--disable-plugin-down-root], [disable down-root plugin @<:@default=platform specific@:>@])], , [ case "$host" in *-mingw*) enable_plugin_down_root="no";; *) enable_plugin_down_root="yes";; esac ] ) AC_ARG_ENABLE( [pam-dlopen], [AS_HELP_STRING([--enable-pam-dlopen], [dlopen libpam @<:@default=no@:>@])], , [enable_pam_dlopen="no"] ) AC_ARG_ENABLE( [strict], [AS_HELP_STRING([--enable-strict], [enable strict compiler warnings (debugging option) @<:@default=no@:>@])], , [enable_strict="no"] ) AC_ARG_ENABLE( [pedantic], [AS_HELP_STRING([--enable-pedantic], [enable pedantic compiler warnings, will not generate a working executable (debugging option) @<:@default=no@:>@])], , [enable_pedantic="no"] ) AC_ARG_ENABLE( [werror], [AS_HELP_STRING([--enable-werror], [promote compiler warnings to errors, will cause builds to fail if the compiler issues warnings (debugging option) @<:@default=no@:>@])], , [enable_werror="no"] ) AC_ARG_ENABLE( [strict-options], [AS_HELP_STRING([--enable-strict-options], [enable strict options check between peers (debugging option) @<:@default=no@:>@])], , [enable_strict_options="no"] ) AC_ARG_ENABLE( [selinux], [AS_HELP_STRING([--enable-selinux], [enable SELinux support @<:@default=no@:>@])], , [enable_selinux="no"] ) AC_ARG_ENABLE( [systemd], [AS_HELP_STRING([--enable-systemd], [enable systemd support @<:@default=no@:>@])], , [enable_systemd="no"] ) AC_ARG_ENABLE( [async-push], [AS_HELP_STRING([--enable-async-push], [enable async-push support for plugins providing deferred authentication @<:@default=no@:>@])], , [enable_async_push="no"] ) AC_ARG_WITH( [special-build], [AS_HELP_STRING([--with-special-build=STRING], [specify special build string])], [test -n "${withval}" && AC_DEFINE_UNQUOTED([CONFIGURE_SPECIAL_BUILD], ["${withval}"], [special build string])] ) AC_ARG_WITH( [mem-check], [AS_HELP_STRING([--with-mem-check=TYPE], [build with debug memory checking, TYPE=no|dmalloc|valgrind|ssl @<:@default=no@:>@])], [ case "${withval}" in dmalloc|valgrind|ssl|no) ;; *) AC_MSG_ERROR([bad value ${withval} for --mem-check]) ;; esac ], [with_mem_check="no"] ) AC_ARG_WITH( [crypto-library], [AS_HELP_STRING([--with-crypto-library=library], [build with the given crypto library, TYPE=openssl|mbedtls|wolfssl @<:@default=openssl@:>@])], [ case "${withval}" in openssl|mbedtls|wolfssl) ;; *) AC_MSG_ERROR([bad value ${withval} for --with-crypto-library]) ;; esac ], [with_crypto_library="openssl"] ) AC_ARG_ENABLE( [wolfssl-options-h], [AS_HELP_STRING([--disable-wolfssl-options-h], [Disable including options.h in wolfSSL @<:@default=yes@:>@])], , [enable_wolfssl_options_h="yes"] ) AC_ARG_WITH( [openssl-engine], [AS_HELP_STRING([--with-openssl-engine], [enable engine support with OpenSSL. Default enabled for OpenSSL < 3.0, auto,yes,no @<:@default=auto@:>@])], [ case "${withval}" in auto|yes|no) ;; *) AC_MSG_ERROR([bad value ${withval} for --with-engine]) ;; esac ], [with_openssl_engine="auto"] ) AC_ARG_VAR([PLUGINDIR], [Path of plug-in directory @<:@default=LIBDIR/openvpn/plugins@:>@]) if test -n "${PLUGINDIR}"; then plugindir="${PLUGINDIR}" else plugindir="\${libdir}/openvpn/plugins" fi AC_ARG_VAR([SCRIPTDIR], [Path of script directory @<:@default=PKGLIBEXECDIR@:>@]) if test -n "${SCRIPTDIR}"; then scriptdir="${SCRIPTDIR}" else scriptdir="\${pkglibexecdir}" fi AC_DEFINE_UNQUOTED([TARGET_ALIAS], ["${host}"], [A string representing our host]) AM_CONDITIONAL([ENABLE_DNS_UPDOWN],[true]) case "$host" in *-*-linux*) AC_DEFINE([TARGET_LINUX], [1], [Are we running on Linux?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["L"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["systemd"]) have_sitnl="yes" pkg_config_required="yes" ;; *-*-solaris*) AC_DEFINE([TARGET_SOLARIS], [1], [Are we running on Solaris?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["S"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) CPPFLAGS="$CPPFLAGS -D_XPG4_2" test -x /bin/bash && SHELL="/bin/bash" ;; *-*-openbsd*) AC_DEFINE([TARGET_OPENBSD], [1], [Are we running on OpenBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["O"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) ;; *-*-freebsd*) AC_DEFINE([TARGET_FREEBSD], [1], [Are we running on FreeBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["F"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-*-netbsd*) AC_DEFINE([TARGET_NETBSD], [1], [Are we running NetBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["N"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-*-darwin*) AC_DEFINE([TARGET_DARWIN], [1], [Are we running on Mac OS X?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["M"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["macos"]) have_tap_header="yes" ac_cv_type_struct_in_pktinfo=no ;; *-mingw*) AC_DEFINE([TARGET_WIN32], [1], [Are we running WIN32?]) AC_DEFINE([ENABLE_DCO], [1], [DCO is always enabled on Windows]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["W"], [Target prefix]) AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false]) AC_SUBST([DNS_UPDOWN_TYPE], ["windows"]) CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN" CPPFLAGS="${CPPFLAGS} -DNTDDI_VERSION=NTDDI_VISTA -D_WIN32_WINNT=_WIN32_WINNT_VISTA" WIN32=yes ;; *-*-dragonfly*) AC_DEFINE([TARGET_DRAGONFLY], [1], [Are we running on DragonFlyBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["D"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-aix*) AC_DEFINE([TARGET_AIX], [1], [Are we running AIX?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["A"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) ROUTE="/usr/sbin/route" have_tap_header="yes" ac_cv_header_net_if_h="no" # exists, but breaks things ;; *-*-haiku*) AC_DEFINE([TARGET_HAIKU], [1], [Are we running Haiku?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["H"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["haikuos_file"]) LIBS="${LIBS} -lnetwork" ;; *) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["X"], [Target prefix]) AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) have_tap_header="yes" ;; esac AM_CONDITIONAL([CROSS_COMPILING], test "${cross_compiling}" = "yes") PKG_PROG_PKG_CONFIG # Add variable to print if pkg-config is found or not. Users often miss that if test "${PKG_CONFIG}" = ""; then if test "${pkg_config_required}" = "yes"; then AC_MSG_ERROR([pkg-config is required]) fi pkg_config_found="(not found)" else pkg_config_found="(${PKG_CONFIG})" fi AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_SED AC_PROG_MAKE_SET AC_ARG_VAR([IFCONFIG], [full path to ipconfig utility]) AC_ARG_VAR([ROUTE], [full path to route utility]) AC_ARG_VAR([IPROUTE], [full path to ip utility]) AC_ARG_VAR([NETSTAT], [path to netstat utility]) # tests AC_ARG_VAR([GIT], [path to git utility]) AC_ARG_VAR([SYSTEMD_ASK_PASSWORD], [path to systemd-ask-password utility]) AC_ARG_VAR([SYSTEMD_UNIT_DIR], [Path of systemd unit directory @<:@default=LIBDIR/systemd/system@:>@]) AC_ARG_VAR([TMPFILES_DIR], [Path of tmpfiles directory @<:@default=LIBDIR/tmpfiles.d@:>@]) AC_PATH_PROGS([IFCONFIG], [ifconfig],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) AC_PATH_PROGS([ROUTE], [route],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) AC_PATH_PROGS([IPROUTE], [ip],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) AC_PATH_PROGS([SYSTEMD_ASK_PASSWORD], [systemd-ask-password],, [$PATH:/usr/local/bin:/usr/bin:/bin]) AC_CHECK_PROGS([NETSTAT], [netstat], [netstat], [$PATH:/usr/local/sbin:/usr/sbin:/sbin:/etc]) # tests AC_CHECK_PROGS([GIT], [git]) # optional AC_DEFINE_UNQUOTED([IFCONFIG_PATH], ["$IFCONFIG"], [Path to ifconfig tool]) AC_DEFINE_UNQUOTED([IPROUTE_PATH], ["$IPROUTE"], [Path to iproute tool]) AC_DEFINE_UNQUOTED([ROUTE_PATH], ["$ROUTE"], [Path to route tool]) AC_DEFINE_UNQUOTED([SYSTEMD_ASK_PASSWORD_PATH], ["$SYSTEMD_ASK_PASSWORD"], [Path to systemd-ask-password tool]) AC_CHECK_TOOLS([WINDMC], [windmc mc.exe],[no]) # # man page generation - based on python-docutils # AC_ARG_VAR([RST2MAN], [path to rst2man utility]) AC_ARG_VAR([RST2HTML], [path to rst2html utility]) AC_CHECK_PROGS([RST2MAN], [rst2man rst2man.py]) AC_CHECK_PROGS([RST2HTML], [rst2html rst2html.py]) AM_CONDITIONAL([HAVE_PYDOCUTILS], [test "${RST2MAN}" -a "${RST2HTML}"]) # Set -std=c11 unless user already specified a -std= case "${CFLAGS}" in *-std=*) ;; *) CFLAGS="${CFLAGS} -std=c11" ;; esac # # Libtool # ifdef( [LT_INIT], [ LT_INIT([win32-dll]) LT_LANG([Windows Resource]) ], [ AC_LIBTOOL_WIN32_DLL AC_LIBTOOL_RC AC_PROG_LIBTOOL ] ) AC_C_INLINE AX_TYPE_SOCKLEN_T AC_CHECK_HEADERS([ \ fcntl.h io.h \ sys/types.h sys/socket.h \ unistd.h dlfcn.h \ netinet/in.h \ netinet/tcp.h arpa/inet.h netdb.h \ ]) AC_CHECK_HEADERS([ \ sys/time.h sys/ioctl.h sys/stat.h \ sys/mman.h sys/file.h sys/wait.h \ libgen.h stropts.h \ syslog.h pwd.h grp.h termios.h \ sys/sockio.h sys/uio.h \ poll.h sys/epoll.h err.h \ ]) SOCKET_INCLUDES=" #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef _WIN32 #include #endif #ifdef _WIN32 #include #endif #ifdef _WIN32 #include #endif #ifdef HAVE_NETINET_IP_H #include #endif " AC_CHECK_HEADERS( [net/if.h netinet/ip.h resolv.h sys/un.h sys/kern_control.h], , , [[${SOCKET_INCLUDES}]] ) AC_CHECK_TYPE( [struct msghdr], [AC_DEFINE([HAVE_MSGHDR], [1], [struct msghdr needed for extended socket error support])], , [[${SOCKET_INCLUDES}]] ) AC_CHECK_TYPE( [struct cmsghdr], [AC_DEFINE([HAVE_CMSGHDR], [1], [struct cmsghdr needed for extended socket error support])], , [[${SOCKET_INCLUDES}]] ) AC_CHECK_TYPE( [struct in_pktinfo], [AC_DEFINE([HAVE_IN_PKTINFO], [1], [struct in_pktinfo needed for IP_PKTINFO support])], , [[${SOCKET_INCLUDES}]] ) AC_CHECK_TYPE( [sa_family_t], [AC_DEFINE([HAVE_SA_FAMILY_T], [1], [sa_family_t, needed to hold AF_* info])], , [[${SOCKET_INCLUDES}]] ) AC_CHECK_MEMBER( [struct in_pktinfo.ipi_spec_dst], [AC_DEFINE([HAVE_IPI_SPEC_DST], [1], [struct in_pktinfo.ipi_spec_dst needed for IP_PKTINFO support])], , [[${SOCKET_INCLUDES}]] ) AC_CHECK_TYPE( [struct sockaddr_in6], , [AC_MSG_ERROR([struct sockaddr_in6 not found, needed for ipv6 transport support.])], [[${SOCKET_INCLUDES}]] ) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--wrap=exit" AC_MSG_CHECKING([linker supports --wrap]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[ void exit(int); void __real_exit(int); void __wrap_exit(int i) { __real_exit(i); } ]], [[ exit(0); ]] )], [ AC_MSG_RESULT([yes]) have_ld_wrap_support=yes ], [AC_MSG_RESULT([no])], ) LDFLAGS="$saved_LDFLAGS" AC_FUNC_FORK AC_CHECK_FUNCS([ \ daemon chroot getpwnam setuid nice dup dup2 \ syslog openlog mlockall getrlimit getgrnam setgid \ setgroups flock gettimeofday \ setsid chdir \ chsize ftruncate execve getpeereid basename dirname \ epoll_create strsep \ ]) AC_CHECK_LIB( [dl], [dlopen], [DL_LIBS="-ldl"] ) AC_SUBST([DL_LIBS]) AC_CHECK_LIB( [nsl], [inet_ntoa], [SOCKETS_LIBS="${SOCKETS_LIBS} -lnsl"] ) AC_CHECK_LIB( [socket], [socket], [SOCKETS_LIBS="${SOCKETS_LIBS} -lsocket"] ) AC_CHECK_LIB( [resolv], [gethostbyname], [SOCKETS_LIBS="${SOCKETS_LIBS} -lresolv"] ) AC_SUBST([SOCKETS_LIBS]) old_LIBS="${LIBS}" LIBS="${LIBS} ${SOCKETS_LIBS}" AC_CHECK_FUNCS([sendmsg recvmsg]) LIBS="${old_LIBS}" # we assume res_init() always exist, but need to find out *where*... AC_SEARCH_LIBS(__res_init, resolv bind, , AC_SEARCH_LIBS(res_9_init, resolv bind, , AC_SEARCH_LIBS(res_init, resolv bind, , ))) AC_ARG_VAR([TAP_CFLAGS], [C compiler flags for tap]) old_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} ${TAP_CFLAGS}" AC_CHECK_HEADERS( [ \ net/if_tun.h net/tun/if_tun.h \ linux/if_tun.h \ tap-windows.h \ ], [have_tap_header="yes"] ) CFLAGS="${old_CFLAGS}" test "${have_tap_header}" = "yes" || AC_MSG_ERROR([no tap header could be found]) AC_CHECK_LIB( [selinux], [setcon], [SELINUX_LIBS="-lselinux"] ) AC_SUBST([SELINUX_LIBS]) AC_ARG_VAR([LIBPAM_CFLAGS], [C compiler flags for libpam]) AC_ARG_VAR([LIBPAM_LIBS], [linker flags for libpam]) if test -z "${LIBPAM_LIBS}"; then AC_CHECK_LIB( [pam], [pam_start], [LIBPAM_LIBS="-lpam"] ) fi case "${with_mem_check}" in valgrind) AC_CHECK_HEADERS( [valgrind/memcheck.h], [ CFLAGS="${CFLAGS} -g -fno-inline" AC_DEFINE( [USE_VALGRIND], [1], [Use valgrind memory debugging library] ) ], [AC_MSG_ERROR([valgrind headers not found.])] ) ;; dmalloc) AC_CHECK_HEADERS( [dmalloc.h], [AC_CHECK_LIB( [dmalloc], [malloc], [ LIBS="${LIBS} -ldmalloc" AC_DEFINE( [DMALLOC], [1], [Use dmalloc memory debugging library] ) ], [AC_MSG_ERROR([dmalloc library not found.])] )], [AC_MSG_ERROR([dmalloc headers not found.])] ) ;; ssl) AC_CHECK_LIB( [ssl], [CRYPTO_mem_ctrl], [ AC_DEFINE( [CRYPTO_MDEBUG], [1], [Use memory debugging function in OpenSSL] ) AC_MSG_NOTICE([NOTE: OpenSSL library must be compiled with CRYPTO_MDEBUG]) ], [AC_MSG_ERROR([Memory Debugging function in OpenSSL library not found.])] ) ;; esac if test "$enable_dco" != "no"; then enable_dco_arg="$enable_dco" if test "${enable_iproute2}" = "yes"; then AC_MSG_WARN([DCO cannot be enabled when using iproute2]) enable_dco="no" fi case "$host" in *-*-linux*) if test "$enable_dco" = "no"; then if test "$enable_dco_arg" = "auto"; then AC_MSG_WARN([DCO support disabled]) else AC_MSG_ERROR([DCO support can't be enabled]) fi else dnl dnl Include generic netlink library used to talk to ovpn-dco dnl PKG_CHECK_MODULES([LIBNL_GENL], [libnl-genl-3.0 >= 3.4.0], [have_libnl="yes"], [ AC_MSG_ERROR([libnl-genl-3.0 package not found or too old. Is the development package and pkg-config ${pkg_config_found} installed? Must be version 3.4.0 or newer for DCO]) ] ) OPTIONAL_LIBNL_GENL_CFLAGS="${LIBNL_GENL_CFLAGS}" OPTIONAL_LIBNL_GENL_LIBS="${LIBNL_GENL_LIBS}" AC_DEFINE(ENABLE_DCO, 1, [Enable shared data channel offload]) AC_MSG_NOTICE([Enabled ovpn-dco support for Linux]) fi ;; *-*-freebsd*) AC_CHECK_HEADERS([net/if_ovpn.h], [ LIBS="${LIBS} -lnv" AC_DEFINE(ENABLE_DCO, 1, [Enable data channel offload for FreeBSD]) AC_MSG_NOTICE([Enabled ovpn-dco support for FreeBSD]) ], [ enable_dco="no" AC_MSG_WARN([DCO header not found.]) ] ) if test "$enable_dco" = "no"; then if test "$enable_dco_arg" = "auto"; then AC_MSG_WARN([DCO support disabled]) else AC_MSG_ERROR([DCO support can't be enabled]) fi fi ;; *-mingw*) AC_MSG_NOTICE([NOTE: --enable-dco ignored on Windows because it's always enabled]) ;; *) AC_MSG_NOTICE([Ignoring --enable-dco on non supported platform]) ;; esac fi dnl dnl Depend on libcap-ng on Linux dnl case "$host" in *-*-linux*) PKG_CHECK_MODULES([LIBCAPNG], [libcap-ng], [], [AC_MSG_ERROR([libcap-ng package not found. Is the development package and pkg-config ${pkg_config_found} installed?])] ) AC_CHECK_HEADER([sys/prctl.h],,[AC_MSG_ERROR([sys/prctl.h not found!])]) OPTIONAL_LIBCAPNG_CFLAGS="${LIBCAPNG_CFLAGS}" OPTIONAL_LIBCAPNG_LIBS="${LIBCAPNG_LIBS}" AC_DEFINE(HAVE_LIBCAPNG, 1, [Enable libcap-ng support]) ;; esac if test "${with_crypto_library}" = "openssl"; then AC_ARG_VAR([OPENSSL_CFLAGS], [C compiler flags for OpenSSL]) AC_ARG_VAR([OPENSSL_LIBS], [linker flags for OpenSSL]) if test -z "${OPENSSL_CFLAGS}" -a -z "${OPENSSL_LIBS}"; then # if the user did not explicitly specify flags, try to autodetect PKG_CHECK_MODULES( [OPENSSL], [openssl >= 1.1.0], [have_openssl="yes"], [AC_MSG_WARN([OpenSSL not found by pkg-config ${pkg_config_found}])] # If this fails, we will do another test next ) OPENSSL_LIBS=${OPENSSL_LIBS:--lssl -lcrypto} fi saved_CFLAGS="${CFLAGS}" saved_LIBS="${LIBS}" CFLAGS="${CFLAGS} ${OPENSSL_CFLAGS}" LIBS="${LIBS} ${OPENSSL_LIBS}" # If pkgconfig check failed or OPENSSL_CFLAGS/OPENSSL_LIBS env vars # are used, check the version directly in the OpenSSL include file if test "${have_openssl}" != "yes"; then AC_MSG_CHECKING([additionally if OpenSSL is available and version >= 1.1.0]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ /* Version encoding: MNNFFPPS - see opensslv.h for details */ #if OPENSSL_VERSION_NUMBER < 0x10100000L #error OpenSSL too old #endif ]] )], [AC_MSG_RESULT([ok])], [AC_MSG_ERROR([OpenSSL version too old])] ) fi AC_CHECK_FUNCS([SSL_CTX_new], , [AC_MSG_ERROR([openssl check failed])] ) if test "${with_openssl_engine}" = "auto"; then AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[ #include #include ]], [[ /* Version encoding: MNNFFPPS - see opensslv.h for details */ #if OPENSSL_VERSION_NUMBER >= 0x30000000L #error Engine support disabled by default in OpenSSL 3.0+ #endif /* BoringSSL and LibreSSL >= 3.8.1 removed engine support */ #ifdef OPENSSL_NO_ENGINE #error Engine support disabled in openssl/opensslconf.h #endif ]] )], [have_openssl_engine="yes"], [have_openssl_engine="no"] ) if test "${have_openssl_engine}" = "yes"; then AC_CHECK_FUNCS( [ \ ENGINE_load_builtin_engines \ ENGINE_register_all_complete \ ], , [have_openssl_engine="no"; break] ) fi else have_openssl_engine="${with_openssl_engine}" if test "${have_openssl_engine}" = "yes"; then AC_CHECK_FUNCS( [ \ ENGINE_load_builtin_engines \ ENGINE_register_all_complete \ ], , [AC_MSG_ERROR([OpenSSL engine support not found])] ) fi fi if test "${have_openssl_engine}" = "yes"; then AC_DEFINE([HAVE_OPENSSL_ENGINE], [1], [OpenSSL engine support available]) fi AC_CHECK_FUNC( [EVP_aes_256_gcm], , [AC_MSG_ERROR([OpenSSL check for AES-256-GCM support failed])] ) CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}" AC_DEFINE([ENABLE_CRYPTO_OPENSSL], [1], [Use OpenSSL library]) CRYPTO_CFLAGS="${OPENSSL_CFLAGS}" CRYPTO_LIBS="${OPENSSL_LIBS}" elif test "${with_crypto_library}" = "mbedtls"; then AC_ARG_VAR([MBEDTLS_CFLAGS], [C compiler flags for mbedtls]) AC_ARG_VAR([MBEDTLS_LIBS], [linker flags for mbedtls]) saved_CFLAGS="${CFLAGS}" saved_LIBS="${LIBS}" if test -z "${MBEDTLS_CFLAGS}" -a -z "${MBEDTLS_LIBS}"; then # if the user did not explicitly specify flags, try to autodetect PKG_CHECK_MODULES([MBEDTLS], [mbedtls >= 3.2.1 mbedx509 >= 3.2.1 mbedcrypto >= 3.2.1], [have_mbedtls="yes"], [LIBS="${LIBS} -lmbedtls -lmbedx509 -lmbedcrypto"] ) # mbedtls might not have pkgconfig integration, so try manually if test "${have_mbedtls}" != "yes"; then AC_CHECK_LIB( [mbedtls], [mbedtls_ssl_init], [MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto"], [AC_MSG_ERROR([Could not find mbed TLS.])], ) fi fi CFLAGS="${MBEDTLS_CFLAGS} ${CFLAGS}" LIBS="${MBEDTLS_LIBS} ${LIBS}" AC_MSG_CHECKING([mbedtls version]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ #if MBEDTLS_VERSION_NUMBER < 0x03020100 #error invalid version #endif ]] )], [AC_MSG_RESULT([ok])], [AC_MSG_ERROR([mbed TLS version >= 3.2.1 required])] ) AC_CHECK_HEADERS(psa/crypto.h) CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}" AC_DEFINE([ENABLE_CRYPTO_MBEDTLS], [1], [Use mbed TLS library]) CRYPTO_CFLAGS="${MBEDTLS_CFLAGS}" CRYPTO_LIBS="${MBEDTLS_LIBS}" elif test "${with_crypto_library}" = "wolfssl"; then AC_ARG_VAR([WOLFSSL_CFLAGS], [C compiler flags for wolfssl. The include directory should contain the regular wolfSSL header files but also the wolfSSL OpenSSL header files. Ex: -I/usr/local/include -I/usr/local/include/wolfssl]) AC_ARG_VAR([WOLFSSL_LIBS], [linker flags for wolfssl]) saved_CFLAGS="${CFLAGS}" saved_LIBS="${LIBS}" if test -z "${WOLFSSL_CFLAGS}" -a -z "${WOLFSSL_LIBS}"; then # if the user did not explicitly specify flags, try to autodetect PKG_CHECK_MODULES( [WOLFSSL], [wolfssl], [], [AC_MSG_ERROR([Could not find wolfSSL using pkg-config ${pkg_config_found}])] ) PKG_CHECK_VAR( [WOLFSSL_INCLUDEDIR], [wolfssl], [includedir], [], [AC_MSG_ERROR([Could not find wolfSSL includedir variable.])] ) WOLFSSL_CFLAGS="${WOLFSSL_CFLAGS} -I${WOLFSSL_INCLUDEDIR}/wolfssl" fi saved_CFLAGS="${CFLAGS}" saved_LIBS="${LIBS}" CFLAGS="${CFLAGS} ${WOLFSSL_CFLAGS}" LIBS="${LIBS} ${WOLFSSL_LIBS}" AC_CHECK_LIB( [wolfssl], [wolfSSL_Init], [], [AC_MSG_ERROR([Could not link wolfSSL library.])] ) AC_CHECK_HEADER([wolfssl/options.h],,[AC_MSG_ERROR([wolfSSL header wolfssl/options.h not found!])]) if test "${enable_wolfssl_options_h}" = "yes"; then AC_DEFINE([EXTERNAL_OPTS_OPENVPN], [1], [Include options.h from wolfSSL library]) else AC_DEFINE([WOLFSSL_USER_SETTINGS], [1], [Use custom user_settings.h file for wolfSSL library]) fi CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}" AC_DEFINE([ENABLE_CRYPTO_WOLFSSL], [1], [Use wolfSSL crypto library]) AC_DEFINE([ENABLE_CRYPTO_OPENSSL], [1], [Use wolfSSL openssl compatibility layer]) CRYPTO_CFLAGS="${WOLFSSL_CFLAGS}" CRYPTO_LIBS="${WOLFSSL_LIBS}" else AC_MSG_ERROR([Invalid crypto library: ${with_crypto_library}]) fi AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo]) AC_ARG_VAR([LZO_LIBS], [linker flags for lzo]) if test -z "${LZO_CFLAGS}" -a -z "${LZO_LIBS}"; then # if the user did not explicitly specify flags, try to autodetect PKG_CHECK_MODULES([LZO], [lzo2], [have_lzo="yes"], [] ) if test "${have_lzo}" != "yes"; then # try to detect without pkg-config have_lzo="yes" AC_CHECK_LIB( [lzo2], [lzo1x_1_15_compress], [LZO_LIBS="-llzo2"], [AC_CHECK_LIB( [lzo], [lzo1x_1_15_compress], [LZO_LIBS="-llzo"], [have_lzo="no"] )] ) fi else # assume the user configured it correctly have_lzo="yes" fi if test "${have_lzo}" = "yes"; then saved_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} ${LZO_CFLAGS}" AC_CHECK_HEADERS( [lzo/lzo1x.h], , [AC_CHECK_HEADERS( [lzo1x.h], , [AC_MSG_ERROR([lzo1x.h is missing])], [#include #include #include ] )], ) CFLAGS="${saved_CFLAGS}" fi dnl dnl check for LZ4 library dnl AC_ARG_VAR([LZ4_CFLAGS], [C compiler flags for lz4]) AC_ARG_VAR([LZ4_LIBS], [linker flags for lz4]) if test "$enable_lz4" = "yes" && test "$enable_comp_stub" = "no"; then if test -z "${LZ4_CFLAGS}" -a -z "${LZ4_LIBS}"; then # if the user did not explicitly specify flags, try to autodetect PKG_CHECK_MODULES([LZ4], [liblz4 >= 1.7.1 liblz4 < 100], [have_lz4="yes"], [LZ4_LIBS="-llz4"] # If this fails, we will do another test next. # We also add set LZ4_LIBS otherwise the # linker will not know about the lz4 library ) fi saved_CFLAGS="${CFLAGS}" saved_LIBS="${LIBS}" CFLAGS="${CFLAGS} ${LZ4_CFLAGS}" LIBS="${LIBS} ${LZ4_LIBS}" # If pkgconfig check failed or LZ4_CFLAGS/LZ4_LIBS env vars # are used, check the version directly in the LZ4 include file if test "${have_lz4}" != "yes"; then AC_CHECK_HEADERS([lz4.h], [have_lz4h="yes"], []) if test "${have_lz4h}" = "yes" ; then AC_MSG_CHECKING([additionally if system LZ4 version >= 1.7.1]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[ /* Version encoding: MMNNPP (Major miNor Patch) - see lz4.h for details */ #if LZ4_VERSION_NUMBER < 10701L #error LZ4 is too old #endif ]] )], [ AC_MSG_RESULT([ok]) have_lz4="yes" ], [AC_MSG_ERROR([system LZ4 library is too old])] ) fi fi # Double check we have a few needed functions if test "${have_lz4}" = "yes" ; then AC_CHECK_LIB([lz4], [LZ4_compress_default], [], [have_lz4="no"]) AC_CHECK_LIB([lz4], [LZ4_decompress_safe], [], [have_lz4="no"]) fi if test "${have_lz4}" != "yes" ; then AC_MSG_ERROR([No compatible LZ4 compression library found. Consider --disable-lz4]) LZ4_LIBS="" fi OPTIONAL_LZ4_CFLAGS="${LZ4_CFLAGS}" OPTIONAL_LZ4_LIBS="${LZ4_LIBS}" AC_DEFINE(ENABLE_LZ4, [1], [Enable LZ4 compression library]) CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}" fi dnl dnl Check for systemd dnl AM_CONDITIONAL([ENABLE_SYSTEMD], [test "${enable_systemd}" = "yes"]) if test "$enable_systemd" = "yes" ; then PKG_CHECK_MODULES([libsystemd], [libsystemd > 216], [], [AC_MSG_ERROR([systemd enabled but libsystemd is missing])] ) OPTIONAL_SYSTEMD_CFLAGS="${libsystemd_CFLAGS}" OPTIONAL_SYSTEMD_LIBS="${libsystemd_LIBS}" AC_DEFINE(ENABLE_SYSTEMD, 1, [Enable systemd integration]) if test -n "${SYSTEMD_UNIT_DIR}"; then systemdunitdir="${SYSTEMD_UNIT_DIR}" else systemdunitdir="\${libdir}/systemd/system" fi if test -n "${TMPFILES_DIR}"; then tmpfilesdir="${TMPFILES_DIR}" else tmpfilesdir="\${libdir}/tmpfiles.d" fi fi AC_MSG_CHECKING([git checkout]) GIT_CHECKOUT="no" if test -n "${GIT}"; then if ${GIT} -C "$srcdir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then AC_DEFINE([HAVE_CONFIG_VERSION_H], [1], [extra version available in config-version.h]) GIT_CHECKOUT="yes" fi fi AC_MSG_RESULT([${GIT_CHECKOUT}]) test "${enable_management}" = "yes" && AC_DEFINE([ENABLE_MANAGEMENT], [1], [Enable management server capability]) test "${enable_debug}" = "yes" && AC_DEFINE([ENABLE_DEBUG], [1], [Enable debugging support]) test "${enable_small}" = "yes" && AC_DEFINE([ENABLE_SMALL], [1], [Enable smaller executable size]) test "${enable_fragment}" = "yes" && AC_DEFINE([ENABLE_FRAGMENT], [1], [Enable internal fragmentation support]) test "${enable_port_share}" = "yes" && AC_DEFINE([ENABLE_PORT_SHARE], [1], [Enable TCP Server port sharing]) test "${enable_dns_updown_by_default}" = "yes" && AC_DEFINE([ENABLE_DNS_UPDOWN_BY_DEFAULT], [1], [Enable dns-updown hook by default]) test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes]) OPTIONAL_CRYPTO_CFLAGS="${OPTIONAL_CRYPTO_CFLAGS} ${CRYPTO_CFLAGS}" OPTIONAL_CRYPTO_LIBS="${OPTIONAL_CRYPTO_LIBS} ${CRYPTO_LIBS}" if test "${enable_plugins}" = "yes"; then OPTIONAL_DL_LIBS="${DL_LIBS}" AC_DEFINE([ENABLE_PLUGIN], [1], [Enable plug-in support]) else enable_plugin_auth_pam="no" enable_plugin_down_root="no" fi AM_CONDITIONAL([HAVE_SITNL], [false]) if test "${enable_iproute2}" = "yes"; then test "${enable_dco}" = "yes" && AC_MSG_ERROR([iproute2 support cannot be enabled when using DCO]) test -z "${IPROUTE}" && AC_MSG_ERROR([ip utility is required but missing]) AC_DEFINE([ENABLE_IPROUTE], [1], [enable iproute2 support]) else if test "${have_sitnl}" = "yes"; then AC_DEFINE([ENABLE_SITNL], [1], [enable sitnl support]) AM_CONDITIONAL([HAVE_SITNL], [true]) else if test "${WIN32}" != "yes" -a "${have_sitnl}" != "yes"; then test -z "${ROUTE}" && AC_MSG_ERROR([route utility is required but missing]) test -z "${IFCONFIG}" && AC_MSG_ERROR([ifconfig utility is required but missing]) fi fi fi if test "${enable_selinux}" = "yes"; then test -z "${SELINUX_LIBS}" && AC_MSG_ERROR([libselinux required but missing]) OPTIONAL_SELINUX_LIBS="${SELINUX_LIBS}" AC_DEFINE([ENABLE_SELINUX], [1], [SELinux support]) fi if test "${enable_lzo}" = "yes"; then test "${have_lzo}" != "yes" && AC_MSG_ERROR([lzo enabled but missing]) OPTIONAL_LZO_CFLAGS="${LZO_CFLAGS}" OPTIONAL_LZO_LIBS="${LZO_LIBS}" AC_DEFINE([ENABLE_LZO], [1], [Enable LZO compression library]) fi if test "${enable_comp_stub}" = "yes"; then test "${enable_lzo}" = "yes" && AC_MSG_ERROR([Cannot have both comp stub and lzo enabled (use --disable-lzo)]) test "${enable_lz4}" = "yes" && AC_MSG_ERROR([Cannot have both comp stub and LZ4 enabled (use --disable-lz4)]) AC_DEFINE([ENABLE_COMP_STUB], [1], [Enable compression stub capability]) fi AM_CONDITIONAL([HAVE_SOFTHSM2], [false]) if test "${enable_pkcs11}" = "yes"; then PKG_CHECK_MODULES( [PKCS11_HELPER], [libpkcs11-helper-1 >= 1.11], [have_pkcs11_helper="yes"], [AC_MSG_ERROR([PKCS11 enabled but libpkcs11-helper is missing])] ) OPTIONAL_PKCS11_HELPER_CFLAGS="${PKCS11_HELPER_CFLAGS}" OPTIONAL_PKCS11_HELPER_LIBS="${PKCS11_HELPER_LIBS}" AC_DEFINE([ENABLE_PKCS11], [1], [Enable PKCS11]) PKG_CHECK_MODULES( [P11KIT], [p11-kit-1], [proxy_module="`$PKG_CONFIG --variable=proxy_module p11-kit-1`" AC_DEFINE_UNQUOTED([DEFAULT_PKCS11_MODULE], "${proxy_module}", [p11-kit proxy])], [] ) # # softhsm2 for pkcs11 tests # AC_ARG_VAR([P11TOOL], [full path to p11tool]) AC_PATH_PROGS([P11TOOL], [p11tool],, [$PATH:/usr/local/bin:/usr/bin:/bin]) AC_DEFINE_UNQUOTED([P11TOOL_PATH], ["$P11TOOL"], [Path to p11tool]) AC_ARG_VAR([SOFTHSM2_UTIL], [full path to softhsm2-util]) AC_ARG_VAR([SOFTHSM2_MODULE], [full path to softhsm2 module @<:@default=/usr/lib/softhsm/libsofthsm2.so@:>@]) AC_PATH_PROGS([SOFTHSM2_UTIL], [softhsm2-util],, [$PATH:/usr/local/bin:/usr/bin:/bin]) test -z "$SOFTHSM2_MODULE" && SOFTHSM2_MODULE=/usr/lib/softhsm/libsofthsm2.so AC_DEFINE_UNQUOTED([SOFTHSM2_UTIL_PATH], ["$SOFTHSM2_UTIL"], [Path to softhsm2-util]) AC_DEFINE_UNQUOTED([SOFTHSM2_MODULE_PATH], ["$SOFTHSM2_MODULE"], [Path to softhsm2 module]) if test "${with_crypto_library}" = "openssl"; then AM_CONDITIONAL([HAVE_SOFTHSM2], [test "${P11TOOL}" -a "${SOFTHSM2_UTIL}" -a "${SOFTHSM2_MODULE}"]) fi fi # When testing a compiler option, we add -Werror to force # an error when the option is unsupported. This is not # required for gcc, but some compilers such as clang need it. AC_DEFUN([ACL_CHECK_ADD_COMPILE_FLAGS], [ old_cflags="$CFLAGS" CFLAGS="-Werror $CFLAGS $1" AC_MSG_CHECKING([whether the compiler accepts $1]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [AC_MSG_RESULT([yes])]; CFLAGS="$old_cflags $1", [AC_MSG_RESULT([no]); CFLAGS="$old_cflags"])] ) ACL_CHECK_ADD_COMPILE_FLAGS([-Wno-stringop-truncation]) ACL_CHECK_ADD_COMPILE_FLAGS([-Wstrict-prototypes]) ACL_CHECK_ADD_COMPILE_FLAGS([-Wold-style-definition]) ACL_CHECK_ADD_COMPILE_FLAGS([-Wconversion -Wno-sign-conversion]) ACL_CHECK_ADD_COMPILE_FLAGS([-Wall]) ACL_CHECK_ADD_COMPILE_FLAGS([-Wextra -Wno-unused-parameter]) # clang doesn't have the different levels but also doesn't include it in -Wextra ACL_CHECK_ADD_COMPILE_FLAGS([-Wimplicit-fallthrough=2]) if test "${WIN32}" = "yes"; then # Not sure how to deal with GetProcAddress ACL_CHECK_ADD_COMPILE_FLAGS([-Wno-cast-function-type]) fi if test "${enable_pedantic}" = "yes"; then enable_strict="yes" CFLAGS="${CFLAGS} -pedantic" AC_DEFINE([PEDANTIC], [1], [Enable pedantic mode]) fi if test "${enable_strict}" = "yes"; then CFLAGS="${CFLAGS} -Wsign-compare -Wuninitialized" fi if test "${enable_werror}" = "yes"; then CFLAGS="${CFLAGS} -Werror" fi if test "${enable_plugin_auth_pam}" = "yes"; then PLUGIN_AUTH_PAM_CFLAGS="${LIBPAM_CFLAGS}" if test "${enable_pam_dlopen}" = "yes"; then AC_DEFINE([USE_PAM_DLOPEN], [1], [dlopen libpam]) PLUGIN_AUTH_PAM_LIBS="${DL_LIBS}" else test -z "${LIBPAM_LIBS}" && AC_MSG_ERROR([libpam required but missing]) PLUGIN_AUTH_PAM_LIBS="${LIBPAM_LIBS}" fi fi if test "${enable_async_push}" = "yes"; then case "$host" in *-*-freebsd1[[0-4]]*) PKG_CHECK_MODULES( [OPTIONAL_INOTIFY], [libinotify], [ AC_DEFINE([HAVE_SYS_INOTIFY_H]) AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]) ] ) ;; *) AC_CHECK_HEADERS( [sys/inotify.h], AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]), AC_MSG_ERROR([inotify.h not found.]) ) ;; esac fi CONFIGURE_DEFINES="`set | grep '^enable_.*=' ; set | grep '^with_.*='`" AC_DEFINE_UNQUOTED([CONFIGURE_DEFINES], ["`echo ${CONFIGURE_DEFINES}`"], [Configuration settings]) TAP_WIN_COMPONENT_ID="PRODUCT_TAP_WIN_COMPONENT_ID" TAP_WIN_MIN_MAJOR="PRODUCT_TAP_WIN_MIN_MAJOR" TAP_WIN_MIN_MINOR="PRODUCT_TAP_WIN_MIN_MINOR" AC_DEFINE_UNQUOTED([TAP_WIN_COMPONENT_ID], ["${TAP_WIN_COMPONENT_ID}"], [The tap-windows id]) AC_DEFINE_UNQUOTED([TAP_WIN_MIN_MAJOR], [${TAP_WIN_MIN_MAJOR}], [The tap-windows version number is required for OpenVPN]) AC_DEFINE_UNQUOTED([TAP_WIN_MIN_MINOR], [${TAP_WIN_MIN_MINOR}], [The tap-windows version number is required for OpenVPN]) AC_SUBST([TAP_WIN_COMPONENT_ID]) AC_SUBST([TAP_WIN_MIN_MAJOR]) AC_SUBST([TAP_WIN_MIN_MINOR]) AC_SUBST([OPTIONAL_DL_LIBS]) AC_SUBST([OPTIONAL_SELINUX_LIBS]) AC_SUBST([OPTIONAL_CRYPTO_CFLAGS]) AC_SUBST([OPTIONAL_CRYPTO_LIBS]) AC_SUBST([OPTIONAL_LIBCAPNG_CFLAGS]) AC_SUBST([OPTIONAL_LIBCAPNG_LIBS]) AC_SUBST([OPTIONAL_LIBNL_GENL_CFLAGS]) AC_SUBST([OPTIONAL_LIBNL_GENL_LIBS]) AC_SUBST([OPTIONAL_LZO_CFLAGS]) AC_SUBST([OPTIONAL_LZO_LIBS]) AC_SUBST([OPTIONAL_LZ4_CFLAGS]) AC_SUBST([OPTIONAL_LZ4_LIBS]) AC_SUBST([OPTIONAL_SYSTEMD_CFLAGS]) AC_SUBST([OPTIONAL_SYSTEMD_LIBS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_CFLAGS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_LIBS]) AC_SUBST([OPTIONAL_INOTIFY_CFLAGS]) AC_SUBST([OPTIONAL_INOTIFY_LIBS]) AC_SUBST([PLUGIN_AUTH_PAM_CFLAGS]) AC_SUBST([PLUGIN_AUTH_PAM_LIBS]) AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) AM_CONDITIONAL([GIT_CHECKOUT], [test "${GIT_CHECKOUT}" = "yes"]) AM_CONDITIONAL([ENABLE_PLUGIN_AUTH_PAM], [test "${enable_plugin_auth_pam}" = "yes"]) AM_CONDITIONAL([ENABLE_PLUGIN_DOWN_ROOT], [test "${enable_plugin_down_root}" = "yes"]) AM_CONDITIONAL([HAVE_LD_WRAP_SUPPORT], [test "${have_ld_wrap_support}" = "yes"]) AM_CONDITIONAL([OPENSSL_ENGINE], [test "${have_openssl_engine}" = "yes"]) sampledir="\$(docdir)/sample" AC_SUBST([plugindir]) AC_SUBST([scriptdir]) AC_SUBST([sampledir]) AC_SUBST([systemdunitdir]) AC_SUBST([tmpfilesdir]) AC_ARG_ENABLE( [unit-tests], [AS_HELP_STRING([--disable-unit-tests], [Disables building and running the unit tests suite])], [], [enable_unit_tests="yes"] ) # Check if cmocka is available - needed for unit testing PKG_CHECK_MODULES( [CMOCKA], [cmocka], [have_cmocka="yes"], [AC_MSG_WARN([cmocka.pc not found on the system using pkg-config ${pkg_config_found}. Unit tests disabled])] ) AM_CONDITIONAL([ENABLE_UNITTESTS], [false]) if test "${enable_unit_tests}" = "yes" -a "${have_cmocka}" = "yes"; then AM_CONDITIONAL([ENABLE_UNITTESTS], [true]) saved_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} ${CMOCKA_CFLAGS}" # detect cmocka < 2.0.0 that had no cmocka_version.h AC_CHECK_HEADERS([cmocka_version.h]) CFLAGS="${saved_CFLAGS}" fi AC_SUBST([ENABLE_UNITTESTS]) TEST_LDFLAGS="${OPTIONAL_CRYPTO_LIBS} ${OPTIONAL_PKCS11_HELPER_LIBS} ${OPTIONAL_LIBCAPNG_LIBS}" TEST_LDFLAGS="${TEST_LDFLAGS} ${OPTIONAL_LIBNL_GENL_LIBS}" TEST_LDFLAGS="${TEST_LDFLAGS} ${OPTIONAL_LZO_LIBS} ${CMOCKA_LIBS}" TEST_CFLAGS="${OPTIONAL_CRYPTO_CFLAGS} ${OPTIONAL_PKCS11_HELPER_CFLAGS} ${OPTIONAL_LIBCAPNG_CFLAGS}" TEST_CFLAGS="${TEST_CFLAGS} ${OPTIONAL_LIBNL_GENL_CFLAGS} ${OPTIONAL_LZO_CFLAGS}" TEST_CFLAGS="${TEST_CFLAGS} -I\$(top_srcdir)/include ${CMOCKA_CFLAGS}" AC_SUBST([TEST_LDFLAGS]) AC_SUBST([TEST_CFLAGS]) AC_CONFIG_FILES([ Makefile distro/Makefile distro/systemd/Makefile distro/dns-scripts/Makefile doc/Makefile doc/doxygen/Makefile doc/doxygen/openvpn.doxyfile include/Makefile sample/sample-plugins/Makefile src/Makefile src/compat/Makefile src/openvpn/Makefile src/openvpnmsica/Makefile src/openvpnserv/Makefile src/plugins/Makefile src/plugins/auth-pam/Makefile src/plugins/down-root/Makefile src/tapctl/Makefile tests/Makefile tests/unit_tests/Makefile tests/unit_tests/example_test/Makefile tests/unit_tests/openvpn/Makefile tests/unit_tests/openvpnserv/Makefile tests/unit_tests/plugins/Makefile tests/unit_tests/plugins/auth-pam/Makefile sample/Makefile ]) AC_CONFIG_FILES([tests/t_client.sh], [chmod +x tests/t_client.sh]) AC_OUTPUT ================================================ FILE: contrib/OCSP_check/OCSP_check.sh ================================================ #!/bin/sh # Sample script to perform OCSP queries with OpenSSL # given a certificate serial number. # If you run your own CA, you can set up a very simple # OCSP server using the -port option to "openssl ocsp". # Full documentation and examples: # https://docs.openssl.org/master/man1/openssl-ocsp/#openssl-ocsp # Edit the following values to suit your needs # OCSP responder URL (mandatory) # YOU MUST UNCOMMENT ONE OF THESE AND SET IT TO A VALID SERVER #ocsp_url="http://ocsp.example.com/" #ocsp_url="https://ocsp.secure.example.com/" # Path to issuer certificate (mandatory) # YOU MUST SET THIS TO THE PATH TO THE CA CERTIFICATE issuer="/path/to/CAcert.crt" # use a nonce in the query, set to "-no_nonce" to not use it nonce="-nonce" # Verify the response # YOU MUST SET THIS TO THE PATH TO THE RESPONSE VERIFICATION CERT verify="/path/to/CAcert.crt" # Depth in the certificate chain where the cert to verify is. # Set to -1 to run the verification at every level (NOTE that # in that case you need a more complex script as the various # parameters for the query will likely be different at each level) # "0" is the usual value here, where the client certificate is check_depth=0 cur_depth=$1 # this is the *CURRENT* depth common_name=$2 # CN in case you need it # minimal sanity checks err=0 if [ -z "$issuer" ] || [ ! -e "$issuer" ]; then echo "Error: issuer certificate undefined or not found!" >&2 err=1 fi if [ -z "$verify" ] || [ ! -e "$verify" ]; then echo "Error: verification certificate undefined or not found!" >&2 err=1 fi if [ -z "$ocsp_url" ]; then echo "Error: OCSP server URL not defined!" >&2 err=1 fi if [ $err -eq 1 ]; then echo "Did you forget to customize the variables in the script?" >&2 exit 1 fi # begin if [ $check_depth -eq -1 ] || [ $cur_depth -eq $check_depth ]; then eval serial="\$tls_serial_${cur_depth}" # To successfully complete, the following must happen: # # - The serial number must not be empty # - The exit status of "openssl ocsp" must be zero # - The output of the above command must contain the line # "${serial}: good" # # Everything else fails with exit status 1. if [ -n "$serial" ]; then # This is only an example; you are encouraged to run this command (without # redirections) manually against your or your CA's OCSP server to see how # it responds, and adapt accordingly. # Sample output that is assumed here: # # Response verify OK # 4287405: good # This Update: Apr 24 19:38:49 2010 GMT # Next Update: May 2 14:23:42 2010 GMT # # NOTE: It is needed to check the exit code of OpenSSL explicitly. OpenSSL # can in some circumstances give a "good" result if it could not # reach the OSCP server. In this case, the exit code will indicate # if OpenSSL itself failed or not. If OpenSSL's exit code is not 0, # don't trust the OpenSSL status. status=$(openssl ocsp -issuer "$issuer" \ "$nonce" \ -CAfile "$verify" \ -url "$ocsp_url" \ -serial "${serial}" 2>&1) if [ $? -eq 0 ]; then # check if ocsp didn't report any errors if echo "$status" | grep -Eq "(error|fail)"; then exit 1 fi # check that the reported status of certificate is ok if echo "$status" | grep -Eq "^${serial}: good"; then # check if signature on the OCSP response verified correctly if echo "$status" | grep -Eq "^Response verify OK"; then exit 0 fi fi fi fi # if we get here, something was wrong exit 1 fi ================================================ FILE: contrib/README ================================================ This directory contains scripts and patches contributed by users. ================================================ FILE: contrib/cmake/git-version.py ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2022-2026 OpenVPN Inc # Copyright (C) 2022-2022 Lev Stipakov # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, see . # # Usage: ./git-version.py [directory] # Find a good textual representation of the git commit currently checked out. # Make that representation available as CONFIGURE_GIT_REVISION in # /config-version.h. # It will prefer a tag name if it is checked out exactly, otherwise will use # the branch name. 'none' if no branch is checked out (detached HEAD). # This is used to enhance the output of openvpn --version with Git information. import os import sys import subprocess def run_command(args): sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) o, _ = sp.communicate() return o.decode("utf-8")[:-1] def get_branch_commit_id(): commit_id = run_command(["git", "rev-parse", "--short=16", "HEAD"]) if not commit_id: raise branch = run_command(["git", "describe", "--exact-match"]) if not branch: # this returns an array like ["master"] or ["release", "2.6"] branch = run_command(["git", "rev-parse", "--symbolic-full-name", "HEAD"]).split("/")[2:] if not branch: branch = ["none"] branch = "/" .join(branch) # handle cases like release/2.6 return branch, commit_id def main(): try: branch, commit_id = get_branch_commit_id() except: branch, commit_id = "unknown", "unknown" prev_content = "" name = os.path.join("%s" % (sys.argv[1] if len(sys.argv) > 1 else "."), "config-version.h") try: with open(name, "r") as f: prev_content = f.read() except: # file doesn't exist pass content = "#define CONFIGURE_GIT_REVISION \"%s/%s\"\n" % (branch, commit_id) content += "#define CONFIGURE_GIT_FLAGS \"\"\n" if prev_content != content: print("Writing %s" % name) with open(name, "w") as f: f.write(content) else: print("Content of %s hasn't changed" % name) if __name__ == "__main__": main() ================================================ FILE: contrib/cmake/parse-version.m4.py ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2022-2026 OpenVPN Inc # Copyright (C) 2022-2022 Lev Stipakov # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, see . # # Usage: ./parse-version.m4.py m4file [directory] # Read , extract all lines looking like M4 define(), and translate # them into CMake style set(). Those are then written out to file # /version.cmake. # Intended to be used on top-level version.m4 file. import os import re import sys def main(): assert len(sys.argv) > 1 version_path = sys.argv[1] output = [] with open(version_path, 'r') as version_file: for line in version_file: match = re.match(r'[ \t]*define\(\[(.*)\],[ \t]*\[(.*)\]\)[ \t]*', line) if match is not None: output.append(match.expand(r'set(\1 \2)')) out_path = os.path.join("%s" % (sys.argv[2] if len(sys.argv) > 2 else "."), "version.cmake") prev_content = "" try: with open(out_path, "r") as out_file: prev_content = out_file.read() except: # file doesn't exist pass content = "\n".join(output) + "\n" if prev_content != content: print("Writing %s" % out_path) with open(out_path, "w") as out_file: out_file.write(content) else: print("Content of %s hasn't changed" % out_path) if __name__ == "__main__": main() ================================================ FILE: contrib/extract-crl/extractcrl.py ================================================ #!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' Helper script for CRL (certificate revocation list) file extraction to a directory containing files named as decimal serial numbers of the revoked certificates, to be used with OpenVPN CRL directory verify mode. To enable this mode, directory and 'dir' flag needs to be specified as parameters of '--crl-verify' option. For more information refer OpenVPN tls-options.rst. Usage example: extractcrl.py -f pem /path/to/crl.pem /path/to/outdir extractcrl.py -f der /path/to/crl.crl /path/to/outdir cat /path/to/crl.pem | extractcrl.py -f pem - /path/to/outdir cat /path/to/crl.crl | extractcrl.py -f der - /path/to/outdir Output example: Loaded: 309797 revoked certs in 4.136s Scanned: 312006 files in 0.61s Created: 475 files in 0.05s Removed: 2684 files in 0.116s ''' import argparse import os import sys import time from subprocess import check_output FILETYPE_PEM = 'PEM' FILETYPE_DER = 'DER' def measure_time(method): def elapsed(*args, **kwargs): start = time.time() result = method(*args, **kwargs) return result, round(time.time() - start, 3) return elapsed @measure_time def load_crl(filename, format): def try_openssl_module(filename, format): from cryptography import x509 load_crl_functions = { FILETYPE_PEM: x509.load_pem_x509_crl, FILETYPE_DER: x509.load_der_x509_crl } if filename == '-': crl = load_crl_functions[format](sys.stdin.buffer.read()) else: with open(filename, 'rb') as f: crl = load_crl_functions[format](f.read()) return set(r.serial_number for r in crl) def try_openssl_exec(filename, format): args = ['openssl', 'crl', '-inform', format, '-text'] if filename != '-': args += ['-in', filename] serials = set() for line in check_output(args, universal_newlines=True).splitlines(): _, _, serial = line.partition('Serial Number:') if serial: serials.add(int(serial.strip(), 16)) return serials try: return try_openssl_module(filename, format) except ImportError: return try_openssl_exec(filename, format) @measure_time def scan_dir(dirname): _, _, files = next(os.walk(dirname)) return set(int(f) for f in files if f.isdigit()) @measure_time def create_new_files(dirname, newset, oldset): addset = newset.difference(oldset) for serial in addset: try: with open(os.path.join(dirname, str(serial)), 'xb'): pass except FileExistsError: pass return addset @measure_time def remove_old_files(dirname, newset, oldset): delset = oldset.difference(newset) for serial in delset: try: os.remove(os.path.join(dirname, str(serial))) except FileNotFoundError: pass return delset def check_crlfile(arg): if arg == '-' or os.path.isfile(arg): return arg raise argparse.ArgumentTypeError('No such file "{}"'.format(arg)) def check_outdir(arg): if os.path.isdir(arg): return arg raise argparse.ArgumentTypeError('No such directory: "{}"'.format(arg)) def main(): parser = argparse.ArgumentParser(description='OpenVPN CRL extractor') parser.add_argument('-f', '--format', type=str.upper, default=FILETYPE_PEM, choices=[FILETYPE_PEM, FILETYPE_DER], help='input CRL format - default {}'.format(FILETYPE_PEM) ) parser.add_argument('crlfile', metavar='CRLFILE|-', type=lambda x: check_crlfile(x), help='input CRL file or "-" for stdin' ) parser.add_argument('outdir', metavar='OUTDIR', type=lambda x: check_outdir(x), help='output directory for serials numbers' ) args = parser.parse_args() certs, t = load_crl(args.crlfile, args.format) print('Loaded: {} revoked certs in {}s'.format(len(certs), t)) files, t = scan_dir(args.outdir) print('Scanned: {} files in {}s'.format(len(files), t)) created, t = create_new_files(args.outdir, certs, files) print('Created: {} files in {}s'.format(len(created), t)) removed, t = remove_old_files(args.outdir, certs, files) print('Removed: {} files in {}s'.format(len(removed), t)) if __name__ == "__main__": main() ================================================ FILE: contrib/multilevel-init.patch ================================================ --- /etc/init.d/openvpn 2004-05-12 20:30:06.000000000 +0200 +++ openvpn 2004-05-12 20:34:33.000000000 +0200 @@ -58,13 +58,13 @@ # returning success or failure status to caller (James Yonan). # Location of openvpn binary -openvpn="/usr/sbin/openvpn" +openvpn=/usr/sbin/openvpn # Lockfile -lock="/var/lock/subsys/openvpn" +lock=/var/lock/subsys/openvpn # PID directory -piddir="/var/run/openvpn" +piddir=/var/run/openvpn # Our working directory work=/etc/openvpn @@ -106,7 +106,7 @@ if [ -f $lock ]; then # we were not shut down correctly - for pidf in `/bin/ls $piddir/*.pid $piddir/*/*.pid 2>/dev/null`; do + for pidf in `find $piddir -name "*.pid" 2>/dev/null`; do if [ -s $pidf ]; then kill `cat $pidf` >/dev/null 2>&1 fi @@ -116,12 +116,12 @@ sleep 2 fi - rm -f $piddir/*.pid $piddir/*/*.pid + find $piddir -name "*.pid"|xargs rm -f # Start every .conf in $work and run .sh if exists errors=0 successes=0 - for c in `/bin/ls *.conf */*.conf 2>/dev/null`; do + for c in `find * -name "*.conf" 2>/dev/null`; do bn=${c%%.conf} if [ -f "$bn.sh" ]; then . $bn.sh @@ -147,7 +147,7 @@ ;; stop) echo -n $"Shutting down openvpn: " - for pidf in `/bin/ls $piddir/*.pid $piddir/*/*.pid 2>/dev/null`; do + for pidf in `find $piddir -name "*.pid" 2>/dev/null`; do if [ -s $pidf ]; then kill `cat $pidf` >/dev/null 2>&1 fi @@ -163,7 +163,7 @@ ;; reload) if [ -f $lock ]; then - for pidf in `/bin/ls $piddir/*.pid $piddir/*/*.pid 2>/dev/null`; do + for pidf in `find $piddir -name "*.pid" 2>/dev/null`; do if [ -s $pidf ]; then kill -HUP `cat $pidf` >/dev/null 2>&1 fi @@ -175,7 +175,7 @@ ;; reopen) if [ -f $lock ]; then - for pidf in `/bin/ls $piddir/*.pid $piddir/*/*.pid 2>/dev/null`; do + for pidf in `find $piddir -name "*.pid" 2>/dev/null`; do if [ -s $pidf ]; then kill -USR1 `cat $pidf` >/dev/null 2>&1 fi @@ -195,7 +195,7 @@ ;; status) if [ -f $lock ]; then - for pidf in `/bin/ls $piddir/*.pid $piddir/*/*.pid 2>/dev/null`; do + for pidf in `find $piddir -name "*.pid" 2>/dev/null`; do if [ -s $pidf ]; then kill -USR2 `cat $pidf` >/dev/null 2>&1 fi ================================================ FILE: contrib/openvpn-fwmarkroute-1.00/README ================================================ OpenVPN fwmark Routing Sean Reifschneider, Thursday November 27, 2003 ========================== These scripts can be used with OpenVPN up and down scripts to set up routing on a Linux system such that the VPN traffic is sent via normal network connectivity, but other traffic to that network runs over the VPN. The idea is to allow encryption of data to the network the remote host is on, without interfering with the VPN traffic. You can't simply add a route to the remote network, becaues that will cause the VPN traffic to also try to run over the VPN, and breaks the VPN. These scripts use the Linux "fwmark" iptables rules to specify routing based not only on IP address, but also by port and protocol. This allows you to effectively say "if the packet is to this IP address on this port using this protocol, then use the normal default gateway, otherwise use the VPN gateway. This is set up on the client VPN system, not the VPN server. These scripts also set up all ICMP echo-responses to run across the VPN. You can comment the lines in the scripts to disable this, but I find this useful at coffee shops which have networks that block ICMP. To configure this, you need to set up these scripts as your up and down scripts in the config file. You will need to set these values in the config file: up /etc/openvpn/fwmarkroute.up down /etc/openvpn/fwmarkroute.down up-restart up-delay setenv remote_netmask_bits 24 Note: For this to work, you can't set the "user" or "group" config options, because then the scripts will not run as root. The last setting allows you to control the size of the network the remote system is on. The remote end has to be set up to route, probably with masquerading or NAT. The network this netmask relates to is calculated using the value of "remote" in the conf file. Sean ================================================ FILE: contrib/openvpn-fwmarkroute-1.00/fwmarkroute.down ================================================ #!/bin/sh # # Bring down vpn routing. # calculate the network address remote_network=`ipcalc -n "$remote"/"$remote_netmask_bits"` remote_network="${remote_network#*=}" # clear routing via VPN ip route del "$remote_network"/"$remote_netmask_bits" via "$5" table vpn.out ip route del table vpnonly.out via "$5" iptables -D OUTPUT -t mangle -p "$proto" \ -d "$remote_network"/"$remote_netmask_bits" \ --dport "$remote_port" -j ACCEPT iptables -D OUTPUT -t mangle -d "$remote" -j MARK --set-mark 2 # undo the ICMP ping tunneling iptables -D OUTPUT -t mangle --protocol icmp --icmp-type echo-request \ -j MARK --set-mark 3 # flush route cache ip route flush cache ================================================ FILE: contrib/openvpn-fwmarkroute-1.00/fwmarkroute.up ================================================ #!/bin/sh # # Bring up vpn routing. # calculate the network address remote_network=`ipcalc -n "$remote"/"$remote_netmask_bits"` remote_network="${remote_network#*=}" # add the stuff that doesn't change if it's not already there grep -q '^202 ' /etc/iproute2/rt_tables if [ "$?" -ne 0 ] then echo 202 vpn.out >> /etc/iproute2/rt_tables fi grep -q '^203 ' /etc/iproute2/rt_tables if [ "$?" -ne 0 ] then echo 203 vpnonly.out >> /etc/iproute2/rt_tables fi ip rule ls | grep -q 'lookup vpn.out *$' if [ "$?" -ne 0 ] then ip rule add fwmark 2 table vpn.out fi ip rule ls | grep -q 'lookup vpnonly.out *$' if [ "$?" -ne 0 ] then ip rule add fwmark 3 table vpnonly.out fi # route VPN traffic using the normal table iptables -A OUTPUT -t mangle -p "$proto" -d "$remote" --dport "$remote_port" \ -j ACCEPT # route all other traffic to that host via VPN iptables -A OUTPUT -t mangle -d "$remote_network"/"$remote_netmask_bits" \ -j MARK --set-mark 2 # route all ICMP pings over the VPN iptables -A OUTPUT -t mangle --protocol icmp --icmp-type echo-request \ -j MARK --set-mark 3 # NAT traffic going over the VPN, so it doesn't have an unknown address iptables -t nat -A POSTROUTING -o "$1" -j SNAT --to-source "$4" # add routing commands ip route add "$remote_network"/"$remote_netmask_bits" via "$5" table vpn.out ip route add table vpnonly.out via "$5" ip route flush cache ================================================ FILE: contrib/vcpkg-manifests/mingw/vcpkg.json ================================================ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "openvpn", "version": "2.7", "dependencies": [ "openssl", "tap-windows6", "lzo", "lz4", "pkcs11-helper", "cmocka" ] } ================================================ FILE: contrib/vcpkg-manifests/windows/vcpkg.json ================================================ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "openvpn", "version": "2.7", "dependencies": [ { "name": "openssl", "features": ["tools"] }, "tap-windows6", "lzo", "lz4", "pkcs11-helper", "cmocka", { "name": "pkgconf", "host": true } ] } ================================================ FILE: contrib/vcpkg-ports/pkcs11-helper/config-w32-vc.h.in-indicate-OpenSSL.patch ================================================ From c2293864de70fec322fe7e559055530ef56b9641 Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Tue, 11 Jan 2022 13:35:42 +0200 Subject: [PATCH] config-w32-vc.h.in: indicate OpenSSL EC support Signed-off-by: Lev Stipakov --- config-w32-vc.h.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/config-w32-vc.h b/config-w32-vc.h index 6d94841..db83825 100644 --- a/config-w32-vc.h +++ b/config-w32-vc.h @@ -218,3 +218,15 @@ /* Define to 1 if you have the `DSA_SIG_set0' function. */ #define HAVE_DSA_SIG_SET0 1 + +/* Define to 1 if you have the `ECDSA_SIG_set0' function. */ +#define HAVE_ECDSA_SIG_SET0 1 + +/* Define to 1 if you have the `EC_KEY_METHOD_get_sign' function. */ +#define HAVE_EC_KEY_METHOD_GET_SIGN 1 + +/* Define to 1 if you have the `EC_KEY_METHOD_set_sign' function. */ +#define HAVE_EC_KEY_METHOD_SET_SIGN 1 + +/* Define to 1 if OpenSSL has EC support. */ +#define ENABLE_PKCS11H_OPENSSL_EC 1 -- 2.23.0.windows.1 ================================================ FILE: contrib/vcpkg-ports/pkcs11-helper/nmake-compatibility-with-vcpkg-nmake.patch ================================================ From 2d3a2c05383f653544b9c7194dd1349c6d5f3067 Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Tue, 11 Jan 2022 13:24:51 +0200 Subject: [PATCH] nmake: compatibility with vcpkg nmake Remove options which contradict or already set by vcpkg nmake scripts. Signed-off-by: Lev Stipakov --- lib/Makefile.w32-vc | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/Makefile.w32-vc b/lib/Makefile.w32-vc index 96f1f89..be68a00 100644 --- a/lib/Makefile.w32-vc +++ b/lib/Makefile.w32-vc @@ -75,15 +75,11 @@ OPENSSL_LIBS=-LIBPATH:$(OPENSSL_LIB) user32.lib advapi32.lib $(OPENSSL_STATIC) CFLAGS = -I../include $(OPENSSL_CFLAGS) -DWIN32 -DWIN32_LEAN_AND_MEAN -D_MBCS -D_CRT_SECURE_NO_DEPRECATE -D_WIN32_WINNT=0x0400 CC=cl.exe RC=rc.exe -CCPARAMS=/nologo /W3 /O2 /FD /c - -CCPARAMS=$(CCPARAMS) /MD -CFLAGS=$(CFLAGS) -DNDEBUG +CCPARAMS=/c LINK32=link.exe LIB32=lib.exe -LINK32_FLAGS=/nologo /subsystem:windows /dll /incremental:no /release -LIB32_FLAGS=/nologo +LINK32_FLAGS=/dll HEADERS = \ config.h \ -- 2.23.0.windows.1 ================================================ FILE: contrib/vcpkg-ports/pkcs11-helper/pkcs11-helper-001-RFC7512.patch ================================================ upstream PR: https://github.com/OpenSC/pkcs11-helper/pull/4 Rebased to 1.31.0 by selva.nair@gmail.com commit 90590b02085edc3830bdfe0942a46c4e7bf3f1ab (HEAD -> master) Author: David Woodhouse Date: Thu Apr 30 14:58:24 2015 +0100 Serialize to RFC7512-compliant PKCS#11 URIs Signed-off-by: David Woodhouse commit 4d5280da8df591aab701dff4493d13a835a9b29c Author: David Woodhouse Date: Wed Dec 10 14:00:21 2014 +0000 Accept RFC7512-compliant PKCS#11 URIs as serialized token/certificate IDs The old format is still accepted for compatibility. Signed-off-by: David Woodhouse commit 14e09211c3d50eb06825090c9765e4382cf52f19 Author: David Woodhouse Date: Sun Dec 14 19:42:18 2014 +0000 Stop _pkcs11h_util_hexToBinary() checking for trailing NUL We are going to want to use this for parsing %XX hex escapes in RFC7512 PKCS#11 URIs, where we cannot expect a trailing NUL. Since there's only one existing caller at the moment, it's simple just to let the caller have responsibility for that check. Signed-off-by: David Woodhouse diff --git a/lib/pkcs11h-serialization.c b/lib/pkcs11h-serialization.c index ad275f8..1d077e4 100644 --- a/lib/pkcs11h-serialization.c +++ b/lib/pkcs11h-serialization.c @@ -61,29 +61,127 @@ #if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE) +#define URI_SCHEME "pkcs11:" + +#define token_field_ofs(field) ((unsigned long)&(((struct pkcs11h_token_id_s *)0)->field)) +#define token_field_size(field) sizeof((((struct pkcs11h_token_id_s *)0)->field)) +#define token_field(name, field) { name "=", sizeof(name), \ + token_field_ofs(field), token_field_size(field) } + +static struct { + const char const *name; + size_t namelen; + unsigned long field_ofs; + size_t field_size; +} __token_fields[] = { + token_field ("model", model), + token_field ("token", label), + token_field ("manufacturer", manufacturerID ), + token_field ("serial", serialNumber ), + { NULL }, +}; + +#define P11_URL_VERBATIM "abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "0123456789_-." + +static +int +__token_attr_escape(char *uri, char *attr, size_t attrlen) +{ + int len = 0, i; + + for (i = 0; i < attrlen; i++) { + if ((attr[i] != '\x0') && strchr(P11_URL_VERBATIM, attr[i])) { + if (uri) { + *(uri++) = attr[i]; + } + len++; + } else { + if (uri) { + sprintf(uri, "%%%02x", (unsigned char)attr[i]); + uri += 3; + } + len += 3; + } + } + return len; +} + +static +CK_RV +__generate_pkcs11_uri ( + OUT char * const sz, + IN OUT size_t *max, + IN const pkcs11h_certificate_id_t certificate_id, + IN const pkcs11h_token_id_t token_id +) { + size_t _max; + char *p = sz; + int i; + + _PKCS11H_ASSERT (max!=NULL); + _PKCS11H_ASSERT (token_id!=NULL); + + _max = strlen(URI_SCHEME); + for (i = 0; __token_fields[i].name; i++) { + char *field = ((char *)token_id) + __token_fields[i].field_ofs; + + _max += __token_fields[i].namelen; + _max += __token_attr_escape (NULL, field, strlen(field)); + _max++; /* For a semicolon or trailing NUL */ + } + if (certificate_id) { + _max += strlen (";id="); + _max += __token_attr_escape (NULL, + (char *)certificate_id->attrCKA_ID, + certificate_id->attrCKA_ID_size); + } + + if (!sz) { + *max = _max; + return CKR_OK; + } + + if (sz && *max < _max) + return CKR_ATTRIBUTE_VALUE_INVALID; + + p += sprintf(p, URI_SCHEME); + for (i = 0; __token_fields[i].name; i++) { + char *field = ((char *)token_id) + __token_fields[i].field_ofs; + + p += sprintf (p, "%s", __token_fields[i].name); + p += __token_attr_escape (p, field, strlen(field)); + *(p++) = ';'; + } + if (certificate_id) { + p += sprintf (p, "id="); + p += __token_attr_escape (p, + (char *)certificate_id->attrCKA_ID, + certificate_id->attrCKA_ID_size); + } else { + /* Remove the unneeded trailing semicolon */ + p--; + } + *(p++) = 0; + + *max = _max; + + return CKR_OK; +} + CK_RV pkcs11h_token_serializeTokenId ( OUT char * const sz, IN OUT size_t *max, IN const pkcs11h_token_id_t token_id ) { - const char *sources[5]; CK_RV rv = CKR_FUNCTION_FAILED; - size_t n; - int e; /*_PKCS11H_ASSERT (sz!=NULL); Not required*/ _PKCS11H_ASSERT (max!=NULL); _PKCS11H_ASSERT (token_id!=NULL); - { /* Must be after assert */ - sources[0] = token_id->manufacturerID; - sources[1] = token_id->model; - sources[2] = token_id->serialNumber; - sources[3] = token_id->label; - sources[4] = NULL; - } - _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_token_serializeTokenId entry sz=%p, *max="P_Z", token_id=%p", @@ -92,67 +190,161 @@ pkcs11h_token_serializeTokenId ( (void *)token_id ); - n = 0; - for (e=0;sources[e] != NULL;e++) { - size_t t; - if ( - (rv = _pkcs11h_util_escapeString ( - NULL, - sources[e], - &t, - __PKCS11H_SERIALIZE_INVALID_CHARS - )) != CKR_OK - ) { - goto cleanup; + rv = __generate_pkcs11_uri(sz, max, NULL, token_id); + + _PKCS11H_DEBUG ( + PKCS11H_LOG_DEBUG2, + "PKCS#11: pkcs11h_token_serializeTokenId return rv=%lu-'%s', *max="P_Z", sz='%s'", + rv, + pkcs11h_getMessage (rv), + *max, + sz + ); + + return rv; +} + +static +CK_RV +__parse_token_uri_attr ( + const char *uri, + size_t urilen, + char *tokstr, + size_t toklen, + size_t *parsed_len +) { + size_t orig_toklen = toklen; + CK_RV rv = CKR_OK; + + while (urilen && toklen > 1) { + if (*uri == '%') { + size_t size = 1; + + if (urilen < 3) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto done; + } + + rv = _pkcs11h_util_hexToBinary ((unsigned char *)tokstr, + uri + 1, &size); + if (rv != CKR_OK) { + goto done; + } + + uri += 2; + urilen -= 2; + } else { + *tokstr = *uri; } - n+=t; + tokstr++; + uri++; + toklen--; + urilen--; + tokstr[0] = 0; } - if (sz != NULL) { - if (*max < n) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto cleanup; + if (urilen) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + } else if (parsed_len) { + *parsed_len = orig_toklen - toklen; + } + + done: + return rv; +} + +static +CK_RV +__parse_pkcs11_uri ( + OUT pkcs11h_token_id_t token_id, + OUT pkcs11h_certificate_id_t certificate_id, + IN const char * const sz +) { + const char *end, *p; + CK_RV rv = CKR_OK; + + _PKCS11H_ASSERT (token_id!=NULL); + _PKCS11H_ASSERT (sz!=NULL); + + if (strncmp (sz, URI_SCHEME, strlen (URI_SCHEME))) + return CKR_ATTRIBUTE_VALUE_INVALID; + + end = sz + strlen (URI_SCHEME) - 1; + while (rv == CKR_OK && end[0] && end[1]) { + int i; + + p = end + 1; + end = strchr (p, ';'); + if (!end) + end = p + strlen(p); + + for (i = 0; __token_fields[i].name; i++) { + /* Parse the token=, label=, manufacturer= and serial= fields */ + if (!strncmp(p, __token_fields[i].name, __token_fields[i].namelen)) { + char *field = ((char *)token_id) + __token_fields[i].field_ofs; + + p += __token_fields[i].namelen; + rv = __parse_token_uri_attr (p, end - p, field, + __token_fields[i].field_size, + NULL); + if (rv != CKR_OK) { + goto cleanup; + } + + goto matched; + } } + if (certificate_id && !strncmp(p, "id=", 3)) { + p += 3; + + rv = _pkcs11h_mem_malloc ((void *)&certificate_id->attrCKA_ID, + end - p + 1); + if (rv != CKR_OK) { + goto cleanup; + } - n = 0; - for (e=0;sources[e] != NULL;e++) { - size_t t = *max-n; - if ( - (rv = _pkcs11h_util_escapeString ( - sz+n, - sources[e], - &t, - __PKCS11H_SERIALIZE_INVALID_CHARS - )) != CKR_OK - ) { + rv = __parse_token_uri_attr (p, end - p, + (char *)certificate_id->attrCKA_ID, + end - p + 1, + &certificate_id->attrCKA_ID_size); + if (rv != CKR_OK) { goto cleanup; } - n+=t; - sz[n-1] = '/'; + + goto matched; } - sz[n-1] = '\x0'; - } - *max = n; - rv = CKR_OK; + /* We don't parse object= because the match code doesn't support + matching by label. */ + + /* Failed to parse PKCS#11 URI element. */ + return CKR_ATTRIBUTE_VALUE_INVALID; + matched: + ; + } cleanup: + /* The matching code doesn't support support partial matches; it needs + * *all* of manufacturer, model, serial and label attributes to be + * defined. So reject partial URIs early instead of letting it do the + * wrong thing. We can maybe improve this later. */ + if (!token_id->model[0] || !token_id->label[0] || + !token_id->manufacturerID[0] || !token_id->serialNumber[0]) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } - _PKCS11H_DEBUG ( - PKCS11H_LOG_DEBUG2, - "PKCS#11: pkcs11h_token_serializeTokenId return rv=%lu-'%s', *max="P_Z", sz='%s'", - rv, - pkcs11h_getMessage (rv), - *max, - sz - ); + /* For a certificate ID we need CKA_ID */ + if (certificate_id && !certificate_id->attrCKA_ID_size) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } return rv; } +static CK_RV -pkcs11h_token_deserializeTokenId ( - OUT pkcs11h_token_id_t *p_token_id, +__pkcs11h_token_legacy_deserializeTokenId ( + OUT pkcs11h_token_id_t token_id, IN const char * const sz ) { #define __PKCS11H_TARGETS_NUMBER 4 @@ -161,24 +353,11 @@ pkcs11h_token_deserializeTokenId ( size_t s; } targets[__PKCS11H_TARGETS_NUMBER]; - pkcs11h_token_id_t token_id = NULL; char *p1 = NULL; char *_sz = NULL; int e; CK_RV rv = CKR_FUNCTION_FAILED; - _PKCS11H_ASSERT (p_token_id!=NULL); - _PKCS11H_ASSERT (sz!=NULL); - - _PKCS11H_DEBUG ( - PKCS11H_LOG_DEBUG2, - "PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'", - (void *)p_token_id, - sz - ); - - *p_token_id = NULL; - if ( (rv = _pkcs11h_mem_strdup ( (void *)&_sz, @@ -190,10 +369,6 @@ pkcs11h_token_deserializeTokenId ( p1 = _sz; - if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) { - goto cleanup; - } - targets[0].p = token_id->manufacturerID; targets[0].s = sizeof (token_id->manufacturerID); targets[1].p = token_id->model; @@ -252,6 +427,51 @@ pkcs11h_token_deserializeTokenId ( p1 = p2+1; } + rv = CKR_OK; + +cleanup: + + if (_sz != NULL) { + _pkcs11h_mem_free ((void *)&_sz); + } + + return rv; +#undef __PKCS11H_TARGETS_NUMBER +} + +CK_RV +pkcs11h_token_deserializeTokenId ( + OUT pkcs11h_token_id_t *p_token_id, + IN const char * const sz +) { + pkcs11h_token_id_t token_id = NULL; + CK_RV rv = CKR_FUNCTION_FAILED; + + _PKCS11H_ASSERT (p_token_id!=NULL); + _PKCS11H_ASSERT (sz!=NULL); + + _PKCS11H_DEBUG ( + PKCS11H_LOG_DEBUG2, + "PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'", + (void *)p_token_id, + sz + ); + + *p_token_id = NULL; + + if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) { + goto cleanup; + } + + if (!strncmp (sz, URI_SCHEME, strlen (URI_SCHEME))) { + rv = __parse_pkcs11_uri(token_id, NULL, sz); + } else { + rv = __pkcs11h_token_legacy_deserializeTokenId(token_id, sz); + } + if (rv != CKR_OK) { + goto cleanup; + } + strncpy ( token_id->display, token_id->label, @@ -264,11 +484,6 @@ pkcs11h_token_deserializeTokenId ( rv = CKR_OK; cleanup: - - if (_sz != NULL) { - _pkcs11h_mem_free ((void *)&_sz); - } - if (token_id != NULL) { pkcs11h_token_freeTokenId (token_id); } @@ -281,7 +496,6 @@ cleanup: ); return rv; -#undef __PKCS11H_TARGETS_NUMBER } #endif /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */ @@ -295,9 +509,6 @@ pkcs11h_certificate_serializeCertificateId ( IN const pkcs11h_certificate_id_t certificate_id ) { CK_RV rv = CKR_FUNCTION_FAILED; - size_t saved_max = 0; - size_t n = 0; - size_t _max = 0; /*_PKCS11H_ASSERT (sz!=NULL); Not required */ _PKCS11H_ASSERT (max!=NULL); @@ -311,42 +522,7 @@ pkcs11h_certificate_serializeCertificateId ( (void *)certificate_id ); - if (sz != NULL) { - saved_max = n = *max; - } - *max = 0; - - if ( - (rv = pkcs11h_token_serializeTokenId ( - sz, - &n, - certificate_id->token_id - )) != CKR_OK - ) { - goto cleanup; - } - - _max = n + certificate_id->attrCKA_ID_size*2 + 1; - - if (sz != NULL) { - if (saved_max < _max) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto cleanup; - } - - sz[n-1] = '/'; - rv = _pkcs11h_util_binaryToHex ( - sz+n, - saved_max-n, - certificate_id->attrCKA_ID, - certificate_id->attrCKA_ID_size - ); - } - - *max = _max; - rv = CKR_OK; - -cleanup: + rv = __generate_pkcs11_uri(sz, max, certificate_id, certificate_id->token_id); _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, @@ -360,27 +536,16 @@ cleanup: return rv; } +static CK_RV -pkcs11h_certificate_deserializeCertificateId ( - OUT pkcs11h_certificate_id_t * const p_certificate_id, +__pkcs11h_certificate_legacy_deserializeCertificateId ( + OUT pkcs11h_certificate_id_t certificate_id, IN const char * const sz ) { - pkcs11h_certificate_id_t certificate_id = NULL; CK_RV rv = CKR_FUNCTION_FAILED; char *p = NULL; char *_sz = NULL; - - _PKCS11H_ASSERT (p_certificate_id!=NULL); - _PKCS11H_ASSERT (sz!=NULL); - - *p_certificate_id = NULL; - - _PKCS11H_DEBUG ( - PKCS11H_LOG_DEBUG2, - "PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'", - (void *)p_certificate_id, - sz - ); + size_t id_hex_len; if ( (rv = _pkcs11h_mem_strdup ( @@ -393,10 +558,6 @@ pkcs11h_certificate_deserializeCertificateId ( p = _sz; - if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) { - goto cleanup; - } - if ((p = strrchr (_sz, '/')) == NULL) { rv = CKR_ATTRIBUTE_VALUE_INVALID; goto cleanup; @@ -414,7 +575,12 @@ pkcs11h_certificate_deserializeCertificateId ( goto cleanup; } - certificate_id->attrCKA_ID_size = strlen (p)/2; + id_hex_len = strlen (p); + if (id_hex_len & 1) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto cleanup; + } + certificate_id->attrCKA_ID_size = id_hex_len/2; if (certificate_id->attrCKA_ID_size == 0) { rv = CKR_ATTRIBUTE_VALUE_INVALID; @@ -434,21 +600,64 @@ pkcs11h_certificate_deserializeCertificateId ( goto cleanup; } + rv = CKR_OK; + +cleanup: + + if (_sz != NULL) { + _pkcs11h_mem_free ((void *)&_sz); + } + + return rv; + +} + +CK_RV +pkcs11h_certificate_deserializeCertificateId ( + OUT pkcs11h_certificate_id_t * const p_certificate_id, + IN const char * const sz +) { + pkcs11h_certificate_id_t certificate_id = NULL; + CK_RV rv = CKR_FUNCTION_FAILED; + + _PKCS11H_ASSERT (p_certificate_id!=NULL); + _PKCS11H_ASSERT (sz!=NULL); + + *p_certificate_id = NULL; + + _PKCS11H_DEBUG ( + PKCS11H_LOG_DEBUG2, + "PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'", + (void *)p_certificate_id, + sz + ); + + if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) { + goto cleanup; + } + if ((rv = _pkcs11h_token_newTokenId (&certificate_id->token_id)) != CKR_OK) { + goto cleanup; + } + + if (!strncmp(sz, URI_SCHEME, strlen (URI_SCHEME))) { + rv = __parse_pkcs11_uri (certificate_id->token_id, certificate_id, sz); + } else { + rv = __pkcs11h_certificate_legacy_deserializeCertificateId (certificate_id, sz); + } + if (rv != CKR_OK) { + goto cleanup; + } + *p_certificate_id = certificate_id; certificate_id = NULL; rv = CKR_OK; cleanup: - if (certificate_id != NULL) { pkcs11h_certificate_freeCertificateId (certificate_id); certificate_id = NULL; } - if (_sz != NULL) { - _pkcs11h_mem_free ((void *)&_sz); - } - _PKCS11H_DEBUG ( PKCS11H_LOG_DEBUG2, "PKCS#11: pkcs11h_certificate_deserializeCertificateId return rv=%lu-'%s'", diff --git a/lib/pkcs11h-util.c b/lib/pkcs11h-util.c index 1fcadfc..a304642 100644 --- a/lib/pkcs11h-util.c +++ b/lib/pkcs11h-util.c @@ -123,10 +123,6 @@ _pkcs11h_util_hexToBinary ( (*p_target_size)++; } - if (*p != '\x0') { - goto cleanup; - } - ret = CKR_OK; cleanup: ================================================ FILE: contrib/vcpkg-ports/pkcs11-helper/portfile.cmake ================================================ vcpkg_download_distfile(ARCHIVE URLS "https://github.com/OpenSC/pkcs11-helper/releases/download/pkcs11-helper-${VERSION}/pkcs11-helper-${VERSION}.tar.bz2" FILENAME "pkcs11-helper-${VERSION}.tar.bz2" SHA512 0833efc59e9093dd398a54640d858b01a830ef7adfb40321c1e0ed0afa004500fc1259cc66bc49c5263935adeda0a3bfe658de538eefd66888685a71f731c484 ) vcpkg_extract_source_archive( SOURCE_PATH ARCHIVE ${ARCHIVE} PATCHES nmake-compatibility-with-vcpkg-nmake.patch config-w32-vc.h.in-indicate-OpenSSL.patch pkcs11-helper-001-RFC7512.patch ) if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) vcpkg_build_nmake( SOURCE_PATH ${SOURCE_PATH} PROJECT_SUBPATH lib PROJECT_NAME Makefile.w32-vc OPTIONS OPENSSL=1 OPENSSL_HOME=${CURRENT_PACKAGES_DIR}/../openssl_${TARGET_TRIPLET} ) file(INSTALL ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/lib/pkcs11-helper.dll.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib RENAME pkcs11-helper.lib) file(INSTALL ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/lib/pkcs11-helper.dll.lib DESTINATION ${CURRENT_PACKAGES_DIR}/debug/lib RENAME pkcs11-helper.lib) file(INSTALL ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/lib/libpkcs11-helper-1.dll DESTINATION ${CURRENT_PACKAGES_DIR}/bin) file(INSTALL ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/lib/libpkcs11-helper-1.dll DESTINATION ${CURRENT_PACKAGES_DIR}/debug/bin) set(PACKAGE_VERSION "${VERSION}") set(libdir [[${prefix}/lib]]) set(exec_prefix [[${prefix}]]) set(PKCS11H_FEATURES key_prompt openssl engine_crypto_cryptoapi engine_crypto_openssl debug threading token data certificate slotevent engine_crypto) set(LIBS -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32) if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") set(includedir [[${prefix}/include]]) set(outfile "${CURRENT_PACKAGES_DIR}/lib/pkgconfig/libpkcs11-helper-1.pc") configure_file("${SOURCE_PATH}/lib/libpkcs11-helper-1.pc.in" "${outfile}" @ONLY) endif() if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") set(includedir [[${prefix}/../include]]) set(outfile "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libpkcs11-helper-1.pc") configure_file("${SOURCE_PATH}/lib/libpkcs11-helper-1.pc.in" "${outfile}" @ONLY) endif() file(INSTALL ${SOURCE_PATH}/include/pkcs11-helper-1.0 DESTINATION ${CURRENT_PACKAGES_DIR}/include/) else() find_program(man_to_html man2html REQUIRED) vcpkg_configure_make( SOURCE_PATH ${SOURCE_PATH} OPTIONS --disable-crypto-engine-gnutls --disable-crypto-engine-nss --disable-crypto-engine-polarssl --disable-crypto-engine-mbedtls ) vcpkg_install_make() file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") endif() vcpkg_fixup_pkgconfig() vcpkg_copy_pdbs() vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/COPYING") ================================================ FILE: contrib/vcpkg-ports/pkcs11-helper/vcpkg.json ================================================ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "pkcs11-helper", "version": "1.31.0", "description": "pkcs11-helper is a library that simplifies the interaction with PKCS#11 providers for end-user applications.", "homepage": "https://github.com/OpenSC/pkcs11-helper", "license": "BSD-3-Clause OR GPL-2.0-only", "dependencies": [ "openssl" ] } ================================================ FILE: contrib/vcpkg-triplets/arm64-windows-ovpn.cmake ================================================ set(VCPKG_TARGET_ARCHITECTURE arm64) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE dynamic) set(STATIC_PORTS lz4 lzo) if(PORT IN_LIST STATIC_PORTS) set(VCPKG_LIBRARY_LINKAGE static) endif() ================================================ FILE: contrib/vcpkg-triplets/x64-mingw-ovpn.cmake ================================================ set(VCPKG_TARGET_ARCHITECTURE x64) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE static) set(VCPKG_ENV_PASSTHROUGH PATH) set(VCPKG_CMAKE_SYSTEM_NAME MinGW) set(VCPKG_MAKE_BUILD_TRIPLET --host=x86_64-w64-mingw32) ================================================ FILE: contrib/vcpkg-triplets/x64-windows-ovpn.cmake ================================================ set(VCPKG_TARGET_ARCHITECTURE x64) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE dynamic) set(STATIC_PORTS lz4 lzo) if(PORT IN_LIST STATIC_PORTS) set(VCPKG_LIBRARY_LINKAGE static) endif() ================================================ FILE: contrib/vcpkg-triplets/x86-mingw-ovpn.cmake ================================================ set(VCPKG_TARGET_ARCHITECTURE x86) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE static) set(VCPKG_ENV_PASSTHROUGH PATH) set(VCPKG_CMAKE_SYSTEM_NAME MinGW) set(VCPKG_MAKE_BUILD_TRIPLET --host=i686-w64-mingw32) ================================================ FILE: contrib/vcpkg-triplets/x86-windows-ovpn.cmake ================================================ set(VCPKG_TARGET_ARCHITECTURE x86) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE dynamic) set(STATIC_PORTS lz4 lzo) if(PORT IN_LIST STATIC_PORTS) set(VCPKG_LIBRARY_LINKAGE static) endif() ================================================ FILE: debug/doval ================================================ #!/bin/bash PROGDIR=`dirname $0` unset LD_LIBRARY_PATH valgrind --tool=memcheck --error-limit=no --suppressions=$PROGDIR/debug/valgrind-suppress --gen-suppressions=all --leak-check=full --show-reachable=yes --num-callers=32 $PROGDIR/openvpn "$@" ================================================ FILE: debug/dovalns ================================================ #!/bin/bash valgrind --tool=memcheck --error-limit=no --gen-suppressions=all --leak-check=full --show-reachable=yes --num-callers=32 $* ================================================ FILE: debug/valgrind-suppress ================================================ { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function fun:__nss_next fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlopen fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlopen fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlsym fun:libdl_resolve_symbol fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Addr8 obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlopen fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Addr8 obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/libc-2.7.so obj:/lib/ld-2.7.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.7.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Addr8 obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/libc-2.7.so obj:/lib/ld-2.7.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.7.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Addr8 obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/libc-2.7.so obj:/lib/ld-2.7.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.7.so fun:getgrnam_r fun:getgrnam fun:get_group fun:management_open fun:open_management fun:main } { Memcheck:Addr8 obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/ld-2.7.so obj:/lib/libc-2.7.so obj:/lib/ld-2.7.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.7.so fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Cond fun:BN_div fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_verify fun:EVP_VerifyFinal fun:ASN1_item_verify obj:/usr/lib/libcrypto.so.0.9.8 fun:X509_verify_cert fun:ssl_verify_cert_chain fun:ssl3_get_client_certificate fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action } { Memcheck:Cond fun:BN_div fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_div fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Cond fun:BN_div fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_sign fun:ssl3_send_server_key_exchange fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_div fun:BN_MONT_CTX_set fun:BN_mod_exp_mont fun:BN_BLINDING_create_param fun:RSA_setup_blinding obj:/usr/lib/libcrypto.so.0.9.8 obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_sign fun:ssl3_send_server_key_exchange fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_div fun:BN_nnmod fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_div fun:BN_nnmod fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Cond fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_verify fun:EVP_VerifyFinal fun:ASN1_item_verify obj:/usr/lib/libcrypto.so.0.9.8 fun:X509_verify_cert fun:ssl_verify_cert_chain fun:ssl3_get_client_certificate fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action } { Memcheck:Cond fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 fun:ssl3_ctx_ctrl fun:init_ssl fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Cond fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_MONT_CTX_set_locked obj:/usr/lib/libcrypto.so.0.9.8 obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_sign fun:ssl3_send_server_key_exchange fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action fun:tunnel_server_tcp fun:main } { Memcheck:Cond fun:BN_mod_inverse fun:BN_MONT_CTX_set fun:BN_mod_exp_mont fun:BN_BLINDING_create_param fun:RSA_setup_blinding obj:/usr/lib/libcrypto.so.0.9.8 obj:/usr/lib/libcrypto.so.0.9.8 fun:RSA_sign fun:ssl3_send_server_key_exchange fun:ssl3_accept fun:ssl3_read_bytes fun:ssl3_read obj:/usr/lib/libssl.so.0.9.8 fun:BIO_read fun:bio_read fun:tls_process fun:tls_multi_process fun:check_tls_dowork fun:pre_select fun:multi_process_post fun:multi_process_incoming_link fun:multi_tcp_action fun:tunnel_server_tcp fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:* obj:* obj:* } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function fun:__nss_next fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function fun:__nss_next fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function fun:__nss_next fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:gethostbyname_r fun:gethostbyname fun:getaddr fun:resolve_remote fun:link_socket_init_phase1 fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/ld-2.5.so fun:__libc_dlopen_mode fun:__nss_lookup_function obj:/lib/libc-2.5.so fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libc-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlsym fun:libdl_resolve_symbol fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Cond obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so obj:/lib/ld-2.5.so obj:/lib/libdl-2.5.so fun:dlopen fun:plugin_list_init fun:init_plugins fun:main } { Memcheck:Leak fun:malloc fun:CRYPTO_malloc fun:sk_new obj:/usr/lib/libssl.so.0.9.8 fun:SSL_COMP_get_compression_methods fun:SSL_library_init fun:init_ssl_lib fun:init_static fun:main } { Memcheck:Leak fun:malloc fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Leak fun:malloc fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Leak fun:malloc fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Leak fun:malloc fun:__nss_lookup_function obj:* obj:* fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Leak fun:malloc fun:getdelim fun:getpass fun:get_console_input fun:get_user_pass fun:context_init_1 fun:main } { Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:management_open fun:open_management fun:main } { Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function obj:* obj:* fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.5.so fun:__nss_database_lookup obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.5.so fun:__nss_database_lookup obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.5.so fun:__nss_database_lookup obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.5.so fun:__nss_database_lookup obj:* obj:* fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.7.so fun:__nss_database_lookup obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_tcp fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.7.so fun:__nss_database_lookup obj:* obj:* fun:getgrnam_r fun:getgrnam fun:get_group fun:do_init_first_time fun:init_instance fun:init_instance_handle_signals fun:tunnel_server_udp fun:main } { Memcheck:Leak fun:malloc obj:/lib/libc-2.7.so fun:__nss_database_lookup obj:* obj:* fun:getpwnam_r fun:getpwnam fun:get_user fun:management_open fun:open_management fun:main } { Memcheck:Cond fun:BN_mod_inverse } { Memcheck:Cond fun:BN_div } ================================================ FILE: dev-tools/gen-release-tarballs.sh ================================================ #!/bin/sh # gen-release-tarballs.sh - Generates release tarballs with signatures # # Copyright (C) 2017-2026 - David Sommerseth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License. # # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # set -u if [ $# -ne 4 ]; then echo "Usage: $0 " echo "" echo " remote-name -- valid remotes: `git remote | tr \\\n ' '`" echo " tag-name -- An existing release tag" echo " sign-key -- PGP key used to sign all files" echo " dest-dir -- Where to put the complete set of release tarballs" echo "" echo " Example: $0 origin v2.4.2 /tmp/openvpn-release" echo exit 1 fi arg_remote_name="$1" arg_tag_name="$2" arg_sign_key="$3" arg_dest_dir="$4" # # Sanity checks # # Check that the tag exists git tag | grep "$arg_tag_name" 1>/dev/null if [ $? -ne 0 ]; then echo "** ERROR ** The tag '$arg_tag_name' does not exist" exit 2 fi # Extract the git URL giturl="`git remote get-url $arg_remote_name 2>/dev/null`" if [ $? -ne 0 ]; then echo "** ERROR ** Invalid git remote name: $arg_remote_name" exit 2 fi # Check we have the needed signing key echo "test" | gpg -a --clearsign -u "$arg_sign_key" 2>/dev/null 1>/dev/null if [ $? -ne 0 ]; then echo "** ERROR ** Failed when testing the PGP signing. Wrong signing key?" exit 2; fi # # Helper functions # get_filename() { local wildcard="$1" res="`find . -maxdepth 1 -type f -name \"$wildcard\" | head -n1 | cut -d/ -f2-`" if [ $? -ne 0 ]; then echo "-- 'find' failed." exit 5 fi if [ -z "$res" ]; then echo "-- Could not find a file with the wildcard: $wildcard" exit 4 fi echo "$res" } copy_files() { local fileext="$1" local dest="$2" file="`get_filename openvpn-*.*.*.$fileext`" if [ -z "$file" ]; then echo "** ERROR Failed to find source file" exit 5 fi echo "-- Copying $file" cp "$file" "$dest" if [ $? -ne 0 ]; then echo "** ERROR ** Failed to copy $file to $destdir" exit 3; fi } sign_file() { local signkey="$1" local srchfile="$2" local signtype="$3" local file="`get_filename $srchfile`" echo "-- Signing $file ..." case "$signtype" in inline) # Have the signature in the same file as the data gpg -a --clearsign -u "$signkey" "$file" 2>/dev/null res=$? if [ $res -eq 0 ]; then rm -f "$file" fi ;; detached) # Have the signature in a separate file gpg -a --detach-sign -u "$signkey" "$file" 2>/dev/null res=$? ;; *) echo "** ERROR ** Unknown signing type \"$signtype\"." exit 4; esac if [ $res -ne 0 ]; then echo "** ERROR ** Failed to sign the file $PWD/$file" exit 4; fi } # # Preparations # # Create the destination directory, using a sub-dir with the tag-name destdir="" case "$arg_dest_dir" in /*) # Absolute path destdir="$arg_dest_dir/$arg_tag_name" ;; *) # Make absolute path from relative path destdir="$PWD/$arg_dest_dir/$arg_tag_name" ;; esac echo "-- Destination directory: $destdir" if [ -e "$destdir" ]; then echo "** ERROR ** Destination directory already exists. " echo " Please check your command line carefully." exit 2 fi mkdir -p "$destdir" if [ $? -ne 0 ]; then echo "** ERROR ** Failed to create destination directory" exit 2 fi # # Start the release process # # Clone the remote repository workdir="`mktemp -d -p /var/tmp openvpn-build-release-XXXXXX`" cd $workdir echo "-- Working directory: $workdir" echo "-- git clone $giturl" git clone $giturl openvpn-gen-tarball 2> "$workdir/git-clone.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** git clone failed. See $workdir/git-clone.log for details" exit 3; fi cd openvpn-gen-tarball # Check out the proper release tag echo "-- Checking out tag $arg_tag_name ... " git checkout -b mkrelease "$arg_tag_name" 2> "$workdir/git-checkout-tag.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** git checkout failed. See $workdir/git-checkout-tag.log for details" exit 3; fi # Prepare the source tree echo "-- Running autoreconf + a simple configure ... " (autoreconf -vi && ./configure) 2> "$workdir/autotools-prep.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** Failed running autotools. See $workdir/autotools-prep.log for details" exit 3; fi # Generate the tar/zip files echo "-- Running make distcheck (generates .tar.gz) ... " (make distcheck) 2> "$workdir/make-distcheck.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** make distcheck failed. See $workdir/make-distcheck.log for details" exit 3; fi copy_files tar.gz "$destdir" echo "-- Running make dist-xz (generates .tar.xz) ... " (make dist-xz) 2> "$workdir/make-dist-xz.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** make dist-xz failed. See $workdir/make-dist-xz.log for details" exit 3; fi copy_files tar.xz "$destdir" echo "-- Running make dist-zip (generates .zip) ... " (make dist-zip) 2> "$workdir/make-dist-zip.log" 1>&2 if [ $? -ne 0 ]; then echo "** ERROR ** make dist-zip failed. See $workdir/make-dist-zip.log for details" exit 3; fi copy_files zip "$destdir" # Generate SHA256 checksums cd "$destdir" sha256sum openvpn-*.tar.{gz,xz} openvpn-*.zip > "openvpn-$arg_tag_name.sha256sum" # Sign all the files echo "-- Signing files ... " sign_file "$arg_sign_key" "openvpn-$arg_tag_name.sha256sum" inline sign_file "$arg_sign_key" "openvpn-*.tar.gz" detached sign_file "$arg_sign_key" "openvpn-*.tar.xz" detached sign_file "$arg_sign_key" "openvpn-*.zip" detached # Create a tar-bundle with everything echo "-- Creating final tarbundle with everything ..." tar cf "openvpn-$arg_tag_name.tar" openvpn-*.{tar.gz,tar.xz,zip}{,.asc} openvpn-*.sha256sum.asc echo "-- Cleaning up ..." # Save the log files mkdir -p "$destdir/logs" mv $workdir/*.log "$destdir/logs" # Finally, done! rm -rf "$workdir" echo "-- Done" exit 0 ================================================ FILE: dev-tools/gerrit-send-mail.py ================================================ #!/usr/bin/env python3 # Copyright (C) 2023-2026 OpenVPN Inc # Copyright (C) 2023-2026 Frank Lichtenheld # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, see . # Extract a patch from Gerrit and transform it in a file suitable as input # for git send-email. import argparse import base64 from datetime import timezone import json import sys from urllib.parse import urlparse import dateutil.parser import requests def get_details(args): params = {"o": ["CURRENT_REVISION", "LABELS", "DETAILED_ACCOUNTS"]} r = requests.get(f"{args.url}/changes/{args.changeid}", params=params) print(r.url) json_txt = r.text.removeprefix(")]}'\n") json_data = json.loads(json_txt) assert len(json_data["revisions"]) == 1 # CURRENT_REVISION works as expected revision = json_data["revisions"].popitem()[1]["_number"] assert "Code-Review" in json_data["labels"] acked_by = [] for reviewer in json_data["labels"]["Code-Review"]["all"]: if "value" in reviewer: assert reviewer["value"] >= 0 # no NACK if reviewer["value"] == 2: # fall back to user name if optional fields are not set reviewer_name = reviewer.get("display_name", reviewer["name"]) reviewer_mail = reviewer.get("email", reviewer["name"]) ack = f"{reviewer_name} <{reviewer_mail}>" print(f"Acked-by: {ack}") acked_by.append(ack) # construct Signed-off-by in case it is missing owner = json_data["owner"] owner_name = owner.get("display_name", owner["name"]) owner_mail = owner.get("email", owner["name"]) sign_off = f"{owner_name} <{owner_mail}>" print(f"Signed-off-by: {sign_off}") change_id = json_data["change_id"] # assumes that the created date in Gerrit is in UTC utc_stamp = ( dateutil.parser.parse(json_data["created"]) .replace(tzinfo=timezone.utc) .timestamp() ) # convert to milliseconds as used in message id created_stamp = int(utc_stamp * 1000) hostname = urlparse(args.url).hostname msg_id = f"gerrit.{created_stamp}.{change_id}@{hostname}" return { "revision": revision, "project": json_data["project"], "target": json_data["branch"], "msg_id": msg_id, "acked_by": acked_by, "sign_off": sign_off, } def get_patch(details, args): r = requests.get( f"{args.url}/changes/{args.changeid}/revisions/{details['revision']}/patch?download" ) print(r.url) patch_text = base64.b64decode(r.text).decode() return patch_text def apply_patch_mods(patch_text, details, args): comment_start = patch_text.index("\n---\n") + len("\n---\n") signed_off_text = "" signed_off_comment = "" try: signed_off_start = patch_text.rindex("\nSigned-off-by: ") signed_off_end = patch_text.index("\n", signed_off_start + 1) + 1 except ValueError: # Signed-off missing signed_off_text = f"Signed-off-by: {details['sign_off']}\n" signed_off_comment = "\nSigned-off-by line for the author was added as per our policy.\n" signed_off_end = patch_text.index("\n---\n") + 1 assert comment_start > signed_off_end acked_by_text = "" acked_by_names = "" gerrit_url = f"{args.url}/c/{details['project']}/+/{args.changeid}" for ack in details["acked_by"]: acked_by_text += f"Acked-by: {ack}\n" acked_by_names += f"{ack}\n" patch_text_mod = ( patch_text[:signed_off_end] + signed_off_text + acked_by_text + f"Gerrit URL: {gerrit_url}\n" + patch_text[signed_off_end:comment_start] + f""" This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to {details["target"]}. Gerrit URL: {gerrit_url} This mail reflects revision {details["revision"]} of this Change. {signed_off_comment} Acked-by according to Gerrit (reflected above): {acked_by_names} """ + patch_text[comment_start:] ) filename = f"gerrit-{args.changeid}-{details['revision']}.patch" patch_text_final = patch_text_mod.replace("Subject: [PATCH]", f"Subject: [PATCH v{details['revision']}]") with open(filename, "w", encoding="utf-8", newline="\n") as patch_file: patch_file.write(patch_text_final) print("send with:") print(f"git send-email --in-reply-to {details['msg_id']} {filename}") def main(): parser = argparse.ArgumentParser( prog="gerrit-send-mail", description="Send patchset from Gerrit to mailing list", ) parser.add_argument("changeid") parser.add_argument("-u", "--url", default="https://gerrit.openvpn.net") args = parser.parse_args() details = get_details(args) patch = get_patch(details, args) apply_patch_mods(patch, details, args) if __name__ == "__main__": sys.exit(main()) ================================================ FILE: dev-tools/git-pre-commit-format.sh ================================================ #!/bin/sh # Copyright (c) 2015, David Martin # 2022, Heiko Hund # 2025, Frank Lichtenheld # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # git pre-commit hook that runs a stylecheck. # Features: # - abort commit when commit does not comply with the style guidelines # - create a patch of the proposed style changes # - use clang-format or uncrustify depending on presence of .clang-format # config file # # More info on Uncrustify: https://uncrustify.sourceforge.net/ # This file was taken from a set of unofficial pre-commit hooks available # at https://github.com/ddddavidmartin/Pre-commit-hooks and modified to # fit the openvpn project's needs # exit on error set -e # If called so, install this script as pre-commit hook if [ "$1" = "install" ] ; then TARGET="$(git rev-parse --git-path hooks)/pre-commit" if [ -e "$TARGET" ] ; then printf "$TARGET file exists. Won't overwrite.\n" printf "Aborting installation.\n" exit 1 fi read -p "Install as $TARGET? [y/N] " INPUT [ "$INPUT" = "y" ] || exit 0 cp "$0" "$TARGET" chmod +x $TARGET exit 0 fi # check whether the given file matches any of the set extensions matches_extension() { local filename="$(basename -- "$1")" local extension=".${filename##*.}" local ext for ext in .c .h ; do [ "$ext" = "$extension" ] && return 0; done return 1 } # necessary check for initial commit if git rev-parse --verify HEAD >/dev/null 2>&1 ; then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi TOPDIR="$(git rev-parse --show-toplevel)" if [ -e "${TOPDIR}/.clang-format" ]; then TOOL=clang-format TOOL_BIN=$(command -v clang-format) TOOL_CMD="$TOOL_BIN" # Allow to use in parallel with pre-commit if [ $(basename "$0") = "pre-commit.legacy" ]; then echo "Skipping clang-format check in favor of pre-commit" exit 0 fi else TOOL=uncrustify TOOL_BIN=$(command -v uncrustify) UNCRUST_CONFIG="${TOPDIR}/dev-tools/uncrustify.conf" TOOL_CMD="$TOOL_BIN -q -l C -c $UNCRUST_CONFIG" # make sure the config file is correctly set if [ ! -f "$UNCRUST_CONFIG" ] ; then printf "Error: uncrustify config file not found.\n" printf "Expected to find it at $UNCRUST_CONFIG.\n" printf "Aborting commit.\n" exit 1 fi fi if [ -z "$TOOL_BIN" ] ; then printf "Error: $TOOL executable not found.\n" printf "Is it installed and in your \$PATH?\n" printf "Aborting commit.\n" exit 1 fi # create a filename to store our generated patch patch=$(mktemp /tmp/ovpn-fmt-patch-XXXXXX) tmpout=$(mktemp /tmp/ovpn-fmt-tmp-XXXXXX) # create one patch containing all changes to the files # sed to remove quotes around the filename, if inserted by the system # (done sometimes, if the filename contains special characters, like the quote itself) git diff-index --cached --diff-filter=ACMR --name-only $against -- | \ sed -e 's/^"\(.*\)"$/\1/' | \ while read file do # ignore file if we do check for file extensions and the file # does not match the extensions .c or .h if ! matches_extension "$file"; then continue; fi # escape special characters in the target filename: # phase 1 (characters escaped in the output diff): # - '\': backslash needs to be escaped in the output diff # - '"': quote needs to be escaped in the output diff if present inside # of the filename, as it used to bracket the entire filename part # phase 2 (characters escaped in the match replacement): # - '\': backslash needs to be escaped again for sed itself # (i.e. double escaping after phase 1) # - '&': would expand to matched string # - '|': used as sed split char instead of '/' # printf %s particularly important if the filename contains the % character file_escaped_target=$(printf "%s" "$file" | sed -e 's/[\"]/\\&/g' -e 's/[\&|]/\\&/g') # uncrustify our sourcefile, create a patch with diff and append it to our $patch # The sed call is necessary to transform the patch from # --- - timestamp # +++ $tmpout timestamp # to both lines working on the same file and having a a/ and b/ prefix. # Else it can not be applied with 'git apply'. git show ":$file" | $TOOL_CMD > "$tmpout" git show ":$file" | diff -u -- - "$tmpout" | \ sed -e "1s|--- -|--- \"b/$file_escaped_target\"|" -e "2s|+++ $tmpout|+++ \"a/$file_escaped_target\"|" >> "$patch" done rm -f "$tmpout" # if no patch has been generated all is ok, clean up the file stub and exit if [ ! -s "$patch" ] ; then rm -f "$patch" exit 0 fi # a patch has been created, notify the user and exit printf "Formatting of some code does not follow the project guidelines.\n" if [ $(wc -l < $patch) -gt 80 ] ; then printf "The file $patch contains the necessary fixes.\n" else printf "Here's the patch that fixes the formatting:\n\n" cat $patch fi printf "\nYou can apply these changes with:\n git apply $patch\n" printf "(from the root directory of the repository) and then commit again.\n" printf "\nAborting commit.\n" exit 1 ================================================ FILE: dev-tools/update-copyright.sh ================================================ #!/bin/sh # update-copyright-sh - Simple tool to update the Copyright lines # in all files checked into git # # Copyright (C) 2016-2026 OpenVPN Inc # Copyright (C) 2016-2026 David Sommerseth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License. # # 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # Basic shell sanity set -eu # Simple argument control if [ $# -ne 1 ]; then echo "Usage: $0 " exit 1 fi # Only update Copyright lines with these owners # The 'or' operator is GNU sed specific, and must be \| UPDATE_COPYRIGHT_LINES="@openvpn\.net\|@sentyron\.com\|@sophos.com\|@eurephia\.org\|@greenie\.muc\.de\|@rozman.si\|@unstable\.cc\|@rfc2549.org\|@karger\.me\|selva.nair@" COPY_YEAR="$1" cd "$(git rev-parse --show-toplevel)" for file in $(git ls-files | grep -v vendor/); 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 /" \ -i $file echo " Done" done echo echo "** All files updated with $COPY_YEAR as the ending copyright year" echo exit 0 ================================================ FILE: distro/Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2002-2026 OpenVPN Inc # Copyright (C) 2006-2012 Alon Bar-Lev # MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in SUBDIRS = systemd if ENABLE_DNS_UPDOWN SUBDIRS += dns-scripts endif ================================================ FILE: distro/dns-scripts/Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2002-2026 OpenVPN Inc # MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in EXTRA_DIST = \ macos-dns-updown.sh \ systemd-dns-updown.sh \ openresolv-dns-updown.sh \ haikuos_file-dns-updown.sh \ resolvconf_file-dns-updown.sh script_SCRIPTS = \ dns-updown CLEANFILES = $(script_SCRIPTS) dns-updown: @DNS_UPDOWN_TYPE@-dns-updown.sh cp ${srcdir}/@DNS_UPDOWN_TYPE@-dns-updown.sh $@ chmod +x $@ all: $(script_SCRIPTS) ================================================ FILE: distro/dns-scripts/haikuos_file-dns-updown.sh ================================================ #!/bin/sh # # Simple OpenVPN up/down script for modifying Haiku OS resolv.conf # (C) Copyright 2024 OpenVPN Inc # # SPDX-License-Identifier: BSD-2-Clause # # Example env from openvpn (most are not applied): # # dns_vars_file /tmp/openvpn_dvf_58b95c0c97b2db43afb5d745f986c53c.tmp # # or # # dev tun0 # script_type dns-up # dns_search_domain_1 mycorp.in # dns_search_domain_2 eu.mycorp.com # dns_server_1_address_1 192.168.99.254 # dns_server_1_address_2 fd00::99:53 # dns_server_1_port_1 53 # dns_server_1_port_2 53 # dns_server_1_resolve_domain_1 mycorp.in # dns_server_1_resolve_domain_2 eu.mycorp.com # dns_server_1_dnssec true # dns_server_1_transport DoH # dns_server_1_sni dns.mycorp.in # set -e +u only_standard_server_ports() { i=1 while true; do eval addr=\"\$dns_server_${n}_address_${i}\" [ -n "$addr" ] || return 0 eval port=\"\$dns_server_${n}_port_${i}\" [ -z "$port" -o "$port" = "53" ] || return 1 i=$(expr $i + 1) done } conf=/boot/system/settings/network/resolv.conf test -e "$conf" || exit 1 test -z "${dns_vars_file}" || . "${dns_vars_file}" case "${script_type}" in dns-up) n=1 while :; do eval addr=\"\$dns_server_${n}_address_1\" [ -n "$addr" ] || { echo "setting DNS failed, no compatible server profile" exit 1 } # Skip server profiles which require DNSSEC, # secure transport or use a custom port eval dnssec=\"\$dns_server_${n}_dnssec\" eval transport=\"\$dns_server_${n}_transport\" [ -z "$transport" -o "$transport" = "plain" ] \ && [ -z "$dnssec" -o "$dnssec" = "no" ] \ && only_standard_server_ports && break n=$(expr $n + 1) done eval addr1=\"\$dns_server_${n}_address_1\" eval addr2=\"\$dns_server_${n}_address_2\" eval addr3=\"\$dns_server_${n}_address_3\" text="### openvpn ${dev} begin ###\n" text="${text}nameserver $addr1\n" test -z "$addr2" || text="${text}nameserver $addr2\n" test -z "$addr3" || text="${text}nameserver $addr3\n" test -z "$dns_search_domain_1" || { for i in $(seq 1 6); do eval domains=\"$domains\$dns_search_domain_${i} \" || break done text="${text}search $domains\n" } text="${text}### openvpn ${dev} end ###" text="${text}\n$(cat ${conf})" echo "${text}" > "${conf}" ;; dns-down) sed -i'' -e "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf" ;; esac ================================================ FILE: distro/dns-scripts/macos-dns-updown.sh ================================================ #!/bin/bash # # dns-updown - add/remove openvpn provided DNS information # # (C) Copyright 2025 OpenVPN Inc # # SPDX-License-Identifier: BSD-2-Clause # # Example env from openvpn (most are not applied): # # dns_vars_file /tmp/openvpn_dvf_58b95c0c97b2db43afb5d745f986c53c.tmp # # or # # dev utun0 # script_type dns-up # dns_search_domain_1 mycorp.in # dns_search_domain_2 eu.mycorp.com # dns_server_1_address_1 192.168.99.254 # dns_server_1_address_2 fd00::99:53 # dns_server_1_port_2 53 # dns_server_1_resolve_domain_1 mycorp.in # dns_server_1_resolve_domain_2 eu.mycorp.com # dns_server_1_dnssec true # dns_server_1_transport DoH # dns_server_1_sni dns.mycorp.in # lockdir=/var/lock if [ ! -d "${lockdir}" ]; then /bin/mkdir "${lockdir}" /bin/chmod 1777 "${lockdir}" fi i=1 lockfile="${lockdir}/openvpn-dns-updown.lock" while ! /usr/bin/shlock -f $lockfile -p $$; do if [ $((++i)) -gt 10 ]; then echo "dns-updown failed, could not acquire lock" exit 1 fi sleep 0.2 done trap "/bin/rm -f ${lockfile}" EXIT [ -z "${dns_vars_file}" ] || . "${dns_vars_file}" itf_dns_key="State:/Network/Service/openvpn-${dev}/DNS" function primary_dns_key { local uuid=$(echo "show State:/Network/Global/IPv4" | /usr/sbin/scutil | grep "PrimaryService" | cut -d: -f2 | xargs) echo "Setup:/Network/Service/${uuid}/DNS" } function dns_backup_key { local key="$(echo "list State:/Network/Service/openvpn-.*/DnsBackup" | /usr/sbin/scutil | cut -d= -f2 | xargs)" if [[ "${key}" =~ no\ key ]]; then echo "State:/Network/Service/openvpn-${dev}/DnsBackup" else echo "${key}" fi } function property_value { local key="$1" local prop="$2" [ -n "${key}" -a -n "${prop}" ] || return local match_prop="${prop} : (.*)" local match_array_start="${prop} : " local match_array_elem="[0-9]* : (.*)" local match_array_end="}" local in_array=false local values="" echo "show ${key}" | /usr/sbin/scutil | while read line; do if [ "${in_array}" = false ] && [[ "${line}" =~ "${match_array_start}" ]]; then in_array=true elif [ "${in_array}" = true ] && [[ "${line}" =~ ${match_array_elem} ]]; then values+="${BASH_REMATCH[1]} " elif [ "${in_array}" = true ] && [[ "${line}" =~ "${match_array_end}" ]]; then echo "${values}" break elif [[ "${line}" =~ ${match_prop} ]]; then echo "${BASH_REMATCH[1]}" break fi done } function only_standard_server_ports { local i=1 while :; do local addr_var=dns_server_${n}_address_${i} [ -n "${!addr_var}" ] || return 0 local port_var=dns_server_${n}_port_${i} [ -z "${!port_var}" -o "${!port_var}" = "53" ] || return 1 i=$((i+1)) done } function find_compat_profile { local n=1 while :; do local addr_var=dns_server_${n}_address_1 [ -n "${!addr_var}" ] || { echo "setting DNS failed, no compatible server profile" exit 1 } # Skip server profiles which require DNSSEC, # secure transport or use a custom port local dnssec_var=dns_server_${n}_dnssec local transport_var=dns_server_${n}_transport [ -z "${!transport_var}" -o "${!transport_var}" = "plain" ] \ && [ -z "${!dnssec_var}" -o "${!dnssec_var}" = "no" ] \ && only_standard_server_ports && break n=$((n+1)) done echo $n } function get_search_domains { property_value State:/Network/Global/DNS SearchDomains } function get_server_addresses { property_value "$(primary_dns_key)" ServerAddresses } function set_search_domains { [ -n "$1" ] || return local dns_key=$(primary_dns_key) local dns_backup_key="$(dns_backup_key)" local search_domains="${1}$(get_search_domains)" local cmds="" cmds+="get ${dns_key}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="set ${dns_key}\n" if ! [[ "${dns_backup_key}" =~ ${dev}/ ]]; then # Add the domains to the backup in case the default goes down local existing="$(property_value ${dns_backup_key} SearchDomains)" cmds+="get ${dns_backup_key}\n" cmds+="d.add SearchDomains * ${search_domains} ${existing}\n" cmds+="set ${dns_backup_key}\n" fi echo -e "${cmds}" | /usr/sbin/scutil } function unset_search_domains { [ -n "$1" ] || return local dns_key=$(primary_dns_key) local dns_backup_key="$(dns_backup_key)" local search_domains="$(get_search_domains)" search_domains=$(echo $search_domains | sed -e "s/$1//") local cmds="" cmds+="get ${dns_key}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="set ${dns_key}\n" if ! [[ "${dns_backup_key}" =~ ${dev}/ ]]; then # Remove the domains from the backup for when the default goes down search_domains="$(property_value ${dns_backup_key} SearchDomains)" search_domains=$(echo $search_domains | sed -e "s/$1//") cmds+="get ${dns_backup_key}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="set ${dns_backup_key}\n" fi echo -e "${cmds}" | /usr/sbin/scutil } function addresses_string { local n=$1 local i=1 local addresses="" while :; do local addr_var=dns_server_${n}_address_${i} local addr="${!addr_var}" [ -n "$addr" ] || break addresses+="${addr} " i=$((i+1)) done echo "$addresses" } function search_domains_string { local n=$1 local i=1 local search_domains="" while :; do domain_var=dns_search_domain_${i} [ -n "${!domain_var}" ] || break # Add as search domain, if it doesn't already exist [[ "$search_domains" =~ (^| )${!domain_var}( |$) ]] \ || search_domains+="${!domain_var} " i=$((i+1)) done echo "$search_domains" } function match_domains_string { local n=$1 local i=1 local match_domains="" while :; do domain_var=dns_server_${n}_resolve_domain_${i} [ -n "${!domain_var}" ] || break # Add as match domain, if it doesn't already exist [[ "$match_domains" =~ (^| )${!domain_var}( |$) ]] \ || match_domains+="${!domain_var} " i=$((i+1)) done echo "$match_domains" } function set_dns { local n="$(find_compat_profile)" local addresses="$(addresses_string $n)" local search_domains="$(search_domains_string $n)" local match_domains="$(match_domains_string $n)" if [ -n "$match_domains" ]; then local cmds="" cmds+="d.init\n" cmds+="d.add ServerAddresses * ${addresses}\n" cmds+="d.add SupplementalMatchDomains * ${match_domains}\n" cmds+="d.add SupplementalMatchDomainsNoSearch # 1\n" cmds+="add ${itf_dns_key}\n" echo -e "${cmds}" | /usr/sbin/scutil set_search_domains "$search_domains" else local dns_backup_key="$(dns_backup_key)" [[ "${dns_backup_key}" =~ ${dev}/ ]] || { echo "setting DNS failed, already redirecting to another tunnel" exit 1 } local cmds="" cmds+="get $(primary_dns_key)\n" cmds+="set ${dns_backup_key}\n" cmds+="d.init\n" cmds+="d.add ServerAddresses * ${addresses}\n" cmds+="d.add SearchDomains * ${search_domains}\n" cmds+="d.add SearchOrder # 5000\n" cmds+="set $(primary_dns_key)\n" echo -e "${cmds}" | /usr/sbin/scutil fi /usr/bin/dscacheutil -flushcache } function unset_dns { local n="$(find_compat_profile)" local match_domains="$(match_domains_string $n)" if [ -n "$match_domains" ]; then local search_domains="$(search_domains_string $n)" echo "remove ${itf_dns_key}" | /usr/sbin/scutil unset_search_domains "$search_domains" else # Do not unset if this tunnel did not set/backup DNS before local dns_backup_key="$(dns_backup_key)" [[ "${dns_backup_key}" =~ ${dev}/ ]] || return local cmds="" local servers="$(get_server_addresses)" local addresses="$(addresses_string $n)" # Only restore backup if the server addresses match if [ "${servers}" = "${addresses}" ]; then cmds+="get ${dns_backup_key}\n" cmds+="set $(primary_dns_key)\n" else echo "not restoring global DNS configuration, server addresses have changed" fi cmds+="remove ${dns_backup_key}\n" echo -e "${cmds}" | /usr/sbin/scutil fi /usr/bin/dscacheutil -flushcache } if [ "$script_type" = "dns-up" ]; then set_dns else unset_dns fi ================================================ FILE: distro/dns-scripts/openresolv-dns-updown.sh ================================================ #!/bin/sh # # Simple OpenVPN up/down script for openresolv integration # (C) Copyright 2016 Baptiste Daroussin # 2024 OpenVPN Inc # # SPDX-License-Identifier: BSD-2-Clause # # Example env from openvpn (most are not applied): # # dns_vars_file /tmp/openvpn_dvf_58b95c0c97b2db43afb5d745f986c53c.tmp # # or # # dev tun0 # script_type dns-up # dns_search_domain_1 mycorp.in # dns_search_domain_2 eu.mycorp.com # dns_server_1_address_1 192.168.99.254 # dns_server_1_address_2 fd00::99:53 # dns_server_1_port_1 53 # dns_server_1_port_2 53 # dns_server_1_resolve_domain_1 mycorp.in # dns_server_1_resolve_domain_2 eu.mycorp.com # dns_server_1_dnssec true # dns_server_1_transport DoH # dns_server_1_sni dns.mycorp.in # set -e +u only_standard_server_ports() { i=1 while true; do eval addr=\"\$dns_server_${n}_address_${i}\" [ -n "$addr" ] || return 0 eval port=\"\$dns_server_${n}_port_${i}\" [ -z "$port" -o "$port" = "53" ] || return 1 i=$(expr $i + 1) done } [ -z "${dns_vars_file}" ] || . "${dns_vars_file}" : ${script_type:=dns-down} case "${script_type}" in dns-up) n=1 while :; do eval addr=\"\$dns_server_${n}_address_1\" [ -n "$addr" ] || { echo "setting DNS failed, no compatible server profile" exit 1 } # Skip server profiles which require DNSSEC, # secure transport or use a custom port eval dnssec=\"\$dns_server_${n}_dnssec\" eval transport=\"\$dns_server_${n}_transport\" [ -z "$transport" -o "$transport" = "plain" ] \ && [ -z "$dnssec" -o "$dnssec" = "no" ] \ && only_standard_server_ports && break n=$(expr $n + 1) done { i=1 maxns=3 while :; do maxns=$((maxns - 1)) [ $maxns -gt 0 ] || break eval option=\"\$dns_server_${n}_address_${i}\" || break [ "${option}" ] || break i=$((i + 1)) echo "nameserver ${option}" done i=1 maxdom=6 while :; do maxdom=$((maxdom - 1)) [ $maxdom -gt 0 ] || break eval option=\"\$dns_search_domain_${i}\" || break [ "${option}" ] || break i=$((i + 1)) echo "search ${option}" done } | /sbin/resolvconf -a "${dev}" ;; dns-down) /sbin/resolvconf -d "${dev}" -f ;; esac ================================================ FILE: distro/dns-scripts/resolvconf_file-dns-updown.sh ================================================ #!/bin/sh # # Simple OpenVPN up/down script for modifying /etc/resolv.conf # (C) Copyright 2024 OpenVPN Inc # # SPDX-License-Identifier: BSD-2-Clause # # Example env from openvpn (most are not applied): # # dns_vars_file /tmp/openvpn_dvf_58b95c0c97b2db43afb5d745f986c53c.tmp # # or # # dev tun0 # script_type dns-up # dns_search_domain_1 mycorp.in # dns_search_domain_2 eu.mycorp.com # dns_server_1_address_1 192.168.99.254 # dns_server_1_address_2 fd00::99:53 # dns_server_1_port_1 53 # dns_server_1_port_2 53 # dns_server_1_resolve_domain_1 mycorp.in # dns_server_1_resolve_domain_2 eu.mycorp.com # dns_server_1_dnssec true # dns_server_1_transport DoH # dns_server_1_sni dns.mycorp.in # set -e +u only_standard_server_ports() { i=1 while true; do eval addr=\"\$dns_server_${n}_address_${i}\" [ -n "$addr" ] || return 0 eval port=\"\$dns_server_${n}_port_${i}\" [ -z "$port" -o "$port" = "53" ] || return 1 i=$(expr $i + 1) done } conf=/etc/resolv.conf test -e "$conf" || exit 1 test -z "${dns_vars_file}" || . "${dns_vars_file}" case "${script_type}" in dns-up) n=1 while :; do eval addr=\"\$dns_server_${n}_address_1\" [ -n "$addr" ] || { echo "setting DNS failed, no compatible server profile" exit 1 } # Skip server profiles which require DNSSEC, # secure transport or use a custom port eval dnssec=\"\$dns_server_${n}_dnssec\" eval transport=\"\$dns_server_${n}_transport\" [ -z "$transport" -o "$transport" = "plain" ] \ && [ -z "$dnssec" -o "$dnssec" = "no" ] \ && only_standard_server_ports && break n=$(expr $n + 1) done eval addr1=\"\$dns_server_${n}_address_1\" eval addr2=\"\$dns_server_${n}_address_2\" eval addr3=\"\$dns_server_${n}_address_3\" text="### openvpn ${dev} begin ###\n" text="${text}nameserver $addr1\n" test -z "$addr2" || text="${text}nameserver $addr2\n" test -z "$addr3" || text="${text}nameserver $addr3\n" test -z "$dns_search_domain_1" || { for i in $(seq 1 6); do eval domains=\"$domains\$dns_search_domain_${i} \" || break done text="${text}search $domains\n" } text="${text}### openvpn ${dev} end ###" text="${text}\n$(cat ${conf})" echo "${text}" > "${conf}" ;; dns-down) sed -i'' -e "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf" ;; esac ================================================ FILE: distro/dns-scripts/systemd-dns-updown.sh ================================================ #!/bin/bash # # dns-updown - add/remove openvpn provided DNS information # # Copyright (C) 2024-2026 OpenVPN Inc # # SPDX-License-Identifier: GPL-2.0 # # Add/remove openvpn DNS settings from the env into/from # the system. Supported backends in this order: # # * systemd-resolved # * resolvconf # * /etc/resolv.conf file # # Example env from openvpn (not all are always applied): # # dns_vars_file /tmp/openvpn_dvf_58b95c0c97b2db43afb5d745f986c53c.tmp # # or # # dev tun0 # script_type dns-up # dns_search_domain_1 mycorp.in # dns_search_domain_2 eu.mycorp.com # dns_server_1_address_1 192.168.99.254 # dns_server_1_address_2 fd00::99:53 # dns_server_1_port_1 53 # dns_server_1_port_2 53 # dns_server_1_resolve_domain_1 mycorp.in # dns_server_1_resolve_domain_2 eu.mycorp.com # dns_server_1_dnssec true # dns_server_1_transport DoH # dns_server_1_sni dns.mycorp.in # [ -z "${dns_vars_file}" ] || . "${dns_vars_file}" function do_resolved_servers { local sni="" local transport_var=dns_server_${n}_transport local sni_var=dns_server_${n}_sni [ "${!transport_var}" = "DoT" ] && sni="#${!sni_var}" local i=1 local addrs="" while :; do local addr_var=dns_server_${n}_address_${i} local addr="${!addr_var}" [ -n "$addr" ] || break local port_var=dns_server_${n}_port_${i} if [ -n "${!port_var}" ]; then if [[ "$addr" =~ : ]]; then addr="[$addr]" fi addrs+="${addr}:${!port_var}${sni} " else addrs+="${addr}${sni} " fi i=$((i+1)) done resolvectl dns "$dev" $addrs } function do_resolved_domains { local list="" for domain_var in ${!dns_search_domain_*}; do list+="${!domain_var} " done local domain_var=dns_server_${n}_resolve_domain_1 if [ -z "${!domain_var}" ]; then resolvectl default-route "$dev" true list+="~." else resolvectl default-route "$dev" false local i=1 while :; do domain_var=dns_server_${n}_resolve_domain_${i} [ -n "${!domain_var}" ] || break # Add as split domain (~ prefix), if it doesn't already exist [[ "$list" =~ (^| )"${!domain_var}"( |$) ]] \ || list+="~${!domain_var} " i=$((i+1)) done fi resolvectl domain "$dev" $list } function do_resolved_dnssec { local dnssec_var=dns_server_${n}_dnssec if [ "${!dnssec_var}" = "optional" ]; then resolvectl dnssec "$dev" allow-downgrade elif [ "${!dnssec_var}" = "yes" ]; then resolvectl dnssec "$dev" true else resolvectl dnssec "$dev" false fi } function do_resolved_dnsovertls { local transport_var=dns_server_${n}_transport if [ "${!transport_var}" = "DoT" ]; then resolvectl dnsovertls "$dev" true else resolvectl dnsovertls "$dev" false fi } function do_resolved { [[ "$(readlink /etc/resolv.conf)" =~ systemd ]] || return 1 n=1 while :; do local addr_var=dns_server_${n}_address_1 [ -n "${!addr_var}" ] || { echo "setting DNS failed, no compatible server profile" return 1 } # Skip server profiles which require DNS-over-HTTPS local transport_var=dns_server_${n}_transport [ -n "${!transport_var}" -a "${!transport_var}" = "DoH" ] || break n=$((n+1)) done if [ "$script_type" = "dns-up" ]; then echo "setting DNS using resolvectl" do_resolved_servers do_resolved_domains do_resolved_dnssec do_resolved_dnsovertls else echo "unsetting DNS using resolvectl" resolvectl revert "$dev" fi return 0 } function only_standard_server_ports { local i=1 while :; do local addr_var=dns_server_${n}_address_${i} [ -n "${!addr_var}" ] || return 0 local port_var=dns_server_${n}_port_${i} [ -z "${!port_var}" -o "${!port_var}" = "53" ] || return 1 i=$((i+1)) done } function resolv_conf_compat_profile { local n=1 while :; do local server_addr_var=dns_server_${n}_address_1 [ -n "${!server_addr_var}" ] || { echo "setting DNS failed, no compatible server profile" exit 1 } # Skip server profiles which require DNSSEC, # secure transport or use a custom port local dnssec_var=dns_server_${n}_dnssec local transport_var=dns_server_${n}_transport [ -z "${!transport_var}" -o "${!transport_var}" = "plain" ] \ && [ -z "${!dnssec_var}" -o "${!dnssec_var}" = "no" ] \ && only_standard_server_ports && break n=$((n+1)) done return $n } function do_resolvconf { [ -x /sbin/resolvconf ] || return 1 resolv_conf_compat_profile local n=$? if [ "$script_type" = "dns-up" ]; then echo "setting DNS using resolvconf" local domains="" for domain_var in ${!dns_search_domain_*}; do domains+="${!domain_var} " done { local i=1 local maxns=3 while [ "${i}" -le "${maxns}" ]; do local addr_var=dns_server_${n}_address_${i} [ -n "${!addr_var}" ] || break echo "nameserver ${!addr_var}" i=$((i+1)) done [ -z "$domains" ] || echo "search $domains" } | /sbin/resolvconf -a "$dev" else echo "unsetting DNS using resolvconf" /sbin/resolvconf -d "$dev" fi return 0 } function do_resolv_conf_file { conf=/etc/resolv.conf test -e "$conf" || exit 1 resolv_conf_compat_profile local n=$? if [ "$script_type" = "dns-up" ]; then echo "setting DNS using resolv.conf file" local addr1_var=dns_server_${n}_address_1 local addr2_var=dns_server_${n}_address_2 local addr3_var=dns_server_${n}_address_3 text="### openvpn ${dev} begin ###\n" text="${text}nameserver ${!addr1_var}\n" test -z "${!addr2_var}" || text="${text}nameserver ${!addr2_var}\n" test -z "${!addr3_var}" || text="${text}nameserver ${!addr3_var}\n" test -z "$dns_search_domain_1" || { for i in $(seq 1 6); do eval domains=\"$domains\$dns_search_domain_${i} \" || break done text="${text}search $domains\n" } text="${text}### openvpn ${dev} end ###" sed -i "1i${text}" "$conf" else echo "unsetting DNS using resolv.conf file" sed -i "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf" fi return 0 } do_resolved || do_resolvconf || do_resolv_conf_file || { echo "setting DNS failed, no method succeeded" exit 1 } ================================================ FILE: distro/systemd/Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2017-2026 OpenVPN Inc # %.service: %.service.in Makefile $(AM_V_GEN)sed \ -e 's|\@OPENVPN_VERSION_MAJOR\@|$(OPENVPN_VERSION_MAJOR)|g' \ -e 's|\@OPENVPN_VERSION_MINOR\@|$(OPENVPN_VERSION_MINOR)|g' \ -e 's|\@sbindir\@|$(sbindir)|g' \ $< > $@.tmp && mv $@.tmp $@ EXTRA_DIST = \ tmpfiles-openvpn.conf \ openvpn-client@.service.in \ openvpn-server@.service.in if ENABLE_SYSTEMD systemdunit_DATA = \ openvpn-client@.service \ openvpn-server@.service CLEANFILES = $(systemdunit_DATA) tmpfiles_DATA = \ tmpfiles-openvpn.conf dist_doc_DATA = \ README.systemd install-data-hook: mv $(DESTDIR)$(tmpfilesdir)/tmpfiles-openvpn.conf $(DESTDIR)$(tmpfilesdir)/openvpn.conf endif MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in ================================================ FILE: distro/systemd/README.systemd ================================================ OpenVPN and systemd =================== As of OpenVPN v2.4, upstream is shipping systemd unit files to provide a fine grained control of each OpenVPN configuration as well as trying to restrict the capabilities the OpenVPN process have on a system. Configuration profile types --------------------------- These new unit files separates between client and server profiles. The configuration files are kept in separate directories, to provide clarity of the profile they run under. Typically the client profile cannot bind to any ports below port 1024 and the client configuration is always started with --nobind. The server profile is allowed to bind to any ports. In addition it enables a client status file, usually found in the /run/openvpn-server directory. The status format is set to version 2 by default. These settings may be overridden by adding --status and/or --status-version in the OpenVPN configuration file. Neither of these profiles makes use of PID files, but OpenVPN reports back to systemd its PID once it has initialized. For configuration using a peer-to-peer mode (not using --mode server on one of the sides) it is recommended to use the client profile. Configuration files ------------------- These new unit files expects client configuration files to be made available in /etc/openvpn/client. Similar for the server configurations, it is expected to be found in /etc/openvpn/server. The configuration files must have a .conf file extension. Managing VPN tunnels -------------------- Use the normal systemctl tool to start, stop VPN tunnels, as well as enable and disable tunnels at boot time. The syntax is: - client configurations: # systemctl $OPER openvpn-client@$CONFIGNAME - server configurations: # systemctl $OPER openvpn-server@$CONFIGNAME Similarly, to view the OpenVPN journal log use a similar syntax: # journalctl -u openvpn-client@$CONFIGNAME or # journalctl -u openvpn-server@$CONFIGNAME * Examples Say your server configuration is /etc/openvpn/server/tun0.conf, you start this VPN service like this: # systemctl start openvpn-server@tun0 A client configuration file in /etc/openvpn/client/corpvpn.conf is started like this: # systemctl start openvpn-client@corpvpn To view the server configuration's journal only listing entries from yesterday and until today: # journalctl --since yesterday -u openvpn-server@tun0 ================================================ FILE: distro/systemd/openvpn-client@.service.in ================================================ [Unit] Description=OpenVPN tunnel for %i After=network-online.target Wants=network-online.target Documentation=man:openvpn(8) Documentation=https://openvpn.net/community-resources/reference-manual-for-openvpn-@OPENVPN_VERSION_MAJOR@-@OPENVPN_VERSION_MINOR@/ Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO [Service] Type=notify PrivateTmp=true WorkingDirectory=/etc/openvpn/client ExecStart=@sbindir@/openvpn --suppress-timestamps --nobind --config %i.conf CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_SYS_NICE TasksMax=20 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw ProtectSystem=true ProtectHome=true KillMode=process [Install] WantedBy=multi-user.target ================================================ FILE: distro/systemd/openvpn-server@.service.in ================================================ [Unit] Description=OpenVPN service for %i After=network-online.target Wants=network-online.target Documentation=man:openvpn(8) Documentation=https://openvpn.net/community-resources/reference-manual-for-openvpn-@OPENVPN_VERSION_MAJOR@-@OPENVPN_VERSION_MINOR@/ Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO [Service] Type=notify PrivateTmp=true WorkingDirectory=/etc/openvpn/server ExecStart=@sbindir@/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_SYS_NICE CAP_AUDIT_WRITE TasksMax=20 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw ProtectSystem=true ProtectHome=true KillMode=process RestartSec=5s Restart=on-failure [Install] WantedBy=multi-user.target ================================================ FILE: distro/systemd/tmpfiles-openvpn.conf ================================================ d /run/openvpn-client 0710 root root - d /run/openvpn-server 0710 root root - ================================================ FILE: doc/CMakeLists.txt ================================================ set(_GENERATE_HTML_DOC YES) set(_GENERATE_MAN_DOC YES) set(_MAYBE_PYTHON "") find_program(RST2HTML NAMES rst2html rst2html.py) find_program(RST2MAN NAMES rst2man rst2man.py) if (RST2HTML STREQUAL "RST2HTML-NOTFOUND") message(STATUS "rst2html not found, not generating HTML documentation") set(_GENERATE_HTML_DOC NO) else () # We only run this for RST2HTML and assume the result would be the same # for RST2MAN if (DEFINED CACHE{DOCUTILS_NEED_PYTHON}) if ($CACHE{DOCUTILS_NEED_PYTHON}) set(_MAYBE_PYTHON ${PYTHON}) endif () else () execute_process( COMMAND ${RST2HTML} --version OUTPUT_VARIABLE RST2HTML_VERSION_EXE ) execute_process( COMMAND ${PYTHON} ${RST2HTML} --version OUTPUT_VARIABLE RST2HTML_VERSION_PY ) set(_DOCUTILS_NEED_PYTHON OFF) if(RST2HTML_VERSION_EXE STREQUAL "") if(RST2HTML_VERSION_PY STREQUAL "") message(STATUS "${RST2HTML} found but not working, not generating documentation") set(_GENERATE_HTML_DOC NO) set(_GENERATE_MAN_DOC NO) else () message(STATUS "${RST2HTML} needs to be executed by ${PYTHON} to work") set(_MAYBE_PYTHON ${PYTHON}) set(_DOCUTILS_NEED_PYTHON ON) endif () endif () set(DOCUTILS_NEED_PYTHON ${_DOCUTILS_NEED_PYTHON} CACHE BOOL "Whether we need to call python instead of rst2*.py directly") endif (DEFINED CACHE{DOCUTILS_NEED_PYTHON}) endif () if (RST2MAN STREQUAL "RST2MAN-NOTFOUND") message(STATUS "rst2man not found, not generating man pages") set(_GENERATE_MAN_DOC NO) endif () set(OPENVPN_SECTIONS man-sections/advanced-options.rst man-sections/cipher-negotiation.rst man-sections/client-options.rst man-sections/connection-profiles.rst man-sections/encryption-options.rst man-sections/generic-options.rst man-sections/inline-files.rst man-sections/link-options.rst man-sections/log-options.rst man-sections/management-options.rst man-sections/network-config.rst man-sections/pkcs11-options.rst man-sections/plugin-options.rst man-sections/protocol-options.rst man-sections/proxy-options.rst man-sections/renegotiation.rst man-sections/signals.rst man-sections/script-options.rst man-sections/server-options.rst man-sections/tls-options.rst man-sections/unsupported-options.rst man-sections/virtual-routing-and-forwarding.rst man-sections/vpn-network-options.rst man-sections/windows-options.rst ) set(OPENVPN_EXAMPLES_SECTIONS man-sections/example-fingerprint.rst man-sections/examples.rst ) set(RST_FLAGS --strict) if (_GENERATE_HTML_DOC) list(APPEND ALL_DOCS openvpn.8.html openvpn-examples.5.html) add_custom_command( OUTPUT openvpn.8.html COMMAND ${_MAYBE_PYTHON} ${RST2HTML} ${RST_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/openvpn.8.rst ${CMAKE_CURRENT_BINARY_DIR}/openvpn.8.html MAIN_DEPENDENCY openvpn.8.rst DEPENDS ${OPENVPN_SECTIONS} ) add_custom_command( OUTPUT openvpn-examples.5.html COMMAND ${_MAYBE_PYTHON} ${RST2HTML} ${RST_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/openvpn-examples.5.rst ${CMAKE_CURRENT_BINARY_DIR}/openvpn-examples.5.html MAIN_DEPENDENCY openvpn-examples.5.rst DEPENDS ${OPENVPN_EXAMPLES_SECTIONS} ) endif () if (_GENERATE_MAN_DOC) list(APPEND ALL_DOCS openvpn.8 openvpn-examples.5) add_custom_command( OUTPUT openvpn.8 COMMAND ${_MAYBE_PYTHON} ${RST2MAN} ${RST_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/openvpn.8.rst ${CMAKE_CURRENT_BINARY_DIR}/openvpn.8 MAIN_DEPENDENCY openvpn.8.rst DEPENDS ${OPENVPN_SECTIONS} ) add_custom_command( OUTPUT openvpn-examples.5 COMMAND ${_MAYBE_PYTHON} ${RST2MAN} ${RST_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/openvpn-examples.5.rst ${CMAKE_CURRENT_BINARY_DIR}/openvpn-examples.5 MAIN_DEPENDENCY openvpn-examples.5.rst DEPENDS ${OPENVPN_EXAMPLES_SECTIONS} ) endif () add_custom_target(documentation ALL DEPENDS ${ALL_DOCS}) ================================================ FILE: doc/Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2002-2026 OpenVPN Inc # Copyright (C) 2006-2012 Alon Bar-Lev # SUBDIRS = doxygen # # List of man and HTML pages we build when rst2man/rst2html is available # # NOTE: Remember to add source .rst files to $(dist_noinst_DATA) below # This could be automated with GNU Make, but we need BSD Make support # build_man_pages = openvpn.8 openvpn-examples.5 build_html_pages = openvpn.8.html openvpn-examples.5.html dist_doc_DATA = \ management-notes.txt gui-notes.txt openvpn_sections = \ man-sections/advanced-options.rst \ man-sections/cipher-negotiation.rst \ man-sections/client-options.rst \ man-sections/connection-profiles.rst \ man-sections/encryption-options.rst \ man-sections/generic-options.rst \ man-sections/inline-files.rst \ man-sections/link-options.rst \ man-sections/log-options.rst \ man-sections/management-options.rst \ man-sections/network-config.rst \ man-sections/pkcs11-options.rst \ man-sections/plugin-options.rst \ man-sections/protocol-options.rst \ man-sections/proxy-options.rst \ man-sections/renegotiation.rst \ man-sections/signals.rst \ man-sections/script-options.rst \ man-sections/server-options.rst \ man-sections/tls-options.rst \ man-sections/unsupported-options.rst \ man-sections/virtual-routing-and-forwarding.rst \ man-sections/vpn-network-options.rst \ man-sections/windows-options.rst openvpn_examples_sections = \ man-sections/example-fingerprint.rst \ man-sections/examples.rst dist_noinst_DATA = \ android.txt \ interactive-service-notes.rst \ keying-material-exporter.txt \ openvpn.8.rst \ openvpn-examples.5.rst \ README.man \ README.plugins \ tls-crypt-v2.txt \ $(openvpn_sections) \ $(openvpn_examples_sections) \ CMakeLists.txt EXTRA_DIST = tests # dependencies openvpn.8 openvpn.8.html: $(openvpn_sections) openvpn-examples.5 openvpn-examples.5.html: $(openvpn_examples_sections) ###### GENERIC RULES ########## SUFFIXES = .8.rst .8 .8.html .5.rst .5 .5.html RST_FLAGS = --strict MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in .8.rst.8 .5.rst.5 : if HAVE_PYDOCUTILS $(RST2MAN) $(RST_FLAGS) $< > $@ else @echo "Missing python-docutils - skipping man page generation ($@)" endif .8.rst.8.html .5.rst.5.html : if HAVE_PYDOCUTILS $(RST2HTML) $(RST_FLAGS) $< > $@ else @echo "Missing python-docutils - skipping html page generation ($@)" endif if HAVE_PYDOCUTILS dist_noinst_DATA += $(build_man_pages) dist_html_DATA = $(build_html_pages) # Failsafe - do not delete these files unless we can recreate them CLEANFILES = $(build_man_pages) $(build_html_pages) endif if WIN32 else dist_man_MANS = $(build_man_pages) endif dist-hook : $(build_man_pages) $(build_html_pages) ================================================ FILE: doc/README.man ================================================ man page documentation ====================== The man page content maintained in the openvpn.8.rst file and proper man and the html version of the man page are generated using python-docutils. Both the man page and html file are generated during 'make dist' or 'make distcheck' and should be distributed inside the tarball by default. Users compiling OpenVPN from the tarball should not need to regenerate the man/html files unless the source file needs to be modified. Further information: * Python docutils project: https://docutils.sourceforge.io/ * Quickstart on .rst https://docutils.sourceforge.io/docs/user/rst/quickstart.html * reStructuredText Markup Specifictaion (.rst) https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html ================================================ FILE: doc/README.plugins ================================================ OpenVPN Plugins --------------- Starting with OpenVPN 2.0-beta17, compiled plugin modules are supported on any *nix OS which includes libdl or on Windows. One or more modules may be loaded into OpenVPN using the --plugin directive, and each plugin module is capable of intercepting any of the script callbacks which OpenVPN supports: (1) up (2) down (3) route-up (4) ipchange (5) tls-verify (6) auth-user-pass-verify (7) client-connect (8) client-disconnect (9) learn-address See the openvpn-plugin.h file in the top-level directory of the OpenVPN source distribution for more detailed information on the plugin interface. Included Plugins ---------------- auth-pam -- Authenticate using PAM and a split privilege execution model which functions even if root privileges or the execution environment have been altered with --user/--group/--chroot. Tested on Linux only. down-root -- Enable the running of down scripts with root privileges even if --user/--group/--chroot have been used to drop root privileges or change the execution environment. Not applicable on Windows. examples -- A simple example that demonstrates a portable plugin, i.e. one which can be built for *nix or Windows from the same source. Building Plugins ---------------- cd to the top-level directory of a plugin, and use the "make" command to build it. The examples plugin is built using a build script, not a makefile. ================================================ FILE: doc/android.txt ================================================ This file documents the support in OpenVPN for Android using the VPNService API (https://developer.android.com/reference/android/net/VpnService) that has been introduced in Android 4.0 (API 14). This support is primarily used in the "OpenVPN for Android" app (https://github.com/schwabe/ics-openvpn). For building see the developer README: https://github.com/schwabe/ics-openvpn/blob/master/doc/README.txt Android provides the VPNService API (https://developer.android.com/reference/android/net/VpnService) which allows establishing VPN connections without rooting the device. Unlike on other platforms, the tun device is openend by UI instead of OpenVPN itself. The VpnService API needs the following parameters: - IP and netmask of tun interface - Networks that should be routed to the tun interface - DNS Servers and DNS Domain - MTU All IPs/Routes are in CIDR style. Non-CIDR routes are not supported. Notable is the lack of support for setting routes to other interfaces usually used to avoid the server connection going over the tun interface. However, Android 13 adds support for exclusion routes that serve the same purpose. The Android VPNService API has the concept of protecting a socket from being routed over an interface. Calling protect (fd) will internally bind the socket to the interface used for the external connection (usually WiFi or mobile data). To use OpenVPN with the VPNService API OpenVPN must be built with the TARGET_ANDROID compile option. Also the UI must use a UNIX domain socket to connect to OpenVPN. When compiled as TARGET_ANDROID OpenVPN will use management callbacks instead of executing traditional ifconfig/route commands use the need-ok callback mechanism which will ask > NEED-OK command where command can be: IFCONFIG6 IPv6/netmask IFCONFIG local remoteOrNetmask MTU topology To tell the UI which IPs addresses OpenVPN expects on the interface. Topology is one of "net30","p2p","subnet" or "undef". ROUTE6 network/netmask ROUTE network netmask To tell the UI which routes should be set on the tun interface. DNSSERVER IP server address DNS6SERVER IPv6 server address DNSDOMAIN searchdomain To set the DNS server and search domain. The GUI will then respond with a "needok 'command' ok' or "needok 'command' cancel', e.g. "needok 'IFCONFIG' ok". PERSIST_TUN_ACTION When OpenVPN wants to open an fd it will do this query via management. The UI should compare the last configuration of the tun device with the current tun configuration and reply with either NOACTION (or always respond with OPEN_BEFORE_CLOSE). - NOACTION: Keep using the old fd - OPEN_BEFORE_CLOSE: the normal behaviour when the VPN configuration changed For example the UI could respond with needok 'PERSIST_TUN_ACTION' OPEN_BEFORE_CLOSE To protect a socket the OpenVPN will send a PROTECTFD to the UI. When sending the PROTECTFD command command to the UI it will send the fd of the socket as ancillary message over the UNIX socket. The UI will then call protect(fd) on the received socket protecting it from being routed over the VPN. When opening a tun device the OpenVPN process will first send all route, ifconfig and DNS related configuration to the UI and after that calls the OPENTUN command to receive a tun fd with the requested configuration. The UI will then use the collected information to call the VPNService's establish() method to receive a fd which in turn is send to the OpenVPN process as ancillary message to the "needok 'OPENTUN' ok' response. The OpenVPN for Android UI extensively uses other features that are not specific to Android but are rarely used on other platform. For example using SIGUSR1 and management-hold to restart, pause, continue the VPN on network changes or the external key management --management-external-key option and inline files. To better support handover between networks, a the management command network-change [samenetwork] is used on the Android platform. It tells OpenVPN to do the necessary action when the network changes. Currently this is just calling the protect callback when using peer-id regardless of the samenetwork. Without peer-id OpenVPN will generate USR1 when samenetwork is not set. ================================================ FILE: doc/doxygen/Makefile.am ================================================ # # OpenVPN -- An application to securely tunnel IP networks # over a single UDP port, with support for SSL/TLS-based # session authentication and key exchange, # packet encryption, packet authentication, and # packet compression. # # Copyright (C) 2017-2026 Sentyron B.V. # MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in DISTCLEANFILES = openvpn.doxyfile DOXYGEN_EXTRA_FILES = \ doc_compression.h \ doc_control_processor.h \ doc_control_tls.h \ doc_data_control.h \ doc_data_crypto.h \ doc_eventloop.h \ doc_external_multiplexer.h \ doc_fragmentation.h \ doc_internal_multiplexer.h \ doc_key_generation.h \ doc_mainpage.h \ doc_memory_management.h \ doc_protocol_overview.h \ doc_reliable.h \ doc_tunnel_state.h EXTRA_DIST = $(DOXYGEN_EXTRA_FILES) .PHONY: doxygen doxygen: openvpn.doxyfile $(DOXYGEN_EXTRA_FILES) doxygen openvpn.doxyfile clean-local: -rm -rf html latex ================================================ FILE: doc/doxygen/doc_compression.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Data Channel Compression module documentation file. */ /** * @defgroup compression Data Channel Compression module * * This module offers compression of data channel packets. * * @par State structures * The Data Channel Compression module stores its internal state in a \c * lzo_compress_workspace structure. This state includes flags which * control the module's behavior and preallocated working memory. One * such structure is present for each VPN tunnel, and is stored in the \c * context.c2.lzo_compwork of the \c context associated with that VPN * tunnel. * * @par Initialization and cleanup * Every time a new \c lzo_compress_workspace is needed, it must be * initialized using the \c lzo_compress_init() function. Similarly, * every time a \c lzo_compress_workspace is no longer needed, it must be * cleaned up using the \c lzo_compress_uninit() function. These * functions take care of the allocation and freeing of internal working * memory, but not of the \c lzo_compress_workspace structures themselves. * * @par * Because of the one-to-one relationship between \c * lzo_compress_workspace structures and VPN tunnels, the above-mentioned * initialization and cleanup functions are called directly from the \c * init_instance() and \c close_instance() functions, which control the * initialization and cleanup of VPN tunnel instances and their associated * \c context structures. * * @par Packet processing functions * This module receives data channel packets from the \link data_control * Data Channel Control module\endlink and processes them according to the * settings of the packet's VPN tunnel. The \link data_control Data * Channel Control module\endlink uses the following interface functions: * - For packets which will be sent to a remote OpenVPN peer: \c * lzo_compress() * - For packets which have been received from a remote OpenVPN peer: \c * lzo_decompress() * * @par Settings that control this module's activity * Whether or not the Data Channel Compression module is active depends on * the compile-time \c ENABLE_LZO preprocessor macro and the runtime flags * stored in \c lzo_compress_workspace.flags of the associated VPN tunnel. * The latter are initialized from \c options.lzo, which gets its value * from the process's configuration sources, such as its configuration * file or command line %options. * * @par Adaptive compression * The compression module supports adaptive compression. If this feature * is enabled, the compression routines monitor their own performance and * turn compression on or off depending on whether it is leading to * significantly reduced payload size. * * @par Compression algorithms * This module uses the Lempel-Ziv-Oberhumer (LZO) compression algorithms. * These offer lossless compression and are designed for high-performance * decompression. This module uses the external \c lzo library's * implementation of the algorithms. * * @par * For more information on the LZO library, see:\n * https://www.oberhumer.com/opensource/lzo/ */ ================================================ FILE: doc/doxygen/doc_control_processor.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Control Channel Processor module documentation file. */ /** * @defgroup control_processor Control Channel Processor module * * This module controls the setup and maintenance of VPN tunnels and the * associated security parameters. * * @par This module's role * The Control Channel Processor module lies at the core of OpenVPN's * activities. It handles the setup of new VPN tunnels, the negotiation * of data channel security parameters, the managing of active VPN * tunnels, and finally the cleanup of expired VPN tunnels. * * @par State structures * A large amount of VPN tunnel state information must be stored within an * OpenVPN process. A wide variety of container structures are used by * this module for that purpose. Several of these structures are listed * below, and the function of the first three VPN tunnel state containers * is described in more detail later. * - VPN tunnel state containers: * - \c tls_multi, security parameter state for a single VPN tunnel. * Contains three instances of the \c tls_session structure. * - \c tls_session, security parameter state of a single session * within a VPN tunnel. Contains two instances of the \c key_state * structure. * - \c key_state, security parameter state of one TLS and data * channel %key set. * - Data channel security parameter containers: * - \c key_ctx_bi, container for two sets of OpenSSL cipher and/or * HMAC context (both directions). Contains two instances of the \c * key_ctx structure. * - \c key_ctx, container for one set of OpenSSL cipher and/or HMAC * context (one directions. * - Key material containers: * - \c key2, container for two sets of cipher and/or HMAC %key * material (both directions). Contains two instances of the \c key * structure. * - \c key, container for one set of cipher and/or HMAC %key material * (one direction). * - \c key_direction_state, ordering of %key material within the \c * key2.key array. * - Key method 2 random material containers: * - \c key_source2, container for both halves of random material used * for %key method 2. Contains two instances of the \c key_source * structure. * - \c key_source, container for one half of random material used for * %key method 2. * * @par The life of a \c tls_multi object * A \c tls_multi structure contains all the security parameter state * information related to the control and data channels of one VPN tunnel. * Its life cycle can be summarized as follows: * -# Initialization: \c tls_multi_init() and \c * tls_multi_init_finalize(), which are called (indirectly) from \c * init_instance() when initializing a new \c context structure. * - Initializes a \c tls_multi structure. * - Allocates the three \c tls_session objects contained by the \c * tls_multi structure, and initializes as appropriate. * -# Management: \c tls_multi_process() and \c tls_pre_decrypt() * - If a new session is initiated by the remote peer, then \c * tls_pre_decrypt() starts the new session negotiation in the * un-trusted \c tls_session. * - If the, as yet, un-trusted \c tls_session authenticates * successfully, then \c tls_multi_process() moves it so as to be * the active \c tls_session. * - If an error occurs during processing of a \c key_state object, * then \c tls_multi_process() cleans up and initializes the * associated \c tls_session object. If the error occurred in the * active \c key_state of the active \c tls_session and the * lame-duck \c key_state of that \c tls_session has not yet * expired, it is preserved as fallback. * -# Cleanup: \c tls_multi_free(), which is called (indirectly) from \c * close_instance() when cleaning up a \c context structure. * - Cleans up a \c tls_multi structure. * - Cleans up the three \c tls_session objects contained by the \c * tls_multi structure. * * @par The life of a \c tls_session object * A \c tls_session structure contains the state information related to an * active and a lame-duck \c key_state. Its life cycle can be summarized * as follows: * -# Initialization: \c tls_session_init() * - Initializes a \c tls_session structure. * - Initializes the primary \c key_state by calling \c * key_state_init(). * -# Renegotiation: \c key_state_soft_reset() * - Cleans up the old lame-duck \c key_state by calling \c * key_state_free(). * - Moves the old primary \c key_state to be the new lame-duck \c * key_state. * - Initializes a new primary \c key_state by calling \c * key_state_init(). * -# Cleanup: \c tls_session_free() * - Cleans up a \c tls_session structure. * - Cleans up all \c key_state objects associated with the session by * calling \c key_state_free() for each. * * @par The life of a \c key_state object * A \c key_state structure represents one control and data channel %key * set. It contains an OpenSSL TLS object that encapsulates the control * channel, and the data channel security parameters needed by the \link * data_crypto Data Channel Crypto module\endlink to perform cryptographic * operations on data channel packets. Its life cycle can be summarized * as follows: * -# Initialization: \c key_state_init() * - Initializes a \c key_state structure. * - Creates a new OpenSSL TLS object to encapsulate this new control * channel session. * - Sets \c key_state.state to \c S_INITIAL. * - Allocates several internal buffers. * - Initializes new reliability layer structures for this key set. * -# Negotiation: \c tls_process() * - The OpenSSL TLS object negotiates a TLS session between itself * and the remote peer's TLS object. * - Key material is generated and exchanged through the TLS session * between OpenVPN peers. * - Both peers initialize their data channel cipher and HMAC key * contexts. * - On successful negotiation, the \c key_state.state will progress * from \c S_INITIAL to \c S_ACTIVE and \c S_NORMAL. * -# Active tunneling: \link data_crypto Data Channel Crypto * module\endlink * - Data channel packet to be sent to a remote OpenVPN peer: * - \c tls_pre_encrypt() loads the security parameters from the \c * key_state into a \c crypto_options structure. * - \c openvpn_encrypt() uses the \c crypto_options to an encrypt * and HMAC sign the data channel packet. * - Data channel packet received from a remote OpenVPN peer: * - \c tls_pre_decrypt() loads the security parameters from the \c * key_state into a \c crypto_options structure. * - \c openvpn_encrypt() uses the \c crypto_options to * authenticate and decrypt the data channel packet. * -# Cleanup: \c key_state_free() * - Cleans up a \c key_state structure together with its OpenSSL TLS * object, key material, internal buffers, and reliability layer * structures. * * @par Control functions * The following two functions drive the Control Channel Processor's * activities. * - \c tls_multi_process(), iterates through the \c tls_session objects * within a given \c tls_multi of a VPN tunnel, and calls \c * tls_process() for each \c tls_session which is being set up, is * already active, or is busy expiring. * - \c tls_process(), performs the Control Channel Processor module's * core handling of received control channel messages, and generates * appropriate messages to be sent. * * @par Functions which control data channel key generation * - Key method 1 key exchange functions were removed from OpenVPN 2.5 * - Key method 2 key exchange functions: * - \c key_method_2_write(), generates and processes key material to * be sent to the remote OpenVPN peer. * - \c key_method_2_read(), processes key material received from the * remote OpenVPN peer. */ ================================================ FILE: doc/doxygen/doc_control_tls.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Control Channel TLS module documentation file. */ /** * @defgroup control_tls Control Channel TLS module * * This module provides secure encapsulation of control channel messages * exchanged between OpenVPN peers. * * The Control Channel TLS module uses the Transport Layer Security (TLS) * protocol to provide an encrypted communication channel between the * local OpenVPN process and a remote peer. This protocol simultaneously * offers certificate-based authentication of the communicating parties. * * @par This module's roles * The Control Channel TLS module is essential for the security of any * OpenVPN-based system. On the one hand, it performs the security * operations necessary to protect control channel messages exchanged * between OpenVPN peers. On the other hand, before the control and data * channels are even setup, it controls the exchange of certificates and * verification of the remote's identity during negotiation of VPN * tunnels. * * @par * The former role is described below. The latter is described in the * documentation for the verify_callback() function. * * @par * In other words, this module takes care of the confidentiality and * integrity of data channel communications, and the authentication of * both the communicating parties and the control channel messages * exchanged. * * @par Initialization and cleanup * Because of the one-to-one relationship between control channel TLS * state and \c key_state structures, the initialization and cleanup of an * instance of the Control Channel TLS module's state happens within the * key_state_init() and key_state_free() functions. In other words, * each \c key_state object contains exactly one OpenSSL SSL-BIO object, * which is initialized and cleaned up together with the rest of the \c * key_state object. * * @par Packet processing functions * This object behaves somewhat like a black box with a ciphertext and a * plaintext I/O port. Its interaction with OpenVPN's control channel * during operation takes place within the tls_process() function of * the \link control_processor Control Channel Processor\endlink. The * following functions are available for processing packets: * - If ciphertext received from the remote peer is available in the \link * reliable Reliability Layer\endlink: * - Insert it into the ciphertext-side of the SSL-BIO. * - Use function: key_state_write_ciphertext() * - If ciphertext can be extracted from the ciphertext-side of the * SSL-BIO: * - Pass it to the \link reliable Reliability Layer\endlink for sending * to the remote peer. * - Use function: key_state_read_ciphertext() * - If plaintext can be extracted from the plaintext-side of the SSL-BIO: * - Pass it on to the \link control_processor Control Channel * Processor\endlink for local processing. * - Use function: key_state_read_plaintext() * - If plaintext from the \link control_processor Control Channel * Processor\endlink is available to be sent to the remote peer: * - Insert it into the plaintext-side of the SSL-BIO. * - Use function: key_state_write_plaintext() or * key_state_write_plaintext_const() * * @par Transport Layer Security protocol implementation * This module uses the OpenSSL library's implementation of the TLS * protocol in the form of an OpenSSL SSL-BIO object. * * @par * For more information on the OpenSSL library's BIO objects, please see: * - OpenSSL's generic BIO objects: * https://docs.openssl.org/master/man7/bio/#bio * - OpenSSL's SSL-BIO object: * https://docs.openssl.org/master/man3/BIO_f_ssl/#bio_f_ssl */ ================================================ FILE: doc/doxygen/doc_data_control.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Data Channel Control module documentation file. */ /** * @defgroup data_control Data Channel Control module * * This module controls the processing of packets as they pass through the * data channel. * * The Data Channel Control module controls the processing of packets as * they pass through the data channel. The processing includes packet * compression, fragmentation, and the performing of security operations * on the packets. This module does not do the processing itself, but * passes the packet to other data channel modules to perform the * appropriate actions. * * Packets can travel in two directions through the data channel. They * can be going to a remote destination which is reachable through a VPN * tunnel, in which case this module prepares them to be sent out through * a VPN tunnel. On the other hand, they can have been received through a * VPN tunnel from a remote OpenVPN peer, in which case this module * retrieves the packet in its original form as it was before entering the * VPN tunnel on the remote OpenVPN peer. How this module processes * packets traveling in the two directions is discussed in more detail * below. * * @par Packets to be sent to a remote OpenVPN peer * This module's main function for processing packets traveling in this * direction is \c encrypt_sign(), which performs the following processing * steps: * - Call the \link compression Data Channel Compression module\endlink to * perform packet compression if necessary. * - Call the \link fragmentation Data Channel Fragmentation * module\endlink to perform packet fragmentation if necessary. * - Call the \link data_crypto Data Channel Crypto module\endlink to * perform the required security operations. * * @par * See the \c encrypt_sign() documentation for details of these * interactions. * * @par * After the above processing is complete, the packet is ready to be sent * to a remote OpenVPN peer as a VPN tunnel packet. The actual sending of * the packet is handled by the \link external_multiplexer External * Multiplexer\endlink. * * @par Packets received from a remote OpenVPN peer * The function that controls how packets traveling in this direction are * processed is \c process_incoming_link(). That function, however, also * performs some of the tasks required for the \link external_multiplexer * External Multiplexer\endlink and is therefore listed as part of that * module, instead of here. * * @par * After the \c process_incoming_link() function has determined that a * received packet is a data channel packet, it performs the following * processing steps: * - Call the \link data_crypto Data Channel Crypto module\endlink to * perform the required security operations. * - Call the \link fragmentation Data Channel Fragmentation * module\endlink to perform packet reassembly if necessary. * - Call the \link compression Data Channel Compression module\endlink to * perform packet decompression if necessary. * * @par * See the \c process_incoming_link() documentation for details of these * interactions. * * @par * After the above processing is complete, the packet is in its original * form again as it was received by the remote OpenVPN peer. It can now * be routed further to its final destination. If that destination is a * locally reachable host, then the \link internal_multiplexer Internal * Multiplexer\endlink will send it there. */ ================================================ FILE: doc/doxygen/doc_data_crypto.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Data Channel Crypto module documentation file. */ /** * @addtogroup data_crypto Data Channel Crypto module * * The Data Channel Crypto Module performs cryptographic operations on * data channel packets. * * @par Security parameters * This module is merely the user of a VPN tunnel's security parameters. * It does not perform the negotiation and setup of the security * parameters, nor the %key generation involved. These actions are done * by the \link control_processor Control Channel Processor\endlink. This * module receives the appropriate security parameters from that module in * the form of a \c crypto_options structure when they are necessary for * processing a packet. * * @par Packet processing functions * This module receives data channel packets from the \link data_control * Data Channel Control module\endlink and processes them according to the * security parameters of the packet's VPN tunnel. The \link data_control * Data Channel Control module\endlink uses the following interface * functions: * - For packets which will be sent to a remote OpenVPN peer: * - \c tls_pre_encrypt() * - \c openvpn_encrypt() * - \c tls_post_encrypt() * - For packets which have been received from a remote OpenVPN peer: * - \c tls_pre_decrypt() (documented as part of the \link * external_multiplexer External Multiplexer\endlink) * - \c openvpn_decrypt() * * @par Settings that control this module's activity * How the data channel processes packets received from the \link data_control * Data Channel Control module\endlink at runtime depends on the associated * \c crypto_options structure. To perform cryptographic operations, the * \c crypto_options.key_ctx_bi must contain the correct cipher and HMAC * security parameters for the direction the packet is traveling in. * * @par Crypto algorithms * This module uses the crypto algorithm implementations of the external * crypto library (currently either OpenSSL (default), or mbed TLS). */ ================================================ FILE: doc/doxygen/doc_eventloop.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Main Event Loop module documentation file. */ /** * @defgroup eventloop Main Event Loop module * * This main event loop module drives the packet processing of OpenVPN. * * OpenVPN is an event driven system. Its activities are driven by a main * event loop, which repeatedly waits for one of several predefined events * to occur, and then calls the appropriate module to handle the event. * The major types of network events that OpenVPN processes are: * - A packet can be read from the external network interface. * - The main event loop activates the \link external_multiplexer * External Multiplexer\endlink to read and process the packet. * - A packet can be read from the virtual tun/tap network interface. * - The main event loop activates the \link internal_multiplexer * Internal Multiplexer\endlink to read and process the packet. * - If a packet is ready to be sent out as a VPN tunnel packet: the * external network interface can be written to. * - The main event loop activates the \link external_multiplexer * External Multiplexer\endlink to send the packet. * - If a packet is ready to be sent to a locally reachable destination: * the virtual tun/tap network interface can be written to. * - The main event loop activates the \link internal_multiplexer * Internal Multiplexer\endlink to send the packet. * * Beside these external events, OpenVPN also processes other types of * internal events. These include scheduled events, such as resending of * non-acknowledged control channel messages. * * @par Main event loop implementations * * Depending on the mode in which OpenVPN is running, a different main * event loop function is called to drive the event processing. The * following implementations are available: * - Client mode using UDP or TCP: \c tunnel_point_to_point() * - Server mode using UDP: \c tunnel_server_udp() * - Server mode using TCP: \c tunnel_server_tcp() */ ================================================ FILE: doc/doxygen/doc_external_multiplexer.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * External Multiplexer module documentation file. */ /** * @addtogroup external_multiplexer External Multiplexer module * * The External Multiplexer is the link between the external network * interface and the other OpenVPN modules. It reads packets from the * external network interface, determines which remote OpenVPN peer and * VPN tunnel they are associated with, and whether they are data channel * or control channel packets. It then passes the packets on to the * appropriate processing module. * * This module also handles packets traveling in the reverse direction, * which have been generated by the local control channel or which have * already been processed by the \link data_control Data Channel Control * module\endlink and are destined for a remote host reachable through a * VPN tunnel. */ ================================================ FILE: doc/doxygen/doc_fragmentation.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Data Channel Fragmentation module documentation file. */ /** * @defgroup fragmentation Data Channel Fragmentation module * * The Data Channel Fragmentation module offers fragmentation of data * channel packets. * * @par State structures * The Data Channel Fragmentation module stores its internal state in a \c * fragment_master structure. One such structure is present for each VPN * tunnel, and is stored in \c context.c2.fragment of the \c context * associated with that VPN tunnel. * * @par * The \c fragment_master structure contains one \c fragment_list * structure \c fragment_master.incoming. This is a list of \c fragment * structures, each of which can store the parts of one fragmented packet * while it is being reassembled. The \c fragment_master structure also * contains one \c buffer called \c fragment_master.outgoing, in which a * data channel large packet to be sent to a remote OpenVPN peer can be * broken up into parts to be sent one by one. * * @par Initialization and cleanup * Every time a new \c fragment_master is needed, it must be allocated and * initialized by the \c fragment_init() function. Similarly, every time * a \c fragment_master is no longer needed, it must be cleaned up using * the \c fragment_free() function. These functions take care of the * allocation and freeing of the \c fragment_master structure itself and * all internal memory required for the use of that structure. Note that * this behavior is different from that displayed by the \link compression * Data Channel Compression module\endlink. * * @par * Because of the one-to-one relationship between \c fragment_master * structures and VPN tunnels, the above-mentioned initialization and * cleanup functions are called directly from the \c init_instance() and * \c close_instance() functions, which control the initialization and * cleanup of VPN tunnel instances and their associated \c context * structures. * * @par Packet processing functions * This module receives data channel packets from the \link data_control * Data Channel Control module\endlink and processes them according to the * settings of the packet's VPN tunnel. The \link data_control Data * Channel Control module\endlink uses the following interface functions: * - For packets which will be sent to a remote OpenVPN peer: \c * fragment_outgoing() \n This function inspects data channel packets as * they are being made ready to be sent as VPN tunnel packets to a * remote OpenVPN peer. If a packet's size is larger than its * destination VPN tunnel's maximum transmission unit (MTU), then this * module breaks that packet up into smaller parts, each of which is * smaller than or equal to the VPN tunnel's MTU. See \c * fragment_outgoing() for details. * - For packets which have been received from a remote OpenVPN peer: \c * fragment_incoming() \n This function inspects data channel packets * that have been received from a remote OpenVPN peer through a VPN * tunnel. It reads the fragmentation header of the packet, and * depending on its value performs the appropriate action. See \c * fragment_incoming() for details. * * @par Settings that control this module's activity * Whether the Data Channel Fragmentation module is active or not depends * on the compile-time \c ENABLE_FRAGMENT preprocessor macro and the * runtime flag \c options.fragment, which gets its value from the * process's configuration sources, such as the configuration file and * commandline %options. */ ================================================ FILE: doc/doxygen/doc_internal_multiplexer.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Internal Multiplexer module documentation file. */ /** * @addtogroup internal_multiplexer Internal Multiplexer module * * The Internal Multiplexer is the link between the virtual tun/tap * network interface and the \link data_control Data Channel Control * module\endlink. It reads packets from the virtual network interface, * determines for which remote OpenVPN peer they are destined, and then * passes the packets on to the Data Channel Control module together with * information about their destination VPN tunnel instance. * * This module also handles packets traveling in the reverse direction, * which have already been processed by the Data Channel Control module * and are destined for a locally reachable host. */ ================================================ FILE: doc/doxygen/doc_key_generation.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Key generation documentation file. */ /** * @page key_generation Data channel %key generation * * This section describes how OpenVPN peers generate and exchange %key * material necessary for the security operations performed on data * channel packets. * * The %key generation and exchange process between OpenVPN client and * server occurs every time data channel security parameters are * negotiated, for example during the initial setup of a VPN tunnel or * when the active security parameters expire. In source code terms, this * is when a new key_state structure is initialized. * * @section key_generation_method Key methods * * OpenVPN supports two different ways of generating and exchanging %key * material between client and server. These are known as %key method 1 * and %key method 2. %Key method 2 is the recommended method. Both are * explained below. * * @subsection key_generation_method_1 Key method 1 * * -# Each host generates its own random material. * -# Each host uses its locally generated random material as %key data * for encrypting and signing packets sent to the remote peer. * -# Each host then sends its random material to the remote peer, so that * the remote peer can use that %key data for authenticating and * decrypting received packets. * * @subsection key_generation_method_2 Key method 2 * * There are two methods for generating key data when using key method 2 * the first is OpenVPN's traditional approach that exchanges random * data and uses a PRF and the other is using the RFC5705 keying material * exporter to generate the key material. For both methods the random * data is exchange but only used in the traditional method. * * -# The client generates random material in the following amounts: * - Pre-master secret: 48 bytes * - Client's PRF seed for master secret: 32 bytes * - Client's PRF seed for %key expansion: 32 bytes * -# The client sends its share of random material to the server. * -# The server generates random material in the following amounts: * - Server's PRF seed for master secret: 32 bytes * - Server's PRF seed for %key expansion: 32 bytes * -# The server computes the %key expansion using its own and the * client's random material. * -# The server sends its share of random material to the client. * -# The client computes the %key expansion using its own and the * server's random material. * * %Key method 2 %key expansion is performed by the \c * generate_key_expansion_openvpn_prf() function. Please refer to its source * code for details of the %key expansion process. * * When the client sends the IV_PROTO_TLS_KEY_EXPORT flag and the server replies * with `key-derivation tls-ekm` the RFC5705 key material exporter with the * label EXPORTER-OpenVPN-datakeys is used for the key data. * * @subsection key_generation_random Source of random material * * OpenVPN uses the either the OpenSSL library or the mbed TLS library as its * source of random material. * * In OpenSSL, the \c RAND_bytes() function is called * to supply cryptographically strong pseudo-random data. The following links * contain more information on this subject: * - For OpenSSL's \c RAND_bytes() function: * https://docs.openssl.org/master/man3/RAND_bytes/#rand_bytes * - For OpenSSL's pseudo-random number generating system: * https://docs.openssl.org/master/man7/RAND/#rand * - For OpenSSL's support for external crypto modules: * https://docs.openssl.org/master/man7/provider/#provider * * In mbed TLS, the Havege random number generator is used. For details, see * the mbed TLS documentation. * * @section key_generation_exchange Key exchange: * * The %key exchange process is initiated by the OpenVPN process running * in client mode. After the initial three-way handshake has successfully * completed, the client sends its share of random material to the server, * after which the server responds with its part. This process is * depicted below: * @verbatim Client Client Server Server State Action Action State ---------- -------------------- -------------------- ---------- ... waiting until three-way handshake complete ... S_START S_START key_method_?_write() send to server --> --> --> --> receive from client S_SENT_KEY key_method_?_read() S_GOT_KEY key_method_?_write() receive from server <-- <-- <-- <-- send to client key_method_?_read() S_SENT_KEY S_GOT_KEY ... waiting until control channel fully synchronized ... S_ACTIVE S_ACTIVE @endverbatim * * For more information about the client and server state values, see the * \link control_processor Control Channel Processor module\endlink. * * Depending on which %key method is used, the \c ? in the function names * of the diagram above is a \c 1 or a \c 2. For example, if %key method * 2 is used, that %key exchange would be started by the client calling \c * key_method_2_write(). These functions are called from the \link * control_processor Control Channel Processor module's\endlink \c * tls_process() function and control the %key generation and exchange * process as follows: * - %Key method 1 has been removed in OpenVPN 2.5 * - %Key method 2: * - \c key_method_2_write(): generate random material locally, and if * in server mode generate %key expansion. * - \c key_method_2_read(): read random material received from remote * peer, and if in client mode generate %key expansion. * * @subsection key_generation_encapsulation Transmission of key material * * The OpenVPN client and server communicate with each other through their * control channel. This means that all of the data transmitted over the * network, such as random material for %key generation, is encapsulated * in a TLS layer. For more details, see the \link control_tls Control * Channel TLS module\endlink documentation. */ ================================================ FILE: doc/doxygen/doc_mainpage.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Main page documentation file. */ /** * @mainpage OpenVPN source code documentation * * This documentation describes the internal structure of OpenVPN. It was * automatically generated from specially formatted comment blocks in * OpenVPN's source code using Doxygen. (See * https://www.doxygen.nl/ for more information on Doxygen) * * The \ref mainpage_modules "Modules section" below gives an introduction * into the high-level module concepts used throughout this documentation. * The \ref mainpage_relatedpages "Related Pages section" below describes * various special subjects related to OpenVPN's implementation which are * discussed in the related pages section. * * @section mainpage_modules Modules * * For the purpose of describing the internal structure of OpenVPN, this * documentation and the underlying source code has been broken up into a * number of conceptually well-defined parts, known as modules. Each * module plays a specific role within the OpenVPN process, and in most * cases each module has a clear interfacing strategy for interacting with * other modules. * * The following modules have been defined: * - Driver module: * - The \link eventloop Main Event Loop\endlink: this module drives the * event handling of OpenVPN. It implements various types of * select-loop which wait until an event happens, and then delegate * the handling of that event to the appropriate module. * - Network interface modules: * - The \link external_multiplexer External Multiplexer\endlink: this * module sends and receives packets to and from remote OpenVPN peers * over the external network interface. It also takes care of * demultiplexing received packets to their appropriate VPN tunnel and * splitting control channel and data channel packets. * - The \link internal_multiplexer Internal Multiplexer\endlink: this * module sends and receives packets to and from locally reachable * posts over the virtual tun/tap network interface. It also takes * care of determining through which VPN tunnel a received packet must * be sent to reach its destination. * - Control channel modules: * - The \link reliable Reliability Layer\endlink: this module offers a * %reliable and sequential transport layer for control channel * messages. * - The \link control_tls Control Channel TLS module\endlink: this * module offers a secure encapsulation of control channel messages * using the TLS protocol. * - The \link control_processor Control Channel Processor\endlink: his * module manages the setup, maintenance, and shut down of VPN * tunnels. * - Data channel modules: * - The \link data_control Data Channel Control module\endlink: this * module controls the processing of data channel packets and, * depending on the settings of the packet's VPN tunnel, passes the * packet to the three modules below for handling. * - The \link data_crypto Data Channel Crypto module\endlink: this * module performs security operations on data channel packets. * - The \link fragmentation Data Channel Fragmentation module\endlink: * this module offers fragmentation of data channel packets larger * than the VPN tunnel's MTU. * - The \link compression Data Channel Compression module\endlink: this * module offers compression of data channel packets. * * @subsection mainpage_modules_example Example event: receiving a packet * * OpenVPN handles many types of events during operation. These include * external events, such as network traffic being received, and internal * events, such as a %key session timing out causing renegotiation. An * example event, receiving a packet over the network, is described here * together with which modules play what roles: * -# The \link eventloop Main Event Loop\endlink detects that a packet * can be read from the external or the virtual tun/tap network * interface. * -# The \link eventloop Main Event Loop\endlink calls the \link * external_multiplexer External Multiplexer\endlink or \link * internal_multiplexer Internal Multiplexer\endlink to read and * process the packet. * -# The multiplexer module determines the type of packet and its * destination, and passes the packet on to the appropriate handling * module: * - A control channel packet received by the \link * external_multiplexer External Multiplexer\endlink is passed on * through the \link reliable Reliability Layer\endlink and the \link * control_tls Control Channel TLS module\endlink to the \link * control_processor Control Channel Processor\endlink. * - A data channel packet received by either multiplexer module is * passed on to the \link data_control Data Channel Control * module\endlink. * -# The packet is processed by the appropriate control channel or data * channel modules. * -# If, after processing the packet, a resulting packet is generated * that needs to be sent to a local or remote destination, it is given * to the \link external_multiplexer External Multiplexer\endlink or * \link internal_multiplexer Internal Multiplexer\endlink for sending. * -# If a packet is waiting to be sent by either multiplexer module and * the \link eventloop Main Event Loop\endlink detects that data can be * written to the associated network interface, it calls the * multiplexer module to send the packet. * * @section mainpage_relatedpages Related pages * * This documentation includes a number of descriptions of various aspects * of OpenVPN and its implementation. These are not directly related to * one module, function, or data structure, and are therefore listed * separately under "Related Pages". * * @subsection mainpage_relatedpages_key_generation Data channel key generation * * The @ref key_generation "Data channel key generation" related page * describes how, during VPN tunnel setup and renegotiation, OpenVPN peers * generate and exchange the %key material required for the symmetric * encryption/decryption and HMAC signing/verifying security operations * performed on data channel packets. * * @subsection mainpage_relatedpages_tunnel_state VPN tunnel state * * The @ref tunnel_state "Structure of VPN tunnel state storage" related * page describes how an OpenVPN process manages the state information * associated with its active VPN tunnels. * * @subsection mainpage_relatedpages_network_protocol Network protocol * * The @ref network_protocol "Network protocol" related page describes the * format and content of VPN tunnel packets exchanged between OpenVPN * peers. * * @subsection mainpage_relatedpages_memory_management Memory management * * The @ref memory_management "Memory management strategies" related page * gives a brief introduction into OpenVPN's memory %buffer library and * garbage collection facilities. */ ================================================ FILE: doc/doxygen/doc_memory_management.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Memory management strategies documentation file. */ /** * @page memory_management OpenVPN's memory management strategies * * This section describes several implementation details relating to * OpenVPN's memory management strategies. * * During operation, the OpenVPN process performs all kinds of operations * on blocks of data. Receiving packets, encrypting content, prepending * headers, etc. To make the programmer's job easier and to decrease the * likelihood of memory-related bugs, OpenVPN uses its own memory %buffer * library and garbage collection facilities. These are described in * brief here. * * @section memory_management_buffer The buffer structure * * The \c buffer structure is a wrapper around a block of dynamically * allocated memory which keeps track of the block's capacity \c * buffer.capacity and location in memory \c buffer.data. This structure * supports efficient prepending and appending within the allocated memory * through the use of offset \c buffer.offset and length \c buffer.len * fields. See the \c buffer documentation for more details on the * structure itself. * * OpenVPN's %buffer library, implemented in the \c buffer.h and \c * buffer.c files, contains many utility functions for working with \c * buffer structures. These functions facilitate common operations, such * as allocating, freeing, reading and writing to \c buffer structures, * and even offer several more advanced operations, such as string * matching and creating sub-buffers. * * Not only do these utility functions make working with \c buffer * structures easy, they also perform extensive error checking. Each * function, where necessary, checks whether enough space is available * before performing its actions. This minimizes the chance of bugs * leading to %buffer overflows and other vulnerabilities. * * @section memory_management_frame The frame structure * * The \c frame structure keeps track of the maximum allowed packet * geometries of a network connection. * * It is used, for example, to determine the size of \c buffer structures * in which to store data channel packets. This is done by having each * data channel processing module register the maximum amount of extra * space it will need for header prepending and content expansion in the * \c frame structure. Once these parameters are known, \c buffer * structures can be allocated, based on the \c frame parameters, so that * they are large enough to allow efficient prepending of headers and * processing of content. * * @section memory_management_garbage Garbage collection * * OpenVPN has many sizable functions which perform various actions * depending on their %context. This makes it difficult to know in advance * exactly how much memory must be allocated. The garbage collection * facilities are used to keep track of dynamic allocations, thereby * allowing easy collective freeing of the allocated memory. * * The garbage collection system is implemented by the \c gc_arena and \c * gc_entry structures. The arena represents a garbage collecting unit, * and contains a linked list of entries. Each entry represents one block * of dynamically allocated memory. * * The garbage collection system also contains various utility functions * for working with the garbage collection structures. These include * functions for initializing new arenas, allocating memory of a given * size and registering the allocation in an arena, and freeing all the * allocated memory associated with an arena. */ ================================================ FILE: doc/doxygen/doc_protocol_overview.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Network protocol overview documentation file. */ /** * @page network_protocol OpenVPN's network protocol * * Description of packet structure in OpenVPN's network protocol. * * This document describes the structure of packets exchanged between * OpenVPN peers. It is based on the protocol description in the \c ssl.h * file. * * @section network_protocol_external Outer structure of packets exchanged between OpenVPN peers * * VPN tunnel packets are transported between OpenVPN peers using the UDP * or TCP protocols. Their structure is described below. * * @subsection network_protocol_external_structure External packet structure * * - packet length (16 bits, unsigned) [TCP-mode only]: always sent as * plain text. Since TCP is a stream protocol, this packet length * defines the packetization of the stream. * - packet opcode and key_id (8 bits) [TLS-mode only]: * - package message type (high 5 bits) * - key_id (low 3 bits): the key_id refers to an already negotiated * TLS session. OpenVPN seamlessly renegotiates the TLS session by * using a new key_id for the new session. Overlap (controlled by * user definable parameters) between old and new TLS sessions is * allowed, providing a seamless transition during tunnel operation. * - payload (n bytes) * * @subsection network_protocol_external_types Message types * * The type of a VPN tunnel packet is indicated by its opcode. The * following describes the various opcodes available. * * - Control channel messages: * - \ref P_CONTROL_HARD_RESET_CLIENT_V1 -- %Key method 1, initial %key * from client, forget previous state. * - \ref P_CONTROL_HARD_RESET_SERVER_V1 -- %Key method 1, initial %key * from server, forget previous state. * - \ref P_CONTROL_HARD_RESET_CLIENT_V2 -- %Key method 2, initial %key * from client, forget previous state. * - \ref P_CONTROL_HARD_RESET_SERVER_V2 -- %Key method 2, initial %key * from server, forget previous state. * - \ref P_CONTROL_SOFT_RESET_V1 -- New %key, with a graceful * transition from old to new %key in the sense that a transition * window exists where both the old or new key_id can be used. * - \ref P_CONTROL_V1 -- Control channel packet (usually TLS * ciphertext). * - \ref P_ACK_V1 -- Acknowledgement for control channel packets * received. * - Data channel messages: * - \ref P_DATA_V1 -- Data channel packet containing data channel * ciphertext. * - \ref P_DATA_V2 -- Data channel packet containing peer-id and data * channel ciphertext. * * @subsection network_protocol_external_key_id Session IDs and Key IDs * * OpenVPN uses two different forms of packet identifiers: * - The first form is 64 bits and is used for all control channel * messages. This form is referred to as a \c session_id. * - Data channel messages on the other hand use a shortened form of 3 * bits for efficiency reasons since the vast majority of OpenVPN * packets in an active tunnel will be data channel messages. This * form is referred to as a \c key_id. * * The control and data channels use independent packet-id sequences, * because the data channel is an unreliable channel while the control * channel is a %reliable channel. Each use their own independent HMAC * keys. * * @subsection network_protocol_external_reliable Control channel reliability layer * * Control channel messages (\c P_CONTROL_* and \c P_ACK_* message types) * are TLS ciphertext packets which have been encapsulated inside of a * reliability layer. The reliability layer is implemented as a * straightforward acknowledge and retransmit model. * * Acknowledgments of received messages can be encoded in either the * dedicated \c P_ACK_* record or they can be prepended to a \c * P_CONTROL_* message. * * See the \link reliable Reliability Layer\endlink module for a detailed * description. * * @section network_protocol_control Structure of control channel messages * * @subsection network_protocol_control_ciphertext Structure of ciphertext control channel messages * * Control channel packets in ciphertext form consist of the following * parts: * * - local \c session_id (random 64 bit value to identify TLS session). * (the tls-server side uses a HMAC of the client to create a pseudo * random number for a SYN Cookie like approach) * - HMAC signature of entire encapsulation header for HMAC firewall * [only if \c --tls-auth is specified] (usually 16 or 20 bytes). * - packet-id for replay protection (4 or 8 bytes, includes sequence * number and optional \c time_t timestamp). * - acknowledgment packet-id array length (1 byte). * - acknowledgment packet-id array (if length > 0). * - acknowledgment remote session-id (if length > 0). * - packet-id of this message (4 bytes). * - TLS payload ciphertext (n bytes) (only for \c P_CONTROL_V1). * * Note that when \c --tls-auth is used, all message types are protected * with an HMAC signature, even the initial packets of the TLS handshake. * This makes it easy for OpenVPN to throw away bogus packets quickly, * without wasting resources on attempting a TLS handshake which will * ultimately fail. * * @subsection network_protocol_control_key_methods Control channel key methods * * Once the TLS session has been initialized and authenticated, the TLS * channel is used to exchange random %key material for bidirectional * cipher and HMAC keys which will be used to secure data channel packets. * OpenVPN currently implements two %key methods. %Key method 1 directly * derives keys using random bits obtained from the \c rand_bytes() function. * %Key method 2 mixes random %key material from both sides of the connection * using the TLS PRF mixing function. %Key method 2 is the preferred method and * is the default for OpenVPN 2.0+. * * The @ref key_generation "Data channel key generation" related page * describes the %key methods in more detail. * * @subsection network_protocol_control_plaintext Structure of plaintext control channel messages * * - %Key method 1 (support removed in OpenVPN 2.5): * - Cipher %key length in bytes (1 byte). * - Cipher %key (n bytes). * - HMAC %key length in bytes (1 byte). * - HMAC %key (n bytes). * - %Options string (n bytes, null terminated, client/server %options * string should match). * - %Key method 2: * - Literal 0 (4 bytes). * - %Key method (1 byte). * - \c key_source structure (\c key_source.pre_master only defined * for client -> server). * - %Options string length, including null (2 bytes). * - %Options string (n bytes, null terminated, client/server %options * string must match). * - [The username/password data below is optional, record can end at * this point.] * - Username string length, including null (2 bytes). * - Username string (n bytes, null terminated). * - Password string length, including null (2 bytes). * - Password string (n bytes, null terminated). * * @section network_protocol_data Structure of data channel messages * * The P_DATA_* payload represents encapsulated tunnel packets which tend to be * either IP packets or Ethernet frames. This is essentially the "payload" of * the VPN. Data channel packets consist of a data channel header, and a * payload. There are two possible formats: * * @par P_DATA_V1 * P_DATA_V1 packets have a 1-byte header, carrying the \ref P_DATA_V1 \c opcode * and \c key_id, followed by the payload:\n * [ 5-bit opcode | 3-bit key_id ] [ payload ] * * @par P_DATA_V2 * P_DATA_V2 packets have the same 1-byte opcode/key_id, but carrying the \ref * P_DATA_V2 opcode, followed by a 3-byte peer-id, which uniquely identifies * the peer:\n * [ 5-bit opcode | 3-bit key_id ] [ 24-bit peer-id ] [ payload ] * * See @ref data_crypto for details on the data channel payload format. * */ ================================================ FILE: doc/doxygen/doc_reliable.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * Reliability Layer module documentation file. */ /** * @defgroup reliable Reliability Layer module * * The Reliability Layer is part of OpenVPN's control channel. It * provides a reliable and sequential transport mechanism for control * channel messages between OpenVPN peers. This module forms the * interface between the \link external_multiplexer External * Multiplexer\endlink and the \link control_tls Control Channel TLS * module\endlink. * * @par UDP or TCP as VPN tunnel transport * * This is especially important when OpenVPN is configured to communicate * over UDP, because UDP does not offer a reliable and sequential * transport. OpenVPN endpoints can also communicate over TCP which does * provide a reliable and sequential transport. In both cases, using UDP * or TCP as an external transport, the internal Reliability Layer is * active. */ ================================================ FILE: doc/doxygen/doc_tunnel_state.h ================================================ /* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2010-2026 Sentyron B.V. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ /** * @file * VPN tunnel state documentation file. */ /** * @page tunnel_state Structure of the VPN tunnel state storage * * This section describes how OpenVPN stores its VPN tunnel state during * operation. * * OpenVPN uses several data structures as storage containers for state * information of active VPN tunnels. These are described in this * section, together with a little bit of history to help understand the * origin of the current architecture. * * Whether an OpenVPN process is running in client-mode or server-mode * determines whether it can support only one or multiple simultaneously * active VPN tunnels. This consequently also determines how the * associated state information is wrapped up internally. This section * gives an overview of the differences. * * @section tunnel_state_history Historic developments * * In the old v1.x series, an OpenVPN process managed only one single VPN * tunnel. This allowed the VPN tunnel state to be stored together with * process-global information in one single \c context structure. * * This changed, however, in the v2.x series, as new OpenVPN versions * running in server-mode can support multiple simultaneously active VPN * tunnels. This necessitated a redesign of the VPN tunnel state * container structures, and modification of the \link * external_multiplexer External Multiplexer\endlink and \link * internal_multiplexer Internal Multiplexer\endlink systems. The * majority of these changes are only relevant for OpenVPN processes * running in server-mode, and the client-mode structure has remained very * similar to the v1.x single-tunnel form. * * @section tunnel_state_client Client-mode state * * An OpenVPN process running in client-mode can manage at most one single * VPN tunnel at any one time. The state information for a client's VPN * tunnel is stored in a \c context structure. * * The \c context structure is created in the \c main() function. That is * also where process-wide initialization takes place, such as parsing * command line %options and reading configuration files. The \c context * is then passed to \c tunnel_point_to_point() which drives OpenVPN's * main event processing loop. These functions are both part of the \link * eventloop Main Event Loop\endlink module. * * @subsection tunnel_state_client_init Initialization and cleanup * * Because there is only one \c context structure present, it can be * initialized and cleaned up from the client's main event processing * function. Before the \c tunnel_point_to_point() function enters its * event loop, it calls \c init_instance_handle_signals() which calls \c * init_instance() to initialize the single \c context structure. After * the event loop stops, it calls \c close_instance() to clean up the \c * context. * * @subsection tunnel_state_client_event Event processing * * When the main event processing loop activates the external or internal * multiplexer to handle a network event, it is not necessary to determine * which VPN tunnel the event is associated with, because there is only * one VPN tunnel active. * * @section tunnel_state_server Server-mode state * * An OpenVPN process running in server-mode can manage multiple * simultaneously active VPN tunnels. For every VPN tunnel active, in * other words for every OpenVPN client which is connected to a server, * the OpenVPN server has one \c context structure in which it stores that * particular VPN tunnel's state information. * * @subsection tunnel_state_server_multi Multi_context and multi_instance structures * * To support multiple \c context structures, each is wrapped in a \c * multi_instance structure, and all the \c multi_instance structures are * registered in one single \c multi_context structure. The \link * external_multiplexer External Multiplexer\endlink and \link * internal_multiplexer Internal Multiplexer\endlink then use the \c * multi_context to retrieve the correct \c multi_instance and \c context * associated with a given network address. * * @subsection tunnel_state_server_init Startup and initialization * * An OpenVPN process running in server-mode starts in the same \c main() * function as it would in client-mode. The same process-wide * initialization is performed, and the resulting state and configuration * is stored in a \c context structure. The server-mode and client-mode * processes diverge when the \c main() function calls one of \c * tunnel_point_to_point() or \c tunnel_server(). * * In server-mode, \c main() calls the \c tunnel_server() function, which * transfers control to \c tunnel_server_udp() or \c * tunnel_server_tcp() depending on the external transport protocol. * * These functions receive the \c context created in \c main(). This * object has a special status in server-mode, as it does not represent an * active VPN tunnel, but does contain process-wide configuration * parameters. In the source code, it is often stored in "top" variables. * To distinguish this object from other instances of the same type, its * \c context.mode value is set to \c CM_TOP. Other \c context objects, * which do represent active VPN tunnels, have a \c context.mode set to \c * CM_CHILD_UDP or \c CM_CHILD_TCP, depending on the external transport * protocol. * * Both \c tunnel_server_udp_single_threaded() and \c tunnel_server_tcp() * perform similar initialization. In either case, a \c multi_context * structure is created, and it is initialized according to the * configuration stored in the top \c context by the \c multi_init() and * \c multi_top_init() functions. * * @subsection tunnel_state_server_tunnels Creating and destroying VPN tunnels * * When an OpenVPN client makes a new connection to a server, the server * creates a new \c context and \c multi_instance. The latter is * registered in the \c multi_context, which makes it possible for the * external and internal multiplexers to retrieve the correct \c * multi_instance and \c context when a network event occurs. * * @subsection tunnel_state_server_cleanup Final cleanup * * After the main event loop exits, both \c * tunnel_server_udp_single_threaded() and \c tunnel_server_tcp() perform * similar cleanup. They call \c multi_uninit() followed by \c * multi_top_free() to clean up the \c multi_context structure. */ ================================================ FILE: doc/doxygen/openvpn.doxyfile.in ================================================ # Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the configuration # file that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = OpenVPN # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = @abs_top_builddir@/doc/doxygen # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all generated output in the proper direction. # Possible values are: None, LTR, RTL and Context. # The default value is: None. OUTPUT_TEXT_DIRECTION = None # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @abs_top_srcdir@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as # /*************** # as being the beginning of a Javadoc-style comment "banner". If set to NO, the # Javadoc-style will behave just like regular comments and it will not be # interpreted by doxygen. # The default value is: NO. JAVADOC_BANNER = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # By default Python docstrings are displayed as preformatted text and doxygen's # special commands cannot be used. By setting PYTHON_DOCSTRING to NO the # doxygen's special commands can be used and the contents of the docstring # documentation blocks is shown as doxygen documentation. # The default value is: YES. PYTHON_DOCSTRING = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines (in the resulting output). You can put ^^ in the value part of an # alias to insert a newline as if a physical newline was in the original file. # When you need a literal { or } or , in the value part of an alias you have to # escape them by means of a backslash (\), this can lead to conflicts with the # commands \{ and \} for these it is advised to use the version @{ and @} or use # a double escape (\\{ and \\}) ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice # sources only. Doxygen will then generate output that is more tailored for that # language. For instance, namespaces will be presented as modules, types will be # separated into more groups, etc. # The default value is: NO. OPTIMIZE_OUTPUT_SLICE = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, JavaScript, # Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, # Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the # default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. # Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of # cores available in the system. You can set it explicitly to a value larger # than 0 to get more control over the balance between CPU load and processing # speed. At this moment only the input processing can be done using multiple # threads. Since this is still an experimental feature the default is set to 1, # which efficively disables parallel processing. Please report any issues you # encounter. Generating dot graphs in parallel is controlled by the # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # methods of a class will be included in the documentation. # The default value is: NO. EXTRACT_PRIV_VIRTUAL = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = YES # If this flag is set to YES, the name of an unnamed parameter in a declaration # will be determined by the corresponding definition. By default unnamed # parameters remain unnamed in the output. # The default value is: YES. RESOLVE_UNNAMED_PARAMS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that # are not case sensitive the option should be be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On # Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. If # EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS # then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but # at the end of the doxygen process doxygen will return with a non-zero status. # Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = @abs_top_builddir@/doc/doxygen.warnings.log #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = @abs_top_srcdir@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), # *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, # *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.h # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = @abs_top_srcdir@/out/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: # http://clang.llvm.org/) for more accurate parsing at the cost of reduced # performance. This can be particularly helpful with template rich C++ code for # which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to # YES then doxygen will add the directory of each input to the include path. # The default value is: YES. CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to # specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = NO # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that # are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML # page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To # create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: # https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path # including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg # tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see # https://inkscape.org) to generate formulas as SVG images instead of PNGs for # the HTML output. These images will generally look nicer at scaled resolutions. # Possible values are: png (the default) and svg (looks nicer but requires the # pdf2svg or inkscape tool). # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from https://www.mathjax.org before deployment. # The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /