diff --git a/.gitignore b/.gitignore index 0e76568..602b0f2 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,33 @@ playground.xcworkspace # Carthage/Checkouts Carthage/Build + +## macOS generated + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/OpenVPNAdapter.xcodeproj/project.pbxproj b/OpenVPNAdapter.xcodeproj/project.pbxproj index f0a7128..986fc9b 100644 --- a/OpenVPNAdapter.xcodeproj/project.pbxproj +++ b/OpenVPNAdapter.xcodeproj/project.pbxproj @@ -1137,6 +1137,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; @@ -1185,6 +1186,7 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = NO; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/README b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/README index 8a91d93..a030c23 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/README +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/README @@ -1,4 +1,4 @@ -asio version 1.13.0 -Released Tuesday, 12 March 2019. +asio version 1.14.0 +Released Sunday, 14 April 2019. See doc/index.html for API documentation and a tutorial. diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/configure.ac b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/configure.ac index e7cd3d1..2e20b84 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/configure.ac +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(asio, [1.13.0]) +AC_INIT(asio, [1.14.0]) AC_CONFIG_SRCDIR(include/asio.hpp) AM_MAINTAINER_MODE AM_INIT_AUTOMAKE([tar-ustar]) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/io_object_impl.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/io_object_impl.hpp index 4280fb8..6f57b66 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/io_object_impl.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/io_object_impl.hpp @@ -24,8 +24,34 @@ #include "asio/detail/push_options.hpp" namespace asio { + +class executor; + namespace detail { +inline bool is_native_io_executor(const io_context::executor_type&) +{ + return true; +} + +template +inline bool is_native_io_executor(const Executor&, + typename enable_if::value>::type* = 0) +{ + return false; +} + +template +inline bool is_native_io_executor(const Executor& ex, + typename enable_if::value>::type* = 0) +{ +#if !defined (ASIO_NO_TYPEID) + return ex.target_type() == typeid(io_context::executor_type); +#else // !defined (ASIO_NO_TYPEID) + return false; +#endif // !defined (ASIO_NO_TYPEID) +} + template class io_object_impl @@ -46,8 +72,7 @@ public: // Construct an I/O object using an executor. explicit io_object_impl(const executor_type& ex) : service_(&asio::use_service(ex.context())), - implementation_executor_(ex, - is_same::value) + implementation_executor_(ex, (is_native_io_executor)(ex)) { service_->construct(implementation_); } @@ -68,9 +93,7 @@ public: // Move-construct an I/O object. io_object_impl(io_object_impl&& other) : service_(&other.get_service()), - implementation_executor_( - ASIO_MOVE_CAST(implementation_executor_type)( - other.implementation_executor_)) + implementation_executor_(other.get_implementation_executor()) { service_->move_construct(implementation_, other.implementation_); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp index 59aaf5f..e4e5fd7 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/reactive_socket_accept_op.hpp @@ -151,8 +151,10 @@ private: template class reactive_socket_move_accept_op : - private Protocol::socket, - public reactive_socket_accept_op_base + private Protocol::socket::template rebind_executor::other, + public reactive_socket_accept_op_base< + typename Protocol::socket::template rebind_executor::other, + Protocol> { public: ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op); @@ -161,8 +163,8 @@ public: socket_type socket, socket_ops::state_type state, const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, Handler& handler, const IoExecutor& io_ex) - : Protocol::socket(peer_io_ex), - reactive_socket_accept_op_base( + : peer_socket_type(peer_io_ex), + reactive_socket_accept_op_base( socket, state, *this, protocol, peer_endpoint, &reactive_socket_move_accept_op::do_complete), handler_(ASIO_MOVE_CAST(Handler)(handler)), @@ -194,9 +196,9 @@ public: // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. detail::move_binder2 + asio::error_code, peer_socket_type> handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, - ASIO_MOVE_CAST(typename Protocol::socket)(*o)); + ASIO_MOVE_CAST(peer_socket_type)(*o)); p.h = asio::detail::addressof(handler.handler_); p.reset(); @@ -211,6 +213,9 @@ public: } private: + typedef typename Protocol::socket::template + rebind_executor::other peer_socket_type; + Handler handler_; IoExecutor io_executor_; }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_global.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_global.hpp index b2036e7..2d5ce75 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_global.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_global.hpp @@ -35,7 +35,7 @@ struct win_global_impl static win_global_impl instance_; static static_mutex mutex_; - static T* ptr_; + T* ptr_; static tss_ptr tss_ptr_; }; @@ -45,9 +45,6 @@ win_global_impl win_global_impl::instance_ = { 0 }; template static_mutex win_global_impl::mutex_ = ASIO_STATIC_MUTEX_INIT; -template -T* win_global_impl::ptr_ = 0; - template tss_ptr win_global_impl::tss_ptr_; @@ -58,9 +55,9 @@ T& win_global() { win_global_impl::mutex_.init(); static_mutex::scoped_lock lock(win_global_impl::mutex_); - if (win_global_impl::ptr_ == 0) - win_global_impl::ptr_ = new T; - win_global_impl::tss_ptr_ = win_global_impl::ptr_; + if (win_global_impl::instance_.ptr_ == 0) + win_global_impl::instance_.ptr_ = new T; + win_global_impl::tss_ptr_ = win_global_impl::instance_.ptr_; } return *win_global_impl::tss_ptr_; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_iocp_socket_accept_op.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_iocp_socket_accept_op.hpp index abd9b28..c7da5c1 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_iocp_socket_accept_op.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/detail/win_iocp_socket_accept_op.hpp @@ -262,9 +262,9 @@ public: // to ensure that any owning sub-object remains valid until after we have // deallocated the memory here. detail::move_binder2 + asio::error_code, peer_socket_type> handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), ec, - ASIO_MOVE_CAST(typename Protocol::socket)(o->peer_)); + ASIO_MOVE_CAST(peer_socket_type)(o->peer_)); p.h = asio::detail::addressof(handler.handler_); p.reset(); @@ -279,10 +279,13 @@ public: } private: + typedef typename Protocol::socket::template + rebind_executor::other peer_socket_type; + win_iocp_socket_service_base& socket_service_; socket_type socket_; socket_holder new_socket_; - typename Protocol::socket peer_; + peer_socket_type peer_; Protocol protocol_; typename Protocol::endpoint* peer_endpoint_; unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/version.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/version.hpp index cdd175f..e8a6c27 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/version.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/version.hpp @@ -18,6 +18,6 @@ // ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100000 is the major version -#define ASIO_VERSION 101300 // 1.13.0 +#define ASIO_VERSION 101400 // 1.14.0 #endif // ASIO_VERSION_HPP diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/doc/history.qbk b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/doc/history.qbk index 3dedb9d..a85e608 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/doc/history.qbk +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/doc/history.qbk @@ -7,6 +7,21 @@ [section:history Revision History] +[heading Asio 1.14.0] + +* Improved I/O object performance by adding runtime detection of native I/O + executors when using the polymorphic executor wrapper. + +* Changed I/O object move constructors so that the executor is copied, not + moved. This ensures that the moved-from I/O object is left in the same state + as if constructed with a valid executor but without a resource. + +* On Windows, fixed an issue where global object destructors were not being + run. + +* Fixed move-based `async_accept` between sockets with different executor + types. + [heading Asio 1.13.0] * Added custom I/O executor support to I/O objects. diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/tcp.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/tcp.cpp index 1ec7015..df45d5f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/tcp.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/tcp.cpp @@ -729,6 +729,17 @@ struct move_accept_handler private: move_accept_handler(const move_accept_handler&) {} }; + +struct move_accept_ioc_handler +{ + move_accept_ioc_handler() {} + void operator()(const asio::error_code&, + asio::basic_stream_socket) {} + move_accept_ioc_handler(move_accept_handler&&) {} +private: + move_accept_ioc_handler(const move_accept_handler&) {} +}; #endif // defined(ASIO_HAS_MOVE) void test() @@ -913,8 +924,12 @@ void test() #if defined(ASIO_HAS_MOVE) acceptor1.async_accept(move_accept_handler()); acceptor1.async_accept(ioc, move_accept_handler()); + acceptor1.async_accept(ioc_ex, move_accept_handler()); + acceptor1.async_accept(ioc_ex, move_accept_ioc_handler()); acceptor1.async_accept(peer_endpoint, move_accept_handler()); acceptor1.async_accept(ioc, peer_endpoint, move_accept_handler()); + acceptor1.async_accept(ioc_ex, peer_endpoint, move_accept_handler()); + acceptor1.async_accept(ioc_ex, peer_endpoint, move_accept_ioc_handler()); #endif // defined(ASIO_HAS_MOVE) } catch (std::exception&) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/aesni.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/aesni.h index 746baa0..7b16b4b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/aesni.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/aesni.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #define MBEDTLS_AESNI_AES 0x02000000u diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/asn1write.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/asn1write.h index f76fc80..083601a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/asn1write.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/asn1write.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "asn1.h" #define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ @@ -183,24 +189,27 @@ int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, const char *text, size_t text_len ); /** - * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf the bitstring - * \param bits the total number of bits in the bitstring + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t bits ); /** - * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. * * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/base64.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/base64.h index 7a64f52..10e4145 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/base64.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/base64.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/bn_mul.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/bn_mul.h index 956b0bc..396c1ac 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/bn_mul.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/bn_mul.h @@ -38,6 +38,12 @@ #ifndef MBEDTLS_BN_MUL_H #define MBEDTLS_BN_MUL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "bignum.h" #if defined(MBEDTLS_HAVE_ASM) @@ -170,19 +176,19 @@ #define MULADDC_INIT \ asm( \ - "xorq %%r8, %%r8 \n\t" + "xorq %%r8, %%r8\n" #define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" #define MULADDC_STOP \ : "+c" (c), "+D" (d), "+S" (s) \ @@ -734,7 +740,7 @@ "sw $10, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ ); #endif /* MIPS */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ccm.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ccm.h index 630b7fd..e311e75 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ccm.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ccm.h @@ -34,6 +34,12 @@ #ifndef MBEDTLS_CCM_H #define MBEDTLS_CCM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "cipher.h" #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/certs.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/certs.h index 8dab7b5..b7c5708 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/certs.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/certs.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_CERTS_H #define MBEDTLS_CERTS_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #ifdef __cplusplus diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/check_config.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/check_config.h index be80332..8ea1c15 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/check_config.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/check_config.h @@ -107,7 +107,7 @@ #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif -#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ @@ -118,10 +118,15 @@ !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) ) ) #error "MBEDTLS_ECP_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ !defined(MBEDTLS_SHA256_C)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" @@ -667,7 +672,7 @@ /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the - * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. */ typedef int mbedtls_iso_c_forbids_empty_translation_units; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/cmac.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/cmac.h index 24839a2..adfe1c3 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/cmac.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/cmac.h @@ -26,6 +26,12 @@ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "cipher.h" #ifdef __cplusplus diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/compat-1.3.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/compat-1.3.h index 600a0f1..94de845 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/compat-1.3.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/compat-1.3.h @@ -25,6 +25,12 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/config.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/config.h index 9feb49b..83dc013 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/config.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/config.h @@ -112,7 +112,7 @@ * \def MBEDTLS_HAVE_TIME_DATE * * System has time.h and time(), gmtime() and the clock is correct. - * The time needs to be correct (not necesarily very accurate, but at least + * The time needs to be correct (not necessarily very accurate, but at least * the date should be correct). This is used to verify the validity period of * X.509 certificates. * @@ -318,7 +318,7 @@ * \note Because of a signature change, the core AES encryption and decryption routines are * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, * respectively. When setting up alternative implementations, these functions should - * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt * must stay untouched. * * \note If you use the AES_xxx_ALT macros, then is is recommended to also set @@ -333,6 +333,16 @@ * dependencies on them, and considering stronger message digests * and ciphers instead. * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * */ //#define MBEDTLS_MD2_PROCESS_ALT //#define MBEDTLS_MD4_PROCESS_ALT @@ -556,6 +566,26 @@ */ #define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + /** * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED * @@ -1188,7 +1218,7 @@ /** * \def MBEDTLS_SSL_RENEGOTIATION * - * Disable support for TLS renegotiation. + * Enable support for TLS renegotiation. * * The two main uses of renegotiation are (1) refresh keys on long-lived * connections and (2) client authentication after the initial handshake. @@ -1372,7 +1402,7 @@ * \def MBEDTLS_SSL_SESSION_TICKETS * * Enable support for RFC 5077 session tickets in SSL. - * Client-side, provides full support for session tickets (maintainance of a + * Client-side, provides full support for session tickets (maintenance of a * session store remains the responsibility of the application, though). * Server-side, you also need to provide callbacks for writing and parsing * tickets, including authenticated encryption and key management. Example @@ -1538,7 +1568,7 @@ * * \warning TLS-level compression MAY REDUCE SECURITY! See for example the * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be a applicable to your use case. + * CRIME or similar exploits may be applicable to your use case. * * \note Currently compression can't be used with DTLS. * @@ -2734,7 +2764,7 @@ //#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ -/* Note: your snprintf must correclty zero-terminate the buffer! */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ //#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ @@ -2751,7 +2781,7 @@ //#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ -/* Note: your snprintf must correclty zero-terminate the buffer! */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ //#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ctr_drbg.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ctr_drbg.h index e554a0a..5a32843 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ctr_drbg.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ctr_drbg.h @@ -28,6 +28,12 @@ #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #if defined(MBEDTLS_THREADING_C) @@ -227,14 +233,37 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. - * \param add_len Length of \p additional data. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * - * \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, - * only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. - * The remaining Bytes are silently discarded. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \warning This function cannot report errors. You should use + * mbedtls_ctr_drbg_update_ret() instead. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. */ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); + const unsigned char *additional, + size_t add_len ); /** * \brief This function updates a CTR_DRBG instance with additional diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdh.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdh.h index 99cfde0..d16bad2 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdh.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdh.h @@ -33,6 +33,12 @@ #ifndef MBEDTLS_ECDH_H #define MBEDTLS_ECDH_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ecp.h" #ifdef __cplusplus diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdsa.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdsa.h index ff6efbc..08811a3 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdsa.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecdsa.h @@ -31,6 +31,12 @@ #ifndef MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ecp.h" #include "md.h" @@ -101,6 +107,20 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * Usage of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA). * + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * * \param grp The ECP group. * \param r The first output integer. * \param s The second output integer. @@ -121,9 +141,56 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * * \see ecp.h */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ); +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecjpake.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecjpake.h index d86e820..8d09bf2 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecjpake.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecjpake.h @@ -40,6 +40,11 @@ * The payloads are serialized in a way suitable for use in TLS, but could * also be use outside TLS. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif #include "ecp.h" #include "md.h" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp.h index 7b8ffff..691415e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "bignum.h" /* @@ -595,6 +601,22 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po */ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); +/** + * \brief Generate a private key + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + /** * \brief Generate a keypair with configurable base point * diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp_internal.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp_internal.h index 1804069..7625ed4 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp_internal.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ecp_internal.h @@ -61,6 +61,12 @@ #ifndef MBEDTLS_ECP_INTERNAL_H #define MBEDTLS_ECP_INTERNAL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #if defined(MBEDTLS_ECP_INTERNAL_ALT) /** diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/error.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/error.h index 8b4d3a8..ef22bc6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/error.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/error.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include /** diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/gcm.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/gcm.h index 00ed421..bd258aa 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/gcm.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/gcm.h @@ -31,6 +31,12 @@ #ifndef MBEDTLS_GCM_H #define MBEDTLS_GCM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "cipher.h" #include diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/havege.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/havege.h index d4cb3ed..e6bf6fa 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/havege.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/havege.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_HAVEGE_H #define MBEDTLS_HAVEGE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/hmac_drbg.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/hmac_drbg.h index 2608de8..bd05da3 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/hmac_drbg.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/hmac_drbg.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "md.h" #if defined(MBEDTLS_THREADING_C) @@ -76,7 +82,7 @@ extern "C" { */ typedef struct { - /* Working state: the key K is not stored explicitely, + /* Working state: the key K is not stored explicitly, * but is implied by the HMAC context */ mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ @@ -195,11 +201,31 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, * \param additional Additional data to update state with, or NULL * \param add_len Length of additional data, or 0 * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG update state + * + * \warning This function cannot report errors. You should use + * mbedtls_hmac_drbg_update_ret() instead. + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * * \note Additional data is optional, pass NULL and 0 as second * third argument if no additional data is being used. */ void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); + const unsigned char *additional, + size_t add_len ); /** * \brief HMAC_DRBG reseeding (extracts data from entropy source) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/net.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/net.h index 6c13b53..8cead58 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/net.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/net.h @@ -23,6 +23,11 @@ * * This file is part of mbed TLS (https://tls.mbed.org) */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) #include "net_sockets.h" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/padlock.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/padlock.h index 677936e..918e619 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/padlock.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/padlock.h @@ -25,6 +25,12 @@ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pem.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pem.h index 2cf4c0a..8191850 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pem.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pem.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include /** diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pk.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pk.h index ee06b2f..8beb2af 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pk.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pk.h @@ -343,6 +343,10 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + * + * \note In order to ensure enough space for the signature, the + * \p sig buffer size must be of at least + * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes. */ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs12.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs12.h index a621ef5..d441357 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs12.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs12.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "md.h" #include "cipher.h" #include "asn1.h" @@ -46,6 +52,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS12 Password Based function (encryption / decryption) * for pbeWithSHAAnd128BitRC4 @@ -87,6 +95,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *input, size_t len, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief The PKCS#12 derivation function uses a password and a salt * to produce pseudo-random bits for a particular "purpose". diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs5.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs5.h index 9a3c9fd..f201250 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs5.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/pkcs5.h @@ -26,6 +26,12 @@ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "asn1.h" #include "md.h" @@ -44,6 +50,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS#5 PBES2 function * @@ -62,6 +70,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *data, size_t datalen, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief PKCS#5 PBKDF2 using HMAC * diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/rsa.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/rsa.h index 5548f3c..a1298da 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/rsa.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/rsa.h @@ -146,13 +146,13 @@ mbedtls_rsa_context; * \note The choice of padding mode is strictly enforced for private key * operations, since there might be security concerns in * mixing padding modes. For public key operations it is - * a default value, which can be overriden by calling specific + * a default value, which can be overridden by calling specific * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. * * \note The hash selected in \p hash_id is always used for OEAP * encryption. For PSS signatures, it is always used for - * making signatures, but can be overriden for verifying them. - * If set to #MBEDTLS_MD_NONE, it is always overriden. + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. */ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, @@ -819,6 +819,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_sign() for details on @@ -862,6 +863,7 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. */ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -902,6 +904,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. * * \note The \p hash_id in the RSA context is the one used for the * encoding. \p md_alg in the function call is the type of hash diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl.h index 72374e3..13a3871 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl.h @@ -1611,7 +1611,7 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * provision more than one cert/key pair (eg one ECDSA, one * RSA with SHA-256, one RSA with SHA-1). An adequate * certificate will be selected according to the client's - * advertised capabilities. In case mutliple certificates are + * advertised capabilities. In case multiple certificates are * adequate, preference is given to the one set by the first * call to this function, then second, etc. * @@ -1622,6 +1622,14 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * whether it matches those preferences - the server can then * decide what it wants to do with it. * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * * \param conf SSL configuration * \param own_cert own public certificate chain * \param pk_key own private key @@ -2102,12 +2110,27 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** - * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * \brief Set the maximum fragment length to emit and/or negotiate. + * (Typical: #MBEDTLS_SSL_MAX_CONTENT_LEN, by default that is + * set to `2^14` bytes) * (Server: set maximum fragment length to emit, - * usually negotiated by the client during handshake + * usually negotiated by the client during handshake) * (Client: set maximum fragment length to emit *and* * negotiate with the server during handshake) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). * * \param conf SSL configuration * \param mfl_code Code for maximum fragment length (allowed values: @@ -2309,13 +2332,14 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); /** * \brief Return the result of the certificate verification * - * \param ssl SSL context + * \param ssl The SSL context to use. * - * \return 0 if successful, - * -1 if result is not available (eg because the handshake was - * aborted too early), or - * a combination of BADCERT_xxx and BADCRL_xxx flags, see - * x509.h + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. */ uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); @@ -2610,7 +2634,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). * * \note You need to call mbedtls_ssl_config_defaults() unless you - * manually set all of the relevent fields yourself. + * manually set all of the relevant fields yourself. * * \param conf SSL configuration context */ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cache.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cache.h index ec081e6..52ba094 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cache.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cache.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" #if defined(MBEDTLS_THREADING_C) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ciphersuites.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ciphersuites.h index 1d2aabc..655d130 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "pk.h" #include "cipher.h" #include "md.h" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cookie.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cookie.h index 80b65bb..6a7ff9c 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cookie.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_cookie.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" #if defined(MBEDTLS_THREADING_C) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_internal.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_internal.h index 2b5a616..168d4a2 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_internal.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_internal.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_SSL_INTERNAL_H #define MBEDTLS_SSL_INTERNAL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" #include "cipher.h" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ticket.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ticket.h index 93ad46a..389b33c 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ticket.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/ssl_ticket.h @@ -24,6 +24,12 @@ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + /* * This implementation of the session ticket callbacks includes key * management, rotating the keys periodically in order to preserve forward @@ -111,14 +117,14 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, /** * \brief Implementation of the ticket write callback * - * \note See \c mbedlts_ssl_ticket_write_t for description + * \note See \c mbedtls_ssl_ticket_write_t for description */ mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; /** * \brief Implementation of the ticket parse callback * - * \note See \c mbedlts_ssl_ticket_parse_t for description + * \note See \c mbedtls_ssl_ticket_parse_t for description */ mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/version.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/version.h index aa2764b..0c8c8ae 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/version.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/version.h @@ -40,16 +40,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 7 -#define MBEDTLS_VERSION_PATCH 5 +#define MBEDTLS_VERSION_PATCH 12 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02070500 -#define MBEDTLS_VERSION_STRING "2.7.5" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.7.5" +#define MBEDTLS_VERSION_NUMBER 0x02070C00 +#define MBEDTLS_VERSION_STRING "2.7.12" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.7.12" #if defined(MBEDTLS_VERSION_C) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509.h index d6db9c6..2a3d7ec 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509.h @@ -77,7 +77,7 @@ #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ -#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ /* \} name */ /** @@ -250,7 +250,7 @@ int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *se * * \param to mbedtls_x509_time to check * - * \return 1 if the given time is in the past or an error occured, + * \return 1 if the given time is in the past or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); @@ -264,7 +264,7 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); * * \param from mbedtls_x509_time to check * - * \return 1 if the given time is in the future or an error occured, + * \return 1 if the given time is in the future or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crl.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crl.h index 08a4283..fa838d6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crl.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crl.h @@ -111,7 +111,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, /** * \brief Parse one or more CRLs and append them to the chained list * - * \note Mutliple CRLs are accepted only if using PEM format + * \note Multiple CRLs are accepted only if using PEM format * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in PEM or DER format @@ -126,7 +126,7 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s /** * \brief Load one or more CRLs and append them to the chained list * - * \note Mutliple CRLs are accepted only if using PEM format + * \note Multiple CRLs are accepted only if using PEM format * * \param chain points to the start of the chain * \param path filename to read the CRLs from (in PEM or DER encoding) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crt.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crt.h index 2e48991..9df19e5 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crt.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_crt.h @@ -100,7 +100,7 @@ mbedtls_x509_crt; * Build flag from an algorithm/curve identifier (pk, md, ecp) * Since 0 is always XXX_NONE, ignore it. */ -#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( ( id ) - 1 ) ) /** * Security profile for certificate verification. @@ -177,19 +177,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu size_t buflen ); /** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_csr.h b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_csr.h index 0c6ccad..a3c2804 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_csr.h +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/include/mbedtls/x509_csr.h @@ -205,6 +205,14 @@ void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_ty * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. */ int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedcrypto.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedcrypto.a index f7e9462..2d883a5 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedcrypto.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedcrypto.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedtls.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedtls.a index 26303bf..9341098 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedtls.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedtls.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedx509.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedx509.a index 91d45c7..c074128 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedx509.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/ios/libmbedx509.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedcrypto.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedcrypto.a index 89bed92..014d19c 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedcrypto.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedcrypto.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedtls.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedtls.a index f2c031b..b9dbd8d 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedtls.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedtls.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedx509.a b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedx509.a index 9c54dbe..96dbf9c 100644 Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedx509.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/mbedtls/lib/macos/libmbedx509.a differ diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml index d8551dc..6b44bdb 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml @@ -1,19 +1,17 @@ -dist: trusty - +dist: bionic os: linux - language: cpp env: global: - secure: "dqiLqbzug/xs6F4Q9ei1pGpNf9Q6H3+iKN1W+P0TtODbCXPr/mLWdvHGVMIMqr7H7rBrIUPFPrfqd80nu3jQuQonjcHK/XyJJfmf5hUdhGAszSaixhWnGfVmn/VSV7/5+9DGAU3l9S6YZg4lvi12+cOrlblNgx8GeI5VdN/6HBSHkEqKNI56qn3Y+ugSdLeL1opmzlY58vRsCCmpBH8Ronn4tmSyi85/WZXfF43o9FGGJcygdh6QVWA1CDdNMeLTCt9ld+oToUIiFLiUrhfS1JpSvzysz2xsuEntxZaTMDYPyL4+O8Mj/scl6ejLLXzxTNa7AZOgySLBahf+F4b+yhL1deSVuu40MfxPW6XiM1jKy3KPH/GlYgM8CZQ3D1hQIq1CIUg8DgnTa06RUzevsR5DqDvz+EcPanFHE7dHGrPy9Rs/0y59dNHp3qWKjWMoSA06GerbF61XFOb4mcE29053kV8uxqIa5ZShZ/ndoLeVpQ4mZ+/XSkUybysVl0gWrKnnNNEPtqrdmKf+jlmKY0jyRPdwf425Ldn+wcbGw9ZEnkosYzqAhDBDX4OETAKLi8G0FEYECKKQcd1OX+HNvsOIyOAoLOj7H30F8UkPsjR3ysdIEmc6702ly06gDYjWmwQaCigL/1ktRKgf7ePB0HS+8fOa5SML7619kQrGrWA=" - PREFIX="${HOME}/opt" - - ASIO_VERSION="862aed305dcf91387535519c9549c17630339a12" + - ASIO_VERSION="90f32660cd503494b3707840cfbd5434d8e9dabe" - LZ4_VERSION="1.8.3" - MBEDTLS_VERSION="2.7.5" - MBEDTLS_CFLAGS="-I${PREFIX}/include" - MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto" - - OPENSSL_VERSION="1.0.2l" + - OPENSSL_VERSION="1.0.2s" - OPENSSL_CFLAGS="-I${PREFIX}/include" - OPENSSL_LIBS="-lssl -lcrypto" - COVERITY_BRANCH="master" @@ -22,9 +20,11 @@ matrix: include: - env: SSLLIB="openssl" os: osx + osx_image: xcode10.2 compiler: clang - env: SSLLIB="mbedtls" os: osx + osx_image: xcode10.2 compiler: clang - env: SSLLIB="openssl" RUN_COVERITY_SCAN="1" os: linux diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis/build-check.sh b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis/build-check.sh index e37d1f4..5c8f2fa 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis/build-check.sh +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis/build-check.sh @@ -25,11 +25,11 @@ else fi LIBS="${SSL_LIBS} -llz4" -CXXFLAGS="-O3 -std=c++11 -Wall -pthread \ +CXXFLAGS="-O3 -std=c++14 -Wall -pthread \ -DOPENVPN_SHOW_SESSION_TOKEN -DHAVE_LZ4 \ -DUSE_ASIO -DASIO_STANDALONE -DASIO_NO_DEPRECATED ${SSL_CFLAGS}" -if [[ "${CC}" == "gcc"* ]]; then +if [ "${CC}" = "gcc" ]; then CXXFLAGS="${CXXFLAGS} -fwhole-program -flto=4" fi diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/README.rst b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/README.rst index c960dc2..550b0d4 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/README.rst +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/README.rst @@ -117,6 +117,7 @@ not required for Mac builds. Build the dependencies:: + $ DL=~/Downloads $ OSX_ONLY=1 $O3/core/scripts/mac/build-all Now build the OpenVPN 3 client executable:: @@ -125,7 +126,7 @@ Now build the OpenVPN 3 client executable:: $ . vars/vars-osx64 $ . vars/setpath $ cd test/ovpncli - $ MTLS=1 LZ4=1 build cli + $ MTLS=1 LZ4=1 ASIO=1 build cli This will build the OpenVPN 3 client library with a small client wrapper (``cli``). It will also statically link in all external @@ -151,8 +152,9 @@ Building the OpenVPN 3 client on Windows Prerequisites: - - Visual Studio 2017 - - Python 2.7 +* Visual Studio 2017 +* Python 2.7 +* Perl (for building openssl) Clone the OpenVPN 3 source repo:: @@ -160,19 +162,19 @@ Clone the OpenVPN 3 source repo:: > c:\Temp>cd O3 > c:\Temp\O3>git clone https://github.com/OpenVPN/openvpn3.git core +Add environment variable ``O3`` with value ``c:\Temp\O3`` and reopen commmand prompt. + Download and build dependencies:: > c:\Temp\O3>cd core\win - > c:\Temp\O3\core\win>set O3=C:\Temp\O3 && python buildep.py + > c:\Temp\O3\core\win>set STATIC=1&& set DEBUG=1&& python buildep.py -Build test client:: +Now you can open project in Visual Studio. Project and solution files are +located in ``O3\core\win`` directory. - > c:\Temp\O3\core\win>set O3=C:\Temp\O3 && python build.py - -Visual Studio 2017 project and solution files are located in ``O3\core\win`` directory. -Before opening project you need to build dependencies and define OVPN3_ROOT -environmental variable (``C:\Temp\O3`` from example above). +You can also build the test client from command prompt:: + > c:\Temp\O3\core\win>set STATIC=1&& set DEBUG=1&& python build.py Testing ------- diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/appveyor.yml b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/appveyor.yml index 03de31a..06884d1 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/appveyor.yml +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/appveyor.yml @@ -1,24 +1,32 @@ version: 1.0.{build} -image: Visual Studio 2017 +image: Visual Studio 2019 clone_folder: c:\ovpn3\core install: - pip install rfc6266 requests +- if not exist "C:\strawberry" choco install strawberryperl -y +- set PATH=C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin;%PATH% environment: - MSVC_DIR: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community + MSVC_DIR: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community O3: C:\ovpn3 STATIC: 1 before_build: - cmd: cd win && python buildep.py +after_build: +- cmd: copy c:\ovpn3\deps\amd64\openssl\out32dll\ssleay32.dll c:\ovpn3\core\win\x64\ReleaseOpenSSL\ +- cmd: copy c:\ovpn3\deps\amd64\openssl\out32dll\libeay32.dll c:\ovpn3\core\win\x64\ReleaseOpenSSL\ + platform: x64 -configuration: Release +configuration: ReleaseOpenSSL artifacts: - - path: win\x64\Release\cli.exe + - path: win\x64\ReleaseOpenSSL\cli.exe + - path: win\x64\ReleaseOpenSSL\*.dll + diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp index 8cc799d..c1a433f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp @@ -262,7 +262,13 @@ namespace openvpn { bool socket_protect(int socket, IP::Addr endpoint) override { if (parent) - return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6()); + { +#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN) + return WinCommandAgent::add_bypass_route(endpoint); +#else + return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6()); +#endif + } else return true; } @@ -436,7 +442,10 @@ namespace openvpn { std::string tls_version_min_override; std::string tls_cert_profile_override; std::string gui_version; + std::string sso_methods; bool allow_local_lan_access; + std::string hw_addr_override; + std::string platform_version; ProtoContextOptions::Ptr proto_context_options; PeerInfo::Set::Ptr extra_peer_info; HTTPProxyTransport::Options::Ptr http_proxy_options; @@ -656,7 +665,7 @@ namespace openvpn { catch (const std::exception& e) { eval.error = true; - eval.message = Unicode::utf8_printable(e.what(), 256); + eval.message = Unicode::utf8_printable(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); } } @@ -689,6 +698,9 @@ namespace openvpn { state->tls_cert_profile_override = config.tlsCertProfileOverride; state->allow_local_lan_access = config.allowLocalLanAccess; state->gui_version = config.guiVersion; + state->sso_methods = config.ssoMethods; + state->platform_version = config.platformVersion; + state->hw_addr_override = config.hwAddrOverride; state->alt_proxy = config.altProxy; state->dco = config.dco; state->echo = config.echo; @@ -801,6 +813,11 @@ namespace openvpn { return ret; } + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::socket_protect(int socket, std::string remote, bool ipv6) + { + return true; + } + OPENVPN_CLIENT_EXPORT bool OpenVPNClient::parse_dynamic_challenge(const std::string& cookie, DynamicChallenge& dc) { try { @@ -962,14 +979,17 @@ namespace openvpn { cc.tls_version_min_override = state->tls_version_min_override; cc.tls_cert_profile_override = state->tls_cert_profile_override; cc.gui_version = state->gui_version; + cc.sso_methods = state->sso_methods; + cc.hw_addr_override = state->hw_addr_override; + cc.platform_version = state->platform_version; cc.extra_peer_info = state->extra_peer_info; cc.stop = state->async_stop_local(); cc.allow_local_lan_access = state->allow_local_lan_access; #ifdef OPENVPN_GREMLIN cc.gremlin_config = state->gremlin_config; #endif -#if defined(USE_TUN_BUILDER) cc.socket_protect = &state->socket_protect; +#if defined(USE_TUN_BUILDER) cc.builder = this; #endif #if defined(OPENVPN_EXTERNAL_TUN_FACTORY) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp index a542a45..f06762a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp @@ -172,6 +172,20 @@ namespace openvpn { // Passed to server as IV_GUI_VER. std::string guiVersion; + // Set to a comma seperated list of supported SSO mechanisms that may + // be signalled via INFO_PRE to the client. + // "openurl" is to continue authentication by opening an url in a browser + // "crtext" gives a challenge response in text format that needs to + // responded via control channel. ( + // Passed to the server as IV_SSO + std::string ssoMethods; + + // Override the string that is passed as IV_HWADDR to the server + std::string hwAddrOverride; + + // Set the string that is passed to the server as IV_PLAT_VER + std::string platformVersion; + // Use a different server than that specified in "remote" // option of profile std::string serverOverride; @@ -481,7 +495,7 @@ namespace openvpn { // Callback to "protect" a socket from being routed through the tunnel. // Will be called from the thread executing connect(). // The remote and ipv6 are the remote host this socket will connect to - virtual bool socket_protect(int socket, std::string remote, bool ipv6) = 0; + virtual bool socket_protect(int socket, std::string remote, bool ipv6); // Primary VPN client connect method, doesn't return until disconnect. // Should be called by a worker thread. This method will make callbacks diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions index 6747668..dee22d5 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions @@ -1,11 +1,11 @@ -export ASIO_VERSION=asio-1-13-0 -export ASIO_CSUM=54a1208d20f2104dbd6b7a04a9262f5ab649f4b7a9faf7eac4c2294e9e104c06 +export ASIO_VERSION=asio-1-14-0 +export ASIO_CSUM=bdb01a649c24d73ca4a836662e7af442d935313ed6deef6b07f17f3bc5f78d7a export LZ4_VERSION=lz4-1.8.3 export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43 -export MBEDTLS_VERSION=mbedtls-2.7.5 -export MBEDTLS_CSUM=a1302ad9094aabb9880d2755927b466a6bac8e02b68e04dee77321f3859e9b40 +export MBEDTLS_VERSION=mbedtls-2.7.12 +export MBEDTLS_CSUM=d3a36dbc9f607747daa6875c1ab2e41f49eff5fc99d3436b4f3ac90c89f3c143 export JSONCPP_VERSION=1.8.4 export JSONCPP_CSUM=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch index 3b1d159..f7f8f00 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0002-Enable-allowing-unsupported-critical-extensions-in-r.patch @@ -1,8 +1,7 @@ -From c6963e33209e7fd40d65513e06c1bbb20319abe3 Mon Sep 17 00:00:00 2001 +From 076f1437fe82de0b1f0ecf9a7ca031cd94c0c579 Mon Sep 17 00:00:00 2001 From: Lev Stipakov Date: Fri, 23 Feb 2018 17:12:49 +0200 -Subject: [PATCH 2/2] Enable allowing unsupported critical extensions in - runtime +Subject: [PATCH] Enable allowing unsupported critical extensions in runtime When compile time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION is not set, certificate parsing fails if certificate contains unsupported critical extension. @@ -55,7 +54,7 @@ index 408645ece..b116736f8 100644 /** diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h -index c6e453274..72374e36b 100644 +index 5fd6969da..1087ea166 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -696,6 +696,10 @@ struct mbedtls_ssl_config @@ -69,7 +68,7 @@ index c6e453274..72374e36b 100644 #if defined(MBEDTLS_SSL_RENEGOTIATION) int renego_max_records; /*!< grace period for renegotiation */ unsigned char renego_period[8]; /*!< value of the record counters -@@ -2275,6 +2279,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, +@@ -2298,6 +2302,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, const unsigned char period[8] ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -95,7 +94,7 @@ index c6e453274..72374e36b 100644 * \brief Return the number of data bytes available to read * diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h -index ac23cffe8..2e489915f 100644 +index e72231ee8..9df19e52c 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -90,6 +90,8 @@ typedef struct mbedtls_x509_crt @@ -220,10 +219,10 @@ index edea950f8..a756d2801 100644 static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { diff --git a/library/ssl_tls.c b/library/ssl_tls.c -index ca9b8c432..dba0d5122 100644 +index 1270ee9b8..2ce3f9b7d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c -@@ -4656,6 +4656,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +@@ -4668,6 +4668,9 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); @@ -233,7 +232,7 @@ index ca9b8c432..dba0d5122 100644 i += 3; while( i < ssl->in_hslen ) -@@ -6586,6 +6589,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, +@@ -6626,6 +6629,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -246,18 +245,18 @@ index ca9b8c432..dba0d5122 100644 #if defined(MBEDTLS_SSL_CLI_C) void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) diff --git a/library/x509_crt.c b/library/x509_crt.c -index 6751da0d2..149149b96 100644 +index 3ad53a715..130b3ad1b 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c -@@ -530,6 +530,7 @@ static int x509_get_crt_ext( unsigned char **p, +@@ -539,6 +539,7 @@ static int x509_get_crt_ext( unsigned char **p, int ret; size_t len; unsigned char *end_ext_data, *end_ext_octet; + int is_supported; - if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) - { -@@ -589,9 +590,9 @@ static int x509_get_crt_ext( unsigned char **p, + if( *p == end ) + return( 0 ); +@@ -593,9 +594,9 @@ static int x509_get_crt_ext( unsigned char **p, /* * Detect supported extensions */ @@ -269,7 +268,7 @@ index 6751da0d2..149149b96 100644 { /* No parser found, skip extension */ *p = end_ext_octet; -@@ -599,6 +600,10 @@ static int x509_get_crt_ext( unsigned char **p, +@@ -603,6 +604,10 @@ static int x509_get_crt_ext( unsigned char **p, #if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) if( is_critical ) { @@ -280,7 +279,7 @@ index 6751da0d2..149149b96 100644 /* Data is marked as critical: fail */ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); -@@ -952,6 +957,7 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu +@@ -956,6 +961,7 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu prev = crt; mbedtls_x509_crt_init( crt->next ); @@ -315,10 +314,10 @@ index 000000000..7e0c56134 +OwQ6w1HweApjB46bGyILpGUi9MZhvCnoLWg+cN3/wQ== +-----END CERTIFICATE----- diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data -index 406cf5931..212a2825a 100644 +index 0fe68cb06..e39f065e2 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data -@@ -1766,6 +1766,12 @@ X509 File parse (trailing spaces, OK) +@@ -1798,6 +1798,12 @@ X509 File parse (trailing spaces, OK) depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C x509parse_crt_file:"data_files/server7_trailing_space.crt":0 @@ -332,10 +331,10 @@ index 406cf5931..212a2825a 100644 depends_on:MBEDTLS_X509_USE_C x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0 diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function -index 06f010828..75936010f 100644 +index 584ee822b..c12a0e0ef 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function -@@ -437,6 +437,21 @@ exit: +@@ -448,6 +448,21 @@ exit: } /* END_CASE */ @@ -358,5 +357,5 @@ index 06f010828..75936010f 100644 void x509parse_crt( char *crt_data, char *result_str, int result ) { -- -2.18.0 +2.22.0.windows.1 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ip.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ip.hpp index 1fda545..cd14e5c 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ip.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ip.hpp @@ -268,7 +268,7 @@ namespace openvpn { } else { - a.ver = V4; + a.ver = V6; a.u.v6 = IPv6::Addr::from_byte_string(bytestr); } return a; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv4.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv4.hpp index 03c7653..1fd55de 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv4.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv4.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include namespace openvpn { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv6.hpp index 9fedb64..d116934 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv6.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/ipv6.hpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp index 4de41c2..e8cdac5 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp @@ -53,6 +53,7 @@ namespace openvpn { } } + // bit positions between templ.prefix_len and prefix_len are randomized inline Route random_subnet(const Route& templ, const unsigned int prefix_len, RandomAPI& prng) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/apple/reachable.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/apple/reachable.hpp index be0a700..abf808a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/apple/reachable.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/apple/reachable.hpp @@ -202,6 +202,8 @@ namespace openvpn { virtual Type vtype() const = 0; virtual Status vstatus(const SCNetworkReachabilityFlags flags) const = 0; + virtual ~ReachabilityBase() {} + CF::NetworkReachability reach; }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiopolysock.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiopolysock.hpp index d7f95d5..638152d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiopolysock.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiopolysock.hpp @@ -48,6 +48,12 @@ namespace openvpn { namespace AsioPolySock { + // for shutdown() + enum ShutdownFlags { + SHUTDOWN_SEND = (1<<0), + SHUTDOWN_RECV = (1<<1), + }; + class Base : public RC { public: @@ -66,6 +72,8 @@ namespace openvpn { virtual void close() = 0; + virtual void shutdown(const unsigned int flags) {} + virtual void tcp_nodelay() {} virtual void set_cloexec() {} @@ -171,6 +179,14 @@ namespace openvpn { } #endif + virtual void shutdown(const unsigned int flags) override + { + if (flags & SHUTDOWN_SEND) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); + else if (flags & SHUTDOWN_RECV) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); + } + virtual void close() override { socket.close(); @@ -194,7 +210,8 @@ namespace openvpn { #if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) virtual std::string remote_endpoint_str() const override { - return "TCP ALT " + socket.to_string(); + const char *proto = (socket.alt_routing_enabled() ? "TCP ALT " : "TCP "); + return proto + socket.to_string(); } virtual bool alt_routing_enabled() override @@ -261,6 +278,14 @@ namespace openvpn { SockOpt::set_cloexec(fd); } + virtual void shutdown(const unsigned int flags) override + { + if (flags & SHUTDOWN_SEND) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); + else if (flags & SHUTDOWN_RECV) + socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); + } + virtual void close() override { socket.close(); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiosignal.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiosignal.hpp index 55bdb95..022c0b9 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiosignal.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/asio/asiosignal.hpp @@ -78,7 +78,6 @@ namespace openvpn { S_SIGINT | S_SIGTERM #ifndef OPENVPN_PLATFORM_WIN - | S_SIGQUIT | S_SIGHUP | S_SIGUSR1 | S_SIGUSR2 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcert.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcert.hpp index 702f601..f22021a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcert.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcert.hpp @@ -35,14 +35,16 @@ #include #include #include +#include namespace openvpn { class OpenSSLContext; class MbedTLSContext; - struct AuthCert : public RC + class AuthCert : public RC { + public: // AuthCert needs to friend SSL implementation classes friend class OpenSSLContext; friend class MbedTLSContext; @@ -52,16 +54,18 @@ namespace openvpn { class Fail { public: - // ordered by priority + // Ordered by severity. If many errors are present, the + // most severe error will be returned by get_code(). enum Type { - OK=0, // OK MUST be 0 - OTHER, + OK=0, // OK MUST be 0 + EXPIRED, // less severe... BAD_CERT_TYPE, - EXPIRED, + CERT_FAIL, + SNI_ERROR, // more severe... N }; - void add_fail(const size_t depth, const Type new_code, const char *reason) + void add_fail(const size_t depth, const Type new_code, std::string reason) { if (new_code > code) code = new_code; @@ -69,7 +73,7 @@ namespace openvpn { errors.emplace_back(); std::string& err = errors[depth]; if (err.empty()) - err = reason; + err = std::move(reason); else if (err.find(reason) == std::string::npos) { err += ", "; @@ -111,19 +115,21 @@ namespace openvpn { return ret; } - static const char *render_code(const Type code) + static std::string render_code(const Type code) { switch (code) { case OK: return "OK"; - case OTHER: + case CERT_FAIL: default: return "CERT_FAIL"; case BAD_CERT_TYPE: return "BAD_CERT_TYPE"; case EXPIRED: return "EXPIRED"; + case SNI_ERROR: + return "SNI_ERROR"; } } @@ -143,6 +149,11 @@ namespace openvpn { return sn >= 0; } + bool sni_defined() const + { + return !sni.empty(); + } + bool cn_defined() const { return !cn.empty(); @@ -161,7 +172,7 @@ namespace openvpn { bool operator==(const AuthCert& other) const { - return cn == other.cn && sn == other.sn && !std::memcmp(issuer_fp, other.issuer_fp, sizeof(issuer_fp)); + return sni == other.sni && cn == other.cn && sn == other.sn && !std::memcmp(issuer_fp, other.issuer_fp, sizeof(issuer_fp)); } bool operator!=(const AuthCert& other) const @@ -172,6 +183,10 @@ namespace openvpn { std::string to_string() const { std::ostringstream os; + if (!sni.empty()) + os << "SNI=" << sni << ' '; + if (sni_metadata) + os << "SNI_CN=" << sni_metadata->sni_client_name(*this) << ' '; os << "CN=" << cn << " SN=" << sn << " ISSUER_FP=" << issuer_fp_str(false); @@ -194,6 +209,21 @@ namespace openvpn { return cn; } + // Allow sni_metadata object, if it exists, to generate the client name. + // Otherwise fall back to normalize_cn(). + std::string sni_client_name() const + { + if (sni_metadata) + return sni_metadata->sni_client_name(*this); + else + return normalize_cn(); + } + + const std::string& get_sni() const + { + return sni; + } + const std::string& get_cn() const { return cn; @@ -214,11 +244,11 @@ namespace openvpn { return std::move(x509_track); } - void add_fail(const size_t depth, const Fail::Type new_code, const char *reason) + void add_fail(const size_t depth, const Fail::Type new_code, std::string reason) { if (!fail) fail.reset(new Fail()); - fail->add_fail(depth, new_code, reason); + fail->add_fail(depth, new_code, std::move(reason)); } bool is_fail() const @@ -231,13 +261,23 @@ namespace openvpn { return fail.get(); } + std::string fail_str() const + { + if (fail) + return fail->to_string(true); + else + return "OK"; + } + private: + std::string sni; // SNI (server name indication) std::string cn; // common name long sn; // serial number unsigned char issuer_fp[20]; // issuer cert fingerprint std::unique_ptr fail; std::unique_ptr x509_track; + SNI::Metadata::UPtr sni_metadata; }; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buflineiter.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buflineiter.hpp new file mode 100644 index 0000000..5fa6d13 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buflineiter.hpp @@ -0,0 +1,58 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + // Iterate over the lines in a buffer by returning + // a sub-buffer for each line. Zero-copy. + class BufferLineIterator + { + public: + BufferLineIterator(const ConstBuffer& buf) + : src(buf) + { + } + + // Returns a zero-length buffer at end of iteration + ConstBuffer next() + { + return src.read_alloc_buf(line_len()); + } + + private: + size_t line_len() const + { + const unsigned char *const data = src.c_data(); + size_t i = 0; + while (i < src.size()) + if (data[i++] == '\n') + break; + return i; + } + + ConstBuffer src; + }; + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/bufstatic.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/bufstatic.hpp new file mode 100644 index 0000000..eee076f --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/bufstatic.hpp @@ -0,0 +1,45 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + // constant-length Buffer for writing that cannot be extended + template + class StaticBuffer : public Buffer + { + public: + StaticBuffer() + : Buffer(data, N, false) + { + } + + StaticBuffer(const StaticBuffer&) = delete; + StaticBuffer& operator=(const StaticBuffer&) = delete; + + private: + unsigned char data[N]; + }; + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/safestr.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/safestr.hpp index 18f87c8..c170215 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/safestr.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/safestr.hpp @@ -71,12 +71,12 @@ namespace openvpn { return buf_to_string(data); } - const size_t length() const + size_t length() const { return data.size(); } - const bool empty() const + bool empty() const { return !length(); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp index 7b6b68e..8399bff 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp @@ -460,6 +460,14 @@ namespace openvpn { stop(); } break; + case Error::TUN_REGISTER_RINGS_ERROR: + { + ClientEvent::Base::Ptr ev = new ClientEvent::TunSetupFailed(client->fatal_reason()); + client_options->events().add_event(std::move(ev)); + client_options->stats().error(Error::TUN_REGISTER_RINGS_ERROR); + stop(); + } + break; case Error::TUN_IFACE_CREATE: { ClientEvent::Base::Ptr ev = new ClientEvent::TunIfaceCreate(client->fatal_reason()); @@ -473,7 +481,7 @@ namespace openvpn { ClientEvent::Base::Ptr ev = new ClientEvent::TunIfaceDisabled(client->fatal_reason()); client_options->events().add_event(std::move(ev)); client_options->stats().error(Error::TUN_IFACE_DISABLED); - stop(); + queue_restart(5000); } break; case Error::PROXY_ERROR: @@ -529,7 +537,10 @@ namespace openvpn { ClientEvent::Base::Ptr ev = new ClientEvent::InactiveTimeout(); client_options->events().add_event(std::move(ev)); client_options->stats().error(Error::INACTIVE_TIMEOUT); - graceful_stop(); + + // explicit exit notify is sent earlier by + // ClientProto::Session::inactive_callback() + stop(); } break; case Error::TRANSPORT_ERROR: @@ -548,6 +559,14 @@ namespace openvpn { queue_restart(5000); } break; + case Error::TUN_HALT: + { + ClientEvent::Base::Ptr ev = new ClientEvent::TunHalt(client->fatal_reason()); + client_options->events().add_event(std::move(ev)); + client_options->stats().error(Error::TUN_HALT); + stop(); + } + break; case Error::RELAY: { ClientEvent::Base::Ptr ev = new ClientEvent::Relay(); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp index 26d4983..6a88cae 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp @@ -55,6 +55,7 @@ namespace openvpn { PAUSE, RESUME, RELAY, + COMPRESSION_ENABLED, UNSUPPORTED_FEATURE, // start of nonfatal errors, must be marked by NONFATAL_ERROR_START below @@ -68,6 +69,7 @@ namespace openvpn { TLS_VERSION_MIN, CLIENT_HALT, CLIENT_SETUP, + TUN_HALT, CONNECTION_TIMEOUT, INACTIVE_TIMEOUT, DYNAMIC_CHALLENGE, @@ -108,6 +110,7 @@ namespace openvpn { "PAUSE", "RESUME", "RELAY", + "COMPRESSION_ENABLED", "UNSUPPORTED_FEATURE", // nonfatal errors @@ -121,6 +124,7 @@ namespace openvpn { "TLS_VERSION_MIN", "CLIENT_HALT", "CLIENT_SETUP", + "TUN_HALT", "CONNECTION_TIMEOUT", "INACTIVE_TIMEOUT", "DYNAMIC_CHALLENGE", @@ -361,6 +365,11 @@ namespace openvpn { ClientRestart(std::string reason) : ReasonBase(CLIENT_RESTART, std::move(reason)) {} }; + struct TunHalt : public ReasonBase + { + TunHalt(std::string reason) : ReasonBase(TUN_HALT, std::move(reason)) {} + }; + struct RelayError : public ReasonBase { RelayError(std::string reason) : ReasonBase(RELAY_ERROR, std::move(reason)) {} @@ -456,6 +465,14 @@ namespace openvpn { } }; + struct CompressionEnabled : public ReasonBase + { + CompressionEnabled(std::string msg) + : ReasonBase(COMPRESSION_ENABLED, std::move(msg)) + { + } + }; + class Queue : public RC { public: diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp index 955b839..bcc0cb6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp @@ -120,8 +120,11 @@ namespace openvpn { struct Config { std::string gui_version; + std::string sso_methods; std::string server_override; std::string port_override; + std::string hw_addr_override; + std::string platform_version; Protocol proto_override; IPv6Setting ipv6; int conn_timeout = 0; @@ -308,6 +311,13 @@ namespace openvpn { synchronous_dns_lookup = config.synchronous_dns_lookup; +#ifdef OPENVPN_TLS_LINK + if (opt.exists("tls-ca")) + { + tls_ca = opt.cat("tls-ca"); + } +#endif + // init transport config const std::string session_name = load_transport_config(); @@ -426,12 +436,14 @@ namespace openvpn { tunconf->stop = config.stop; tunconf->wintun = config.wintun; if (config.tun_persist) - { - tunconf->tun_persist.reset(new TunWin::TunPersist(true, false, nullptr)); - tunconf->tun_prop.remote_bypass = true; - /* remote_list is required by remote_bypass to work */ - tunconf->tun_prop.remote_list = remote_list; - } + { + tunconf->tun_persist.reset(new TunWin::TunPersist(true, false, nullptr)); +#ifndef OPENVPN_COMMAND_AGENT + /* remote_list is required by remote_bypass to work */ + tunconf->tun_prop.remote_bypass = true; + tunconf->tun_prop.remote_list = remote_list; +#endif + } #ifdef OPENVPN_COMMAND_AGENT tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt); #endif @@ -534,14 +546,27 @@ namespace openvpn { // setenv UV_ options pi->append_foreign_set_ptr(pcc.peerInfoUV()); + // UI version + if (!config.gui_version.empty()) + pi->emplace_back("IV_GUI_VER", config.gui_version); + + // Supported SSO methods + if (!config.sso_methods.empty()) + pi->emplace_back("IV_SSO", config.sso_methods); + // MAC address if (pcc.pushPeerInfo()) { std::string hwaddr = get_hwaddr(); - if (!hwaddr.empty()) + if (!config.hw_addr_override.empty()) + pi->emplace_back("IV_HWADDR", config.hw_addr_override); + else if (!hwaddr.empty()) pi->emplace_back("IV_HWADDR", hwaddr); - } + pi->emplace_back ("IV_SSL", get_ssl_library_version()); + if (!config.platform_version.empty()) + pi->emplace_back("IV_PLAT_VER", config.platform_version); + } return pi; } @@ -716,7 +741,6 @@ namespace openvpn { cp->ssl_factory = cc->new_factory(); cp->load(opt, *proto_context_options, config.default_key_direction, false); cp->set_xmit_creds(!autologin || pcc.hasEmbeddedPassword() || autologin_sessions); - cp->gui_version = config.gui_version; cp->force_aes_cbc_ciphersuites = config.force_aes_cbc_ciphersuites; // also used to disable proto V2 cp->extra_peer_info = build_peer_info(config, pcc, autologin_sessions); cp->frame = frame; @@ -825,6 +849,7 @@ namespace openvpn { #ifdef OPENVPN_TLS_LINK if (transport_protocol.is_tls()) tcpconf->use_tls = true; + tcpconf->tls_ca = tls_ca; #endif #ifdef OPENVPN_GREMLIN tcpconf->gremlin_config = gremlin_config; @@ -881,6 +906,9 @@ namespace openvpn { DCO::Ptr dco; #ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY ExternalTransport::Factory* extern_transport_factory; +#endif +#ifdef OPENVPN_TLS_LINK + std::string tls_ca; #endif }; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp index 7d27fce..818bab5 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp @@ -97,7 +97,7 @@ namespace openvpn { if (arg1 == "GENERIC_CONFIG") { error_ = true; - message_ = "SERVER_LOCKED_UNSUPPORTED: server locked profiles are currently unsupported"; + message_ = "ERR_PROFILE_SERVER_LOCKED_UNSUPPORTED: server locked profiles are currently unsupported"; return; } else if (arg1 == "ALLOW_PASSWORD_SAVE") @@ -307,7 +307,7 @@ namespace openvpn { catch (const std::exception& e) { error_ = true; - message_ = Unicode::utf8_printable(e.what(), 256); + message_ = Unicode::utf8_printable(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); } } @@ -374,7 +374,7 @@ namespace openvpn { { ParseClientConfig ret; ret.error_ = true; - ret.message_ = Unicode::utf8_printable(e.what(), 256); + ret.message_ = Unicode::utf8_printable(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); return ret; } } @@ -558,8 +558,8 @@ namespace openvpn { // JSON config is aimed to users, therefore we do not export the raw private // key, but only some basic info - SSLConfigAPI::PKType priv_key_type = sslConfig->private_key_type(); - if (priv_key_type != SSLConfigAPI::PK_NONE) + PKType::Type priv_key_type = sslConfig->private_key_type(); + if (priv_key_type != PKType::PK_NONE) { root["key"] = Json::Value(Json::objectValue); root["key"]["type"] = Json::Value(sslConfig->private_key_type_string()); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp index 3694fa8..0cf41bf 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp @@ -506,7 +506,7 @@ namespace openvpn { { const Option* o = opt.get_ptr("auth-token-user"); if (o) - username = base64->decode(o->get(1, 256)); + username = base64->decode(o->get(1, 340)); // 255 chars after base64 decode } // auth-token @@ -601,6 +601,20 @@ namespace openvpn { // send the Connected event cli_events->add_event(connected_); + + // Issue an event if compression is enabled + CompressContext::Type comp_type = Base::conf().comp_ctx.type(); + if (comp_type != CompressContext::NONE + && !CompressContext::is_any_stub(comp_type)) + { + std::ostringstream msg; + msg << (proto_context_options->is_comp_asym() + ? "Asymmetric compression enabled. Server may send compressed data." + : "Compression enabled."); + msg << " This may be a potential security issue."; + ClientEvent::Base::Ptr ev = new ClientEvent::CompressionEnabled(msg.str()); + cli_events->add_event(std::move(ev)); + } } else OPENVPN_LOG("Options continuation..."); @@ -739,6 +753,8 @@ namespace openvpn { virtual void tun_error(const Error::Type fatal_err, const std::string& err_text) { + if (fatal_err == Error::TUN_HALT) + send_explicit_exit_notify(); if (fatal_err != Error::UNDEF) { fatal_ = fatal_err; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp index f9b3dca..7114cfa 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp @@ -759,7 +759,7 @@ namespace openvpn { // return the current primary index (into list) and raise an exception // if it is undefined - const size_t primary_index() const + size_t primary_index() const { const size_t pri = index.primary(); if (pri < list.size()) @@ -890,7 +890,7 @@ namespace openvpn { } else e->server_port = default_port; - if (o.size() >= 4+adj) + if (o.size() >= (size_t)(4+adj)) e->transport_protocol = Protocol::parse(o.get(3+adj, 16), Protocol::CLIENT_SUFFIX); else e->transport_protocol = default_proto; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/clamp.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/clamp.hpp new file mode 100644 index 0000000..5ea766c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/clamp.hpp @@ -0,0 +1,39 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +// loose emulation of std::clamp for pre-C++17 + +namespace openvpn { + + template + T clamp(T value, T low, T high) + { + if (value < low) + return low; + else if (value > high) + return high; + else + return value; + } + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/daemon.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/daemon.hpp index 142cc1a..2f18626 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/daemon.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/daemon.hpp @@ -34,17 +34,52 @@ #include #include #include +#include namespace openvpn { OPENVPN_EXCEPTION(daemon_err); - inline void log_setup(const std::string& log_fn, - const SetUserGroup* user_group, - const bool log_append, - const int log_versions, - const bool stdin_to_dev_null, - const bool combine_out_err) + class LogReopen : public LogSetup + { + public: + LogReopen(const std::string& log_fn, + const bool combine_out_err) + : log_fn_(log_fn), + combine_out_err_(combine_out_err) + { + } + + virtual void reopen() const override + { + try { + // open redirection log file, but don't redirect yet + RedirectStd redir(std::string(), + log_fn_, + RedirectStd::FLAGS_APPEND, + RedirectStd::MODE_USER_GROUP, + combine_out_err_); + + // now do the redirect + redir.redirect(); + } + catch (const std::exception& e) + { + std::cerr << "LogReopen: " << e.what() << std::endl; + } + } + + private: + const std::string log_fn_; + const bool combine_out_err_; + }; + + inline LogSetup::Ptr log_setup(const std::string& log_fn, + const SetUserGroup* user_group, + const bool log_append, + const int log_versions, + const bool stdin_to_dev_null, + const bool combine_out_err) { if (!log_append && log_versions >= 1) log_rotate(log_fn, log_versions); @@ -62,6 +97,12 @@ namespace openvpn { { } redir.redirect(); + + // possibly return a LogReopen object + if (!log_versions) + return LogSetup::Ptr(new LogReopen(log_fn, combine_out_err)); + else + return LogSetup::Ptr(); } inline void daemonize() @@ -70,13 +111,14 @@ namespace openvpn { throw daemon_err("daemon() failed"); } - inline void daemonize(const std::string& log_fn, - const SetUserGroup* user_group, - const bool log_append, - const int log_versions) + inline LogSetup::Ptr daemonize(const std::string& log_fn, + const SetUserGroup* user_group, + const bool log_append, + const int log_versions) { - log_setup(log_fn, user_group, log_append, log_versions, true, true); + LogSetup::Ptr ret = log_setup(log_fn, user_group, log_append, log_versions, true, true); daemonize(); + return ret; } inline void write_pid(const std::string& fn) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/enumdir.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/enumdir.hpp index 00ef6ed..fb8cfef 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/enumdir.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/enumdir.hpp @@ -34,13 +34,13 @@ #include #include #include -#include namespace openvpn { OPENVPN_EXCEPTION(enum_dir_error); + template inline bool enum_dir(const std::string& dirname, - Function func) + F func) { unique_ptr_del dir(::opendir(dirname.c_str()), [](DIR* d) { ::closedir(d); }); if (!dir) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/extern.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/extern.hpp index 035a977..bcf7a25 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/extern.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/extern.hpp @@ -23,6 +23,10 @@ #define OPENVPN_COMMON_EXTERN_H #ifndef OPENVPN_EXTERN +// Remember that OPENVPN_EXTERN was not defined since something like +// #if OPENVPN_EXTERN == extern or OPENVPN_EXTERN == "" is not allowed +// in C/C++ preprocessor +#define OPENVPN_NO_EXTERN #define OPENVPN_EXTERN #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/file.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/file.hpp index e53eb77..44be84b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/file.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/file.hpp @@ -35,6 +35,10 @@ #include #include +#if defined(OPENVPN_PLATFORM_WIN) +#include +#endif + namespace openvpn { OPENVPN_UNTAGGED_EXCEPTION(file_exception); @@ -61,7 +65,12 @@ namespace openvpn { const std::uint64_t max_size = 0, const unsigned int buffer_flags = 0) { +#if defined(OPENVPN_PLATFORM_WIN) + Win::UTF16 filenamew(Win::utf16(filename)); + std::ifstream ifs(filenamew.get(), std::ios::binary); +#else std::ifstream ifs(filename.c_str(), std::ios::binary); +#endif if (!ifs) OPENVPN_THROW(open_file_error, "cannot open for read: " << filename); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp index 009bc35..2369451 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp @@ -55,7 +55,7 @@ namespace openvpn { // generate temporary filename unsigned char data[16]; rng.rand_fill(data); - const std::string tfn = path::join(tmpdir, '.' + path::basename(fn) + '.' + render_hex(data, sizeof(data))); + const std::string tfn = path::join(tmpdir, '.' + path::basename(fn).substr(0, 64) + '.' + render_hex(data, sizeof(data))); // write to temporary file write_binary_unix(tfn, mode, mtime_ns, buf); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileunix.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileunix.hpp index 4a0584f..a1901cb 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileunix.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileunix.hpp @@ -158,12 +158,12 @@ namespace openvpn { return bp; } - inline bool read_binary_unix_fast(const std::string& fn, - Buffer& out) + inline int read_binary_unix_fast(const std::string& fn, + Buffer& out) { ScopedFD fd(::open(fn.c_str(), O_RDONLY|O_CLOEXEC)); if (!fd.defined()) - return errno; + return errno; const ssize_t status = ::read(fd(), out.data_end(), out.remaining(0)); if (status < 0) return errno; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp index 22fa166..3bec134 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp @@ -279,6 +279,21 @@ namespace openvpn { return os.str(); } + /** + * Renders a combined hexadecimal and character dump of a buffer, + * with the typical 16 bytes split between hexadecimal and character + * separation per line. + * + * @param data Void pointer to the buffer to dump. + * @param size Size of the buffer to render. + * + * @return Returns a string containing a preformatted output of the + * hexadecimal dump. + */ + inline std::string dump_hex(void* data, size_t size) + { + return dump_hex((const unsigned char *)data, size); + } /** * Renders a combined hexadecimal and character dump of a std::string buffer, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/logsetup.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/logsetup.hpp new file mode 100644 index 0000000..bffd6d9 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/logsetup.hpp @@ -0,0 +1,36 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + class LogSetup : public RC + { + public: + typedef RCPtr Ptr; + + virtual void reopen() const = 0; + }; + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/msfind.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/msfind.hpp index b348301..eb3588d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/msfind.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/msfind.hpp @@ -29,16 +29,23 @@ namespace openvpn { namespace MSF { - template + template class Iter : public ITERATOR { public: + template Iter(const MAP_SET& ms, ITERATOR&& iter) : ITERATOR(std::move(iter)), exists_(*this != ms.end()) { } + Iter(ITERATOR&& iter) + : ITERATOR(std::move(iter)), + exists_(true) + { + } + explicit operator bool() const { return exists_; @@ -50,11 +57,34 @@ namespace openvpn { // Like ordinary map/set find, but returns an iterator // that defines an operator bool() method for testing if - // the iterator is defined, i.e. iter != map_or_set.end() + // the iterator is defined, so instead of: + // + // if (iter != map.end()) + // do_stuff(); + // + // you can say: + // + // if (iter) + // do_stuff(); + // template inline auto find(MAP_SET& ms, const KEY& k) { - return Iter(ms, ms.find(k)); + return Iter(ms, ms.find(k)); + } + + // Does key exist in map/set? + template + inline bool exists(MAP_SET& ms, const KEY& k) + { + return ms.find(k) != ms.end(); + } + + // Convert an ordinary, dereferenceable iterator to an MSF::Iter + template + inline auto iter(ITERATOR i) + { + return Iter(std::move(i)); } } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp index 8627b8f..a26942f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp @@ -196,6 +196,12 @@ namespace openvpn { return px != rhs.px; } + template + RCPtr static_pointer_cast() const noexcept + { + return RCPtr(static_cast(px)); + } + template RCPtr dynamic_pointer_cast() const noexcept { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp index a3e408d..f1088d6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp @@ -37,6 +37,7 @@ #include #include #include // for std::is_nothrow_move_constructible +#include #include #include @@ -45,10 +46,12 @@ #include #include #include +#include #include #include #include #include +#include #ifdef ASIO_HAS_LOCAL_SOCKETS #include @@ -131,6 +134,11 @@ namespace openvpn { async_stop_ = async_stop; } + void set_log_reopen(LogSetup::Ptr lr) + { + log_reopen = std::move(lr); + } + void set_thread(const unsigned int unit, std::thread* thread) { while (threadlist.size() <= unit) @@ -312,7 +320,7 @@ namespace openvpn { stats = stats_arg; } - virtual Stop* async_stop() + virtual Stop* async_stop() override { return async_stop_; } @@ -342,14 +350,11 @@ namespace openvpn { { if (!error && !halt) { - OPENVPN_LOG("ASIO SIGNAL " << signum); + OPENVPN_LOG("ASIO SIGNAL: " << signal_name(signum)); switch (signum) { case SIGINT: case SIGTERM: -#if !defined(OPENVPN_PLATFORM_WIN) - case SIGQUIT: -#endif cancel(); break; #if !defined(OPENVPN_PLATFORM_WIN) @@ -358,6 +363,11 @@ namespace openvpn { OPENVPN_LOG(stats->dump()); signal_rearm(); break; + case SIGHUP: + if (log_reopen) + log_reopen->reopen(); + signal_rearm(); + break; #endif default: signal_rearm(); @@ -385,7 +395,7 @@ namespace openvpn { exit_timer.expires_after(Time::Duration::seconds(n_sec)); exit_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { - if (error) + if (error || self->halt) return; OPENVPN_LOG("DEBUG EXIT"); self->cancel(); @@ -420,6 +430,7 @@ namespace openvpn { // logging Log::Context log_context; Log::Context::Wrapper log_wrap; // must be constructed after log_context + LogSetup::Ptr log_reopen; protected: volatile bool halt = false; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp index 8fe303c..e333596 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp @@ -115,6 +115,12 @@ namespace openvpn { return u.dataz[0]; } + template + void hash(HASH& h) const + { + h(u.dataz[0]); + } + // Use a URL-safe base64 encoding. std::string to_string() const { @@ -160,13 +166,15 @@ namespace openvpn { } // Find an element in an unordered map (keyed by Session ID) - // using weak equality. + // using weak equality. If conflict is true, only return + // element that is present by weak equality, but which is + // not equal to *this by strong equality. template - const SessionIDType* find_weak(const UNORDERED_MAP& m) const + const SessionIDType* find_weak(const UNORDERED_MAP& m, const bool conflict) const { const size_t bi = m.bucket(*this); for (auto i = m.cbegin(bi); i != m.cend(bi); ++i) - if (shortform() == i->first.shortform()) + if (shortform() == i->first.shortform() && (!conflict || *this != i->first)) return &i->first; return nullptr; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/signal_name.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/signal_name.hpp new file mode 100644 index 0000000..b69068e --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/signal_name.hpp @@ -0,0 +1,50 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include +#include + +namespace openvpn { + + inline std::string signal_name(const int signum) + { + switch (signum) + { + case SIGINT: + return "SIGINT"; + case SIGTERM: + return "SIGTERM"; + case SIGHUP: + return "SIGHUP"; + case SIGUSR1: + return "SIGUSR1"; + case SIGUSR2: + return "SIGUSR2"; + case SIGPIPE: + return "SIGPIPE"; + default: + return std::to_string(signum); + } + } + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp index 4d7b508..4099f4b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp @@ -150,6 +150,21 @@ namespace openvpn { return false; } + // Prepend leading characters (c) to str to obtain a minimum string length (min_len). + // Useful for adding leading zeros to numeric values or formatting tables. + inline std::string add_leading(const std::string& str, const size_t min_len, const char c) + { + if (min_len <= str.length()) + return str; + size_t len = min_len - str.length(); + std::string ret; + ret.reserve(min_len); + while (len--) + ret += c; + ret += str; + return ret; + } + // make sure that string ends with char c, if not append it inline std::string add_trailing_copy(const std::string& str, const char c) { @@ -235,16 +250,23 @@ namespace openvpn { return str.find_first_of('\n') != std::string::npos; } - // return the first line (without newline) of a multi-line string - inline std::string first_line(const std::string& str) + // Return string up to a delimiter (without the delimiter). + // Returns the entire string if no delimiter is found. + inline std::string to_delim(const std::string& str, const char delim) { - const size_t pos = str.find_first_of('\n'); + const size_t pos = str.find_first_of(delim); if (pos != std::string::npos) return str.substr(0, pos); else return str; } + // return the first line (without newline) of a multi-line string + inline std::string first_line(const std::string& str) + { + return to_delim(str, '\n'); + } + // Define a common interpretation of what constitutes a space character. // Return true if c is a space char. inline bool is_space(const char c) @@ -385,12 +407,16 @@ namespace openvpn { // indent a multiline string inline std::string indent(const std::string& str, const int first, const int remaining) { - std::string ret = spaces(first); + std::string ret; + int n_spaces = first; for (auto &c : str) { + if (n_spaces) + ret += spaces(n_spaces); + n_spaces = 0; ret += c; if (c == '\n') - ret += spaces(remaining); + n_spaces = remaining; } return ret; } @@ -447,7 +473,8 @@ namespace openvpn { } // Split a string on sep delimiter. The size of the - // returned string list will be at most maxsplit + 1. + // returned string vector will be at least 1 and at + // most maxsplit + 1 (unless maxsplit is passed as -1). inline std::vector split(const std::string& str, const char sep, const int maxsplit = -1) @@ -456,13 +483,16 @@ namespace openvpn { int nterms = 0; std::string term; - for (auto &c : str) + if (maxsplit >= 0) + ret.reserve(maxsplit + 1); + + for (const auto c : str) { if (c == sep && (maxsplit < 0 || nterms < maxsplit)) { ret.push_back(std::move(term)); ++nterms; - term = ""; + term.clear(); } else term += c; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/umask.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/umask.hpp index 5aecda4..c1630b9 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/umask.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/umask.hpp @@ -56,5 +56,13 @@ namespace openvpn { { } }; + + struct UMaskDaemon : public UMask + { + UMaskDaemon() + : UMask(S_IWOTH) + { + } + }; } #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/usergroup.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/usergroup.hpp index 6ba459c..df61a6b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/usergroup.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/usergroup.hpp @@ -76,6 +76,16 @@ namespace openvpn { } } + const std::string& user() const + { + return user_name; + } + + const std::string& group() const + { + return group_name; + } + void activate() const { if (gr) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp index e7dd107..99720f8 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp @@ -24,5 +24,5 @@ #pragma once #ifndef OPENVPN_VERSION -#define OPENVPN_VERSION "3.2 (qa:d87f5bbc04)" +#define OPENVPN_VERSION "3.git:master" #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/compress/compress.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/compress/compress.hpp index 8c72143..b6a82be 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/compress/compress.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/compress/compress.hpp @@ -511,6 +511,26 @@ namespace openvpn { } } + /** + * Checks if the compression type is one of the available stub modes + * + * @param t The CompressContext::Type value + * @return Returns true if the type is one of the *_STUB{,v2} types, + * otherwise false. + */ + static bool is_any_stub(const Type t) + { + switch (t) + { + case LZO_STUB: + case COMP_STUB: + case COMP_STUBv2: + return true; + default: + return false; + } + } + static void init_static() { #ifndef NO_LZO diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptoalgs.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptoalgs.hpp index 53b0020..3d8b12d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptoalgs.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptoalgs.hpp @@ -80,6 +80,7 @@ namespace openvpn { F_CIPHER=(1<<2), // alg is a cipher F_DIGEST=(1<<3), // alg is a digest F_ALLOW_DC=(1<<4), // alg may be used in OpenVPN data channel + F_NO_CIPHER_DIGEST=(1<<5), // cipher alg does not depend on any additional digest }; // size in bytes of AEAD "nonce tail" normally taken from @@ -130,9 +131,9 @@ namespace openvpn { { "DES-EDE3-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 24, 8, 8 }, { "BF-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 16, 8, 8 }, { "AES-256-CTR", F_CIPHER, 32, 16, 16 }, - { "AES-128-GCM", F_CIPHER|F_ALLOW_DC|AEAD, 16, 12, 16 }, - { "AES-192-GCM", F_CIPHER|F_ALLOW_DC|AEAD, 24, 12, 16 }, - { "AES-256-GCM", F_CIPHER|F_ALLOW_DC|AEAD, 32, 12, 16 }, + { "AES-128-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 16, 12, 16 }, + { "AES-192-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 24, 12, 16 }, + { "AES-256-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, { "MD4", F_DIGEST, 16, 0, 0 }, { "MD5", F_DIGEST|F_ALLOW_DC, 16, 0, 0 }, { "SHA1", F_DIGEST|F_ALLOW_DC, 20, 0, 0 }, @@ -240,6 +241,20 @@ namespace openvpn { return type; } + /** + * Check if a specific algorithm depends on an additional digest or not + * + * @param type CryptoAlgs::Type to check + * + * @return Returns true if the queried algorithm depends on a digest, + * otherwise false. The check is done strictly against the + * CryptoAlgs::AlgFlags F_NO_CIPHER_DIGEST flag. + */ + inline bool use_cipher_digest(const Type type) + { + const Alg& alg = get(type); + return !(alg.flags() & F_NO_CIPHER_DIGEST); + } } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptodc.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptodc.hpp index 953b1ba..ed07609 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptodc.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/cryptodc.hpp @@ -184,7 +184,19 @@ namespace openvpn { } CryptoAlgs::Type cipher() const { return cipher_; } - CryptoAlgs::Type digest() const { return digest_; } + + /** + * Retrieve the digest configured for the data channel. + * If the configured data channel cipher does not use any + * additional digest, CryptoAlgs::NONE is returned. + * + * @return Returns the cipher digest in use + */ + CryptoAlgs::Type digest() const + { + return (CryptoAlgs::use_cipher_digest(cipher_) ? digest_ : CryptoAlgs::NONE); + } + CryptoDCFactory::Ptr factory() const { return factory_; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/packet_id.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/packet_id.hpp index 2e8e157..df6a19e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/packet_id.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/packet_id.hpp @@ -83,11 +83,14 @@ namespace openvpn { static size_t size(const int form) { if (form == PacketID::LONG_FORM) - return sizeof(id_t) + sizeof(net_time_t); + return longidsize; else - return sizeof(id_t); + return shortidsize; } + constexpr static size_t shortidsize = sizeof(id_t); + constexpr static size_t longidsize = sizeof(id_t) + sizeof(net_time_t); + bool is_valid() const { return id != UNDEF; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp index f95ab00..e2c74a0 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp @@ -192,17 +192,17 @@ namespace openvpn { virtual TLSCryptInstance::Ptr new_obj_recv() = 0; - static const size_t hmac_offset; + // This is the size of the header in a TLSCrypt-wrapped packets, + // excluding the HMAC. Format: + // + // [OP] [PSID] [PID] [HMAC] [...] + // + + constexpr const static size_t hmac_offset = 1 + ProtoSessionID::SIZE + PacketID::longidsize; + }; - // initialize static member with non-constexpr. - // This is the size of the header in a TLSCrypt-wrapped packets, - // excluding the HMAC. Format: - // - // [OP] [PSID] [PID] [HMAC] [...] - // - const size_t TLSCryptContext::hmac_offset = 1 + ProtoSessionID::SIZE + - PacketID::size(PacketID::LONG_FORM); + class TLSCryptFactory : public RC { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp index 41d5bb1..00507fc 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp @@ -33,6 +33,9 @@ #include namespace openvpn { + constexpr static const char* tls_crypt_v2_server_key_name = "OpenVPN tls-crypt-v2 server key"; + constexpr static const char* tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key"; + class TLSCryptV2ServerKey { public: @@ -79,10 +82,8 @@ namespace openvpn { private: const size_t key_size; BufferAllocated key; - static const std::string tls_crypt_v2_server_key_name; }; - const std::string TLSCryptV2ServerKey::tls_crypt_v2_server_key_name = "OpenVPN tls-crypt-v2 server key"; class TLSCryptV2ClientKey { @@ -133,7 +134,8 @@ namespace openvpn { BufferAllocated in(key, BufferAllocated::GROW); in.append(wkc); - if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), tls_crypt_v2_client_key_name)) + if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), + tls_crypt_v2_client_key_name)) throw tls_crypt_v2_client_key_encode_error(); return std::string((const char *)data.c_data()); @@ -150,12 +152,8 @@ namespace openvpn { const size_t key_size; const size_t tag_size; - - static const std::string tls_crypt_v2_client_key_name; }; - const std::string TLSCryptV2ClientKey::tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key"; - // the user can extend the TLSCryptMetadata and the TLSCryptMetadataFactory // classes to implement its own metadata verification method. // diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp index bf3e300..c026c98 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp @@ -41,11 +41,9 @@ #include #include #include -#include #ifdef ENABLE_PG #include -#include #endif // client-side DCO (Data Channel Offload) module for Linux/kovpn @@ -68,6 +66,7 @@ namespace openvpn { DCO::TunConfig tun; int trunk_unit = -1; + unsigned int ping_restart_override = 0; virtual TunClientFactory::Ptr new_tun_factory(const DCO::TunConfig& conf, const OptionList& opt) override { @@ -89,6 +88,9 @@ namespace openvpn { // parse trunk-unit trunk_unit = opt.get_num("trunk-unit", 1, trunk_unit, 0, 511); + // parse ping-restart-override + ping_restart_override = opt.get_num("ping-restart-override", 1, ping_restart_override, 0, 3600); + return TunClientFactory::Ptr(this); } @@ -195,7 +197,7 @@ namespace openvpn { devconf.dc.peer_lookup = OVPN_PEER_LOOKUP_NONE; devconf.dc.cpu_id = -1; - // create kovpn tun socket + // create kovpn tun socket (implementation in kodevtun.hpp) impl.reset(new TunImpl(io_context, devconf, this, @@ -216,12 +218,6 @@ namespace openvpn { transport_start_udp(); } - // VPN IP collision detection for multi-channel trunking - static void set_vpn_ip_collision(IPCollisionDetectBase* vpn_ip_collision_arg) - { - vpn_ip_collision = vpn_ip_collision_arg; - } - virtual bool transport_send_const(const Buffer& buf) override { return send(buf); @@ -323,47 +319,55 @@ namespace openvpn { OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - // add/remove command lists - ActionList::Ptr add_cmds = new ActionList(); - remove_cmds.reset(new ActionListReversed()); - - // configure tun properties - std::vector rtvec; +#ifdef ENABLE_PG if (config->trunk_unit >= 0) { - // VPN IP collision detection, will throw on collision - if (vpn_ip_collision) - detect_vpn_ip_collision(*vpn_ip_collision, *po, config->trunk_unit, *remove_cmds); - // trunk setup - TunIPRoute::iface_config(state->iface_name, - config->trunk_unit, - *po, - nullptr, - *add_cmds, - *remove_cmds); + ovpn_peer_assign_route_id kri; + std::memset(&kri, 0, sizeof(kri)); + kri.peer_id = peer_id; + kri.route_id = config->trunk_unit; + kri.allow_incoming = true; + kri.snat_flags = OVPN_SNAT_DEFAULT_ON | OVPN_SNAT_REQUIRED; - // Note that in trunking mode, kovpn must be - // configured for source routing. - add_vpn_ips_as_source_routes(*po, rtvec, IP::Addr::V4); - add_vpn_ips_as_source_routes(*po, rtvec, IP::Addr::V6); + // SNAT via VPN IPv4 addresses received from server + { + const TunBuilderCapture::RouteAddress *ra = po->vpn_ip(IP::Addr::V4); + if (ra) + kri.snat.a4 = IP::Addr(ra->address, "server-assigned-vpn4-addr", IP::Addr::V4).to_ipv4().to_in_addr(); + } + + // SNAT via VPN IPv6 addresses received from server + { + const TunBuilderCapture::RouteAddress *ra = po->vpn_ip(IP::Addr::V6); + if (ra) + kri.snat.a6 = IP::Addr(ra->address, "server-assigned-vpn6-addr", IP::Addr::V4).to_ipv6().to_in6_addr(); + } + + // kovpn route ID setup + KoTun::API::peer_assign_route_id(impl->native_handle(), &kri); } else +#endif // ENABLE_PG { + // add/remove command lists + ActionList::Ptr add_cmds = new ActionList(); + remove_cmds.reset(new ActionListReversed()); + + // configure tun properties + std::vector rtvec; + // non-trunk setup - TunIPRoute::TunMethods::tun_config(state->iface_name, - *po, - &rtvec, - *add_cmds, - *remove_cmds); + TUN_LINUX::tun_config(state->iface_name, *po, &rtvec, *add_cmds, + *remove_cmds); + + // Add routes to DCO implementation + impl->peer_add_routes(peer_id, rtvec); + + // execute commands to bring up interface + add_cmds->execute_log(); } - // Add routes to DCO implementation - impl->peer_add_routes(peer_id, rtvec); - - // execute commands to bring up interface - add_cmds->execute_log(); - // Add a hook so ProtoContext will call back to // rekey() on rekey ops. dc_settings.set_factory(CryptoDCFactory::Ptr(new KoRekey::Factory(dc_settings.factory(), this, config->transport.frame))); @@ -371,12 +375,6 @@ namespace openvpn { // signal that we are connected tun_parent->tun_connected(); } - catch (const IPCollisionDetectBase::ip_collision& e) - { - // on VPN IP address collision, just reconnect to get a new address - stop_(); - tun_parent->tun_error(Error::TUN_ERROR, e.what()); - } catch (const std::exception& e) { stop_(); @@ -453,6 +451,10 @@ namespace openvpn { transport_parent->disable_keepalive(ka.keepalive_ping, ka.keepalive_timeout); + // Allow overide of keepalive timeout + if (config->ping_restart_override) + ka.keepalive_timeout = config->ping_restart_override; + // Modify the peer impl->peer_set_keepalive(&ka); } @@ -659,35 +661,6 @@ namespace openvpn { return *static_cast(proto.get()); } - static void add_vpn_ips_as_source_routes(const TunBuilderCapture& pull, - std::vector& rtvec, - const IP::Addr::Version ver) - { - const TunBuilderCapture::RouteAddress *ra = pull.vpn_ip(ver); - if (ra) - rtvec.push_back(IP::route_from_string_prefix(ra->address, - IP::Addr::version_size(ver), - "DCOTransport::Client::add_vpn_ips_as_source_routes", - ver)); - } - - // Throw an exception of type IPCollisionDetectBase::ip_collision - // if VPN IP is already in use by another client thread. - // This is intended to force a reconnect and obtain a - // new non-colliding address. - static void detect_vpn_ip_collision(IPCollisionDetectBase& ipcoll, - const TunBuilderCapture& pull, - unsigned int unit, - ActionList& remove) - { - const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4(); - const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6(); - if (local4) - ipcoll.add(local4->address, unit, remove); - if (local6) - ipcoll.add(local6->address, unit, remove); - } - // override for SessionStats::DCOTransportSource virtual SessionStats::DCOTransportSource::Data dco_transport_stats_delta() override { @@ -727,8 +700,6 @@ namespace openvpn { SessionStats::DCOTransportSource::Data last_stats; __u64 cc_rx_bytes = 0; - - static IPCollisionDetectBase* vpn_ip_collision; }; inline DCO::Ptr new_controller() @@ -750,8 +721,6 @@ namespace openvpn { cli->tun_parent = &parent; return TunClient::Ptr(cli); } - - IPCollisionDetectBase* Client::vpn_ip_collision; // GLOBAL } }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp index 9ebd9c1..59cc61e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp @@ -51,6 +51,7 @@ namespace openvpn { TUN_IFACE_CREATE, // error creating tun/tap interface TUN_IFACE_DISABLED, // tun/tap interface is disabled TUN_ERROR, // general tun error + TUN_REGISTER_RINGS_ERROR, // error registering ring buffers with wintun TAP_NOT_SUPPORTED, // dev tap is present in profile but not supported REROUTE_GW_NO_DNS, // redirect-gateway specified without alt DNS servers TRANSPORT_ERROR, // general transport error @@ -76,6 +77,7 @@ namespace openvpn { AUTH_FAILED, // general authentication failure CLIENT_HALT, // HALT message from server received CLIENT_RESTART, // RESTART message from server received + TUN_HALT, // halt command from tun interface RELAY, // RELAY message from server received RELAY_ERROR, // RELAY error N_PAUSE, // Number of transitions to Pause state @@ -127,6 +129,7 @@ namespace openvpn { "TUN_IFACE_CREATE", "TUN_IFACE_DISABLED", "TUN_ERROR", + "TUN_REGISTER_RINGS_ERROR", "TAP_NOT_SUPPORTED", "REROUTE_GW_NO_DNS", "TRANSPORT_ERROR", @@ -152,6 +155,7 @@ namespace openvpn { "AUTH_FAILED", "CLIENT_HALT", "CLIENT_RESTART", + "TUN_HALT", "RELAY", "RELAY_ERROR", "N_PAUSE", diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame.hpp index 74d5d97..64b1909 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame.hpp @@ -46,7 +46,6 @@ namespace openvpn { READ_LINK_UDP, READ_LINK_TCP, READ_TUN, - READ_WINTUN, READ_BIO_MEMQ_DGRAM, READ_BIO_MEMQ_STREAM, READ_SSL_CLEARTEXT, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame_init.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame_init.hpp index adc75ea..c34cd3a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame_init.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/frame/frame_init.hpp @@ -52,12 +52,6 @@ namespace openvpn { (*frame)[Frame::WRITE_SSL_CLEARTEXT] = Frame::Context(headroom, payload, tailroom, 0, align_block, BufferAllocated::GROW); frame->standardize_capacity(~0); - // Wintun could return 256 packets no larger than tun mtu, - // each packet is prepended with 4 bytes size and 12 bytes - // start padding and appended by up to 15 bytes end padding - const size_t tun_mtu_wintun = tun_mtu > 0 ? tun_mtu : 1500; - (*frame)[Frame::READ_WINTUN] = Frame::Context(0, (tun_mtu_wintun + 4 + 12 + 15) * 256, 0, 0, align_block, 0); - if (verbose) OPENVPN_LOG("Frame=" << headroom << '/' << payload << '/' << tailroom << " mssfix-ctrl=" << (*frame)[Frame::READ_BIO_MEMQ_STREAM].payload()); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp index 2813004..647849b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp @@ -36,6 +36,7 @@ namespace openvpn { enum { ECHO_REQUEST = 128, ECHO_REPLY = 129, + DEST_UNREACH = 1, PACKET_TOO_BIG = 2 }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp index 3f2158f..5b37dc9 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp @@ -63,23 +63,23 @@ namespace openvpn { return ctx != nullptr; } - SSLConfigAPI::PKType key_type() const + PKType::Type key_type() const { switch (mbedtls_pk_get_type(ctx)) { case MBEDTLS_PK_RSA: case MBEDTLS_PK_RSA_ALT: case MBEDTLS_PK_RSASSA_PSS: - return SSLConfigAPI::PK_RSA; + return PKType::PK_RSA; case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: - return SSLConfigAPI::PK_EC; + return PKType::PK_EC; case MBEDTLS_PK_ECDSA: - return SSLConfigAPI::PK_ECDSA; + return PKType::PK_ECDSA; case MBEDTLS_PK_NONE: - return SSLConfigAPI::PK_NONE; + return PKType::PK_NONE; default: - return SSLConfigAPI::PK_UNKNOWN; + return PKType::PK_UNKNOWN; } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp index 051df51..ecb71c6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp @@ -248,6 +248,18 @@ namespace openvpn { throw MbedTLSException("set_client_session_tickets not implemented"); } + virtual void set_sni_handler(SNI::HandlerBase* sni_handler) + { + // fixme -- this method should be implemented on the server-side for SNI + throw MbedTLSException("set_sni_handler not implemented"); + } + + virtual void set_sni_name(const std::string& sni_name_arg) + { + // fixme -- this method should be implemented on the client-side for SNI + throw MbedTLSException("set_sni_name not implemented"); + } + virtual void set_private_key_password(const std::string& pwd) { priv_key_pwd = pwd; @@ -339,10 +351,10 @@ namespace openvpn { return dh->extract(); } - virtual PKType private_key_type() const + virtual PKType::Type private_key_type() const { if (!priv_key) - return PK_NONE; + return PKType::PK_NONE; return priv_key->key_type(); } @@ -467,6 +479,13 @@ namespace openvpn { allow_name_constraints = lflags & LF_ALLOW_NAME_CONSTRAINTS; + // sni + { + const std::string name = opt.get_optional("sni", 1, 256); + if (!name.empty()) + set_sni_name(name); + } + // ca { std::string ca_txt = opt.cat("ca"); @@ -543,6 +562,13 @@ namespace openvpn { } } +#ifdef HAVE_JSON + virtual SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const + { + throw MbedTLSException("json_override not implemented"); + } +#endif + bool name_constraints_allowed() const { return allow_name_constraints; @@ -709,7 +735,7 @@ namespace openvpn { return false; // fixme -- not implemented } - virtual const AuthCert::Ptr& auth_cert() override + virtual const AuthCert::Ptr& auth_cert() const override { return authcert; } @@ -791,11 +817,23 @@ namespace openvpn { #endif } - // peer must present a valid certificate unless SSLConst::NO_VERIFY_PEER is set - mbedtls_ssl_conf_authmode(sslconf, - (c.flags & SSLConst::NO_VERIFY_PEER) - ? MBEDTLS_SSL_VERIFY_NONE - : MBEDTLS_SSL_VERIFY_REQUIRED); + + { + // peer must present a valid certificate unless SSLConst::NO_VERIFY_PEER. + // Presenting a valid certificate can be made optional by specifying + // SSL:Const::PEER_CERT_OPTIONAL + + int authmode; + + if (c.flags & SSLConst::NO_VERIFY_PEER) + authmode = MBEDTLS_SSL_VERIFY_NONE; + else if (c.flags & SSLConst::PEER_CERT_OPTIONAL) + throw MbedTLSException("Optional peer verification not supported"); + else + authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + + mbedtls_ssl_conf_authmode(sslconf, authmode); + } // set verify callback mbedtls_ssl_conf_verify(sslconf, c.mode.is_server() ? verify_callback_server : verify_callback_client, this); @@ -825,7 +863,7 @@ namespace openvpn { // In pre-mbedtls-2.x the hostname for the CA chain was set in ssl_set_ca_chain(). // From mbedtls-2.x, the hostname must be set via mbedtls_ssl_set_hostname() // https://tls.mbed.org/kb/how-to/upgrade-2.0 - if (hostname && ((c.flags & SSLConst::ENABLE_SNI) || c.ca_chain)) + if (hostname && ((c.flags & SSLConst::ENABLE_CLIENT_SNI) || c.ca_chain)) { if (mbedtls_ssl_set_hostname(ssl, hostname)) throw MbedTLSException("mbedtls_ssl_set_hostname failed"); @@ -1423,6 +1461,16 @@ namespace openvpn { } }; + inline const std::string get_ssl_library_version() + { + unsigned int ver = mbedtls_version_get_number(); + std::string version = "mbed TLS " + + std::to_string((ver>>24)&0xff) + + "." + std::to_string((ver>>16)&0xff) + + "." + std::to_string((ver>>8)&0xff); + + return version; + } } // namespace openvpn #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp index e0524e6..f663fff 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp @@ -58,7 +58,7 @@ namespace openvpn { { std::string header = "-----BEGIN " + key_name + "-----"; std::string footer = "-----END " + key_name + "-----"; - mbedtls_pem_context ctx = { 0 }; + mbedtls_pem_context ctx = { }; size_t out_len = 0; int ret = mbedtls_pem_read_buffer(&ctx, header.c_str(), footer.c_str(), diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/compat.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/compat.hpp index bf2511a..7d8d995 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/compat.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/compat.hpp @@ -97,7 +97,7 @@ inline EVP_MD_CTX *EVP_MD_CTX_new() return new EVP_MD_CTX(); } -void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { delete ctx; } @@ -211,10 +211,10 @@ inline int RSA_meth_set_priv_enc(RSA_METHOD *meth, return 1; } -int RSA_meth_set_priv_dec(RSA_METHOD *meth, - int (*priv_dec)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, - int padding)) +inline int RSA_meth_set_priv_dec(RSA_METHOD *meth, + int (*priv_dec)(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, + int padding)) { meth->rsa_priv_dec = priv_dec; return 1; @@ -307,6 +307,19 @@ inline void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, con /* Renamed in OpenSSL 1.1 */ #define X509_get0_pubkey X509_get_pubkey #define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT + +/* + * EVP_CIPHER_CTX_init and EVP_CIPHER_CTX_cleanup are both replaced by + * EVP_CIPHER_CTX_reset in OpenSSL 1.1 but replacing them both with + * reset is wrong for older version. The man page mention cleanup + * being officially removed and init to be an alias for reset. + * + * So we only use reset as alias for init in older versions. + * + * EVP_CIPHER_CTX_free already implicitly calls EVP_CIPHER_CTX_cleanup in + * 1.0.2, so we can avoid using the old API. + */ +#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_init #endif #if OPENSSL_VERSION_NUMBER < 0x10101000L @@ -333,4 +346,4 @@ inline const BIGNUM *DSA_get0_p(const DSA *d) DSA_get0_pqg(d, &p, nullptr, nullptr); return p; } -#endif \ No newline at end of file +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/cipher.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/cipher.hpp index 0b60952..c1b6f29 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/cipher.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/cipher.hpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace openvpn { namespace OpenSSLCrypto { @@ -75,7 +76,7 @@ namespace openvpn { throw openssl_cipher_mode_error(); erase(); ctx = EVP_CIPHER_CTX_new (); - EVP_CIPHER_CTX_init (ctx); + EVP_CIPHER_CTX_reset (ctx); if (!EVP_CipherInit_ex (ctx, cipher_type(alg), nullptr, key, nullptr, mode)) { openssl_clear_error_stack(); @@ -177,7 +178,6 @@ namespace openvpn { { if (initialized) { - EVP_CIPHER_CTX_cleanup(ctx); EVP_CIPHER_CTX_free (ctx); initialized = false; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/ciphergcm.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/ciphergcm.hpp index cabb136..4b5c923 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/ciphergcm.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/crypto/ciphergcm.hpp @@ -78,7 +78,7 @@ namespace openvpn { if (ckeysz > keysize) throw openssl_gcm_error("insufficient key material"); ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_init(ctx); + EVP_CIPHER_CTX_reset(ctx); switch (mode) { case ENCRYPT: @@ -223,15 +223,17 @@ namespace openvpn { { if (initialized) { - EVP_CIPHER_CTX_cleanup(ctx); + EVP_CIPHER_CTX_free(ctx); initialized = false; } } void check_initialized() const { +#ifdef OPENVPN_ENABLE_ASSERT if (unlikely(!initialized)) throw openssl_gcm_error("uninitialized"); +#endif } bool initialized; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/crl.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/crl.hpp index c857e9f..4674a9e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/crl.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/crl.hpp @@ -21,8 +21,7 @@ // Wrap an OpenSSL X509_CRL object -#ifndef OPENVPN_OPENSSL_PKI_CRL_H -#define OPENVPN_OPENSSL_PKI_CRL_H +#pragma once #include #include @@ -32,16 +31,18 @@ #include #include -#include #include namespace openvpn { namespace OpenSSLPKI { - class CRL : public RC + class CRL { public: - CRL() : crl_(nullptr) {} + CRL() + : crl_(nullptr) + { + } explicit CRL(const std::string& crl_txt) : crl_(nullptr) @@ -50,27 +51,48 @@ namespace openvpn { } CRL(const CRL& other) - : crl_(nullptr) + : crl_(dup(other.crl_)) { - assign(other.crl_); } - void operator=(const CRL& other) + CRL(CRL&& other) noexcept + : crl_(other.crl_) { - assign(other.crl_); + other.crl_ = nullptr; + } + + CRL& operator=(const CRL& other) + { + if (this != &other) + { + erase(); + crl_ = dup(other.crl_); + } + return *this; + } + + CRL& operator=(CRL&& other) noexcept + { + if (this != &other) + { + erase(); + crl_ = other.crl_; + other.crl_ = nullptr; + } + return *this; } bool defined() const { return crl_ != nullptr; } - X509_CRL* obj() const { return crl_; } + ::X509_CRL* obj() const { return crl_; } void parse_pem(const std::string& crl_txt) { - BIO *bio = BIO_new_mem_buf(const_cast(crl_txt.c_str()), crl_txt.length()); + BIO *bio = ::BIO_new_mem_buf(const_cast(crl_txt.c_str()), crl_txt.length()); if (!bio) throw OpenSSLException(); - X509_CRL *crl = PEM_read_bio_X509_CRL(bio, nullptr, nullptr, nullptr); - BIO_free(bio); + ::X509_CRL *crl = ::PEM_read_bio_X509_CRL(bio, nullptr, nullptr, nullptr); + ::BIO_free(bio); if (!crl) throw OpenSSLException("CRL::parse_pem"); @@ -82,19 +104,19 @@ namespace openvpn { { if (crl_) { - BIO *bio = BIO_new(BIO_s_mem()); - const int ret = PEM_write_bio_X509_CRL(bio, crl_); + BIO *bio = ::BIO_new(BIO_s_mem()); + const int ret = ::PEM_write_bio_X509_CRL(bio, crl_); if (ret == 0) { - BIO_free(bio); + ::BIO_free(bio); throw OpenSSLException("CRL::render_pem"); } { char *temp; - const int buf_len = BIO_get_mem_data(bio, &temp); + const int buf_len = ::BIO_get_mem_data(bio, &temp); std::string ret = std::string(temp, buf_len); - BIO_free(bio); + ::BIO_free(bio); return ret; } } @@ -102,59 +124,46 @@ namespace openvpn { return ""; } - void erase() - { - if (crl_) - { - X509_CRL_free(crl_); - crl_ = nullptr; - } - } - ~CRL() { erase(); } private: + void erase() + { + if (crl_) + ::X509_CRL_free(crl_); + } + static X509_CRL *dup(const X509_CRL *crl) { if (crl) - { - return X509_CRL_dup(const_cast(crl)); - } + return ::X509_CRL_dup(const_cast(crl)); else return nullptr; } - void assign(const X509_CRL *crl) - { - erase(); - crl_ = dup(crl); - } - - X509_CRL *crl_; + ::X509_CRL *crl_; }; - typedef RCPtr CRLPtr; - - class CRLList : public std::vector + class CRLList : public std::vector { public: - typedef CRL Item; - typedef CRLPtr ItemPtr; + typedef X509 CRL; - bool defined() const { return !empty(); } + bool defined() const + { + return !empty(); + } std::string render_pem() const { std::string ret; - for (const_iterator i = begin(); i != end(); ++i) - ret += (*i)->render_pem(); + for (const auto &e : *this) + ret += e.render_pem(); return ret; } }; } -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_PKI_CRL_H +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/dh.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/dh.hpp index baac178..d5a86f7 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/dh.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/dh.hpp @@ -21,8 +21,7 @@ // Wrap an OpenSSL DH object -#ifndef OPENVPN_OPENSSL_PKI_DH_H -#define OPENVPN_OPENSSL_PKI_DH_H +#pragma once #include @@ -57,7 +56,10 @@ namespace openvpn { class DH { public: - DH() : dh_(nullptr) {} + DH() + : dh_(nullptr) + { + } explicit DH(const std::string& dh_txt) : dh_(nullptr) @@ -66,14 +68,34 @@ namespace openvpn { } DH(const DH& other) - : dh_(nullptr) { - assign(other.dh_); + dup(other.dh_); + } + + DH(DH&& other) noexcept + : dh_(other.dh_) + { + other.dh_ = nullptr; } void operator=(const DH& other) { - assign(other.dh_); + if (this != &other) + { + erase(); + dup(other.dh_); + } + } + + DH& operator=(DH&& other) noexcept + { + if (this != &other) + { + erase(); + dh_ = other.dh_; + other.dh_ = nullptr; + } + return *this; } bool defined() const { return dh_ != nullptr; } @@ -81,12 +103,12 @@ namespace openvpn { void parse_pem(const std::string& dh_txt) { - BIO *bio = BIO_new_mem_buf(const_cast(dh_txt.c_str()), dh_txt.length()); + BIO *bio = ::BIO_new_mem_buf(const_cast(dh_txt.c_str()), dh_txt.length()); if (!bio) throw OpenSSLException(); - ::DH *dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); - BIO_free(bio); + ::DH *dh = ::PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); + ::BIO_free(bio); if (!dh) throw OpenSSLException("DH::parse_pem"); @@ -98,19 +120,19 @@ namespace openvpn { { if (dh_) { - BIO *bio = BIO_new(BIO_s_mem()); - const int ret = PEM_write_bio_DHparams(bio, dh_); + BIO *bio = ::BIO_new(BIO_s_mem()); + const int ret = ::PEM_write_bio_DHparams(bio, dh_); if (ret == 0) { - BIO_free(bio); + ::BIO_free(bio); throw OpenSSLException("DH::render_pem"); } { char *temp; - const int buf_len = BIO_get_mem_data(bio, &temp); + const int buf_len = ::BIO_get_mem_data(bio, &temp); std::string ret = std::string(temp, buf_len); - BIO_free(bio); + ::BIO_free(bio); return ret; } } @@ -118,31 +140,24 @@ namespace openvpn { return ""; } - void erase() - { - if (dh_) - { - DH_free(dh_); - dh_ = nullptr; - } - } - ~DH() { erase(); } private: - void assign(const ::DH *dh) + void erase() + { + if (dh_) + ::DH_free(dh_); + } + + void dup(const ::DH *dh) { - erase(); dh_ = DH_private::dup(dh); } ::DH *dh_; }; } -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_PKI_DH_H - +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp index 2f1324a..07e82db 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp @@ -21,10 +21,10 @@ // Wrap an OpenSSL EVP_PKEY object -#ifndef OPENVPN_OPENSSL_PKI_PKEY_H -#define OPENVPN_OPENSSL_PKI_PKEY_H +#pragma once #include +#include #include #include @@ -32,6 +32,7 @@ #include #include #include +#include namespace openvpn { namespace OpenSSLPKI { @@ -39,7 +40,10 @@ namespace openvpn { class PKey { public: - PKey() : pkey_(nullptr) {} + PKey() + : pkey_(nullptr) + { + } PKey(const std::string& pkey_txt, const std::string& title) : pkey_(nullptr) @@ -48,45 +52,69 @@ namespace openvpn { } PKey(const PKey& other) - : pkey_(nullptr) + : pkey_(dup(other.pkey_)), + priv_key_pwd(other.priv_key_pwd) { - assign(other.pkey_); } - void operator=(const PKey& other) + PKey(PKey&& other) noexcept + : pkey_(other.pkey_), + priv_key_pwd(std::move(other.priv_key_pwd)) { - assign(other.pkey_); - priv_key_pwd = other.priv_key_pwd; + other.pkey_ = nullptr; + } + + PKey& operator=(const PKey& other) + { + if (this != &other) + { + erase(); + pkey_ = dup(other.pkey_); + priv_key_pwd = other.priv_key_pwd; + } + return *this; + } + + PKey& operator=(PKey&& other) noexcept + { + if (this != &other) + { + erase(); + pkey_ = other.pkey_; + other.pkey_ = nullptr; + priv_key_pwd = std::move(other.priv_key_pwd); + } + return *this; } bool defined() const { return pkey_ != nullptr; } - EVP_PKEY* obj() const { return pkey_; } + ::EVP_PKEY* obj() const { return pkey_; } - SSLConfigAPI::PKType key_type() const + PKType::Type key_type() const { - switch (EVP_PKEY_id(pkey_)) + switch (::EVP_PKEY_id(pkey_)) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - return SSLConfigAPI::PK_RSA; + return PKType::PK_RSA; case EVP_PKEY_EC: - return SSLConfigAPI::PK_EC; + return PKType::PK_EC; case EVP_PKEY_DSA: case EVP_PKEY_DSA1: case EVP_PKEY_DSA2: case EVP_PKEY_DSA3: case EVP_PKEY_DSA4: - return SSLConfigAPI::PK_DSA; + return PKType::PK_DSA; case EVP_PKEY_NONE: - return SSLConfigAPI::PK_NONE; + return PKType::PK_NONE; default: - return SSLConfigAPI::PK_UNKNOWN; + return PKType::PK_UNKNOWN; } } size_t key_length() const { - int ret = i2d_PrivateKey(pkey_, NULL); + int ret = ::i2d_PrivateKey(pkey_, NULL); if (ret < 0) return 0; @@ -101,12 +129,12 @@ namespace openvpn { void parse_pem(const std::string& pkey_txt, const std::string& title) { - BIO *bio = BIO_new_mem_buf(const_cast(pkey_txt.c_str()), pkey_txt.length()); + BIO *bio = ::BIO_new_mem_buf(const_cast(pkey_txt.c_str()), pkey_txt.length()); if (!bio) throw OpenSSLException(); - EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, nullptr, pem_password_callback, this); - BIO_free(bio); + ::EVP_PKEY *pkey = ::PEM_read_bio_PrivateKey(bio, nullptr, pem_password_callback, this); + ::BIO_free(bio); if (!pkey) throw OpenSSLException(std::string("PKey::parse_pem: error in ") + title + std::string(":")); @@ -118,19 +146,19 @@ namespace openvpn { { if (pkey_) { - BIO *bio = BIO_new(BIO_s_mem()); - const int ret = PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr); + BIO *bio = ::BIO_new(BIO_s_mem()); + const int ret = ::PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr); if (ret == 0) { - BIO_free(bio); + ::BIO_free(bio); throw OpenSSLException("PKey::render_pem"); } { char *temp; - const int buf_len = BIO_get_mem_data(bio, &temp); + const int buf_len = ::BIO_get_mem_data(bio, &temp); std::string ret = std::string(temp, buf_len); - BIO_free(bio); + ::BIO_free(bio); return ret; } } @@ -138,15 +166,6 @@ namespace openvpn { return ""; } - void erase() - { - if (pkey_) - { - EVP_PKEY_free(pkey_); - pkey_ = nullptr; - } - } - ~PKey() { erase(); @@ -165,33 +184,31 @@ namespace openvpn { return 0; } - static EVP_PKEY *dup(const EVP_PKEY *pkey) + void erase() + { + if (pkey_) + ::EVP_PKEY_free(pkey_); + } + + static ::EVP_PKEY *dup(const ::EVP_PKEY *pkey) { // No OpenSSL EVP_PKEY_dup method so we roll our own if (pkey) { - EVP_PKEY* pDupKey = EVP_PKEY_new(); - RSA* pRSA = EVP_PKEY_get1_RSA(const_cast(pkey)); - RSA* pRSADupKey = RSAPrivateKey_dup(pRSA); - RSA_free(pRSA); - EVP_PKEY_set1_RSA(pDupKey, pRSADupKey); - RSA_free(pRSADupKey); + ::EVP_PKEY* pDupKey = ::EVP_PKEY_new(); + ::RSA* pRSA = ::EVP_PKEY_get1_RSA(const_cast<::EVP_PKEY *>(pkey)); + ::RSA* pRSADupKey = ::RSAPrivateKey_dup(pRSA); + ::RSA_free(pRSA); + ::EVP_PKEY_set1_RSA(pDupKey, pRSADupKey); + ::RSA_free(pRSADupKey); return pDupKey; } else return nullptr; } - void assign(const EVP_PKEY *pkey) - { - erase(); - pkey_ = dup(pkey); - } - + ::EVP_PKEY *pkey_; std::string priv_key_pwd; - EVP_PKEY *pkey_; }; } -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_PKI_PKEY_H +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509.hpp index f3a6daf..dfa6401 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509.hpp @@ -21,8 +21,7 @@ // Wrap an OpenSSL X509 object -#ifndef OPENVPN_OPENSSL_PKI_X509_H -#define OPENVPN_OPENSSL_PKI_X509_H +#pragma once #include #include @@ -32,89 +31,77 @@ #include #include -#include #include namespace openvpn { namespace OpenSSLPKI { - class X509; - - class X509Base + class X509 { public: - X509Base() : x509_(nullptr) {} - explicit X509Base(::X509 *x509) : x509_(x509) {} + X509() + : x509_(nullptr) + { + } + + X509(const std::string& cert_txt, const std::string& title) + : x509_(nullptr) + { + parse_pem(cert_txt, title); + } + + explicit X509(::X509 *x509, const bool create=true) + { + if (create) + x509_ = x509; + else + x509_ = dup(x509); + } + + X509(const X509& other) + : x509_(dup(other.x509_)) + { + } + + X509(X509&& other) noexcept + : x509_(other.x509_) + { + other.x509_ = nullptr; + } + + X509& operator=(const X509& other) + { + if (this != &other) + { + erase(); + x509_ = dup(other.x509_); + } + return *this; + } + + X509& operator=(X509&& other) noexcept + { + if (this != &other) + { + erase(); + x509_ = other.x509_; + other.x509_ = nullptr; + } + return *this; + } bool defined() const { return x509_ != nullptr; } ::X509* obj() const { return x509_; } ::X509* obj_dup() const { return dup(x509_); } - std::string render_pem() const - { - if (x509_) - { - BIO *bio = BIO_new(BIO_s_mem()); - const int ret = PEM_write_bio_X509(bio, x509_); - if (ret == 0) - { - BIO_free(bio); - throw OpenSSLException("X509::render_pem"); - } - - { - char *temp; - const int buf_len = BIO_get_mem_data(bio, &temp); - std::string ret = std::string(temp, buf_len); - BIO_free(bio); - return ret; - } - } - else - return ""; - } - - private: - static ::X509 *dup(const ::X509 *x509) - { - if (x509) - return X509_dup(const_cast< ::X509 * >(x509)); - else - return nullptr; - } - - friend class X509; - ::X509 *x509_; - }; - - class X509 : public X509Base, public RC - { - public: - X509() {} - - X509(const std::string& cert_txt, const std::string& title) - { - parse_pem(cert_txt, title); - } - - X509(const X509& other) - { - assign(other.x509_); - } - - void operator=(const X509& other) - { - assign(other.x509_); - } - void parse_pem(const std::string& cert_txt, const std::string& title) { - BIO *bio = BIO_new_mem_buf(const_cast(cert_txt.c_str()), cert_txt.length()); + BIO *bio = ::BIO_new_mem_buf(const_cast(cert_txt.c_str()), cert_txt.length()); if (!bio) throw OpenSSLException(); - ::X509 *cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); - BIO_free(bio); + ::X509 *cert = ::PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); + ::BIO_free(bio); if (!cert) throw OpenSSLException(std::string("X509::parse_pem: error in ") + title + std::string(":")); @@ -122,13 +109,28 @@ namespace openvpn { x509_ = cert; } - void erase() + std::string render_pem() const { if (x509_) { - X509_free(x509_); - x509_ = nullptr; + BIO *bio = ::BIO_new(BIO_s_mem()); + const int ret = ::PEM_write_bio_X509(bio, x509_); + if (ret == 0) + { + ::BIO_free(bio); + throw OpenSSLException("X509::render_pem"); + } + + { + char *temp; + const int buf_len = ::BIO_get_mem_data(bio, &temp); + std::string ret = std::string(temp, buf_len); + ::BIO_free(bio); + return ret; + } } + else + return ""; } ~X509() @@ -137,32 +139,40 @@ namespace openvpn { } private: - void assign(const ::X509 *x509) + static ::X509 *dup(const ::X509 *x509) { - erase(); - x509_ = dup(x509); + if (x509) + return ::X509_dup(const_cast< ::X509 * >(x509)); + else + return nullptr; } + + void erase() + { + if (x509_) + ::X509_free(x509_); + } + + ::X509 *x509_; }; - typedef RCPtr X509Ptr; - - class X509List : public std::vector + class X509List : public std::vector { public: typedef X509 Item; - typedef X509Ptr ItemPtr; - bool defined() const { return !empty(); } + bool defined() const + { + return !empty(); + } std::string render_pem() const { std::string ret; - for (const_iterator i = begin(); i != end(); ++i) - ret += (*i)->render_pem(); + for (const auto &e : *this) + ret += e.render_pem(); return ret; } }; } -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_PKI_X509_H +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509store.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509store.hpp index fb475cd..2aee345 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509store.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/x509store.hpp @@ -21,12 +21,10 @@ // Wrap an OpenSSL X509Store object -#ifndef OPENVPN_OPENSSL_PKI_X509STORE_H -#define OPENVPN_OPENSSL_PKI_X509STORE_H +#pragma once #include #include -#include #include #include #include @@ -35,16 +33,17 @@ namespace openvpn { namespace OpenSSLPKI { - class X509Store : public RC + class X509Store { public: - OPENVPN_SIMPLE_EXCEPTION(x509_store_init_error); - OPENVPN_SIMPLE_EXCEPTION(x509_store_add_cert_error); - OPENVPN_SIMPLE_EXCEPTION(x509_store_add_crl_error); + OPENVPN_EXCEPTION(x509_store_error); typedef CertCRLListTemplate CertCRLList; - X509Store() : x509_store_(nullptr) {} + X509Store() + : x509_store_(nullptr) + { + } explicit X509Store(const CertCRLList& cc) { @@ -52,10 +51,10 @@ namespace openvpn { // Load cert list { - for (X509List::const_iterator i = cc.certs.begin(); i != cc.certs.end(); ++i) + for (const auto &e : cc.certs) { - if (!X509_STORE_add_cert(x509_store_, (*i)->obj())) - throw x509_store_add_cert_error(); + if (!::X509_STORE_add_cert(x509_store_, e.obj())) + throw x509_store_error("X509_STORE_add_cert("); } } @@ -63,19 +62,22 @@ namespace openvpn { { if (cc.crls.defined()) { - X509_STORE_set_flags(x509_store_, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); - for (CRLList::const_iterator i = cc.crls.begin(); i != cc.crls.end(); ++i) + ::X509_STORE_set_flags(x509_store_, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + for (const auto &e : cc.crls) { - if (!X509_STORE_add_crl(x509_store_, (*i)->obj())) - throw x509_store_add_crl_error(); + if (!::X509_STORE_add_crl(x509_store_, e.obj())) + throw x509_store_error("X509_STORE_add_crl"); } } } } - X509_STORE* obj() const { return x509_store_; } + X509_STORE* obj() const + { + return x509_store_; + } - X509_STORE* move() + X509_STORE* release() { X509_STORE* ret = x509_store_; x509_store_ = nullptr; @@ -85,20 +87,18 @@ namespace openvpn { ~X509Store() { if (x509_store_) - X509_STORE_free(x509_store_); + ::X509_STORE_free(x509_store_); } private: void init() { - x509_store_ = X509_STORE_new(); + x509_store_ = ::X509_STORE_new(); if (!x509_store_) - throw x509_store_init_error(); + throw x509_store_error("X509_STORE_new"); } - X509_STORE* x509_store_; + ::X509_STORE* x509_store_; }; } -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_PKI_X509STORE_H +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/pkcs7verify.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/pkcs7verify.hpp index 31fc9b2..888f48b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/pkcs7verify.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/pkcs7verify.hpp @@ -41,7 +41,7 @@ namespace openvpn { * On success, return. * On fail, throw exception. */ - inline void verify_pkcs7(const OpenSSLPKI::X509Base& cert, + inline void verify_pkcs7(const OpenSSLPKI::X509& cert, const std::string& sig, const std::string& data) { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/verify.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/verify.hpp index be62fb5..2dd406b 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/verify.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/sign/verify.hpp @@ -34,6 +34,8 @@ #include #include +#include + namespace openvpn { namespace OpenSSLSign { /* @@ -41,21 +43,25 @@ namespace openvpn { * On success, return. * On fail, throw exception. */ - inline void verify(const OpenSSLPKI::X509Base& cert, + inline void verify(const OpenSSLPKI::X509& cert, const std::string& sig, const std::string& data, const std::string& digest) { const EVP_MD *dig; - EVP_MD_CTX md_ctx; - bool md_ctx_initialized = false; + EVP_MD_CTX* md_ctx = nullptr; EVP_PKEY *pkey = nullptr; auto clean = Cleanup([&]() { if (pkey) EVP_PKEY_free(pkey); - if (md_ctx_initialized) - EVP_MD_CTX_cleanup(&md_ctx); + if (md_ctx) + { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_MD_CTX_cleanup(md_ctx); +#endif + EVP_MD_CTX_free(md_ctx); + } }); // get digest @@ -78,11 +84,13 @@ namespace openvpn { throw Exception(std::string("OpenSSLSign::verify: base64 decode error on signature: ") + e.what()); } + // initialize digest context + md_ctx = EVP_MD_CTX_new(); + // verify signature - EVP_VerifyInit (&md_ctx, dig); - md_ctx_initialized = 1; - EVP_VerifyUpdate(&md_ctx, data.c_str(), data.length()); - if (EVP_VerifyFinal(&md_ctx, binsig.c_data(), binsig.length(), pkey) != 1) + EVP_VerifyInit (md_ctx, dig); + EVP_VerifyUpdate(md_ctx, data.c_str(), data.length()); + if (EVP_VerifyFinal(md_ctx, binsig.c_data(), binsig.length(), pkey) != 1) throw OpenSSLException("OpenSSLSign::verify: verification failed"); } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp index adf1db7..aac5ff1 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -44,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +68,10 @@ #include #include +#ifdef HAVE_JSON +#include +#endif + // An SSL Context is essentially a configuration that can be used // to generate an arbitrary number of actual SSL connections objects. @@ -125,6 +133,18 @@ namespace openvpn { client_session_tickets = v; } + // server side + virtual void set_sni_handler(SNI::HandlerBase* sni_handler_arg) + { + sni_handler = sni_handler_arg; + } + + // client side + virtual void set_sni_name(const std::string& sni_name_arg) + { + sni_name = sni_name_arg; + } + virtual void set_private_key_password(const std::string& pwd) { pkey.set_private_key_password(pwd); @@ -182,7 +202,7 @@ namespace openvpn { std::vector ret; for (auto const& cert : extra_certs) - ret.push_back(cert->render_pem()); + ret.push_back(cert.render_pem()); return ret; } @@ -197,10 +217,10 @@ namespace openvpn { return dh.render_pem(); } - virtual PKType private_key_type() const + virtual PKType::Type private_key_type() const { if (!pkey.defined()) - return PK_NONE; + return PKType::PK_NONE; return pkey.key_type(); } @@ -322,6 +342,13 @@ namespace openvpn { && opt.exists("client-cert-not-required")) flags |= SSLConst::NO_VERIFY_PEER; + // sni + { + const std::string name = opt.get_optional("sni", 1, 256); + if (!name.empty()) + set_sni_name(name); + } + // ca { std::string ca_txt = opt.cat("ca"); @@ -379,18 +406,7 @@ namespace openvpn { tls_remote = opt.get_optional(relay_prefix + "tls-remote", 1, 256); // Parse tls-version-min option. - // Assume that presence of SSL_OP_NO_TLSvX macro indicates - // that local OpenSSL library implements TLSvX. - { -# if defined(SSL_OP_NO_TLSv1_2) - const TLSVersion::Type maxver = TLSVersion::V1_2; -# elif defined(SSL_OP_NO_TLSv1_1) - const TLSVersion::Type maxver = TLSVersion::V1_1; -# else - const TLSVersion::Type maxver = TLSVersion::V1_0; -# endif - tls_version_min = TLSVersion::parse_tls_version_min(opt, relay_prefix, maxver); - } + tls_version_min = TLSVersion::parse_tls_version_min(opt, relay_prefix, maxver()); // parse tls-cert-profile tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(opt, relay_prefix); @@ -400,7 +416,122 @@ namespace openvpn { } } +#ifdef HAVE_JSON + virtual SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const override + { + static const char title[] = "json_override"; + + Config::Ptr ret(new Config); + + // inherit from self + ret->mode = mode; + ret->dh = dh; + ret->frame = frame; + ret->ssl_debug_level = ssl_debug_level; + ret->flags = flags; + ret->local_cert_enabled = local_cert_enabled; + + // ca + { + const std::string& ca_txt = json::get_string_ref(root, "ca", title); + ret->load_ca(ca_txt, true); + } + + // CRL + { + const std::string crl_txt = json::get_string_optional(root, "crl_verify", std::string(), title); + if (!crl_txt.empty()) + ret->load_crl(crl_txt); + } + + // cert/key + if (load_cert_key && local_cert_enabled) + { + bool loaded_cert = false; + + // cert/extra_certs + { + const std::string cert_txt = json::get_string_optional(root, "cert", std::string(), title); + if (!cert_txt.empty()) + { + const std::string ec_txt = json::get_string_optional(root, "extra_certs", std::string(), title); + ret->load_cert(cert_txt, ec_txt); + loaded_cert = true; + } + else + { + ret->cert = cert; + ret->extra_certs = extra_certs; + } + } + + // private key + if (loaded_cert && !external_pki) + { + const std::string& key_txt = json::get_string_ref(root, "key", title); + if (!key_txt.empty()) + ret->load_private_key(key_txt); + else + ret->pkey = pkey; + } + } + else + { + // inherit from self + ret->cert = cert; + ret->extra_certs = extra_certs; + ret->pkey = pkey; + } + + // ns_cert_type + { + const std::string ct = json::get_string_optional(root, "ns_cert_type", std::string(), title); + if (!ct.empty()) + ret->ns_cert_type = NSCert::ns_cert_type(ct); + } + + // ku, eku + { + const std::string ct = json::get_string_optional(root, "remote_cert_tls", std::string(), title); + if (!ct.empty()) + KUParse::remote_cert_tls(ct, ret->ku, ret->eku); + } + + // tls_version_min + { + const std::string tvm = json::get_string_optional(root, "tls_version_min", std::string(), title); + if (!tvm.empty()) + ret->tls_version_min = TLSVersion::parse_tls_version_min(tvm, false, maxver()); + } + + // tls_cert_profile + { + const std::string prof = json::get_string_optional(root, "tls_cert_profile", std::string(), title); + if (!prof.empty()) + ret->tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(prof); + } + + return ret; + } +#endif + private: + static TLSVersion::Type maxver() + { + // Return maximum TLS version supported by OpenSSL. + // Assume that presence of SSL_OP_NO_TLSvX macro indicates + // that local OpenSSL library implements TLSvX. +#if defined(SSL_OP_NO_TLSv1_3) + return TLSVersion::V1_3; +#elif defined(SSL_OP_NO_TLSv1_2) + return TLSVersion::V1_2; +#elif defined(SSL_OP_NO_TLSv1_1) + return TLSVersion::V1_1; +#else + return TLSVersion::V1_0; +#endif + } + Mode mode; CertCRLList ca; // from OpenVPN "ca" and "crl-verify" option OpenSSLPKI::X509 cert; // from OpenVPN "cert" option @@ -409,9 +540,11 @@ namespace openvpn { OpenSSLPKI::DH dh; // diffie-hellman parameters (only needed in server mode) ExternalPKIBase* external_pki = nullptr; TLSSessionTicketBase* session_ticket_handler = nullptr; // server side only + SNI::HandlerBase* sni_handler = nullptr; // server side only Frame::Ptr frame; int ssl_debug_level = 0; unsigned int flags = 0; // defined in sslconsts.hpp + std::string sni_name; // client side only NSCert::Type ns_cert_type{NSCert::NONE}; std::vector ku; // if defined, peer cert X509 key usage must match one of these values std::string eku; // if defined, peer cert X509 extended key usage must match this OID/string @@ -433,12 +566,12 @@ namespace openvpn { public: typedef RCPtr Ptr; - virtual void start_handshake() + void start_handshake() override { SSL_do_handshake(ssl); } - virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) + ssize_t write_cleartext_unbuffered(const void *data, const size_t size) override { const int status = BIO_write(ssl_bio, data, size); if (status < 0) @@ -455,7 +588,7 @@ namespace openvpn { return status; } - virtual ssize_t read_cleartext(void *data, const size_t capacity) + ssize_t read_cleartext(void *data, const size_t capacity) override { if (!overflow) { @@ -477,12 +610,12 @@ namespace openvpn { throw ssl_ciphertext_in_overflow(); } - virtual bool read_cleartext_ready() const + bool read_cleartext_ready() const override { return !bmq_stream::memq_from_bio(ct_in)->empty() || SSL_pending(ssl) > 0; } - virtual void write_ciphertext(const BufferPtr& buf) + void write_ciphertext(const BufferPtr& buf) override { bmq_stream::MemQ* in = bmq_stream::memq_from_bio(ct_in); if (in->size() < MAX_CIPHERTEXT_IN) @@ -491,7 +624,7 @@ namespace openvpn { overflow = true; } - virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) + void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) override { bmq_stream::MemQ* in = bmq_stream::memq_from_bio(ct_in); if (in->size() < MAX_CIPHERTEXT_IN) @@ -500,17 +633,17 @@ namespace openvpn { overflow = true; } - virtual bool read_ciphertext_ready() const + bool read_ciphertext_ready() const override { return !bmq_stream::memq_from_bio(ct_out)->empty(); } - virtual BufferPtr read_ciphertext() + BufferPtr read_ciphertext() override { return bmq_stream::memq_from_bio(ct_out)->read_buf(); } - virtual std::string ssl_handshake_details() const + std::string ssl_handshake_details() const override { return ssl_handshake_details(ssl); } @@ -526,7 +659,7 @@ namespace openvpn { return !SSL_session_reused(ssl); } - virtual const AuthCert::Ptr& auth_cert() + const AuthCert::Ptr& auth_cert() const override { // Reused sessions don't call the cert verify callbacks, // so we must use an alternative method to build authcert. @@ -535,7 +668,7 @@ namespace openvpn { return authcert; } - virtual void mark_no_cache() + void mark_no_cache() override { sess_cache_key.reset(); } @@ -549,7 +682,7 @@ namespace openvpn { { bmq_stream::init_static(); - mydata_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr); + ssl_data_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr); context_data_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext", nullptr, nullptr, nullptr); /* @@ -592,7 +725,7 @@ namespace openvpn { SSL_set_mode(ssl, SSL_MODE_RELEASE_BUFFERS); // verify hostname - if (hostname) + if (hostname && !(ctx.config->flags & SSLConst::NO_VERIFY_HOSTNAME)) { X509_VERIFY_PARAM *param = SSL_get0_param(ssl); X509_VERIFY_PARAM_set_hostflags(param, 0); @@ -628,9 +761,18 @@ namespace openvpn { sess_cache_key.reset(new OpenSSLSessionCache::Key(*cache_key, ctx.sess_cache)); } SSL_set_connect_state(ssl); - if (ctx.config->flags & SSLConst::ENABLE_SNI) - if (SSL_set_tlsext_host_name(ssl, hostname) != 1) - throw OpenSSLException("OpenSSLContext::SSL: SSL_set_tlsext_host_name failed"); + + // client-side SNI + if (!ctx.config->sni_name.empty()) + { + if (SSL_set_tlsext_host_name(ssl, ctx.config->sni_name.c_str()) != 1) + throw OpenSSLException("OpenSSLContext::SSL: SSL_set_tlsext_host_name failed (sni_name)"); + } + else if ((ctx.config->flags & SSLConst::ENABLE_CLIENT_SNI) && hostname) + { + if (SSL_set_tlsext_host_name(ssl, hostname->c_str()) != 1) + throw OpenSSLException("OpenSSLContext::SSL: SSL_set_tlsext_host_name failed (hostname)"); + } } else OPENVPN_THROW(ssl_context_error, "OpenSSLContext::SSL: unknown client/server mode"); @@ -640,12 +782,10 @@ namespace openvpn { SSL_set_bio (ssl, ct_in, ct_out); BIO_set_ssl (ssl_bio, ssl, BIO_NOCLOSE); - if (mydata_index < 0) - throw ssl_context_error("OpenSSLContext::SSL: mydata_index is uninitialized"); - if (context_data_index < 0) - throw ssl_context_error("OpenSSLContext::SSL: context_data_index is uninitialized"); - SSL_set_ex_data (ssl, mydata_index, this); - SSL_set_ex_data (ssl, context_data_index, (void*) &ctx); + if (ssl_data_index < 0) + throw ssl_context_error("OpenSSLContext::SSL: ssl_data_index is uninitialized"); + SSL_set_ex_data (ssl, ssl_data_index, this); + set_parent(&ctx); } catch (...) { @@ -654,9 +794,15 @@ namespace openvpn { } } - void rebuild_authcert() + void set_parent(const OpenSSLContext* ctx) + { + if (context_data_index < 0) + throw ssl_context_error("OpenSSLContext::SSL: context_data_index is uninitialized"); + SSL_set_ex_data(ssl, context_data_index, (void *)ctx); + } + + void rebuild_authcert() const { - authcert.reset(new AuthCert()); ::X509 *cert = SSL_get_peer_certificate(ssl); if (cert) { @@ -684,17 +830,21 @@ namespace openvpn { } // Print a one line summary of SSL/TLS session handshake. - static std::string ssl_handshake_details (::SSL *c_ssl) + static std::string ssl_handshake_details (const ::SSL *c_ssl) { std::ostringstream os; + ::X509 *cert = SSL_get_peer_certificate (c_ssl); + + if (cert) + os << "CN=" << x509_get_field(cert, NID_commonName) << ", "; + os << SSL_get_version (c_ssl); const SSL_CIPHER *ciph = SSL_get_current_cipher (c_ssl); if (ciph) os << ", cipher " << SSL_CIPHER_get_version (ciph) << ' ' << SSL_CIPHER_get_name (ciph); - ::X509 *cert = SSL_get_peer_certificate (c_ssl); if (cert != nullptr) { EVP_PKEY *pkey = X509_get_pubkey (cert); @@ -710,7 +860,10 @@ namespace openvpn { } X509_free (cert); } - if (SSL_session_reused(c_ssl)) + // This has been changed in upstream SSL to have a const + // parameter, so we cast away const for older versions compatibility + // (Upstream commit: c04b66b18d1a90f0c6326858e4b8367be5444582) + if (SSL_session_reused(const_cast<::SSL *>(c_ssl))) os << " [REUSED]"; return os.str(); } @@ -792,12 +945,13 @@ namespace openvpn { BIO *ct_out; // read ciphertext from here AuthCert::Ptr authcert; OpenSSLSessionCache::Key::UPtr sess_cache_key; // client-side only + OpenSSLContext::Ptr sni_ctx; bool ssl_bio_linkage; bool overflow; bool called_did_full_handshake; // Helps us to store pointer to self in ::SSL object - static int mydata_index; + static int ssl_data_index; static int context_data_index; #if OPENSSL_VERSION_NUMBER < 0x10100000L @@ -1003,6 +1157,17 @@ namespace openvpn { throw OpenSSLException("OpenSSLContext: SSL_CTX_set_tmp_dh failed"); if (config->flags & SSLConst::SERVER_TO_SERVER) SSL_CTX_set_purpose(ctx, X509_PURPOSE_SSL_SERVER); + + // server-side SNI + if (config->sni_handler) + { +#if OPENSSL_VERSION_NUMBER >= 0x10101000L +#define OPENSSL_SERVER_SNI + SSL_CTX_set_client_hello_cb(ctx, client_hello_callback, nullptr); +#else + OPENVPN_THROW(ssl_context_error, "OpenSSLContext: server-side SNI requires OpenSSL 1.1 or higher"); +#endif + } } else if (config->mode.is_client()) { @@ -1024,11 +1189,8 @@ namespace openvpn { SSL_CTX_set_verify_depth(ctx, 16); } - long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION; - /* Disable SSLv2 and SSLv3, might be a noop but does not hurt */ - sslopt |= SSL_OP_NO_SSLv2; - sslopt |= SSL_OP_NO_SSLv3; + long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; if (config->mode.is_server()) { @@ -1044,6 +1206,16 @@ namespace openvpn { } else sslopt |= SSL_OP_NO_TICKET; + + // send a client CA list to the client + if (config->flags & SSLConst::SEND_CLIENT_CA_LIST) + { + for (const auto& e : config->ca.certs) + { + if (SSL_CTX_add_client_CA(ctx, e.obj()) != 1) + throw OpenSSLException("OpenSSLContext: SSL_CTX_add_client_CA failed"); + } + } } else { @@ -1062,23 +1234,20 @@ namespace openvpn { /* mbed TLS also ignores tls version when force aes cbc cipher suites is on */ if (!config->force_aes_cbc_ciphersuites) { - if (!config->force_aes_cbc_ciphersuites || config->tls_version_min > TLSVersion::UNDEF) - { - if (config->tls_version_min > TLSVersion::V1_0) - sslopt |= SSL_OP_NO_TLSv1; -# ifdef SSL_OP_NO_TLSv1_1 - if (config->tls_version_min > TLSVersion::V1_1) - sslopt |= SSL_OP_NO_TLSv1_1; -# endif -# ifdef SSL_OP_NO_TLSv1_2 - if (config->tls_version_min > TLSVersion::V1_2) - sslopt |= SSL_OP_NO_TLSv1_2; -# endif -# ifdef SSL_OP_NO_TLSv1_3 - if (config->tls_version_min > TLSVersion::V1_3) - sslopt |= SSL_OP_NO_TLSv1_3; -# endif - } + if (config->tls_version_min > TLSVersion::V1_0) + sslopt |= SSL_OP_NO_TLSv1; +# ifdef SSL_OP_NO_TLSv1_1 + if (config->tls_version_min > TLSVersion::V1_1) + sslopt |= SSL_OP_NO_TLSv1_1; +# endif +# ifdef SSL_OP_NO_TLSv1_2 + if (config->tls_version_min > TLSVersion::V1_2) + sslopt |= SSL_OP_NO_TLSv1_2; +# endif +# ifdef SSL_OP_NO_TLSv1_3 + if (config->tls_version_min > TLSVersion::V1_3) + sslopt |= SSL_OP_NO_TLSv1_3; +# endif } SSL_CTX_set_options(ctx, sslopt); @@ -1178,9 +1347,9 @@ namespace openvpn { // chain but shouldn't be included in the verify chain. if (config->extra_certs.defined()) { - for (OpenSSLPKI::X509List::const_iterator i = config->extra_certs.begin(); i != config->extra_certs.end(); ++i) + for (const auto& e : config->extra_certs) { - if (SSL_CTX_add_extra_chain_cert(ctx, (*i)->obj_dup()) != 1) + if (SSL_CTX_add_extra_chain_cert(ctx, e.obj_dup()) != 1) throw OpenSSLException("OpenSSLContext: SSL_CTX_add_extra_chain_cert failed"); } } @@ -1219,7 +1388,7 @@ namespace openvpn { void update_trust(const CertCRLList& cc) { OpenSSLPKI::X509Store store(cc); - SSL_CTX_set_cert_store(ctx, store.move()); + SSL_CTX_set_cert_store(ctx, store.release()); } ~OpenSSLContext() @@ -1528,7 +1697,7 @@ namespace openvpn { case X509_V_ERR_CERT_HAS_EXPIRED: return AuthCert::Fail::EXPIRED; default: - return AuthCert::Fail::OTHER; + return AuthCert::Fail::CERT_FAIL; } } @@ -1601,7 +1770,7 @@ namespace openvpn { const OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data (ssl, SSL::context_data_index); // get OpenSSLContext::SSL - SSL* self_ssl = (SSL *) SSL_get_ex_data (ssl, SSL::mydata_index); + SSL* self_ssl = (SSL *) SSL_get_ex_data (ssl, SSL::ssl_data_index); // get error code const int err = X509_STORE_CTX_get_error(ctx); @@ -1678,9 +1847,7 @@ namespace openvpn { self->config->x509_track_config, *self_ssl->authcert->x509_track); - return preverify_ok || ((self->config->flags & SSLConst::DEFERRED_CERT_VERIFY) - && self_ssl->authcert // failsafe: don't defer error unless - && self_ssl->authcert->is_fail()); // authcert has recorded it + return preverify_ok || self->deferred_cert_verify_failsafe(*self_ssl); } // Print debugging information on SSL/TLS session negotiation. @@ -1806,6 +1973,139 @@ namespace openvpn { return true; } +#if OPENSSL_VERSION_NUMBER >= 0x10101000L + + static int client_hello_callback(::SSL *s, int *al, void *) + { + std::string sni_name; + + // get OpenSSLContext + OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data(s, SSL::context_data_index); + + // get OpenSSLContext::SSL + SSL* self_ssl = (SSL *) SSL_get_ex_data(s, SSL::ssl_data_index); + + try { + // get the SNI from the client hello + sni_name = client_hello_get_sni(s); + + // process the SNI name, if provided + if (!sni_name.empty()) + { + // save the SNI name in authcert + if (self_ssl->authcert) + self_ssl->authcert->sni = sni_name; + + // ignore the SNI if no handler was provided + if (self->config->sni_handler) + { + // get an alternative SSLFactoryAPI from the sni_handler + SSLFactoryAPI::Ptr fapi; + try { + SNI::Metadata::UPtr sm; + fapi = self->config->sni_handler->sni_hello(sni_name, sm, self->config); + if (self_ssl->authcert) + self_ssl->authcert->sni_metadata = std::move(sm); + } + catch (const std::exception& e) + { + OPENVPN_LOG("SNI HANDLER ERROR: " << e.what()); + return sni_error(e.what(), SSL_AD_INTERNAL_ERROR, self, self_ssl, al); + } + if (!fapi) + return sni_error("SNI name not found", SSL_AD_UNRECOGNIZED_NAME, self, self_ssl, al); + + // make sure that returned SSLFactoryAPI is an OpenSSLContext + self_ssl->sni_ctx = fapi.dynamic_pointer_cast(); + if (!self_ssl->sni_ctx) + throw Exception("sni_handler returned wrong kind of SSLFactoryAPI"); + + // don't modify SSL CTX if the returned SSLFactoryAPI is ourself + if (fapi.get() != self) + { + SSL_set_SSL_CTX(s, self_ssl->sni_ctx->ctx); + self_ssl->set_parent(self_ssl->sni_ctx.get()); + } + } + } + return SSL_CLIENT_HELLO_SUCCESS; + } + catch (const std::exception& e) + { + OPENVPN_LOG("SNI exception in OpenSSLContext, SNI=" << sni_name << " : " << e.what()); + *al = SSL_AD_INTERNAL_ERROR; + return SSL_CLIENT_HELLO_ERROR; + } + } + + static int sni_error(std::string err, + const int ssl_ad_error, + OpenSSLContext* self, + SSL* self_ssl, + int* al) + { + if (self_ssl->authcert) + self_ssl->authcert->add_fail(0, AuthCert::Fail::SNI_ERROR, std::move(err)); + if (self->deferred_cert_verify_failsafe(*self_ssl)) + return SSL_CLIENT_HELLO_SUCCESS; + *al = ssl_ad_error; + return SSL_CLIENT_HELLO_ERROR; + } + + static size_t sni_get_len(ConstBuffer& buf) + { + size_t ret = buf.pop_front() << 8; + ret += buf.pop_front(); + return ret; + } + + static std::string client_hello_get_sni(::SSL* s) + { + const unsigned char *p; + size_t remaining; + if (!SSL_client_hello_get0_ext(s, TLSEXT_TYPE_server_name, &p, &remaining)) + return std::string(); + + // For safety, map a ConstBuffer onto returned OpenSSL TLSEXT_TYPE_server_name data. + ConstBuffer buf(p, remaining, true); + + // Extract the length of the supplied list of names, + // and check that it matches size of remaining data + // in buf. + { + const size_t len = sni_get_len(buf); + if (len != buf.size()) + throw Exception("bad name list size"); + } + + // Next byte must be TLSEXT_NAMETYPE_host_name. + if (buf.pop_front() != TLSEXT_NAMETYPE_host_name) + throw Exception("expecting TLSEXT_NAMETYPE_host_name"); + + // Now try to extract the SNI name. + { + const size_t len = sni_get_len(buf); + if (len > buf.size()) + throw Exception("bad name size"); + if (!Unicode::is_valid_utf8_uchar_buf(buf.c_data(), len, 1024 | Unicode::UTF8_NO_CTRL)) + throw Exception("invalid UTF-8"); + return std::string((const char *)buf.c_data(), len); + } + } +#endif + + // Return true if we should continue with authentication + // even though there was an error, because the user has + // enabled SSLConst::DEFERRED_CERT_VERIFY and wants the + // error to be logged in authcert so that it can be handled + // by a higher layer. + bool deferred_cert_verify_failsafe(const SSL& ssl) const + { + return (config->flags & SSLConst::DEFERRED_CERT_VERIFY) + && ssl.authcert // failsafe: don't defer error unless + && ssl.authcert->is_fail(); // authcert has recorded it + } + void erase() { if (epki) @@ -1826,13 +2126,19 @@ namespace openvpn { OpenSSLSessionCache::Ptr sess_cache; // client-side only }; - int OpenSSLContext::SSL::mydata_index = -1; +#ifdef OPENVPN_NO_EXTERN + int OpenSSLContext::SSL::ssl_data_index = -1; int OpenSSLContext::SSL::context_data_index = -1; +#endif -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(OPENVPN_NO_EXTERN) SSL_METHOD OpenSSLContext::SSL::ssl23_method_client_; SSL_METHOD OpenSSLContext::SSL::ssl23_method_server_; #endif -} + inline const std::string get_ssl_library_version() + { + return OPENSSL_VERSION_TEXT; + } +} #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/reseed.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/reseed.hpp new file mode 100644 index 0000000..f56192f --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/reseed.hpp @@ -0,0 +1,40 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +// seed OpenSSL's random number generator with /dev/urandom + +#include + +#include + +namespace openvpn { + inline void openssl_reseed_rng() + { + unsigned char entropy[64]; + + RandomAPI::Ptr rng(new DevURand); + rng->rand_bytes(entropy, sizeof(entropy)); + + RAND_seed(entropy, sizeof(entropy)); + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/tokenencrypt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/tokenencrypt.hpp index 41ab797..e25fd1d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/tokenencrypt.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/tokenencrypt.hpp @@ -66,15 +66,17 @@ namespace openvpn { TokenEncrypt(const Key& key, const int mode) { ctx = EVP_CIPHER_CTX_new (); - EVP_CIPHER_CTX_init (ctx); + EVP_CIPHER_CTX_reset (ctx); if (!EVP_CipherInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key.data, nullptr, mode)) - throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[1] failed"); + { + EVP_CIPHER_CTX_free(ctx); + throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[1] failed"); + } EVP_CIPHER_CTX_set_padding(ctx, 0); } ~TokenEncrypt() { - EVP_CIPHER_CTX_cleanup(ctx); EVP_CIPHER_CTX_free(ctx); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp index a1097cc..f8a8a06 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp @@ -140,14 +140,14 @@ namespace openvpn { else { status_ = MERGE_OVPN_EXT_FAIL; - error_ = basename_; + error_ = std::string("ERR_PROFILE_NO_OVPN_EXTENSION: ") + basename_; return; } } catch (const std::exception& e) { status_ = MERGE_OVPN_FILE_FAIL; - error_ = e.what(); + error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); return; } @@ -157,7 +157,7 @@ namespace openvpn { catch (const std::exception& e) { status_ = MERGE_EXCEPTION; - error_ = e.what(); + error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); } } @@ -189,7 +189,7 @@ namespace openvpn { if (total_size > max_size) { status_ = MERGE_EXCEPTION; - error_ = "file too large"; + error_ = "ERR_PROFILE_FILE_TOO_LARGE: file too large"; return; } @@ -207,7 +207,7 @@ namespace openvpn { if (in.line_overflow()) { status_ = MERGE_EXCEPTION; - error_ = "line too long"; + error_ = "ERR_PROFILE_LINE_TOO_LONG: line too long"; return; } const std::string& line = in.line_ref(); @@ -276,12 +276,13 @@ namespace openvpn { { echo = false; status_ = MERGE_REF_FAIL; + error_ = "ERR_PROFILE_NO_FILENAME: filename not provided"; } else if (follow_references != FOLLOW_FULL && !path::is_flat(fn)) { echo = false; status_ = MERGE_REF_FAIL; - error_ = fn; + error_ = std::string("ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn; if (ref_fail_list_.size() < MAX_FN_LIST_SIZE) ref_fail_list_.push_back(fn); } @@ -294,7 +295,7 @@ namespace openvpn { if (follow_references == FOLLOW_NONE) { status_ = MERGE_EXCEPTION; - error_ = fn + ": cannot follow file reference"; + error_ = std::string("ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn + ": cannot follow file reference"; return; } path = path::join(profile_dir, fn); @@ -303,7 +304,7 @@ namespace openvpn { if (total_size > max_size) { status_ = MERGE_EXCEPTION; - error_ = fn + ": file too large"; + error_ = std::string("ERR_PROFILE_FILE_TOO_LARGE: ") + fn + ": file too large"; return; } OptionList::detect_multiline_breakout(file_content, opt.ref(0)); @@ -312,7 +313,7 @@ namespace openvpn { { error = true; status_ = MERGE_REF_FAIL; - error_ = fn + " : " + e.what(); + error_ = std::string("ERR_PROFILE_GENERIC: ") + fn + " : " + e.what(); if (ref_fail_list_.size() < MAX_FN_LIST_SIZE) ref_fail_list_.push_back(fn); } @@ -363,7 +364,7 @@ namespace openvpn { if (ref_fail_list_.size() >= 2) { status_ = MERGE_MULTIPLE_REF_FAIL; - error_ = ""; + error_ = "ERR_PROFILE_GENERIC: "; for (size_t i = 0; i < ref_fail_list_.size(); ++i) { if (i) @@ -459,7 +460,7 @@ namespace openvpn { catch (const std::exception& e) { status_ = MERGE_EXCEPTION; - error_ = e.what(); + error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/cclist.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/cclist.hpp index 469e19f..55c84c0 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/cclist.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/cclist.hpp @@ -35,7 +35,7 @@ namespace openvpn { // Parse a concatenated list of certs and CRLs (PEM format). // Abstracts CertList and CRLList, so can be used with any crypto lib. - // CertList and CRLList must define Item and ItemPtr types. + // CertList and CRLList must define Item type. template class CertCRLListTemplate { @@ -109,8 +109,7 @@ namespace openvpn { if (state == S_IN_CERT && line == cert_end) { try { - typename CertList::ItemPtr x509(new typename CertList::Item(item, title)); - cert_list->push_back(x509); + cert_list->emplace_back(item, title); } catch (const std::exception& e) { @@ -122,8 +121,7 @@ namespace openvpn { if (state == S_IN_CRL && line == crl_end) { try { - typename CRLList::ItemPtr crl(new typename CRLList::Item(item)); - crl_list->push_back(crl); + crl_list->emplace_back(item); } catch (const std::exception& e) { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/pktype.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/pktype.hpp new file mode 100644 index 0000000..b6bcebb --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/pki/pktype.hpp @@ -0,0 +1,39 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +// private key types + +namespace openvpn { + namespace PKType { + + enum Type { + PK_UNKNOWN = 0, + PK_NONE, + PK_DSA, + PK_RSA, + PK_EC, + PK_ECDSA, + }; + + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/mtrandapi.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/mtrandapi.hpp index 7a9735b..ac46193 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/mtrandapi.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/mtrandapi.hpp @@ -50,6 +50,11 @@ namespace openvpn { { } + MTRand(const rand_type::result_type seed) + : rng(seed) + { + } + // Random algorithm name virtual std::string name() const { @@ -59,7 +64,11 @@ namespace openvpn { // Return true if algorithm is crypto-strength virtual bool is_crypto() const { +#ifdef OPENVPN_INSECURE_RANDOM // DO NOT enable in production! + return true; +#else return false; +#endif } // Fill buffer with random bytes diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randapi.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randapi.hpp index 667eba0..b73adce 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randapi.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randapi.hpp @@ -25,10 +25,12 @@ #define OPENVPN_MBEDTLS_UTIL_RANDAPI_H #include +#include #include #include #include +#include namespace openvpn { @@ -94,6 +96,41 @@ namespace openvpn { return start + rand_get_positive() % (end - start + 1); } + // Return a uniformly distributed random number in the range [0, end). + // This version is strictly 32-bit only and optimizes by avoiding + // integer division. + std::uint32_t randrange32(const std::uint32_t end) + { + std::uint32_t r; + rand_fill(r); + return rand32_distribute(r, end); + } + + // Return a uniformly distributed random number in the range [start, end]. + // This version is strictly 32-bit only and optimizes by avoiding + // integer division. + std::uint32_t randrange32(const std::uint32_t start, const std::uint32_t end) + { + if (start >= end) + return start; + else + return start + randrange32(end - start + 1); + } + + // Return a random byte + std::uint8_t randbyte() + { + std::uint8_t byte; + rand_fill(byte); + return byte; + } + + // Return a random boolean + bool randbool() + { + return bool(randbyte() & 1); + } + // Throw an exception if algorithm is not crypto-strength. // Be sure to always call this method before using an rng // for crypto purposes. diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randistrib.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randistrib.hpp new file mode 100644 index 0000000..bbc7d81 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/random/randistrib.hpp @@ -0,0 +1,37 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +namespace openvpn { + + // Return a uniformly distributed random number in the range [0, end) + // using seed as a random seed. This version is strictly 32-bit only + // and optimizes by avoiding integer division. + inline std::uint32_t rand32_distribute(const std::uint32_t seed, + const std::uint32_t end) + { + return (std::uint64_t(seed) * end) >> 32; + } + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp index fa34b3b..a1401ef 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp @@ -71,7 +71,7 @@ namespace openvpn { virtual std::uint64_t instance_id() const = 0; // return a JSON string describing connected user - virtual std::string describe_user() = 0; + virtual std::string describe_user(const bool show_userprop) = 0; // disconnect virtual void disconnect_user(const HaltRestart::Type type, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/vpnservnetblock.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/vpnservnetblock.hpp index b578123..4003443 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/vpnservnetblock.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/vpnservnetblock.hpp @@ -69,7 +69,7 @@ namespace openvpn { std::string to_string() const { - return '[' + net.to_string() + ',' + server_gw.to_string() + ']'; + return '[' + net.to_string() + '/' + std::to_string(prefix_len) + ',' + server_gw.to_string() + ']'; } IP::Addr net; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/kuparse.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/kuparse.hpp index 45a2a51..68e1cd9 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/kuparse.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/kuparse.hpp @@ -65,6 +65,23 @@ namespace openvpn { } } + inline TLSWebType remote_cert_type(const std::string& ct) + { + if (ct == "server") + return TLS_WEB_SERVER; + else if (ct == "client") + return TLS_WEB_CLIENT; + else + throw option_error("remote-cert-tls must be 'client' or 'server'"); + } + + inline void remote_cert_tls(const std::string& ct, + std::vector& ku, + std::string& eku) + { + remote_cert_tls(remote_cert_type(ct), ku, eku); + } + inline void remote_cert_tls(const OptionList& opt, const std::string& relay_prefix, std::vector& ku, @@ -75,12 +92,7 @@ namespace openvpn { if (o) { const std::string ct = o->get_optional(1, 16); - if (ct == "server") - wt = TLS_WEB_SERVER; - else if (ct == "client") - wt = TLS_WEB_CLIENT; - else - throw option_error("remote-cert-tls must be 'client' or 'server'"); + wt = remote_cert_type(ct); } remote_cert_tls(wt, ku, eku); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/nscert.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/nscert.hpp index 1343cb7..5a36d4a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/nscert.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/nscert.hpp @@ -38,17 +38,23 @@ namespace openvpn { SERVER }; - inline Type ns_cert_type(const OptionList& opt, const std::string& relay_prefix) { + inline Type ns_cert_type(const std::string& ct) + { + if (ct == "server") + return SERVER; + else if (ct == "client") + return CLIENT; + else + throw option_error("ns-cert-type must be 'client' or 'server'"); + } + + inline Type ns_cert_type(const OptionList& opt, const std::string& relay_prefix) + { const Option* o = opt.get_ptr(relay_prefix + "ns-cert-type"); if (o) { const std::string ct = o->get_optional(1, 16); - if (ct == "server") - return SERVER; - else if (ct == "client") - return CLIENT; - else - throw option_error("ns-cert-type must be 'client' or 'server'"); + return ns_cert_type(ct); } return NONE; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp index 3cdd8e3..c838054 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp @@ -334,9 +334,6 @@ namespace openvpn { // extra peer info key/value pairs generated by client app PeerInfo::Set::Ptr extra_peer_info; - // GUI version, passed to server as IV_GUI_VER - std::string gui_version; - // op header bool enable_op32 = false; int remote_peer_id = -1; // -1 to disable @@ -627,7 +624,12 @@ namespace openvpn { // server pushes compression but client has compression disabled // degrade to asymmetric compression (downlink only) comp_ctx = CompressContext(meth, true); - OPENVPN_LOG("Server has pushed compressor " << comp_ctx.str() << ", but client has disabled compression, switching to asymmetric"); + if (!comp_ctx.is_any_stub(meth)) + { + OPENVPN_LOG("Server has pushed compressor " + << comp_ctx.str() + << ", but client has disabled compression, switching to asymmetric"); + } } } } @@ -803,8 +805,6 @@ namespace openvpn { std::ostringstream out; const char *compstr = nullptr; - if (!gui_version.empty()) - out << "IV_GUI_VER=" << gui_version << '\n'; out << "IV_VER=" << OPENVPN_VERSION << '\n'; out << "IV_PLAT=" << platform_name() << '\n'; if (!force_aes_cbc_ciphersuites) @@ -3491,8 +3491,8 @@ namespace openvpn { bool is_client() const { return mode_.is_client(); } // tcp/udp mode - const bool is_tcp() { return config->protocol.is_tcp(); } - const bool is_udp() { return config->protocol.is_udp(); } + bool is_tcp() { return config->protocol.is_tcp(); } + bool is_udp() { return config->protocol.is_udp(); } // configuration const Config& conf() const { return *config; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_handler.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_handler.hpp new file mode 100644 index 0000000..a1feb30 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_handler.hpp @@ -0,0 +1,52 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include +#include + +#include +#include + +namespace openvpn { + namespace SNI { + + // Abstract base class used to provide an SNI handler + class HandlerBase + { + public: + typedef std::unique_ptr UPtr; + + // Return a new SSLFactoryAPI for this SNI name. + // Implementation may also set sni_metadata. + // Return SSLFactoryAPI::Ptr() if sni_name is not recognized. + // The caller guarantees that sni_name is valid UTF-8 and + // doesn't contain any control characters. + virtual SSLFactoryAPI::Ptr sni_hello(const std::string& sni_name, + SNI::Metadata::UPtr& sni_metadata, + SSLConfigAPI::Ptr default_factory) const = 0; + + virtual ~HandlerBase() {} + }; + + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_metadata.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_metadata.hpp new file mode 100644 index 0000000..5446f0c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sni_metadata.hpp @@ -0,0 +1,44 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include +#include + +namespace openvpn { + + class AuthCert; + + namespace SNI { + + class Metadata + { + public: + typedef std::unique_ptr UPtr; + + virtual std::string sni_client_name(const AuthCert& ac) const = 0; + + virtual ~Metadata() = default; + }; + + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp index c207a91..9258340 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp @@ -32,10 +32,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -46,6 +48,10 @@ namespace openvpn { + namespace SNI { + class HandlerBase; + } + class SSLAPI : public RC { public: @@ -67,7 +73,7 @@ namespace openvpn { virtual BufferPtr read_ciphertext() = 0; virtual std::string ssl_handshake_details() const = 0; virtual bool did_full_handshake() = 0; - virtual const AuthCert::Ptr& auth_cert() = 0; + virtual const AuthCert::Ptr& auth_cert() const = 0; virtual void mark_no_cache() = 0; // prevent caching of client-side session (only meaningful when client_session_tickets is enabled) uint32_t get_tls_warnings() const { @@ -103,15 +109,6 @@ namespace openvpn { public: typedef RCPtr Ptr; - enum PKType { - PK_UNKNOWN = 0, - PK_NONE, - PK_DSA, - PK_RSA, - PK_EC, - PK_ECDSA, - }; - enum LoadFlags { LF_PARSE_MODE = (1<<0), LF_ALLOW_CLIENT_CERT_NOT_REQUIRED = (1<<1), @@ -121,21 +118,21 @@ namespace openvpn { std::string private_key_type_string() const { - PKType type = private_key_type(); + PKType::Type type = private_key_type(); switch (type) { - case PK_NONE: + case PKType::PK_NONE: return "None"; - case PK_DSA: + case PKType::PK_DSA: return "DSA"; - case PK_RSA: + case PKType::PK_RSA: return "RSA"; - case PK_EC: + case PKType::PK_EC: return "EC"; - case PK_ECDSA: + case PKType::PK_ECDSA: return "ECDSA"; - case PK_UNKNOWN: + case PKType::PK_UNKNOWN: default: return "Unknown"; } @@ -146,6 +143,8 @@ namespace openvpn { virtual void set_external_pki_callback(ExternalPKIBase* external_pki_arg) = 0; // private key alternative virtual void set_session_ticket_handler(TLSSessionTicketBase* session_ticket_handler) = 0; // server side virtual void set_client_session_tickets(const bool v) = 0; // client side + virtual void set_sni_handler(SNI::HandlerBase* sni_handler) = 0; // server side + virtual void set_sni_name(const std::string& sni_name_arg) = 0; // client side virtual void set_private_key_password(const std::string& pwd) = 0; virtual void load_ca(const std::string& ca_txt, bool strict) = 0; virtual void load_crl(const std::string& crl_txt) = 0; @@ -159,7 +158,7 @@ namespace openvpn { virtual std::vector extract_extra_certs() const = 0; virtual std::string extract_private_key() const = 0; virtual std::string extract_dh() const = 0; - virtual PKType private_key_type() const = 0; + virtual PKType::Type private_key_type() const = 0; virtual size_t private_key_length() const = 0; virtual void set_frame(const Frame::Ptr& frame_arg) = 0; virtual void set_debug_level(const int debug_level) = 0; @@ -177,6 +176,10 @@ namespace openvpn { virtual void set_rng(const RandomAPI::Ptr& rng_arg) = 0; virtual void load(const OptionList& opt, const unsigned int lflags) = 0; +#ifdef HAVE_JSON + virtual SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const = 0; +#endif + virtual std::string validate_cert(const std::string& cert_txt) const = 0; virtual std::string validate_cert_list(const std::string& certs_txt) const = 0; virtual std::string validate_crl(const std::string& crl_txt) const = 0; @@ -185,6 +188,15 @@ namespace openvpn { virtual SSLFactoryAPI::Ptr new_factory() = 0; }; + + /** + * Reports a human readable string of the SSL library in use and its version. + * E.g. mbed TLS 1.2.4 + * + * @return a human readable SSL library version string + */ + inline const std::string get_ssl_library_version(); + } #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp index eb07766..093ab7f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp @@ -41,7 +41,7 @@ #include #include #include -#ifdef HAVE_OPENVPN_COMMON +#if defined(HAVE_OPENVPN_COMMON) && !defined(MBEDTLS_DISABLE_NAME_CONSTRAINTS) #include #endif #ifdef OPENVPN_PLATFORM_UWP @@ -61,7 +61,7 @@ namespace openvpn { #if defined(USE_MBEDTLS) #define SSL_LIB_NAME "MbedTLS" typedef MbedTLSCryptoAPI CryptoAPI; - #ifdef HAVE_OPENVPN_COMMON + #if defined(HAVE_OPENVPN_COMMON) && !defined(MBEDTLS_DISABLE_NAME_CONSTRAINTS) typedef MbedTLSContextNameConstraints SSLAPI; #else typedef MbedTLSContext SSLAPI; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslconsts.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslconsts.hpp index 88bab41..9bc8006 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslconsts.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslconsts.hpp @@ -44,25 +44,33 @@ namespace openvpn { // Disable peer verification NO_VERIFY_PEER=(1<<1), - // Enable SNI (Server Name Indication) when hostname is provided - ENABLE_SNI=(1<<2), + // [client only] Enable client-side SNI (Server Name Indication) + // when hostname is provided + ENABLE_CLIENT_SNI=(1<<2), + + // [client only] Don't require that the hostname matches + // the common name in the certificate. + NO_VERIFY_HOSTNAME=(1<<3), // [server only] Don't automatically fail connections on // bad peer cert. Succeed the connection, but pass the // fail status data via AuthCert so the higher layers // can handle it. - DEFERRED_CERT_VERIFY=(1<<3), + DEFERRED_CERT_VERIFY=(1<<4), // [server only] When running as a server, require that // clients that connect to us have their certificate // purpose set to server. - SERVER_TO_SERVER=(1<<4), + SERVER_TO_SERVER=(1<<5), // Peer certificate is optional - PEER_CERT_OPTIONAL=(1<<5), + PEER_CERT_OPTIONAL=(1<<6), + + // [server only] Send a list of client CAs to the client + SEND_CLIENT_CA_LIST=(1<<7), // last flag marker - LAST=(1<<6), + LAST=(1<<8) }; // filter all but SSL flags diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp index d277072..06794d8 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp @@ -21,58 +21,71 @@ #pragma once +#include #include -// AsioTimerSafe is like AsioTimer but with an epoch counter -// that allows a handler to determine if it is the most recent -// handler to be queued. +// AsioTimerSafe is like AsioTimer but with strict cancellation +// semantics that guarantees that a handler will never be called +// with a non-error status after the timer is cancelled. namespace openvpn { class AsioTimerSafe { public: - typedef std::size_t epoch_t; - AsioTimerSafe(openvpn_io::io_context& io_context) - : timer_(io_context) + : timer_(io_context), + epoch_(new Epoch) { } std::size_t expires_at(const Time& t) { - ++epoch_; + inc_epoch(); return timer_.expires_at(t); } std::size_t expires_after(const Time::Duration& d) { - ++epoch_; + inc_epoch(); return timer_.expires_after(d); } std::size_t cancel() { - ++epoch_; + inc_epoch(); return timer_.cancel(); } - epoch_t epoch() const - { - return epoch_; - } - template void async_wait(F&& func) { - ++epoch_; - timer_.async_wait([func=std::move(func), epoch=epoch_](const openvpn_io::error_code& error) mutable + inc_epoch(); + timer_.async_wait([func=std::move(func), epoch=epoch(), eptr=epoch_](const openvpn_io::error_code& error) { - func(error, epoch); + func(epoch == eptr->epoch ? error : openvpn_io::error::operation_aborted); }); } private: + typedef std::size_t epoch_t; + + struct Epoch : public RC + { + typedef RCPtr Ptr; + epoch_t epoch = 0; + }; + + epoch_t epoch() const + { + return epoch_->epoch; + } + + void inc_epoch() + { + ++epoch_->epoch; + } + AsioTimer timer_; - epoch_t epoch_ = 0; + Epoch::Ptr epoch_; }; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/epoch.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/epoch.hpp index 7bc13ff..ea90a11 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/epoch.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/epoch.hpp @@ -27,6 +27,8 @@ namespace openvpn { + typedef std::uint64_t nanotime_t; + inline std::uint64_t milliseconds_since_epoch() { struct timespec ts; @@ -36,7 +38,7 @@ namespace openvpn { + std::uint64_t(ts.tv_nsec) / std::uint64_t(1000000); } - inline std::uint64_t nanoseconds_since_epoch() + inline nanotime_t nanoseconds_since_epoch() { struct timespec ts; if (::clock_gettime(CLOCK_REALTIME, &ts)) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/skew.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/skew.hpp new file mode 100644 index 0000000..133bea6 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/skew.hpp @@ -0,0 +1,53 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2019 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . + +#pragma once + +#include + +#include +#include + +namespace openvpn { + + struct TimeSkew + { + // Skew factors (+/- %). + // Pass these to skew() via factor parameter. + enum { + PCT_50 = 0, + PCT_25 = 1, + PCT_12_5 = 2, + PCT_6_25 = 3, + PCT_3_125 = 4, + PCT_1_5625 = 5, + }; + + // Skew a duration by some random flux. + static Time::Duration skew(const Time::Duration& dur, const unsigned int factor, RandomAPI& prng) + { + const std::uint32_t bms = std::min(dur.to_binary_ms() >> factor, oulong(0x40000000)); // avoid 32-bit overflow in next step + const int flux = int(prng.randrange32(bms)) - int(bms/2); + return dur + flux; + } + }; + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp index 8eb3fd6..50c8811 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp @@ -909,7 +909,7 @@ namespace openvpn { OPENVPN_LOG("Contacting " << server_endpoint << " via HTTP Proxy"); parent->transport_wait_proxy(); socket.open(server_endpoint.protocol()); -#ifdef OPENVPN_PLATFORM_TYPE_UNIX + if (config->socket_protect) { if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) @@ -920,7 +920,7 @@ namespace openvpn { return; } } -#endif + socket.set_option(openvpn_io::ip::tcp::no_delay(true)); socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp index 9fddd4c..8077a8e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp @@ -53,6 +53,7 @@ namespace openvpn { #ifdef OPENVPN_TLS_LINK bool use_tls = false; + std::string tls_ca; #endif #ifdef OPENVPN_GREMLIN @@ -281,7 +282,7 @@ namespace openvpn { << server_protocol.str()); parent->transport_wait(); socket.open(server_endpoint.protocol()); -#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP) + if (config->socket_protect) { if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) @@ -292,7 +293,7 @@ namespace openvpn { return; } } -#endif + socket.set_option(openvpn_io::ip::tcp::no_delay(true)); socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { @@ -311,15 +312,26 @@ namespace openvpn { #ifdef OPENVPN_TLS_LINK if (config->use_tls) { + int flags = SSLConst::LOG_VERIFY_STATUS|SSLConst::ENABLE_CLIENT_SNI; SSLLib::SSLAPI::Config::Ptr ssl_conf; ssl_conf.reset(new SSLLib::SSLAPI::Config()); ssl_conf->set_mode(Mode(Mode::CLIENT)); - ssl_conf->set_flags(SSLConst::LOG_VERIFY_STATUS|SSLConst::NO_VERIFY_PEER| - SSLConst::ENABLE_SNI); ssl_conf->set_local_cert_enabled(false); ssl_conf->set_frame(config->frame); ssl_conf->set_rng(new SSLLib::RandomAPI(false)); + if (!config->tls_ca.empty()) + { + ssl_conf->load_ca(config->tls_ca, true); + } + else + { + flags |= SSLConst::NO_VERIFY_PEER; + } + + ssl_conf->set_flags(flags); + ssl_factory = ssl_conf->new_factory(); + impl.reset(new LinkImplTLS(this, io_context, socket, @@ -327,7 +339,7 @@ namespace openvpn { config->free_list_max_size, config->frame, config->stats, - ssl_conf->new_factory())); + ssl_factory)); } else #endif @@ -370,6 +382,10 @@ namespace openvpn { LinkImpl::Base::protocol::endpoint server_endpoint; bool halt; bool stop_requeueing; + +#ifdef OPENVPN_TLS_LINK + SSLFactoryAPI::Ptr ssl_factory; +#endif }; inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp index 2350c92..27c85ea 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp @@ -266,7 +266,7 @@ namespace openvpn { OPENVPN_LOG("Contacting " << server_endpoint << " via UDP"); parent->transport_wait(); socket.open(server_endpoint.protocol()); -#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP) + if (config->socket_protect) { if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) @@ -277,7 +277,7 @@ namespace openvpn { return; } } -#endif + socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { OPENVPN_ASYNC_HANDLER; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp index 3a79b5c..7129730 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -182,9 +183,22 @@ namespace openvpn { } catch (const std::exception& e) { + Error::Type err = Error::TCP_SIZE_ERROR; + const char *msg = "TCP_SIZE_ERROR"; + // if exception is an ExceptionCode, translate the code + // to return status string + { + const ExceptionCode *ec = dynamic_cast(&e); + if (ec && ec->code_defined()) + { + err = ec->code(); + msg = ec->what(); + } + } + OPENVPN_LOG_TCPLINK_ERROR("TCP packet extract exception: " << e.what()); - self->stats->error(Error::TCP_SIZE_ERROR); - self->read_handler->tcp_error_handler("TCP_SIZE_ERROR"); + self->stats->error(err); + self->read_handler->tcp_error_handler(msg); self->stop(); } }); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/persist/tunpersist.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/persist/tunpersist.hpp index dc8d074..eaf1225 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/persist/tunpersist.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/persist/tunpersist.hpp @@ -31,7 +31,7 @@ namespace openvpn { // TunPersistTemplate adds persistence capabilities onto TunWrapTemplate, // in order to implement logic for the persist-tun directive. - template + template class TunPersistTemplate : public TunWrapTemplate { public: @@ -47,7 +47,7 @@ namespace openvpn { } // Current persisted state - const TunProp::State::Ptr& state() const + const STATE& state() const { return state_; } @@ -124,7 +124,7 @@ namespace openvpn { // Possibly save tunnel fd/handle, state, and options. bool persist_tun_state(const typename SCOPED_OBJ::base_type obj, - const TunProp::State::Ptr& state) + const STATE& state) { if (!enable_persistence_ || !use_persisted_tun_) { @@ -151,7 +151,7 @@ namespace openvpn { const bool enable_persistence_; TunBuilderBase * const tb_; - TunProp::State::Ptr state_; + STATE state_; std::string options_; TunBuilderCapture::Ptr copt_; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/clientconfig.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/clientconfig.hpp new file mode 100644 index 0000000..613e568 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/clientconfig.hpp @@ -0,0 +1,99 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace openvpn { + namespace TunWin { + + // These types manage the underlying TAP driver HANDLE + typedef openvpn_io::windows::stream_handle TAPStream; + typedef ScopedAsioStream ScopedTAPStream; + struct TunPersistState { + TunProp::State::Ptr state; + RingBuffer::Ptr ring_buffer; + + void reset() + { + state.reset(); + ring_buffer.reset(); + } + }; + typedef TunPersistTemplate TunPersist; + + class ClientConfig : public TunClientFactory + { + friend class Client; // accesses wfp + + public: + typedef RCPtr Ptr; + + TunProp::Config tun_prop; + int n_parallel = 8; // number of parallel async reads on tun socket + bool wintun = false; + + Frame::Ptr frame; + SessionStats::Ptr stats; + + Stop* stop = nullptr; + + TunPersist::Ptr tun_persist; + + TunWin::SetupFactory::Ptr tun_setup_factory; + + TunWin::SetupBase::Ptr new_setup_obj(openvpn_io::io_context& io_context) + { + if (tun_setup_factory) + return tun_setup_factory->new_setup_obj(io_context, wintun); + else + return new TunWin::Setup(io_context, wintun); + } + + static Ptr new_obj() + { + return new ClientConfig; + } + + virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, + TunClientParent& parent, + TransportClient* transcli) override; + + virtual void finalize(const bool disconnected) override + { + if (disconnected) + tun_persist.reset(); + } + + virtual bool layer_2_supported() const override + { + return true; + } + }; + } +} + diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/setupbase.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/setupbase.hpp index 6c8a29b..7b10762 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/setupbase.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/setupbase.hpp @@ -35,6 +35,8 @@ #include #include +#include + namespace openvpn { namespace TunWin { struct SetupBase : public DestructorBase @@ -46,7 +48,8 @@ namespace openvpn { virtual HANDLE establish(const TunBuilderCapture& pull, const std::wstring& openvpn_app_path, Stop* stop, - std::ostream& os) = 0; + std::ostream& os, + RingBuffer::Ptr rings) = 0; virtual bool l2_ready(const TunBuilderCapture& pull) = 0; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tuncli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tuncli.hpp index 8b7b2ab..f2b301a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tuncli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tuncli.hpp @@ -38,12 +38,10 @@ #include #include #include +#include #include #include - -#define OPENVPN_WINTUN_START_PADDING_LEN 12 -#define OPENVPN_WINTUN_PACKET_SIZE_LEN 4 -#define OPENVPN_WINTUN_PACKET_ALIGN 16 +#include namespace openvpn { namespace TunWin { @@ -71,9 +69,8 @@ namespace openvpn { const bool retain_stream, ReadHandler read_handler, const Frame::Ptr& frame, - const SessionStats::Ptr& stats, - const bool wintun) - : Base(read_handler, frame, stats, wintun ? Frame::READ_WINTUN : Frame::READ_TUN) + const SessionStats::Ptr& stats) + : Base(read_handler, frame, stats, Frame::READ_TUN) { Base::name_ = name; Base::retain_stream = retain_stream; @@ -81,60 +78,6 @@ namespace openvpn { } }; - // These types manage the underlying TAP driver HANDLE - typedef openvpn_io::windows::stream_handle TAPStream; - typedef ScopedAsioStream ScopedTAPStream; - typedef TunPersistTemplate TunPersist; - - class ClientConfig : public TunClientFactory - { - friend class Client; // accesses wfp - - public: - typedef RCPtr Ptr; - - TunProp::Config tun_prop; - int n_parallel = 8; // number of parallel async reads on tun socket - bool wintun = false; // wintun may return up to 256 packets - - Frame::Ptr frame; - SessionStats::Ptr stats; - - Stop* stop = nullptr; - - TunPersist::Ptr tun_persist; - - TunWin::SetupFactory::Ptr tun_setup_factory; - - TunWin::SetupBase::Ptr new_setup_obj(openvpn_io::io_context& io_context) - { - if (tun_setup_factory) - return tun_setup_factory->new_setup_obj(io_context, wintun); - else - return new TunWin::Setup(io_context, wintun); - } - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) override; - - virtual void finalize(const bool disconnected) override - { - if (disconnected) - tun_persist.reset(); - } - - virtual bool layer_2_supported() const override - { - return true; - } - }; - class Client : public TunClient { friend class ClientConfig; // calls constructor @@ -161,7 +104,7 @@ namespace openvpn { // Check if persisted tun session matches properties of to-be-created session if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) { - state = tun_persist->state(); + state = tun_persist->state().state; OPENVPN_LOG("TunPersist: reused tun context"); } else @@ -192,14 +135,14 @@ namespace openvpn { { std::ostringstream os; auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - th = tun_setup->establish(*po, Win::module_name(), config->stop, os); + th = tun_setup->establish(*po, Win::module_name(), config->stop, os, NULL); } // create ASIO wrapper for HANDLE TAPStream* ts = new TAPStream(io_context, th); // persist tun settings state - if (tun_persist->persist_tun_state(ts, state)) + if (tun_persist->persist_tun_state(ts, { state, nullptr })) OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); // setup handler for external tun close @@ -225,8 +168,7 @@ namespace openvpn { true, this, config->frame, - config->stats, - config->wintun)); + config->stats)); impl->start(config->n_parallel); if (!dhcp_capture) @@ -319,19 +261,6 @@ namespace openvpn { if (dhcp_capture) dhcp_inspect(buf); - if (config->wintun) - { - // end padding - auto packet_size = buf.size(); - auto end_padding_size = OPENVPN_WINTUN_PACKET_ALIGN - - (buf.size() & (OPENVPN_WINTUN_PACKET_ALIGN - 1)); - buf.write(wintun_padding, end_padding_size); - - // start padding and size - buf.prepend(wintun_padding, OPENVPN_WINTUN_START_PADDING_LEN); - buf.prepend((unsigned char *)&packet_size, OPENVPN_WINTUN_PACKET_SIZE_LEN); - } - return impl->write(buf); } else @@ -343,34 +272,7 @@ namespace openvpn { void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl { - if (config->wintun) - { - // we might receive up to 256 packets - while (pfp->buf.size() > 0) - { - // parse wintun encapsulation - auto packet_size = *(std::uint32_t*)pfp->buf.c_data(); - pfp->buf.advance(OPENVPN_WINTUN_PACKET_SIZE_LEN); - pfp->buf.advance(OPENVPN_WINTUN_START_PADDING_LEN); - - // extract individual packet - frame_context.prepare(wintun_packet); - wintun_packet.write(pfp->buf.c_data(), packet_size); - - parent.tun_recv(wintun_packet); - - // skip to the next packet - pfp->buf.advance(packet_size); - - auto padding = (OPENVPN_WINTUN_PACKET_ALIGN - - (packet_size & (OPENVPN_WINTUN_PACKET_ALIGN - 1))) % OPENVPN_WINTUN_PACKET_ALIGN; - pfp->buf.advance(padding); - } - } - else - { - parent.tun_recv(pfp->buf); - } + parent.tun_recv(pfp->buf); #ifdef OPENVPN_DEBUG_TAPWIN tap_process_logging(); @@ -487,8 +389,6 @@ namespace openvpn { std::unique_ptr dhcp_capture; AsioTimer l2_timer; - unsigned char wintun_padding[OPENVPN_WINTUN_PACKET_ALIGN] = {}; - BufferAllocated wintun_packet; Frame::Context& frame_context; bool halt; @@ -498,7 +398,10 @@ namespace openvpn { TunClientParent& parent, TransportClient* transcli) { - return TunClient::Ptr(new Client(io_context, this, parent)); + if (wintun) + return TunClient::Ptr(new WintunClient(io_context, this, parent)); + else + return TunClient::Ptr(new Client(io_context, this, parent)); } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tunsetup.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tunsetup.hpp index c902572..69120c2 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tunsetup.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tunsetup.hpp @@ -68,7 +68,8 @@ namespace openvpn { virtual HANDLE establish(const TunBuilderCapture& pull, const std::wstring& openvpn_app_path, Stop* stop, - std::ostream& os) override // defined by SetupBase + std::ostream& os, + RingBuffer::Ptr ring_buffer) override // defined by SetupBase { // close out old remove cmds, if they exist destroy(os); @@ -104,7 +105,7 @@ namespace openvpn { switch (pull.layer()) { case Layer::OSI_LAYER_3: - adapter_config(th(), openvpn_app_path, tap, wintun, pull, false, *add_cmds, *remove_cmds, os); + adapter_config(th(), openvpn_app_path, tap, pull, false, *add_cmds, *remove_cmds, os); break; case Layer::OSI_LAYER_2: adapter_config_l2(th(), openvpn_app_path, tap, pull, *add_cmds, *remove_cmds, os); @@ -123,6 +124,9 @@ namespace openvpn { if (pull.layer() == Layer::OSI_LAYER_2) l2_state.reset(new L2State(tap, openvpn_app_path)); + if (ring_buffer) + register_rings(th(), ring_buffer); + return th.release(); } @@ -162,7 +166,7 @@ namespace openvpn { { Win::ScopedHANDLE nh; ActionList::Ptr add_cmds(new ActionList()); - adapter_config(nh(), l2s->openvpn_app_path, l2s->tap, wintun, pull, true, *add_cmds, *remove_cmds, os); + adapter_config(nh(), l2s->openvpn_app_path, l2s->tap, pull, true, *add_cmds, *remove_cmds, os); add_cmds->execute(os); } } @@ -200,6 +204,20 @@ namespace openvpn { destroy(os); } + static void add_bypass_route(const std::string& route, + bool ipv6, + ActionList& add_cmds, + ActionList& remove_cmds_bypass_gw) + { + const Util::DefaultGateway gw; + + if (!ipv6) + { + add_cmds.add(new WinCmd("netsh interface ip add route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active")); + remove_cmds_bypass_gw.add(new WinCmd("netsh interface ip delete route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active")); + } + } + private: struct L2State { @@ -250,12 +268,36 @@ namespace openvpn { int indices[2] = {0, 0}; }; + void register_rings(HANDLE handle, RingBuffer::Ptr ring_buffer) + { + TUN_REGISTER_RINGS rings; + + ZeroMemory(&rings, sizeof(rings)); + + rings.receive.ring = ring_buffer->receive_ring(); + rings.receive.tail_moved = ring_buffer->receive_ring_tail_moved(); + rings.receive.ring_size = sizeof(rings.receive.ring->data); + + rings.send.ring = ring_buffer->send_ring(); + rings.send.tail_moved = ring_buffer->send_ring_tail_moved(); + rings.send.ring_size = sizeof(rings.send.ring->data); + + { + Win::Impersonate imp(true); + + if (!DeviceIoControl(handle, TUN_IOCTL_REGISTER_RINGS, &rings, sizeof(rings), NULL, NULL, NULL, NULL)) + { + const Win::LastError err; + throw ErrorCode(Error::TUN_REGISTER_RINGS_ERROR, true, "Error registering ring buffers: " + err.message()); + } + } + } + #if _WIN32_WINNT >= 0x0600 // Configure TAP adapter on Vista and higher void adapter_config(HANDLE th, const std::wstring& openvpn_app_path, const Util::TapNameGuidPair& tap, - bool wintun, const TunBuilderCapture& pull, const bool l2_post, ActionList& create, diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/wintun.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/wintun.hpp new file mode 100644 index 0000000..cd7e52f --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/wintun.hpp @@ -0,0 +1,318 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace openvpn { + namespace TunWin { + + class WintunClient : public TunClient + { + typedef RCPtr Ptr; + + public: + WintunClient(openvpn_io::io_context& io_context_arg, + ClientConfig* config_arg, + TunClientParent& parent_arg) + : io_context(io_context_arg), + config(config_arg), + parent(parent_arg), + state(new TunProp::State()), + frame(config_arg->frame) + { + } + + // Inherited via TunClient + void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override + { + halt = false; + if (config->tun_persist) + tun_persist = config->tun_persist; // long-term persistent + else + tun_persist.reset(new TunPersist(false, false, nullptr)); // short-term + + try { + + const IP::Addr server_addr = transcli.server_endpoint_addr(); + + // Check if persisted tun session matches properties of to-be-created session + if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) + { + state = tun_persist->state().state; + ring_buffer = tun_persist->state().ring_buffer; + OPENVPN_LOG("TunPersist: reused tun context"); + } + else + { + // notify parent + parent.tun_pre_tun_config(); + + // close old TAP handle if persisted + tun_persist->close(); + + // parse pushed options + TunBuilderCapture::Ptr po(new TunBuilderCapture()); + TunProp::configure_builder(po.get(), + state.get(), + config->stats.get(), + server_addr, + config->tun_prop, + opt, + nullptr, + false); + OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); + + // create new tun setup object + tun_setup = config->new_setup_obj(io_context); + + ring_buffer.reset(new RingBuffer(io_context)); + + // open/config TAP + HANDLE th; + { + std::ostringstream os; + auto os_print = Cleanup([&os]() { OPENVPN_LOG_STRING(os.str()); }); + th = tun_setup->establish(*po, Win::module_name(), config->stop, os, ring_buffer); + } + + // create ASIO wrapper for HANDLE + TAPStream* ts = new TAPStream(io_context, th); + + // persist tun settings state + if (tun_persist->persist_tun_state(ts, { state, ring_buffer })) + OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); + + // enable tun_setup destructor + tun_persist->add_destructor(tun_setup); + + // assert ownership over TAP device handle + tun_setup->confirm(); + } + + openvpn_io::post(io_context, [self=Ptr(this)](){ + self->read(); + }); + + parent.tun_connected(); // signal that we are connected + } + catch (const std::exception& e) + { + stop(); + Error::Type err = Error::TUN_SETUP_FAILED; + const ExceptionCode* ec = dynamic_cast(&e); + if (ec && ec->code_defined()) + err = ec->code(); + parent.tun_error(err, e.what()); + } + } + + void stop() override + { + if (!halt) + { + halt = true; + + tun_persist.reset(); + } + } + + void set_disconnect() override + { + + } + + bool tun_send(BufferAllocated& buf) override + { + TUN_RING* receive_ring = ring_buffer->receive_ring(); + + ULONG head = receive_ring->head.load(std::memory_order_acquire); + if (head > WINTUN_RING_CAPACITY) + { + if (head == 0xFFFFFFFF) + parent.tun_error(Error::TUN_WRITE_ERROR, "invalid ring head/tail or bogus packet received"); + return false; + } + + ULONG tail = receive_ring->tail.load(std::memory_order_acquire); + if (tail >= WINTUN_RING_CAPACITY) + return false; + + ULONG aligned_packet_size = packet_align(sizeof(TUN_PACKET_HEADER) + buf.size()); + ULONG buf_space = wrap(head - tail - WINTUN_PACKET_ALIGN); + if (aligned_packet_size > buf_space) + { + OPENVPN_LOG("ring is full"); + return false; + } + + // copy packet size and data into ring + TUN_PACKET* packet = (TUN_PACKET*)& receive_ring->data[tail]; + packet->size = buf.size(); + std::memcpy(packet->data, buf.data(), buf.size()); + + // move ring tail + receive_ring->tail.store(wrap(tail + aligned_packet_size), std::memory_order_release); + if (receive_ring->alertable.load(std::memory_order_acquire) != 0) + SetEvent(ring_buffer->receive_ring_tail_moved()); + + return true; + } + + std::string tun_name() const override + { + return "wintun"; + } + + std::string vpn_ip4() const override + { + if (state->vpn_ip4_addr.specified()) + return state->vpn_ip4_addr.to_string(); + else + return ""; + } + + std::string vpn_ip6() const override + { + if (state->vpn_ip6_addr.specified()) + return state->vpn_ip6_addr.to_string(); + else + return ""; + } + + std::string vpn_gw4() const override + { + if (state->vpn_ip4_gw.specified()) + return state->vpn_ip4_gw.to_string(); + else + return ""; + } + + std::string vpn_gw6() const override + { + if (state->vpn_ip6_gw.specified()) + return state->vpn_ip6_gw.to_string(); + else + return ""; + } + + private: + void read() + { + TUN_RING* send_ring = ring_buffer->send_ring(); + + if (halt) + return; + + ULONG head = send_ring->head.load(std::memory_order_acquire); + if (head >= WINTUN_RING_CAPACITY) + { + parent.tun_error(Error::TUN_ERROR, "ring head exceeds ring capacity"); + return; + } + + ULONG tail = send_ring->tail.load(std::memory_order_acquire); + if (tail >= WINTUN_RING_CAPACITY) + { + parent.tun_error(Error::TUN_ERROR, "ring tail exceeds ring capacity"); + return; + } + + while (true) + { + // tail has moved? + if (head == tail) + { + ring_buffer->send_tail_moved_asio_event().async_wait([self = Ptr(this)](const openvpn_io::error_code& error) { + if (!error) + self->read(); + else + { + if (!self->halt) + self->parent.tun_error(Error::TUN_ERROR, "error waiting on ring send tail moved"); + } + }); + return; + } + + // read buffer content + ULONG content_len = wrap(tail - head); + if (content_len < sizeof(TUN_PACKET_HEADER)) + { + parent.tun_error(Error::TUN_ERROR, "incomplete packet header in send ring"); + return; + } + + TUN_PACKET* packet = (TUN_PACKET *)&send_ring->data[head]; + if (packet->size > WINTUN_MAX_PACKET_SIZE) + { + parent.tun_error(Error::TUN_ERROR, "packet too big in send ring"); + return; + } + + ULONG aligned_packet_size = packet_align(sizeof(TUN_PACKET_HEADER) + packet->size); + if (aligned_packet_size > content_len) + { + parent.tun_error(Error::TUN_ERROR, "incomplete packet in send ring"); + return; + } + + frame->prepare(Frame::READ_TUN, buf); + + buf.write(packet->data, packet->size); + + head = wrap(head + aligned_packet_size); + send_ring->head.store(head, std::memory_order_release); + + parent.tun_recv(buf); + + if (halt) + return; + } + } + + struct TUN_PACKET_HEADER + { + uint32_t size; + }; + + struct TUN_PACKET + { + uint32_t size; + UCHAR data[WINTUN_MAX_PACKET_SIZE]; + }; + + ULONG packet_align(ULONG size) + { + return (size + (WINTUN_PACKET_ALIGN - 1)) & ~(WINTUN_PACKET_ALIGN - 1); + } + + ULONG wrap(ULONG value) + { + return value & (WINTUN_RING_CAPACITY - 1); + } + + openvpn_io::io_context& io_context; + TunPersist::Ptr tun_persist; // contains the TAP device HANDLE + ClientConfig::Ptr config; + TunClientParent& parent; + TunProp::State::Ptr state; + TunWin::SetupBase::Ptr tun_setup; + + TUN_RING* receive_ring = nullptr; + TUN_RING* send_ring = nullptr; + + BufferAllocated buf; + + Frame::Ptr frame; + + bool halt = false; + + ScopedHANDLE driver_handle; + + RingBuffer::Ptr ring_buffer; + }; + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/ringbuffer.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/ringbuffer.hpp new file mode 100644 index 0000000..bae3a79 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/ringbuffer.hpp @@ -0,0 +1,172 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . +// + +#pragma once + +#include + +#include +#include + +#include +#include +#include +#include + +#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) +#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) + +#define WINTUN_RING_CAPACITY 0x800000 +#define WINTUN_RING_TRAILING_BYTES 0x10000 +#define WINTUN_RING_FRAMING_SIZE 12 +#define WINTUN_MAX_PACKET_SIZE 0xffff +#define WINTUN_PACKET_ALIGN 4 + +namespace openvpn +{ + namespace TunWin + { + struct TUN_RING { + std::atomic_ulong head; + std::atomic_ulong tail; + std::atomic_long alertable; + UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES + WINTUN_RING_FRAMING_SIZE]; + }; + + struct TUN_REGISTER_RINGS + { + struct + { + ULONG ring_size; + TUN_RING* ring; + HANDLE tail_moved; + } send, receive; + }; + + typedef openvpn_io::windows::object_handle AsioEvent; + + class RingBuffer : public RC + { + public: + typedef RCPtr Ptr; + + RingBuffer(openvpn_io::io_context& io_context) + : send_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)), + receive_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)), + send_tail_moved_asio_event_(io_context) + { + // sanity checks + static_assert((sizeof(TUN_RING) - sizeof(TUN_RING::data)) == 12, "sizeof(TUN_RING) is expected to be 12"); +#if !defined(ATOMIC_LONG_LOCK_FREE) || (ATOMIC_LONG_LOCK_FREE != 2) +#error Atomic long is expected to be always lock-free +#endif + + send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); + receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); + send_tail_moved_asio_event_.assign(send_ring_tail_moved_()); + } + + RingBuffer(openvpn_io::io_context& io_context, + HANDLE client_process, + const std::string& send_ring_hmem_hex, + const std::string& receive_ring_hmem_hex, + const std::string& send_ring_tail_moved_hex, + const std::string& receive_ring_tail_moved_hex) + : send_tail_moved_asio_event_(io_context) + { + HANDLE remote_handle = BufHex::parse(send_ring_hmem_hex, "send_ring_hmem"); + HANDLE handle; + DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + send_ring_hmem.reset(handle); + + remote_handle = BufHex::parse(receive_ring_hmem_hex, "receive_ring_hmem"); + DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + receive_ring_hmem.reset(handle); + + remote_handle = BufHex::parse(send_ring_tail_moved_hex, "send_ring_tail_moved"); + DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + send_ring_tail_moved_.reset(handle); + + remote_handle = BufHex::parse(receive_ring_tail_moved_hex, "receive_ring_tail_moved"); + DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + receive_ring_tail_moved_.reset(handle); + + send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); + receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); + } + + RingBuffer(RingBuffer const&) = delete; + RingBuffer& operator=(RingBuffer const&) = delete; + + ~RingBuffer() + { + UnmapViewOfFile(send_ring_); + UnmapViewOfFile(receive_ring_); + } + + HANDLE send_ring_tail_moved() + { + return send_ring_tail_moved_(); + } + + HANDLE receive_ring_tail_moved() + { + return receive_ring_tail_moved_(); + } + + TUN_RING* send_ring() + { + return send_ring_; + } + + TUN_RING* receive_ring() + { + return receive_ring_; + } + + AsioEvent& send_tail_moved_asio_event() + { + return send_tail_moved_asio_event_; + } + +#ifdef HAVE_JSON + void serialize(Json::Value& json) + { + json["send_ring_hmem"] = BufHex::render(send_ring_hmem()); + json["receive_ring_hmem"] = BufHex::render(receive_ring_hmem()); + json["send_ring_tail_moved"] = BufHex::render(send_ring_tail_moved()); + json["receive_ring_tail_moved"] = BufHex::render(receive_ring_tail_moved()); + } +#endif + + protected: + Win::ScopedHANDLE send_ring_hmem; + Win::ScopedHANDLE receive_ring_hmem; + Win::Event send_ring_tail_moved_{FALSE}; + Win::Event receive_ring_tail_moved_{FALSE}; + AsioEvent send_tail_moved_asio_event_; + + TUN_RING* send_ring_ = nullptr; + TUN_RING* receive_ring_ = nullptr; + }; + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/tunutil.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/tunutil.hpp index 6b93056..12f4563 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/tunutil.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/tunutil.hpp @@ -35,6 +35,12 @@ #include // for IPv6 #include // for impersonating as LocalSystem + +#include +#include +#include +#include + #include #include #include @@ -342,93 +348,123 @@ namespace openvpn { } }; - inline HANDLE impersonate_as_system() + struct DeviceInstanceIdInterfacePair { - HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token, file_handle; - PROCESSENTRY32 entry = {}; - entry.dwSize = sizeof(PROCESSENTRY32); - BOOL ret; - DWORD pid = 0; - TOKEN_PRIVILEGES privileges = {}; - privileges.PrivilegeCount = 1; - privileges.Privileges->Attributes = SE_PRIVILEGE_ENABLED; + std::string net_cfg_instance_id; + std::string device_interface_list; + }; - if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid)) - return INVALID_HANDLE_VALUE; - if (!ImpersonateSelf(SecurityImpersonation)) - return INVALID_HANDLE_VALUE; - if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token)) - { - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) - { - CloseHandle(thread_token); - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - CloseHandle(thread_token); + class DevInfoSetHelper + { + public: + DevInfoSetHelper() + { + handle = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); + } - process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (process_snapshot == INVALID_HANDLE_VALUE) - { - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) - { - if (!_stricmp(entry.szExeFile, "winlogon.exe")) - { - pid = entry.th32ProcessID; - break; - } - } - CloseHandle(process_snapshot); - if (!pid) - { - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } + bool is_valid() + { + return handle != INVALID_HANDLE_VALUE; + } - winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!winlogon_process) - { - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } + operator HDEVINFO() + { + return handle; + } - if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token)) - { - CloseHandle(winlogon_process); - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - CloseHandle(winlogon_process); + ~DevInfoSetHelper() + { + if (is_valid()) + { + SetupDiDestroyDeviceInfoList(handle); + } + } - if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) - { - CloseHandle(winlogon_token); - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - CloseHandle(winlogon_token); + private: + HDEVINFO handle; + }; - if (!SetThreadToken(NULL, duplicated_token)) - { - CloseHandle(duplicated_token); - RevertToSelf(); - return INVALID_HANDLE_VALUE; - } - CloseHandle(duplicated_token); - } + struct DeviceInstanceIdInterfaceList : public std::vector + { + DeviceInstanceIdInterfaceList() + { + DevInfoSetHelper device_info_set; + if (!device_info_set.is_valid()) + return; + + for (DWORD i = 0;; ++i) + { + SP_DEVINFO_DATA dev_info_data; + ZeroMemory(&dev_info_data, sizeof(SP_DEVINFO_DATA)); + dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + BOOL res = SetupDiEnumDeviceInfo(device_info_set, i, &dev_info_data); + if (!res) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + else + continue; + } + + Win::RegKey regkey; + *regkey.ref() = SetupDiOpenDevRegKey(device_info_set, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); + if (!regkey.defined()) + continue; + + std::string str_net_cfg_instance_id; + + DWORD size; + LONG status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, NULL, &size); + if (status != ERROR_SUCCESS) + continue; + BufferAllocatedType buf_net_cfg_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); + + status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, (LPBYTE)buf_net_cfg_inst_id.data(), &size); + if (status == ERROR_SUCCESS) + { + buf_net_cfg_inst_id.data()[size - 1] = '\0'; + str_net_cfg_instance_id = std::string(buf_net_cfg_inst_id.data()); + } + else + continue; + + res = SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, NULL, 0, &size); + if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + continue; + + BufferAllocatedType buf_dev_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); + if (!SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, buf_dev_inst_id.data(), size, &size)) + continue; + buf_dev_inst_id.set_size(size); + + ULONG dev_interface_list_size = 0; + CONFIGRET cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size, + (LPGUID)& GUID_DEVINTERFACE_NET, + buf_dev_inst_id.data(), + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + + if (cr != CR_SUCCESS) + continue; + + BufferAllocatedType buf_dev_iface_list(dev_interface_list_size, BufferAllocated::CONSTRUCT_ZERO); + cr = CM_Get_Device_Interface_List((LPGUID)& GUID_DEVINTERFACE_NET, buf_dev_inst_id.data(), + buf_dev_iface_list.data(), + dev_interface_list_size, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (cr != CR_SUCCESS) + continue; + + DeviceInstanceIdInterfacePair pair; + pair.net_cfg_instance_id = str_net_cfg_instance_id; + pair.device_interface_list = std::string(buf_dev_iface_list.data()); + push_back(pair); + } + } + }; // given a TAP GUID, form the pathname of the TAP device node - inline std::string tap_path(const TapNameGuidPair& tap, bool wintun) + inline std::string tap_path(const TapNameGuidPair& tap) { - if (wintun) - return std::string(USERMODEDEVICEDIR) + "WINTUN" + std::to_string(tap.net_luid_index); - else return std::string(USERMODEDEVICEDIR) + tap.guid + std::string(TAP_WIN_SUFFIX); } @@ -440,31 +476,49 @@ namespace openvpn { { Win::ScopedHANDLE hand; + std::unique_ptr inst_id_interface_list; + if (wintun) + inst_id_interface_list.reset(new DeviceInstanceIdInterfaceList()); + // iterate over list of TAP adapters on system for (TapNameGuidPairList::const_iterator i = guids.begin(); i != guids.end(); i++) { const TapNameGuidPair& tap = *i; - const std::string path = tap_path(tap, wintun); - // wintun device can be only opened under LocalSystem account + std::string path; + if (wintun) - impersonate_as_system(); - - hand.reset(::CreateFileA(path.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, /* was: FILE_SHARE_READ */ - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - 0)); - if (wintun) - RevertToSelf(); - - if (hand.defined()) { - used = tap; - path_opened = path; - break; + for (const auto& inst_id_interface : *inst_id_interface_list) + { + if (inst_id_interface.net_cfg_instance_id != tap.guid) + continue; + + path = inst_id_interface.device_interface_list; + break; + } + } + else + { + path = tap_path(tap); + } + + if (path.length() > 0) + { + hand.reset(::CreateFileA(path.c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, /* was: FILE_SHARE_READ */ + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0)); + + if (hand.defined()) + { + used = tap; + path_opened = path; + break; + } } } return hand.release(); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/winproxy.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/winproxy.hpp index 6a1f78e..c1011fa 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/winproxy.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/winproxy.hpp @@ -43,7 +43,7 @@ namespace openvpn { void set_proxy(bool del) override { - ImpersonateAsUser imp; + Impersonate imp{false}; LONG status; RegKey hkcu; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/call.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/call.hpp index 54c2ee7..2e965e8 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/call.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/call.hpp @@ -37,6 +37,9 @@ namespace openvpn { OPENVPN_EXCEPTION(win_call); + // console codepage, used to decode output + int console_cp = ::GetOEMCP(); + inline std::string call(const std::string& cmd) { // split command name from args @@ -145,6 +148,13 @@ namespace openvpn { out += std::string(outbuf.get(), 0, dwRead); } + // decode output using console codepage, convert to utf16 + UTF16 utf16output(Win::utf16(out, console_cp)); + + // re-encode utf16 to utf8 + UTF8 utf8output(Win::utf8(utf16output.get())); + out.assign(utf8output.get()); + // wait for child to exit if (::WaitForSingleObject(process_hand(), INFINITE) == WAIT_FAILED) throw win_call("WaitForSingleObject failed on child process handle"); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/event.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/event.hpp new file mode 100644 index 0000000..f51cf06 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/event.hpp @@ -0,0 +1,108 @@ +// OpenVPN -- An application to securely tunnel IP networks +// over a single port, with support for SSL/TLS-based +// session authentication and key exchange, +// packet encryption, packet authentication, and +// packet compression. +// +// Copyright (C) 2012-2017 OpenVPN Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License Version 3 +// as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program in the COPYING file. +// If not, see . +// + +#ifndef OPENVPN_WIN_EVENT_H +#define OPENVPN_WIN_EVENT_H + +#include + +#include + +#include +#include +#include + +namespace openvpn { + namespace Win { + + // Wrap a standard Windows Event object + class Event + { + public: + explicit Event(BOOL manual_reset=TRUE) + { + event.reset(::CreateEvent(NULL, manual_reset, FALSE, NULL)); + if (!event.defined()) + { + const Win::LastError err; + OPENVPN_THROW_EXCEPTION("Win::Event: cannot create Windows event: " << err.message()); + } + } + + std::string duplicate_local() + { + HANDLE new_handle; + if (!::DuplicateHandle(GetCurrentProcess(), + event(), + GetCurrentProcess(), + &new_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) + { + const Win::LastError err; + OPENVPN_THROW_EXCEPTION("Win::Event: DuplicateHandle failed: " << err.message()); + } + return BufHex::render(new_handle); + } + + void signal_event() + { + if (event.defined()) + { + ::SetEvent(event()); + event.close(); + } + } + + void release_event() + { + event.close(); + } + + HANDLE operator()() const + { + return event(); + } + + void reset(HANDLE h) + { + event.reset(h); + } + + private: + ScopedHANDLE event; + }; + + // Windows event object that automatically signals in the destructor + struct DestroyEvent : public Event + { + ~DestroyEvent() + { + signal_event(); + } + }; + + } +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/impersonate.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/impersonate.hpp index ea7b026..8cf3fd3 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/impersonate.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/impersonate.hpp @@ -29,19 +29,120 @@ namespace openvpn { namespace Win { - class ImpersonateAsUser { + + class Impersonate + { public: - ImpersonateAsUser() : local_system(is_local_system_()) + explicit Impersonate(bool as_local_system) + : local_system_(is_local_system_()) { - if (local_system) - OPENVPN_LOG("ImpersonateAsUser: running under SYSTEM account, need to impersonate"); + if (as_local_system) + { + if (local_system_) + OPENVPN_LOG("ImpersonateAsSystem: running under SYSTEM account, no need to impersonate"); + else + impersonate_as_local_system(); + } else { - OPENVPN_LOG("ImpersonateAsUser: running under user account, no need to impersonate"); + if (local_system_) + impersonate_as_user(); + else + OPENVPN_LOG("ImpersonateAsUser: running under user account, no need to impersonate"); + } + } + + ~Impersonate() + { + if (impersonated) + { + if (!RevertToSelf()) + { + const Win::LastError err; + OPENVPN_LOG("Impersonate: RevertToSelf() failed: " << err.message()); + } + } + } + + bool is_local_system() const + { + return local_system_; + } + + private: + void impersonate_as_local_system() + { + HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token, file_handle; + PROCESSENTRY32 entry = {}; + entry.dwSize = sizeof(PROCESSENTRY32); + BOOL ret; + DWORD pid = 0; + TOKEN_PRIVILEGES privileges = {}; + privileges.PrivilegeCount = 1; + privileges.Privileges->Attributes = SE_PRIVILEGE_ENABLED; + + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid)) + return; + + if (!ImpersonateSelf(SecurityImpersonation)) + return; + + impersonated = true; + + if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token)) + return; + if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) + { + CloseHandle(thread_token); return; } + CloseHandle(thread_token); - DWORD sessId = WTSGetActiveConsoleSessionId(); + process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (process_snapshot == INVALID_HANDLE_VALUE) + return; + + for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) + { + if (!_stricmp(entry.szExeFile, "winlogon.exe")) + { + pid = entry.th32ProcessID; + break; + } + } + CloseHandle(process_snapshot); + if (!pid) + return; + + winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!winlogon_process) + return; + + if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token)) + { + CloseHandle(winlogon_process); + return; + } + CloseHandle(winlogon_process); + + if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) + { + CloseHandle(winlogon_token); + return; + } + CloseHandle(winlogon_token); + + if (!SetThreadToken(NULL, duplicated_token)) + { + CloseHandle(duplicated_token); + return; + } + CloseHandle(duplicated_token); + } + + void impersonate_as_user() + { + DWORD sessId = WTSGetActiveConsoleSessionId(); if (sessId == 0xFFFFFFFF) { const Win::LastError err; @@ -76,23 +177,6 @@ namespace openvpn { OPENVPN_LOG("ImpersonateAsUser: impersonated as " << uname); } - ~ImpersonateAsUser() { - if (impersonated) - { - if (!RevertToSelf()) - { - const Win::LastError err; - OPENVPN_LOG("ImpersonateAsUser: RevertToSelf() failed: " << err.message()); - } - } - } - - bool is_local_system() const - { - return local_system; - } - - private: // https://stackoverflow.com/a/4024388/227024 BOOL is_local_system_() const { @@ -129,8 +213,8 @@ namespace openvpn { return bSystem; } + bool local_system_ = false; bool impersonated = false; - bool local_system = false; }; } } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/scoped_handle.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/scoped_handle.hpp index bc67999..eb92f93 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/scoped_handle.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/scoped_handle.hpp @@ -87,10 +87,17 @@ namespace openvpn { { if (defined()) { - const BOOL ret = ::CloseHandle(handle); - //OPENVPN_LOG("**** SH CLOSE hand=" << handle << " ret=" << ret); - handle = nullptr; - return ret != 0; + __try + { + const BOOL ret = ::CloseHandle(handle); + //OPENVPN_LOG("**** SH CLOSE hand=" << handle << " ret=" << ret); + handle = nullptr; + return ret != 0; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return false; + } } else return true; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/unicode.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/unicode.hpp index 0dd9a19..7e0b764 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/unicode.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/win/unicode.hpp @@ -33,13 +33,14 @@ namespace openvpn { namespace Win { typedef std::unique_ptr UTF16; + typedef std::unique_ptr UTF8; OPENVPN_SIMPLE_EXCEPTION(win_utf16); - inline wchar_t* utf16(const std::string& str) + inline wchar_t* utf16(const std::string& str, int cp=CP_UTF8) { // first get output length (return value includes space for trailing nul) - const int len = ::MultiByteToWideChar(CP_UTF8, + const int len = ::MultiByteToWideChar(cp, 0, str.c_str(), -1, @@ -48,7 +49,7 @@ namespace openvpn { if (len <= 0) throw win_utf16(); UTF16 ret(new wchar_t[len]); - const int len2 = ::MultiByteToWideChar(CP_UTF8, + const int len2 = ::MultiByteToWideChar(cp, 0, str.c_str(), -1, @@ -63,6 +64,33 @@ namespace openvpn { { return ::wcslen(str); } + + inline char* utf8(wchar_t* str) + { + // first get output length (return value includes space for trailing nul) + const int len = ::WideCharToMultiByte(CP_UTF8, + 0, + str, + -1, + NULL, + 0, + NULL, + NULL); + if (len <= 0) + throw win_utf16(); + UTF8 ret(new char[len]); + const int len2 = ::WideCharToMultiByte(CP_UTF8, + 0, + str, + -1, + ret.get(), + len, + NULL, + NULL); + if (len != len2) + throw win_utf16(); + return ret.release(); + } } } #endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-all b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-all deleted file mode 100755 index dfab3af..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-all +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -# Build the entire core package as required by Android App -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -[ -z "$ECHO" ] && ECHO=0 - -if [ "$ECHO" -eq 0 ]; then - exec > $O3/android_build.log - exec 2>&1 -fi - -[ -z "$DEP_DIR" ] && export DEP_DIR=${O3}/deps -[ -z "$DL" ] && export DL=~/dl - -mkdir -p $DEP_DIR -mkdir -p $DL - -export NO_MOD_PATH=1 -. $O3/core/vars/android-sdk-path - -echo BUILD ANDROID SDK -$O3/core/scripts/android/build-sdk - -echo BUILD TOOLCHAIN -$O3/core/scripts/android/build-toolchain - -echo BUILD DEPS -cd $DEP_DIR -rm -rf asio* lz4* mbedtls* #lzo* boost* minicrypto openssl* polarssl* snappy* -echo "******* ASIO" -$O3/core/deps/asio/build-asio -echo "******* MBEDTLS" -$O3/core/scripts/android/build-mbedtls -echo "******* LZ4" -$O3/core/scripts/android/build-lz4 - -#echo "******* BOOST" -#$O3/core/scripts/android/build-boost -#echo "******* MINICRYPTO" -#$O3/core/scripts/android/build-minicrypto -#echo "******* OpenSSL" -#$O3/core/scripts/android/build-openssl-small -#echo "******* LZO" -#$O3/core/scripts/android/build-lzo -#echo "******* SNAPPY" -#$O3/core/scripts/android/build-snappy - -echo BUILD CORE LIBRARY -$O3/core/javacli/build-android - -echo DONE. diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost deleted file mode 100755 index e1536b8..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# Note: thread library may fail with PAGE_SIZE undefined. -# The pthread.h header makes reference to the PAGE_SIZE define however -# this only gets defined in which is not pulled in by any -# of the pthread.h includes. A google-suggested fix was to add -# #include , which does indeed work, but may not be the -# correct solution for all cases. -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf boost -mkdir boost -export LINK_MODE=static -export TARGETS="android-a8a android-a8a-dbg android-a7a android-a7a-dbg" -export SDK_PATH_SCRIPT=$O3/core/vars/android-sdk-path -$O3/core/deps/boost/build-boost -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lz4 b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lz4 deleted file mode 100755 index 113e6d4..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lz4 +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to the dependency build directory - exit 1 -fi - -. $O3/core/vars/android-sdk-path - -cd $DEP_DIR -rm -rf lz4 -mkdir lz4 - -TARGETS=${TARGETS:-android-a7a android-a8a android-x86} - -for target in $TARGETS; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lz4/build-lz4 -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo deleted file mode 100755 index 2d39e2e..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -. $O3/core/vars/android-sdk-path - -rm -rf lzo -mkdir lzo - -for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lzo/build-lzo -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-mbedtls b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-mbedtls deleted file mode 100755 index 7f5cf1a..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-mbedtls +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to the dependency build directory - exit 1 -fi - -. $O3/core/vars/android-sdk-path - -cd $DEP_DIR -rm -rf mbedtls -mkdir -p mbedtls - -# disable minicrypto for now -mini=0 - -TARGETS=${TARGETS:-android-a7a android-a8a android-x86} - -for target in $TARGETS; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target CMAKE_TARGET=android USE_MINICRYPTO=$mini MINICRYPTO_DIR=$(pwd)/minicrypto/minicrypto-$target $O3/core/deps/mbedtls/build-mbedtls - [ "$ANDROID_DBG_ONLY" = "1" ] && exit -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto deleted file mode 100755 index 3f613fd..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -. $O3/core/vars/android-sdk-path - -rm -rf minicrypto -mkdir minicrypto - -for target in android-a7a android-a7a-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/minicrypto/build-minicrypto -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-openssl-small b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-openssl-small deleted file mode 100755 index 5fdbcce..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-openssl-small +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -. $O3/core/deps/lib-versions -. $O3/core/vars/android-sdk-path -[ -z "$DL" ] && DL=~/Downloads -rm -rf openssl -mkdir openssl -for TARGET in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android-dbg android ; do - . $O3/core/vars/vars-$TARGET - export OPENSSL=$OPENSSL_VERSION - export DIST=$(pwd)/openssl-$PLATFORM - export BIN=$TC/bin - rm -rf $DIST - rm -rf $OPENSSL - tar xfz $DL/$OPENSSL.tar.gz - pushd $OPENSSL - OSSL_FLAGS="no-shared threads no-idea no-mdc2 no-rc5 no-engine no-comp no-hw no-ssl2 no-ssl3 no-zlib no-rc2 no-cast no-md2 no-ripemd no-camellia no-seed no-krb5 no-socks no-ecdsa no-ec no-ecdh no-md2 no-whirlpool no-dsa no-cms no-jpake no-gost" - #OSSL_FLAGS="no-shared threads no-comp no-zlib" - ./Configure linux-armv4 $OSSL_FLAGS --prefix=$DIST - sed -i "" -e "s|-O3|$LIB_OPT_LEVEL $LIB_FPIC $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS|" Makefile - sed -i "" -e "s|ERR_load_COMP_strings()|//ERR_load_COMP_strings()|" crypto/err/err_all.c - make -j 4 build_libs - touch apps/openssl - touch openssl.pc - touch libcrypto.pc - touch libssl.pc - make install_sw - popd - mv $DIST openssl -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl deleted file mode 100755 index 9950c9a..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -. $O3/core/vars/android-sdk-path - -# disable minicrypto for now -mini=0 - -rm -rf polarssl -mkdir polarssl - -for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target CMAKE_TARGET=android USE_MINICRYPTO=$mini MINICRYPTO_DIR=$(pwd)/minicrypto/minicrypto-$target $O3/core/deps/polarssl/build-polarssl - mv polarssl-$target polarssl/ - [ "$ANDROID_DBG_ONLY" = "1" ] && exit -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk deleted file mode 100755 index 01f1a49..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to the dependency build directory - exit 1 -fi - -[ -z "$SDK" ] && export SDK=$DEP_DIR/android-sdk - -if [ -d "$SDK" ]; then - echo "Android SDK already exists at $SDK. Doing only update" -else - . $O3/core/deps/functions.sh - - FNAME=sdk-tools-linux-3859397.zip - URL=https://dl.google.com/android/repository/${FNAME} - CSUM=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0 - - download - - cd $DEP_DIR - rm -rf android-sdk - mkdir android-sdk - - . $O3/core/vars/android-sdk-path - - cd $SDK - unzip $DL/$FNAME -fi - -yes | $SDK/tools/bin/sdkmanager --licenses -$SDK/tools/bin/sdkmanager --update -$SDK/tools/bin/sdkmanager --install 'build-tools;26.0.2' \ - 'ndk-bundle' \ - 'extras;android;m2repository' \ - 'patcher;v4' \ - 'platform-tools' \ - 'platforms;android-26' \ - 'tools' - -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy deleted file mode 100755 index 394a1e8..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -. $O3/core/vars/android-sdk-path - -rm -rf snappy -mkdir snappy - -for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/snappy/build-snappy -done -exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain deleted file mode 100755 index 0f8c613..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -# Build the Android toolchain (run first) -#set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -export DEP_DIR=${DEP_DIR:-$HOME/src/android} -export NO_MOD_PATH=1 -. $O3/core/vars/android-sdk-path - -# 64 bit -cd $DEP_DIR -DEST=$(pwd)/tc-arm64 -rm -rf $DEST -ABI=aarch64-linux-android -ABI_VER=4.9 -$NDK/build/tools/make-standalone-toolchain.sh \ - --verbose \ - --toolchain=$ABI-$ABI_VER \ - --stl=gnustl \ - --arch=arm64 \ - --platform=android-21 \ - --install-dir=$DEST -cd $DEST/$ABI/bin -ln -s ../../bin/$ABI-gcc cc -ln -s ../../bin/$ABI-gcc gcc -ln -s ../../bin/$ABI-g++ g++ -ln -s ../../libexec/gcc/$ABI/$ABI_VER.x/cc1 cc1 -ln -s ../../libexec/gcc/$ABI/$ABI_VER.x/cc1plus cc1plus - -# 32 bit -cd $DEP_DIR -DEST=$(pwd)/tc-arm -rm -rf $DEST -ABI=arm-linux-androideabi -ABI_VER=4.9 -$NDK/build/tools/make-standalone-toolchain.sh \ - --verbose \ - --toolchain=$ABI-$ABI_VER \ - --stl=gnustl \ - --arch=arm \ - --platform=android-16 \ - --install-dir=$DEST -cd $DEST/$ABI/bin -ln -s ../../bin/$ABI-gcc cc -ln -s ../../libexec/gcc/$ABI/$ABI_VER.x/cc1 cc1 -ln -s ../../libexec/gcc/$ABI/$ABI_VER.x/cc1plus cc1plus - -# 32 bit x86 for Android emulator -cd $DEP_DIR -DEST=$(pwd)/tc-x86 -rm -rf $DEST -ABI=x86-linux-android -SUB=i686-linux-android -ABI_VER=4.9 -$NDK/build/tools/make-standalone-toolchain.sh \ - --verbose \ - --toolchain=$ABI-$ABI_VER \ - --stl=gnustl \ - --arch=x86 \ - --platform=android-16 \ - --install-dir=$DEST -cd $DEST/$SUB/bin -ln -s ../../bin/$SUB-gcc cc -ln -s ../../libexec/gcc/$SUB/$ABI_VER.x/cc1 cc1 -ln -s ../../libexec/gcc/$SUB/$ABI_VER.x/cc1plus cc1plus diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build index a4d46e6..e2e8a20 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build @@ -35,6 +35,7 @@ if [ -z "$1" ]; then echo " MTLS_SYS=1 -- use system mbedTLS" echo " MTLS_PATH=path -- use user specified mbedTLS source folder" echo " MTLS_LIBS=ldflags -- user specific mbedTLS LDFLAGS" + echo " MTLS_DIST=path -- use user-specified mbedTLS distribution" echo " MA_HYBRID=1 -- use mbedTLS/AppleCrypto hybrid" echo " OPENSSL_DIST= -- specify custom OpenSSL build" echo " NOSSL=1 -- don't include OpenSSL" @@ -49,6 +50,7 @@ if [ -z "$1" ]; then echo " LZ4_SYS=1 -- build with system LZ4 compression library" echo " SNAP=1 -- build with Snappy compression library" echo " CITY=1 -- build with Cityhash hash library" + echo " CAP=1 -- build with libcap" echo " VAL=1 -- build with valgrind run-time extensions" echo " JAVA=1 -- build with JVM" echo ' EXTRA_CPP="foo1.cpp foo2.cpp" -- add extra .cpp files' @@ -59,6 +61,18 @@ if [ -z "$1" ]; then exit 1 fi +# determine platform if PROF is set to "auto" +if [ "$PROF" = "auto" ]; then + if [ "$(uname)" == "Darwin" ]; then + export PROF=osx64 + elif [ "$(uname)" == "Linux" ]; then + export PROF=linux + else + echo "PROF=auto : cannot determine platform" + exit 1 + fi +fi + # source vars file if [ "$PROF" ]; then suffix="" @@ -123,7 +137,12 @@ FLAGS="$FLAGS -Wno-sign-compare -Wno-unused-parameter" #fi # MbedTLS -if [ "$MTLS_SYS" = "1" ]; then +if [ -n "$MTLS_DIST" ]; then + CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS -I$MTLS_DIST/include" + LIBDIRS="$LIBDIRS -L$MTLS_DIST/library" + LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" + MTLS=1 +elif [ "$MTLS_SYS" = "1" ]; then CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS" LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" elif [ "$MTLS" = "1" ]; then @@ -257,6 +276,12 @@ if [ "$CITY" = "1" ]; then CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH" fi +# libcap +if [ "$CAP" = "1" ]; then + LIBS="$LIBS -lcap" + CPPFLAGS="$CPPFLAGS -DHAVE_LIBCAP" +fi + # Valgrind if [ "$VAL" = "1" ]; then CPPFLAGS="$CPPFLAGS -DHAVE_VALGRIND" @@ -330,8 +355,12 @@ fi # release/debug builds if [ "$DEBUG" = "1" ]; then - # debug build - FLAGS="-g $FLAGS" + # build with debug symbols + if [ "$PLATFORM" = "linux" ]; then + FLAGS="-ggdb $FLAGS" + else + FLAGS="-g $FLAGS" + fi else # release build [ "$LTO" = "1" ] && [ "$CLANG" != "1" ] && FLAGS="$FLAGS -flto=4 -Wl,--no-as-needed" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp index fe07d23..a61fa44 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp @@ -78,6 +78,7 @@ #if defined(OPENVPN_PLATFORM_WIN) #include +#include #endif #ifdef USE_NETCFG @@ -942,7 +943,14 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content) ClientAPI::Config config; config.guiVersion = "cli 1.0"; +#if defined(OPENVPN_PLATFORM_WIN) + int nargs = 0; + auto argvw = CommandLineToArgvW(GetCommandLineW(), &nargs); + UTF8 utf8(Win::utf8(argvw[nargs - 1])); + config.content = read_profile(utf8.get(), profile_content); +#else config.content = read_profile(argv[0], profile_content); +#endif for (int i = 1; i < argc; ++i) { config.content += argv[i]; @@ -975,6 +983,7 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content) config.gremlinConfig = gremlin; config.info = true; config.wintun = wintun; + config.ssoMethods = "openurl"; #if defined(OPENVPN_OVPNCLI_SINGLE_THREAD) config.clockTickMS = 250; #endif @@ -1173,6 +1182,10 @@ int main(int argc, char *argv[]) LogBaseSimple log; #endif +#if defined(OPENVPN_PLATFORM_WIN) + SetConsoleOutputCP(CP_UTF8); +#endif + try { Client::init_process(); ret = openvpn_client(argc, argv, nullptr); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go index 873cf1f..f88aeb8 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go @@ -16,6 +16,7 @@ GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN" [ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE" [ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK" [ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL" +[ "$MDNC" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DMBEDTLS_DISABLE_NAME_CONSTRAINTS" if [ "$AGENT" = "1" ]; then GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT" fi diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/core_tests.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/core_tests.cpp index 030d9fa..24f7fd7 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/core_tests.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/core_tests.cpp @@ -27,6 +27,7 @@ #include #include +#include int main (int argc, char **argv) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/test_log.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/test_log.cpp index dc2b5b0..8f0a717 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/test_log.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/test_log.cpp @@ -27,6 +27,10 @@ // file test_ovpncli and do ALL test that require ovpncli in this file // (or have multiple test suites) +// This file needs to included with OPENVPN_EXTERN still defined otherwise +// the include from ovpncli.cpp breaks with duplicate symbols +#include + #undef OPENVPN_EXTERN #define OPENVPN_EXTERN diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path deleted file mode 100644 index 61edf99..0000000 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path +++ /dev/null @@ -1,7 +0,0 @@ -# setup PATH for Android SDK and NDK -[ -z "$SDK" ] && export SDK=$DEP_DIR/android-sdk -[ -z "$NDK" ] && export NDK=$SDK/ndk-bundle -if [ "$NO_MOD_PATH" != "1" ]; then - export PATH="$SDK/tools:$SDK/platform-tools:$PATH" -fi -export ANDROID_HOME=$SDK \ No newline at end of file diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/build.py b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/build.py index 47a04dc..b349336 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/build.py +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/build.py @@ -80,7 +80,7 @@ def build(parms, srcfile, unit_test=False): if parms.get("USE_OPENSSL"): options['extra_inc'] += ' /DUSE_OPENSSL /I %s' % os.path.join(options['openssl'], 'inc32') - options['extra_lib_path'] += ' /LIBPATH:%s' % os.path.join(options['openssl'], 'out32') + options['extra_lib_path'] += ' /LIBPATH:%s' % os.path.join(options['openssl'], 'out32dll') options['extra_lib'] += ' libeay32.lib ssleay32.lib' else: options['extra_inc'] += ' /DUSE_MBEDTLS /I %s' % os.path.join(options['mbedtls'], 'include') @@ -88,7 +88,7 @@ def build(parms, srcfile, unit_test=False): options['extra_lib'] += ' mbedtls.lib' # build it - vc_cmd(parms, r"cl %(extra_defs)s /DNOMINMAX /bigobj /D_CRT_SECURE_NO_WARNINGS /DUSE_ASIO /DASIO_STANDALONE /DASIO_NO_DEPRECATED /I %(asio)s\asio\include /DHAVE_LZ4 /I %(lz4)s %(extra_inc)s -DTAP_WIN_COMPONENT_ID=%(tap_component_id)s /I %(tap)s /I %(ovpn3)s\core /EHsc %(link_static_dynamic_flags)s /W0 %(dbg_rel_flags)s /nologo %(srcfile)s /link /LIBPATH:%(lz4)s%(extra_lib_path)s lz4.lib%(extra_lib)s ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib shell32.lib ole32.lib rpcrt4.lib Wtsapi32.lib" % options, arch=os.environ.get("ARCH")) + vc_cmd(parms, r"cl %(extra_defs)s /DNOMINMAX /bigobj /D_CRT_SECURE_NO_WARNINGS /DUSE_ASIO /DASIO_STANDALONE /DASIO_NO_DEPRECATED /I %(asio)s\asio\include /DHAVE_LZ4 /I %(lz4)s %(extra_inc)s -DTAP_WIN_COMPONENT_ID=%(tap_component_id)s /I %(tap)s /I %(ovpn3)s\core /EHsc %(link_static_dynamic_flags)s /W0 %(dbg_rel_flags)s /nologo %(srcfile)s /link /LIBPATH:%(lz4)s%(extra_lib_path)s lz4.lib%(extra_lib)s ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib shell32.lib ole32.lib rpcrt4.lib Wtsapi32.lib Setupapi.lib Cfgmgr32.lib" % options, arch=os.environ.get("ARCH")) if __name__ == "__main__": import sys diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py index 401c2f4..eee96f9 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py @@ -149,7 +149,7 @@ def build_openssl(parms): rm(arch_path) os.chdir(dist) - for cmd in ["perl Configure VC-WIN64A", "ms\\do_win64a", "nmake -f ms\\nt.mak"]: + for cmd in ["perl Configure VC-WIN64A", "ms\\do_win64a", "nmake -f ms\\ntdll.mak"]: vc_cmd(parms, cmd) def build_all(parms): diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln index 15249a8..49f8954 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln @@ -10,6 +10,9 @@ Global Debug|ARM = Debug|ARM Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + DebugAgent|ARM = DebugAgent|ARM + DebugAgent|x64 = DebugAgent|x64 + DebugAgent|x86 = DebugAgent|x86 DebugOpenSSL|ARM = DebugOpenSSL|ARM DebugOpenSSL|x64 = DebugOpenSSL|x64 DebugOpenSSL|x86 = DebugOpenSSL|x86 @@ -25,6 +28,10 @@ Global {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.ActiveCfg = Debug|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.Build.0 = Debug|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x86.ActiveCfg = Debug|x64 + {1F891260-2039-494F-9777-EC5166AF31BC}.DebugAgent|ARM.ActiveCfg = DebugAgent|x64 + {1F891260-2039-494F-9777-EC5166AF31BC}.DebugAgent|x64.ActiveCfg = DebugAgent|x64 + {1F891260-2039-494F-9777-EC5166AF31BC}.DebugAgent|x64.Build.0 = DebugAgent|x64 + {1F891260-2039-494F-9777-EC5166AF31BC}.DebugAgent|x86.ActiveCfg = DebugAgent|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.DebugOpenSSL|ARM.ActiveCfg = DebugOpenSSL|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.DebugOpenSSL|x64.ActiveCfg = DebugOpenSSL|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.DebugOpenSSL|x64.Build.0 = DebugOpenSSL|x64 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj index 06cf127..ba2daca 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj @@ -1,6 +1,10 @@  + + DebugAgent + x64 + DebugOpenSSL x64 @@ -121,6 +125,7 @@ + @@ -420,16 +425,19 @@ + + + @@ -445,7 +453,7 @@ {1F891260-2039-494F-9777-EC5166AF31BC} ovpn3core - 10.0.17134.0 + 10.0 cli @@ -453,25 +461,31 @@ Application true MultiByte - v141 + v142 + + + Application + true + MultiByte + v142 Application true MultiByte - v141 + v142 Application false - v141 + v142 true MultiByte Application false - v141 + v142 true MultiByte @@ -497,10 +511,30 @@ true $(O3)\deps\amd64\mbedtls\library;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) - lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib + lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;setupapi.lib NotSet + + + TurnOffAllWarnings + Disabled + false + _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;OPENVPN_COMMAND_AGENT;HAVE_JSONCPP;OVPNAGENT_DISABLE_PATH_CHECK;%(PreprocessorDefinitions) + $(O3)\deps\amd64\mbedtls\include;$(O3)\deps\amd64\tap-windows\src;$(O3)\deps\amd64\asio\asio\include;$(O3)\deps\amd64\lz4\lib;$(O3)\common;$(O3)\core;$(O3)\deps\amd64\jsoncpp\include;%(AdditionalIncludeDirectories) + false + ProgramDatabase + /bigobj %(AdditionalOptions) + MultiThreadedDebug + + + true + $(O3)\deps\amd64\mbedtls\library;$(O3)\deps\amd64\lz4\lib;$(O3)\deps\amd64\jsoncpp\dist;%(AdditionalLibraryDirectories) + lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;setupapi.lib;jsoncpp.lib + NotSet + Console + + TurnOffAllWarnings @@ -515,8 +549,8 @@ true - $(O3)\deps\amd64\openssl\out32;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) - gdi32.lib;user32.lib;ssleay32.lib;libeay32.lib;lz4.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib + $(O3)\deps\amd64\openssl\out32dll;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) + gdi32.lib;user32.lib;ssleay32.lib;libeay32.lib;lz4.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;setupapi.lib NotSet @@ -536,7 +570,7 @@ true true $(O3)\deps\amd64\mbedtls\library;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) - lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;%(AdditionalDependencies) + lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;setupapi.lib;%(AdditionalDependencies) @@ -554,8 +588,8 @@ true true true - $(O3)\deps\amd64\openssl\out32;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) - ssleay32.lib;libeay32.lib;lz4.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;%(AdditionalDependencies) + $(O3)\deps\amd64\openssl\out32dll;$(O3)\deps\amd64\lz4\lib;%(AdditionalLibraryDirectories) + ssleay32.lib;libeay32.lib;lz4.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;Wtsapi32.lib;setupapi.lib;%(AdditionalDependencies) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters index a6ce3b7..8fd9954 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters @@ -428,6 +428,10 @@ + + + + diff --git a/Sources/OpenVPNAdapter/NSError+OpenVPNError.m b/Sources/OpenVPNAdapter/NSError+OpenVPNError.m index 70e8344..5d6fd1f 100644 --- a/Sources/OpenVPNAdapter/NSError+OpenVPNError.m +++ b/Sources/OpenVPNAdapter/NSError+OpenVPNError.m @@ -57,6 +57,7 @@ @"TUN_IFACE_CREATE": @(OpenVPNAdapterErrorTUNIfaceCreate), @"TUN_IFACE_DISABLED": @(OpenVPNAdapterErrorTUNIfaceDisabled), @"TUN_ERROR": @(OpenVPNAdapterErrorTUNError), + @"TUN_REGISTER_RINGS_ERROR": @(OpenVPNAdapterErrorTUNRegisterRingsError), @"TAP_NOT_SUPPORTED": @(OpenVPNAdapterErrorTAPNotSupported), @"REROUTE_GW_NO_DNS": @(OpenVPNAdapterErrorRerouteGatewayNoDns), @"TRANSPORT_ERROR": @(OpenVPNAdapterErrorTransportError), @@ -82,6 +83,7 @@ @"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed), @"CLIENT_HALT": @(OpenVPNAdapterErrorClientHalt), @"CLIENT_RESTART": @(OpenVPNAdapterErrorClientRestart), + @"TUN_HALT": @(OpenVPNAdapterErrorTUNHalt), @"RELAY": @(OpenVPNAdapterErrorRelay), @"RELAY_ERROR": @(OpenVPNAdapterErrorRelayError), @"N_PAUSE": @(OpenVPNAdapterErrorPauseNumber), @@ -134,6 +136,7 @@ case OpenVPNAdapterErrorTUNIfaceCreate: return @"Error creating TUN/TAP interface."; case OpenVPNAdapterErrorTUNIfaceDisabled: return @"TUN/TAP interface is disabled."; case OpenVPNAdapterErrorTUNError: return @"General tun error."; + case OpenVPNAdapterErrorTUNRegisterRingsError: return @"Error registering ring buffers with wintun."; case OpenVPNAdapterErrorTAPNotSupported: return @"Dev TAP is present in profile but not supported."; case OpenVPNAdapterErrorRerouteGatewayNoDns: return @"redirect-gateway specified without alt DNS servers."; case OpenVPNAdapterErrorTransportError: return @"General transport error"; @@ -159,6 +162,7 @@ case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure"; case OpenVPNAdapterErrorClientHalt: return @"HALT message from server received."; case OpenVPNAdapterErrorClientRestart: return @"RESTART message from server received."; + case OpenVPNAdapterErrorTUNHalt: return @"Halt command from tun interface"; case OpenVPNAdapterErrorRelay: return @"RELAY message from server received."; case OpenVPNAdapterErrorRelayError: return @"RELAY error."; case OpenVPNAdapterErrorPauseNumber: return nil; diff --git a/Sources/OpenVPNAdapter/OpenVPNAdapter.mm b/Sources/OpenVPNAdapter/OpenVPNAdapter.mm index 84a6e29..5064fb4 100644 --- a/Sources/OpenVPNAdapter/OpenVPNAdapter.mm +++ b/Sources/OpenVPNAdapter/OpenVPNAdapter.mm @@ -8,6 +8,8 @@ #define OPENVPN_EXTERN extern +#define TUNNEL_CONFIGURATION_TIMEOUT 30 + #import "OpenVPNAdapter.h" #import @@ -48,7 +50,7 @@ #pragma mark - OpenVPNClient Lifecycle - (OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError * __autoreleasing *)error { - ClientAPI::EvalConfig eval = self.vpnClient->eval_config(configuration.config); + ClientAPI::EvalConfig eval = self.vpnClient->apply_config(configuration.config); if (eval.error) { if (error) { @@ -326,7 +328,7 @@ [self.delegate openVPNAdapter:self configureTunnelWithNetworkSettings:networkSettings completionHandler:completionHandler]; - dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC)); + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, TUNNEL_CONFIGURATION_TIMEOUT * NSEC_PER_SEC)); NSError *socketError; if (self.packetFlowBridge && [self.packetFlowBridge configureSocketsWithError:&socketError]) { @@ -361,6 +363,7 @@ @"PAUSE": @(OpenVPNAdapterEventPause), @"RESUME": @(OpenVPNAdapterEventResume), @"RELAY": @(OpenVPNAdapterEventRelay), + @"COMPRESSION_ENABLED": @(OpenVPNAdapterEventCompressionEnabled), @"UNSUPPORTED_FEATURE": @(OpenVPNAdapterEventUnsupportedFeature) }; @@ -396,8 +399,11 @@ - (void)resetSettings { _sessionName = nil; - _packetFlowBridge = nil; _networkSettingsBuilder = nil; +} + +- (void)resetTun { + _packetFlowBridge = nil; dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); @@ -407,7 +413,7 @@ [self.delegate openVPNAdapter:self configureTunnelWithNetworkSettings:nil completionHandler:completionHandler]; - dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC)); + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, TUNNEL_CONFIGURATION_TIMEOUT * NSEC_PER_SEC)); } #pragma mark - diff --git a/Sources/OpenVPNAdapter/OpenVPNAdapterEvent.h b/Sources/OpenVPNAdapter/OpenVPNAdapterEvent.h index fc6d2e9..e900443 100644 --- a/Sources/OpenVPNAdapter/OpenVPNAdapterEvent.h +++ b/Sources/OpenVPNAdapter/OpenVPNAdapterEvent.h @@ -29,6 +29,7 @@ typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent) { OpenVPNAdapterEventPause, OpenVPNAdapterEventResume, OpenVPNAdapterEventRelay, + OpenVPNAdapterEventCompressionEnabled, OpenVPNAdapterEventUnsupportedFeature, OpenVPNAdapterEventUnknown }; diff --git a/Sources/OpenVPNAdapter/OpenVPNClient.h b/Sources/OpenVPNAdapter/OpenVPNClient.h index fe5f6fc..30be5a6 100644 --- a/Sources/OpenVPNAdapter/OpenVPNClient.h +++ b/Sources/OpenVPNAdapter/OpenVPNClient.h @@ -51,6 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)tick; - (void)resetSettings; +- (void)resetTun; @end NS_ASSUME_NONNULL_END @@ -60,6 +61,9 @@ using namespace openvpn; class OpenVPNClient : public ClientAPI::OpenVPNClient { public: OpenVPNClient(id _Nonnull delegate); + ~OpenVPNClient(); + + ClientAPI::EvalConfig apply_config(const ClientAPI::Config& config); bool tun_builder_new() override; @@ -89,9 +93,6 @@ public: void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override; void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override; - bool remote_override_enabled() override; - void remote_override(ClientAPI::RemoteOverride& remote) override; - void event(const ClientAPI::Event& event) override; void log(const ClientAPI::LogInfo& log) override; @@ -99,6 +100,7 @@ public: private: __weak id _Nonnull delegate; + ClientAPI::Config * _Nullable config; }; diff --git a/Sources/OpenVPNAdapter/OpenVPNClient.mm b/Sources/OpenVPNAdapter/OpenVPNClient.mm index f5c0333..b2adbae 100644 --- a/Sources/OpenVPNAdapter/OpenVPNClient.mm +++ b/Sources/OpenVPNAdapter/OpenVPNClient.mm @@ -17,10 +17,24 @@ using ::IPv4::Addr; OpenVPNClient::OpenVPNClient(id delegate): ClientAPI::OpenVPNClient() { this->delegate = delegate; + this->config = nullptr; +} + +OpenVPNClient::~OpenVPNClient() { + if (this->config != nullptr) { delete this->config; } +} + +ClientAPI::EvalConfig OpenVPNClient::apply_config(const ClientAPI::Config& config) { + if (this->config != nullptr) { delete this->config; } + this->config = new ClientAPI::Config(config); + + return eval_config(config); } bool OpenVPNClient::tun_builder_new() { [this->delegate resetSettings]; + [this->delegate resetTun]; + return true; } @@ -134,11 +148,12 @@ int OpenVPNClient::tun_builder_establish() { } bool OpenVPNClient::tun_builder_persist() { - return true; + return config->tunPersist; } void OpenVPNClient::tun_builder_teardown(bool disconnect) { [this->delegate resetSettings]; + [this->delegate resetTun]; } bool OpenVPNClient::socket_protect(int socket, std::string remote, bool ipv6) { @@ -152,14 +167,6 @@ bool OpenVPNClient::pause_on_connection_timeout() { void OpenVPNClient::external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) { } void OpenVPNClient::external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) { } -bool OpenVPNClient::remote_override_enabled() { - return false; -} - -void OpenVPNClient::remote_override(ClientAPI::RemoteOverride& remote) { - // TODO: Override remote server -} - void OpenVPNClient::event(const ClientAPI::Event& ev) { NSString *name = [NSString stringWithUTF8String:ev.name.c_str()]; NSString *message = [NSString stringWithUTF8String:ev.info.c_str()]; diff --git a/Sources/OpenVPNAdapter/OpenVPNConfiguration.h b/Sources/OpenVPNAdapter/OpenVPNConfiguration.h index f0a324a..a153976 100644 --- a/Sources/OpenVPNAdapter/OpenVPNConfiguration.h +++ b/Sources/OpenVPNAdapter/OpenVPNConfiguration.h @@ -37,6 +37,26 @@ typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile); */ @property (nullable, nonatomic) NSString *guiVersion; +/** + Set to a comma seperated list of supported SSO mechanisms that may + be signalled via INFO_PRE to the client. + "openurl" is to continue authentication by opening an url in a browser + "crtext" gives a challenge response in text format that needs to + responded via control channel. + Passed to the server as IV_SSO. +*/ +@property (nullable, nonatomic) NSString *ssoMethods; + +/** + Override the string that is passed as IV_HWADDR to the server. +*/ +@property (nullable, nonatomic) NSString *hardwareAdressOverride; + +/** + Set the string that is passed to the server as IV_PLAT_VER +*/ +@property (nullable, nonatomic) NSString *platformVersion; + /** Use a different server than that specified in "remote" option of profile @@ -64,6 +84,11 @@ typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile); */ @property (nonatomic) NSInteger connectionTimeout; +/** + Keep tun interface active during pauses or reconnections + */ +@property (nonatomic) BOOL tunPersist; + /** If YES and a redirect-gateway profile doesn't also define DNS servers, use the standard Google DNS servers. diff --git a/Sources/OpenVPNAdapter/OpenVPNConfiguration.mm b/Sources/OpenVPNAdapter/OpenVPNConfiguration.mm index bb8d414..99d34c8 100644 --- a/Sources/OpenVPNAdapter/OpenVPNConfiguration.mm +++ b/Sources/OpenVPNAdapter/OpenVPNConfiguration.mm @@ -260,6 +260,30 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; _config.guiVersion = guiVersion ? std::string([guiVersion UTF8String]) : ""; } +- (NSString *)ssoMethods { + return !_config.ssoMethods.empty() ? [NSString stringWithUTF8String:_config.ssoMethods.c_str()] : nil; +} + +- (void)setSsoMethods:(NSString *)ssoMethods { + _config.ssoMethods = ssoMethods ? std::string([ssoMethods UTF8String]) : ""; +} + +- (NSString *)hardwareAdressOverride { + return !_config.hwAddrOverride.empty() ? [NSString stringWithUTF8String:_config.hwAddrOverride.c_str()] : nil; +} + +- (void)setHardwareAdressOverride:(NSString *)hardwareAdressOverride { + _config.hwAddrOverride = hardwareAdressOverride ? std::string([hardwareAdressOverride UTF8String]) : ""; +} + +- (NSString *)platformVersion { + return !_config.platformVersion.empty() ? [NSString stringWithUTF8String:_config.platformVersion.c_str()] : nil; +} + +- (void)setPlatformVersion:(NSString *)platformVersion { + _config.platformVersion = platformVersion ? std::string([platformVersion UTF8String]) : ""; +} + - (NSString *)server { return !_config.serverOverride.empty() ? [NSString stringWithUTF8String:_config.serverOverride.c_str()] : nil; } @@ -308,6 +332,14 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; _config.connTimeout = connectionTimeout; } +- (BOOL)tunPersist { + return _config.tunPersist; +} + +- (void)setTunPersist:(BOOL)tunPersist { + _config.tunPersist = tunPersist; +} + - (BOOL)googleDNSFallback { return _config.googleDnsFallback; } @@ -473,10 +505,14 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; configuration.fileContent = [self.fileContent copyWithZone:zone]; configuration.settings = [self.settings copyWithZone:zone]; configuration.guiVersion = [self.guiVersion copyWithZone:zone]; + configuration.ssoMethods = [self.ssoMethods copyWithZone:zone]; + configuration.hardwareAdressOverride = [self.hardwareAdressOverride copyWithZone:zone]; + configuration.platformVersion = [self.platformVersion copyWithZone:zone]; configuration.server = [self.server copyWithZone:zone]; configuration.proto = self.proto; configuration.ipv6 = self.ipv6; configuration.connectionTimeout = self.connectionTimeout; + configuration.tunPersist = self.tunPersist; configuration.googleDNSFallback = self.googleDNSFallback; configuration.synchronousDNSLookup = self.synchronousDNSLookup; configuration.autologinSessions = self.autologinSessions; @@ -499,10 +535,14 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; [aCoder encodeObject:self.fileContent forKey:NSStringFromSelector(@selector(fileContent))]; [aCoder encodeObject:self.settings forKey:NSStringFromSelector(@selector(settings))]; [aCoder encodeObject:self.guiVersion forKey:NSStringFromSelector(@selector(guiVersion))]; + [aCoder encodeObject:self.ssoMethods forKey:NSStringFromSelector(@selector(ssoMethods))]; + [aCoder encodeObject:self.hardwareAdressOverride forKey:NSStringFromSelector(@selector(hardwareAdressOverride))]; + [aCoder encodeObject:self.platformVersion forKey:NSStringFromSelector(@selector(platformVersion))]; [aCoder encodeObject:self.server forKey:NSStringFromSelector(@selector(server))]; [aCoder encodeInteger:self.proto forKey:NSStringFromSelector(@selector(proto))]; [aCoder encodeInteger:self.ipv6 forKey:NSStringFromSelector(@selector(ipv6))]; [aCoder encodeInteger:self.connectionTimeout forKey:NSStringFromSelector(@selector(connectionTimeout))]; + [aCoder encodeBool:self.tunPersist forKey:NSStringFromSelector(@selector(tunPersist))]; [aCoder encodeBool:self.googleDNSFallback forKey:NSStringFromSelector(@selector(googleDNSFallback))]; [aCoder encodeBool:self.synchronousDNSLookup forKey:NSStringFromSelector(@selector(synchronousDNSLookup))]; [aCoder encodeBool:self.autologinSessions forKey:NSStringFromSelector(@selector(autologinSessions))]; @@ -525,10 +565,14 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; self.fileContent = [aDecoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(fileContent))]; self.settings = [aDecoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(settings))]; self.guiVersion = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(guiVersion))]; + self.ssoMethods = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(ssoMethods))]; + self.hardwareAdressOverride = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(hardwareAdressOverride))]; + self.platformVersion = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(platformVersion))]; self.server = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(server))]; self.proto = (OpenVPNTransportProtocol)[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(proto))]; self.ipv6 = (OpenVPNIPv6Preference)[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(ipv6))]; self.connectionTimeout = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(connectionTimeout))]; + self.tunPersist = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(tunPersist))]; self.googleDNSFallback = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(googleDNSFallback))]; self.synchronousDNSLookup = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(synchronousDNSLookup))]; self.autologinSessions = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(autologinSessions))]; diff --git a/Sources/OpenVPNAdapter/OpenVPNError.h b/Sources/OpenVPNAdapter/OpenVPNError.h index c60e740..c32d113 100644 --- a/Sources/OpenVPNAdapter/OpenVPNError.h +++ b/Sources/OpenVPNAdapter/OpenVPNError.h @@ -45,6 +45,7 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError) { OpenVPNAdapterErrorTUNIfaceCreate, OpenVPNAdapterErrorTUNIfaceDisabled, OpenVPNAdapterErrorTUNError, + OpenVPNAdapterErrorTUNRegisterRingsError, OpenVPNAdapterErrorTAPNotSupported, OpenVPNAdapterErrorRerouteGatewayNoDns, OpenVPNAdapterErrorTransportError, @@ -70,6 +71,7 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError) { OpenVPNAdapterErrorAuthFailed, OpenVPNAdapterErrorClientHalt, OpenVPNAdapterErrorClientRestart, + OpenVPNAdapterErrorTUNHalt, OpenVPNAdapterErrorRelay, OpenVPNAdapterErrorRelayError, OpenVPNAdapterErrorPauseNumber, diff --git a/Tests/OpenVPNConfigurationTests.swift b/Tests/OpenVPNConfigurationTests.swift index fb279c6..04b0dac 100644 --- a/Tests/OpenVPNConfigurationTests.swift +++ b/Tests/OpenVPNConfigurationTests.swift @@ -70,9 +70,10 @@ class OpenVPNConfigurationTests: XCTestCase { return } - let equals = originalSettings.elementsEqual(returnedSettings) { (first, second) -> Bool in - first.key == second.key && first.value == second.value + let equals = originalSettings.allSatisfy { (key, value) in + returnedSettings[key] == value } + XCTAssert(equals) configuration.settings = [:]