diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/basic_socket.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/basic_socket.hpp index 0d1b0d2..4343016 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/basic_socket.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/basic_socket.hpp @@ -865,8 +865,6 @@ public: asio::error_code ec; const protocol_type protocol = peer_endpoint.protocol(); this->get_service().open(this->get_implementation(), protocol, ec); - if (!ec) - async_connect_post_open(protocol, ec); if (ec) { async_completionai_family == AF_INET6) - { - sockaddr_in6* a6 = (sockaddr_in6*)(*result)->ai_addr; - if (a6->sin6_scope_id && !(IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&a6->sin6_addr))) - a6->sin6_scope_id = 0; - } - return ec = translate_addrinfo_error(error); #else int error = ::getaddrinfo(host, service, &hints, result); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/ip/basic_resolver_results.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/ip/basic_resolver_results.hpp index f0ae258..4146a46 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/ip/basic_resolver_results.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/include/asio/ip/basic_resolver_results.hpp @@ -18,7 +18,6 @@ #include "asio/detail/config.hpp" #include #include -#include #include "asio/detail/socket_ops.hpp" #include "asio/detail/socket_types.hpp" #include "asio/ip/basic_resolver_iterator.hpp" @@ -300,12 +299,6 @@ public: return !a.equal(b); } - template - void randomize(Random& r) - { - std::shuffle(this->values_->begin(), this->values_->end(), r); - } - private: typedef std::vector > values_type; }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4.cpp new file mode 100644 index 0000000..ee26bd9 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4.cpp @@ -0,0 +1,324 @@ +// +// address_v4.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v4.hpp" + +#include "../unit_test.hpp" +#include + +//------------------------------------------------------------------------------ + +// ip_address_v4_compile test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that all public member functions on the class +// ip::address_v4 compile and link correctly. Runtime failures are ignored. + +namespace ip_address_v4_compile { + +void test() +{ + using namespace asio; + namespace ip = asio::ip; + + try + { + asio::error_code ec; + + // address_v4 constructors. + + ip::address_v4 addr1; + const ip::address_v4::bytes_type const_bytes_value = { { 127, 0, 0, 1 } }; + ip::address_v4 addr2(const_bytes_value); + const unsigned long const_ulong_value = 0x7F000001; + ip::address_v4 addr3(const_ulong_value); + + // address_v4 functions. + + bool b = addr1.is_loopback(); + (void)b; + + b = addr1.is_unspecified(); + (void)b; + +#if !defined(ASIO_NO_DEPRECATED) + b = addr1.is_class_a(); + (void)b; + + b = addr1.is_class_b(); + (void)b; + + b = addr1.is_class_c(); + (void)b; +#endif // !defined(ASIO_NO_DEPRECATED) + + b = addr1.is_multicast(); + (void)b; + + ip::address_v4::bytes_type bytes_value = addr1.to_bytes(); + (void)bytes_value; + + ip::address_v4::uint_type uint_value = addr1.to_uint(); + (void)uint_value; + +#if !defined(ASIO_NO_DEPRECATED) + unsigned long ulong_value = addr1.to_ulong(); + (void)ulong_value; +#endif // !defined(ASIO_NO_DEPRECATED) + + std::string string_value = addr1.to_string(); +#if !defined(ASIO_NO_DEPRECATED) + string_value = addr1.to_string(ec); +#endif // !defined(ASIO_NO_DEPRECATED) + + // address_v4 static functions. + +#if !defined(ASIO_NO_DEPRECATED) + addr1 = ip::address_v4::from_string("127.0.0.1"); + addr1 = ip::address_v4::from_string("127.0.0.1", ec); + addr1 = ip::address_v4::from_string(string_value); + addr1 = ip::address_v4::from_string(string_value, ec); +#endif // !defined(ASIO_NO_DEPRECATED) + + addr1 = ip::address_v4::any(); + + addr1 = ip::address_v4::loopback(); + + addr1 = ip::address_v4::broadcast(); + +#if !defined(ASIO_NO_DEPRECATED) + addr1 = ip::address_v4::broadcast(addr2, addr3); + + addr1 = ip::address_v4::netmask(addr2); +#endif // !defined(ASIO_NO_DEPRECATED) + + // address_v4 comparisons. + + b = (addr1 == addr2); + (void)b; + + b = (addr1 != addr2); + (void)b; + + b = (addr1 < addr2); + (void)b; + + b = (addr1 > addr2); + (void)b; + + b = (addr1 <= addr2); + (void)b; + + b = (addr1 >= addr2); + (void)b; + + // address_v4 creation functions. + + addr1 = ip::make_address_v4(const_bytes_value); + addr1 = ip::make_address_v4(const_ulong_value); + addr1 = ip::make_address_v4("127.0.0.1"); + addr1 = ip::make_address_v4("127.0.0.1", ec); + addr1 = ip::make_address_v4(string_value); + addr1 = ip::make_address_v4(string_value, ec); +#if defined(ASIO_HAS_STD_STRING_VIEW) +# if defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + std::experimental::string_view string_view_value("127.0.0.1"); +# else // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + std::string_view string_view_value("127.0.0.1"); +# endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + addr1 = ip::make_address_v4(string_view_value); + addr1 = ip::make_address_v4(string_view_value, ec); +#endif // defined(ASIO_HAS_STD_STRING_VIEW) + + // address_v4 I/O. + + std::ostringstream os; + os << addr1; + +#if !defined(BOOST_NO_STD_WSTREAMBUF) + std::wostringstream wos; + wos << addr1; +#endif // !defined(BOOST_NO_STD_WSTREAMBUF) + } + catch (std::exception&) + { + } +} + +} // namespace ip_address_v4_compile + +//------------------------------------------------------------------------------ + +// ip_address_v4_runtime test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that the various public member functions meet the +// necessary postconditions. + +namespace ip_address_v4_runtime { + +void test() +{ + using asio::ip::address_v4; + + address_v4 a1; + ASIO_CHECK(a1.to_bytes()[0] == 0); + ASIO_CHECK(a1.to_bytes()[1] == 0); + ASIO_CHECK(a1.to_bytes()[2] == 0); + ASIO_CHECK(a1.to_bytes()[3] == 0); + ASIO_CHECK(a1.to_uint() == 0); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(a1.to_ulong() == 0); +#endif // !defined(ASIO_NO_DEPRECATED) + + address_v4::bytes_type b1 = {{ 1, 2, 3, 4 }}; + address_v4 a2(b1); + ASIO_CHECK(a2.to_bytes()[0] == 1); + ASIO_CHECK(a2.to_bytes()[1] == 2); + ASIO_CHECK(a2.to_bytes()[2] == 3); + ASIO_CHECK(a2.to_bytes()[3] == 4); + ASIO_CHECK(((a2.to_uint() >> 24) & 0xFF) == b1[0]); + ASIO_CHECK(((a2.to_uint() >> 16) & 0xFF) == b1[1]); + ASIO_CHECK(((a2.to_uint() >> 8) & 0xFF) == b1[2]); + ASIO_CHECK((a2.to_uint() & 0xFF) == b1[3]); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(((a2.to_ulong() >> 24) & 0xFF) == b1[0]); + ASIO_CHECK(((a2.to_ulong() >> 16) & 0xFF) == b1[1]); + ASIO_CHECK(((a2.to_ulong() >> 8) & 0xFF) == b1[2]); + ASIO_CHECK((a2.to_ulong() & 0xFF) == b1[3]); +#endif // !defined(ASIO_NO_DEPRECATED) + + address_v4 a3(0x01020304); + ASIO_CHECK(a3.to_bytes()[0] == 1); + ASIO_CHECK(a3.to_bytes()[1] == 2); + ASIO_CHECK(a3.to_bytes()[2] == 3); + ASIO_CHECK(a3.to_bytes()[3] == 4); + ASIO_CHECK(a3.to_uint() == 0x01020304); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(a3.to_ulong() == 0x01020304); +#endif // !defined(ASIO_NO_DEPRECATED) + + ASIO_CHECK(address_v4(0x7F000001).is_loopback()); + ASIO_CHECK(address_v4(0x7F000002).is_loopback()); + ASIO_CHECK(!address_v4(0x00000000).is_loopback()); + ASIO_CHECK(!address_v4(0x01020304).is_loopback()); + + ASIO_CHECK(address_v4(0x00000000).is_unspecified()); + ASIO_CHECK(!address_v4(0x7F000001).is_unspecified()); + ASIO_CHECK(!address_v4(0x01020304).is_unspecified()); + +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(address_v4(0x01000000).is_class_a()); + ASIO_CHECK(address_v4(0x7F000000).is_class_a()); + ASIO_CHECK(!address_v4(0x80000000).is_class_a()); + ASIO_CHECK(!address_v4(0xBFFF0000).is_class_a()); + ASIO_CHECK(!address_v4(0xC0000000).is_class_a()); + ASIO_CHECK(!address_v4(0xDFFFFF00).is_class_a()); + ASIO_CHECK(!address_v4(0xE0000000).is_class_a()); + ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_a()); + ASIO_CHECK(!address_v4(0xF0000000).is_class_a()); + ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_a()); + + ASIO_CHECK(!address_v4(0x01000000).is_class_b()); + ASIO_CHECK(!address_v4(0x7F000000).is_class_b()); + ASIO_CHECK(address_v4(0x80000000).is_class_b()); + ASIO_CHECK(address_v4(0xBFFF0000).is_class_b()); + ASIO_CHECK(!address_v4(0xC0000000).is_class_b()); + ASIO_CHECK(!address_v4(0xDFFFFF00).is_class_b()); + ASIO_CHECK(!address_v4(0xE0000000).is_class_b()); + ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_b()); + ASIO_CHECK(!address_v4(0xF0000000).is_class_b()); + ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_b()); + + ASIO_CHECK(!address_v4(0x01000000).is_class_c()); + ASIO_CHECK(!address_v4(0x7F000000).is_class_c()); + ASIO_CHECK(!address_v4(0x80000000).is_class_c()); + ASIO_CHECK(!address_v4(0xBFFF0000).is_class_c()); + ASIO_CHECK(address_v4(0xC0000000).is_class_c()); + ASIO_CHECK(address_v4(0xDFFFFF00).is_class_c()); + ASIO_CHECK(!address_v4(0xE0000000).is_class_c()); + ASIO_CHECK(!address_v4(0xEFFFFFFF).is_class_c()); + ASIO_CHECK(!address_v4(0xF0000000).is_class_c()); + ASIO_CHECK(!address_v4(0xFFFFFFFF).is_class_c()); +#endif // !defined(ASIO_NO_DEPRECATED) + + ASIO_CHECK(!address_v4(0x01000000).is_multicast()); + ASIO_CHECK(!address_v4(0x7F000000).is_multicast()); + ASIO_CHECK(!address_v4(0x80000000).is_multicast()); + ASIO_CHECK(!address_v4(0xBFFF0000).is_multicast()); + ASIO_CHECK(!address_v4(0xC0000000).is_multicast()); + ASIO_CHECK(!address_v4(0xDFFFFF00).is_multicast()); + ASIO_CHECK(address_v4(0xE0000000).is_multicast()); + ASIO_CHECK(address_v4(0xEFFFFFFF).is_multicast()); + ASIO_CHECK(!address_v4(0xF0000000).is_multicast()); + ASIO_CHECK(!address_v4(0xFFFFFFFF).is_multicast()); + + address_v4 a4 = address_v4::any(); + ASIO_CHECK(a4.to_bytes()[0] == 0); + ASIO_CHECK(a4.to_bytes()[1] == 0); + ASIO_CHECK(a4.to_bytes()[2] == 0); + ASIO_CHECK(a4.to_bytes()[3] == 0); + ASIO_CHECK(a4.to_uint() == 0); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(a4.to_ulong() == 0); +#endif // !defined(ASIO_NO_DEPRECATED) + + address_v4 a5 = address_v4::loopback(); + ASIO_CHECK(a5.to_bytes()[0] == 0x7F); + ASIO_CHECK(a5.to_bytes()[1] == 0); + ASIO_CHECK(a5.to_bytes()[2] == 0); + ASIO_CHECK(a5.to_bytes()[3] == 0x01); + ASIO_CHECK(a5.to_uint() == 0x7F000001); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(a5.to_ulong() == 0x7F000001); +#endif // !defined(ASIO_NO_DEPRECATED) + + address_v4 a6 = address_v4::broadcast(); + ASIO_CHECK(a6.to_bytes()[0] == 0xFF); + ASIO_CHECK(a6.to_bytes()[1] == 0xFF); + ASIO_CHECK(a6.to_bytes()[2] == 0xFF); + ASIO_CHECK(a6.to_bytes()[3] == 0xFF); + ASIO_CHECK(a6.to_uint() == 0xFFFFFFFF); +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(a6.to_ulong() == 0xFFFFFFFF); +#endif // !defined(ASIO_NO_DEPRECATED) + +#if !defined(ASIO_NO_DEPRECATED) + address_v4 class_a_net(0xFF000000); + address_v4 class_b_net(0xFFFF0000); + address_v4 class_c_net(0xFFFFFF00); + address_v4 other_net(0xFFFFFFFF); + ASIO_CHECK(address_v4::netmask(address_v4(0x01000000)) == class_a_net); + ASIO_CHECK(address_v4::netmask(address_v4(0x7F000000)) == class_a_net); + ASIO_CHECK(address_v4::netmask(address_v4(0x80000000)) == class_b_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xBFFF0000)) == class_b_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xC0000000)) == class_c_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xDFFFFF00)) == class_c_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xE0000000)) == other_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xEFFFFFFF)) == other_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xF0000000)) == other_net); + ASIO_CHECK(address_v4::netmask(address_v4(0xFFFFFFFF)) == other_net); +#endif // !defined(ASIO_NO_DEPRECATED) +} + +} // namespace ip_address_v4_runtime + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v4", + ASIO_TEST_CASE(ip_address_v4_compile::test) + ASIO_TEST_CASE(ip_address_v4_runtime::test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_iterator.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_iterator.cpp new file mode 100644 index 0000000..bad8a6f --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_iterator.cpp @@ -0,0 +1,27 @@ +// +// address_v4_iterator.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v4_iterator.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v4_iterator", + ASIO_TEST_CASE(null_test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_range.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_range.cpp new file mode 100644 index 0000000..8b3641c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v4_range.cpp @@ -0,0 +1,27 @@ +// +// address_v4_range.cpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v4_range.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v4_range", + ASIO_TEST_CASE(null_test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6.cpp new file mode 100644 index 0000000..15edacc --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6.cpp @@ -0,0 +1,409 @@ +// +// address_v6.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v6.hpp" + +#include "../unit_test.hpp" +#include + +//------------------------------------------------------------------------------ + +// ip_address_v6_compile test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that all public member functions on the class +// ip::address_v6 compile and link correctly. Runtime failures are ignored. + +namespace ip_address_v6_compile { + +void test() +{ + using namespace asio; + namespace ip = asio::ip; + + try + { + asio::error_code ec; + + // address_v6 constructors. + + ip::address_v6 addr1; + const ip::address_v6::bytes_type const_bytes_value = { { 0 } }; + ip::address_v6 addr2(const_bytes_value); + + // address_v6 functions. + + unsigned long scope_id = addr1.scope_id(); + addr1.scope_id(scope_id); + + bool b = addr1.is_unspecified(); + (void)b; + + b = addr1.is_loopback(); + (void)b; + + b = addr1.is_multicast(); + (void)b; + + b = addr1.is_link_local(); + (void)b; + + b = addr1.is_site_local(); + (void)b; + + b = addr1.is_v4_mapped(); + (void)b; + +#if !defined(ASIO_NO_DEPRECATED) + b = addr1.is_v4_compatible(); + (void)b; +#endif // !defined(ASIO_NO_DEPRECATED) + + b = addr1.is_multicast_node_local(); + (void)b; + + b = addr1.is_multicast_link_local(); + (void)b; + + b = addr1.is_multicast_site_local(); + (void)b; + + b = addr1.is_multicast_org_local(); + (void)b; + + b = addr1.is_multicast_global(); + (void)b; + + ip::address_v6::bytes_type bytes_value = addr1.to_bytes(); + (void)bytes_value; + + std::string string_value = addr1.to_string(); +#if !defined(ASIO_NO_DEPRECATED) + string_value = addr1.to_string(ec); +#endif // !defined(ASIO_NO_DEPRECATED) + +#if !defined(ASIO_NO_DEPRECATED) + ip::address_v4 addr3 = addr1.to_v4(); +#endif // !defined(ASIO_NO_DEPRECATED) + + // address_v6 static functions. + +#if !defined(ASIO_NO_DEPRECATED) + addr1 = ip::address_v6::from_string("0::0"); + addr1 = ip::address_v6::from_string("0::0", ec); + addr1 = ip::address_v6::from_string(string_value); + addr1 = ip::address_v6::from_string(string_value, ec); +#endif // !defined(ASIO_NO_DEPRECATED) + + addr1 = ip::address_v6::any(); + + addr1 = ip::address_v6::loopback(); + +#if !defined(ASIO_NO_DEPRECATED) + addr1 = ip::address_v6::v4_mapped(addr3); + + addr1 = ip::address_v6::v4_compatible(addr3); +#endif // !defined(ASIO_NO_DEPRECATED) + + // address_v6 comparisons. + + b = (addr1 == addr2); + (void)b; + + b = (addr1 != addr2); + (void)b; + + b = (addr1 < addr2); + (void)b; + + b = (addr1 > addr2); + (void)b; + + b = (addr1 <= addr2); + (void)b; + + b = (addr1 >= addr2); + (void)b; + + // address_v6 creation functions. + + addr1 = ip::make_address_v6(const_bytes_value, scope_id); + addr1 = ip::make_address_v6("0::0"); + addr1 = ip::make_address_v6("0::0", ec); + addr1 = ip::make_address_v6(string_value); + addr1 = ip::make_address_v6(string_value, ec); +#if defined(ASIO_HAS_STD_STRING_VIEW) +# if defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + std::experimental::string_view string_view_value("0::0"); +# else // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + std::string_view string_view_value("0::0"); +# endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) + addr1 = ip::make_address_v6(string_view_value); + addr1 = ip::make_address_v6(string_view_value, ec); +#endif // defined(ASIO_HAS_STD_STRING_VIEW) + + // address_v6 IPv4-mapped conversion. +#if defined(ASIO_NO_DEPRECATED) + ip::address_v4 addr3; +#endif // defined(ASIO_NO_DEPRECATED) + addr1 = ip::make_address_v6(ip::v4_mapped, addr3); + addr3 = ip::make_address_v4(ip::v4_mapped, addr1); + + // address_v6 I/O. + + std::ostringstream os; + os << addr1; + +#if !defined(BOOST_NO_STD_WSTREAMBUF) + std::wostringstream wos; + wos << addr1; +#endif // !defined(BOOST_NO_STD_WSTREAMBUF) + } + catch (std::exception&) + { + } +} + +} // namespace ip_address_v6_compile + +//------------------------------------------------------------------------------ + +// ip_address_v6_runtime test +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following test checks that the various public member functions meet the +// necessary postconditions. + +namespace ip_address_v6_runtime { + +void test() +{ + using asio::ip::address_v6; + + address_v6 a1; + ASIO_CHECK(a1.is_unspecified()); + ASIO_CHECK(a1.scope_id() == 0); + + address_v6::bytes_type b1 = {{ 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }}; + address_v6 a2(b1, 12345); + ASIO_CHECK(a2.to_bytes()[0] == 1); + ASIO_CHECK(a2.to_bytes()[1] == 2); + ASIO_CHECK(a2.to_bytes()[2] == 3); + ASIO_CHECK(a2.to_bytes()[3] == 4); + ASIO_CHECK(a2.to_bytes()[4] == 5); + ASIO_CHECK(a2.to_bytes()[5] == 6); + ASIO_CHECK(a2.to_bytes()[6] == 7); + ASIO_CHECK(a2.to_bytes()[7] == 8); + ASIO_CHECK(a2.to_bytes()[8] == 9); + ASIO_CHECK(a2.to_bytes()[9] == 10); + ASIO_CHECK(a2.to_bytes()[10] == 11); + ASIO_CHECK(a2.to_bytes()[11] == 12); + ASIO_CHECK(a2.to_bytes()[12] == 13); + ASIO_CHECK(a2.to_bytes()[13] == 14); + ASIO_CHECK(a2.to_bytes()[14] == 15); + ASIO_CHECK(a2.to_bytes()[15] == 16); + ASIO_CHECK(a2.scope_id() == 12345); + + address_v6 a3; + a3.scope_id(12345); + ASIO_CHECK(a3.scope_id() == 12345); + + address_v6 unspecified_address; + address_v6::bytes_type loopback_bytes = {{ 0 }}; + loopback_bytes[15] = 1; + address_v6 loopback_address(loopback_bytes); + address_v6::bytes_type link_local_bytes = {{ 0xFE, 0x80, 1 }}; + address_v6 link_local_address(link_local_bytes); + address_v6::bytes_type site_local_bytes = {{ 0xFE, 0xC0, 1 }}; + address_v6 site_local_address(site_local_bytes); + address_v6::bytes_type v4_mapped_bytes = {{ 0 }}; + v4_mapped_bytes[10] = 0xFF, v4_mapped_bytes[11] = 0xFF; + v4_mapped_bytes[12] = 1, v4_mapped_bytes[13] = 2; + v4_mapped_bytes[14] = 3, v4_mapped_bytes[15] = 4; + address_v6 v4_mapped_address(v4_mapped_bytes); + address_v6::bytes_type v4_compat_bytes = {{ 0 }}; + v4_compat_bytes[12] = 1, v4_compat_bytes[13] = 2; + v4_compat_bytes[14] = 3, v4_compat_bytes[15] = 4; + address_v6 v4_compat_address(v4_compat_bytes); + address_v6::bytes_type mcast_global_bytes = {{ 0xFF, 0x0E, 1 }}; + address_v6 mcast_global_address(mcast_global_bytes); + address_v6::bytes_type mcast_link_local_bytes = {{ 0xFF, 0x02, 1 }}; + address_v6 mcast_link_local_address(mcast_link_local_bytes); + address_v6::bytes_type mcast_node_local_bytes = {{ 0xFF, 0x01, 1 }}; + address_v6 mcast_node_local_address(mcast_node_local_bytes); + address_v6::bytes_type mcast_org_local_bytes = {{ 0xFF, 0x08, 1 }}; + address_v6 mcast_org_local_address(mcast_org_local_bytes); + address_v6::bytes_type mcast_site_local_bytes = {{ 0xFF, 0x05, 1 }}; + address_v6 mcast_site_local_address(mcast_site_local_bytes); + + ASIO_CHECK(!unspecified_address.is_loopback()); + ASIO_CHECK(loopback_address.is_loopback()); + ASIO_CHECK(!link_local_address.is_loopback()); + ASIO_CHECK(!site_local_address.is_loopback()); + ASIO_CHECK(!v4_mapped_address.is_loopback()); + ASIO_CHECK(!v4_compat_address.is_loopback()); + ASIO_CHECK(!mcast_global_address.is_loopback()); + ASIO_CHECK(!mcast_link_local_address.is_loopback()); + ASIO_CHECK(!mcast_node_local_address.is_loopback()); + ASIO_CHECK(!mcast_org_local_address.is_loopback()); + ASIO_CHECK(!mcast_site_local_address.is_loopback()); + + ASIO_CHECK(unspecified_address.is_unspecified()); + ASIO_CHECK(!loopback_address.is_unspecified()); + ASIO_CHECK(!link_local_address.is_unspecified()); + ASIO_CHECK(!site_local_address.is_unspecified()); + ASIO_CHECK(!v4_mapped_address.is_unspecified()); + ASIO_CHECK(!v4_compat_address.is_unspecified()); + ASIO_CHECK(!mcast_global_address.is_unspecified()); + ASIO_CHECK(!mcast_link_local_address.is_unspecified()); + ASIO_CHECK(!mcast_node_local_address.is_unspecified()); + ASIO_CHECK(!mcast_org_local_address.is_unspecified()); + ASIO_CHECK(!mcast_site_local_address.is_unspecified()); + + ASIO_CHECK(!unspecified_address.is_link_local()); + ASIO_CHECK(!loopback_address.is_link_local()); + ASIO_CHECK(link_local_address.is_link_local()); + ASIO_CHECK(!site_local_address.is_link_local()); + ASIO_CHECK(!v4_mapped_address.is_link_local()); + ASIO_CHECK(!v4_compat_address.is_link_local()); + ASIO_CHECK(!mcast_global_address.is_link_local()); + ASIO_CHECK(!mcast_link_local_address.is_link_local()); + ASIO_CHECK(!mcast_node_local_address.is_link_local()); + ASIO_CHECK(!mcast_org_local_address.is_link_local()); + ASIO_CHECK(!mcast_site_local_address.is_link_local()); + + ASIO_CHECK(!unspecified_address.is_site_local()); + ASIO_CHECK(!loopback_address.is_site_local()); + ASIO_CHECK(!link_local_address.is_site_local()); + ASIO_CHECK(site_local_address.is_site_local()); + ASIO_CHECK(!v4_mapped_address.is_site_local()); + ASIO_CHECK(!v4_compat_address.is_site_local()); + ASIO_CHECK(!mcast_global_address.is_site_local()); + ASIO_CHECK(!mcast_link_local_address.is_site_local()); + ASIO_CHECK(!mcast_node_local_address.is_site_local()); + ASIO_CHECK(!mcast_org_local_address.is_site_local()); + ASIO_CHECK(!mcast_site_local_address.is_site_local()); + + ASIO_CHECK(!unspecified_address.is_v4_mapped()); + ASIO_CHECK(!loopback_address.is_v4_mapped()); + ASIO_CHECK(!link_local_address.is_v4_mapped()); + ASIO_CHECK(!site_local_address.is_v4_mapped()); + ASIO_CHECK(v4_mapped_address.is_v4_mapped()); + ASIO_CHECK(!v4_compat_address.is_v4_mapped()); + ASIO_CHECK(!mcast_global_address.is_v4_mapped()); + ASIO_CHECK(!mcast_link_local_address.is_v4_mapped()); + ASIO_CHECK(!mcast_node_local_address.is_v4_mapped()); + ASIO_CHECK(!mcast_org_local_address.is_v4_mapped()); + ASIO_CHECK(!mcast_site_local_address.is_v4_mapped()); + +#if !defined(ASIO_NO_DEPRECATED) + ASIO_CHECK(!unspecified_address.is_v4_compatible()); + ASIO_CHECK(!loopback_address.is_v4_compatible()); + ASIO_CHECK(!link_local_address.is_v4_compatible()); + ASIO_CHECK(!site_local_address.is_v4_compatible()); + ASIO_CHECK(!v4_mapped_address.is_v4_compatible()); + ASIO_CHECK(v4_compat_address.is_v4_compatible()); + ASIO_CHECK(!mcast_global_address.is_v4_compatible()); + ASIO_CHECK(!mcast_link_local_address.is_v4_compatible()); + ASIO_CHECK(!mcast_node_local_address.is_v4_compatible()); + ASIO_CHECK(!mcast_org_local_address.is_v4_compatible()); + ASIO_CHECK(!mcast_site_local_address.is_v4_compatible()); +#endif // !defined(ASIO_NO_DEPRECATED) + + ASIO_CHECK(!unspecified_address.is_multicast()); + ASIO_CHECK(!loopback_address.is_multicast()); + ASIO_CHECK(!link_local_address.is_multicast()); + ASIO_CHECK(!site_local_address.is_multicast()); + ASIO_CHECK(!v4_mapped_address.is_multicast()); + ASIO_CHECK(!v4_compat_address.is_multicast()); + ASIO_CHECK(mcast_global_address.is_multicast()); + ASIO_CHECK(mcast_link_local_address.is_multicast()); + ASIO_CHECK(mcast_node_local_address.is_multicast()); + ASIO_CHECK(mcast_org_local_address.is_multicast()); + ASIO_CHECK(mcast_site_local_address.is_multicast()); + + ASIO_CHECK(!unspecified_address.is_multicast_global()); + ASIO_CHECK(!loopback_address.is_multicast_global()); + ASIO_CHECK(!link_local_address.is_multicast_global()); + ASIO_CHECK(!site_local_address.is_multicast_global()); + ASIO_CHECK(!v4_mapped_address.is_multicast_global()); + ASIO_CHECK(!v4_compat_address.is_multicast_global()); + ASIO_CHECK(mcast_global_address.is_multicast_global()); + ASIO_CHECK(!mcast_link_local_address.is_multicast_global()); + ASIO_CHECK(!mcast_node_local_address.is_multicast_global()); + ASIO_CHECK(!mcast_org_local_address.is_multicast_global()); + ASIO_CHECK(!mcast_site_local_address.is_multicast_global()); + + ASIO_CHECK(!unspecified_address.is_multicast_link_local()); + ASIO_CHECK(!loopback_address.is_multicast_link_local()); + ASIO_CHECK(!link_local_address.is_multicast_link_local()); + ASIO_CHECK(!site_local_address.is_multicast_link_local()); + ASIO_CHECK(!v4_mapped_address.is_multicast_link_local()); + ASIO_CHECK(!v4_compat_address.is_multicast_link_local()); + ASIO_CHECK(!mcast_global_address.is_multicast_link_local()); + ASIO_CHECK(mcast_link_local_address.is_multicast_link_local()); + ASIO_CHECK(!mcast_node_local_address.is_multicast_link_local()); + ASIO_CHECK(!mcast_org_local_address.is_multicast_link_local()); + ASIO_CHECK(!mcast_site_local_address.is_multicast_link_local()); + + ASIO_CHECK(!unspecified_address.is_multicast_node_local()); + ASIO_CHECK(!loopback_address.is_multicast_node_local()); + ASIO_CHECK(!link_local_address.is_multicast_node_local()); + ASIO_CHECK(!site_local_address.is_multicast_node_local()); + ASIO_CHECK(!v4_mapped_address.is_multicast_node_local()); + ASIO_CHECK(!v4_compat_address.is_multicast_node_local()); + ASIO_CHECK(!mcast_global_address.is_multicast_node_local()); + ASIO_CHECK(!mcast_link_local_address.is_multicast_node_local()); + ASIO_CHECK(mcast_node_local_address.is_multicast_node_local()); + ASIO_CHECK(!mcast_org_local_address.is_multicast_node_local()); + ASIO_CHECK(!mcast_site_local_address.is_multicast_node_local()); + + ASIO_CHECK(!unspecified_address.is_multicast_org_local()); + ASIO_CHECK(!loopback_address.is_multicast_org_local()); + ASIO_CHECK(!link_local_address.is_multicast_org_local()); + ASIO_CHECK(!site_local_address.is_multicast_org_local()); + ASIO_CHECK(!v4_mapped_address.is_multicast_org_local()); + ASIO_CHECK(!v4_compat_address.is_multicast_org_local()); + ASIO_CHECK(!mcast_global_address.is_multicast_org_local()); + ASIO_CHECK(!mcast_link_local_address.is_multicast_org_local()); + ASIO_CHECK(!mcast_node_local_address.is_multicast_org_local()); + ASIO_CHECK(mcast_org_local_address.is_multicast_org_local()); + ASIO_CHECK(!mcast_site_local_address.is_multicast_org_local()); + + ASIO_CHECK(!unspecified_address.is_multicast_site_local()); + ASIO_CHECK(!loopback_address.is_multicast_site_local()); + ASIO_CHECK(!link_local_address.is_multicast_site_local()); + ASIO_CHECK(!site_local_address.is_multicast_site_local()); + ASIO_CHECK(!v4_mapped_address.is_multicast_site_local()); + ASIO_CHECK(!v4_compat_address.is_multicast_site_local()); + ASIO_CHECK(!mcast_global_address.is_multicast_site_local()); + ASIO_CHECK(!mcast_link_local_address.is_multicast_site_local()); + ASIO_CHECK(!mcast_node_local_address.is_multicast_site_local()); + ASIO_CHECK(!mcast_org_local_address.is_multicast_site_local()); + ASIO_CHECK(mcast_site_local_address.is_multicast_site_local()); + + ASIO_CHECK(address_v6::loopback().is_loopback()); +} + +} // namespace ip_address_v6_runtime + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v6", + ASIO_TEST_CASE(ip_address_v6_compile::test) + ASIO_TEST_CASE(ip_address_v6_runtime::test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_iterator.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_iterator.cpp new file mode 100644 index 0000000..1749134 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_iterator.cpp @@ -0,0 +1,27 @@ +// +// address_v6_iterator.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v6_iterator.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v6_iterator", + ASIO_TEST_CASE(null_test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_range.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_range.cpp new file mode 100644 index 0000000..dd2fe60 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/asio/asio/src/tests/unit/ip/address_v6_range.cpp @@ -0,0 +1,27 @@ +// +// address_v6_range.cpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/ip/address_v6_range.hpp" + +#include "../unit_test.hpp" + +//------------------------------------------------------------------------------ + +ASIO_TEST_SUITE +( + "ip/address_v6_range", + ASIO_TEST_CASE(null_test) +) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp index 65b937c..656e16d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp @@ -88,6 +88,7 @@ #endif #include +#include #include #include #include @@ -321,20 +322,28 @@ namespace openvpn { { const std::string title = "remote-override"; ClientAPI::RemoteOverride ro; - parent->remote_override(ro); - if (!ro.error.empty()) - throw Exception("remote override exception: " + ro.error); + try { + parent->remote_override(ro); + } + catch (const std::exception& e) + { + ro.error = e.what(); + } RemoteList::Item::Ptr ri(new RemoteList::Item); - if (!ro.ip.empty()) - ri->set_ip_addr(IP::Addr(ro.ip, title)); - if (ro.host.empty()) - ro.host = ro.ip; - HostPort::validate_host(ro.host, title); - HostPort::validate_port(ro.port, title); - ri->server_host = std::move(ro.host); - ri->server_port = std::move(ro.port); - ri->transport_protocol = Protocol::parse(ro.proto, Protocol::CLIENT_SUFFIX, title.c_str()); - + if (ro.error.empty()) + { + if (!ro.ip.empty()) + ri->set_ip_addr(IP::Addr(ro.ip, title)); + if (ro.host.empty()) + ro.host = ro.ip; + HostPort::validate_host(ro.host, title); + HostPort::validate_port(ro.port, title); + ri->server_host = std::move(ro.host); + ri->server_port = std::move(ro.port); + ri->transport_protocol = Protocol::parse(ro.proto, Protocol::CLIENT_SUFFIX, title.c_str()); + } + else + throw Exception("remote override exception: " + ro.error); return ri; } else @@ -542,10 +551,12 @@ namespace openvpn { void setup_async_stop_scopes() { stop_scope_local.reset(new AsioStopScope(*io_context(), async_stop_local(), [this]() { + OPENVPN_ASYNC_HANDLER; session->graceful_stop(); })); stop_scope_global.reset(new AsioStopScope(*io_context(), async_stop_global(), [this]() { + OPENVPN_ASYNC_HANDLER; trigger_async_stop_local(); })); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp index 0d5bc92..06575a4 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp @@ -551,7 +551,7 @@ namespace openvpn { virtual bool remote_override_enabled(); virtual void remote_override(RemoteOverride&); - // Periodic convenience clock tick, controlled by Config::clock_tick_ms + // Periodic convenience clock tick, controlled by Config::clockTickMS virtual void clock_tick(); // Do a crypto library self test @@ -610,3 +610,4 @@ namespace openvpn { } #endif + diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/cityhash/build-cityhash b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/cityhash/build-cityhash new file mode 100755 index 0000000..d5835f6 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/cityhash/build-cityhash @@ -0,0 +1,64 @@ +#!/usr/bin/env bash + +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree + exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to dependency build folder + exit 1 +fi +if [ -z "$DL" ]; then + echo DL var must point to the download folder + exit 1 +fi + +if [ -z "$TARGET" ]; then + echo TARGET var must be defined + exit 1 +fi + +# source vars +. $O3/core/vars/vars-${TARGET} +. $O3/core/deps/lib-versions + +# source helper functions +. $O3/core/deps/functions.sh + +FNAME=cityhash-${CITYHASH_VERSION}.tar.gz +PN=${CITYHASH_VERSION#*-} +URL=https://codeload.github.com/google/cityhash/tar.gz/${CITYHASH_VERSION} +CSUM=${CITYHASH_CSUM} + +download + +CC=cc +LD=ld +AR=ar +RANLIB=ranlib +[ "$GCC_CMD" ] && CC=$GCC_CMD +[ "$LD_CMD" ] && LD=$LD_CMD +[ "$AR_CMD" ] && AR=$AR_CMD +[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD + +if [ "$NO_WIPE" != "1" ]; then + rm -rf $CITYHASH_VERSION + tar xfz $DL/cityhash-$CITYHASH_VERSION.tar.gz +fi + +DIST=$(pwd)/cityhash/cityhash-$PLATFORM +rm -rf $DIST +mkdir -p $DIST/include +mkdir $DIST/lib +cd cityhash-$CITYHASH_VERSION +CMD=./configure +echo $CMD +$CMD +CMD="$CC $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -I. -Isrc -c src/city.cc" +echo $CMD +$CMD +$AR rc $DIST/lib/libcityhash.a city.o +$RANLIB $DIST/lib/libcityhash.a +cp src/city.h $DIST/include/ +exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions index a508af1..e7d16dd 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions @@ -14,3 +14,6 @@ export JSONCPP_CSUM=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219a export TAP_VERSION=0e30f5c13b3c7b0bdd60da915350f653e4c14d92 export TAP_CSUM=8ff65f9e741c5ecfe1af904eaa38713f05639ce9457ef92041fd8e6b2a170315 + +export CITYHASH_VERSION=8af9b8c2b889d80c22d6bc26ba0df1afb79a30db +export CITYHASH_CSUM=f70368facd15735dffc77fe2b27ab505bfdd05be5e9166d94149a8744c212f49 \ No newline at end of file diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lz4/build-lz4 b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lz4/build-lz4 index 30a5c86..53777d0 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lz4/build-lz4 +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lz4/build-lz4 @@ -47,6 +47,11 @@ if [ "$NO_WIPE" != "1" ]; then tar xfz $DL/$LZ4_VERSION.tar.gz fi +if [ "x$NO_BUILD" == x1 ]; then + echo "Not building" + exit +fi + DIST=$(pwd)/lz4/lz4-$PLATFORM rm -rf $DIST mkdir -p $DIST/include diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/build-mbedtls b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/build-mbedtls index a12e376..a962ad9 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/build-mbedtls +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/build-mbedtls @@ -54,6 +54,11 @@ else apply_patches "mbedtls" fi +if [ "x$NO_BUILD" == x1 ]; then + echo "Not building" + exit 0 +fi + if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then # run unit tests and then clean echo RUNNING CHECK diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0007-cmake-build.patch b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0007-cmake-build.patch new file mode 100644 index 0000000..2c521a8 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/mbedtls/patches/0007-cmake-build.patch @@ -0,0 +1,28 @@ +From 5d31999442a41c154f6c56e91c8fe7705c74e2be Mon Sep 17 00:00:00 2001 +From: Arne Schwabe +Date: Thu, 28 Dec 2017 00:19:10 +0100 +Subject: [PATCH] Use current cmake directory instead of source root directory + when exuting config.pl + +When mdbedtls is added as a subdirectory to another project this will +call config.pl with the right path If mbedtls is build standalone +current and root source directory are identical. + +Signed-off-by: Arne Schwabe +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3e47224ea1..2883eff270 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -31,7 +31,7 @@ find_package(Perl) + if(PERL_FOUND) + + # If NULL Entropy is configured, display an appropriate warning +- execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY ++ execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY + RESULT_VARIABLE result) + if(${result} EQUAL 0) + message(WARNING ${NULL_ENTROPY_WARNING}) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj index 642a62b..4df459d 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE8201F0DB80003272D /* IOKit.framework */; }; DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEA201F0DDC0003272D /* CoreServices.framework */; }; DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEC201F0E0E0003272D /* libmbedtls.a */; }; + DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF838B402090AC2F00B68F90 /* liblz4.a */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -36,6 +37,7 @@ DF380AE8201F0DB80003272D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; DF380AEA201F0DDC0003272D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; DF380AEC201F0E0E0003272D /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = "../../../deps/mbedtls/mbedtls-osx/library/libmbedtls.a"; sourceTree = ""; }; + DF838B402090AC2F00B68F90 /* liblz4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblz4.a; path = "../../../deps/lz4/lz4-osx/lib/liblz4.a"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -43,6 +45,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */, DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */, DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */, DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */, @@ -83,6 +86,7 @@ DF380AE3201F0D4F0003272D /* Frameworks */ = { isa = PBXGroup; children = ( + DF838B402090AC2F00B68F90 /* liblz4.a */, DF380AEC201F0E0E0003272D /* libmbedtls.a */, DF380AEA201F0DDC0003272D /* CoreServices.framework */, DF380AE8201F0DB80003272D /* IOKit.framework */, @@ -267,13 +271,19 @@ USE_ASIO, ASIO_STANDALONE, USE_MBEDTLS, + HAVE_LZ4, + LZ4_DISABLE_DEPRECATE_WARNINGS, ); HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../..\"", "\"$(SRCROOT)/../../../deps/asio/asio/include\"", "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", ); - LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\""; PRODUCT_NAME = "$(TARGET_NAME)"; STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; }; @@ -287,13 +297,19 @@ USE_ASIO, ASIO_STANDALONE, USE_MBEDTLS, + HAVE_LZ4, + LZ4_DISABLE_DEPRECATE_WARNINGS, ); HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/../..\"", "\"$(SRCROOT)/../../../deps/asio/asio/include\"", "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", + "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", ); - LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\""; PRODUCT_NAME = "$(TARGET_NAME)"; STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; }; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/quoteip.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/quoteip.hpp new file mode 100644 index 0000000..cab2b8b --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/quoteip.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-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 + +namespace openvpn { + + // return ip_addr in brackets if it is IPv6 + std::string quote_ip(const std::string& ip_addr) + { + if (ip_addr.find(':') != std::string::npos) + return '[' + ip_addr + ']'; + else + return ip_addr; + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp new file mode 100644 index 0000000..73ffd1d --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/randaddr.hpp @@ -0,0 +1,59 @@ +// 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 + +namespace openvpn { + namespace IP { + + inline Addr random_addr(const Addr::Version v, RandomAPI& prng) + { + switch (v) + { + case Addr::V4: + return Addr::from_ipv4(IPv4::Addr::from_uint32(prng.rand_get())); + case Addr::V6: + { + unsigned char bytes[16]; + prng.rand_fill(bytes); + return Addr::from_ipv6(IPv6::Addr::from_byte_string(bytes)); + } + default: + throw ip_exception("address unspecified"); + } + } + + inline Route random_subnet(const Route& templ, + const unsigned int prefix_len, + RandomAPI& prng) + { + if (!templ.is_canonical()) + throw Exception("IP::random_subnet: template route not canonical: " + templ.to_string()); + return Route(((random_addr(templ.addr.version(), prng) & ~templ.netmask()) | templ.addr) + & Addr::netmask_from_prefix_len(templ.addr.version(), prefix_len), + prefix_len); + } + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/route.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/route.hpp index 0aa1fdd..730c2bf 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/route.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/addr/route.hpp @@ -176,6 +176,11 @@ namespace openvpn { return std::tie(prefix_len, addr) == std::tie(other.prefix_len, other.addr); } + bool operator!=(const RouteType& other) const + { + return std::tie(prefix_len, addr) != std::tie(other.prefix_len, other.addr); + } + bool operator<(const RouteType& other) const { return std::tie(prefix_len, addr) < std::tie(other.prefix_len, other.addr); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcreds.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcreds.hpp index 43fec46..fcc3a4a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcreds.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/authcreds.hpp @@ -55,15 +55,15 @@ namespace openvpn { return !username.empty(); } - bool is_valid_user_pass() const + bool is_valid_user_pass(const bool strict) const { - return ValidateCreds::is_valid(ValidateCreds::USERNAME, username) - && ValidateCreds::is_valid(ValidateCreds::PASSWORD, password); + return ValidateCreds::is_valid(ValidateCreds::USERNAME, username, strict) + && ValidateCreds::is_valid(ValidateCreds::PASSWORD, password, strict); } - bool is_valid() const + bool is_valid(const bool strict) const { - return defined() && is_valid_user_pass(); + return defined() && is_valid_user_pass(strict); } void wipe_password() diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/validatecreds.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/validatecreds.hpp index fe02f34..8a71afc 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/validatecreds.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/auth/validatecreds.hpp @@ -38,22 +38,30 @@ namespace openvpn { }; template - static bool is_valid(const Type type, const STRING& cred) + static bool is_valid(const Type type, const STRING& cred, const bool strict) { size_t max_len_flags; - switch (type) + if (strict) { - case USERNAME: - // length <= 256 unicode chars, no control chars allowed - max_len_flags = 256 | Unicode::UTF8_NO_CTRL; - break; - case PASSWORD: - case RESPONSE: - // length <= 16384 unicode chars - max_len_flags = 16384; - break; - default: - return false; + // length <= 512 unicode chars, no control chars allowed + max_len_flags = 512 | Unicode::UTF8_NO_CTRL; + } + else + { + switch (type) + { + case USERNAME: + // length <= 512 unicode chars, no control chars allowed + max_len_flags = 512 | Unicode::UTF8_NO_CTRL; + break; + case PASSWORD: + case RESPONSE: + // length <= 16384 unicode chars + max_len_flags = 16384; + break; + default: + return false; + } } return Unicode::is_valid_utf8(cred, max_len_flags); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp index 41851b1..7b6b68e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliconnect.hpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -173,6 +174,7 @@ namespace openvpn { if (!halt) openvpn_io::post(io_context, [self=Ptr(this)]() { + OPENVPN_ASYNC_HANDLER; self->graceful_stop(); }); } @@ -220,6 +222,7 @@ namespace openvpn { restart_wait_timer.expires_after(Time::Duration::seconds(seconds)); restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->restart_wait_callback(gen, error); }); } @@ -230,6 +233,7 @@ namespace openvpn { if (!halt) openvpn_io::post(io_context, [self=Ptr(this), reason]() { + OPENVPN_ASYNC_HANDLER; self->pause(reason); }); } @@ -239,6 +243,7 @@ namespace openvpn { if (!halt) openvpn_io::post(io_context, [self=Ptr(this)]() { + OPENVPN_ASYNC_HANDLER; self->resume(); }); } @@ -248,6 +253,7 @@ namespace openvpn { if (!halt) openvpn_io::post(io_context, [self=Ptr(this), seconds]() { + OPENVPN_ASYNC_HANDLER; self->reconnect(seconds); }); } @@ -268,6 +274,7 @@ namespace openvpn { if (!halt) openvpn_io::post(io_context, [self=Ptr(this), msg=std::move(msg)]() { + OPENVPN_ASYNC_HANDLER; self->post_cc_msg(msg); }); } @@ -351,6 +358,7 @@ namespace openvpn { conn_timer.expires_after(Time::Duration::seconds(conn_timeout)); conn_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->conn_timer_callback(gen, error); }); conn_timer_pending = true; @@ -399,6 +407,7 @@ namespace openvpn { restart_wait_timer.expires_after(Time::Duration::milliseconds(delay_ms)); restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->restart_wait_callback(gen, error); }); } @@ -602,6 +611,7 @@ namespace openvpn { server_poll_timer.expires_after(client_options->server_poll_timeout()); server_poll_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->server_poll_callback(gen, error); }); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp index d865646..26d4983 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/clievent.hpp @@ -41,6 +41,7 @@ namespace openvpn { DISCONNECTED=0, CONNECTED, RECONNECTING, + AUTH_PENDING, RESOLVE, WAIT, WAIT_PROXY, @@ -93,6 +94,7 @@ namespace openvpn { "DISCONNECTED", "CONNECTED", "RECONNECTING", + "AUTH_PENDING", "RESOLVE", "WAIT", "WAIT_PROXY", @@ -210,6 +212,11 @@ namespace openvpn { Reconnecting() : Base(RECONNECTING) {} }; + struct AuthPending : public Base + { + AuthPending() : Base(AUTH_PENDING) {} + }; + struct GetConfig : public Base { GetConfig() : Base(GET_CONFIG) {} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp index 0ebb576..ba3a942 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp @@ -649,6 +649,23 @@ namespace openvpn { else cli_events->add_event(std::move(ev)); } + else if (info && string::starts_with(msg, "INFO_PRE,")) + { + // INFO_PRE is like INFO but it is never buffered + ClientEvent::Base::Ptr ev = new ClientEvent::Info(msg.substr(9)); + cli_events->add_event(std::move(ev)); + } + else if (msg == "AUTH_PENDING") + { + // AUTH_PENDING indicates an out-of-band authentication step must + // be performed before the server will send the PUSH_REPLY message. + if (!auth_pending) + { + auth_pending = true; + ClientEvent::Base::Ptr ev = new ClientEvent::AuthPending(); + cli_events->add_event(std::move(ev)); + } + } else if (msg == "RELAY") { if (Base::conf().relay_mode) @@ -761,9 +778,22 @@ namespace openvpn { set_housekeeping_timer(); { - const Time::Duration newdur = std::min(dur + Time::Duration::seconds(1), - Time::Duration::seconds(3)); - schedule_push_request_callback(newdur); + if (auth_pending) + { + // With auth_pending, we can dial back the PUSH_REQUEST + // frequency, but we still need back-and-forth network + // activity to avoid an inactivity timeout, since the crypto + // layer (and hence keepalive ping) is not initialized until + // we receive the PUSH_REPLY from the server. + schedule_push_request_callback(Time::Duration::seconds(8)); + } + else + { + // step function with ceiling: 1 sec, 2 secs, 3 secs, 3, 3, ... + const Time::Duration newdur = std::min(dur + Time::Duration::seconds(1), + Time::Duration::seconds(3)); + schedule_push_request_callback(newdur); + } } } } @@ -780,6 +810,7 @@ namespace openvpn { push_request_timer.expires_after(dur); push_request_timer.async_wait([self=Ptr(this), dur](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->send_push_request_callback(dur, error); }); } @@ -855,6 +886,7 @@ namespace openvpn { housekeeping_timer.expires_at(next); housekeeping_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->housekeeping_callback(error); }); } @@ -888,6 +920,7 @@ namespace openvpn { inactive_timer.expires_after(inactive_duration); inactive_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->inactive_callback(error); }); } @@ -978,6 +1011,7 @@ namespace openvpn { info_hold_timer.expires_after(Time::Duration::seconds(1)); info_hold_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->info_hold_callback(error); }); } @@ -1042,6 +1076,7 @@ namespace openvpn { bool first_packet_received_ = false; bool sent_push_request = false; + bool auth_pending = false; SessionStats::Ptr cli_stats; ClientEvent::Queue::Ptr cli_events; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp index b9285bc..458a90a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp @@ -341,6 +341,7 @@ namespace openvpn { resolver.async_resolve(item.server_host, item.server_port, [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::tcp::resolver::results_type results) { + OPENVPN_ASYNC_HANDLER; self->resolve_callback(error, results); }); return; @@ -587,18 +588,19 @@ namespace openvpn { { if (remote_override) { - list.clear(); - index.reset(); Item::Ptr item = remote_override->get(); if (item) - list.push_back(std::move(item)); - } - else - { - index.increment(list.size(), secondary_length(index.primary())); - if (!enable_cache) - reset_item(index.primary()); + { + list.clear(); + index.reset(); + list.push_back(std::move(item)); + return; + } } + + index.increment(list.size(), secondary_length(index.primary())); + if (!enable_cache) + reset_item(index.primary()); } // Return details about current connection entry. diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp new file mode 100644 index 0000000..ebd1667 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.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-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 . + +// Macro to maintain thread-safety. + +// Platforms like UWP and iOS may call core methods +// from another threads. Since core is not thread-safe, +// we provide OPENVPN_ASYNC_HANDLER macro which instantiates +// lock guard. It follows RIAA principle and locks global +// mutex in constructor and unlocks in destructor. This +// guarantees that code in block protected with this macro +// won't be called simultaneously from different threads. + +#ifndef OPENVPN_COMMON_BIGMUTEX_H +#define OPENVPN_COMMON_BIGMUTEX_H + +#include + +namespace openvpn { + namespace bigmutex { + std::recursive_mutex the_recursive_mutex; + } + + #ifdef OPENVPN_ENABLE_BIGMUTEX + #define OPENVPN_ASYNC_HANDLER \ + std::lock_guard lg(bigmutex::the_recursive_mutex); + #else + #define OPENVPN_ASYNC_HANDLER + #endif +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp index eb3f927..22fa166 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/hexstr.hpp @@ -33,6 +33,18 @@ namespace openvpn { + /** + * Renders an integer value within the hexadecimal range (0-15) + * to a hexadecimal character. + * + * @param c Integer to render as a hexadecimal character. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a char with the hexadecimal representation of + * the input value. If the value is out-of-range (outside + * of 0-15), it will be replaced with a questionmark (?). + */ inline char render_hex_char(const int c, const bool caps=false) { if (c < 10) @@ -43,6 +55,18 @@ namespace openvpn { return '?'; } + + /** + * Parses a character in the range {0..9,A-F,a-f} to an + * integer value. Used to convert hexadecimal character to integer. + * Only a single character is parsed by this function. + * + * @param c Character to be be parsed. + * + * @return Returns an integer value of the hexadecimal input. If the + * input character is invalid, outside of {0..9,A-F,a-f}, it will + * return -1. + */ inline int parse_hex_char(const char c) { if (c >= '0' && c <= '9') @@ -55,9 +79,20 @@ namespace openvpn { return -1; } + + /** + * Class which Renders a single byte as hexadecimal + */ class RenderHexByte { public: + /** + * Initializes a new object + * + * @param byte Unsigned char (one byte) to be processed + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + */ RenderHexByte(const unsigned char byte, const bool caps=false) { c[0] = render_hex_char(byte >> 4, caps); @@ -67,12 +102,31 @@ namespace openvpn { char char1() const { return c[0]; } char char2() const { return c[1]; } + /** + * Retrieve the hexadecimal representation of the value. + * Warning: The result is a non-NULL terminated string. + * + * @return Returns a non-NULL terminated 2 byte string with the hexadecimal + * representation of the initial value. The return value is guaranteed + * to always be 2 bytes. + */ const char *str2() const { return c; } // Note: length=2, NOT null terminated private: char c[2]; }; + + /** + * Render a byte buffer (unsigned char *) as a hexadecimal string. + * + * @param data Unsigned char pointer to buffer to render. + * @param size size_t of the number of bytes to parse from the buffer. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string of the complete hexadecimal representation + */ inline std::string render_hex(const unsigned char *data, size_t size, const bool caps=false) { if (!data) @@ -88,11 +142,36 @@ namespace openvpn { return ret; } + + /** + * Render a byte buffer (void *) as a hexadecimal string. + * + * @param data Void pointer to buffer to render. + * @param size size_t of the number of bytes to parse from the buffer. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string of the complete hexadecimal representation. + */ inline std::string render_hex(const void *data, const size_t size, const bool caps=false) { return render_hex((const unsigned char *)data, size, caps); } + + /** + * Variant of @render_hex(const unsiged char *,...) which adds a + * separator between each byte + * + * @param data Unsigned char pointer to buffer to render. + * @param size size_t of the number of bytes to parse from the buffer. + * @param sep A single character to use as the separator. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string of the complete hexadecimal representation + * with each byte separated by a given character. + */ inline std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps=false) { if (!data) @@ -112,11 +191,36 @@ namespace openvpn { return ret; } + /** + * Variant of @render_hex(const void *,...) which adds a + * separator between each byte + + * @param data Void pointer to buffer to render. + * @param size size_t of the number of bytes to parse from the buffer. + * @param sep A single character to use as the separator. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string of the complete hexadecimal representation + * with each byte separated by a given character. + */ inline std::string render_hex_sep(const void *data, const size_t size, const char sep, const bool caps=false) { return render_hex_sep((const unsigned char *)data, size, sep, caps); } + + /** + * Render a std::vector container as a hexadecimal string. + * T must be a data type compatible with + * RenderHexByte(const unsigned char,...) + * + * @param data std::vector containing the data to render + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string of the complete hexadecimal representation. + */ template inline std::string render_hex_generic(const V& data, const bool caps=false) { @@ -131,6 +235,18 @@ namespace openvpn { return ret; } + + /** + * 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 Unsigned char 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(const unsigned char *data, size_t size) { if (!data) @@ -163,19 +279,56 @@ namespace openvpn { return os.str(); } + + /** + * Renders a combined hexadecimal and character dump of a std::string buffer, + * with the typical 16 bytes split between hexadecimal and character + * separation per line. + * + * @param data std::string containing the buffer to render + * + * @return Returns a string containing a preformatted output of the + * hexadecimal dump. + */ inline std::string dump_hex(const std::string& str) { return dump_hex((const unsigned char *)str.c_str(), str.length()); } + + /** + * Renders a combined hexadecimal and character dump of a std::vector + * based buffer, with the typical 16 bytes split between hexadecimal and + * character separation per line. + * + * @param data std::vector containing the buffer to render + * + * @return Returns a string containing a preformatted output of the + * hexadecimal dump. + */ template inline std::string dump_hex(const V& data) { return dump_hex(data.c_data(), data.size()); } + /** + * Declaration of a hexadecimal parsing error exception class + */ OPENVPN_SIMPLE_EXCEPTION(parse_hex_error); + + /** + * Parses a std::string containing a hexadecimal value into + * a std::vector. + * + * @param dest std::vector destination buffer to use. + * @param str std::string& containing the hexadecimal string to parse. + * + * @return Returns nothing on success. Will throw a parse_hex_error + * exception if the input is invalid/not parseable as a hexadecimal + * number. + */ template inline void parse_hex(V& dest, const std::string& str) { @@ -193,7 +346,19 @@ namespace openvpn { throw parse_hex_error(); // straggler char } - // note -- currently doesn't detect overflow + + /** + * Parses a char buffer (C string) containing a hexadecimal + * string into a templated (T) variable. The input buffer + * MUST be NULL terminated. + * + * WARNING: There are _NO_ overflow checks. + * + * @param str Char pointer (char *) to the buffer to be parsed. + * @param retval Return buffer where the parsed value is stored. + * + * @return Returns true on successful parsing, otherwise false. + */ template inline bool parse_hex_number(const char *str, T& retval) { @@ -220,12 +385,37 @@ namespace openvpn { } } + + /** + * Variant of @parse_hex_number(const char *, ...) which takes a std::string + * as the input. + * + * @param str std::string containing the hexadecimal string to be parsed. + * @param retval Return buffer where the parsed value is stored. + * + * @return Returns true on successful parsing, otherwise false. + */ template inline bool parse_hex_number(const std::string& str, T& retval) { return parse_hex_number(str.c_str(), retval); } + + /** + * Parses a std::string containing a hexadecimal + * string into a templated (T) variable. + * + * NOTE: Currently doesn't detect overflow + * + * @param str std::string containing the hexadecimal + * string to be parsed. + * + * @return Returns a template T variable containing the + * parsed value on success. Will throw the parse_hex_error + * exception on parsing errors. + * + */ template inline T parse_hex_number(const std::string& str) { @@ -235,6 +425,18 @@ namespace openvpn { return ret; } + /** + * Renders a templated T variable containing a numeric value + * into a std::string containing a hexadecimal representation. + * + * @param value Numeric (T) value to represent as hexadecimal. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Retuns a std::string containing the hexadecimal + * representation on succes. Will throw a parse_hex_error + * exception on parsing errors. + */ template inline std::string render_hex_number(T value, const bool caps=false) { @@ -247,6 +449,18 @@ namespace openvpn { return render_hex(buf, sizeof(T), caps); } + + /** + * Renders a single byte as a hexadecimal string + * + * @param value Unsigned char (byte) to be represented as hexadecimal. + * @param caps Boolean (default false) which sets the outout to + * be either lower case (false) or upper case (true). + * + * @return Returns a std::string with the hexadecimal representation + * of the input value. The result will always contain only + * two characters. + */ inline std::string render_hex_number(unsigned char uc, const bool caps=false) { RenderHexByte b(uc, caps); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp index ea42208..8627b8f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/rc.hpp @@ -313,6 +313,11 @@ namespace openvpn { return rc; } + static constexpr bool is_thread_safe() + { + return false; + } + #ifdef OPENVPN_RC_NOTIFY void notify_release() noexcept { @@ -394,6 +399,11 @@ namespace openvpn { return rc.load(std::memory_order_relaxed); } + static constexpr bool is_thread_safe() + { + return true; + } + #ifdef OPENVPN_RC_NOTIFY void notify_release() noexcept { @@ -454,6 +464,11 @@ namespace openvpn { return refcount_.use_count(); } + static constexpr bool is_thread_safe() + { + return RCImpl::is_thread_safe(); + } + private: RC(const RC&) = delete; RC& operator=(const RC&) = delete; 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 bf71137..8fe303c 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/sess_id.hpp @@ -54,9 +54,10 @@ namespace openvpn { } // Create a random Session ID. - explicit SessionIDType(RandomAPI& rng) + explicit SessionIDType(RandomAPI& rng, const bool allow_noncrypto_rng=false) { - rng.assert_crypto(); + if (!allow_noncrypto_rng) + rng.assert_crypto(); rng.rand_bytes(u.data, sizeof(u.data)); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp index 21d4a65..99720f8 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp @@ -4,7 +4,7 @@ // packet encryption, packet authentication, and // packet compression. // -// Copyright (C) 2012-2017 OpenVPN Inc. +// Copyright (C) 2012-2018 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 @@ -21,9 +21,8 @@ // Current version of the OpenVPN core -#ifndef OPENVPN_COMMON_VERSION_H -#define OPENVPN_COMMON_VERSION_H +#pragma once +#ifndef OPENVPN_VERSION #define OPENVPN_VERSION "3.git:master" - -#endif // OPENVPN_COMMON_VERSION_H +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp new file mode 100644 index 0000000..37843e9 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp @@ -0,0 +1,761 @@ +// 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-2018 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_TRANSPORT_DCO_DCOCLI_H +#define OPENVPN_TRANSPORT_DCO_DCOCLI_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_PG +#include +#include +#endif + +// client-side DCO (Data Channel Offload) module for Linux/kovpn + +namespace openvpn { + namespace DCOTransport { + + OPENVPN_EXCEPTION(dco_error); + + class ClientConfig : public DCO, + public TransportClientFactory, + public TunClientFactory + { + public: + typedef RCPtr Ptr; + + std::string dev_name; + + DCO::TransportConfig transport; + DCO::TunConfig tun; + + int trunk_unit = -1; + + virtual TunClientFactory::Ptr new_tun_factory(const DCO::TunConfig& conf, const OptionList& opt) override + { + tun = conf; + + // set a default MTU + if (!tun.tun_prop.mtu) + tun.tun_prop.mtu = 1500; + + // parse "dev" option + { + const Option* dev = opt.get_ptr("dev"); + if (dev) + dev_name = dev->get(1, 64); + else + dev_name = "ovpnc"; + } + + // parse trunk-unit + trunk_unit = opt.get_num("trunk-unit", 1, trunk_unit, 0, 511); + + return TunClientFactory::Ptr(this); + } + + virtual TransportClientFactory::Ptr new_transport_factory(const DCO::TransportConfig& conf) override + { + transport = conf; + return TransportClientFactory::Ptr(this); + } + + virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, + TunClientParent& parent, + TransportClient* transcli) override; + + virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, + TransportClientParent* parent) override; + + static DCO::Ptr new_controller() + { + return new ClientConfig(); + } + + private: + ClientConfig() {} + }; + + class Client : public TransportClient, + public TunClient, + public KoRekey::Receiver, + public SessionStats::DCOTransportSource + { + friend class ClientConfig; + + typedef RCPtr Ptr; + + struct ProtoBase + { + ProtoBase() {} + virtual IP::Addr server_endpoint_addr() const = 0; + virtual void close() = 0; + virtual ~ProtoBase() {} + + ProtoBase(const ProtoBase&) = delete; + ProtoBase& operator=(const ProtoBase&) = delete; + }; + + struct UDP : public ProtoBase + { + UDP(openvpn_io::io_context& io_context) + : resolver(io_context), + socket(io_context) + { + } + + virtual IP::Addr server_endpoint_addr() const override + { + return IP::Addr::from_asio(server_endpoint.address()); + } + + virtual void close() override + { + socket.close(); + resolver.cancel(); + } + + openvpn_io::ip::udp::resolver resolver; + openvpn_io::ip::udp::socket socket; + UDPTransport::AsioEndpoint server_endpoint; + }; + +#ifdef ENABLE_PG + typedef KoTun::Tun TunImpl; +#else + typedef KoTun::TunClient TunImpl; +#endif + + // calls tun_read_handler and tun_error_handler + friend TunImpl::Base; + + public: + // transport methods + + virtual void transport_start() override + { + if (halt) + OPENVPN_THROW(dco_error, "transport_start called on halted instance"); + + KoTun::DevConf devconf; + + if (config->transport.protocol.is_udp()) + devconf.dc.tcp = false; + else if (config->transport.protocol.is_tcp()) + devconf.dc.tcp = true; + else + OPENVPN_THROW(dco_error, "protocol " << config->transport.protocol.str() << " not implemented"); + + // config settings + devconf.set_dev_name(config->dev_name); + devconf.dc.max_peers = 1; + devconf.dc.max_dev_queues = 1; + devconf.dc.dev_tx_queue_len = 4096; + devconf.dc.max_tun_queue_len = 4096; + devconf.dc.max_tcp_send_queue_len = 64; + devconf.dc.peer_lookup = OVPN_PEER_LOOKUP_NONE; + devconf.dc.cpu_id = -1; + + // create kovpn tun socket + impl.reset(new TunImpl(io_context, + devconf, + this, + config->transport.frame, + nullptr, + nullptr)); + + // set kovpn stats hook + config->transport.stats->dco_configure(this); + + // if trunking, set RPS/XPS on iface + if (config->trunk_unit >= 0) + KoTun::KovpnBase::set_rps_xps(config->dev_name, devconf.dc.queue_index, config->tun.stop); + + if (devconf.dc.tcp) + transport_start_tcp(); + else + 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); + } + + virtual bool transport_send(BufferAllocated& buf) override + { + return send(buf); + } + + virtual bool transport_send_queue_empty() override + { + return false; + } + + virtual bool transport_has_send_queue() override + { + return false; + } + + virtual unsigned int transport_send_queue_size() override + { + return 0; + } + + virtual void reset_align_adjust(const size_t align_adjust) override + { + } + + virtual void transport_stop_requeueing() override + { + } + + virtual void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const override + { + host = server_host; + port = server_port; + const IP::Addr addr = server_endpoint_addr(); + proto = "UDP"; + proto += addr.version_string(); + proto += "-DCO"; + ip_addr = addr.to_string(); + } + + virtual IP::Addr server_endpoint_addr() const override + { + if (proto) + return proto->server_endpoint_addr(); + else + return IP::Addr(); + } + + virtual Protocol transport_protocol() const override + { + switch (server_endpoint_addr().version()) + { + case IP::Addr::V4: + return Protocol(Protocol::UDPv4); + case IP::Addr::V6: + return Protocol(Protocol::UDPv6); + default: + return Protocol(); + } + } + + virtual ~Client() override + { + stop_(); + } + + // tun methods + + virtual void tun_start(const OptionList& opt, + TransportClient& transcli, + CryptoDCSettings& dc_settings) override + { + if (halt || !tun_parent) + OPENVPN_THROW(dco_error, "tun_start called on halted/undefined instance"); + + try { + const IP::Addr server_addr = server_endpoint_addr(); + + // get the iface name + state->iface_name = config->dev_name; + + // notify parent + tun_parent->tun_pre_tun_config(); + + // parse pushed options + TunBuilderCapture::Ptr po(new TunBuilderCapture()); + TunProp::configure_builder(po.get(), + state.get(), + config->transport.stats.get(), + server_addr, + config->tun.tun_prop, + opt, + nullptr, + false); + + 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; + 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 + TunLinux::iface_config(state->iface_name, + config->trunk_unit, + *po, + nullptr, + *add_cmds, + *remove_cmds); + + // 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); + } + else + { + // non-trunk setup + TunLinux::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 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))); + + // 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_(); + tun_parent->tun_error(Error::TUN_SETUP_FAILED, e.what()); + } + } + + virtual void set_disconnect() override + { + } + + virtual bool tun_send(BufferAllocated& buf) override // return true if send succeeded + { + return false; + } + + virtual std::string tun_name() const override + { + if (impl) + return impl->name(); + else + return "UNDEF_DCO"; + } + + virtual std::string vpn_ip4() const override + { + if (state->vpn_ip4_addr.specified()) + return state->vpn_ip4_addr.to_string(); + else + return ""; + } + + virtual std::string vpn_ip6() const override + { + if (state->vpn_ip6_addr.specified()) + return state->vpn_ip6_addr.to_string(); + else + return ""; + } + + virtual std::string vpn_gw4() const override + { + if (state->vpn_ip4_gw.specified()) + return state->vpn_ip4_gw.to_string(); + else + return ""; + } + + virtual std::string vpn_gw6() const override + { + if (state->vpn_ip6_gw.specified()) + return state->vpn_ip6_gw.to_string(); + else + return ""; + } + + // KoRekey::Receiver methods + + virtual void rekey(const CryptoDCInstance::RekeyType rktype, + const KoRekey::Info& rkinfo) override + { + if (halt) + return; + + KoRekey::Key key(rktype, rkinfo, peer_id, false); + impl->peer_keys_reset(key()); + if (transport_parent->is_keepalive_enabled()) + { + struct ovpn_peer_keepalive ka; + + // Disable userspace keepalive, get the userspace + // keepalive parameters, and enable kovpn keepalive. + ka.peer_id = peer_id; + transport_parent->disable_keepalive(ka.keepalive_ping, + ka.keepalive_timeout); + + // Modify the peer + impl->peer_set_keepalive(&ka); + } + } + + virtual void explicit_exit_notify() override + { + impl->peer_xmit_explicit_exit_notify(peer_id); + } + + // shared methods + + virtual void stop() override + { + stop_(); + } + + private: + Client(openvpn_io::io_context& io_context_arg, + ClientConfig* config_arg, + TransportClientParent* parent_arg) + : io_context(io_context_arg), + halt(false), + state(new TunProp::State()), + config(config_arg), + transport_parent(parent_arg), + tun_parent(nullptr), + peer_id(-1) + { + } + + virtual void transport_reparent(TransportClientParent* parent_arg) + { + transport_parent = parent_arg; + } + + void transport_start_udp() + { + proto.reset(new UDP(io_context)); + if (config->transport.remote_list->endpoint_available(&server_host, &server_port, nullptr)) + { + start_connect_udp(); + } + else + { + transport_parent->transport_pre_resolve(); + udp().resolver.async_resolve(server_host, server_port, + [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::udp::resolver::results_type results) + { + self->do_resolve_udp(error, results); + }); + } + } + + // called after DNS resolution has succeeded or failed + void do_resolve_udp(const openvpn_io::error_code& error, + openvpn_io::ip::udp::resolver::results_type results) + { + if (!halt) + { + if (!error) + { + // save resolved endpoint list in remote_list + config->transport.remote_list->set_endpoint_range(results); + start_connect_udp(); + } + else + { + std::ostringstream os; + os << "DNS resolve error on '" << server_host << "' for UDP session: " << error.message(); + config->transport.stats->error(Error::RESOLVE_ERROR); + stop_(); + transport_parent->transport_error(Error::UNDEF, os.str()); + } + } + } + + // do UDP connect + void start_connect_udp() + { + config->transport.remote_list->get_endpoint(udp().server_endpoint); + OPENVPN_LOG("Contacting " << udp().server_endpoint << " via UDP"); + transport_parent->transport_wait(); + transport_parent->ip_hole_punch(server_endpoint_addr()); + udp().socket.open(udp().server_endpoint.protocol()); + udp().socket.async_connect(udp().server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) + { + self->start_impl_udp(error); + }); + } + + // start I/O on UDP socket + void start_impl_udp(const openvpn_io::error_code& error) + { + if (!halt) + { + if (!error) + { + // attach UDP socket to kovpn + peer_id = impl->peer_new_udp_client(udp().socket.native_handle(), 0, 0); + + // queue reads on tun + impl->start(8); // parallel reads + transport_parent->transport_connecting(); + } + else + { + std::ostringstream os; + os << "UDP connect error on '" << server_host << ':' << server_port << "' (" << udp().server_endpoint << "): " << error.message(); + config->transport.stats->error(Error::UDP_CONNECT_ERROR); + stop_(); + transport_parent->transport_error(Error::UNDEF, os.str()); + } + } + } + + void transport_start_tcp() + { + OPENVPN_THROW(dco_error, "TCP not implemented yet"); // fixme for DCO + } + + void tun_read_handler(KoTun::PacketFrom::SPtr& pfp) // called by TunImpl + { + if (halt) + return; + + try { + const struct ovpn_tun_head *th = (const struct ovpn_tun_head *)pfp->buf.read_alloc(sizeof(struct ovpn_tun_head)); + switch (th->type) + { + case OVPN_TH_TRANS_BY_PEER_ID: + { + if (peer_id < 0 || th->peer_id != peer_id) + { + OPENVPN_LOG("dcocli: OVPN_TH_TRANS_BY_PEER_ID unrecognized peer_id=" << th->peer_id); + return; + } + + transport_parent->transport_recv(pfp->buf); + cc_rx_bytes += pfp->buf.size(); + break; + } + case OVPN_TH_NOTIFY_STATUS: + { + const struct ovpn_tun_head_status *thn = (const struct ovpn_tun_head_status *)th; + + if (peer_id < 0 || thn->head.peer_id != peer_id) + { + OPENVPN_LOG("dcocli: OVPN_TH_NOTIFY_STATUS unrecognized peer_id=" << thn->head.peer_id); + return; + } + + const bool stop = (thn->head.status != OVPN_STATUS_ACTIVE); + OPENVPN_LOG("dcocli: status=" << int(thn->head.status) << " peer_id=" << peer_id << " rx_bytes=" << thn->rx_bytes << " tx_bytes=" << thn->tx_bytes); // fixme + if (stop) + throw Exception("stop status=" + to_string(thn->head.status)); + break; + } + default: + OPENVPN_LOG("dcocli: unknown ovpn_tun_head type=" << (int)th->type); + break; + } + } + catch (const std::exception& e) + { + const std::string msg = std::string("dcocli: tun_read_handler: ") + e.what(); + OPENVPN_LOG(msg); + stop_(); + transport_parent->transport_error(Error::TRANSPORT_ERROR, msg); + } + } + + void tun_error_handler(const Error::Type errtype, // called by TunImpl + const openvpn_io::error_code* error) + { + OPENVPN_LOG("TUN error"); + stop_(); + } + + bool send(const Buffer& buf) + { + struct ovpn_tun_head head; + std::memset(&head, 0, sizeof(head)); + head.type = OVPN_TH_TRANS_BY_PEER_ID; + head.peer_id = peer_id; + return impl->write_seq(AsioConstBufferSeq2(Buffer(reinterpret_cast(&head), sizeof(head), true), + buf)); + } + + void stop_() + { + if (!halt) + { + halt = true; + config->transport.stats->dco_update(); // final update + config->transport.stats->dco_configure(nullptr); + if (remove_cmds) + remove_cmds->execute_log(); + if (impl) + impl->stop(); + if (proto) + proto->close(); + } + } + + UDP& udp() + { + 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 + { + if (impl) + { + struct ovpn_peer_status ops; + ops.peer_id = peer_id; + if (impl->peer_get_status(&ops)) + { + const SessionStats::DCOTransportSource::Data data(ops.rx_bytes + cc_rx_bytes, ops.tx_bytes); + const SessionStats::DCOTransportSource::Data delta = data - last_stats; + last_stats = data; + return delta; + } + } + return SessionStats::DCOTransportSource::Data(); + } + + openvpn_io::io_context& io_context; + bool halt; + + TunProp::State::Ptr state; + + ClientConfig::Ptr config; + TransportClientParent* transport_parent; + TunClientParent* tun_parent; + + std::unique_ptr proto; + + ActionList::Ptr remove_cmds; + + std::string server_host; + std::string server_port; + + TunImpl::Ptr impl; + int peer_id; + + SessionStats::DCOTransportSource::Data last_stats; + __u64 cc_rx_bytes = 0; + + static IPCollisionDetectBase* vpn_ip_collision; + }; + + inline DCO::Ptr new_controller() + { + return ClientConfig::new_controller(); + } + + inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, + TransportClientParent* parent) + { + return TransportClient::Ptr(new Client(io_context, this, parent)); + } + + inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, + TunClientParent& parent, + TransportClient* transcli) + { + Client* cli = static_cast(transcli); + cli->tun_parent = &parent; + return TunClient::Ptr(cli); + } + + IPCollisionDetectBase* Client::vpn_ip_collision; // GLOBAL + } +}; + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/ipcollbase.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/ipcollbase.hpp new file mode 100644 index 0000000..9b09e17 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/ipcollbase.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-2018 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 + +namespace openvpn { + class IPCollisionDetectBase + { + public: + OPENVPN_EXCEPTION(ip_collision); + + virtual void add(const std::string& addr_str, + const unsigned int unit, + ActionList& late_remove) { } + }; + +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/dhcp.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/dhcp.hpp index 5bb18f5..293f838 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/dhcp.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/dhcp.hpp @@ -23,7 +23,7 @@ #define OPENVPN_IP_DHCP_H #include -#include +#include #include #pragma pack(push) @@ -78,7 +78,7 @@ namespace openvpn { struct DHCPPacket { EthHeader eth; - IPHeader ip; + IPv4Header ip; UDPHeader udp; DHCP dhcp; std::uint8_t options[]; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp similarity index 84% rename from Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp.hpp rename to Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp index 5813b56..d08c028 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp @@ -19,40 +19,42 @@ // along with this program in the COPYING file. // If not, see . -// Define the ICMP header +// Define the ICMPv4 header -#ifndef OPENVPN_IP_ICMP_H -#define OPENVPN_IP_ICMP_H +#pragma once #include // for std::uint32_t, uint16_t, uint8_t -#include +#include #pragma pack(push) #pragma pack(1) namespace openvpn { - struct ICMP { + struct ICMPv4 { enum { - ECHO_REPLY = 0, ECHO_REQUEST = 8, + ECHO_REPLY = 0, }; - struct IPHeader head; + struct IPv4Header head; - std::uint8_t type; - std::uint8_t code; + union { + struct { + std::uint8_t type; + std::uint8_t code; + }; + std::uint16_t type_code; + }; std::uint16_t checksum; union { struct { std::uint16_t id; std::uint16_t seq_num; - } echo; - } hd; + }; + }; }; } #pragma pack(pop) - -#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp new file mode 100644 index 0000000..c23e03e --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp @@ -0,0 +1,61 @@ +// 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 . + +// Define the ICMPv6 header + +#pragma once + +#include // for std::uint32_t, uint16_t, uint8_t + +#include + +#pragma pack(push) +#pragma pack(1) + +namespace openvpn { + + struct ICMPv6 { + enum { + ECHO_REQUEST = 128, + ECHO_REPLY = 129, + }; + + struct IPv6Header head; + + union { + struct { + std::uint8_t type; + std::uint8_t code; + }; + std::uint16_t type_code; + }; + std::uint16_t checksum; + + union { + struct { + std::uint16_t id; + std::uint16_t seq_num; + }; + }; + }; +} + +#pragma pack(pop) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip4.hpp similarity index 69% rename from Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip.hpp rename to Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip4.hpp index 437256d..f2a0bef 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip4.hpp @@ -19,10 +19,9 @@ // along with this program in the COPYING file. // If not, see . -// Define the IP protocol header +// IPv4 header -#ifndef OPENVPN_IP_IP_H -#define OPENVPN_IP_IP_H +#pragma once #include // for std::uint32_t, uint16_t, uint8_t @@ -30,13 +29,9 @@ #pragma pack(1) namespace openvpn { - struct IPHeader - { - static unsigned int version(const std::uint8_t version_len) - { - return (version_len >> 4) & 0x0F; - } + struct IPv4Header + { static unsigned int length(const std::uint8_t version_len) { return (version_len & 0x0F) << 2; @@ -61,12 +56,6 @@ namespace openvpn { std::uint8_t ttl; - enum { - ICMP = 1, /* ICMP protocol */ - IGMP = 2, /* IGMP protocol */ - TCP = 6, /* TCP protocol */ - UDP = 17, /* UDP protocol */ - }; std::uint8_t protocol; std::uint16_t check; @@ -74,28 +63,6 @@ namespace openvpn { std::uint32_t daddr; /* The options start here. */ }; - - inline std::uint16_t ip_checksum(const void *ip, unsigned int size) - { - std::uint16_t *buffer = (std::uint16_t *)ip; - std::uint32_t cksum = 0; - - while (size > 1) - { - cksum += *buffer++; - size -= sizeof(uint16_t); - } - - if (size) - cksum += *(uint8_t*)buffer; - - cksum = (cksum >> 16) + (cksum & 0xffff); - cksum += (cksum >> 16); - return ~cksum; - } - } #pragma pack(pop) - -#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip6.hpp new file mode 100644 index 0000000..892ccbf --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ip6.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-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 . + +// IPv6 header + +#pragma once + +#include // for std::uint32_t, uint16_t, uint8_t + +#include + +#pragma pack(push) +#pragma pack(1) + +namespace openvpn { + + struct IPv6Header + { + std::uint8_t version_prio; + + std::uint8_t flow_lbl[3]; + + std::uint16_t payload_len; + std::uint8_t nexthdr; + std::uint8_t hop_limit; + + struct in6_addr saddr; + struct in6_addr daddr; + }; +} + +#pragma pack(pop) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp new file mode 100644 index 0000000..34afe6c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.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-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 . + +// Common declarations for IPv4 and IPv6 + +#pragma once + +#include // for std::uint32_t, uint16_t, uint8_t + +namespace openvpn { + namespace IPCommon { + + enum { + ICMPv4 = 1, /* ICMPv4 protocol */ + ICMPv6 = 58, /* ICMPv6 protocol */ + IGMP = 2, /* IGMP protocol */ + TCP = 6, /* TCP protocol */ + UDP = 17, /* UDP protocol */ + }; + + inline unsigned int version(const std::uint8_t version_len_prio) + { + return (version_len_prio >> 4) & 0x0F; + } + + } +} diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/udp.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/udp.hpp index 0437be2..5ba6702 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/udp.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/udp.hpp @@ -24,7 +24,7 @@ #ifndef OPENVPN_IP_UDP_H #define OPENVPN_IP_UDP_H -#include +#include namespace openvpn { @@ -68,7 +68,7 @@ namespace openvpn { } /* the protocol number and the length of the UDP packet */ - sum += (std::uint16_t)IPHeader::UDP + (std::uint16_t)len_udp; + sum += (std::uint16_t)IPCommon::UDP + (std::uint16_t)len_udp; /* keep only the last 16 bits of the 32 bit calculated sum and add the carries */ while (sum >> 16) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kocrypto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kocrypto.hpp new file mode 100644 index 0000000..422c63a --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kocrypto.hpp @@ -0,0 +1,389 @@ +// 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-2018 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 . + +// kovpn crypto wrappers + +#ifndef OPENVPN_KOVPN_KOCRYPTO_H +#define OPENVPN_KOVPN_KOCRYPTO_H + +#include // for std::memset, std::memcpy +#include // for std::move + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace KoRekey { + + OPENVPN_EXCEPTION(korekey_error); + + struct Info { + Info() {} + + Info(const CryptoDCContext::Ptr& dc_context_delegate_arg, + const unsigned int key_id_arg, + const Frame::Ptr& frame_arg) + : dc_context_delegate(dc_context_delegate_arg), + key_id(key_id_arg), + frame(frame_arg) + { + } + + CryptoDCContext::Ptr dc_context_delegate; + CompressContext comp_ctx; + unsigned int key_id = 0; + int remote_peer_id = -1; + bool tcp_linear = false; + StaticKey encrypt_cipher; + StaticKey encrypt_hmac; + StaticKey decrypt_cipher; + StaticKey decrypt_hmac; + Frame::Ptr frame; + }; + + class Key + { + // noncopyable because of "opk.primary = &key" below + Key(const Key&) = delete; + Key& operator=(const Key&) = delete; + + public: + static void validate(const CryptoAlgs::Type cipher, + const CryptoAlgs::Type digest) + { + const CryptoAlgs::Alg& calg = CryptoAlgs::get(cipher); + const CryptoAlgs::Alg& halg = CryptoAlgs::get(digest); + + switch (cipher) + { + case CryptoAlgs::AES_128_GCM: + case CryptoAlgs::AES_192_GCM: + case CryptoAlgs::AES_256_GCM: + case CryptoAlgs::AES_128_CBC: + case CryptoAlgs::AES_192_CBC: + case CryptoAlgs::AES_256_CBC: + case CryptoAlgs::BF_CBC: + break; + default: + OPENVPN_THROW(korekey_error, "cipher alg " << calg.name() << " is not currently supported by kovpn"); + } + + if (calg.mode() == CryptoAlgs::CBC_HMAC) + { + switch (digest) + { + case CryptoAlgs::SHA1: + case CryptoAlgs::SHA256: + break; + default: + OPENVPN_THROW(korekey_error, "HMAC alg " << halg.name() << " is not currently supported by kovpn"); + } + } + } + + Key(const CryptoDCInstance::RekeyType rktype, + const Info& rkinfo, // must remain in scope for duration of Key lifetime + const int peer_id, + const bool verbose) + { + std::memset(&opk, 0, sizeof(opk)); + + // set peer ID + opk.peer_id = peer_id; + + // set rekey op + bool new_key = false; + bool secondary_key = false; // only relevant for non-deactivate ops to secondary + switch (rktype) + { + case CryptoDCInstance::ACTIVATE_PRIMARY: + { + new_key = true; + opk.op = OVPN_KEYS_PRIMARY_ONLY; + break; + } + case CryptoDCInstance::ACTIVATE_PRIMARY_MOVE: + { + new_key = true; + opk.op = OVPN_KEYS_PRIMARY_ASSIGN_MOVE; + break; + } + case CryptoDCInstance::NEW_SECONDARY: + { + new_key = true; + secondary_key = true; + opk.op = OVPN_KEYS_SECONDARY_ONLY; + break; + } + case CryptoDCInstance::PRIMARY_SECONDARY_SWAP: + { + opk.op = OVPN_KEYS_PRIMARY_SECONDARY_SWAP; + break; + } + case CryptoDCInstance::DEACTIVATE_SECONDARY: + { + opk.op = OVPN_KEYS_SECONDARY_ONLY; + break; + } + case CryptoDCInstance::DEACTIVATE_ALL: + { + opk.op = OVPN_KEYS_BOTH; + break; + } + default: + OPENVPN_THROW(korekey_error, "unrecognized rekey type=" << (int)rktype); + } + + if (new_key) + { + const CryptoDCContext::Info ci = rkinfo.dc_context_delegate->crypto_info(); + const CryptoAlgs::Alg& calg = CryptoAlgs::get(ci.cipher_alg); + + // set crypto family + switch (calg.mode()) + { + case CryptoAlgs::CBC_HMAC: + opk.crypto_family = OVPN_CRYPTO_FAMILY_CBC_HMAC; + break; + case CryptoAlgs::AEAD: + opk.crypto_family = OVPN_CRYPTO_FAMILY_AEAD; + break; + default: + opk.crypto_family = OVPN_CRYPTO_FAMILY_UNDEF; + break; + } + + std::memset(&key, 0, sizeof(key)); + key.key_id = rkinfo.key_id; + key.remote_peer_id = rkinfo.remote_peer_id; + + switch (ci.cipher_alg) + { + case CryptoAlgs::AES_128_GCM: + key.cipher_alg = OVPN_ALG_AES_GCM; + key.encrypt.cipher_key_size = 128 / 8; + break; + case CryptoAlgs::AES_192_GCM: + key.cipher_alg = OVPN_ALG_AES_GCM; + key.encrypt.cipher_key_size = 192 / 8; + break; + case CryptoAlgs::AES_256_GCM: + key.cipher_alg = OVPN_ALG_AES_GCM; + key.encrypt.cipher_key_size = 256 / 8; + break; + case CryptoAlgs::AES_128_CBC: + key.cipher_alg = OVPN_ALG_AES_CBC; + key.encrypt.cipher_key_size = 128 / 8; + break; + case CryptoAlgs::AES_192_CBC: + key.cipher_alg = OVPN_ALG_AES_CBC; + key.encrypt.cipher_key_size = 192 / 8; + break; + case CryptoAlgs::AES_256_CBC: + key.cipher_alg = OVPN_ALG_AES_CBC; + key.encrypt.cipher_key_size = 256 / 8; + break; + case CryptoAlgs::BF_CBC: + key.cipher_alg = OVPN_ALG_BF_CBC; + key.encrypt.cipher_key_size = 128 / 8; + + // special data limits for 64-bit block-size ciphers (CVE-2016-6329) + key.encrypt.data_limit = key.decrypt.data_limit = OPENVPN_BS64_DATA_LIMIT; + break; + default: + key.cipher_alg = OVPN_ALG_UNDEF; + break; + } + key.decrypt.cipher_key_size = key.encrypt.cipher_key_size; + + // make sure that chosen cipher/family is supported + if (opk.crypto_family == OVPN_CRYPTO_FAMILY_UNDEF + || key.cipher_alg == OVPN_ALG_UNDEF) + OPENVPN_THROW(korekey_error, "cipher alg " << calg.name() << " is not currently supported by kovpn"); + + // set cipher keys + key.encrypt.cipher_key = verify_key("cipher encrypt", + rkinfo.encrypt_cipher, + key.encrypt.cipher_key_size); + key.decrypt.cipher_key = verify_key("cipher decrypt", + rkinfo.decrypt_cipher, + key.decrypt.cipher_key_size); + + switch (calg.mode()) + { + case CryptoAlgs::CBC_HMAC: + { + // if CBC mode, process HMAC digest + const CryptoAlgs::Alg& halg = CryptoAlgs::get(ci.hmac_alg); + switch (ci.hmac_alg) + { + case CryptoAlgs::SHA1: + key.hmac_alg = OVPN_ALG_HMAC_SHA1; + break; + case CryptoAlgs::SHA256: + key.hmac_alg = OVPN_ALG_HMAC_SHA256; + break; + default: + OPENVPN_THROW(korekey_error, "HMAC alg " << halg.name() << " is not currently supported by kovpn"); + } + key.encrypt.hmac_key_size = halg.size(); + key.decrypt.hmac_key_size = key.encrypt.hmac_key_size; + + // set hmac keys + key.encrypt.hmac_key = verify_key("hmac encrypt", + rkinfo.encrypt_hmac, + key.encrypt.hmac_key_size); + key.decrypt.hmac_key = verify_key("hmac decrypt", + rkinfo.decrypt_hmac, + key.decrypt.hmac_key_size); + + // handle compression V1 + switch (rkinfo.comp_ctx.type()) + { + case CompressContext::LZO_STUB: + key.compress.alg = OVPN_COMP_NONE; + key.compress.swap = false; + break; + case CompressContext::COMP_STUB: + key.compress.alg = OVPN_COMP_NONE; + key.compress.swap = true; + break; + case CompressContext::LZ4: + key.compress.alg = OVPN_COMP_LZ4; + key.compress.swap = true; + break; + default: + OPENVPN_THROW(korekey_error, "Compression alg " << rkinfo.comp_ctx.str() << " is not supported by kovpn in CBC/HMAC mode"); + } + break; + } + case CryptoAlgs::AEAD: + { + // if AEAD mode, copy nonce tail from the HMAC key material + set_nonce_tail("AEAD nonce tail encrypt", + key.encrypt.nonce_tail, + sizeof(key.encrypt.nonce_tail), + rkinfo.encrypt_hmac); + set_nonce_tail("AEAD nonce tail decrypt", + key.decrypt.nonce_tail, + sizeof(key.decrypt.nonce_tail), + rkinfo.decrypt_hmac); + + // handle compression V2 + switch (rkinfo.comp_ctx.type()) + { + case CompressContext::COMP_STUBv2: + key.compress.alg = OVPN_COMP_NONE; + break; + case CompressContext::LZ4v2: + key.compress.alg = OVPN_COMP_LZ4; + break; + default: + OPENVPN_THROW(korekey_error, "Compression alg " << rkinfo.comp_ctx.str() << " is not supported by kovpn in AEAD mode"); + } + key.compress.swap = false; + + break; + } + default: + { + // should have been caught above + throw korekey_error("internal error"); + } + } + + // handle compression + key.compress.asym = rkinfo.comp_ctx.asym(); + key.compress.max_decompress_size = (*rkinfo.frame)[Frame::DECOMPRESS_WORK].payload(); + + // handle TCP linear + key.tcp_linear = rkinfo.tcp_linear; + + if (verbose) + OPENVPN_LOG("KOREKEY" + << " op=" << int(rktype) << '/' << opk.op + << " rpid=" << key.remote_peer_id + << " pri=" << key.key_id + << " cipher=" << key.cipher_alg + << "[e=" << render_hex(key.encrypt.cipher_key, 8) + << " d=" << render_hex(key.decrypt.cipher_key, 8) << ']' + << " hmac=" << key.hmac_alg + << "[e=" << render_hex(key.encrypt.hmac_key, 8) + << " d=" << render_hex(key.decrypt.hmac_key, 8) << ']' + << " comp=" << key.compress.alg + << " swap=" << key.compress.swap + << " asym=" << key.compress.asym + << " tcp_linear=" << key.tcp_linear + << " dl=[e=" << key.encrypt.data_limit + << " d=" << key.decrypt.data_limit << ']'); + + // set key + if (secondary_key) + opk.secondary = &key; + else + opk.primary = &key; + } + else if (verbose) + { + OPENVPN_LOG("KOREKEY" << " op=" << int(rktype) << '/' << opk.op); + } + } + + const struct ovpn_peer_keys_reset *operator()() const + { + return &opk; + } + + private: + const unsigned char *verify_key(const char *title, const StaticKey& sk, const size_t size_required) + { + if (sk.size() < size_required) + OPENVPN_THROW(korekey_error, title << ": insufficient key material, provided=" << sk.size() << " required=" << size_required); + return sk.data(); + } + + void set_nonce_tail(const char *title, unsigned char *dest, const size_t dest_size, const StaticKey& src) + { + const int NONCE_TAIL_SIZE = CryptoAlgs::AEAD_NONCE_TAIL_SIZE; + + const unsigned char *k = verify_key(title, src, NONCE_TAIL_SIZE); + if (dest_size < NONCE_TAIL_SIZE) + OPENVPN_THROW(korekey_error, title << ": cannot set"); + std::memcpy(dest, k, NONCE_TAIL_SIZE); + + // if dest is larger than NONCE_TAIL_SIZE, zero remaining bytes + if (dest_size > NONCE_TAIL_SIZE) + std::memset(dest + NONCE_TAIL_SIZE, 0, dest_size - NONCE_TAIL_SIZE); + } + + struct ovpn_peer_keys_reset opk; + struct ovpn_key_config key; + }; + + } +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kodev.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kodev.hpp new file mode 100644 index 0000000..41c7d0c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kodev.hpp @@ -0,0 +1,391 @@ +// 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-2018 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 . + +// OpenVPN 3 kovpn-based tun interface + +#ifndef OPENVPN_KOVPN_KODEV_H +#define OPENVPN_KOVPN_KODEV_H + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + namespace KoTun { + + OPENVPN_EXCEPTION(kotun_error); + + struct DevConf + { + DevConf() + { + std::memset(&dc, 0, sizeof(dc)); + } + + void set_dev_name(const std::string& name) + { + if (name.length() < IFNAMSIZ) + ::strcpy(dc.dev_name, name.c_str()); + else + OPENVPN_THROW(kotun_error, "ovpn dev name too long"); + } + + struct ovpn_dev_init dc; + }; + + // kovpn API methods + namespace API { + + // Attach UDP socket to ovpn instance + inline void socket_attach_udp(const int kovpn_fd, + const int sock_fd) + { + struct ovpn_socket_attach_udp asock; + asock.fd = sock_fd; + if (::ioctl(kovpn_fd, OVPN_SOCKET_ATTACH_UDP, &asock) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_SOCKET_ATTACH_UDP failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // New UDP client + inline int peer_new_udp_client(const int kovpn_fd, + int fd, + const __u64 notify_per, + const unsigned int notify_seconds) + { + int peer_id = -1; + + // attach UDP socket fd + { + struct ovpn_socket_attach_udp asock; + asock.fd = fd; + if (::ioctl(kovpn_fd, OVPN_SOCKET_ATTACH_UDP, &asock) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_SOCKET_ATTACH_UDP failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // get a new Peer ID + { + struct ovpn_peer_new opn; + opn.peer_float = OVPN_PF_DISABLED; + opn.ovpn_file_bind = true; + opn.notify_per = notify_per; + opn.notify_seconds = notify_seconds; + peer_id = ::ioctl(kovpn_fd, OVPN_PEER_NEW, &opn); + if (peer_id < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_PEER_NEW failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // set up endpoints for peer + { + struct ovpn_peer_sockaddr_reset psr; + std::memset(&psr, 0, sizeof(psr)); + psr.peer_id = peer_id; + psr.fd = fd; + if (::ioctl(kovpn_fd, OVPN_PEER_SOCKADDR_RESET, &psr) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_PEER_SOCKADDR_RESET failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + return peer_id; + } + + // Send explicit-exit-notify message to peer + inline void peer_xmit_explicit_exit_notify(const int kovpn_fd, + const int peer_id) + { + if (::ioctl(kovpn_fd, OVPN_PEER_XMIT_EXPLICIT_EXIT_NOTIFY, peer_id) < 0) + { + const int eno = errno; + OPENVPN_LOG("kotun: OVPN_PEER_XMIT_EXPLICIT_EXIT_NOTIFY failed, id=" << peer_id << " errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // Set peer crypto keys + inline void peer_keys_reset(const int kovpn_fd, + const struct ovpn_peer_keys_reset *opk) + { + if (::ioctl(kovpn_fd, OVPN_PEER_KEYS_RESET, opk) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_PEER_KEYS_RESET failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // Set keepalive + inline void peer_set_keepalive(const int kovpn_fd, + const struct ovpn_peer_keepalive *ka) + { + if (::ioctl(kovpn_fd, OVPN_PEER_KEEPALIVE, ka) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_PEER_KEEPALIVE failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // Add routes + inline void peer_add_routes(const int kovpn_fd, + const int peer_id, + const std::vector& rtvec) + { + std::unique_ptr routes(KoRoute::from_routes(rtvec)); + struct ovpn_peer_routes_add r; + r.peer_id = peer_id; + r.usurp = true; + r.n_routes = rtvec.size(); + r.routes = routes.get(); + if (::ioctl(kovpn_fd, OVPN_PEER_ROUTES_ADD, &r) < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_PEER_ROUTES_ADD failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + } + } + + // Get status info + inline bool peer_get_status(const int kovpn_fd, + const struct ovpn_peer_status* ops) + { + if (::ioctl(kovpn_fd, OVPN_PEER_STATUS, ops) >= 0) + { + OPENVPN_MAKE_MEM_DEFINED(ops, sizeof(*ops)); + return true; + } + else + { + const int eno = errno; + OPENVPN_LOG("kotun: OVPN_PEER_STATUS failed, errno=" << eno << ' ' << KovpnStats::errstr(eno)); + return false; + } + } + } + + struct PacketFrom + { + typedef std::unique_ptr SPtr; + BufferAllocated buf; + }; + + class KovpnBase + { + public: + static ScopedFD open_kovpn(DevConf& devconf, + KovpnStats* kovpn_stats, + bool* first) + { + if (first) + *first = false; + + // Open kovpn device + static const char node[] = "/dev/net/ovpn"; + ScopedFD fd(open(node, O_RDWR)); + if (!fd.defined()) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "error opening ovpn tunnel device " << node << ": " << strerror_str(eno)); + } + + // Check kovpn version + const int ver_packed = ::ioctl(fd(), OVPN_GET_VERSION, nullptr); + if (ver_packed < 0) + OPENVPN_THROW(kotun_error, "OVPN_GET_VERSION failed"); + if (ver_major(ver_packed) != OVPN_VER_MAJOR + || ver_minor(ver_packed) != OVPN_VER_MINOR) + OPENVPN_THROW(kotun_error, "version mismatch, pg=" << ver_string() << " installed=" << ver_string(ver_packed)); + + // Configure tun + const int status = ::ioctl(fd(), OVPN_DEV_INIT, &devconf.dc); + if (status < 0) + { + const int eno = errno; + OPENVPN_THROW(kotun_error, "OVPN_DEV_INIT failed: " << KovpnStats::errstr(eno)); + } + + if (devconf.dc.expire) + OPENVPN_LOG("NOTE: this evaluation build expires on " << date_time(devconf.dc.expire)); + + if (status == 1) + { + if (kovpn_stats) + kovpn_stats->set_fd(fd()); + if (first) + *first = true; + OPENVPN_LOG("KVER pg=" << ver_string() << " installed=" << ver_string(ver_packed)); + OPENVPN_LOG("IE_NAT=" << devconf.dc.ie_nat); + } + + return fd; + } + + static void set_rps_xps(const std::string& dev_name, const unsigned int dev_queue_index, Stop* async_stop) + { + // set RPS/XPS on iface + ProcFS::write_sys(fmt_qfn(dev_name, "rx", dev_queue_index, "rps_cpus"), "ffffffff\n", async_stop); + ProcFS::write_sys(fmt_qfn(dev_name, "rx", dev_queue_index, "rps_cpus"), "ffffffff\n", async_stop); + ProcFS::write_sys(fmt_qfn(dev_name, "rx", dev_queue_index, "rps_flow_cnt"), "1024\n", async_stop); + ProcFS::write_sys(fmt_qfn(dev_name, "tx", dev_queue_index, "xps_cpus"), "0\n", async_stop); + } + + static void disable_reverse_path_filter(const std::string& dev_name, Stop* async_stop) + { + // disable reverse path filter on iface + IPv4ReversePathFilter::write(dev_name, 0, async_stop); + } + + protected: + static int ver_major(const int ver_packed) + { + return (ver_packed >> 16) & 0xFF; + } + + static int ver_minor(const int ver_packed) + { + return (ver_packed >> 8) & 0xFF; + } + + static int ver_build(const int ver_packed) + { + return ver_packed & 0xFF; + } + + static std::string ver_string(const int major, const int minor, const int build) + { + return std::to_string(major) + '.' + std::to_string(minor) + '.' + std::to_string(build); + } + + static std::string ver_string(const int ver_packed) + { + return ver_string(ver_major(ver_packed), ver_minor(ver_packed), ver_build(ver_packed)); + } + + static std::string ver_string() + { + return ver_string(OVPN_VER_MAJOR, OVPN_VER_MINOR, OVPN_VER_BUILD); + } + + static std::string fmt_qfn(const std::string& dev, const std::string& type, int qnum, const std::string& bn) + { + std::ostringstream os; + os << "/sys/class/net/" << dev << "/queues/" << type << "-" << qnum << '/' << bn; + return os.str(); + } + }; + + template + struct TunClient : public TunIO, public virtual KovpnBase + { + typedef TunIO Base; + typedef RCPtr Ptr; + + // constructed by start() in in koudp.c/kotcp.c + TunClient(openvpn_io::io_context& io_context, + DevConf& devconf, + ReadHandler read_handler, + const Frame::Ptr& frame, + KovpnStats* kovpn_stats, // not persisted + bool *first) + : Base(read_handler, frame, SessionStats::Ptr()) + { + ScopedFD fd(open_kovpn(devconf, kovpn_stats, first)); + Base::name_ = devconf.dc.dev_name; + Base::stream = new openvpn_io::posix::stream_descriptor(io_context, fd.release()); + } + + // Attach UDP socket to ovpn instance + void socket_attach_udp(const int sock_fd) + { + API::socket_attach_udp(native_handle(), sock_fd); + } + + // New UDP client (used by dcocli) + int peer_new_udp_client(int fd, + const __u64 notify_per, + const unsigned int notify_seconds) + { + return API::peer_new_udp_client(native_handle(), fd, notify_per, notify_seconds); + } + + // Add routes (used by dcocli) + void peer_add_routes(const int peer_id, + const std::vector& rtvec) + { + API::peer_add_routes(native_handle(), peer_id, rtvec); + } + + // Send explicit-exit-notify message to peer + void peer_xmit_explicit_exit_notify(const int peer_id) + { + API::peer_xmit_explicit_exit_notify(native_handle(), peer_id); + } + + // Set peer crypto keys + void peer_keys_reset(const struct ovpn_peer_keys_reset *opk) + { + API::peer_keys_reset(native_handle(), opk); + } + + // Set keepalive + void peer_set_keepalive(const struct ovpn_peer_keepalive *ka) + { + API::peer_set_keepalive(native_handle(), ka); + } + + // Get status info + bool peer_get_status(struct ovpn_peer_status* ops) + { + return API::peer_get_status(native_handle(), ops); + } + + // Return kovpn fd + int native_handle() const + { + return Base::stream->native_handle(); + } + }; + + } +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/korekey.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/korekey.hpp new file mode 100644 index 0000000..6e7605b --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/korekey.hpp @@ -0,0 +1,195 @@ +// 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-2018 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 . + +// OpenVPN 3 wrapper for kovpn crypto + +#ifndef OPENVPN_KOVPN_KOREKEY_H +#define OPENVPN_KOVPN_KOREKEY_H + +#include + +namespace openvpn { + namespace KoRekey { + + class Receiver : public virtual RC + { + public: + typedef RCPtr Ptr; + + virtual void rekey(const CryptoDCInstance::RekeyType type, + const Info& info) = 0; + + virtual void explicit_exit_notify() {} + }; + + class Instance : public CryptoDCInstance + { + public: + Instance(const Receiver::Ptr& rcv_arg, + const CryptoDCContext::Ptr& dc_context_delegate, + const unsigned int key_id, + const Frame::Ptr& frame) + : rcv(rcv_arg), + info(dc_context_delegate, key_id, frame) + { + } + + // Initialization + + virtual unsigned int defined() const override + { + return CIPHER_DEFINED|HMAC_DEFINED|EXPLICIT_EXIT_NOTIFY_DEFINED; + } + + virtual void init_cipher(StaticKey&& encrypt_key, + StaticKey&& decrypt_key) override + { + info.encrypt_cipher = std::move(encrypt_key); + info.decrypt_cipher = std::move(decrypt_key); + } + + virtual void init_hmac(StaticKey&& encrypt_key, + StaticKey&& decrypt_key) override + { + info.encrypt_hmac = std::move(encrypt_key); + info.decrypt_hmac = std::move(decrypt_key); + } + + virtual void init_pid(const int send_form, + const int recv_mode, + const int recv_form, + const char *recv_name, + const int recv_unit, + const SessionStats::Ptr& recv_stats_arg) override + { + info.tcp_linear = (recv_mode == PacketIDReceive::TCP_MODE); + } + + virtual void init_remote_peer_id(const int remote_peer_id) override + { + info.remote_peer_id = remote_peer_id; + } + + virtual bool consider_compression(const CompressContext& comp_ctx) override + { + info.comp_ctx = comp_ctx; + return false; + } + + // Rekeying + + virtual void rekey(const RekeyType type) override + { + rcv->rekey(type, info); + } + + virtual void explicit_exit_notify() override + { + rcv->explicit_exit_notify(); + } + + // Encrypt/Decrypt -- data channel handled by kernel, so these methods + // should never be reached. + + // returns true if packet ID is close to wrapping + virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) override + { + throw korekey_error("encrypt"); + } + + virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) override + { + throw korekey_error("decrypt"); + } + + private: + Receiver::Ptr rcv; + Info info; + }; + + class Context : public CryptoDCContext + { + public: + Context(const CryptoAlgs::Type cipher, + const CryptoAlgs::Type digest, + CryptoDCFactory& dc_factory_delegate, + const Receiver::Ptr& rcv_arg, + const Frame::Ptr& frame_arg) + : rcv(rcv_arg), + dc_context_delegate(dc_factory_delegate.new_obj(cipher, digest)), + frame(frame_arg) + { + Key::validate(cipher, digest); + } + + virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) override + { + return new Instance(rcv, dc_context_delegate, key_id, frame); + } + + // Info for ProtoContext::options_string + + virtual Info crypto_info() override + { + return dc_context_delegate->crypto_info(); + } + + // Info for ProtoContext::link_mtu_adjust + + virtual size_t encap_overhead() const override + { + return dc_context_delegate->encap_overhead(); + } + + private: + Receiver::Ptr rcv; + CryptoDCContext::Ptr dc_context_delegate; + Frame::Ptr frame; + }; + + class Factory : public CryptoDCFactory + { + public: + Factory(const CryptoDCFactory::Ptr& dc_factory_delegate_arg, + const Receiver::Ptr& rcv_arg, + const Frame::Ptr& frame_arg) + : dc_factory_delegate(dc_factory_delegate_arg), + rcv(rcv_arg), + frame(frame_arg) + { + } + + virtual CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher, + const CryptoAlgs::Type digest) override + { + return new Context(cipher, digest, *dc_factory_delegate, rcv, frame); + } + + private: + CryptoDCFactory::Ptr dc_factory_delegate; + Receiver::Ptr rcv; + Frame::Ptr frame; + }; + + } +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/koroute.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/koroute.hpp new file mode 100644 index 0000000..e300a43 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/koroute.hpp @@ -0,0 +1,69 @@ +// 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-2018 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 . + +// OpenVPN 3 wrapper for kovpn + +#ifndef OPENVPN_KOVPN_KOROUTE_H +#define OPENVPN_KOVPN_KOROUTE_H + +#include +#include + +#include +#include + +namespace openvpn { + namespace KoRoute { + inline struct ovpn_route from_route(const IP::Route& r) + { + struct ovpn_route ret; + ret.prefix_len = r.prefix_len; + ret.addr.v6 = (r.addr.version() == IP::Addr::V6); + switch (r.addr.version()) + { + case IP::Addr::V6: + ret.addr.u.a6 = r.addr.to_ipv6_nocheck().to_in6_addr(); + break; + case IP::Addr::V4: + ret.addr.u.a4 = r.addr.to_ipv4_nocheck().to_in_addr(); + break; + default: + throw IP::ip_exception("route address unspecified"); + } + return ret; + } + + inline struct ovpn_route *from_routes(const std::vector& rtvec) + { + if (rtvec.size()) + { + std::unique_ptr routes(new ovpn_route[rtvec.size()]); + for (size_t i = 0; i < rtvec.size(); ++i) + routes[i] = from_route(rtvec[i]); + return routes.release(); + } + else + return nullptr; + } + } +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kostats.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kostats.hpp new file mode 100644 index 0000000..d64452b --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kostats.hpp @@ -0,0 +1,165 @@ +// 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-2018 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_KOVPN_KOSTATS_H +#define OPENVPN_KOVPN_KOSTATS_H + +#include // for std::min, std::max +#include +#include + +#include + +#include +#include +#include + +namespace openvpn { + namespace kostats_private { +# include + } + + class KovpnStats + { + public: + void set_fd(const int fd) + { + kovpn_fd.store(fd, std::memory_order_relaxed); + } + + void output_stats(std::ostream& os) const + { + struct ovpn_stats stats; + if (::ioctl(get_fd(), OVPN_DEV_STATS, &stats) < 0) + return; + os << "STAT.BYTES_IN," << (stats.rx_bytes + cc_rx_bytes.load(std::memory_order_relaxed)) << '\n'; + os << "STAT.BYTES_OUT," << stats.tx_bytes << '\n'; + } + + void output_percpu(std::ostream& os) const + { + std::unique_ptr pcs; + unsigned int stats_cap = 16; + for (int i = 0; i < 2; ++i) + { + const size_t pcs_size = sizeof(struct ovpn_percpu_stats) + + sizeof(struct ovpn_percpu_stat) * stats_cap; + pcs.reset((struct ovpn_percpu_stats *) ::operator new(pcs_size)); + pcs->total_stats = 0; + pcs->n_stats = stats_cap; + if (::ioctl(get_fd(), OVPN_PERCPU_STATS, (void *)pcs.get()) < 0) + return; + stats_cap = std::max(stats_cap, pcs->total_stats); + if (pcs->total_stats <= pcs->n_stats) + break; + } + const size_t n = std::min(pcs->total_stats, pcs->n_stats); + for (size_t i = 0; i < n; ++i) + { + const struct ovpn_percpu_stat *s = &pcs->stats[i]; + if (s->rx_bytes || s->tx_bytes) + { + os << "KOVPN.STAT.CPU-" << i << ".BYTES_IN," << s->rx_bytes << '\n'; + os << "KOVPN.STAT.CPU-" << i << ".BYTES_OUT," << s->tx_bytes << '\n'; + } + } + } + + void output_err_counters(std::ostream& os) const + { + std::unique_ptr esp; + unsigned int stats_cap = 128; + for (int i = 0; i < 2; ++i) + { + const size_t es_size = sizeof(struct ovpn_err_stats) + + sizeof(struct ovpn_err_stat) * stats_cap; + esp.reset((struct ovpn_err_stats *) ::operator new(es_size)); + esp->total_stats = 0; + esp->n_stats = stats_cap; + if (::ioctl(get_fd(), OVPN_ERR_STATS, (void *)esp.get()) < 0) + return; + stats_cap = std::max(stats_cap, esp->total_stats); + if (esp->total_stats <= esp->n_stats) + break; + } + const size_t n = std::min(esp->total_stats, esp->n_stats); + for (size_t i = 0; i < n; ++i) + { + const struct ovpn_err_stat *s = &esp->stats[i]; + os << "KOVPN"; + const char *cat = cat_name(s->category); + if (cat) + { + os << '.'; + os << cat; + } + const char *err = err_name(s->errcode); + if (err) + { + os << '.'; + os << err; + } + os << ',' << s->count << '\n'; + } + } + + void increment_cc_rx_bytes(const std::uint64_t value) + { + cc_rx_bytes.fetch_add(value, std::memory_order_relaxed); + } + + static const char *errstr(const size_t i) + { + const char *ret = err_name(i); + if (ret) + return ret; + else + return ""; + } + + private: + static const char *err_name(const size_t i) + { + if (i < array_size(kostats_private::ovpn_err_names)) + return kostats_private::ovpn_err_names[i]; + else + return nullptr; + } + + static const char *cat_name(const size_t i) + { + if (i < array_size(kostats_private::ovpn_errcat_names)) + return kostats_private::ovpn_errcat_names[i]; + else + return nullptr; + } + + int get_fd() const + { + return kovpn_fd.load(std::memory_order_relaxed); + } + + std::atomic kovpn_fd{-1}; + std::atomic cc_rx_bytes{0}; + }; +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kovpn.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kovpn.hpp new file mode 100644 index 0000000..32dd07c --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/kovpn/kovpn.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-2018 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 . + +// OpenVPN 3 wrapper for kovpn + +#ifndef OPENVPN_KOVPN_KOVPN_HPP +#define OPENVPN_KOVPN_KOVPN_HPP + +#include +#include +#include +#include + +extern "C" { +#include +} + +#endif diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/linux/procfs.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/linux/procfs.hpp new file mode 100644 index 0000000..e20341e --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/linux/procfs.hpp @@ -0,0 +1,108 @@ +// Private Gateway +// Copyright (C) 2012-2017 OpenVPN Technologies, Inc. +// All rights reserved + +#ifndef OPENVPN_LINUX_PROCFS_H +#define OPENVPN_LINUX_PROCFS_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace openvpn { + + class ProcFS : public Action + { + public: + OPENVPN_EXCEPTION(procfs_error); + + ProcFS(std::string fn_arg, std::string text_arg) + : fn(std::move(fn_arg)), + text(std::move(text_arg)) + { + } + + virtual void execute(std::ostream& os) override + { + os << to_string() << std::endl; + try { + write_sys(fn, text); + } + catch (const std::exception& e) + { + os << "ProcFS exception: " << e.what() << std::endl; + } + } + + virtual std::string to_string() const override + { + return to_string(fn, text); + } + + static std::string to_string(const std::string& fn, const std::string& text) + { + return "ProcFS: " + fn + " -> " + string::trim_crlf_copy(text); + } + + static void write_sys(const std::string& fn, const std::string& text, Stop* async_stop=nullptr) + { + //OPENVPN_LOG(to_string(fn, text)); + + const unsigned int n_retries = 200; + const unsigned int milliseconds_per_retry = 100; + volatile bool stop = false; + + // allow asynchronous stop + Stop::Scope stop_scope(async_stop, [&stop]() { + stop = true; + }); + + for (unsigned int i = 0; i < n_retries && !stop; ++i) + { + if (file_exists(fn)) + { + write_string(fn, text); + return; + } + sleep_milliseconds(milliseconds_per_retry); + } + if (stop) + OPENVPN_THROW(procfs_error, "file " << fn << " : aborting write attempt due to stop signal"); + else + OPENVPN_THROW(procfs_error, "file " << fn << " failed to exist within " << (n_retries * milliseconds_per_retry / 1000) << " seconds"); + } + + private: + std::string fn; + std::string text; + }; + + class IPv4ReversePathFilter : public ProcFS + { + public: + IPv4ReversePathFilter(const std::string& dev, const unsigned int value) + : ProcFS(key_fn(dev), openvpn::to_string(value)) + { + OPENVPN_LOG("IPv4ReversePathFilter " << dev << " -> " << value); + } + + static void write(const std::string& dev, const unsigned int value, Stop* stop=nullptr) + { + ProcFS::write_sys(key_fn(dev), openvpn::to_string(value), stop); + } + + private: + static std::string key_fn(const std::string& dev) + { + return printfmt("/proc/sys/net/ipv4/conf/%s/rp_filter", dev); + } + }; +} + +#endif 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 ce7b674..3f2158f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/pki/pkctx.hpp @@ -68,17 +68,14 @@ namespace openvpn { switch (mbedtls_pk_get_type(ctx)) { case MBEDTLS_PK_RSA: + case MBEDTLS_PK_RSA_ALT: + case MBEDTLS_PK_RSASSA_PSS: return SSLConfigAPI::PK_RSA; case MBEDTLS_PK_ECKEY: - return SSLConfigAPI::PK_ECKEY; case MBEDTLS_PK_ECKEY_DH: - return SSLConfigAPI::PK_ECKEY_DH; + return SSLConfigAPI::PK_EC; case MBEDTLS_PK_ECDSA: return SSLConfigAPI::PK_ECDSA; - case MBEDTLS_PK_RSA_ALT: - return SSLConfigAPI::PK_RSA_ALT; - case MBEDTLS_PK_RSASSA_PSS: - return SSLConfigAPI::PK_RSASSA_PSS; case MBEDTLS_PK_NONE: return SSLConfigAPI::PK_NONE; default: 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 b8ba19d..2f1324a 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/pki/pkey.hpp @@ -62,6 +62,38 @@ namespace openvpn { bool defined() const { return pkey_ != nullptr; } EVP_PKEY* obj() const { return pkey_; } + SSLConfigAPI::PKType key_type() const + { + switch (EVP_PKEY_id(pkey_)) + { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA2: + return SSLConfigAPI::PK_RSA; + case EVP_PKEY_EC: + return SSLConfigAPI::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; + case EVP_PKEY_NONE: + return SSLConfigAPI::PK_NONE; + default: + return SSLConfigAPI::PK_UNKNOWN; + } + } + + size_t key_length() const + { + int ret = i2d_PrivateKey(pkey_, NULL); + if (ret < 0) + return 0; + + /* convert to bits */ + return ret * 8; + } + void set_private_key_password(const std::string& pwd) { priv_key_pwd = pwd; 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 ead66ed..540482f 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp @@ -132,7 +132,7 @@ namespace openvpn { virtual void load_crl(const std::string& crl_txt) { - throw ssl_options_error("CRL not implemented yet in OpenSSL driver"); // fixme + ca.parse_pem(crl_txt, "crl"); } virtual void load_cert(const std::string& cert_txt) @@ -159,42 +159,49 @@ namespace openvpn { virtual std::string extract_ca() const { - throw ssl_options_error("extract_ca not implemented yet in OpenSSL driver"); // fixme + return ca.certs.render_pem(); } virtual std::string extract_crl() const { - throw ssl_options_error("CRL not implemented yet in OpenSSL driver"); // fixme + return ca.crls.render_pem(); } virtual std::string extract_cert() const { - throw ssl_options_error("extract_cert not implemented yet in OpenSSL driver"); // fixme + return cert.render_pem(); } virtual std::vector extract_extra_certs() const { - throw ssl_options_error("extract_extra_certs not implemented yet in OpenSSL driver"); // fixme + std::vector ret; + + for (auto const& cert : extra_certs) + ret.push_back(cert->render_pem()); + + return ret; } virtual std::string extract_private_key() const { - throw ssl_options_error("extract_priv_key not implemented yet in OpenSSL driver"); // fixme + return pkey.render_pem(); } virtual std::string extract_dh() const { - throw ssl_options_error("extract_dh not implemented yet in OpenSSL driver"); // fixme + return dh.render_pem(); } virtual PKType private_key_type() const { - throw ssl_options_error("private_key_type not implemented yet in OpenSSL driver"); // fixme + if (!pkey.defined()) + return PK_NONE; + return pkey.key_type(); } virtual size_t private_key_length() const { - throw ssl_options_error("private_key_length not implemented yet in OpenSSL driver"); // fixme + return pkey.key_length(); } virtual void set_frame(const Frame::Ptr& frame_arg) @@ -300,7 +307,8 @@ namespace openvpn { virtual std::string validate_crl(const std::string& crl_txt) const { - throw ssl_options_error("CRL not implemented yet in OpenSSL driver"); // fixme + OpenSSLPKI::CRL crl(crl_txt); + return crl.render_pem(); } virtual void load(const OptionList& opt, const unsigned int lflags) @@ -322,6 +330,13 @@ namespace openvpn { load_ca(ca_txt, true); } + // CRL + { + const std::string crl_txt = opt.cat("crl-verify"); + if (!crl_txt.empty()) + load_crl(crl_txt); + } + // local cert/key if (local_cert_enabled) { @@ -387,7 +402,7 @@ namespace openvpn { private: Mode mode; - CertCRLList ca; // from OpenVPN "ca" option + CertCRLList ca; // from OpenVPN "ca" and "crl-verify" option OpenSSLPKI::X509 cert; // from OpenVPN "cert" option OpenSSLPKI::X509List extra_certs; // from OpenVPN "extra-certs" option OpenSSLPKI::PKey pkey; // private key @@ -926,10 +941,41 @@ namespace openvpn { #endif } - // tls-cert-profile is not implemented yet in OpenSSL (fixme), - // so throw exception if the setting is anything other than LEGACY. + /* HAVE_SSL_CTX_SET_SECURITY_LEVEL exists from OpenSSL-1.1.0 up */ +#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL + switch(TLSCertProfile::default_if_undef(config->tls_cert_profile)) + { + case TLSCertProfile::UNDEF: + OPENVPN_THROW(ssl_context_error, + "OpenSSLContext: undefined tls-cert-profile"); + break; +#ifdef OPENVPN_USE_TLS_MD5 + case TLSCertProfile::INSECURE: + SSL_CTX_set_security_level(ctx, 0); + break; +#endif + case TLSCertProfile::LEGACY: + SSL_CTX_set_security_level(ctx, 1); + break; + case TLSCertProfile::PREFERRED: + SSL_CTX_set_security_level(ctx, 2); + break; + case TLSCertProfile::SUITEB: + SSL_CTX_set_security_level(ctx, 3); + break; + default: + OPENVPN_THROW(ssl_context_error, + "OpenSSLContext: unexpected tls-cert-profile value"); + break; + } +#else + // when OpenSSL does not CertProfile support we force the user to set 'legacy' if (TLSCertProfile::default_if_undef(config->tls_cert_profile) != TLSCertProfile::LEGACY) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: tls-cert-profile not implemented yet"); + { + OPENVPN_THROW(ssl_context_error, + "OpenSSLContext: tls-cert-profile not supported by this OpenSSL build. Use 'legacy' instead"); + } +#endif if (config->local_cert_enabled) { diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp index d1ce2a9..e6a0da7 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/manage.hpp @@ -55,7 +55,7 @@ namespace openvpn { virtual void auth_request(const AuthCreds::Ptr& auth_creds, const AuthCert::Ptr& auth_cert, const PeerAddr::Ptr& peer_addr) = 0; - virtual void push_request(const ProtoContext::Config::Ptr& pconf) = 0; + virtual void push_request(ProtoContext::Config::Ptr pconf) = 0; // INFO notification virtual void info_request(const std::string& imsg) = 0; @@ -85,8 +85,7 @@ namespace openvpn { // set ACL index for user virtual void set_acl_index(const int acl_index, const std::string* username, - const bool challenge, - const bool throw_on_error) = 0; + const bool challenge) = 0; // notify of local user properties update virtual void userprop_local_update() = 0; @@ -119,6 +118,9 @@ namespace openvpn { // schedule a low-level connection disconnect in seconds virtual void schedule_disconnect(const unsigned int seconds) = 0; + // schedule an auth pending disconnect in seconds + virtual void schedule_auth_pending_timeout(const unsigned int seconds) = 0; + // set up relay to target virtual void relay(const IP::Addr& target, const int port) = 0; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/servproto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/servproto.hpp index 547a866..e638610 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/servproto.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/server/servproto.hpp @@ -345,16 +345,10 @@ namespace openvpn { Unicode::UTF8_FILTER); if (msg == "PUSH_REQUEST") { - if (!did_push) - { - did_push = true; - if (get_management()) - ManLink::send->push_request(Base::conf_ptr()); - else - { - auth_failed("no management provider", false); - } - } + if (get_management()) + ManLink::send->push_request(Base::conf_ptr()); + else + auth_failed("no management provider", false); } else if (string::starts_with(msg, "INFO,")) { @@ -375,11 +369,14 @@ namespace openvpn { virtual void relay(const IP::Addr& target, const int port) override { + if (halt || disconnect_type == DT_HALT_RESTART) + return; + Base::update_now(); - if (TunLink::send && !relay_transition) + if (TunLink::send && (disconnect_type < DT_RELAY_TRANSITION)) { - relay_transition = true; + disconnect_type = DT_RELAY_TRANSITION; TunLink::send->relay(target, port); disconnect_in(Time::Duration::seconds(10)); // not a real disconnect, just complete transition to relay } @@ -398,9 +395,15 @@ namespace openvpn { virtual void push_reply(std::vector&& push_msgs) override { - if (halt || relay_transition || !Base::primary_defined()) + if (halt || (disconnect_type >= DT_RELAY_TRANSITION) || !Base::primary_defined()) return; + if (disconnect_type == DT_AUTH_PENDING) + { + disconnect_type = DT_NONE; + cancel_disconnect(); + } + Base::update_now(); if (get_tun()) @@ -432,7 +435,7 @@ namespace openvpn { const std::string& reason, const bool tell_client) override { - if (halt || did_client_halt_restart) + if (halt || disconnect_type == DT_HALT_RESTART) return; Base::update_now(); @@ -498,7 +501,7 @@ namespace openvpn { if (type != HaltRestart::RESTART_PASSIVE) { - did_client_halt_restart = true; + disconnect_type = DT_HALT_RESTART; disconnect_in(Time::Duration::seconds(1)); } @@ -514,13 +517,23 @@ namespace openvpn { virtual void schedule_disconnect(const unsigned int seconds) { - if (halt || did_client_halt_restart) + if (halt || disconnect_type == DT_HALT_RESTART) return; Base::update_now(); disconnect_in(Time::Duration::seconds(seconds)); set_housekeeping_timer(); } + virtual void schedule_auth_pending_timeout(const unsigned int seconds) + { + if (halt || (disconnect_type >= DT_RELAY_TRANSITION) || !seconds) + return; + Base::update_now(); + disconnect_type = DT_AUTH_PENDING; + disconnect_in(Time::Duration::seconds(seconds)); + set_housekeeping_timer(); + } + virtual void post_cc_msg(BufferPtr&& msg) override { if (halt || !Base::primary_defined()) @@ -582,6 +595,11 @@ namespace openvpn { disconnect_at = now() + dur; } + void cancel_disconnect() + { + disconnect_at = Time::infinite(); + } + void housekeeping_callback(const openvpn_io::error_code& e) { try { @@ -596,10 +614,21 @@ namespace openvpn { invalidation_error(Base::invalidation_reason()); else if (now() >= disconnect_at) { - if (relay_transition && !did_client_halt_restart) - Base::pre_destroy(); - else - error("disconnect triggered"); + switch (disconnect_type) + { + case DT_HALT_RESTART: + error("disconnect triggered"); + break; + case DT_RELAY_TRANSITION: + Base::pre_destroy(); + break; + case DT_AUTH_PENDING: + auth_failed("Auth Pending Timeout", true); + break; + default: + error("unknown disconnect"); + break; + } } else set_housekeeping_timer(); @@ -676,9 +705,15 @@ namespace openvpn { openvpn_io::io_context& io_context; bool halt = false; - bool did_push = false; - bool did_client_halt_restart = false; - bool relay_transition = false; + + // higher values are higher priority + enum DisconnectType { + DT_NONE=0, + DT_AUTH_PENDING, + DT_RELAY_TRANSITION, + DT_HALT_RESTART, + }; + int disconnect_type = DT_NONE; PeerAddr::Ptr peer_addr; diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp index 7a7b2c1..e3c1b5e 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp @@ -559,7 +559,18 @@ namespace openvpn { new_comp = o->get(1, 128); CompressContext::Type meth = CompressContext::parse_method(new_comp); if (meth != CompressContext::NONE) - comp_ctx = CompressContext(pco.is_comp() ? meth : CompressContext::stub(meth), pco.is_comp_asym()); + { + // if compression is not availabe, CompressContext ctor throws an exception + if (pco.is_comp()) + comp_ctx = CompressContext(meth, pco.is_comp_asym()); + else + { + // 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"); + } + } } else { @@ -3177,7 +3188,7 @@ namespace openvpn { // configuration const Config& conf() const { return *config; } Config& conf() { return *config; } - const Config::Ptr& conf_ptr() const { return config; } + Config::Ptr conf_ptr() const { return config; } // stats SessionStats& stat() const { return *stats; } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp index 378a6e1..d1e0656 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslapi.hpp @@ -102,12 +102,10 @@ namespace openvpn { enum PKType { PK_UNKNOWN = 0, PK_NONE, + PK_DSA, PK_RSA, - PK_ECKEY, - PK_ECKEY_DH, + PK_EC, PK_ECDSA, - PK_RSA_ALT, - PK_RSASSA_PSS, }; enum LoadFlags { @@ -125,18 +123,14 @@ namespace openvpn { { case PK_NONE: return "None"; + case PK_DSA: + return "DSA"; case PK_RSA: return "RSA"; - case PK_ECKEY: + case PK_EC: return "EC"; - case PK_ECKEY_DH: - return "EC_DH"; case PK_ECDSA: return "ECDSA"; - case PK_RSA_ALT: - return "RSA_ALT"; - case PK_RSASSA_PSS: - return "RSASSA_PSS"; case PK_UNKNOWN: default: return "Unknown"; 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 83c865f..5b48629 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp @@ -248,6 +248,7 @@ namespace openvpn { resolver.async_resolve(proxy_host, proxy_port, [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::tcp::resolver::results_type results) { + OPENVPN_ASYNC_HANDLER; self->do_resolve_(error, results); }); } @@ -927,6 +928,7 @@ namespace openvpn { socket.set_option(openvpn_io::ip::tcp::no_delay(true)); socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->start_impl_(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 ba3c33a..3a273bf 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp @@ -93,7 +93,9 @@ namespace openvpn { { halt = false; stop_requeueing = false; - if (config->remote_list->endpoint_available(&server_host, &server_port, nullptr)) + if (config->remote_list->endpoint_available(&server_host, + &server_port, + &server_protocol)) { start_connect_(); } @@ -103,6 +105,7 @@ namespace openvpn { resolver.async_resolve(server_host, server_port, [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::tcp::resolver::results_type results) { + OPENVPN_ASYNC_HANDLER; self->do_resolve_(error, results); }); } @@ -151,8 +154,7 @@ namespace openvpn { host = server_host; port = server_port; const IP::Addr addr = server_endpoint_addr(); - proto = "TCP"; - proto += addr.version_string(); + proto = server_protocol.str(); ip_addr = addr.to_string(); } @@ -163,12 +165,7 @@ namespace openvpn { virtual Protocol transport_protocol() const { - if (server_endpoint.address().is_v4()) - return Protocol(Protocol::TCPv4); - else if (server_endpoint.address().is_v6()) - return Protocol(Protocol::TCPv6); - else - return Protocol(); + return server_protocol; } virtual void stop() { stop_(); } @@ -270,7 +267,7 @@ namespace openvpn { else { std::ostringstream os; - os << "DNS resolve error on '" << server_host << "' for TCP session: " << error.message(); + os << "DNS resolve error on '" << server_host << "' for " << server_protocol.str() << " session: " << error.message(); config->stats->error(Error::RESOLVE_ERROR); stop(); parent->transport_error(Error::UNDEF, os.str()); @@ -282,7 +279,8 @@ namespace openvpn { void start_connect_() { config->remote_list->get_endpoint(server_endpoint); - OPENVPN_LOG("Contacting " << server_endpoint << " via TCP"); + OPENVPN_LOG("Contacting " << server_endpoint << " via " + << server_protocol.str()); parent->transport_wait(); parent->ip_hole_punch(server_endpoint_addr()); socket.open(server_endpoint.protocol()); @@ -293,7 +291,7 @@ namespace openvpn { { config->stats->error(Error::SOCKET_PROTECT_ERROR); stop(); - parent->transport_error(Error::UNDEF, "socket_protect error (TCP)"); + parent->transport_error(Error::UNDEF, "socket_protect error (" + std::string(server_protocol.str()) + ")"); return; } } @@ -301,6 +299,7 @@ namespace openvpn { socket.set_option(openvpn_io::ip::tcp::no_delay(true)); socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->start_impl_(error); }); } @@ -352,7 +351,7 @@ namespace openvpn { else { std::ostringstream os; - os << "TCP connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message(); + os << server_protocol.str() << " connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message(); config->stats->error(Error::TCP_CONNECT_ERROR); stop(); parent->transport_error(Error::UNDEF, os.str()); @@ -362,6 +361,7 @@ namespace openvpn { std::string server_host; std::string server_port; + Protocol server_protocol; openvpn_io::io_context& io_context; openvpn_io::ip::tcp::socket socket; 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 b53af7f..e55e7c6 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -107,6 +108,7 @@ namespace openvpn { resolver.async_resolve(server_host, server_port, [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::udp::resolver::results_type results) { + OPENVPN_ASYNC_HANDLER; self->do_resolve_(error, results); }); } @@ -283,6 +285,7 @@ namespace openvpn { #endif socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; self->start_impl_(error); }); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/protocol.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/protocol.hpp index 834c100..3c75c03 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/protocol.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/protocol.hpp @@ -186,9 +186,9 @@ namespace openvpn { case TCPv6: return "TCPv6"; case TLSv4: - return "TLSv4"; + return "TLS/TCPv4"; case TLSv6: - return "TLSv6"; + return "TLS/TCPv6"; case UnixStream: return "UnixStream"; case UnixDGram: diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplink.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplink.hpp index e48cabc..618de67 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplink.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplink.hpp @@ -30,6 +30,7 @@ #include +#include #include #include #include @@ -73,16 +74,6 @@ namespace openvpn { free_list_max_size_arg, frame_context_arg, stats_arg) { } - // Called by LinkCommon and TCPTransport Client class - unsigned int send_queue_size() const - { - return Base::queue.size() -#ifdef OPENVPN_GREMLIN - + (gremlin ? gremlin->send_size() : 0) -#endif - ; - } - private: // Called by LinkCommon virtual void from_app_send_buffer(BufferPtr& buf) override diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp index 8ce808a..3a79b5c 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/tcplinkcommon.hpp @@ -175,6 +175,7 @@ namespace openvpn { socket.async_receive(frame_context.mutable_buffer_clamp(tcpfrom->buf), [self=Ptr(this), tcpfrom=PacketFrom::SPtr(tcpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable { + OPENVPN_ASYNC_HANDLER; try { self->handle_recv(std::move(tcpfrom), error, bytes_recvd); @@ -248,6 +249,7 @@ namespace openvpn { socket.async_send(buf.const_buffer_clamp(), [self=Ptr(this)](const openvpn_io::error_code& error, const size_t bytes_sent) { + OPENVPN_ASYNC_HANDLER; self->handle_send(error, bytes_sent); }); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/udplink.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/udplink.hpp index bb2ee4a..d45a1fd 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/udplink.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/udplink.hpp @@ -143,6 +143,7 @@ namespace openvpn { udpfrom->sender_endpoint, [self=Ptr(this), udpfrom=PacketFrom::SPtr(udpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable { + OPENVPN_ASYNC_HANDLER; self->handle_read(std::move(udpfrom), error, bytes_recvd); }); } diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/dhcp_capture.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/dhcp_capture.hpp index 547b8a9..17828a3 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/dhcp_capture.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/dhcp_capture.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include @@ -54,7 +54,7 @@ namespace openvpn { return false; DHCPPacket* dhcp = (DHCPPacket*)buf.data(); - if (dhcp->ip.protocol == IPHeader::UDP + if (dhcp->ip.protocol == IPCommon::UDP && dhcp->udp.source == htons(DHCP::BOOTPS_PORT) && dhcp->udp.dest == htons(DHCP::BOOTPC_PORT) && dhcp->dhcp.op == DHCP::BOOTREPLY) diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/mac/macdns.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/mac/macdns.hpp index 4121ca3..afd8b56 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/mac/macdns.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/mac/macdns.hpp @@ -58,7 +58,8 @@ namespace openvpn { Config(const TunBuilderCapture& settings) : dns_servers(get_dns_servers(settings)), - search_domains(get_search_domains(settings)) + search_domains(get_search_domains(settings)), + adapter_domain_suffix(settings.adapter_domain_suffix) { // We redirect DNS if either of the following is true: // 1. redirect-gateway (IPv4) is pushed, or @@ -73,6 +74,7 @@ namespace openvpn { os << " SO=" << search_order; os << " DNS=" << CF::array_to_string(dns_servers); os << " DOM=" << CF::array_to_string(search_domains); + os << " ADS=" << adapter_domain_suffix; return os.str(); } @@ -80,6 +82,7 @@ namespace openvpn { int search_order = 5000; CF::Array dns_servers; CF::Array search_domains; + std::string adapter_domain_suffix; private: static CF::Array get_dns_servers(const TunBuilderCapture& settings) @@ -170,8 +173,14 @@ namespace openvpn { // set search domains info->dns.backup_orig("SearchDomains"); - if (CF::array_len(config.search_domains)) - CF::dict_set_obj(info->dns.mod, "SearchDomains", config.search_domains()); + CF::MutableArray search_domains(CF::mutable_array()); + + // add adapter_domain_suffix to SearchDomains for domain autocompletion + if (config.adapter_domain_suffix.length() > 0) + CF::array_append_str(search_domains, config.adapter_domain_suffix); + + if (CF::array_len(search_domains)) + CF::dict_set_obj(info->dns.mod, "SearchDomains", search_domains()); // set search order info->dns.backup_orig("SearchOrder"); @@ -182,16 +191,22 @@ namespace openvpn { } else { - // redirect specific domains + // split-DNS - resolve only specific domains info->ovpn.mod_reset(); if (CF::array_len(config.dns_servers) && CF::array_len(config.search_domains)) { // set DNS servers CF::dict_set_obj(info->ovpn.mod, "ServerAddresses", config.dns_servers()); - // set search domains, reverse domains can be added here as well + // DNS will be used only for those domains CF::dict_set_obj(info->ovpn.mod, "SupplementalMatchDomains", config.search_domains()); + + // do not use those domains in autocompletion + CF::dict_set_int(info->ovpn.mod, "SupplementalMatchDomainsNoSearch", 1); } + + // in case of split-DNS macOS uses domain suffix of network adapter, + // not the one provided by VPN (which we put to SearchDomains) // push it mod |= info->ovpn.push_to_store(); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/tunio.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/tunio.hpp index 0a5098a..51aa900 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/tunio.hpp +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/tunio.hpp @@ -26,10 +26,11 @@ #include +#include #include #include #include -#include +#include #include #include #include @@ -73,7 +74,7 @@ namespace openvpn { { if (buf.offset() >= 4 && buf.size() >= 1) { - switch (IPHeader::version(buf[0])) + switch (IPCommon::version(buf[0])) { case 4: prepend_pf_inet(buf, PF_INET); @@ -208,6 +209,7 @@ namespace openvpn { stream->async_read_some(frame_context.mutable_buffer(tunfrom->buf), [self=Ptr(this), tunfrom=typename PacketFrom::SPtr(tunfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable { + OPENVPN_ASYNC_HANDLER; self->handle_read(std::move(tunfrom), error, bytes_recvd); }); } 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 a16d372..ac23be5 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 @@ -391,6 +391,7 @@ namespace openvpn { l2_timer.expires_after(Time::Duration::seconds(seconds)); l2_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { + OPENVPN_ASYNC_HANDLER; if (!error && !self->halt) self->layer_2_timer_callback(); }); 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 69a0d56..ef74426 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 @@ -294,6 +294,9 @@ namespace openvpn { // Process ifconfig and topology if (!l2_post) { + // set lowest interface metric to make Windows use pushed DNS search domain + create.add(new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=1")); + const std::string metric = route_metric_opt(pull, *local4, MT_IFACE); const std::string netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length).to_string(); const IP::Addr localaddr = IP::Addr::from_string(local4->address); diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build index b482fdc..e78d98f 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build @@ -237,6 +237,8 @@ fi # Cityhash if [ "$CITY" = "1" ]; then + LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" + CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include" LIBS="$LIBS -lcityhash" CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH" fi diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-all b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-all index c773799..51c79ab 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-all +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-all @@ -12,6 +12,8 @@ echo "******* MBEDTLS" $O3/core/scripts/linux/build-mbedtls echo "******* LZ4" $O3/core/scripts/linux/build-lz4 +echo "******* CITYHASH" +$O3/core/scripts/linux/build-cityhash #$O3/core/scripts/linux/build-openssl x64 #$O3/core/scripts/linux/build-lzo diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-cityhash b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-cityhash new file mode 100755 index 0000000..8349a20 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/linux/build-cityhash @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -e +if [ -z "$O3" ]; then + echo O3 var must point to ovpn3 tree ; exit 1 +fi +if [ -z "$DEP_DIR" ]; then + echo DEP_DIR var must point to ovpn3 dependency tree + exit 1 +fi +cd $DEP_DIR +rm -rf cityhash +mkdir cityhash +TARGET=linux $O3/core/deps/cityhash/build-cityhash +exit 0 diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/version b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/version new file mode 100755 index 0000000..97ffd3f --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/version @@ -0,0 +1,34 @@ +#!/bin/bash + +# OpenVPN -- An application to securely tunnel IP networks +# over a single port, with support for SSL/TLS-based +# session authentication and key exchange, +# packet encryption, packet authentication, and +# packet compression. +# +# Copyright (C) 2018 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 . + +set -eu + +# ensure this script works even when core is used as submodule, by setting +# O3/core/.git as git folder +export GIT_DIR=$(dirname $0)/../.git + +MAJOR=3 +BRANCH="$(git rev-parse --symbolic-full-name HEAD | cut -d/ -f3- | tr / _)" +COMMIT_ID="$(git rev-list HEAD -1 --abbrev-commit)" + +echo "$MAJOR.git:$BRANCH:$COMMIT_ID" diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go index dbad4ad..8f1a1ec 100755 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go @@ -1,4 +1,11 @@ #!/bin/bash + +# Options: +# OSSL=1 -- build using OpenSSL +# MTLS=1 -- build using mbedTLS +# PTPROXY=1 -- build using Private Tunnel proxy + +# Other options GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN" [ "$EER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DTEST_EER" [ "$NULL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_FORCE_TUN_NULL" @@ -11,25 +18,26 @@ GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN" if [ "$AGENT" = "1" ]; then GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT" fi +GCC_EXTRA="$GCC_EXTRA -DOPENVPN_VERSION=\"$($(dirname $0)/../../scripts/version)\"" export GCC_EXTRA + +# determine platform if [ "$(uname)" == "Darwin" ]; then - cd $O3/core - if [ "$DEBUG" = "3" ]; then - . vars/vars-osx64-dbg - else - . vars/vars-osx64 - fi - . vars/setpath - cd test/ovpncli - ASIO=1 MTLS=1 LZ4=1 PTPROXY=1 build cli 2>&1 + export PROF=osx64 +elif [ "$(uname)" == "Linux" ]; then + export PROF=linux else - cd $O3/core - if [ "$DEBUG" = "3" ]; then - . vars/vars-linux-dbg - else - . vars/vars-linux - fi - . vars/setpath - cd test/ovpncli - ASIO=1 MTLS=1 LZ4=1 NOSSL=1 PTPROXY=1 build cli 2>&1 + echo this script only knows how to build on Mac OS or Linux fi + +# use mbedTLS by default +[[ -z "$OSSL" && -z "$MTLS" ]] && export MTLS=1 + +# don't link with OpenSSL if mbedTLS is specified +if [ "$MTLS" = "1" ]; then + export OSSL=0 + export NOSSL=1 +fi + +# build +ASIO=1 LZ4=1 ../../scripts/build cli diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path index 753c493..61edf99 100644 --- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/android-sdk-path @@ -4,3 +4,4 @@ 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/vars/vars-android-srconly b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-srconly new file mode 100644 index 0000000..67bb063 --- /dev/null +++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-srconly @@ -0,0 +1 @@ +# Nothing in here diff --git a/Sources/OpenVPNAdapter/OpenVPNPacket.mm b/Sources/OpenVPNAdapter/OpenVPNPacket.mm index 0846016..9acecae 100644 --- a/Sources/OpenVPNAdapter/OpenVPNPacket.mm +++ b/Sources/OpenVPNAdapter/OpenVPNPacket.mm @@ -9,7 +9,7 @@ #include -#include +#include @interface OpenVPNPacket () { NSData *_data; @@ -39,7 +39,7 @@ uint32_t protocol = PF_UNSPEC; - uint32_t version = openvpn::IPHeader::version(header); + uint32_t version = openvpn::IPCommon::version(header); switch (version) { case 4: protocol = PF_INET;