diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp index c18fa31..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; } @@ -659,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); } } @@ -807,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 { @@ -977,8 +988,8 @@ namespace openvpn { #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 11f0f8e..f06762a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp @@ -495,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/openvpn/client/cliopt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp index e8561e4..bcc0cb6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp @@ -436,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 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopthelper.hpp index a5c97b3..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; } } 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/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/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 5a7dbb0..8077a8e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp @@ -282,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())) @@ -293,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) { 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/tun/win/client/tunsetup.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/win/client/tunsetup.hpp index 1bec60a..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 @@ -204,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 { 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 06fbc96..8fd9954 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters @@ -431,6 +431,7 @@ +