diff --git a/Configuration/Framework.xcconfig b/Configuration/Framework.xcconfig
index b72131d..7343136 100755
--- a/Configuration/Framework.xcconfig
+++ b/Configuration/Framework.xcconfig
@@ -12,5 +12,5 @@ LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*] = "$(VENDORS_DIR)/lz4/lib/sim" "$(VEN
LIBRARY_SEARCH_PATHS[sdk=iphoneos*] = "$(VENDORS_DIR)/lz4/lib/ios" "$(VENDORS_DIR)/mbedtls/lib/ios"
LIBRARY_SEARCH_PATHS[sdk=macosx*] = "$(VENDORS_DIR)/lz4/lib/macos" "$(VENDORS_DIR)/mbedtls/lib/macos"
OTHER_LDFLAGS = -lmbedtls -lmbedx509 -lmbedcrypto -llz4
-OTHER_CPLUSPLUSFLAGS = $(OTHER_CFLAGS) -DUSE_ASIO -DUSE_ASIO_THREADLOCAL -DASIO_STANDALONE -DASIO_NO_DEPRECATED -DHAVE_LZ4 -DUSE_MBEDTLS -DOPENVPN_FORCE_TUN_NULL -DUSE_TUN_BUILDER
+OTHER_CPLUSPLUSFLAGS = $(OTHER_CFLAGS) -DUSE_ASIO -DUSE_ASIO_THREADLOCAL -DASIO_STANDALONE -DASIO_NO_DEPRECATED -DASIO_HAS_STD_STRING_VIEW -DHAVE_LZ4 -DUSE_MBEDTLS -DOPENVPN_FORCE_TUN_NULL -DUSE_TUN_BUILDER
GCC_WARN_64_TO_32_BIT_CONVERSION = NO
diff --git a/Configuration/Info-Framework.plist b/Configuration/Info-Framework.plist
index db8ba7b..badd676 100644
--- a/Configuration/Info-Framework.plist
+++ b/Configuration/Info-Framework.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.1.0
+ 0.2.0
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
NSPrincipalClass
diff --git a/NOTICE b/NOTICE
index f57541a..0612210 100644
--- a/NOTICE
+++ b/NOTICE
@@ -4,7 +4,6 @@ Third party libraries used by the OpenVPNAdapter project:
--------------------------------------------------------------------
Dependency: https://github.com/OpenVPN/openvpn3
-Revision: 3e002c83ce2e9f9f40ddcee750d3cfa664238abe
License type: GNU Affero General Public License - Version 3.0
--------------------------------------------------------------------
OpenVPN Library
@@ -675,7 +674,6 @@ For more information on this, and how to apply and follow the GNU AGPL, see
--------------------------------------------------------------------
Dependency: https://github.com/ARMmbed/mbedtls
-Revision: 72ea31b026e1fc61b01662474aa5125817b968bc
License type: Apache License - Version 2.0
--------------------------------------------------------------------
mbedTLS Library
@@ -886,7 +884,6 @@ limitations under the License.
--------------------------------------------------------------------
Dependency: https://github.com/chriskohlhoff/asio
-Revision: 72ea31b026e1fc61b01662474aa5125817b968bc
License type: Boost Software License - Version 1.0
--------------------------------------------------------------------
ASIO Library
@@ -920,7 +917,6 @@ DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------
Dependency: https://github.com/lz4/lz4
-Revision: c10863b98e1503af90616ae99725ecd120265dfb
License type: BSD 2-Clause License
--------------------------------------------------------------------
LZ4 Library
diff --git a/OpenVPNAdapter.podspec b/OpenVPNAdapter.podspec
index 9df2af5..8cf5f11 100644
--- a/OpenVPNAdapter.podspec
+++ b/OpenVPNAdapter.podspec
@@ -3,7 +3,7 @@ Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.name = "OpenVPNAdapter"
- s.version = "0.1.0"
+ s.version = "0.2.0"
s.summary = "Objective-C wrapper for OpenVPN library. Compatible with iOS and macOS."
s.description = <<-DESC
OpenVPNAdapter is an Objective-C framework that allows to easily configure and establish VPN connection using OpenVPN protocol.
@@ -143,7 +143,7 @@ Pod::Spec.new do |s|
openvpn.xcconfig = {
"HEADER_SEARCH_PATHS" => "${PODS_TARGET_SRCROOT}/#{openvpn_path}/**",
- "OTHER_CPLUSPLUSFLAGS" => "$(OTHER_CFLAGS) -DUSE_ASIO -DUSE_ASIO_THREADLOCAL -DASIO_STANDALONE -DASIO_NO_DEPRECATED -DHAVE_LZ4 -DUSE_MBEDTLS -DOPENVPN_FORCE_TUN_NULL -DUSE_TUN_BUILDER"
+ "OTHER_CPLUSPLUSFLAGS" => "$(OTHER_CFLAGS) -DUSE_ASIO -DUSE_ASIO_THREADLOCAL -DASIO_STANDALONE -DASIO_NO_DEPRECATED -DASIO_HAS_STD_STRING_VIEW -DHAVE_LZ4 -DUSE_MBEDTLS -DOPENVPN_FORCE_TUN_NULL -DUSE_TUN_BUILDER"
}
end
diff --git a/OpenVPNAdapter.xcodeproj/project.pbxproj b/OpenVPNAdapter.xcodeproj/project.pbxproj
index 57aed9b..f0a7128 100644
--- a/OpenVPNAdapter.xcodeproj/project.pbxproj
+++ b/OpenVPNAdapter.xcodeproj/project.pbxproj
@@ -775,7 +775,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
- LastUpgradeCheck = 0930;
+ LastUpgradeCheck = 1020;
TargetAttributes = {
C9BB475B1E71663A00F3F98C = {
CreatedOnToolsVersion = 8.2.1;
@@ -785,7 +785,7 @@
C9BB478D1E71821A00F3F98C = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = 2TWXCGG7R3;
- LastSwiftMigration = 0900;
+ LastSwiftMigration = 1020;
ProvisioningStyle = Manual;
};
C9D2ABD81EA20F99007EDF9D = {
@@ -793,13 +793,13 @@
};
C9D2ABF21EA212A3007EDF9D = {
DevelopmentTeam = 2TWXCGG7R3;
- LastSwiftMigration = 0900;
+ LastSwiftMigration = 1020;
};
};
};
buildConfigurationList = C91030FB1E471D760004DFFE /* Build configuration list for PBXProject "OpenVPNAdapter" */;
compatibilityVersion = "Xcode 8.0";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -1240,7 +1240,7 @@
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -1285,7 +1285,7 @@
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -1437,7 +1437,7 @@
SUPPORTED_PLATFORMS = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -1483,7 +1483,7 @@
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
diff --git a/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter iOS.xcscheme b/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter iOS.xcscheme
index 11230dc..b6344ff 100644
--- a/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter iOS.xcscheme
+++ b/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter iOS.xcscheme
@@ -1,6 +1,6 @@
'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.1.0'
+ pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.2.0'
end
```
@@ -53,7 +53,7 @@ Then we need to create or load a VPN profile. [`NETunnelProviderManager`](https:
```swift
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
guard error == nil else {
- // Handle an occured error
+ // Handle an occurred error
return
}
@@ -65,7 +65,7 @@ The next step is to provide VPN settings to the instance of [`NETunnelProviderMa
```swift
self.providerManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else {
- // Handle an occured error
+ // Handle an occurred error
return
}
@@ -107,7 +107,7 @@ self.providerManager?.loadFromPreferences(completionHandler: { (error) in
// Save configuration in the Network Extension preferences
self.providerManager?.saveToPreferences(completionHandler: { (error) in
if let error = error {
- // Handle an occured error
+ // Handle an occurred error
}
})
}
@@ -118,14 +118,14 @@ Start VPN by calling the following code.
```swift
self.providerManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else {
- // Handle an occured error
+ // Handle an occurred error
return
}
do {
try self.providerManager?.connection.startVPNTunnel()
} catch {
- // Handle an occured error
+ // Handle an occurred error
}
}
```
@@ -247,7 +247,12 @@ extension PacketTunnelProvider: OpenVPNAdapterDelegate {
// `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so
// you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and
// send `self.packetFlow` to `completionHandler` callback.
- func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
+ func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
+ // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers
+ // send empty string to NEDNSSettings.matchDomains
+ networkSettings?.dnsSettings?.matchDomains = [""]
+
+ // Specify the network settings for the current tunneling session.
setTunnelNetworkSettings(settings) { (error) in
completionHandler(error == nil ? self.packetFlow : nil)
}
@@ -320,7 +325,7 @@ extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {}
Any contributions and suggestions are welcome! But before creating a PR or an issue please read the [Contribution Guide](CONTRIBUTING.md).
## Acknowledgments
-Special thanks goes to @JonathanDowning for great help in development of this project and bug fixing.
+Special thanks goes to [@JonathanDowning](https://github.com/JonathanDowning) for great help in development of this project and bug fixing.
## License
OpenVPNAdapter is available under the AGPLv3 license. See the [LICENSE](LICENSE) file for more info. Also this project has a few dependencies:
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 4343016..0d1b0d2 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,6 +865,8 @@ 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 4146a46..f0ae258 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,6 +18,7 @@
#include "asio/detail/config.hpp"
#include
#include
+#include
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
@@ -299,6 +300,12 @@ public:
return !a.equal(b);
}
+ template
+ void randomize(Random& r)
+ {
+ std::shuffle(this->values_->begin(), this->values_->end(), r);
+ }
+
private:
typedef std::vector > values_type;
};
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/include/lz4.h b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/include/lz4.h
index df648eb..059ef7c 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/include/lz4.h
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/include/lz4.h
@@ -1,7 +1,7 @@
/*
* LZ4 - Fast LZ compression algorithm
* Header File
- * Copyright (C) 2011-2017, Yann Collet.
+ * Copyright (C) 2011-present, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -46,7 +46,7 @@ extern "C" {
/**
Introduction
- LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core,
+ LZ4 is lossless compression algorithm, providing compression speed at 500 MB/s per core,
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
@@ -62,8 +62,8 @@ extern "C" {
An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md),
take care of encoding standard metadata alongside LZ4-compressed blocks.
- If your application requires interoperability, it's recommended to use it.
- A library is provided to take care of it, see lz4frame.h.
+ Frame format is required for interoperability.
+ It is delivered through a companion API, declared in lz4frame.h.
*/
/*^***************************************************************
@@ -72,24 +72,28 @@ extern "C" {
/*
* LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
-* LZ4LIB_API :
+* LZ4LIB_VISIBILITY :
* Control library symbols visibility.
*/
-#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
-# define LZ4LIB_API __declspec(dllexport)
-#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
-# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
-#elif defined(__GNUC__) && (__GNUC__ >= 4)
-# define LZ4LIB_API __attribute__ ((__visibility__ ("default")))
-#else
-# define LZ4LIB_API
+#ifndef LZ4LIB_VISIBILITY
+# if defined(__GNUC__) && (__GNUC__ >= 4)
+# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
+# else
+# define LZ4LIB_VISIBILITY
+# endif
+#endif
+#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
+# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
+#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
+# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
+#else
+# define LZ4LIB_API LZ4LIB_VISIBILITY
#endif
-
/*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */
-#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
+#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
@@ -98,8 +102,8 @@ extern "C" {
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
-LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; to be used when checking dll version */
-LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; to be used when checking dll version */
+LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
+LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; unseful to check dll version */
/*-************************************
@@ -109,7 +113,7 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string;
* LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
* Increasing memory usage improves compression ratio
- * Reduced memory usage can improve speed, due to cache effect
+ * Reduced memory usage may improve speed, thanks to cache effect
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/
#ifndef LZ4_MEMORY_USAGE
@@ -120,30 +124,29 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string;
* Simple Functions
**************************************/
/*! LZ4_compress_default() :
- Compresses 'sourceSize' bytes from buffer 'source'
- into already allocated 'dest' buffer of size 'maxDestSize'.
- Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
+ Compresses 'srcSize' bytes from buffer 'src'
+ into already allocated 'dst' buffer of size 'dstCapacity'.
+ Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
It also runs faster, so it's a recommended setting.
- If the function cannot compress 'source' into a more limited 'dest' budget,
+ If the function cannot compress 'src' into a more limited 'dst' budget,
compression stops *immediately*, and the function result is zero.
- As a consequence, 'dest' content is not valid.
- This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
- sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
- maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
- return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
- or 0 if compression fails */
-LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
+ Note : as a consequence, 'dst' content is not valid.
+ Note 2 : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
+ srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
+ dstCapacity : size of buffer 'dst' (which must be already allocated)
+ return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
+ or 0 if compression fails */
+LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_safe() :
- compressedSize : is the precise full size of the compressed block.
- maxDecompressedSize : is the size of destination buffer, which must be already allocated.
- return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
- If destination buffer is not large enough, decoding will stop and output an error code (<0).
+ compressedSize : is the exact complete size of the compressed block.
+ dstCapacity : is the size of destination buffer, which must be already allocated.
+ return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
+ If destination buffer is not large enough, decoding will stop and output an error code (negative value).
If the source stream is detected malformed, the function will stop decoding and return a negative result.
- This function is protected against buffer overflow exploits, including malicious data packets.
- It never writes outside output buffer, nor reads outside input buffer.
+ This function is protected against malicious data packets.
*/
-LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
+LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
/*-************************************
@@ -157,22 +160,22 @@ LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
- Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
+ Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
- or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
+ or 0, if input size is incorrect (too large or negative)
*/
LZ4LIB_API int LZ4_compressBound(int inputSize);
/*!
LZ4_compress_fast() :
- Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
+ Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
- Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
+ Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).
*/
-LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
+LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*!
@@ -180,58 +183,79 @@ LZ4_compress_fast_extState() :
Same compression function, just using an externally allocated memory space to store compression state.
Use LZ4_sizeofState() to know how much memory must be allocated,
and allocate it on 8-bytes boundaries (using malloc() typically).
- Then, provide it as 'void* state' to compression function.
+ Then, provide this buffer as 'void* state' to compression function.
*/
LZ4LIB_API int LZ4_sizeofState(void);
-LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
+LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
-/*!
-LZ4_compress_destSize() :
- Reverse the logic, by compressing as much data as possible from 'source' buffer
- into already allocated buffer 'dest' of size 'targetDestSize'.
- This function either compresses the entire 'source' content into 'dest' if it's large enough,
- or fill 'dest' buffer completely with as much data as possible from 'source'.
- *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
- New value is necessarily <= old value.
- return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
- or 0 if compression fails
+/*! LZ4_compress_destSize() :
+ * Reverse the logic : compresses as much data as possible from 'src' buffer
+ * into already allocated buffer 'dst', of size >= 'targetDestSize'.
+ * This function either compresses the entire 'src' content into 'dst' if it's large enough,
+ * or fill 'dst' buffer completely with as much data as possible from 'src'.
+ * note: acceleration parameter is fixed to "default".
+ *
+ * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
+ * New value is necessarily <= input value.
+ * @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
+ * or 0 if compression fails.
*/
-LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
+LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
-/*!
-LZ4_decompress_fast() :
- originalSize : is the original and therefore uncompressed size
- return : the number of bytes read from the source buffer (in other words, the compressed size)
- If the source stream is detected malformed, the function will stop decoding and return a negative result.
- Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
- note : This function fully respect memory boundaries for properly formed compressed data.
- It is a bit faster than LZ4_decompress_safe().
- However, it does not provide any protection against intentionally modified data stream (malicious input).
- Use this function in trusted environment only (data to decode comes from a trusted source).
-*/
-LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
+/*! LZ4_decompress_fast() : **unsafe!**
+ * This function used to be a bit faster than LZ4_decompress_safe(),
+ * though situation has changed in recent versions,
+ * and now `LZ4_decompress_safe()` can be as fast and sometimes faster than `LZ4_decompress_fast()`.
+ * Moreover, LZ4_decompress_fast() is not protected vs malformed input, as it doesn't perform full validation of compressed data.
+ * As a consequence, this function is no longer recommended, and may be deprecated in future versions.
+ * It's only remaining specificity is that it can decompress data without knowing its compressed size.
+ *
+ * originalSize : is the uncompressed size to regenerate.
+ * `dst` must be already allocated, its size must be >= 'originalSize' bytes.
+ * @return : number of bytes read from source buffer (== compressed size).
+ * If the source stream is detected malformed, the function stops decoding and returns a negative result.
+ * note : This function requires uncompressed originalSize to be known in advance.
+ * The function never writes past the output buffer.
+ * However, since it doesn't know its 'src' size, it may read past the intended input.
+ * Also, because match offsets are not validated during decoding,
+ * reads from 'src' may underflow.
+ * Use this function in trusted environment **only**.
+ */
+LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
-/*!
-LZ4_decompress_safe_partial() :
- This function decompress a compressed block of size 'compressedSize' at position 'source'
- into destination buffer 'dest' of size 'maxDecompressedSize'.
- The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
- reducing decompression time.
- return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
- Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
- Always control how many bytes were decoded.
- If the source stream is detected malformed, the function will stop decoding and return a negative result.
- This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
-*/
-LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
+/*! LZ4_decompress_safe_partial() :
+ * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
+ * into destination buffer 'dst' of size 'dstCapacity'.
+ * Up to 'targetOutputSize' bytes will be decoded.
+ * The function stops decoding on reaching this objective,
+ * which can boost performance when only the beginning of a block is required.
+ *
+ * @return : the number of bytes decoded in `dst` (necessarily <= dstCapacity)
+ * If source stream is detected malformed, function returns a negative result.
+ *
+ * Note : @return can be < targetOutputSize, if compressed block contains less data.
+ *
+ * Note 2 : this function features 2 parameters, targetOutputSize and dstCapacity,
+ * and expects targetOutputSize <= dstCapacity.
+ * It effectively stops decoding on reaching targetOutputSize,
+ * so dstCapacity is kind of redundant.
+ * This is because in a previous version of this function,
+ * decoding operation would not "break" a sequence in the middle.
+ * As a consequence, there was no guarantee that decoding would stop at exactly targetOutputSize,
+ * it could write more bytes, though only up to dstCapacity.
+ * Some "margin" used to be required for this operation to work properly.
+ * This is no longer necessary.
+ * The function nonetheless keeps its signature, in an effort to not break API.
+ */
+LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
/*-*********************************************
* Streaming Compression Functions
***********************************************/
-typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
+typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
/*! LZ4_createStream() and LZ4_freeStream() :
* LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure.
@@ -242,87 +266,219 @@ LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
/*! LZ4_resetStream() :
* An LZ4_stream_t structure can be allocated once and re-used multiple times.
- * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression.
+ * Use this function to start compressing a new stream.
*/
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
/*! LZ4_loadDict() :
- * Use this function to load a static dictionary into LZ4_stream.
+ * Use this function to load a static dictionary into LZ4_stream_t.
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
- * Loading a size of 0 is allowed.
- * Return : dictionary size, in bytes (necessarily <= 64 KB)
+ * Loading a size of 0 is allowed, and is the same as reset.
+ * @return : dictionary size, in bytes (necessarily <= 64 KB)
*/
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_compress_fast_continue() :
- * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
- * Important : Previous data blocks are assumed to remain present and unmodified !
+ * Compress 'src' content using data from previously compressed blocks, for better compression ratio.
* 'dst' buffer must be already allocated.
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
- * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function @return==0.
- * After an error, the stream status is invalid, it can only be reset or freed.
+ *
+ * @return : size of compressed block
+ * or 0 if there is an error (typically, cannot fit into 'dst').
+ *
+ * Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
+ * Each block has precise boundaries.
+ * It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
+ * Each block must be decompressed separately, calling LZ4_decompress_*() with associated metadata.
+ *
+ * Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory!
+ *
+ * Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
+ * Make sure that buffers are separated, by at least one byte.
+ * This construction ensures that each block only depends on previous block.
+ *
+ * Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
+ *
+ * Note 5 : After an error, the stream status is invalid, it can only be reset or freed.
*/
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_saveDict() :
- * If previously compressed data block is not guaranteed to remain available at its current memory location,
+ * If last 64KB data cannot be guaranteed to remain available at its current memory location,
* save it into a safer place (char* safeBuffer).
- * Note : it's not necessary to call LZ4_loadDict() after LZ4_saveDict(), dictionary is immediately usable.
- * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
+ * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
+ * but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
+ * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
*/
-LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
+LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
/*-**********************************************
* Streaming Decompression Functions
* Bufferless synchronous API
************************************************/
-typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */
+typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
- * creation / destruction of streaming decompression tracking structure */
+ * creation / destruction of streaming decompression tracking context.
+ * A tracking context can be re-used multiple times.
+ */
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
/*! LZ4_setStreamDecode() :
- * Use this function to instruct where to find the dictionary.
- * Setting a size of 0 is allowed (same effect as reset).
- * @return : 1 if OK, 0 if error
+ * An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
+ * Use this function to start decompression of a new stream of blocks.
+ * A dictionary can optionally be set. Use NULL or size 0 for a reset order.
+ * Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
+ * @return : 1 if OK, 0 if error
*/
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
+/*! LZ4_decoderRingBufferSize() : v1.8.2
+ * Note : in a ring buffer scenario (optional),
+ * blocks are presumed decompressed next to each other
+ * up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
+ * at which stage it resumes from beginning of ring buffer.
+ * When setting such a ring buffer for streaming decompression,
+ * provides the minimum size of this ring buffer
+ * to be compatible with any source respecting maxBlockSize condition.
+ * @return : minimum ring buffer size,
+ * or 0 if there is an error (invalid maxBlockSize).
+ */
+LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
+#define LZ4_DECODER_RING_BUFFER_SIZE(mbs) (65536 + 14 + (mbs)) /* for static allocation; mbs presumed valid */
+
/*! LZ4_decompress_*_continue() :
- * These decoding functions allow decompression of multiple blocks in "streaming" mode.
- * Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
- * In the case of a ring buffers, decoding buffer must be either :
- * - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
- * In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
- * - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
- * maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
+ * These decoding functions allow decompression of consecutive blocks in "streaming" mode.
+ * A block is an unsplittable entity, it must be presented entirely to a decompression function.
+ * Decompression functions only accepts one block at a time.
+ * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
+ * If less than 64KB of data has been decoded, all the data must be present.
+ *
+ * Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
+ * - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
+ * maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
+ * In which case, encoding and decoding buffers do not need to be synchronized.
+ * Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
+ * - Synchronized mode :
+ * Decompression buffer size is _exactly_ the same as compression buffer size,
+ * and follows exactly same update rule (block boundaries at same positions),
+ * and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
+ * _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
+ * - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
* In which case, encoding and decoding buffers do not need to be synchronized,
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
- * - _At least_ 64 KB + 8 bytes + maxBlockSize.
- * In which case, encoding and decoding buffers do not need to be synchronized,
- * and encoding ring buffer can have any size, including larger than decoding buffer.
- * Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
- * and indicate where it is saved using LZ4_setStreamDecode()
+ *
+ * Whenever these conditions are not possible,
+ * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
+ * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
*/
-LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
-LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
+LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
+LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
/*! LZ4_decompress_*_usingDict() :
* These decoding functions work the same as
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
+ * Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
*/
-LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
-LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
+LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
+LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
/*^**********************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***********************************************/
+
+/*-************************************
+ * Unstable declarations
+ **************************************
+ * Declarations in this section should be considered unstable.
+ * Use at your own peril, etc., etc.
+ * They may be removed in the future.
+ * Their signatures may change.
+ **************************************/
+
+#ifdef LZ4_STATIC_LINKING_ONLY
+
+/*! LZ4_resetStream_fast() :
+ * Use this, like LZ4_resetStream(), to prepare a context for a new chain of
+ * calls to a streaming API (e.g., LZ4_compress_fast_continue()).
+ *
+ * Note:
+ * Using this in advance of a non- streaming-compression function is redundant,
+ * and potentially bad for performance, since they all perform their own custom
+ * reset internally.
+ *
+ * Differences from LZ4_resetStream():
+ * When an LZ4_stream_t is known to be in a internally coherent state,
+ * it can often be prepared for a new compression with almost no work, only
+ * sometimes falling back to the full, expensive reset that is always required
+ * when the stream is in an indeterminate state (i.e., the reset performed by
+ * LZ4_resetStream()).
+ *
+ * LZ4_streams are guaranteed to be in a valid state when:
+ * - returned from LZ4_createStream()
+ * - reset by LZ4_resetStream()
+ * - memset(stream, 0, sizeof(LZ4_stream_t)), though this is discouraged
+ * - the stream was in a valid state and was reset by LZ4_resetStream_fast()
+ * - the stream was in a valid state and was then used in any compression call
+ * that returned success
+ * - the stream was in an indeterminate state and was used in a compression
+ * call that fully reset the state (e.g., LZ4_compress_fast_extState()) and
+ * that returned success
+ *
+ * When a stream isn't known to be in a valid state, it is not safe to pass to
+ * any fastReset or streaming function. It must first be cleansed by the full
+ * LZ4_resetStream().
+ */
+LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
+
+/*! LZ4_compress_fast_extState_fastReset() :
+ * A variant of LZ4_compress_fast_extState().
+ *
+ * Using this variant avoids an expensive initialization step. It is only safe
+ * to call if the state buffer is known to be correctly initialized already
+ * (see above comment on LZ4_resetStream_fast() for a definition of "correctly
+ * initialized"). From a high level, the difference is that this function
+ * initializes the provided state with a call to something like
+ * LZ4_resetStream_fast() while LZ4_compress_fast_extState() starts with a
+ * call to LZ4_resetStream().
+ */
+LZ4LIB_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
+
+/*! LZ4_attach_dictionary() :
+ * This is an experimental API that allows for the efficient use of a
+ * static dictionary many times.
+ *
+ * Rather than re-loading the dictionary buffer into a working context before
+ * each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
+ * working LZ4_stream_t, this function introduces a no-copy setup mechanism,
+ * in which the working stream references the dictionary stream in-place.
+ *
+ * Several assumptions are made about the state of the dictionary stream.
+ * Currently, only streams which have been prepared by LZ4_loadDict() should
+ * be expected to work.
+ *
+ * Alternatively, the provided dictionary stream pointer may be NULL, in which
+ * case any existing dictionary stream is unset.
+ *
+ * If a dictionary is provided, it replaces any pre-existing stream history.
+ * The dictionary contents are the only history that can be referenced and
+ * logically immediately precede the data compressed in the first subsequent
+ * compression call.
+ *
+ * The dictionary will only remain attached to the working stream through the
+ * first compression call, at the end of which it is cleared. The dictionary
+ * stream (and source buffer) must remain in-place / accessible / unchanged
+ * through the completion of the first compression call on the stream.
+ */
+LZ4LIB_API void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream);
+
+#endif
+
/*-************************************
* Private definitions
**************************************
@@ -337,14 +493,16 @@ LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, in
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
#include
-typedef struct {
+typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
+struct LZ4_stream_t_internal {
uint32_t hashTable[LZ4_HASH_SIZE_U32];
uint32_t currentOffset;
- uint32_t initCheck;
+ uint16_t initCheck;
+ uint16_t tableType;
const uint8_t* dictionary;
- uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */
+ const LZ4_stream_t_internal* dictCtx;
uint32_t dictSize;
-} LZ4_stream_t_internal;
+};
typedef struct {
const uint8_t* externalDict;
@@ -355,14 +513,16 @@ typedef struct {
#else
-typedef struct {
+typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
+struct LZ4_stream_t_internal {
unsigned int hashTable[LZ4_HASH_SIZE_U32];
unsigned int currentOffset;
- unsigned int initCheck;
+ unsigned short initCheck;
+ unsigned short tableType;
const unsigned char* dictionary;
- unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */
+ const LZ4_stream_t_internal* dictCtx;
unsigned int dictSize;
-} LZ4_stream_t_internal;
+};
typedef struct {
const unsigned char* externalDict;
@@ -409,21 +569,19 @@ union LZ4_streamDecode_u {
* Obsolete Functions
**************************************/
- /*! Deprecation warnings
- Should deprecation warnings be a problem,
- it is generally possible to disable them,
- typically with -Wno-deprecated-declarations for gcc
- or _CRT_SECURE_NO_WARNINGS in Visual.
- Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
+/*! Deprecation warnings
+ Should deprecation warnings be a problem,
+ it is generally possible to disable them,
+ typically with -Wno-deprecated-declarations for gcc
+ or _CRT_SECURE_NO_WARNINGS in Visual.
+ Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
#else
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-# if defined(__clang__) /* clang doesn't handle mixed C++11 and CNU attributes */
-# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
-# elif defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
+# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
-# elif (LZ4_GCC_VERSION >= 405)
+# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif (LZ4_GCC_VERSION >= 301)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
@@ -436,26 +594,34 @@ union LZ4_streamDecode_u {
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
/* Obsolete compression functions */
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize);
+LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
+LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete decompression functions */
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast() instead") int LZ4_uncompress (const char* source, char* dest, int outputSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_safe() instead") int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
+LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
-/* Obsolete streaming functions; use new streaming interface whenever possible */
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
+/* Obsolete streaming functions; degraded functionality; do not use!
+ *
+ * In order to perform streaming compression, these functions depended on data
+ * that is no longer tracked in the state. They have been preserved as well as
+ * possible: using them will still produce a correct output. However, they don't
+ * actually retain any history between compression calls. The compression ratio
+ * achieved will therefore be no better than compressing each chunk
+ * independently.
+ */
+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
+LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
+LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
+LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
/* Obsolete streaming decoding functions */
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
-LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
#endif /* LZ4_H_2983827168210 */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/ios/liblz4.a b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/ios/liblz4.a
index 60c3ea3..af98018 100644
Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/ios/liblz4.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/ios/liblz4.a differ
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/macos/liblz4.a b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/macos/liblz4.a
index 85e8cb0..5d87ff4 100644
Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/macos/liblz4.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/macos/liblz4.a differ
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/sim/liblz4.a b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/sim/liblz4.a
index 6f13d32..f7b7522 100644
Binary files a/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/sim/liblz4.a and b/Sources/OpenVPNAdapter/Libraries/Vendors/lz4/lib/sim/liblz4.a differ
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml
index f19a4db..d8551dc 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/.travis.yml
@@ -9,8 +9,8 @@ env:
- secure: "dqiLqbzug/xs6F4Q9ei1pGpNf9Q6H3+iKN1W+P0TtODbCXPr/mLWdvHGVMIMqr7H7rBrIUPFPrfqd80nu3jQuQonjcHK/XyJJfmf5hUdhGAszSaixhWnGfVmn/VSV7/5+9DGAU3l9S6YZg4lvi12+cOrlblNgx8GeI5VdN/6HBSHkEqKNI56qn3Y+ugSdLeL1opmzlY58vRsCCmpBH8Ronn4tmSyi85/WZXfF43o9FGGJcygdh6QVWA1CDdNMeLTCt9ld+oToUIiFLiUrhfS1JpSvzysz2xsuEntxZaTMDYPyL4+O8Mj/scl6ejLLXzxTNa7AZOgySLBahf+F4b+yhL1deSVuu40MfxPW6XiM1jKy3KPH/GlYgM8CZQ3D1hQIq1CIUg8DgnTa06RUzevsR5DqDvz+EcPanFHE7dHGrPy9Rs/0y59dNHp3qWKjWMoSA06GerbF61XFOb4mcE29053kV8uxqIa5ZShZ/ndoLeVpQ4mZ+/XSkUybysVl0gWrKnnNNEPtqrdmKf+jlmKY0jyRPdwf425Ldn+wcbGw9ZEnkosYzqAhDBDX4OETAKLi8G0FEYECKKQcd1OX+HNvsOIyOAoLOj7H30F8UkPsjR3ysdIEmc6702ly06gDYjWmwQaCigL/1ktRKgf7ePB0HS+8fOa5SML7619kQrGrWA="
- PREFIX="${HOME}/opt"
- ASIO_VERSION="862aed305dcf91387535519c9549c17630339a12"
- - LZ4_VERSION="1.7.5"
- - MBEDTLS_VERSION="2.5.1"
+ - LZ4_VERSION="1.8.3"
+ - MBEDTLS_VERSION="2.7.5"
- MBEDTLS_CFLAGS="-I${PREFIX}/include"
- MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto"
- OPENSSL_VERSION="1.0.2l"
@@ -22,11 +22,9 @@ matrix:
include:
- env: SSLLIB="openssl"
os: osx
- osx_image: xcode8.3
compiler: clang
- env: SSLLIB="mbedtls"
os: osx
- osx_image: xcode8.3
compiler: clang
- env: SSLLIB="openssl" RUN_COVERITY_SCAN="1"
os: linux
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp
index 656e16d..71182c9 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.cpp
@@ -259,10 +259,10 @@ namespace openvpn {
parent = parent_arg;
}
- virtual bool socket_protect(int socket)
+ bool socket_protect(int socket, IP::Addr endpoint) override
{
if (parent)
- return parent->socket_protect(socket);
+ return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6());
else
return true;
}
@@ -858,6 +858,9 @@ namespace openvpn {
#endif
Log::Context log_context(this);
#endif
+
+ OPENVPN_LOG(ClientAPI::OpenVPNClient::platform());
+
return do_connect();
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp
index 06575a4..218cd45 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/client/ovpncli.hpp
@@ -469,7 +469,8 @@ namespace openvpn {
// Callback to "protect" a socket from being routed through the tunnel.
// Will be called from the thread executing connect().
- virtual bool socket_protect(int socket) = 0;
+ // The remote and ipv6 are the remote host this socket will connect to
+ virtual bool socket_protect(int socket, std::string remote, bool ipv6) = 0;
// Primary VPN client connect method, doesn't return until disconnect.
// Should be called by a worker thread. This method will make callbacks
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions
index 63a16eb..90a5c26 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/deps/lib-versions
@@ -1,8 +1,8 @@
export ASIO_VERSION=asio-1-12-0
export ASIO_CSUM=fa8c3a16dc2163f5b3451f2a14ce95277c971f46700497d4e94af6059c00dc06
-export LZ4_VERSION=lz4-1.8.0
-export LZ4_CSUM=2ca482ea7a9bb103603108b5a7510b7592b90158c151ff50a28f1ca8389fccf6
+export LZ4_VERSION=lz4-1.8.3
+export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43
export MBEDTLS_VERSION=mbedtls-2.7.5
export MBEDTLS_CSUM=a1302ad9094aabb9880d2755927b466a6bac8e02b68e04dee77321f3859e9b40
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/javacli/build-android b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/javacli/build-android
index 72bfcf1..2fcfa40 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/javacli/build-android
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/javacli/build-android
@@ -76,6 +76,7 @@ $GPP_CMD \
-DASIO_NO_DEPRECATED \
-DHAVE_LZ4 \
-DOPENVPN_USE_TLS_MD5 \
+ -DASIO_HAS_STD_STRING_VIEW \
-I$O3/core/client \
-I$O3/core \
$common \
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buffer.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buffer.hpp
index 986d1cb..30c35b3 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buffer.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/buffer/buffer.hpp
@@ -557,7 +557,8 @@ namespace openvpn {
init_headroom(headroom);
}
- void append(const BufferType& other)
+ template
+ void append(const B& other)
{
write(other.c_data(), other.size());
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve.hpp
new file mode 100644
index 0000000..1ce03e4
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve.hpp
@@ -0,0 +1,37 @@
+// OpenVPN -- An application to securely tunnel IP networks
+// over a single port, with support for SSL/TLS-based
+// session authentication and key exchange,
+// packet encryption, packet authentication, and
+// packet compression.
+//
+// Copyright (C) 2012-2019 OpenVPN Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License Version 3
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_H
+#define OPENVPN_CLIENT_ASYNC_RESOLVE_H
+
+#ifdef USE_ASIO
+#include
+#else
+#include
+#endif
+
+// create shortcuts for common templated classes
+namespace openvpn {
+ typedef AsyncResolvable AsyncResolvableUDP;
+ typedef AsyncResolvable AsyncResolvableTCP;
+}
+
+#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/asio.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/asio.hpp
new file mode 100644
index 0000000..967ffb3
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/asio.hpp
@@ -0,0 +1,121 @@
+// OpenVPN -- An application to securely tunnel IP networks
+// over a single port, with support for SSL/TLS-based
+// session authentication and key exchange,
+// packet encryption, packet authentication, and
+// packet compression.
+//
+// Copyright (C) 2012-2019 OpenVPN Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License Version 3
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
+#define OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
+
+#include
+#include
+
+#include
+#include
+#include
+
+
+namespace openvpn {
+ template
+ class AsyncResolvable: public virtual RC
+ {
+ private:
+ typedef RCPtr Ptr;
+
+ openvpn_io::io_context& io_context;
+
+ class ResolveThread : public RC
+ {
+ friend class AsyncResolvable;
+
+ private:
+ typedef RCPtr Ptr;
+
+ std::unique_ptr asio_work;
+ openvpn_io::io_context& io_context;
+ AsyncResolvable *resolvable;
+
+ ResolveThread(openvpn_io::io_context &io_context_arg,
+ AsyncResolvable *resolvable_arg,
+ const std::string& host, const std::string& port)
+ : asio_work(new AsioWork(io_context_arg)),
+ io_context(io_context_arg),
+ resolvable(resolvable_arg)
+ {
+ std::thread resolve_thread([self=Ptr(this), host, port]() {
+ openvpn_io::io_context io_context(1);
+ openvpn_io::error_code error;
+ RESOLVER_TYPE resolver(io_context);
+ typename RESOLVER_TYPE::results_type results;
+ results = resolver.resolve(host, port, error);
+
+ openvpn_io::post(self->io_context, [self, results, error]() {
+ OPENVPN_ASYNC_HANDLER;
+ self->resolvable->resolve_callback(error, results);
+ });
+
+ // the AsioWork can be released now that we have posted
+ // something else to the main io_context queue
+ self->asio_work.reset();
+ });
+ // detach the thread so that the client won't need to wait for
+ // it to join.
+ resolve_thread.detach();
+ }
+ };
+
+ public:
+ AsyncResolvable(openvpn_io::io_context& io_context_arg)
+ : io_context(io_context_arg)
+ {
+ }
+
+ virtual void resolve_callback(const openvpn_io::error_code& error,
+ typename RESOLVER_TYPE::results_type results) = 0;
+
+ // mimic the asynchronous DNS resolution by performing a
+ // synchronous one in a detached thread.
+ //
+ // This strategy has the advantage of allowing the core to
+ // stop/exit without waiting for the getaddrinfo() (used
+ // internally) to terminate.
+ // Note: getaddrinfo() is non-interruptible by design.
+ //
+ // In other words, we are re-creating exactly what ASIO would
+ // normally do in case of async_resolve(), with the difference
+ // that here we have control over the resolving thread and we
+ // can easily detach it. Deatching the internal thread created
+ // by ASIO would not be feasible as it is not exposed.
+ void async_resolve_name(const std::string& host, const std::string& port)
+ {
+ // there might be nothing else in the main io_context queue
+ // right now, therefore we use AsioWork to prevent the loop
+ // from exiting while we perform the DNS resolution in the
+ // detached thread.
+ typename ResolveThread::Ptr t(new ResolveThread(io_context, this, host, port));
+ }
+
+ // The core assumes the existence of this method because it is used on
+ // other platforms (i.e. iOS), therefore we must declare it, even if no-op
+ void async_resolve_cancel()
+ {
+ }
+ };
+}
+
+#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/generic.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/generic.hpp
new file mode 100644
index 0000000..77274ee
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/async_resolve/generic.hpp
@@ -0,0 +1,74 @@
+// OpenVPN -- An application to securely tunnel IP networks
+// over a single port, with support for SSL/TLS-based
+// session authentication and key exchange,
+// packet encryption, packet authentication, and
+// packet compression.
+//
+// Copyright (C) 2012-2019 OpenVPN Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License Version 3
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H
+#define OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H
+
+#include
+#include
+#include
+
+
+namespace openvpn {
+ template
+ class AsyncResolvable: public virtual RC
+ {
+ private:
+ typedef RCPtr Ptr;
+
+ openvpn_io::io_context& io_context;
+ RESOLVER_TYPE resolver;
+
+ public:
+ AsyncResolvable(openvpn_io::io_context& io_context_arg)
+ : io_context(io_context_arg),
+ resolver(io_context_arg)
+ {
+ }
+
+ virtual void resolve_callback(const openvpn_io::error_code& error,
+ typename RESOLVER_TYPE::results_type results) = 0;
+
+ // This implementation assumes that the i/o reactor provides an asynchronous
+ // DNS resolution routine using its own primitives and that doesn't require
+ // us to take care of any non-interruptible opration (i.e. getaddrinfo() in
+ // case of ASIO).
+ //
+ // For example, iOS implements aync_resolve using GCD and CFHost. This
+ // implementation satisfies the constraints mentioned above
+ void async_resolve_name(const std::string& host, const std::string& port)
+ {
+ resolver.async_resolve(host, port, [self=Ptr(this)](const openvpn_io::error_code& error,
+ typename RESOLVER_TYPE::results_type results)
+ {
+ OPENVPN_ASYNC_HANDLER;
+ self->resolve_callback(error, results);
+ });
+ }
+
+ void async_resolve_cancel()
+ {
+ resolver.cancel();
+ }
+ };
+}
+
+#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp
index 419fa6b..e399df3 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliopt.hpp
@@ -395,7 +395,12 @@ namespace openvpn {
tunconf->stats = cli_stats;
tunconf->stop = config.stop;
if (config.tun_persist)
+ {
tunconf->tun_persist.reset(new TunMac::TunPersist(true, false, nullptr));
+ tunconf->tun_prop.remote_bypass = true;
+ /* remote_list is required by remote_bypass to work */
+ tunconf->tun_prop.remote_list = remote_list;
+ }
client_lifecycle.reset(new MacLifeCycle);
#ifdef OPENVPN_COMMAND_AGENT
tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt);
@@ -414,7 +419,12 @@ namespace openvpn {
tunconf->stats = cli_stats;
tunconf->stop = config.stop;
if (config.tun_persist)
+ {
tunconf->tun_persist.reset(new TunWin::TunPersist(true, false, nullptr));
+ tunconf->tun_prop.remote_bypass = true;
+ /* remote_list is required by remote_bypass to work */
+ tunconf->tun_prop.remote_list = remote_list;
+ }
#ifdef OPENVPN_COMMAND_AGENT
tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt);
#endif
@@ -693,6 +703,7 @@ namespace openvpn {
cp->dc_deferred = true; // defer data channel setup until after options pull
cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory());
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
+ cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
cp->tlsprf_factory.reset(new CryptoTLSPRFFactory());
cp->ssl_factory = cc->new_factory();
cp->load(opt, *proto_context_options, config.default_key_direction, false);
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp
index ba3a942..e7b2f5f 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/cliproto.hpp
@@ -49,6 +49,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -376,15 +377,24 @@ namespace openvpn {
// encrypt packet
if (buf.size())
{
- Base::data_encrypt(buf);
- if (buf.size())
+ const ProtoContext::Config& c = Base::conf();
+ if (c.mss_inter > 0 && buf.size() > c.mss_inter)
{
- // send packet via transport to destination
- OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << Base::dump_packet(buf));
- if (transport->transport_send(buf))
- Base::update_last_sent();
- else if (halt)
- return;
+ Ptb::generate_icmp_ptb(buf, c.mss_inter);
+ tun->tun_send(buf);
+ }
+ else
+ {
+ Base::data_encrypt(buf);
+ if (buf.size())
+ {
+ // send packet via transport to destination
+ OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << Base::dump_packet(buf));
+ if (transport->transport_send(buf))
+ Base::update_last_sent();
+ else if (halt)
+ return;
+ }
}
}
@@ -600,6 +610,13 @@ namespace openvpn {
else
OPENVPN_LOG("Options continuation...");
}
+ else if (received_options.complete() && string::starts_with(msg, "PUSH_REPLY,"))
+ {
+ // We got a PUSH REPLY in the middle of a session. Ignore it apart from
+ // updating the auth-token if included in the push reply
+ auto opts = OptionList::parse_from_csv_static(msg.substr(11), nullptr);
+ extract_auth_token(opts);
+ }
else if (string::starts_with(msg, "AUTH_FAILED"))
{
std::string reason;
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp
index 458a90a..83d07f0 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/client/remotelist.hpp
@@ -31,9 +31,12 @@
#include
#include
#include
+#include
#include
+#include
+#include
#include
#include
#include
@@ -45,6 +48,7 @@
#include
#include
#include
+#include
#if OPENVPN_DEBUG_REMOTELIST >= 1
#define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x)
@@ -53,7 +57,6 @@
#endif
namespace openvpn {
-
class RemoteList : public RC
{
// A single IP address that is part of a list of IP addresses
@@ -262,7 +265,7 @@ namespace openvpn {
// This is useful in tun_persist mode, where it may be necessary
// to pre-resolve all potential remote server items prior
// to initial tunnel establishment.
- class PreResolve : public RC
+ class PreResolve : public virtual RC, AsyncResolvableTCP
{
public:
typedef RCPtr Ptr;
@@ -276,8 +279,7 @@ namespace openvpn {
PreResolve(openvpn_io::io_context& io_context_arg,
const RemoteList::Ptr& remote_list_arg,
const SessionStats::Ptr& stats_arg)
- : io_context(io_context_arg),
- resolver(io_context_arg),
+ : AsyncResolvableTCP(io_context_arg),
notify_callback(nullptr),
remote_list(remote_list_arg),
stats(stats_arg),
@@ -313,7 +315,7 @@ namespace openvpn {
{
notify_callback = nullptr;
index = 0;
- resolver.cancel();
+ async_resolve_cancel();
}
private:
@@ -336,14 +338,8 @@ namespace openvpn {
}
else
{
- // call into Asio to do the resolve operation
OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << item.server_host << " : " << item.server_port);
- 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);
- });
+ async_resolve_name(item.server_host, item.server_port);
return;
}
}
@@ -364,7 +360,7 @@ namespace openvpn {
// callback on resolve completion
void resolve_callback(const openvpn_io::error_code& error,
- openvpn_io::ip::tcp::resolver::results_type results)
+ openvpn_io::ip::tcp::resolver::results_type results) override
{
if (notify_callback && index < remote_list->list.size())
{
@@ -385,8 +381,6 @@ namespace openvpn {
}
}
- openvpn_io::io_context& io_context;
- openvpn_io::ip::tcp::resolver resolver;
NotifyCallback* notify_callback;
RemoteList::Ptr remote_list;
SessionStats::Ptr stats;
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp
index 134f65b..bf3cf7d 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/bigmutex.hpp
@@ -34,11 +34,13 @@
#include
+#include
+
namespace openvpn {
namespace bigmutex {
OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex;
}
-
+
#ifdef OPENVPN_ENABLE_BIGMUTEX
#define OPENVPN_ASYNC_HANDLER \
std::lock_guard lg(bigmutex::the_recursive_mutex);
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian.hpp
index dd6ba70..53dd015 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian.hpp
@@ -19,25 +19,13 @@
// along with this program in the COPYING file.
// If not, see .
-#ifndef OPENVPN_COMMON_ENDIAN_H
-#define OPENVPN_COMMON_ENDIAN_H
+#pragma once
-#include
-
-// test for machine endiannes
-#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && defined(__ORDER_LITTLE_ENDIAN__)
-#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#define OPENVPN_BIG_ENDIAN
-#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#define OPENVPN_LITTLE_ENDIAN
-#endif
-#elif defined(_WIN32)
-#define OPENVPN_LITTLE_ENDIAN // assume that Windows is always little-endian
-#endif
+#include
namespace openvpn {
namespace Endian {
-# ifdef OPENVPN_LITTLE_ENDIAN
+# if defined(OPENVPN_LITTLE_ENDIAN)
inline size_t e16(const size_t v)
{
return v;
@@ -62,7 +50,7 @@ namespace openvpn {
{
return 1-v;
}
-# elif OPENVPN_BIG_ENDIAN
+# elif defined(OPENVPN_BIG_ENDIAN)
inline size_t e16rev(const size_t v)
{
return v;
@@ -92,5 +80,3 @@ namespace openvpn {
# endif
}
} // namespace openvpn
-
-#endif // OPENVPN_COMMON_ENDIAN_H
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian_platform.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian_platform.hpp
new file mode 100644
index 0000000..353a4e8
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/endian_platform.hpp
@@ -0,0 +1,35 @@
+// 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
+
+// test for machine endiannes
+#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && defined(__ORDER_LITTLE_ENDIAN__)
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define OPENVPN_BIG_ENDIAN
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define OPENVPN_LITTLE_ENDIAN
+#endif
+#elif defined(_WIN32)
+#define OPENVPN_LITTLE_ENDIAN // assume that Windows is always little-endian
+#endif
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/ffs.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/ffs.hpp
index da8373d..b92b942 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/ffs.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/ffs.hpp
@@ -32,18 +32,88 @@ namespace openvpn {
#if defined(__GNUC__)
- inline int find_first_set(unsigned int v)
+ template
+ inline constexpr int n_bits_type()
+ {
+ return sizeof(T) * 8;
+ }
+
+ template
+ inline constexpr int n_bits_type(const T& v)
+ {
+ return sizeof(v) * 8;
+ }
+
+ inline int find_first_set(const unsigned int v)
{
if (!v)
return 0;
return __builtin_ffs(v);
}
- inline int find_last_set(unsigned int v)
+ inline int find_first_set(const int v)
+ {
+ return find_first_set(static_cast(v));
+ }
+
+ inline int find_last_set(const unsigned int v)
{
if (!v)
return 0;
- return 32 - __builtin_clz(v);
+ return n_bits_type(v) - __builtin_clz(v);
+ }
+
+ inline int find_last_set(const int v)
+ {
+ return find_last_set(static_cast(v));
+ }
+
+ inline int find_first_set(const unsigned long v)
+ {
+ if (!v)
+ return 0;
+ return __builtin_ffsl(v);
+ }
+
+ inline int find_first_set(const long v)
+ {
+ return find_first_set(static_cast(v));
+ }
+
+ inline int find_last_set(const unsigned long v)
+ {
+ if (!v)
+ return 0;
+ return n_bits_type(v) - __builtin_clzl(v);
+ }
+
+ inline int find_last_set(const long v)
+ {
+ return find_last_set(static_cast(v));
+ }
+
+ inline int find_first_set(const unsigned long long v)
+ {
+ if (!v)
+ return 0;
+ return __builtin_ffsll(v);
+ }
+
+ inline int find_first_set(const long long v)
+ {
+ return find_first_set(static_cast(v));
+ }
+
+ inline int find_last_set(const unsigned long long v)
+ {
+ if (!v)
+ return 0;
+ return n_bits_type(v) - __builtin_clzll(v);
+ }
+
+ inline int find_last_set(const long long v)
+ {
+ return find_last_set(static_cast(v));
}
#elif defined(_MSC_VER)
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp
index 2d22ec6..009bc35 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/fileatomic.hpp
@@ -30,7 +30,8 @@
#error atomic file methods not supported on Windows
#endif
-#include // for rename()
+#include // for rename()
+#include // for unlink()
#include
#include
@@ -63,6 +64,7 @@ namespace openvpn {
if (::rename(tfn.c_str(), fn.c_str()) == -1)
{
const int eno = errno;
+ ::unlink(tfn.c_str()); // move failed, so delete the temporary file
OPENVPN_THROW(file_unix_error, "error moving '" << tfn << "' -> '" << fn << "' : " << strerror_str(eno));
}
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/jsonlib.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/jsonlib.hpp
index a8eba12..193c9a5 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/jsonlib.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/jsonlib.hpp
@@ -26,5 +26,6 @@
#include "json/json.h" // JsonCpp library
#elif defined(HAVE_OPENVPN_COMMON)
#define HAVE_JSON
+#define OPENVPN_JSON_INTERNAL
#include // internal OpenVPN JSON implementation
#endif
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/modstat.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/modstat.hpp
index 609c449..f89a857 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/modstat.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/modstat.hpp
@@ -28,8 +28,12 @@
#include
+#include
+
namespace openvpn {
+#if defined(OPENVPN_PLATFORM_LINUX)
+
inline int update_file_mod_time_nanoseconds(const std::string& filename,
const std::uint64_t nanoseconds_since_epooch)
{
@@ -54,4 +58,20 @@ namespace openvpn {
return 0;
}
+#else
+
+ inline int update_file_mod_time_nanoseconds(const std::string& filename,
+ const std::uint64_t nanoseconds_since_epooch)
+ {
+ return 0;
+ }
+
+ inline int update_file_mod_time_nanoseconds(const int fd,
+ const std::uint64_t nanoseconds_since_epooch)
+ {
+ return 0;
+ }
+
+#endif
+
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/path.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/path.hpp
index e57c651..4d9d017 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/path.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/path.hpp
@@ -113,6 +113,56 @@ namespace openvpn {
return "";
}
+ // return true if path is a regular file that doesn't try to traverse via ".." or "/..."
+ inline bool is_contained(const std::string& path)
+ {
+ if (path.empty())
+ return false;
+ if (win_dev(path, false))
+ return false;
+ if (is_dirsep(path[0]))
+ return false;
+
+ // look for ".." in path
+ enum State {
+ SEP, // immediately after separator
+ MID, // middle of dir
+ DOT_2, // looking for second '.'
+ POST_DOT_2, // after ".."
+ };
+ State state = SEP;
+ for (const auto c : path)
+ {
+ switch (state)
+ {
+ case SEP:
+ if (c == '.')
+ state = DOT_2;
+ else if (!is_dirsep(c))
+ state = MID;
+ break;
+ case MID:
+ if (is_dirsep(c))
+ state = SEP;
+ break;
+ case DOT_2:
+ if (c == '.')
+ state = POST_DOT_2;
+ else if (is_dirsep(c))
+ state = SEP;
+ else
+ state = MID;
+ break;
+ case POST_DOT_2:
+ if (is_dirsep(c))
+ return false;
+ state = MID;
+ break;
+ }
+ }
+ return state != POST_DOT_2;
+ }
+
inline std::string ext(const std::string& basename)
{
const size_t pos = basename.find_last_of('.');
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp
index 1789427..5aa7131 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/runcontext.hpp
@@ -325,7 +325,8 @@ namespace openvpn {
cancel();
}
- void signal(const openvpn_io::error_code& error, int signum)
+ protected:
+ virtual void signal(const openvpn_io::error_code& error, int signum)
{
if (!error && !halt)
{
@@ -346,10 +347,14 @@ namespace openvpn {
signal_rearm();
break;
#endif
+ default:
+ signal_rearm();
+ break;
}
}
}
+ private:
void signal_rearm()
{
signals->register_signals_all([self=Ptr(this)](const openvpn_io::error_code& error, int signal_number)
@@ -392,7 +397,6 @@ namespace openvpn {
// servlist and related vars protected by mutex
std::vector servlist;
int thread_count = 0;
- volatile bool halt = false;
// stop
Stop* async_stop_ = nullptr;
@@ -404,6 +408,9 @@ namespace openvpn {
// logging
Log::Context log_context;
Log::Context::Wrapper log_wrap; // must be constructed after log_context
+
+ protected:
+ volatile bool halt = false;
};
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp
index 8807693..823cd77 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/string.hpp
@@ -296,7 +296,7 @@ namespace openvpn {
inline bool contains_non_space_ctrl(const std::string& str)
{
for (auto &c : str)
- if (!is_space(c) && is_ctrl(c))
+ if ((!is_space(c) && is_ctrl(c)) || c == 127)
return true;
return false;
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp
index 99720f8..e7dd107 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/version.hpp
@@ -24,5 +24,5 @@
#pragma once
#ifndef OPENVPN_VERSION
-#define OPENVPN_VERSION "3.git:master"
+#define OPENVPN_VERSION "3.2 (qa:d87f5bbc04)"
#endif
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/waitbarrier.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/waitbarrier.hpp
index 604f38e..182f977 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/waitbarrier.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/common/waitbarrier.hpp
@@ -26,9 +26,16 @@
#include
namespace openvpn {
+
+#ifdef HAVE_VALGRIND
+ static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 300;
+#else
+ static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 30;
+#endif
+
template
inline void event_loop_wait_barrier(THREAD_COMMON& tc,
- const unsigned int seconds=30)
+ const unsigned int seconds=WAIT_BARRIER_TIMEOUT)
{
// barrier prior to event-loop entry
switch (tc.event_loop_bar.wait(seconds))
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp
index d91e8b8..f95ab00 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt.hpp
@@ -89,11 +89,8 @@ namespace openvpn {
bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len)
{
- if (header_len < head_size + output_hmac_size())
- return false;
-
- hmac_pre(header, payload, payload_len);
- ctx_hmac.final(header + head_size);
+ hmac_pre(header, header_len, payload, payload_len);
+ ctx_hmac.final(header + header_len);
return true;
}
@@ -103,13 +100,10 @@ namespace openvpn {
{
unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE];
- if (header_len < head_size + output_hmac_size())
- return false;
-
- hmac_pre(header, payload, payload_len);
+ hmac_pre(header, header_len, payload, payload_len);
ctx_hmac.final(local_hmac);
- return !crypto::memneq(header + head_size, local_hmac, output_hmac_size());
+ return !crypto::memneq(header + header_len, local_hmac, output_hmac_size());
}
size_t encrypt(const unsigned char *iv, unsigned char *out, const size_t olen,
@@ -132,11 +126,11 @@ namespace openvpn {
private:
// assume length check on header has already been performed
- void hmac_pre(const unsigned char *header, const unsigned char *payload,
- const size_t payload_len)
+ void hmac_pre(const unsigned char *header, const size_t header_len,
+ const unsigned char *payload, const size_t payload_len)
{
ctx_hmac.reset();
- ctx_hmac.update(header, head_size);
+ ctx_hmac.update(header, header_len);
ctx_hmac.update(payload, payload_len);
}
@@ -159,19 +153,8 @@ namespace openvpn {
typename CRYPTO_API::HMACContext ctx_hmac;
typename CRYPTO_API::CipherContext ctx_crypt;
int mode;
-
- static const size_t head_size;
};
- // initialize static member with non-constexpr.
- // This is the size of the header in a TLSCrypt-wrapped packets,
- // excluding the HMAC. Format:
- //
- // [OP] [PSID] [PID] [HMAC] [...]
- //
- template
- const size_t TLSCrypt::head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
-
// OvpnHMAC wrapper API using dynamic polymorphism
class TLSCryptInstance : public RC
@@ -208,8 +191,19 @@ namespace openvpn {
virtual TLSCryptInstance::Ptr new_obj_send() = 0;
virtual TLSCryptInstance::Ptr new_obj_recv() = 0;
+
+ static const size_t hmac_offset;
};
+ // initialize static member with non-constexpr.
+ // This is the size of the header in a TLSCrypt-wrapped packets,
+ // excluding the HMAC. Format:
+ //
+ // [OP] [PSID] [PID] [HMAC] [...]
+ //
+ const size_t TLSCryptContext::hmac_offset = 1 + ProtoSessionID::SIZE +
+ PacketID::size(PacketID::LONG_FORM);
+
class TLSCryptFactory : public RC
{
public:
@@ -244,21 +238,6 @@ namespace openvpn {
return tls_crypt.output_hmac_size();
}
- void ovpn_hmac_reset()
- {
- tls_crypt.ovpn_hmac_reset();
- }
-
- void ovpn_hmac_update(const unsigned char *in, const size_t in_size)
- {
- tls_crypt.ovpn_hmac_update(in, in_size);
- }
-
- void ovpn_hmac_write(unsigned char *out)
- {
- tls_crypt.ovpn_hmac_write(out);
- }
-
bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len)
{
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp
new file mode 100644
index 0000000..41d5bb1
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/crypto/tls_crypt_v2.hpp
@@ -0,0 +1,198 @@
+// 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) 2017-2018 OpenVPN Technologies, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+// Classes for handling OpenVPN tls-crypt-v2 internals
+
+#ifndef OPENVPN_CRYPTO_TLS_CRYPT_V2_H
+#define OPENVPN_CRYPTO_TLS_CRYPT_V2_H
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace openvpn {
+ class TLSCryptV2ServerKey
+ {
+ public:
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_parse_error);
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_encode_error);
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_bad_size);
+
+ TLSCryptV2ServerKey()
+ : key_size(128),
+ key(key_size, BufferAllocated::DESTRUCT_ZERO)
+ {}
+
+ bool defined() const
+ {
+ return key.defined();
+ }
+
+ void parse(const std::string& key_text)
+ {
+ if (!SSLLib::PEMAPI::pem_decode(key, key_text.c_str(), key_text.length(),
+ tls_crypt_v2_server_key_name))
+ throw tls_crypt_v2_server_key_parse_error();
+
+ if (key.size() != key_size)
+ throw tls_crypt_v2_server_key_bad_size();
+ }
+
+ void extract_key(OpenVPNStaticKey& tls_key)
+ {
+ std::memcpy(tls_key.raw_alloc(), key.c_data(), key_size);
+ }
+
+ std::string render() const
+ {
+ BufferAllocated data(32 + 2 * key.size(), 0);
+
+ if (!SSLLib::PEMAPI::pem_encode(data, key.c_data(), key.size(),
+ tls_crypt_v2_server_key_name))
+ throw tls_crypt_v2_server_key_encode_error();
+
+ return std::string((const char *)data.c_data());
+ }
+
+ private:
+ const size_t key_size;
+ BufferAllocated key;
+ static const std::string tls_crypt_v2_server_key_name;
+ };
+
+ const std::string TLSCryptV2ServerKey::tls_crypt_v2_server_key_name = "OpenVPN tls-crypt-v2 server key";
+
+ class TLSCryptV2ClientKey
+ {
+ public:
+ enum {
+ WKC_MAX_SIZE = 1024, // bytes
+ };
+
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_parse_error);
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_encode_error);
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_bad_size);
+
+ TLSCryptV2ClientKey() = delete;
+
+ TLSCryptV2ClientKey(TLSCryptContext::Ptr context)
+ : key_size(OpenVPNStaticKey::KEY_SIZE),
+ tag_size(context->digest_size())
+ {}
+
+ bool defined() const
+ {
+ return key.defined() && wkc.defined();
+ }
+
+ void parse(const std::string& key_text)
+ {
+ BufferAllocated data(key_size + WKC_MAX_SIZE, BufferAllocated::DESTRUCT_ZERO);
+
+ if (!SSLLib::PEMAPI::pem_decode(data, key_text.c_str(), key_text.length(),
+ tls_crypt_v2_client_key_name))
+ throw tls_crypt_v2_client_key_parse_error();
+
+ if (data.size() < (tag_size + key_size))
+ throw tls_crypt_v2_client_key_bad_size();
+
+ key.init(data.data(), key_size, BufferAllocated::DESTRUCT_ZERO);
+ wkc.init(data.data() + key_size, data.size() - key_size, BufferAllocated::DESTRUCT_ZERO);
+ }
+
+ void extract_key(OpenVPNStaticKey& tls_key)
+ {
+ std::memcpy(tls_key.raw_alloc(), key.c_data(), key_size);
+ }
+
+ std::string render() const
+ {
+ BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0);
+ BufferAllocated in(key, BufferAllocated::GROW);
+ in.append(wkc);
+
+ if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), tls_crypt_v2_client_key_name))
+ throw tls_crypt_v2_client_key_encode_error();
+
+ return std::string((const char *)data.c_data());
+ }
+
+ void extract_wkc(BufferAllocated& wkc_out) const
+ {
+ wkc_out = wkc;
+ }
+
+ private:
+ BufferAllocated key;
+ BufferAllocated wkc;
+
+ const size_t key_size;
+ const size_t tag_size;
+
+ static const std::string tls_crypt_v2_client_key_name;
+ };
+
+ const std::string TLSCryptV2ClientKey::tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key";
+
+ // the user can extend the TLSCryptMetadata and the TLSCryptMetadataFactory
+ // classes to implement its own metadata verification method.
+ //
+ // default method is to *ignore* the metadata contained in the WKc sent by the client
+ class TLSCryptMetadata : public RC
+ {
+ public:
+ typedef RCPtr Ptr;
+
+ // override this method with your own verification mechanism.
+ //
+ // If type is -1 it means that metadata is empty.
+ //
+ virtual bool verify(int type, Buffer& metadata) const
+ {
+ return true;
+ }
+ };
+
+ // abstract class to be extended when creating other factories
+ class TLSCryptMetadataFactory : public RC
+ {
+ public:
+ typedef RCPtr Ptr;
+
+ virtual TLSCryptMetadata::Ptr new_obj() = 0;
+ };
+
+ // factory implementation for the basic verification method
+ class CryptoTLSCryptMetadataFactory : public TLSCryptMetadataFactory
+ {
+ public:
+ TLSCryptMetadata::Ptr new_obj()
+ {
+ return new TLSCryptMetadata();
+ }
+ };
+}
+
+#endif /* OPENVPN_CRYPTO_TLS_CRYPT_V2_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp
index 37843e9..33eaace 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/dco/dcocli.hpp
@@ -117,7 +117,8 @@ namespace openvpn {
class Client : public TransportClient,
public TunClient,
public KoRekey::Receiver,
- public SessionStats::DCOTransportSource
+ public SessionStats::DCOTransportSource,
+ public AsyncResolvableUDP
{
friend class ClientConfig;
@@ -473,7 +474,8 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg,
TransportClientParent* parent_arg)
- : io_context(io_context_arg),
+ : AsyncResolvableUDP(io_context_arg),
+ io_context(io_context_arg),
halt(false),
state(new TunProp::State()),
config(config_arg),
@@ -498,17 +500,13 @@ namespace openvpn {
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);
- });
+ async_resolve_name(server_host, server_port);
}
}
// 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)
+ void resolve_callback(const openvpn_io::error_code& error,
+ openvpn_io::ip::udp::resolver::results_type results)
{
if (!halt)
{
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp
index 740dba8..9ebd9c1 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/error/error.hpp
@@ -70,6 +70,7 @@ namespace openvpn {
PRIMARY_EXPIRE, // primary key context expired
TLS_VERSION_MIN, // peer cannot handshake at our minimum required TLS version
TLS_AUTH_FAIL, // tls-auth HMAC verification failed
+ TLS_CRYPT_META_FAIL, // tls-crypt-v2 metadata verification failed
CERT_VERIFY_FAIL, // peer certificate verification failure
PEM_PASSWORD_FAIL, // incorrect or missing PEM private key decryption password
AUTH_FAILED, // general authentication failure
@@ -145,6 +146,7 @@ namespace openvpn {
"PRIMARY_EXPIRE",
"TLS_VERSION_MIN",
"TLS_AUTH_FAIL",
+ "TLS_CRYPT_META_FAIL",
"CERT_VERIFY_FAIL",
"PEM_PASSWORD_FAIL",
"AUTH_FAILED",
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/http/reply.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/http/reply.hpp
index 6f3c058..9c303af 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/http/reply.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/http/reply.hpp
@@ -93,7 +93,6 @@ namespace openvpn {
public:
enum status {
- undefined,
pending,
fail,
success,
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/init/initprocess.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/init/initprocess.hpp
index 8e18fc2..05c5b2a 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/init/initprocess.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/init/initprocess.hpp
@@ -59,10 +59,6 @@ namespace openvpn {
{
base64_uninit_static();
}
-
- private:
- // initialize SSL library
- crypto_init crypto_init_;
};
// process-wide singular instance
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/csum.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/csum.hpp
new file mode 100644
index 0000000..87b64c3
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/csum.hpp
@@ -0,0 +1,171 @@
+// 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 .
+
+// IP checksum based on Linux kernel implementation
+
+#pragma once
+
+#include
+
+#include
+#include
+#include
+
+namespace openvpn {
+ namespace IPChecksum {
+
+ inline std::uint16_t fold(std::uint32_t sum)
+ {
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ return sum;
+ }
+
+ inline std::uint16_t cfold(const std::uint32_t sum)
+ {
+ return ~fold(sum);
+ }
+
+ inline std::uint32_t unfold(const std::uint16_t sum)
+ {
+ return sum;
+ }
+
+ inline std::uint32_t cunfold(const std::uint16_t sum)
+ {
+ return ~unfold(sum);
+ }
+
+ inline std::uint32_t compute(const std::uint8_t *buf, size_t len)
+ {
+ std::uint32_t result = 0;
+
+ if (!len)
+ return 0;
+
+ const bool odd = size_t(buf) & 1;
+ if (odd)
+ {
+#ifdef OPENVPN_LITTLE_ENDIAN
+ result += (*buf << 8);
+#else
+ result = *buf;
+#endif
+ len--;
+ buf++;
+ }
+
+ if (len >= 2)
+ {
+ if (size_t(buf) & 2)
+ {
+ result += *(std::uint16_t *)buf;
+ len -= 2;
+ buf += 2;
+ }
+ if (len >= 4)
+ {
+ const uint8_t *end = buf + (len & ~3);
+ std::uint32_t carry = 0;
+ do {
+ std::uint32_t w = *(std::uint32_t *)buf;
+ buf += 4;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (buf < end);
+ result += carry;
+ result = (result & 0xffff) + (result >> 16);
+ }
+ if (len & 2)
+ {
+ result += *(std::uint16_t *)buf;
+ buf += 2;
+ }
+ }
+ if (len & 1)
+ {
+#ifdef OPENVPN_LITTLE_ENDIAN
+ result += *buf;
+#else
+ result += (*buf << 8);
+#endif
+ }
+ result = fold(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+ return result;
+ }
+
+ inline std::uint32_t compute(const void *buf, const size_t len)
+ {
+ return compute((const std::uint8_t *)buf, len);
+ }
+
+ inline std::uint32_t partial(const void *buf, const size_t len, const std::uint32_t sum)
+ {
+ std::uint32_t result = compute(buf, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ if (sum > result)
+ result += 1;
+ return result;
+ }
+
+ inline std::uint32_t diff16(const std::uint32_t *old,
+ const std::uint32_t *new_,
+ const std::uint32_t oldsum)
+ {
+ std::uint32_t diff[8] = { ~old[0], ~old[1], ~old[2], ~old[3],
+ new_[0], new_[1], new_[2], new_[3] };
+ return partial(diff, sizeof(diff), oldsum);
+ }
+
+ inline std::uint32_t diff16(const std::uint8_t *old,
+ const std::uint8_t *new_,
+ const std::uint32_t oldsum)
+ {
+ return diff16((const std::uint32_t *)old, (const std::uint32_t *)new_, oldsum);
+ }
+
+ inline std::uint32_t diff4(const std::uint32_t old,
+ const std::uint32_t new_,
+ const std::uint32_t oldsum)
+ {
+ std::uint32_t diff[2] = { ~old, new_ };
+ return partial(diff, sizeof(diff), oldsum);
+ }
+
+ inline std::uint32_t diff2(const std::uint16_t old,
+ const std::uint16_t new_,
+ const std::uint32_t oldsum)
+ {
+ std::uint16_t diff[2] = { std::uint16_t(~old), new_ };
+ return partial(diff, sizeof(diff), oldsum);
+ }
+
+ inline std::uint16_t checksum(const void *data, const size_t size)
+ {
+ return cfold(compute(data, size));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp
index d08c028..2d20ade 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp4.hpp
@@ -33,8 +33,11 @@
namespace openvpn {
struct ICMPv4 {
enum {
- ECHO_REQUEST = 8,
- ECHO_REPLY = 0,
+ ECHO_REQUEST = 8,
+ ECHO_REPLY = 0,
+ DEST_UNREACH = 3,
+ FRAG_NEEDED = 4,
+ MIN_DATA_SIZE = 8
};
struct IPv4Header head;
@@ -53,6 +56,10 @@ namespace openvpn {
std::uint16_t id;
std::uint16_t seq_num;
};
+ struct {
+ std::uint16_t unused;
+ std::uint16_t nexthop_mtu;
+ };
};
};
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp
index c23e03e..2813004 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/icmp6.hpp
@@ -34,8 +34,9 @@ namespace openvpn {
struct ICMPv6 {
enum {
- ECHO_REQUEST = 128,
- ECHO_REPLY = 129,
+ ECHO_REQUEST = 128,
+ ECHO_REPLY = 129,
+ PACKET_TOO_BIG = 2
};
struct IPv6Header head;
@@ -54,6 +55,7 @@ namespace openvpn {
std::uint16_t id;
std::uint16_t seq_num;
};
+ std::uint32_t mtu;
};
};
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp
index 34afe6c..5e52e30 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ipcommon.hpp
@@ -36,6 +36,11 @@ namespace openvpn {
UDP = 17, /* UDP protocol */
};
+ enum {
+ IPv4 = 4,
+ IPv6 = 6
+ };
+
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/ping4.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ping4.hpp
new file mode 100644
index 0000000..50eaaff
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ping4.hpp
@@ -0,0 +1,113 @@
+// 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
+#include
+#include
+#include
+
+namespace openvpn {
+ namespace Ping4 {
+
+ inline void generate_echo_request(Buffer& buf,
+ const IPv4::Addr& src,
+ const IPv4::Addr& dest,
+ const void *extra_data,
+ const size_t extra_data_size,
+ const unsigned int id,
+ const unsigned int seq_num,
+ const size_t total_size,
+ std::string* log_info)
+ {
+ const unsigned int data_size = std::max(int(extra_data_size), int(total_size) - int(sizeof(ICMPv4)));
+
+ if (log_info)
+ *log_info = "PING4 " + src.to_string() + " -> " + dest.to_string() + " id=" + std::to_string(id) + " seq_num=" + std::to_string(seq_num) + " data_size=" + std::to_string(data_size);
+
+ std::uint8_t *b = buf.write_alloc(sizeof(ICMPv4) + data_size);
+ ICMPv4 *icmp = (ICMPv4 *)b;
+
+ // IP Header
+ icmp->head.version_len = IPv4Header::ver_len(4, sizeof(IPv4Header));
+ icmp->head.tos = 0;
+ icmp->head.tot_len = htons(sizeof(ICMPv4) + data_size);
+ icmp->head.id = 0;
+ icmp->head.frag_off = 0;
+ icmp->head.ttl = 64;
+ icmp->head.protocol = IPCommon::ICMPv4;
+ icmp->head.check = 0;
+ icmp->head.saddr = src.to_uint32_net();
+ icmp->head.daddr = dest.to_uint32_net();
+ icmp->head.check = IPChecksum::checksum(b, sizeof(IPv4Header));
+
+ // ICMP header
+ icmp->type = ICMPv4::ECHO_REQUEST;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->id = ntohs(id);
+ icmp->seq_num = ntohs(seq_num);
+
+ // Data
+ std::uint8_t *data = b + sizeof(ICMPv4);
+ for (size_t i = 0; i < data_size; ++i)
+ data[i] = (std::uint8_t)i;
+
+ // Extra data
+ std::memcpy(data, extra_data, extra_data_size);
+
+ // ICMP checksum
+ icmp->checksum = IPChecksum::checksum(b + sizeof(IPv4Header),
+ sizeof(ICMPv4) - sizeof(IPv4Header) + data_size);
+
+ //std::cout << dump_hex(buf);
+ }
+
+ // assumes that buf is a validated ECHO_REQUEST
+ inline void generate_echo_reply(Buffer& buf,
+ std::string* log_info)
+ {
+ if (buf.size() < sizeof(ICMPv4))
+ {
+ if (log_info)
+ *log_info = "Invalid ECHO4_REQUEST";
+ return;
+ }
+
+ ICMPv4* icmp = (ICMPv4*) buf.c_data();
+ std::swap(icmp->head.saddr, icmp->head.daddr);
+ const std::uint16_t old_type_code = icmp->type_code;
+ icmp->type = ICMPv4::ECHO_REPLY;
+ icmp->checksum = IPChecksum::cfold(IPChecksum::diff2(old_type_code, icmp->type_code, IPChecksum::cunfold(icmp->checksum)));
+
+ if (log_info)
+ *log_info = "ECHO4_REPLY size=" + std::to_string(buf.size()) + ' ' + IPv4::Addr::from_uint32_net(icmp->head.saddr).to_string() + " -> " + IPv4::Addr::from_uint32_net(icmp->head.daddr).to_string();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ping6.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ping6.hpp
new file mode 100644
index 0000000..19933ee
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ping6.hpp
@@ -0,0 +1,171 @@
+// 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
+#include
+#include
+#include
+
+namespace openvpn {
+ namespace Ping6 {
+
+ inline static const std::uint16_t* get_addr16(const struct in6_addr *addr)
+ {
+#if defined(_MSC_VER)
+ return addr->u.Word;
+#elif defined(__APPLE__)
+ return addr->__u6_addr.__u6_addr16;
+#else
+ return addr->s6_addr16;
+#endif
+ }
+
+ inline std::uint16_t csum_ipv6_pseudo(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ const std::uint32_t len,
+ const std::uint16_t proto,
+ std::uint32_t sum)
+ {
+ int carry = 0;
+ std::uint32_t val = 0;
+
+ const std::uint16_t* addr = get_addr16(saddr);
+ for (int i = 0; i < 4; ++i)
+ {
+ val = (std::uint32_t)(addr[i * 2] << 16) + addr[i * 2 + 1];
+ sum += val;
+ carry = (sum < val);
+ sum += carry;
+ }
+
+ addr = get_addr16(daddr);
+ for (int i = 0; i < 4; ++i)
+ {
+ val = (std::uint32_t)(addr[i * 2] << 16) + addr[i * 2 + 1];
+ sum += val;
+ carry = (sum < val);
+ sum += carry;
+ }
+
+ const std::uint32_t ulen = (std::uint32_t)htonl((std::uint32_t) len);
+ sum += ulen;
+ carry = (sum < ulen);
+ sum += carry;
+
+ const std::uint32_t uproto = (std::uint32_t)htonl(proto);
+ sum += uproto;
+ carry = (sum < uproto);
+ sum += carry;
+
+ return IPChecksum::cfold(sum);
+ }
+
+ // len must be >= sizeof(ICMPv6)
+ inline std::uint16_t csum_icmp(const ICMPv6 *icmp, const size_t len)
+ {
+ return csum_ipv6_pseudo(&icmp->head.saddr,
+ &icmp->head.daddr,
+ len - sizeof(IPv6Header),
+ IPCommon::ICMPv6,
+ IPChecksum::compute((std::uint8_t *)icmp + sizeof(IPv6Header), len - sizeof(IPv6Header)));
+ }
+
+ inline void generate_echo_request(Buffer& buf,
+ const IPv6::Addr& src,
+ const IPv6::Addr& dest,
+ const void *extra_data,
+ const size_t extra_data_size,
+ const unsigned int id,
+ const unsigned int seq_num,
+ const size_t total_size,
+ std::string* log_info)
+ {
+ const unsigned int data_size = std::max(int(extra_data_size), int(total_size) - int(sizeof(ICMPv6)));
+
+ if (log_info)
+ *log_info = "PING6 " + src.to_string() + " -> " + dest.to_string() + " id=" + std::to_string(id) + " seq_num=" + std::to_string(seq_num) + " data_size=" + std::to_string(data_size);
+
+ std::uint8_t *b = buf.write_alloc(sizeof(ICMPv6) + data_size);
+ ICMPv6 *icmp = (ICMPv6 *)b;
+
+ // IP Header
+ icmp->head.version_prio = (6 << 4);
+ icmp->head.flow_lbl[0] = 0;
+ icmp->head.flow_lbl[1] = 0;
+ icmp->head.flow_lbl[2] = 0;
+ icmp->head.payload_len = htons(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size);
+ icmp->head.nexthdr = IPCommon::ICMPv6;
+ icmp->head.hop_limit = 64;
+ icmp->head.saddr = src.to_in6_addr();
+ icmp->head.daddr = dest.to_in6_addr();
+
+ // ICMP header
+ icmp->type = ICMPv6::ECHO_REQUEST;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->id = ntohs(id);
+ icmp->seq_num = ntohs(seq_num);
+
+ // Data
+ std::uint8_t *data = b + sizeof(ICMPv6);
+ for (size_t i = 0; i < data_size; ++i)
+ data[i] = (std::uint8_t)i;
+
+ // Extra data
+ std::memcpy(data, extra_data, extra_data_size);
+
+ // ICMP checksum
+ icmp->checksum = csum_icmp(icmp, sizeof(ICMPv6) + data_size);
+
+ //std::cout << dump_hex(buf);
+ }
+
+ // assumes that buf is a validated ECHO_REQUEST
+ inline void generate_echo_reply(Buffer& buf,
+ std::string* log_info)
+ {
+ if (buf.size() < sizeof(ICMPv6))
+ {
+ if (log_info)
+ *log_info = "Invalid ECHO6_REQUEST";
+ return;
+ }
+
+ ICMPv6* icmp = (ICMPv6*) buf.c_data();
+ std::swap(icmp->head.saddr, icmp->head.daddr);
+ const std::uint16_t old_type_code = icmp->type_code;
+ icmp->type = ICMPv6::ECHO_REPLY;
+ icmp->checksum = IPChecksum::cfold(IPChecksum::diff2(old_type_code, icmp->type_code, IPChecksum::cunfold(icmp->checksum)));
+
+ if (log_info)
+ *log_info = "ECHO6_REPLY size=" + std::to_string(buf.size()) + ' ' + IPv6::Addr::from_in6_addr(&icmp->head.saddr).to_string() + " -> " + IPv6::Addr::from_in6_addr(&icmp->head.daddr).to_string();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ptb.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ptb.hpp
new file mode 100644
index 0000000..1d73d28
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/ptb.hpp
@@ -0,0 +1,136 @@
+// 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 .
+
+// Generates ICMP "packet too big" response
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace openvpn {
+ class Ptb {
+ public:
+ static void generate_icmp_ptb(BufferAllocated& buf, std::uint16_t nexthop_mtu)
+ {
+ if (buf.empty())
+ return;
+
+ switch (IPCommon::version(buf[0]))
+ {
+ case IPCommon::IPv4:
+ if (buf.length() <= sizeof(struct IPv4Header))
+ break;
+
+ generate_icmp4_ptb(buf, nexthop_mtu);
+ break;
+
+ case IPCommon::IPv6:
+ if (buf.length() <= sizeof(struct IPv6Header))
+ break;
+
+ generate_icmp6_ptb(buf, nexthop_mtu);
+ break;
+ }
+ }
+
+ private:
+ static void generate_icmp6_ptb(BufferAllocated& buf, std::uint16_t nexthop_mtu)
+ {
+ // ICMPv6 data includes original IPv6 header and as many bytes of payload as possible
+ int data_size = std::min(buf.length(), (size_t)(nexthop_mtu - sizeof(ICMPv6)));
+
+ // sanity check
+ // we use headroom for adding IPv6 + ICMPv6 headers
+ if ((buf.offset() < sizeof(ICMPv6)) || (buf.capacity() < (sizeof(ICMPv6) + data_size)))
+ return;
+
+ IPv6Header* ipv6 = (IPv6Header*)buf.c_data();
+
+ uint8_t *b = buf.prepend_alloc(sizeof(ICMPv6));
+ ICMPv6 *icmp = (ICMPv6 *)b;
+
+ // IPv6 header
+ icmp->head.version_prio = (6 << 4);
+ icmp->head.flow_lbl[0] = 0;
+ icmp->head.flow_lbl[1] = 0;
+ icmp->head.flow_lbl[2] = 0;
+ icmp->head.payload_len = htons(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size);
+ icmp->head.nexthdr = IPCommon::ICMPv6;
+ icmp->head.hop_limit = 64;
+ icmp->head.saddr = ipv6->daddr;
+ icmp->head.daddr = ipv6->saddr;
+
+ // ICMP header
+ icmp->type = ICMPv6::PACKET_TOO_BIG;
+ icmp->code = 0;
+ icmp->mtu = htonl(nexthop_mtu);
+ icmp->checksum = 0;
+ icmp->checksum = Ping6::csum_icmp(icmp, sizeof(ICMPv6) + data_size);
+
+ buf.set_size(sizeof(ICMPv6) + data_size);
+ }
+
+ static void generate_icmp4_ptb(BufferAllocated& buf, std::uint16_t nexthop_mtu)
+ {
+ // ICMP data includes original IP header and first 8 bytes of payload
+ int data_size = sizeof(IPv4Header) + ICMPv4::MIN_DATA_SIZE;
+
+ // sanity check
+ // we use headroom for adding IPv4 + ICMPv4 headers
+ if ((buf.offset() < sizeof(ICMPv4)) || (buf.capacity() < (sizeof(ICMPv4) + data_size)))
+ return;
+
+ IPv4Header* ipv4 = (IPv4Header*)buf.c_data();
+
+ uint8_t *b = buf.prepend_alloc(sizeof(ICMPv4));
+ ICMPv4 *icmp = (ICMPv4 *)b;
+
+ icmp->head.saddr = ipv4->daddr;
+ icmp->head.daddr = ipv4->saddr;
+ icmp->head.version_len = IPv4Header::ver_len(IPCommon::IPv4, sizeof(IPv4Header));
+ icmp->head.tos = 0;
+ icmp->head.tot_len = htons(sizeof(ICMPv4) + data_size);
+ icmp->head.id = 0;
+ icmp->head.frag_off = 0;
+ icmp->head.ttl = 64;
+ icmp->head.protocol = IPCommon::ICMPv4;
+ icmp->head.check = 0;
+ icmp->head.check = IPChecksum::checksum(b, sizeof(IPv4Header));
+
+ icmp->type = ICMPv4::DEST_UNREACH;
+ icmp->code = ICMPv4::FRAG_NEEDED;
+ icmp->unused = 0;
+ icmp->nexthop_mtu = htons(nexthop_mtu);
+ icmp->checksum = 0;
+ icmp->checksum = IPChecksum::checksum(b + sizeof(IPv4Header), sizeof(ICMPv4) - sizeof(IPv4Header) + data_size);
+
+ buf.set_size(sizeof(ICMPv4) + data_size);
+ }
+ };
+}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/tcp.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/tcp.hpp
new file mode 100644
index 0000000..04cf3fd
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ip/tcp.hpp
@@ -0,0 +1,90 @@
+// 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
+
+namespace openvpn {
+
+#pragma pack(push)
+#pragma pack(1)
+
+ struct TCPHeader {
+ static unsigned int length(const std::uint8_t doff_res)
+ {
+ return ((doff_res) & 0xF0) >> 2;
+ }
+
+ std::uint16_t source;
+ std::uint16_t dest;
+ std::uint32_t seq;
+ std::uint32_t ack_seq;
+ std::uint8_t doff_res;
+ std::uint8_t flags;
+ std::uint16_t window;
+ std::uint16_t check;
+ std::uint16_t urgent_p;
+
+ // helper enum to parse options in TCP header
+ enum {
+ OPT_EOL = 0,
+ OPT_NOP = 1,
+ OPT_MAXSEG = 2,
+ OPTLEN_MAXSEG = 4
+ };
+
+ enum {
+ FLAG_SYN = 1 << 1
+ };
+ };
+
+#pragma pack(pop)
+
+ /*
+ * The following routine is used to update an
+ * internet checksum. "acc" is a 32-bit
+ * accumulation of all the changes to the
+ * checksum (adding in old 16-bit words and
+ * subtracting out new words), and "cksum"
+ * is the checksum value to be updated.
+ */
+ inline void tcp_adjust_checksum(int acc, std::uint16_t& cksum)
+ {
+ int _acc = acc;
+ _acc += cksum;
+ if (_acc < 0)
+ {
+ _acc = -_acc;
+ _acc = (_acc >> 16) + (_acc & 0xffff);
+ _acc += _acc >> 16;
+ cksum = (uint16_t)~_acc;
+ }
+ else
+ {
+ _acc = (_acc >> 16) + (_acc & 0xffff);
+ _acc += _acc >> 16;
+ cksum = (uint16_t)_acc;
+ }
+ }
+}
+
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp
index d043770..8640981 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/ssl/sslctx.hpp
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#include
#include
@@ -826,8 +827,15 @@ namespace openvpn {
// set our own certificate, supporting chain (i.e. extra-certs), and external private key
if (c.crt_chain)
{
- epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len);
- mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get());
+ if (mbedtls_pk_get_type(&c.crt_chain.get()->get()->pk) == MBEDTLS_PK_RSA)
+ {
+ epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len);
+ mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get());
+ }
+ else
+ {
+ throw MbedTLSException("cert has unsupported type for external pki support");
+ }
}
else
throw MbedTLSException("cert is undefined");
@@ -1217,7 +1225,20 @@ namespace openvpn {
{
const int SHA_DIGEST_LEN = 20;
static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LEN, "size inconsistency");
+#if MBEDTLS_VERSION_NUMBER < 0x02070000
+ // mbed TLS 2.7.0 and newer deprecates mbedtls_sha1()
+ // in favour of mbedtls_sha1_ret().
+
+ // We support for older mbed TLS versions
+ // to be able to build on Debian 9 and Ubuntu 16.
mbedtls_sha1(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp);
+#else
+ if(mbedtls_sha1_ret(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp))
+ {
+ OPENVPN_LOG_SSL("VERIFY FAIL -- SHA1 calculation failed.");
+ fail = true;
+ }
+#endif
}
}
else if (depth == 0) // leaf-cert
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp
new file mode 100644
index 0000000..e0524e6
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/mbedtls/util/pem.hpp
@@ -0,0 +1,77 @@
+// 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) 2017-2018 OpenVPN Technologies, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+// Wrap the mbedTLS PEM API defined in so
+// that it can be used as part of the crypto layer of the OpenVPN core.
+
+#ifndef OPENVPN_MBEDTLS_UTIL_PEM_H
+#define OPENVPN_MBEDTLS_UTIL_PEM_H
+
+#include
+
+namespace openvpn {
+ class MbedTLSPEM
+ {
+ public:
+ static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
+ size_t src_len, const std::string& key_name)
+ {
+ std::string header = "-----BEGIN " + key_name + "-----\n";
+ std::string footer = "-----END " + key_name + "-----\n";
+ size_t out_len = 0;
+
+ int ret = mbedtls_pem_write_buffer(header.c_str(), footer.c_str(),
+ src, src_len, dst.data(),
+ dst.max_size(), &out_len);
+ if (ret == 0)
+ dst.set_size(out_len);
+ else
+ {
+ char buf[128];
+ mbedtls_strerror(ret, buf, 128);
+ OPENVPN_LOG("mbedtls_pem_write_buffer error: " << buf);
+ }
+
+ return (ret == 0);
+ }
+
+ static bool pem_decode(BufferAllocated& dst, const char *src,
+ size_t src_len, const std::string& key_name)
+ {
+ std::string header = "-----BEGIN " + key_name + "-----";
+ std::string footer = "-----END " + key_name + "-----";
+ mbedtls_pem_context ctx = { 0 };
+ size_t out_len = 0;
+
+ int ret = mbedtls_pem_read_buffer(&ctx, header.c_str(), footer.c_str(),
+ (unsigned char *)src, nullptr, 0,
+ &out_len);
+ if (ret == 0)
+ dst.init(ctx.buf, ctx.buflen, BufferAllocated::DESTRUCT_ZERO);
+
+ mbedtls_pem_free(&ctx);
+
+ return (ret == 0);
+ }
+ };
+};
+
+#endif /* OPENVPN_MBEDTLS_UTIL_PEM_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/netconf/linux/gwnetlink.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/netconf/linux/gwnetlink.hpp
new file mode 100644
index 0000000..7af5f30
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/netconf/linux/gwnetlink.hpp
@@ -0,0 +1,141 @@
+// 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 .
+
+// Find default gateways on Linux using ip route command
+
+#pragma once
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+namespace openvpn {
+ class LinuxGWNetlink
+ {
+ public:
+ OPENVPN_EXCEPTION(linux_gw_netlink_error);
+
+ LinuxGWNetlink(bool ipv6)
+ {
+ try
+ {
+ if (ipv6)
+ {
+ IPv6::Addr addr6;
+
+ if (TunNetlink::SITNL::net_route_best_gw(IP::Route6(IPv6::Addr::from_zero(), 0),
+ addr6, dev_) < 0)
+ {
+ OPENVPN_THROW(linux_gw_netlink_error,
+ "error retrieving default IPv6 GW");
+ }
+
+ addr_ = IP::Addr::from_ipv6(addr6);
+ }
+ else
+ {
+ IPv4::Addr addr4;
+
+ if (TunNetlink::SITNL::net_route_best_gw(IP::Route4(IPv4::Addr::from_zero(), 0),
+ addr4, dev_) < 0)
+ {
+ OPENVPN_THROW(linux_gw_netlink_error,
+ "error retrieving default IPv4 GW");
+ }
+
+ addr_ = IP::Addr::from_ipv4(addr4);
+ }
+ } catch (...)
+ {
+ /* nothing to do. just leave default GW unassigned */
+ }
+ }
+
+ const std::string& dev() const
+ {
+ return dev_;
+ }
+
+ const IP::Addr& addr() const
+ {
+ return addr_;
+ }
+
+ bool defined() const
+ {
+ return !dev_.empty() && addr_.defined();
+ }
+
+ std::string to_string() const
+ {
+ return dev_ + '/' + addr_.to_string();
+ }
+
+ private:
+ IP::Addr addr_;
+ std::string dev_;
+ };
+
+ struct LinuxGW46Netlink
+ {
+ LinuxGW46Netlink()
+ : v4(false),
+ v6(true)
+ {
+ }
+
+ std::string to_string() const
+ {
+ std::string ret = "[";
+ if (v4.defined())
+ {
+ ret += "4:";
+ ret += v4.to_string();
+ }
+ if (v6.defined())
+ {
+ if (v4.defined())
+ ret += ' ';
+ ret += "6:";
+ ret += v6.to_string();
+ }
+ ret += "]";
+ return ret;
+ }
+
+ std::string dev() const
+ {
+ if (v4.defined())
+ return v4.dev();
+ else if (v6.defined())
+ return v6.dev();
+ else
+ throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface");
+ }
+
+ LinuxGWNetlink v4;
+ LinuxGWNetlink v6;
+ };
+}
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 540482f..678f331 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/ssl/sslctx.hpp
@@ -520,6 +520,8 @@ namespace openvpn {
static void init_static()
{
+ SSL_library_init();
+
mydata_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr);
// We actually override some of the OpenSSL SSLv23 methods here,
@@ -867,7 +869,7 @@ namespace openvpn {
try
{
// Create new SSL_CTX for server or client mode
- const bool ssl23 = (config->force_aes_cbc_ciphersuites || (config->tls_version_min > TLSVersion::UNDEF));
+ const bool ssl23 = (!config->force_aes_cbc_ciphersuites || (config->tls_version_min > TLSVersion::UNDEF));
if (config->mode.is_server())
{
ctx = SSL_CTX_new(ssl23 ? SSL::ssl23_method_server() : TLSv1_server_method());
@@ -910,20 +912,17 @@ namespace openvpn {
if (ssl23)
{
sslopt |= SSL_OP_NO_SSLv2;
- if (!config->force_aes_cbc_ciphersuites || config->tls_version_min > TLSVersion::UNDEF)
- {
- sslopt |= SSL_OP_NO_SSLv3;
- if (config->tls_version_min > TLSVersion::V1_0)
- sslopt |= SSL_OP_NO_TLSv1;
-# ifdef SSL_OP_NO_TLSv1_1
- if (config->tls_version_min > TLSVersion::V1_1)
- sslopt |= SSL_OP_NO_TLSv1_1;
-# endif
-# ifdef SSL_OP_NO_TLSv1_2
- if (config->tls_version_min > TLSVersion::V1_2)
- sslopt |= SSL_OP_NO_TLSv1_2;
-# endif
- }
+ sslopt |= SSL_OP_NO_SSLv3;
+ if (config->tls_version_min > TLSVersion::V1_0)
+ sslopt |= SSL_OP_NO_TLSv1;
+# ifdef SSL_OP_NO_TLSv1_1
+ if (config->tls_version_min > TLSVersion::V1_1)
+ sslopt |= SSL_OP_NO_TLSv1_1;
+# endif
+# ifdef SSL_OP_NO_TLSv1_2
+ if (config->tls_version_min > TLSVersion::V1_2)
+ sslopt |= SSL_OP_NO_TLSv1_2;
+# endif
}
SSL_CTX_set_options(ctx, sslopt);
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/pem.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/pem.hpp
new file mode 100644
index 0000000..a3ea1cb
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/openssl/util/pem.hpp
@@ -0,0 +1,103 @@
+// 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) 2017-2018 OpenVPN Technologies, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program in the COPYING file.
+// If not, see .
+
+// Wrap the OpenSSL PEM API defined in so
+// that it can be used as part of the crypto layer of the OpenVPN core.
+
+#ifndef OPENVPN_OPENSSL_UTIL_PEM_H
+#define OPENVPN_OPENSSL_UTIL_PEM_H
+
+#include
+
+#include
+
+namespace openvpn {
+ class OpenSSLPEM
+ {
+ public:
+ static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
+ size_t src_len, const std::string& key_name)
+ {
+ bool ret = false;
+ BIO *bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ return false;
+
+ if (!PEM_write_bio(bio, key_name.c_str(), "", src, src_len))
+ goto out;
+
+ BUF_MEM *bptr;
+ BIO_get_mem_ptr(bio, &bptr);
+ dst.write((unsigned char *)bptr->data, bptr->length);
+
+ ret = true;
+
+out:
+ if (!BIO_free(bio))
+ ret = false;
+
+ return ret;
+ }
+
+ static bool pem_decode(BufferAllocated& dst, const char *src,
+ size_t src_len, const std::string& key_name)
+ {
+ bool ret = false;
+ BIO *bio;
+
+ if (!(bio = BIO_new_mem_buf(src, src_len)))
+ throw OpenSSLException("Cannot open memory BIO for PEM decode");
+
+ char *name_read = NULL;
+ char *header_read = NULL;
+ uint8_t *data_read = NULL;
+ long data_read_len = 0;
+ if (!PEM_read_bio(bio, &name_read, &header_read, &data_read,
+ &data_read_len))
+ {
+ OPENVPN_LOG("PEM decode failed");
+ goto out;
+ }
+
+ if (key_name.compare(std::string(name_read)))
+ {
+ OPENVPN_LOG("unexpected PEM name (got '" << name_read <<
+ "', expected '" << key_name << "')");
+ goto out;
+ }
+
+ dst.write(data_read, data_read_len);
+
+ ret = true;
+out:
+ OPENSSL_free(name_read);
+ OPENSSL_free(header_read);
+ OPENSSL_free(data_read);
+
+ if (!BIO_free(bio))
+ ret = false;
+
+ return ret;
+ }
+ };
+};
+
+#endif /* OPENVPN_OPENSSL_UTIL_PEM_H */
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp
index 4ee3173..1f59b6a 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/options/merge.hpp
@@ -422,6 +422,8 @@ namespace openvpn {
}
if (d == "tls-crypt")
return true;
+ if (d == "tls-crypt-v2")
+ return true;
return false;
}
}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/is_openvpn_protocol.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/is_openvpn_protocol.hpp
index 57de8bf..8b9a436 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/is_openvpn_protocol.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/is_openvpn_protocol.hpp
@@ -34,6 +34,7 @@ namespace openvpn {
inline bool is_openvpn_protocol(const unsigned char *p, const size_t len)
{
const int CONTROL_HARD_RESET_CLIENT_V2 = 7;
+ const int CONTROL_HARD_RESET_CLIENT_V3 = 10;
const int OPCODE_SHIFT = 3;
const int MIN_INITIAL_PKT_SIZE = 14;
@@ -42,7 +43,8 @@ namespace openvpn {
case 3:
return p[0] == 0
&& p[1] >= MIN_INITIAL_PKT_SIZE
- && p[2] == (CONTROL_HARD_RESET_CLIENT_V2 << OPCODE_SHIFT);
+ && (p[2] == (CONTROL_HARD_RESET_CLIENT_V2 << OPCODE_SHIFT)
+ || p[2] == (CONTROL_HARD_RESET_CLIENT_V3 << OPCODE_SHIFT));
case 2:
return p[0] == 0 && p[1] >= MIN_INITIAL_PKT_SIZE;
case 1:
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp
index e3c1b5e..03d91e7 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/proto.hpp
@@ -48,6 +48,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -57,6 +61,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -65,6 +70,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -171,6 +178,7 @@ namespace openvpn {
// indicates key_method >= 2
CONTROL_HARD_RESET_CLIENT_V2 = 7, // initial key from client, forget previous state
+ CONTROL_HARD_RESET_CLIENT_V3 = 10, // initial key from client, forget previous state
CONTROL_HARD_RESET_SERVER_V2 = 8, // initial key from server, forget previous state
// define the range of legal opcodes
@@ -291,8 +299,10 @@ namespace openvpn {
// compressor
CompressContext comp_ctx;
- // tls_auth parms
+ // tls_auth/crypt parms
OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt
+ bool tls_crypt_v2 = false; // needed to distinguish between tls-crypt and tls-crypt-v2 server mode
+ BufferAllocated wkc; // leave this undefined to disable tls-crypt-v2 on client
OvpnHMACFactory::Ptr tls_auth_factory;
OvpnHMACContext::Ptr tls_auth_context;
@@ -301,6 +311,8 @@ namespace openvpn {
TLSCryptFactory::Ptr tls_crypt_factory;
TLSCryptContext::Ptr tls_crypt_context;
+ TLSCryptMetadataFactory::Ptr tls_crypt_metadata_factory;
+
// reliability layer parms
reliable::id_t reliable_window = 0;
size_t max_ack_list = 0;
@@ -332,13 +344,15 @@ namespace openvpn {
// MTU
unsigned int tun_mtu = 1500;
+ MSSParms mss_parms;
+ unsigned int mss_inter = 0;
// Debugging
int debug_level = 1;
// Compatibility
bool force_aes_cbc_ciphersuites = false;
-
+
// For compatibility with openvpn2 we send initial options on rekeying,
// instead of possible modifications caused by NCP
std::string initial_options;
@@ -433,6 +447,8 @@ namespace openvpn {
{
if (tls_auth_context)
throw proto_option_error("tls-auth and tls-crypt are mutually exclusive");
+ if (tls_crypt_context)
+ throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive");
tls_key.parse(o->get(1, 0));
@@ -445,6 +461,46 @@ namespace openvpn {
set_tls_crypt_algs(digest, cipher);
}
}
+
+ // tls-crypt-v2
+ {
+ const Option *o = opt.get_ptr(relay_prefix("tls-crypt-v2"));
+ if (o)
+ {
+ if (tls_auth_context)
+ throw proto_option_error("tls-auth and tls-crypt-v2 are mutually exclusive");
+ if (tls_crypt_context)
+ throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive");
+
+ digest = CryptoAlgs::lookup("SHA256");
+ cipher = CryptoAlgs::lookup("AES-256-CTR");
+
+ if ((digest == CryptoAlgs::NONE) || (cipher == CryptoAlgs::NONE))
+ throw proto_option_error("missing support for tls-crypt-v2 algorithms");
+
+ // initialize tls_crypt_context
+ set_tls_crypt_algs(digest, cipher);
+
+ std::string keyfile = o->get(1, 0);
+
+ if (opt.exists("client"))
+ {
+ // in client mode expect the key to be a PEM encoded tls-crypt-v2 client key (key + WKc)
+ TLSCryptV2ClientKey tls_crypt_v2_key(tls_crypt_context);
+ tls_crypt_v2_key.parse(keyfile);
+ tls_crypt_v2_key.extract_key(tls_key);
+ tls_crypt_v2_key.extract_wkc(wkc);
+ }
+ else
+ {
+ // in server mode this is a PEM encoded tls-crypt-v2 server key
+ TLSCryptV2ServerKey tls_crypt_v2_key;
+ tls_crypt_v2_key.parse(keyfile);
+ tls_crypt_v2_key.extract_key(tls_key);
+ }
+ tls_crypt_v2 = true;
+ }
+ }
}
// key-direction
@@ -507,6 +563,9 @@ namespace openvpn {
// tun-mtu
tun_mtu = parse_tun_mtu(opt, tun_mtu);
+ // mssfix
+ mss_parms.parse(opt);
+
// load parameters that can be present in both config file or pushed options
load_common(opt, pco, server ? LOAD_COMMON_SERVER : LOAD_COMMON_CLIENT);
}
@@ -680,13 +739,18 @@ namespace openvpn {
return tls_key.defined() && tls_crypt_context;
}
+ bool tls_crypt_v2_enabled() const
+ {
+ return tls_crypt_enabled() && tls_crypt_v2;
+ }
+
// generate a string summarizing options that will be
// transmitted to peer for options consistency check
std::string options_string()
{
if (!initial_options.empty())
return initial_options;
-
+
std::ostringstream out;
const bool server = ssl_factory->mode().is_server();
@@ -726,7 +790,7 @@ namespace openvpn {
out << ",tls-server";
else
out << ",tls-client";
-
+
initial_options = out.str();
return initial_options;
@@ -892,6 +956,7 @@ namespace openvpn {
break;
}
case CONTROL_HARD_RESET_CLIENT_V2:
+ case CONTROL_HARD_RESET_CLIENT_V3:
{
if (!proto.is_server())
return;
@@ -946,6 +1011,8 @@ namespace openvpn {
return "DATA_V2";
case CONTROL_HARD_RESET_CLIENT_V2:
return "CONTROL_HARD_RESET_CLIENT_V2";
+ case CONTROL_HARD_RESET_CLIENT_V3:
+ return "CONTROL_HARD_RESET_CLIENT_V3";
case CONTROL_HARD_RESET_SERVER_V2:
return "CONTROL_HARD_RESET_SERVER_V2";
}
@@ -1217,6 +1284,8 @@ namespace openvpn {
public:
typedef RCPtr Ptr;
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_unwrap_wkc_error);
+
// KeyContext events occur on two basic key types:
// Primary Key -- the key we transmit/encrypt on.
// Secondary Key -- new keys and retiring keys.
@@ -1351,7 +1420,7 @@ namespace openvpn {
send_reset();
set_state(state+1);
dirty = true;
- }
+ }
}
// control channel flush
@@ -1466,6 +1535,10 @@ namespace openvpn {
// decompress packet
if (compress)
compress->decompress(buf);
+
+ // set MSS for segments server can receive
+ if (proto.config->mss_inter > 0)
+ MSSFix::mssfix(buf, proto.config->mss_inter);
}
else
buf.reset_size(); // no crypto context available
@@ -1607,6 +1680,15 @@ namespace openvpn {
{
case TLS_AUTH:
return validate_tls_auth(recv, proto, now);
+ case TLS_CRYPT_V2:
+ if (opcode_extract(recv[0]) == CONTROL_HARD_RESET_CLIENT_V3)
+ {
+ // skip validation of HARD_RESET_V3 because the tls-crypt
+ // engine has not been initialized yet
+ OPENVPN_LOG_PROTO_VERBOSE("SKIPPING VALIDATION OF HARD_RESET_V3");
+ return true;
+ }
+ /* no break */
case TLS_CRYPT:
return validate_tls_crypt(recv, proto, now);
case TLS_PLAIN:
@@ -1675,6 +1757,35 @@ namespace openvpn {
// cache op32 for hot path in do_encrypt
cache_op32();
+
+ int crypto_encap = (enable_op32 ? OP_SIZE_V2 : 1) +
+ c.comp_ctx.extra_payload_bytes() +
+ PacketID::size(PacketID::SHORT_FORM) +
+ c.dc.context().encap_overhead();
+
+ int transport_encap = 0;
+ if (c.mss_parms.mtu)
+ {
+ if (proto.is_tcp())
+ transport_encap += sizeof(struct TCPHeader);
+ else
+ transport_encap += sizeof(struct UDPHeader);
+
+ if (c.protocol.is_ipv6())
+ transport_encap += sizeof(struct IPv6Header);
+ else
+ transport_encap += sizeof(struct IPv4Header);
+
+ transport_encap += c.protocol.extra_transport_bytes();
+ }
+
+ if (c.mss_parms.mssfix != 0)
+ {
+ OPENVPN_LOG_PROTO("MTU mssfix=" << c.mss_parms.mssfix <<
+ " crypto_encap=" << crypto_encap <<
+ " transport_encap=" << transport_encap);
+ c.mss_inter = c.mss_parms.mssfix - (crypto_encap + transport_encap);
+ }
}
}
@@ -1765,7 +1876,9 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
- if (!proto.tls_crypt_recv->hmac_cmp(orig_data, orig_size, work.c_data(), work.size()))
+ if (!proto.tls_crypt_recv->hmac_cmp(orig_data,
+ TLSCryptContext::hmac_offset,
+ work.c_data(), work.size()))
return false;
// verify source PSID
@@ -1819,6 +1932,10 @@ namespace openvpn {
{
bool pid_wrap;
+ // set MSS for segments client can receive
+ if (proto.config->mss_inter > 0)
+ MSSFix::mssfix(buf, proto.config->mss_inter);
+
// compress packet
if (compress)
compress->compress(buf, compress_hint);
@@ -1990,25 +2107,36 @@ namespace openvpn {
set_event(ev);
}
- unsigned int initial_op(const bool sender) const
+ unsigned int initial_op(const bool sender, const bool tls_crypt_v2) const
{
if (key_id_)
- return CONTROL_SOFT_RESET_V1;
+ {
+ return CONTROL_SOFT_RESET_V1;
+ }
else
- return (proto.is_server() == sender) ? CONTROL_HARD_RESET_SERVER_V2 : CONTROL_HARD_RESET_CLIENT_V2;
+ {
+ if (proto.is_server() == sender)
+ return CONTROL_HARD_RESET_SERVER_V2;
+
+ if (!tls_crypt_v2)
+ return CONTROL_HARD_RESET_CLIENT_V2;
+ else
+ return CONTROL_HARD_RESET_CLIENT_V3;
+ }
}
void send_reset()
{
Packet pkt;
- pkt.opcode = initial_op(true);
+ pkt.opcode = initial_op(true, proto.tls_wrap_mode == TLS_CRYPT_V2);
pkt.frame_prepare(*proto.config->frame, Frame::WRITE_SSL_INIT);
raw_send(std::move(pkt));
}
void raw_recv(Packet&& raw_pkt) // called by ProtoStackBase
{
- if (raw_pkt.buf->empty() && raw_pkt.opcode == initial_op(false))
+ if (raw_pkt.buf->empty() &&
+ raw_pkt.opcode == initial_op(false, proto.tls_wrap_mode == TLS_CRYPT_V2))
{
switch (state)
{
@@ -2265,14 +2393,15 @@ namespace openvpn {
// write opcode
work.push_front(op_compose(opcode, key_id_));
- // compute HMAC using header fields (from 'work') and plaintext payload (from 'buf')
- proto.tls_crypt_send->hmac_gen(work.data(), work.size(), buf.c_data(), buf.size());
+ // compute HMAC using header fields (from 'work') and plaintext
+ // payload (from 'buf')
+ proto.tls_crypt_send->hmac_gen(work.data(), TLSCryptContext::hmac_offset,
+ buf.c_data(), buf.size());
- const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
- const size_t data_offset = head_size + proto.hmac_size;
+ const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size;
// encrypt the content of 'buf' (packet payload) into 'work'
- const size_t decrypt_bytes = proto.tls_crypt_send->encrypt(work.c_data() + head_size,
+ const size_t decrypt_bytes = proto.tls_crypt_send->encrypt(work.c_data() + TLSCryptContext::hmac_offset,
work.data() + data_offset,
work.max_size() - data_offset,
buf.c_data(), buf.size());
@@ -2283,6 +2412,11 @@ namespace openvpn {
}
work.inc_size(decrypt_bytes);
+ // append WKc to wrapped packet for tls-crypt-v2
+ if ((opcode == CONTROL_HARD_RESET_CLIENT_V3)
+ && (proto.tls_wrap_mode == TLS_CRYPT_V2))
+ proto.tls_crypt_append_wkc(work);
+
// 'work' now contains the complete packet ready to go. swap it with 'buf'
buf.swap(work);
}
@@ -2303,6 +2437,7 @@ namespace openvpn {
gen_head_tls_auth(opcode, buf);
break;
case TLS_CRYPT:
+ case TLS_CRYPT_V2:
gen_head_tls_crypt(opcode, buf);
break;
case TLS_PLAIN:
@@ -2448,15 +2583,14 @@ namespace openvpn {
// skip the hmac
recv.advance(proto.hmac_size);
- const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
- const size_t data_offset = head_size + proto.hmac_size;
+ const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size;
if (orig_size < data_offset)
return false;
// decrypt payload
proto.config->frame->prepare(Frame::DECRYPT_WORK, work);
- const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + head_size,
+ const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + TLSCryptContext::hmac_offset,
work.data(), work.max_size(),
recv.c_data(), recv.size());
if (!decrypt_bytes)
@@ -2470,7 +2604,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
- if (!proto.tls_crypt_recv->hmac_cmp(orig_data, orig_size, work.c_data(), work.size()))
+ if (!proto.tls_crypt_recv->hmac_cmp(orig_data, TLSCryptContext::hmac_offset,
+ work.c_data(), work.size()))
{
proto.stats->error(Error::HMAC_ERROR);
if (proto.is_tcp())
@@ -2528,6 +2663,100 @@ namespace openvpn {
return false;
}
+ bool unwrap_tls_crypt_wkc(Buffer &recv)
+ {
+ // the ``WKc`` is located at the end of the packet, after the tls-crypt
+ // payload.
+ // Format is as follows (as documented by Steffan Krager):
+ //
+ // ``len = len(WKc)`` (16 bit, network byte order)
+ // ``T = HMAC-SHA256(Ka, len || Kc || metadata)``
+ // ``IV = 128 most significant bits of T``
+ // ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len``
+
+ const unsigned char *orig_data = recv.data();
+ const size_t orig_size = recv.size();
+ const size_t hmac_size = proto.config->tls_crypt_context->digest_size();
+ const size_t tls_frame_size = 1 + ProtoSessionID::SIZE +
+ PacketID::size(PacketID::LONG_FORM) +
+ hmac_size +
+ // the following is the tls-crypt payload
+ sizeof(char) + // length of ACK array
+ sizeof(id_t); // reliable ID
+
+ // check that at least the authentication tag ``T`` is present
+ if (orig_size < (tls_frame_size + hmac_size))
+ return false;
+
+ // the ``WKc`` is just appended after the standard tls-crypt frame
+ const unsigned char *wkc_raw = orig_data + tls_frame_size;
+ const size_t wkc_raw_size = orig_size - tls_frame_size - sizeof(uint16_t);
+ // retrieve the ``WKc`` len from the bottom of the packet and convert it to Host Order
+ uint16_t wkc_len = ntohs(*(uint16_t *)(wkc_raw + wkc_raw_size));
+ // length sanity check (the size of the ``len`` field is included in the value)
+ if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size)
+ return false;
+
+ BufferAllocated plaintext(wkc_len, BufferAllocated::CONSTRUCT_ZERO);
+ // plaintext will be used to compute the Auth Tag, therefore start by prepnding
+ // the WKc length in network order
+ wkc_len = htons(wkc_len);
+ plaintext.write(&wkc_len, sizeof(wkc_len));
+ const size_t decrypt_bytes = proto.tls_crypt_server->decrypt(wkc_raw,
+ plaintext.data() + 2,
+ plaintext.max_size() - 2,
+ wkc_raw + hmac_size,
+ wkc_raw_size - hmac_size);
+ plaintext.inc_size(decrypt_bytes);
+ // decrypted data must at least contain a full 2048bits client key
+ // (metadata is optional)
+ if (plaintext.size() < OpenVPNStaticKey::KEY_SIZE)
+ {
+ proto.stats->error(Error::DECRYPT_ERROR);
+ if (proto.is_tcp())
+ invalidate(Error::DECRYPT_ERROR);
+ return false;
+ }
+
+ if (!proto.tls_crypt_server->hmac_cmp(wkc_raw, 0,
+ plaintext.c_data(),
+ plaintext.size()))
+ {
+ proto.stats->error(Error::HMAC_ERROR);
+ if (proto.is_tcp())
+ invalidate(Error::HMAC_ERROR);
+ return false;
+ }
+
+ // we can now remove the WKc length from the plaintext, as it is not
+ // really part of the key material
+ plaintext.advance(sizeof(wkc_len));
+
+ // WKc has been authenticated: it contains the client key followed
+ // by the optional metadata. Let's initialize the tls-crypt context
+ // with the client key
+
+ OpenVPNStaticKey client_key;
+ plaintext.read(client_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE);
+ proto.reset_tls_crypt(*proto.config, client_key);
+
+ // verify metadata
+ int metadata_type = -1;
+ if (!plaintext.empty())
+ metadata_type = plaintext.pop_front();
+
+ if (!proto.tls_crypt_metadata->verify(metadata_type, plaintext))
+ {
+ proto.stats->error(Error::TLS_CRYPT_META_FAIL);
+ return false;
+ }
+
+ // virtually remove the WKc from the packet
+ recv.set_size(tls_frame_size);
+
+ return true;
+ }
+
bool decapsulate(Packet& pkt) // called by ProtoStackBase
{
try {
@@ -2535,6 +2764,20 @@ namespace openvpn {
{
case TLS_AUTH:
return decapsulate_tls_auth(pkt);
+ case TLS_CRYPT_V2:
+ if (pkt.opcode == CONTROL_HARD_RESET_CLIENT_V3)
+ {
+ // unwrap WKc and extract Kc (client key) from packet.
+ // This way we can initialize the tls-crypt per-client contexts
+ // (this happens on the server side only)
+ if (!unwrap_tls_crypt_wkc(*pkt.buf))
+ {
+ return false;
+ }
+ }
+ // now that the tls-crypt contexts have been initialized it is
+ // possible to proceed with the standard tls-crypt decapsulation
+ /* no break */
case TLS_CRYPT:
return decapsulate_tls_crypt(pkt);
case TLS_PLAIN:
@@ -2724,15 +2967,14 @@ namespace openvpn {
if (opcode_extract(op) != reset_op || key_id_extract(op) != 0)
return false;
- const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
- const size_t data_offset = head_size + tls_crypt_recv->output_hmac_size();
+ const size_t data_offset = TLSCryptContext::hmac_offset + tls_crypt_recv->output_hmac_size();
if (net_buf.size() < data_offset)
return false;
frame->prepare(Frame::DECRYPT_WORK, work);
// decrypt payload from 'net_buf' into 'work'
- const size_t decrypt_bytes = tls_crypt_recv->decrypt(net_buf.c_data() + head_size,
+ const size_t decrypt_bytes = tls_crypt_recv->decrypt(net_buf.c_data() + TLSCryptContext::hmac_offset,
work.data(), work.max_size(),
net_buf.c_data() + data_offset,
net_buf.size() - data_offset);
@@ -2742,7 +2984,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
- return tls_crypt_recv->hmac_cmp(net_buf.c_data(), net_buf.size(),
+ return tls_crypt_recv->hmac_cmp(net_buf.c_data(),
+ TLSCryptContext::hmac_offset,
work.data(), work.size());
}
catch (BufferException&)
@@ -2751,11 +2994,30 @@ namespace openvpn {
return false;
}
+ protected:
+ unsigned int reset_op;
+
private:
TLSCryptInstance::Ptr tls_crypt_recv;
Frame::Ptr frame;
BufferAllocated work;
- unsigned int reset_op;
+ };
+
+ class TLSCryptV2PreValidate : public TLSCryptPreValidate
+ {
+ public:
+ OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_pre_validate);
+
+ TLSCryptV2PreValidate(const Config& c, const bool server)
+ : TLSCryptPreValidate(c, server)
+ {
+ if (!c.tls_crypt_v2_enabled())
+ throw tls_crypt_v2_pre_validate();
+
+ // in case of server peer, we expect the new v3 packet type
+ if (server)
+ reset_op = CONTROL_HARD_RESET_CLIENT_V3;
+ }
};
OPENVPN_SIMPLE_EXCEPTION(select_key_context_error);
@@ -2771,20 +3033,27 @@ namespace openvpn {
const Config& c = *config;
// tls-auth setup
- if (c.tls_auth_context)
+ if (c.tls_crypt_v2_enabled())
{
- tls_wrap_mode = TLS_AUTH;
+ tls_wrap_mode = TLS_CRYPT_V2;
// get HMAC size from Digest object
- hmac_size = c.tls_auth_context->size();
+ hmac_size = c.tls_crypt_context->digest_size();
}
- else if (c.tls_crypt_context)
+ else if (c.tls_crypt_enabled())
{
tls_wrap_mode = TLS_CRYPT;
// get HMAC size from Digest object
hmac_size = c.tls_crypt_context->digest_size();
}
+ else if (c.tls_auth_enabled())
+ {
+ tls_wrap_mode = TLS_AUTH;
+
+ // get HMAC size from Digest object
+ hmac_size = c.tls_auth_context->size();
+ }
else
{
tls_wrap_mode = TLS_PLAIN;
@@ -2801,6 +3070,43 @@ namespace openvpn {
return 0;
}
+ void reset_tls_crypt(const Config& c, const OpenVPNStaticKey& key)
+ {
+ tls_crypt_send = c.tls_crypt_context->new_obj_send();
+ tls_crypt_recv = c.tls_crypt_context->new_obj_recv();
+
+ // static direction assignment - not user configurable
+ unsigned int key_dir = is_server() ?
+ OpenVPNStaticKey::NORMAL :
+ OpenVPNStaticKey::INVERSE;
+
+ tls_crypt_send->init(key.slice(OpenVPNStaticKey::HMAC |
+ OpenVPNStaticKey::ENCRYPT | key_dir),
+ key.slice(OpenVPNStaticKey::CIPHER |
+ OpenVPNStaticKey::ENCRYPT | key_dir));
+ tls_crypt_recv->init(key.slice(OpenVPNStaticKey::HMAC |
+ OpenVPNStaticKey::DECRYPT | key_dir),
+ key.slice(OpenVPNStaticKey::CIPHER |
+ OpenVPNStaticKey::DECRYPT | key_dir));
+ }
+
+ void reset_tls_crypt_server(const Config& c)
+ {
+ //tls-crypt session key is derived later from WKc received from the client
+ tls_crypt_send.reset();
+ tls_crypt_recv.reset();
+
+ //server context is used only to process incoming WKc's
+ tls_crypt_server = c.tls_crypt_context->new_obj_recv();
+
+ //the server key is composed by one key set only, therefore direction and
+ //mode should not be specified when slicing
+ tls_crypt_server->init(c.tls_key.slice(OpenVPNStaticKey::HMAC),
+ c.tls_key.slice(OpenVPNStaticKey::CIPHER));
+
+ tls_crypt_metadata = c.tls_crypt_metadata_factory->new_obj();
+ }
+
void reset()
{
const Config& c = *config;
@@ -2820,16 +3126,19 @@ namespace openvpn {
switch (tls_wrap_mode)
{
case TLS_CRYPT:
- tls_crypt_send = c.tls_crypt_context->new_obj_send();
- tls_crypt_recv = c.tls_crypt_context->new_obj_recv();
-
- // static direction assignment - not user configurable
- key_dir = is_server() ? OpenVPNStaticKey::NORMAL : OpenVPNStaticKey::INVERSE;
- tls_crypt_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir),
- c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir));
- tls_crypt_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir),
- c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir));
-
+ reset_tls_crypt(c, c.tls_key);
+ // init tls_crypt packet ID
+ ta_pid_send.init(PacketID::LONG_FORM);
+ ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
+ break;
+ case TLS_CRYPT_V2:
+ if (is_server())
+ // setup key to be used to unwrap WKc upon client connection.
+ // tls-crypt session key setup is postponed to reception of WKc
+ // from client
+ reset_tls_crypt_server(c);
+ else
+ reset_tls_crypt(c, c.tls_key);
// init tls_crypt packet ID
ta_pid_send.init(PacketID::LONG_FORM);
ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
@@ -2860,7 +3169,7 @@ namespace openvpn {
break;
case TLS_PLAIN:
break;
- }
+ }
// initialize proto session ID
psid_self.randomize(*c.prng);
@@ -3199,7 +3508,8 @@ namespace openvpn {
enum TLSWrapMode {
TLS_PLAIN,
TLS_AUTH,
- TLS_CRYPT
+ TLS_CRYPT,
+ TLS_CRYPT_V2
};
void reset_all()
@@ -3483,6 +3793,13 @@ namespace openvpn {
keepalive_xmit = kx;
}
+ void tls_crypt_append_wkc(BufferAllocated& dst)
+ {
+ if (!config->wkc.defined())
+ throw proto_error("Client Key Wrapper undefined");
+ dst.append(config->wkc);
+ }
+
// BEGIN ProtoContext data members
Config::Ptr config;
@@ -3506,6 +3823,9 @@ namespace openvpn {
TLSCryptInstance::Ptr tls_crypt_send;
TLSCryptInstance::Ptr tls_crypt_recv;
+ TLSCryptInstance::Ptr tls_crypt_server;
+ TLSCryptMetadata::Ptr tls_crypt_metadata;
+
PacketIDSend ta_pid_send;
PacketIDReceive ta_pid_recv;
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp
index 285260e..eb07766 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/ssl/sslchoose.hpp
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#endif
#ifdef USE_APPLE_SSL
@@ -46,6 +47,7 @@
#ifdef OPENVPN_PLATFORM_UWP
#include
#endif
+#include
#endif
#ifdef USE_MBEDTLS_APPLE_HYBRID
@@ -69,6 +71,7 @@ namespace openvpn {
#else
typedef MbedTLSRandom RandomAPI;
#endif
+ typedef MbedTLSPEM PEMAPI;
#elif defined(USE_MBEDTLS_APPLE_HYBRID)
// Uses Apple framework for CryptoAPI and MbedTLS for SSLAPI and RandomAPI
#define SSL_LIB_NAME "MbedTLSAppleHybrid"
@@ -85,6 +88,7 @@ namespace openvpn {
typedef OpenSSLCryptoAPI CryptoAPI;
typedef OpenSSLContext SSLAPI;
typedef OpenSSLRandom RandomAPI;
+ typedef OpenSSLPEM PEMAPI;
#else
#error no SSL library defined
#endif
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp
new file mode 100644
index 0000000..d277072
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/time/asiotimersafe.hpp
@@ -0,0 +1,78 @@
+// 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
+
+// AsioTimerSafe is like AsioTimer but with an epoch counter
+// that allows a handler to determine if it is the most recent
+// handler to be queued.
+
+namespace openvpn {
+ class AsioTimerSafe
+ {
+ public:
+ typedef std::size_t epoch_t;
+
+ AsioTimerSafe(openvpn_io::io_context& io_context)
+ : timer_(io_context)
+ {
+ }
+
+ std::size_t expires_at(const Time& t)
+ {
+ ++epoch_;
+ return timer_.expires_at(t);
+ }
+
+ std::size_t expires_after(const Time::Duration& d)
+ {
+ ++epoch_;
+ return timer_.expires_after(d);
+ }
+
+ std::size_t cancel()
+ {
+ ++epoch_;
+ return timer_.cancel();
+ }
+
+ epoch_t epoch() const
+ {
+ return epoch_;
+ }
+
+ template
+ void async_wait(F&& func)
+ {
+ ++epoch_;
+ timer_.async_wait([func=std::move(func), epoch=epoch_](const openvpn_io::error_code& error) mutable
+ {
+ func(error, epoch);
+ });
+ }
+
+ private:
+ AsioTimer timer_;
+ epoch_t epoch_ = 0;
+ };
+}
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 5b48629..46d8795 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/httpcli.hpp
@@ -209,7 +209,7 @@ namespace openvpn {
{}
};
- class Client : public TransportClient
+ class Client : public TransportClient, AsyncResolvableTCP
{
typedef RCPtr Ptr;
@@ -245,12 +245,8 @@ namespace openvpn {
{
// resolve it
parent->transport_pre_resolve();
- 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);
- });
+
+ async_resolve_name(proxy_host, proxy_port);
}
}
}
@@ -340,7 +336,7 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg,
TransportClientParent* parent_arg)
- : io_context(io_context_arg),
+ : AsyncResolvableTCP(io_context_arg),
socket(io_context_arg),
config(config_arg),
parent(parent_arg),
@@ -860,12 +856,13 @@ namespace openvpn {
socket.close();
resolver.cancel();
+ async_resolve_cancel();
}
}
// do DNS resolve
- void do_resolve_(const openvpn_io::error_code& error,
- openvpn_io::ip::tcp::resolver::results_type results)
+ void resolve_callback(const openvpn_io::error_code& error,
+ openvpn_io::ip::tcp::resolver::results_type results) override
{
if (!halt)
{
@@ -916,7 +913,7 @@ namespace openvpn {
#ifdef OPENVPN_PLATFORM_TYPE_UNIX
if (config->socket_protect)
{
- if (!config->socket_protect->socket_protect(socket.native_handle()))
+ if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();
@@ -1008,7 +1005,6 @@ namespace openvpn {
std::string server_host;
std::string server_port;
- openvpn_io::io_context& io_context;
openvpn_io::ip::tcp::socket socket;
ClientConfig::Ptr config;
TransportClientParent* parent;
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 3a273bf..c1f18d7 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/tcpcli.hpp
@@ -74,7 +74,7 @@ namespace openvpn {
{}
};
- class Client : public TransportClient
+ class Client : public TransportClient, AsyncResolvableTCP
{
typedef RCPtr Ptr;
@@ -102,12 +102,8 @@ namespace openvpn {
else
{
parent->transport_pre_resolve();
- 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);
- });
+
+ async_resolve_name(server_host, server_port);
}
}
}
@@ -175,7 +171,8 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg,
TransportClientParent* parent_arg)
- : io_context(io_context_arg),
+ : AsyncResolvableTCP(io_context_arg),
+ io_context(io_context_arg),
socket(io_context_arg),
config(config_arg),
parent(parent_arg),
@@ -249,12 +246,13 @@ namespace openvpn {
socket.close();
resolver.cancel();
+ async_resolve_cancel();
}
}
// do DNS resolve
- void do_resolve_(const openvpn_io::error_code& error,
- openvpn_io::ip::tcp::resolver::results_type results)
+ void resolve_callback(const openvpn_io::error_code& error,
+ openvpn_io::ip::tcp::resolver::results_type results) override
{
if (!halt)
{
@@ -287,7 +285,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect)
{
- if (!config->socket_protect->socket_protect(socket.native_handle()))
+ if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/transbase.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/transbase.hpp
index a0183ae..18f9451 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/transbase.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/transbase.hpp
@@ -91,6 +91,8 @@ namespace openvpn {
// the keepalive parameters (in seconds).
virtual void disable_keepalive(unsigned int& keepalive_ping,
unsigned int& keepalive_timeout) = 0;
+
+ virtual ~TransportClientParent() {}
};
// Factory for client transport object.
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 e55e7c6..be94e66 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/client/udpcli.hpp
@@ -74,7 +74,7 @@ namespace openvpn {
{}
};
- class Client : public TransportClient
+ class Client : public TransportClient, AsyncResolvableUDP
{
typedef RCPtr Ptr;
@@ -101,16 +101,11 @@ namespace openvpn {
{
openvpn_io::error_code error;
openvpn_io::ip::udp::resolver::results_type results = resolver.resolve(server_host, server_port, error);
- do_resolve_(error, results);
+ resolve_callback(error, results);
}
else
{
- 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);
- });
+ async_resolve_name(server_host, server_port);
}
}
}
@@ -181,7 +176,7 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg,
TransportClientParent* parent_arg)
- : io_context(io_context_arg),
+ : AsyncResolvableUDP(io_context_arg),
socket(io_context_arg),
config(config_arg),
parent(parent_arg),
@@ -237,12 +232,13 @@ namespace openvpn {
impl->stop();
socket.close();
resolver.cancel();
+ async_resolve_cancel();
}
}
// called after DNS resolution has succeeded or failed
- void do_resolve_(const openvpn_io::error_code& error,
- openvpn_io::ip::udp::resolver::results_type results)
+ void resolve_callback(const openvpn_io::error_code& error,
+ openvpn_io::ip::udp::resolver::results_type results) override
{
if (!halt)
{
@@ -274,7 +270,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect)
{
- if (!config->socket_protect->socket_protect(socket.native_handle()))
+ if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();
@@ -321,7 +317,6 @@ namespace openvpn {
std::string server_host;
std::string server_port;
- openvpn_io::io_context& io_context;
openvpn_io::ip::udp::socket socket;
ClientConfig::Ptr config;
TransportClientParent* parent;
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/mssfix.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/mssfix.hpp
new file mode 100644
index 0000000..de61519
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/mssfix.hpp
@@ -0,0 +1,150 @@
+// 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
+
+#if OPENVPN_DEBUG_PROTO >= 2
+#define OPENVPN_LOG_MSSFIX(x) OPENVPN_LOG(x)
+#else
+#define OPENVPN_LOG_MSSFIX(x)
+#endif
+
+namespace openvpn {
+ class MSSFix {
+ public:
+ static void mssfix(BufferAllocated& buf, int mss_inter)
+ {
+ if (buf.empty())
+ return;
+
+ switch (IPCommon::version(buf[0]))
+ {
+ case IPCommon::IPv4:
+ {
+ if (buf.length() <= sizeof(struct IPv4Header))
+ break;
+
+ const IPv4Header *iphdr = (const IPv4Header *)buf.c_data();
+
+ auto ipv4hlen = IPv4Header::length(iphdr->version_len);
+
+ if (iphdr->protocol == IPCommon::TCP &&
+ ntohs(iphdr->tot_len) == buf.length() &&
+ (ntohs(iphdr->frag_off) & IPv4Header::OFFMASK) == 0 &&
+ ipv4hlen <= buf.length() &&
+ buf.length() - ipv4hlen >= sizeof(struct TCPHeader))
+ {
+ TCPHeader* tcphdr = (TCPHeader*)(buf.data() + ipv4hlen);
+ int ip_payload_len = buf.length() - ipv4hlen;
+
+ do_mssfix(tcphdr, mss_inter - (sizeof(struct IPv4Header) + sizeof(struct TCPHeader)), ip_payload_len);
+ }
+ }
+ break;
+
+ case IPCommon::IPv6:
+ {
+ if (buf.length() <= sizeof(struct IPv6Header))
+ break;
+
+ const IPv6Header *iphdr = (const IPv6Header *)buf.c_data();
+
+ if (buf.length() != ntohs(iphdr->payload_len) + sizeof(struct IPv6Header))
+ break;
+
+ /* follow header chain until we reach final header, then check for TCP
+ *
+ * An IPv6 packet could, theoretically, have a chain of multiple headers
+ * before the final header (TCP, UDP, ...), so we'd need to walk that
+ * chain (see RFC 2460 and RFC 6564 for details).
+ *
+ * In practice, "most typically used" extention headers (AH, routing,
+ * fragment, mobility) are very unlikely to be seen inside an OpenVPN
+ * tun, so for now, we only handle the case of "single next header = TCP"
+ */
+ if (iphdr->nexthdr != IPCommon::TCP)
+ break;
+
+ /* skip IPv6 header (40 bytes),
+ * verify remainder is large enough to contain a full TCP header
+ */
+ int payload_len = buf.length() - sizeof(struct IPv6Header);
+ if (payload_len >= (int) sizeof(struct TCPHeader))
+ {
+ TCPHeader *tcphdr = (TCPHeader *)(buf.data() + sizeof(struct IPv6Header));
+ do_mssfix(tcphdr, mss_inter - (sizeof(struct IPv6Header) + sizeof(struct TCPHeader)),
+ payload_len);
+ }
+ }
+ break;
+ }
+ }
+
+ private:
+ static void do_mssfix(TCPHeader *tcphdr, int max_mss, int ip_payload_len)
+ {
+ if ((tcphdr->flags & TCPHeader::FLAG_SYN) == 0)
+ return;
+
+ int tcphlen = TCPHeader::length(tcphdr->doff_res);
+ if (tcphlen <= (int) sizeof(struct TCPHeader) || tcphlen > ip_payload_len)
+ return;
+
+ int olen, optlen; // length of options field and Option-Length
+ uint8_t *opt; // option type
+
+ for (olen = tcphlen - sizeof(struct TCPHeader), opt = (uint8_t *)(tcphdr + 1);
+ olen > 1;
+ olen -= optlen, opt += optlen)
+ {
+ if (*opt == TCPHeader::OPT_EOL)
+ break;
+ else if (*opt == TCPHeader::OPT_NOP)
+ optlen = 1;
+ else
+ {
+ optlen = *(opt + 1);
+ if (optlen <= 0 || optlen > olen)
+ break;
+ if ((*opt == TCPHeader::OPT_MAXSEG) && (optlen == TCPHeader::OPTLEN_MAXSEG))
+ {
+ uint16_t mssval = (opt[2] << 8) + opt[3];
+ if (mssval > max_mss)
+ {
+ OPENVPN_LOG_MSSFIX("MTU MSS " << mssval << " -> " << max_mss);
+ int accumulate = htons(mssval);
+ opt[2] = (max_mss >> 8) & 0xff;
+ opt[3] = max_mss & 0xff;
+ accumulate -= htons(max_mss);
+ tcp_adjust_checksum(accumulate, tcphdr->check);
+ }
+ }
+ }
+ }
+ }
+ };
+}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/socket_protect.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/socket_protect.hpp
index 97aef72..6552498 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/socket_protect.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/transport/socket_protect.hpp
@@ -22,6 +22,7 @@
#ifndef OPENVPN_TRANSPORT_SOCKET_PROTECT_H
#define OPENVPN_TRANSPORT_SOCKET_PROTECT_H
+#include
#ifdef OPENVPN_PLATFORM_UWP
#include
#endif
@@ -33,7 +34,7 @@ namespace openvpn {
// the socket from being routed into the VPN tunnel.
class BaseSocketProtect {
public:
- virtual bool socket_protect(int socket) = 0;
+ virtual bool socket_protect(int socket, IP::Addr endpoint) = 0;
};
#ifdef OPENVPN_PLATFORM_UWP
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/builder/capture.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/builder/capture.hpp
index 209429c..524e044 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/builder/capture.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/builder/capture.hpp
@@ -342,7 +342,7 @@ namespace openvpn {
{
try {
if (defined())
- URL::Parse(url);
+ (URL::Parse(url));
}
catch (const std::exception& e)
{
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/tunprop.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/tunprop.hpp
index 5631e1e..c18b407 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/tunprop.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/client/tunprop.hpp
@@ -485,7 +485,7 @@ namespace openvpn {
const Option& o = opt[*i];
try {
const std::string& type = o.get(1, 64);
- if (type == "DNS")
+ if (type == "DNS" || type == "DNS6")
{
o.exact_args(3);
const IP::Addr ip = IP::Addr::from_string(o.get(2, 256), "dns-server-ip");
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/sitnl.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/sitnl.hpp
new file mode 100644
index 0000000..975d6cb
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/sitnl.hpp
@@ -0,0 +1,917 @@
+// 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.
+// Copyright (C) 2018 Antonio Quartulli
+//
+// 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
+
+#include
+#include
+#include
+#include
+
+
+#ifdef DEBUG_RTNL
+#define OPENVPN_LOG_RTNL(_x) OPENVPN_LOG(_x)
+#else
+#define OPENVPN_LOG_RTNL(_x)
+#endif
+
+namespace openvpn {
+ namespace TunNetlink {
+
+#define SNDBUF_SIZE (1024 * 2)
+#define RCVBUF_SIZE (1024 * 4)
+
+#define SITNL_ADDATTR(_msg, _max_size, _attr, _data, _size) \
+ { \
+ if (sitnl_addattr(_msg, _max_size, _attr, _data, _size) < 0)\
+ { \
+ goto err; \
+ } \
+ }
+
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *)(((uint8_t *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
+ /* this class contains only static members */
+ class SITNL
+ {
+ private:
+ /**
+ * Link state request message
+ */
+ struct sitnl_link_req
+ {
+ struct nlmsghdr n;
+ struct ifinfomsg i;
+ char buf[256];
+ };
+
+ /**
+ * Address request message
+ */
+ struct sitnl_addr_req
+ {
+ struct nlmsghdr n;
+ struct ifaddrmsg i;
+ char buf[256];
+ };
+
+ /**
+ * Route request message
+ */
+ struct sitnl_route_req
+ {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[256];
+ };
+
+ typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *msg, void *arg);
+
+ /**
+ * Helper function used to easily add attributes to a rtnl message
+ */
+ static int
+ sitnl_addattr(struct nlmsghdr *n, int maxlen, int type, const void *data,
+ int alen)
+ {
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta;
+
+ if ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: message exceeded bound of " << maxlen);
+ return -EMSGSIZE;
+ }
+
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+
+ if (!data)
+ {
+ memset(RTA_DATA(rta), 0, alen);
+ }
+ else
+ {
+ memcpy(RTA_DATA(rta), data, alen);
+ }
+
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+
+ return 0;
+ }
+
+ /**
+ * Open RTNL socket
+ */
+ static int
+ sitnl_socket(void)
+ {
+ int sndbuf = SNDBUF_SIZE;
+ int rcvbuf = RCVBUF_SIZE;
+ int fd;
+
+ fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0)
+ {
+ OPENVPN_LOG(__func__ << ": cannot open netlink socket");
+ return fd;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0)
+ {
+ OPENVPN_LOG(__func__ << ": SO_SNDBUF");
+ close(fd);
+ return -1;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0)
+ {
+ OPENVPN_LOG(__func__ << ": SO_RCVBUF");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+ }
+
+ /**
+ * Bind socket to Netlink subsystem
+ */
+ static int
+ sitnl_bind(int fd, uint32_t groups)
+ {
+ socklen_t addr_len;
+ struct sockaddr_nl local = { };
+
+ local.nl_family = AF_NETLINK;
+ local.nl_groups = groups;
+
+ if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
+ {
+ OPENVPN_LOG(__func__ << ": cannot bind netlink socket");
+ return -errno;
+ }
+
+ addr_len = sizeof(local);
+ if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0)
+ {
+ OPENVPN_LOG(__func__ << ": cannot getsockname");
+ return -errno;
+ }
+
+ if (addr_len != sizeof(local))
+ {
+ OPENVPN_LOG(__func__ << ": wrong address length " << addr_len);
+ return -EINVAL;
+ }
+
+ if (local.nl_family != AF_NETLINK)
+ {
+ OPENVPN_LOG(__func__ << ": wrong address family " << local.nl_family);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Send Netlink message and run callback on reply (if specified)
+ */
+ static int
+ sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups,
+ sitnl_parse_reply_cb cb, void *arg_cb)
+ {
+ int len, rem_len, fd, ret, rcv_len;
+ struct sockaddr_nl nladdr = { };
+ struct nlmsgerr *err;
+ struct nlmsghdr *h;
+ unsigned int seq;
+ char buf[1024 * 16];
+ struct iovec iov =
+ {
+ .iov_base = payload,
+ .iov_len = payload->nlmsg_len,
+ };
+ struct msghdr nlmsg =
+ {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = peer;
+ nladdr.nl_groups = groups;
+
+ payload->nlmsg_seq = seq = time(NULL);
+
+ /* no need to send reply */
+ if (!cb)
+ {
+ payload->nlmsg_flags |= NLM_F_ACK;
+ }
+
+ fd = sitnl_socket();
+ if (fd < 0)
+ {
+ OPENVPN_LOG(__func__ << ": can't open rtnl socket");
+ return -errno;
+ }
+
+ ret = sitnl_bind(fd, 0);
+ if (ret < 0)
+ {
+ OPENVPN_LOG(__func__ << ": can't bind rtnl socket");
+ ret = -errno;
+ goto out;
+ }
+
+ ret = sendmsg(fd, &nlmsg, 0);
+ if (ret < 0)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: error on sendmsg()");
+ ret = -errno;
+ goto out;
+ }
+
+ /* prepare buffer to store RTNL replies */
+ memset(buf, 0, sizeof(buf));
+ iov.iov_base = buf;
+
+ while (1)
+ {
+ /*
+ * iov_len is modified by recvmsg(), therefore has to be initialized before
+ * using it again
+ */
+ OPENVPN_LOG_RTNL(__func__ << ": checking for received messages");
+ iov.iov_len = sizeof(buf);
+ rcv_len = recvmsg(fd, &nlmsg, 0);
+ OPENVPN_LOG_RTNL(__func__ << ": rtnl: received " << rcv_len << " bytes");
+ if (rcv_len < 0)
+ {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ {
+ OPENVPN_LOG(__func__ << ": interrupted call");
+ continue;
+ }
+ OPENVPN_LOG(__func__ << ": rtnl: error on recvmsg()");
+ ret = -errno;
+ goto out;
+ }
+
+ if (rcv_len == 0)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: socket reached unexpected EOF");
+ ret = -EIO;
+ goto out;
+ }
+
+ if (nlmsg.msg_namelen != sizeof(nladdr))
+ {
+ OPENVPN_LOG(__func__ << ": sender address length: "
+ << nlmsg.msg_namelen << " (expected " << sizeof(nladdr)
+ << ")");
+ ret = -EIO;
+ goto out;
+ }
+
+ h = (struct nlmsghdr *)buf;
+ while (rcv_len >= (int)sizeof(*h))
+ {
+ len = h->nlmsg_len;
+ rem_len = len - sizeof(*h);
+
+ if ((rem_len < 0) || (len > rcv_len))
+ {
+ if (nlmsg.msg_flags & MSG_TRUNC)
+ {
+ OPENVPN_LOG(__func__ << ": truncated message");
+ ret = -EIO;
+ goto out;
+ }
+ OPENVPN_LOG(__func__ << ": malformed message: len=" << len);
+ ret = -EIO;
+ goto out;
+ }
+
+ if (h->nlmsg_type == NLMSG_ERROR)
+ {
+ err = (struct nlmsgerr *)NLMSG_DATA(h);
+ if (rem_len < (int)sizeof(struct nlmsgerr))
+ {
+ OPENVPN_LOG(__func__ << ": ERROR truncated");
+ ret = -EIO;
+ }
+ else
+ {
+ if (!err->error)
+ {
+ ret = 0;
+ if (cb)
+ ret = cb(h, arg_cb);
+ }
+ else
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: generic error: "
+ << strerror(-err->error)
+ << " (" << err->error << ")");
+ ret = err->error;
+ }
+ }
+ goto out;
+ }
+
+ if (cb)
+ {
+ ret = cb(h, arg_cb);
+ goto out;
+ }
+ else
+ {
+ OPENVPN_LOG(__func__ << ": RTNL: unexpected reply");
+ }
+
+ rcv_len -= NLMSG_ALIGN(len);
+ h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
+ }
+
+ if (nlmsg.msg_flags & MSG_TRUNC)
+ {
+ OPENVPN_LOG(__func__ << ": message truncated");
+ continue;
+ }
+
+ if (rcv_len)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: " << rcv_len
+ << " not parsed bytes");
+ ret = -1;
+ goto out;
+ }
+ }
+out:
+ close(fd);
+
+ return ret;
+ }
+
+ /* store the route entry resulting from the query */
+ typedef struct
+ {
+ sa_family_t family;
+ IP::Addr gw;
+ std::string iface;
+ } route_res_t;
+
+ static int
+ sitnl_route_save(struct nlmsghdr *n, void *arg)
+ {
+ route_res_t *res = (route_res_t *)arg;
+ struct rtmsg *r = (struct rtmsg *)NLMSG_DATA(n);
+ struct rtattr *rta = RTM_RTA(r);
+ int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
+ int ifindex = 0;
+
+ while (RTA_OK(rta, len))
+ {
+ switch (rta->rta_type)
+ {
+ case RTA_OIF:
+ /* route interface */
+ ifindex = *(unsigned int *)RTA_DATA(rta);
+ break;
+ case RTA_DST:
+ /* route prefix */
+ RTA_DATA(rta);
+ break;
+ case RTA_GATEWAY:
+ /* GW for the route */
+ {
+ const unsigned char *bytestr = (unsigned char *)RTA_DATA(rta);
+ switch (res->family)
+ {
+ case AF_INET:
+ res->gw = IP::Addr::from_ipv4(IPv4::Addr::from_bytes_net(bytestr));
+ break;
+ case AF_INET6:
+ res->gw = IP::Addr::from_ipv6(IPv6::Addr::from_byte_string(bytestr));
+ break;
+ }
+ }
+ break;
+ }
+
+ rta = RTA_NEXT(rta, len);
+ }
+
+ if (ifindex > 0)
+ {
+ char iface[IFNAMSIZ];
+ if (!if_indextoname(ifindex, iface))
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: can't get ifname for index "
+ << ifindex);
+ return -1;
+ }
+
+ res->iface = iface;
+ }
+
+ return 0;
+ }
+
+ static int
+ sitnl_route_best_gw(const IP::Route& route, IP::Addr& best_gw,
+ std::string& best_iface)
+ {
+ struct sitnl_route_req req = { };
+ route_res_t res;
+ int ret = -EINVAL;
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
+ req.n.nlmsg_type = RTM_GETROUTE;
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+
+ res.family = req.r.rtm_family = route.addr.family();
+ req.r.rtm_dst_len = route.prefix_len;
+
+ if (route.addr.family() == AF_INET)
+ {
+ req.n.nlmsg_flags |= NLM_F_DUMP;
+ }
+
+ {
+ unsigned char bytestr[IP::Addr::V6_SIZE / 8];
+ route.addr.to_byte_string_variable(bytestr);
+
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, bytestr,
+ route.addr.size_bytes());
+ }
+
+ ret = sitnl_send(&req.n, 0, 0, sitnl_route_save, &res);
+ if (ret >= 0)
+ {
+ /* save result in output variables */
+ best_gw = std::move(res.gw);
+ best_iface = std::move(res.iface);
+
+ OPENVPN_LOG(__func__ << " result: via " << best_gw << " dev " << best_iface);
+ }
+ else
+ {
+ OPENVPN_LOG(__func__ << ": failed to retrieve route, err=" << ret);
+ }
+
+err:
+ return ret;
+ }
+
+ static int
+ sitnl_addr_set(const int cmd, const uint32_t flags, const std::string& iface,
+ const IP::Addr& local, const IP::Addr& remote, int prefixlen,
+ const IP::Addr& broadcast)
+ {
+ struct sitnl_addr_req req = { };
+ int ret = -EINVAL;
+
+ if (iface.empty())
+ {
+ OPENVPN_LOG(__func__ << ": passed empty interface");
+ return -EINVAL;
+ }
+
+ if (local.unspecified())
+ {
+ OPENVPN_LOG(__func__ << ": passed zero IP address");
+ return -EINVAL;
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
+ req.n.nlmsg_type = cmd;
+ req.n.nlmsg_flags = NLM_F_REQUEST | flags;
+
+ req.i.ifa_family = local.family();
+ req.i.ifa_index = if_nametoindex(iface.c_str());
+ if (req.i.ifa_index == 0)
+ {
+ OPENVPN_LOG(__func__ << ": cannot get ifindex for " << iface << " "
+ << strerror(errno));
+ return -ENOENT;
+ }
+
+ /* if no prefixlen has been specified, assume host address */
+ if (prefixlen == 0)
+ {
+ prefixlen = local.size();
+ }
+ req.i.ifa_prefixlen = prefixlen;
+
+ {
+ unsigned char bytestr[IP::Addr::V6_SIZE / 8];
+
+ local.to_byte_string_variable(bytestr);
+ SITNL_ADDATTR(&req.n, sizeof(req), IFA_LOCAL, bytestr, local.size_bytes());
+
+ if (remote.specified())
+ {
+ remote.to_byte_string_variable(bytestr);
+ SITNL_ADDATTR(&req.n, sizeof(req), IFA_ADDRESS, bytestr, remote.size_bytes());
+ }
+
+ if (broadcast.specified())
+ {
+ broadcast.to_byte_string_variable(bytestr);
+ SITNL_ADDATTR(&req.n, sizeof(req), IFA_BROADCAST, bytestr, broadcast.size_bytes());
+ }
+ }
+
+ ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+ if ((ret < 0) && (errno == EEXIST))
+ {
+ ret = 0;
+ }
+
+err:
+ return ret;
+ }
+
+ static int
+ sitnl_addr_ptp_add(const std::string& iface, const IP::Addr& local,
+ const IP::Addr& remote)
+ {
+ return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, iface,
+ local, remote, 0,
+ IP::Addr::from_zero(local.version()));
+ }
+
+ static int
+ sitnl_addr_ptp_del(const std::string& iface, const IP::Addr& local)
+ {
+ return sitnl_addr_set(RTM_DELADDR, 0, iface, local,
+ IP::Addr::from_zero(local.version()),
+ 0, IP::Addr::from_zero(local.version()));
+ }
+
+ static int
+ sitnl_route_set(const int cmd, const uint32_t flags,
+ const std::string& iface, const IP::Route& route,
+ const IP::Addr& gw, const enum rt_class_t table,
+ const int metric, const enum rt_scope_t scope,
+ const int protocol, const int type)
+ {
+ struct sitnl_route_req req = { };
+ int ret = -1;
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
+ req.n.nlmsg_type = cmd;
+ req.n.nlmsg_flags = NLM_F_REQUEST | flags;
+
+ req.r.rtm_family = route.addr.family();
+ req.r.rtm_scope = scope;
+ req.r.rtm_protocol = protocol;
+ req.r.rtm_type = type;
+ req.r.rtm_dst_len = route.prefix_len;
+
+ if (table < 256)
+ {
+ req.r.rtm_table = table;
+ }
+ else
+ {
+ req.r.rtm_table = RT_TABLE_UNSPEC;
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_TABLE, &table, 4);
+ }
+
+ {
+ unsigned char bytestr[IP::Addr::V6_SIZE / 8];
+
+ route.addr.to_byte_string_variable(bytestr);
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, bytestr, route.addr.size_bytes());
+
+ if (gw.specified())
+ {
+ gw.to_byte_string_variable(bytestr);
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_GATEWAY, bytestr, gw.size_bytes());
+ }
+ }
+
+ if (!iface.empty())
+ {
+ int ifindex = if_nametoindex(iface.c_str());
+ if (ifindex == 0)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface);
+ return -ENOENT;
+ }
+
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_OIF, &ifindex, 4);
+ }
+
+ if (metric > 0)
+ {
+ SITNL_ADDATTR(&req.n, sizeof(req), RTA_PRIORITY, &metric, 4);
+ }
+
+ ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
+ if ((ret < 0) && (errno == EEXIST))
+ {
+ ret = 0;
+ }
+
+err:
+ return ret;
+ }
+
+ static int
+ sitnl_addr_add(const std::string& iface, const IP::Addr& addr,
+ int prefixlen, const IP::Addr& broadcast)
+ {
+ return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, iface,
+ addr, IP::Addr::from_zero(addr.version()),
+ prefixlen, broadcast);
+ }
+
+ static int
+ sitnl_addr_del(const std::string& iface, const IP::Addr& addr, int prefixlen)
+ {
+ return sitnl_addr_set(RTM_DELADDR, 0, iface, addr,
+ IP::Addr::from_zero(addr.version()), prefixlen,
+ IP::Addr::from_zero(addr.version()));
+ }
+
+ static int
+ sitnl_route_add(const IP::Route& route, const IP::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ return sitnl_route_set(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE, iface,
+ route, gw,
+ (enum rt_class_t)(!table ? RT_TABLE_MAIN : table),
+ metric, RT_SCOPE_UNIVERSE, RTPROT_BOOT, RTN_UNICAST);
+ }
+
+ static int
+ sitnl_route_del(const IP::Route& route, const IP::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ return sitnl_route_set(RTM_DELROUTE, 0, iface, route, gw,
+ (enum rt_class_t)(!table ? RT_TABLE_MAIN : table),
+ metric, RT_SCOPE_NOWHERE,
+ 0, 0);
+ }
+
+ public:
+
+ static int
+ net_route_best_gw(const IP::Route6& route, IPv6::Addr& best_gw6,
+ std::string& best_iface)
+ {
+ IP::Addr best_gw;
+ int ret;
+
+ OPENVPN_LOG(__func__ << " query IPv6: " << route);
+
+ ret = sitnl_route_best_gw(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
+ best_gw, best_iface);
+ if (ret >= 0)
+ {
+ best_gw6 = best_gw.to_ipv6();
+ }
+
+ return ret;
+ }
+
+ static int
+ net_route_best_gw(const IP::Route4& route, IPv4::Addr &best_gw4,
+ std::string& best_iface)
+ {
+ IP::Addr best_gw;
+ int ret;
+
+ OPENVPN_LOG(__func__ << " query IPv4: " << route);
+
+ ret = sitnl_route_best_gw(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
+ best_gw, best_iface);
+ if (ret >= 0)
+ {
+ best_gw4 = best_gw.to_ipv4();
+ }
+
+ return ret;
+ }
+
+ static int
+ net_iface_up(std::string& iface, bool up)
+ {
+ struct sitnl_link_req req = { };
+ int ifindex;
+
+ if (iface.empty())
+ {
+ OPENVPN_LOG(__func__ << ": passed empty interface");
+ return -EINVAL;
+ }
+
+ ifindex = if_nametoindex(iface.c_str());
+ if (ifindex == 0)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface
+ << ": " << strerror(errno));
+ return -ENOENT;
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_NEWLINK;
+
+ req.i.ifi_family = AF_PACKET;
+ req.i.ifi_index = ifindex;
+ req.i.ifi_change |= IFF_UP;
+ if (up)
+ {
+ req.i.ifi_flags |= IFF_UP;
+ }
+ else
+ {
+ req.i.ifi_flags &= ~IFF_UP;
+ }
+
+ OPENVPN_LOG(__func__ << ": set " << iface << " " << (up ? "up" : "down"));
+
+ return sitnl_send(&req.n, 0, 0, NULL, NULL);
+ }
+
+ static int
+ net_iface_mtu_set(std::string& iface, uint32_t mtu)
+ {
+ struct sitnl_link_req req = { };
+ int ifindex;
+
+ if (iface.empty())
+ {
+ OPENVPN_LOG(__func__ << ": passed empty interface");
+ return -EINVAL;
+ }
+
+ ifindex = if_nametoindex(iface.c_str());
+ if (ifindex == 0)
+ {
+ OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface);
+ return -1;
+ }
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_NEWLINK;
+
+ req.i.ifi_family = AF_PACKET;
+ req.i.ifi_index = ifindex;
+
+ SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
+
+ OPENVPN_LOG(__func__ << ": mtu " << mtu << " for " << iface);
+
+err:
+ return sitnl_send(&req.n, 0, 0, NULL, NULL);
+ }
+
+ static int
+ net_addr_add(const std::string& iface, const IPv4::Addr& addr,
+ const int prefixlen, const IPv4::Addr& broadcast)
+ {
+ OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " brd "
+ << broadcast << " dev " << iface);
+
+ return sitnl_addr_add(iface, IP::Addr::from_ipv4(addr), prefixlen,
+ IP::Addr::from_ipv4(broadcast));
+ }
+
+ static int
+ net_addr_add(const std::string& iface, const IPv6::Addr& addr,
+ const int prefixlen)
+ {
+ OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
+
+ return sitnl_addr_add(iface, IP::Addr::from_ipv6(addr), prefixlen,
+ IP::Addr::from_zero(IP::Addr::V6));
+ }
+
+ static int
+ net_addr_del(const std::string& iface, const IPv4::Addr& addr,
+ const int prefixlen)
+ {
+ OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
+
+ return sitnl_addr_del(iface, IP::Addr::from_ipv4(addr), prefixlen);
+ }
+
+ static int
+ net_addr_del(const std::string& iface, const IPv6::Addr& addr,
+ const int prefixlen)
+ {
+ OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
+
+ return sitnl_addr_del(iface, IP::Addr::from_ipv6(addr), prefixlen);
+ }
+
+ static int
+ net_addr_ptp_add(const std::string& iface, const IPv4::Addr& local,
+ const IPv4::Addr& remote)
+ {
+ OPENVPN_LOG(__func__ << ": " << local << " peer " << remote << " dev " << iface);
+
+ return sitnl_addr_ptp_add(iface, IP::Addr::from_ipv4(local),
+ IP::Addr::from_ipv4(remote));
+ }
+
+ static int
+ net_addr_ptp_del(const std::string& iface, const IPv4::Addr& local,
+ const IPv4::Addr& remote)
+ {
+ OPENVPN_LOG(__func__ << ": " << local << " dev " << iface);
+
+ return sitnl_addr_ptp_del(iface, IP::Addr::from_ipv4(local));
+ }
+
+ static int
+ net_route_add(const IP::Route4& route, const IPv4::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
+ << " table " << table << " metric " << metric);
+
+ return sitnl_route_add(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
+ IP::Addr::from_ipv4(gw), iface, table, metric);
+ }
+
+ static int
+ net_route_add(const IP::Route6& route, const IPv6::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
+ << " table " << table << " metric " << metric);
+
+ return sitnl_route_add(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
+ IP::Addr::from_ipv6(gw), iface, table, metric);
+ }
+
+ static int
+ net_route_del(const IP::Route4& route, const IPv4::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
+ << " table " << table << " metric " << metric);
+
+ return sitnl_route_del(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
+ IP::Addr::from_ipv4(gw), iface, table, metric);
+ }
+
+ static int
+ net_route_del(const IP::Route6& route, const IPv6::Addr& gw,
+ const std::string& iface, const uint32_t table,
+ const int metric)
+ {
+ OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
+ << " table " << table << " metric " << metric);
+
+ return sitnl_route_del(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
+ IP::Addr::from_ipv6(gw), iface, table, metric);
+ }
+ };
+ }
+}
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tuncli.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tuncli.hpp
index fccccdd..e6daa67 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tuncli.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tuncli.hpp
@@ -30,7 +30,15 @@
#include
#include
#include
+
+// check if Netlink has been selected at compile time
+#ifdef OPENVPN_USE_SITNL
+#include
+#define TUN_LINUX TunNetlink
+#else
#include
+#define TUN_LINUX TunLinux
+#endif
namespace openvpn {
namespace TunLinux {
@@ -114,7 +122,7 @@ namespace openvpn {
if (tun_setup_factory)
return tun_setup_factory->new_setup_obj();
else
- return new TunLinux::Setup();
+ return new TUN_LINUX::Setup();
}
private:
@@ -129,7 +137,7 @@ namespace openvpn {
typedef Tun TunImpl;
public:
- virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&)
+ virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override
{
if (!impl)
{
@@ -184,7 +192,7 @@ namespace openvpn {
tun_setup = config->new_setup_obj();
// create config object for tun setup layer
- Setup::Config tsconf;
+ TUN_LINUX::Setup::Config tsconf;
tsconf.layer = config->tun_prop.layer;
tsconf.dev_name = config->dev_name;
tsconf.txqueuelen = config->txqueuelen;
@@ -228,12 +236,12 @@ namespace openvpn {
}
}
- virtual bool tun_send(BufferAllocated& buf)
+ virtual bool tun_send(BufferAllocated& buf) override
{
return send(buf);
}
- virtual std::string tun_name() const
+ virtual std::string tun_name() const override
{
if (impl)
return impl->name();
@@ -241,7 +249,7 @@ namespace openvpn {
return "UNDEF_TUN";
}
- virtual std::string vpn_ip4() const
+ virtual std::string vpn_ip4() const override
{
if (state->vpn_ip4_addr.specified())
return state->vpn_ip4_addr.to_string();
@@ -249,7 +257,7 @@ namespace openvpn {
return "";
}
- virtual std::string vpn_ip6() const
+ virtual std::string vpn_ip6() const override
{
if (state->vpn_ip6_addr.specified())
return state->vpn_ip6_addr.to_string();
@@ -273,11 +281,11 @@ namespace openvpn {
return "";
}
- virtual void set_disconnect()
+ virtual void set_disconnect() override
{
}
- virtual void stop() { stop_(); }
+ virtual void stop() override { stop_(); }
virtual ~Client() { stop_(); }
private:
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunnetlink.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunnetlink.hpp
new file mode 100644
index 0000000..17f0536
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunnetlink.hpp
@@ -0,0 +1,821 @@
+// 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
+#include
+#include
+
+namespace openvpn {
+ namespace TunNetlink {
+
+ OPENVPN_EXCEPTION(tun_linux_error);
+ OPENVPN_EXCEPTION(tun_open_error);
+ OPENVPN_EXCEPTION(tun_layer_error);
+ OPENVPN_EXCEPTION(tun_ioctl_error);
+ OPENVPN_EXCEPTION(tun_fcntl_error);
+ OPENVPN_EXCEPTION(tun_name_error);
+ OPENVPN_EXCEPTION(tun_tx_queue_len_error);
+ OPENVPN_EXCEPTION(tun_ifconfig_error);
+
+ struct NetlinkLinkSet : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkLinkSet() {}
+
+ NetlinkLinkSet(std::string dev_arg, bool up_arg, int mtu_arg)
+ : dev(dev_arg),
+ up(up_arg),
+ mtu(mtu_arg)
+ {
+ }
+
+ NetlinkLinkSet* copy() const
+ {
+ NetlinkLinkSet *ret = new NetlinkLinkSet;
+ ret->dev = dev;
+ ret->up = up;
+ ret->mtu = mtu;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkLinkSet with no interface" << std::endl;
+ return;
+ }
+
+ ret = SITNL::net_iface_mtu_set(dev, mtu);
+ if (ret)
+ {
+ os << "Error while executing NetlinkLinkSet " << dev << " mtu " << mtu
+ << ": " << ret << std::endl;
+ }
+
+ ret = SITNL::net_iface_up(dev, up);
+ if (ret)
+ {
+ os << "Error while executing NetlinkLinkSet " << dev << " up " << up
+ << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ std::ostringstream os;
+ os << "netlink iface " << dev << " link set " << up << " mtu " << mtu;
+ return os.str();
+ }
+
+ std::string dev;
+ bool up;
+ int mtu;
+ };
+
+ struct NetlinkAddr4 : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkAddr4() {}
+
+ NetlinkAddr4(std::string dev_arg, IPv4::Addr& addr_arg, int prefixlen_arg,
+ IPv4::Addr& broadcast_arg, bool add_arg)
+ : dev(dev_arg),
+ addr(addr_arg),
+ prefixlen(prefixlen_arg),
+ broadcast(broadcast_arg),
+ add(add_arg)
+ {
+ }
+
+ NetlinkAddr4* copy() const
+ {
+ NetlinkAddr4 *ret = new NetlinkAddr4;
+ ret->dev = dev;
+ ret->addr = addr;
+ ret->prefixlen = prefixlen;
+ ret->broadcast = broadcast;
+ ret->add = add;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkAddr4 with no interface" << std::endl;
+ return;
+ }
+
+ if (add)
+ {
+ ret = SITNL::net_addr_add(dev, addr, prefixlen, broadcast);
+ }
+ else
+ {
+ ret = SITNL::net_addr_del(dev, addr, prefixlen);
+ }
+
+ if (ret)
+ {
+ os << "Error while executing NetlinkAddr4(add: " << add << ") "
+ << dev << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ std::ostringstream os;
+ os << "netlink iface " << dev << " " << (add ? "add" : "del") << " "
+ << addr.to_string() << "/" << prefixlen << " broadcast "
+ << broadcast.to_string();
+ return os.str();
+ }
+
+ std::string dev;
+ IPv4::Addr addr;
+ int prefixlen;
+ IPv4::Addr broadcast;
+ bool add;
+ };
+
+ struct NetlinkAddr6 : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkAddr6() {}
+
+ NetlinkAddr6(std::string dev_arg, IPv6::Addr& addr_arg, int prefixlen_arg,
+ bool add_arg)
+ : dev(dev_arg),
+ addr(addr_arg),
+ prefixlen(prefixlen_arg),
+ add(add_arg)
+ {
+ }
+
+ NetlinkAddr6* copy() const
+ {
+ NetlinkAddr6 *ret = new NetlinkAddr6;
+ ret->dev = dev;
+ ret->addr = addr;
+ ret->prefixlen = prefixlen;
+ ret->add = add;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkAddr6 with no interface" << std::endl;
+ return;
+ }
+
+ if (add)
+ {
+ ret = SITNL::net_addr_add(dev, addr, prefixlen);
+ }
+ else
+ {
+ ret = SITNL::net_addr_del(dev, addr, prefixlen);
+ }
+
+ if (ret)
+ {
+ os << "Error while executing NetlinkAddr6(add: " << add << ") "
+ << dev << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ std::ostringstream os;
+ os << "netlink iface " << dev << " " << (add ? "add" : "del") << " "
+ << addr.to_string() << "/" << prefixlen;
+ return os.str();
+ }
+
+ std::string dev;
+ IPv6::Addr addr;
+ int prefixlen;
+ bool add;
+ };
+
+ struct NetlinkAddr4PtP : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkAddr4PtP() {}
+
+ NetlinkAddr4PtP(std::string dev_arg, IPv4::Addr local_arg,
+ IPv4::Addr remote_arg, bool add_arg)
+ : dev(dev_arg),
+ local(local_arg),
+ remote(remote_arg),
+ add(add_arg)
+ {
+ }
+
+ NetlinkAddr4PtP* copy() const
+ {
+ NetlinkAddr4PtP *ret = new NetlinkAddr4PtP;
+ ret->dev = dev;
+ ret->local = local;
+ ret->remote = remote;
+ ret->add = add;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkAddr4PtP with no interface" << std::endl;
+ return;
+ }
+
+ if (add)
+ {
+ ret = SITNL::net_addr_ptp_add(dev, local, remote);
+ }
+ else
+ {
+ ret = SITNL::net_addr_ptp_del(dev, local, remote);
+ }
+
+ if (ret)
+ {
+ os << "Error while executing NetlinkAddr4PtP(add: " << add << ") "
+ << dev << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ return "netlink iface " + dev + " " + (add ? "add" : "del") + " ptp "
+ + local.to_string() + " remote " + remote.to_string();
+ }
+
+ std::string dev;
+ IPv4::Addr local;
+ IPv4::Addr remote;
+ bool add;
+ };
+
+ struct NetlinkRoute4 : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkRoute4() {}
+
+ NetlinkRoute4(IPv4::Addr& dst_arg, int prefixlen_arg, IPv4::Addr& gw_arg,
+ std::string dev_arg, bool add_arg)
+ : route(dst_arg, prefixlen_arg),
+ gw(gw_arg),
+ dev(dev_arg),
+ add(add_arg)
+ {
+ }
+
+ NetlinkRoute4* copy() const
+ {
+ NetlinkRoute4 *ret = new NetlinkRoute4;
+ ret->route = route;
+ ret->gw = gw;
+ ret->dev = dev;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkRoute4 with no interface" << std::endl;
+ return;
+ }
+
+ if (add)
+ {
+ ret = SITNL::net_route_add(route, gw, dev, 0, 0);
+ }
+ else
+ {
+ ret = SITNL::net_route_del(route, gw, dev, 0, 0);
+ }
+
+ if (ret)
+ {
+ os << "Error while executing NetlinkRoute4(add: " << add << ") "
+ << dev << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ std::ostringstream os;
+ os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " "
+ << route << " via " << gw.to_string();
+ return os.str();
+ }
+
+ IP::Route4 route;
+ IPv4::Addr gw;
+ std::string dev;
+ bool add;
+ };
+
+ struct NetlinkRoute6 : public Action
+ {
+ typedef RCPtr Ptr;
+
+ NetlinkRoute6() {}
+
+ NetlinkRoute6(IPv6::Addr& dst_arg, int prefixlen_arg, IPv6::Addr& gw_arg,
+ std::string dev_arg, bool add_arg)
+ : route(dst_arg, prefixlen_arg),
+ gw(gw_arg),
+ dev(dev_arg),
+ add(add_arg)
+ {
+ }
+
+ NetlinkRoute6* copy() const
+ {
+ NetlinkRoute6 *ret = new NetlinkRoute6;
+ ret->route = route;
+ ret->gw = gw;
+ ret->dev = dev;
+ return ret;
+ }
+
+ virtual void execute(std::ostream& os) override
+ {
+ int ret;
+
+ if (dev.empty())
+ {
+ os << "Error: can't call NetlinkRoute6 with no interface" << std::endl;
+ return;
+ }
+
+ if (add)
+ {
+ ret = SITNL::net_route_add(route, gw, dev, 0, 0);
+ }
+ else
+ {
+ ret = SITNL::net_route_del(route, gw, dev, 0, 0);
+ }
+
+ if (ret)
+ {
+ os << "Error while executing NetlinkRoute6(add: " << add << ") "
+ << dev << ": " << ret << std::endl;
+ }
+ }
+
+ virtual std::string to_string() const override
+ {
+ std::ostringstream os;
+ os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " "
+ << route << " via " << gw.to_string();
+ return os.str();
+ }
+
+ IP::Route6 route;
+ IPv6::Addr gw;
+ std::string dev;
+ bool add;
+ };
+
+ enum { // add_del_route flags
+ R_IPv6=(1<<0),
+ R_ADD_SYS=(1<<1),
+ R_ADD_DCO=(1<<2),
+ R_ADD_ALL=R_ADD_SYS|R_ADD_DCO,
+ };
+
+ /*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr)
+ {
+ BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO);
+ parse_hex(v, hexaddr);
+ if (v.size() != 4)
+ throw tun_linux_error("bad hex address");
+ IPv4::Addr ret = IPv4::Addr::from_bytes(v.data());
+ return IP::Addr::from_ipv4(ret);
+ }*/
+
+ inline void add_del_route(const std::string& addr_str,
+ const int prefix_len,
+ const std::string& gateway_str,
+ const std::string& dev,
+ const unsigned int flags,
+ std::vector* rtvec,
+ Action::Ptr& create,
+ Action::Ptr& destroy)
+ {
+ if (flags & R_IPv6)
+ {
+ const IPv6::Addr addr = IPv6::Addr::from_string(addr_str);
+ const IPv6::Addr netmask = IPv6::Addr::netmask_from_prefix_len(prefix_len);
+ const IPv6::Addr net = addr & netmask;
+
+ if (flags & R_ADD_SYS)
+ {
+ // ip route add 2001:db8:1::/48 via 2001:db8:1::1
+ NetlinkRoute6::Ptr add(new NetlinkRoute6);
+ add->route.addr = net;
+ add->route.prefix_len = prefix_len;
+ add->gw = IPv6::Addr::from_string(gateway_str);
+ add->dev = dev;
+ add->add = true;
+
+ create = add;
+ // for the destroy command, copy the add command but replace "add" with "delete"
+ NetlinkRoute6::Ptr del(add->copy());
+ del->add = false;
+ destroy = del;
+ }
+
+ if (rtvec && (flags & R_ADD_DCO))
+ rtvec->emplace_back(IP::Addr::from_ipv6(net), prefix_len);
+ }
+ else
+ {
+ const IPv4::Addr addr = IPv4::Addr::from_string(addr_str);
+ const IPv4::Addr netmask = IPv4::Addr::netmask_from_prefix_len(prefix_len);
+ const IPv4::Addr net = addr & netmask;
+
+ if (flags & R_ADD_SYS)
+ {
+ // ip route add 192.0.2.128/25 via 192.0.2.1
+ NetlinkRoute4::Ptr add(new NetlinkRoute4);
+ add->route.addr = net;
+ add->route.prefix_len = prefix_len;
+ add->gw = IPv4::Addr::from_string(gateway_str);
+ add->dev = dev;
+ add->add = true;
+
+ create = add;
+ // for the destroy command, copy the add command but replace "add" with "delete"
+ NetlinkRoute4::Ptr del(add->copy());
+ del->add = false;
+ destroy = del;
+ }
+
+ if (rtvec && (flags & R_ADD_DCO))
+ rtvec->emplace_back(IP::Addr::from_ipv4(net), prefix_len);
+ }
+ }
+
+ inline void add_del_route(const std::string& addr_str,
+ const int prefix_len,
+ const std::string& gateway_str,
+ const std::string& dev,
+ const unsigned int flags,// add interface route to rtvec if defined
+ std::vector* rtvec,
+ ActionList& create,
+ ActionList& destroy)
+ {
+ Action::Ptr c, d;
+ add_del_route(addr_str, prefix_len, gateway_str, dev, flags, rtvec, c, d);
+ create.add(c);
+ destroy.add(d);
+ }
+
+ inline void iface_up(const std::string& iface_name,
+ const int mtu,
+ ActionList& create,
+ ActionList& destroy)
+ {
+ {
+ NetlinkLinkSet::Ptr add(new NetlinkLinkSet);
+ add->dev = iface_name;
+ add->up = true;
+ add->mtu = mtu;
+
+ create.add(add);
+ // for the destroy command, copy the add command but replace "up" with "down"
+ NetlinkLinkSet::Ptr del(add->copy());
+ del->up = false;
+ destroy.add(del);
+ }
+ }
+
+ inline void iface_config(const std::string& iface_name,
+ int unit,
+ const TunBuilderCapture& pull,
+ std::vector* rtvec,
+ ActionList& create,
+ ActionList& destroy)
+ {
+ // set local4 and local6 to point to IPv4/6 route configurations
+ const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4();
+ const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6();
+
+ // Set IPv4 Interface
+ if (local4)
+ {
+ NetlinkAddr4::Ptr add(new NetlinkAddr4);
+ add->addr = IPv4::Addr::from_string(local4->address);
+ add->prefixlen = local4->prefix_length;
+ add->broadcast = IPv4::Addr::from_string(local4->address)
+ | ~IPv4::Addr::netmask_from_prefix_len(local4->prefix_length);
+ add->dev = iface_name;
+ add->add = true;
+// if (unit >= 0)
+// {
+// add->argv.push_back("label");
+// add->argv.push_back(iface_name + ':' + openvpn::to_string(unit));
+// }
+ create.add(add);
+
+ // for the destroy command, copy the add command but replace "add" with "delete"
+ NetlinkAddr4::Ptr del(add->copy());
+ del->add = false;
+ destroy.add(del);
+
+ // add interface route to rtvec if defined
+ add_del_route(local4->address, local4->prefix_length, local4->address, iface_name, R_ADD_DCO, rtvec, create, destroy);
+ }
+
+ // Set IPv6 Interface
+ if (local6 && !pull.block_ipv6)
+ {
+ NetlinkAddr6::Ptr add(new NetlinkAddr6);
+ add->addr = IPv6::Addr::from_string(local6->address);
+ add->prefixlen = local6->prefix_length;
+ add->dev = iface_name;
+ add->add = true;
+
+ create.add(add);
+
+ // for the destroy command, copy the add command but replace "add" with "delete"
+ NetlinkAddr6::Ptr del(add->copy());
+ del->add = false;
+ destroy.add(del);
+
+ // add interface route to rtvec if defined
+ add_del_route(local6->address, local6->prefix_length, local6->address, iface_name, R_ADD_DCO|R_IPv6, rtvec, create, destroy);
+ }
+ }
+
+ inline void tun_config(const std::string& iface_name,
+ const TunBuilderCapture& pull,
+ std::vector* rtvec,
+ ActionList& create,
+ ActionList& destroy)
+ {
+ const LinuxGW46Netlink gw;
+
+ // set local4 and local6 to point to IPv4/6 route configurations
+ const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4();
+ const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6();
+
+ // configure interface
+ iface_up(iface_name, pull.mtu, create, destroy);
+ iface_config(iface_name, -1, pull, rtvec, create, destroy);
+
+ // Process Routes
+ {
+ for (const auto &route : pull.add_routes)
+ {
+ if (route.ipv6)
+ {
+ if (!pull.block_ipv6)
+ add_del_route(route.address, route.prefix_length, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
+ }
+ else
+ {
+ if (local4 && !local4->gateway.empty())
+ add_del_route(route.address, route.prefix_length, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
+ else
+ OPENVPN_LOG("ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway");
+ }
+ }
+ }
+
+ // Process exclude routes
+ {
+ for (const auto &route : pull.exclude_routes)
+ {
+ if (route.ipv6)
+ {
+ OPENVPN_LOG("NOTE: exclude IPv6 routes not supported yet"); // fixme
+ }
+ else
+ {
+ if (gw.v4.defined())
+ add_del_route(route.address, route.prefix_length, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy);
+ else
+ OPENVPN_LOG("NOTE: cannot determine gateway for exclude IPv4 routes");
+ }
+ }
+ }
+
+ // Process IPv4 redirect-gateway
+ if (pull.reroute_gw.ipv4)
+ {
+ // add bypass route
+ if (!pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL))
+ add_del_route(pull.remote_address.address, 32, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy);
+
+ add_del_route("0.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
+ add_del_route("128.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
+ }
+
+ // Process IPv6 redirect-gateway
+ if (pull.reroute_gw.ipv6 && !pull.block_ipv6)
+ {
+ // add bypass route
+ if (pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL))
+ add_del_route(pull.remote_address.address, 128, gw.v6.addr().to_string(), gw.v6.dev(), R_ADD_SYS|R_IPv6, rtvec, create, destroy);
+
+ add_del_route("0000::", 1, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
+ add_del_route("8000::", 1, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
+ }
+
+ // fixme -- Process block-ipv6
+
+ // fixme -- Handle pushed DNS servers
+ }
+
+ class Setup : public TunBuilderSetup::Base
+ {
+ public:
+ typedef RCPtr Ptr;
+
+ struct Config : public TunBuilderSetup::Config
+ {
+ std::string iface_name;
+ Layer layer; // OSI layer
+ std::string dev_name;
+ int txqueuelen;
+
+#ifdef HAVE_JSON
+ virtual Json::Value to_json() override
+ {
+ Json::Value root(Json::objectValue);
+ root["iface_name"] = Json::Value(iface_name);
+ root["layer"] = Json::Value(layer.str());
+ root["dev_name"] = Json::Value(dev_name);
+ root["txqueuelen"] = Json::Value(txqueuelen);
+ return root;
+ };
+
+ virtual void from_json(const Json::Value& root, const std::string& title) override
+ {
+ json::assert_dict(root, title);
+ json::to_string(root, iface_name, "iface_name", title);
+ layer = Layer::from_str(json::get_string(root, "layer", title));
+ json::to_string(root, dev_name, "dev_name", title);
+ json::to_int(root, txqueuelen, "txqueuelen", title);
+ }
+#endif
+ };
+
+ virtual void destroy(std::ostream &os) override
+ {
+ // remove added routes
+ if (remove_cmds)
+ remove_cmds->execute(std::cout);
+ }
+
+ virtual int establish(const TunBuilderCapture& pull, // defined by TunBuilderSetup::Base
+ TunBuilderSetup::Config* config,
+ Stop* stop,
+ std::ostream& os) override
+ {
+ // get configuration
+ Config *conf = dynamic_cast(config);
+ if (!conf)
+ throw tun_linux_error("missing config");
+
+ static const char node[] = "/dev/net/tun";
+ ScopedFD fd(open(node, O_RDWR));
+ if (!fd.defined())
+ OPENVPN_THROW(tun_open_error, "error opening tun device " << node << ": " << errinfo(errno));
+
+ struct ifreq ifr;
+ std::memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_ONE_QUEUE;
+ ifr.ifr_flags |= IFF_NO_PI;
+ if (conf->layer() == Layer::OSI_LAYER_3)
+ ifr.ifr_flags |= IFF_TUN;
+ else if (conf->layer() == Layer::OSI_LAYER_2)
+ ifr.ifr_flags |= IFF_TAP;
+ else
+ throw tun_layer_error("unknown OSI layer");
+
+ open_unit(conf->dev_name, ifr, fd);
+
+ if (fcntl (fd(), F_SETFL, O_NONBLOCK) < 0)
+ throw tun_fcntl_error(errinfo(errno));
+
+ // Set the TX send queue size
+ if (conf->txqueuelen)
+ {
+ struct ifreq netifr;
+ ScopedFD ctl_fd(socket (AF_INET, SOCK_DGRAM, 0));
+
+ if (ctl_fd.defined())
+ {
+ std::memset(&netifr, 0, sizeof(netifr));
+ strcpy (netifr.ifr_name, ifr.ifr_name);
+ netifr.ifr_qlen = conf->txqueuelen;
+ if (ioctl (ctl_fd(), SIOCSIFTXQLEN, (void *) &netifr) < 0)
+ throw tun_tx_queue_len_error(errinfo(errno));
+ }
+ else
+ throw tun_tx_queue_len_error(errinfo(errno));
+ }
+
+ conf->iface_name = ifr.ifr_name;
+
+ ActionList::Ptr add_cmds = new ActionList();
+ remove_cmds.reset(new ActionListReversed()); // remove commands executed in reversed order
+
+ // configure tun properties
+ tun_config(ifr.ifr_name, pull, nullptr, *add_cmds, *remove_cmds);
+
+ // execute commands to bring up interface
+ add_cmds->execute(std::cout);
+
+ return fd.release();
+ }
+
+ private:
+ void open_unit(const std::string& name, struct ifreq& ifr, ScopedFD& fd)
+ {
+ if (!name.empty())
+ {
+ const int max_units = 256;
+ for (int unit = 0; unit < max_units; ++unit)
+ {
+ std::string n = name;
+ if (unit)
+ n += openvpn::to_string(unit);
+ if (n.length() < IFNAMSIZ)
+ ::strcpy (ifr.ifr_name, n.c_str());
+ else
+ throw tun_name_error();
+ if (ioctl (fd(), TUNSETIFF, (void *) &ifr) == 0)
+ return;
+ }
+ const int eno = errno;
+ OPENVPN_THROW(tun_ioctl_error, "failed to open tun device '" << name << "' after trying " << max_units << " units : " << errinfo(eno));
+ }
+ else
+ {
+ if (ioctl (fd(), TUNSETIFF, (void *) &ifr) < 0)
+ {
+ const int eno = errno;
+ OPENVPN_THROW(tun_ioctl_error, "failed to open tun device '" << name << "' : " << errinfo(eno));
+ }
+ }
+ }
+
+ ActionListReversed::Ptr remove_cmds;
+ };
+ }
+} // namespace openvpn
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunsetup.hpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunsetup.hpp
index b9accc0..0d9eadb 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunsetup.hpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/openvpn/tun/linux/client/tunsetup.hpp
@@ -364,7 +364,7 @@ namespace openvpn {
#endif
};
- virtual void destroy(std::ostream &os)
+ virtual void destroy(std::ostream &os) override
{
// remove added routes
if (remove_cmds)
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost
index eaa89e4..e1536b8 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-boost
@@ -17,7 +17,7 @@ cd $DEP_DIR
rm -rf boost
mkdir boost
export LINK_MODE=static
-export TARGETS="android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg"
+export TARGETS="android-a8a android-a8a-dbg android-a7a android-a7a-dbg"
export SDK_PATH_SCRIPT=$O3/core/vars/android-sdk-path
$O3/core/deps/boost/build-boost
exit 0
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo
index 7fedc43..2d39e2e 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-lzo
@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf lzo
mkdir lzo
-for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
+for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/lzo/build-lzo
done
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto
index a2e954f..3f613fd 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-minicrypto
@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf minicrypto
mkdir minicrypto
-for target in android android-dbg android-a7a android-a7a-dbg ; do
+for target in android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/minicrypto/build-minicrypto
done
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl
index e04e51c..9950c9a 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-polarssl
@@ -18,7 +18,7 @@ mini=0
rm -rf polarssl
mkdir polarssl
-for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
+for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
VERBOSE=1 TARGET=$target CMAKE_TARGET=android USE_MINICRYPTO=$mini MINICRYPTO_DIR=$(pwd)/minicrypto/minicrypto-$target $O3/core/deps/polarssl/build-polarssl
mv polarssl-$target polarssl/
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk
index f8a8b95..01f1a49 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-sdk
@@ -15,31 +15,28 @@ fi
if [ -d "$SDK" ]; then
echo "Android SDK already exists at $SDK. Doing only update"
- yes | $SDK/tools/bin/sdkmanager --licenses
- $SDK/tools/bin/sdkmanager --update
- exit 0
+else
+ . $O3/core/deps/functions.sh
+
+ FNAME=sdk-tools-linux-3859397.zip
+ URL=https://dl.google.com/android/repository/${FNAME}
+ CSUM=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
+
+ download
+
+ cd $DEP_DIR
+ rm -rf android-sdk
+ mkdir android-sdk
+
+ . $O3/core/vars/android-sdk-path
+
+ cd $SDK
+ unzip $DL/$FNAME
fi
-. $O3/core/deps/functions.sh
-
-FNAME=sdk-tools-linux-3859397.zip
-URL=https://dl.google.com/android/repository/${FNAME}
-CSUM=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
-
-download
-
-cd $DEP_DIR
-rm -rf android-sdk
-mkdir android-sdk
-
-. $O3/core/vars/android-sdk-path
-
-cd $SDK
-unzip $DL/$FNAME
-
yes | $SDK/tools/bin/sdkmanager --licenses
$SDK/tools/bin/sdkmanager --update
-$SDK/tools/bin/sdkmanager 'build-tools;26.0.2' \
+$SDK/tools/bin/sdkmanager --install 'build-tools;26.0.2' \
'ndk-bundle' \
'extras;android;m2repository' \
'patcher;v4' \
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy
index a94e439..394a1e8 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-snappy
@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf snappy
mkdir snappy
-for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
+for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/snappy/build-snappy
done
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain
index efe9b6f..0f8c613 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/android/build-toolchain
@@ -39,7 +39,7 @@ $NDK/build/tools/make-standalone-toolchain.sh \
--toolchain=$ABI-$ABI_VER \
--stl=gnustl \
--arch=arm \
- --platform=android-14 \
+ --platform=android-16 \
--install-dir=$DEST
cd $DEST/$ABI/bin
ln -s ../../bin/$ABI-gcc cc
@@ -58,7 +58,7 @@ $NDK/build/tools/make-standalone-toolchain.sh \
--toolchain=$ABI-$ABI_VER \
--stl=gnustl \
--arch=x86 \
- --platform=android-14 \
+ --platform=android-16 \
--install-dir=$DEST
cd $DEST/$SUB/bin
ln -s ../../bin/$SUB-gcc cc
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build
index 8f8ee88..cd3f872 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/build
@@ -242,8 +242,12 @@ fi
# Cityhash
if [ "$CITY" = "1" ]; then
- LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib"
- CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include"
+ if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" ]; then
+ LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib"
+ fi
+ if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/include" ]; then
+ CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include"
+ fi
LIBS="$LIBS -lcityhash"
CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH"
fi
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/update-copyright b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/update-copyright
new file mode 100755
index 0000000..d831fcf
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/update-copyright
@@ -0,0 +1,51 @@
+#!/bin/sh
+# update-copyright - Simple tool to update the Copyright lines
+# in all files checked into git
+#
+# Copyright (C) 2018 OpenVPN Inc
+# Copyright (C) 2018 David Sommerseth
+#
+# 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 .
+#
+
+# Basic shell sanity
+set -eu
+
+# Simple argument control
+if [ $# -ne 1 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+# Only update Copyright lines with these owners
+# The 'or' operator is GNU sed specific, and must be \|
+UPDATE_COPYRIGHT_LINES="OpenVPN Inc\|@openvpn\.net\\|unstable\.cc\|gmail\.com\|@fox-it\.com"
+COPY_YEAR="$1"
+
+cd "$(git rev-parse --show-toplevel)"
+for file in $(git ls-files | grep -v deps/);
+do
+ echo -n "Updating $file ..."
+ # The first sed operation covers 20xx-20yy copyright lines,
+ # The second sed operation changes 20xx -> 20xx-20yy
+ sed -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) 20..-\)\(20..\)[[:blank:]]\+/\1$COPY_YEAR /" \
+ -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) \)\(20..\)[[:blank:]]\+/\1\2-$COPY_YEAR /" \
+ -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) $COPY_YEAR\)\(-$COPY_YEAR\)[[:blank:]]\+/\1 /" \
+ -i $file
+ echo " Done"
+done
+echo
+echo "** All files updated with $COPY_YEAR as the ending copyright year"
+echo
+exit 0
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp
index 717066c..ea08f63 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/cli.cpp
@@ -80,6 +80,10 @@
#include
#endif
+#ifdef USE_NETCFG
+#include "client/core-client-netcfg.hpp"
+#endif
+
using namespace openvpn;
namespace {
@@ -141,9 +145,10 @@ public:
#endif
private:
- virtual bool socket_protect(int socket) override
+ bool socket_protect(int socket, std::string remote, bool ipv6) override
{
- std::cout << "*** socket_protect " << socket << std::endl;
+ std::cout << "*** socket_protect " << socket << " "
+ << remote << std::endl;
return true;
}
@@ -910,7 +915,13 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
}
else
{
+#if defined(USE_NETCFG)
+ DBus conn(G_BUS_TYPE_SYSTEM);
+ conn.Connect();
+ NetCfgTunBuilder client(conn.GetConnection());
+#else
Client client;
+#endif
const ClientAPI::EvalConfig eval = client.eval_config(config);
if (eval.error)
OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message);
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go
index 8f1a1ec..873cf1f 100755
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ovpncli/go
@@ -15,6 +15,7 @@ GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN"
[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000"
[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE"
[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK"
+[ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL"
if [ "$AGENT" = "1" ]; then
GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT"
fi
@@ -23,9 +24,9 @@ export GCC_EXTRA
# determine platform
if [ "$(uname)" == "Darwin" ]; then
- export PROF=osx64
+ export PROF=${PROF:-osx64}
elif [ "$(uname)" == "Linux" ]; then
- export PROF=linux
+ export PROF=${PROF:-linux}
else
echo this script only knows how to build on Mac OS or Linux
fi
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/proto.cpp b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/proto.cpp
index 497abb3..c712aef 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/proto.cpp
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/proto.cpp
@@ -41,7 +41,8 @@
#if !defined(USE_TLS_AUTH) && !defined(USE_TLS_CRYPT)
//#define USE_TLS_AUTH
-#define USE_TLS_CRYPT
+//#define USE_TLS_CRYPT
+#define USE_TLS_CRYPT_V2
#endif
#define OPENVPN_INSTRUMENTATION
@@ -834,6 +835,8 @@ int test(const int thread_num)
const std::string server_key = read_text("server.key");
const std::string dh_pem = read_text("dh.pem");
const std::string tls_auth_key = read_text("tls-auth.key");
+ const std::string tls_crypt_v2_server_key = read_text("tls-crypt-v2-server.key");
+ const std::string tls_crypt_v2_client_key = read_text("tls-crypt-v2-client.key");
// client config
ClientSSLAPI::Config::Ptr cc(new ClientSSLAPI::Config());
@@ -888,6 +891,17 @@ int test(const int thread_num)
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
cp->tls_key.parse(tls_auth_key);
cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
+#endif
+#ifdef USE_TLS_CRYPT_V2
+ cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
+ cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
+ {
+ TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context);
+ tls_crypt_v2_key.parse(tls_crypt_v2_client_key);
+ tls_crypt_v2_key.extract_key(cp->tls_key);
+ tls_crypt_v2_key.extract_wkc(cp->wkc);
+ }
+ cp->tls_crypt_v2 = true;
#endif
cp->reliable_window = 4;
cp->max_ack_list = 4;
@@ -959,10 +973,21 @@ int test(const int thread_num)
sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST));
sp->key_direction = 1;
#endif
-#ifdef USE_TLS_CRYPT
- sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
+#if defined(USE_TLS_CRYPT)
+ sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
sp->tls_key.parse(tls_auth_key);
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
+#endif
+#ifdef USE_TLS_CRYPT_V2
+ sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory());
+ {
+ TLSCryptV2ServerKey tls_crypt_v2_key;
+ tls_crypt_v2_key.parse(tls_crypt_v2_server_key);
+ tls_crypt_v2_key.extract_key(sp->tls_key);
+ }
+ sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
+ sp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
+ sp->tls_crypt_v2 = true;
#endif
sp->reliable_window = 4;
sp->max_ack_list = 4;
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-client.key b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-client.key
new file mode 100644
index 0000000..ea6f933
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-client.key
@@ -0,0 +1,14 @@
+-----BEGIN OpenVPN tls-crypt-v2 client key-----
+fxgWlYpYT1H8ZCW3/139Ip6WSAa2QQZUu64N/x3g7RzhYuaInPRpP9GLpeDpj/PP
+MOa0LuvbIr9Wm6V4+WUO+R8hOdfIMwtBlRleMDedFNRD5h1DCpoDdpgr5CxaPyqO
+H6eCvNP7POmqdGJyo9L6H9ndyetQp4r/8wXeYWSkcJKsIJsmyBqRzuODTENGYCqG
+FN3+XcUrEMYUyvb/c8NqDVQ6xpwc9+6N7840encSMZPYCq6o8J1QXZJ8sMoBEPa1
+gVtLCsPXp2oTs1h82NBpxO8BNPNFz1xIG+2Zy1NpU8PONnr0rtCRPNU7ejsG+p2I
+vRDt3VOf+3aD2eVFesR4NAWYTZlxg3eLG4zD/xSiGblBltbB/7qGPxgK6WOP2XD/
+V0Yh+TruX2vo4xjEXqV1umTx9K8u6nvaC8uv/72NsvPWkuAOEpY6qpDrqiya+zod
+zjrlKdLmftaTEMGURDIjooNygFOAania7UhLWOjhnzZFntLHoYmskF0C7om4CqPR
+dhf1OuyaD436yQVdt3t/8sjBGuY4hQZ3PuMKDEsHEzmq8bYwfmDf3U8IsK39NbXO
+Bh7Q3Gxxy0vTP2TRsGUbePh5ZveVtCJGe79tjtveLdEVdh+TsMB2xo/ZLFfjDPOx
+6xvj5xKQtyou5YawuniHn5nrDWbyARQDTmVl7a5w5HvK3SbuVDrJsuLiRohfKyah
+M17SAY5reFev6+piR+zT64zwTYdU20i28gEr
+-----END OpenVPN tls-crypt-v2 client key-----
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-server.key b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-server.key
new file mode 100644
index 0000000..e8152aa
--- /dev/null
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/ssl/tls-crypt-v2-server.key
@@ -0,0 +1,5 @@
+-----BEGIN OpenVPN tls-crypt-v2 server key-----
+hn6VWraZG0o64iPI7faGYkwTMajjqhXqG2kC1X19jCl+aXhWPSgmDbRCT/pSfjLZ
+a2pKXP6DGdi3nuINKuPw4655AcuMaBe4b45+zJz5xk92NnNosLaTsanXtjfBNOK5
+S/M1f4cLZViVsJTDSMcINK/RCclWVK+IFi//CThZQM8=
+-----END OpenVPN tls-crypt-v2 server key-----
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/unittests.vcxproj b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/unittests.vcxproj
index 1d1e793..fc8c7aa 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/unittests.vcxproj
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/test/unittests/unittests.vcxproj
@@ -1,143 +1,143 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- {18446924-20CC-4EB7-B639-A76C1422E5C2}
- unittests
- 8.1
-
-
-
- Application
- true
- v140
- MultiByte
-
-
- Application
- false
- v140
- true
- MultiByte
-
-
- Application
- true
- v140
- MultiByte
-
-
- Application
- false
- v140
- true
- MultiByte
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TurnOffAllWarnings
- Disabled
- false
- $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
-
-
- true
- lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)
- $(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib
-
-
-
-
- TurnOffAllWarnings
- Disabled
- false
- $(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)
- MultiThreadedDebug
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)
-
-
- true
- lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
- $(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib
-
-
-
-
- TurnOffAllWarnings
- MaxSpeed
- true
- true
- false
- $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
-
-
- true
- true
- true
- lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
- $(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib
-
-
-
-
- TurnOffAllWarnings
- MaxSpeed
- true
- true
- false
- $(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
-
-
- true
- true
- true
- lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
- $(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib
-
-
-
-
-
-
-
-
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}
+ unittests
+ 10.0.17134.0
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v140
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TurnOffAllWarnings
+ Disabled
+ false
+ $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
+
+
+ true
+ lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)
+ $(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib
+
+
+
+
+ TurnOffAllWarnings
+ Disabled
+ false
+ $(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)
+ MultiThreadedDebug
+ _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
+ $(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib
+
+
+
+
+ TurnOffAllWarnings
+ MaxSpeed
+ true
+ true
+ false
+ $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
+ $(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib
+
+
+
+
+ TurnOffAllWarnings
+ MaxSpeed
+ true
+ true
+ false
+ $(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)
+ _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)
+ $(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android
deleted file mode 100644
index 0f5a186..0000000
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android
+++ /dev/null
@@ -1,15 +0,0 @@
-[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android
-export PLATFORM=android
-export ABI=armeabi
-export DEBUG_BUILD=0
-export OTHER_COMPILER_FLAGS=""
-export CXX_COMPILER_FLAGS="-std=c++1y"
-export LIB_OPT_LEVEL="-O3"
-export LIB_FPIC="-fPIC"
-export TC=$DEP_DIR/tc-arm
-export PLATFORM_FLAGS="-march=armv5te --sysroot=$TC/sysroot"
-export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
-export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"
-
-[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH"
-export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH"
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a7a b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a7a
index edf0c7d..ac72bf1 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a7a
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a7a
@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm
-export PLATFORM_FLAGS="-D__LP32__ -D__ANDROID_API__=14 -march=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot"
+export PLATFORM_FLAGS="-D__LP32__ -march=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a8a b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a8a
index 59c8dcf..0f29a51 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a8a
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-a8a
@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm64
-export PLATFORM_FLAGS="-D__ANDROID_API__=21 -march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot"
+export PLATFORM_FLAGS="-march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/aarch64-linux-android-g++"
export GCC_CMD="$TC/bin/aarch64-linux-android-gcc"
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-dbg b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-dbg
deleted file mode 100644
index 1c0713c..0000000
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-dbg
+++ /dev/null
@@ -1,15 +0,0 @@
-[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android
-export PLATFORM=android-dbg
-export ABI=armeabi
-export DEBUG_BUILD=1
-export OTHER_COMPILER_FLAGS="-g"
-export CXX_COMPILER_FLAGS="-std=c++1y"
-export LIB_OPT_LEVEL="-O0"
-export LIB_FPIC="-fPIC"
-export TC=$DEP_DIR/tc-arm
-export PLATFORM_FLAGS="-march=armv5te --sysroot=$TC/sysroot"
-export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
-export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"
-
-[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH"
-export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH"
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-x86 b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-x86
index 965a32b..6f6c74f 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-x86
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/vars/vars-android-x86
@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-x86
-export PLATFORM_FLAGS="-D__LP32__ -D__ANDROID_API__=14 -march=i686 -fomit-frame-pointer --sysroot=$TC/sysroot"
+export PLATFORM_FLAGS="-D__LP32__ -march=i686 -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/i686-linux-android-g++"
export GCC_CMD="$TC/bin/i686-linux-android-gcc"
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py
index 1d48489..c01eb6e 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/buildep.py
@@ -25,10 +25,14 @@ def build_asio(parms):
sys.exit("Checksum mismatch, expected %s, actual %s" % (parms["ASIO_CSUM"], checksum))
with ModEnv('PATH', "%s\\bin;%s" % (parms.get('GIT'), os.environ['PATH'])):
extract(arch_path, "gz")
- rmtree("asio")
- os.rename("asio-%s" % asio_ver, "asio")
+ dist = os.path.realpath('asio')
+ rmtree(dist)
+ os.rename("asio-%s" % asio_ver, dist)
rm(arch_path)
+ for patch_file in glob.glob(os.path.join(parms.get('OVPN3'), "core", "deps", "asio", "patches", "*.patch")):
+ call(["git", "apply", "--whitespace=nowarn", "--ignore-space-change", "--verbose", patch_file], cwd=dist)
+
def build_mbedtls(parms):
print "**************** MBEDTLS"
with Cd(build_dir(parms)):
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln
index e6fe3cd..5af53dc 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.sln
@@ -1,44 +1,45 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "ovpn3-core.vcxproj", "{1F891260-2039-494F-9777-EC5166AF31BC}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "..\test\unittests\unittests.vcxproj", "{18446924-20CC-4EB7-B639-A76C1422E5C2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|ARM = Debug|ARM
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|ARM = Release|ARM
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|ARM.ActiveCfg = Debug|Win32
- {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.ActiveCfg = Debug|x64
- {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.Build.0 = Debug|x64
- {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x86.ActiveCfg = Debug|Win32
- {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x86.Build.0 = Debug|Win32
- {1F891260-2039-494F-9777-EC5166AF31BC}.Release|ARM.ActiveCfg = Release|Win32
- {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.ActiveCfg = Release|x64
- {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.Build.0 = Release|x64
- {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.ActiveCfg = Release|Win32
- {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.Build.0 = Release|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|ARM.ActiveCfg = Debug|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.ActiveCfg = Debug|x64
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.Build.0 = Debug|x64
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.ActiveCfg = Debug|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.Build.0 = Debug|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|ARM.ActiveCfg = Release|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.ActiveCfg = Release|x64
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.Build.0 = Release|x64
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.ActiveCfg = Release|Win32
- {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.106
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "ovpn3-core.vcxproj", "{1F891260-2039-494F-9777-EC5166AF31BC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "..\test\unittests\unittests.vcxproj", "{18446924-20CC-4EB7-B639-A76C1422E5C2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|ARM.ActiveCfg = Debug|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.ActiveCfg = Debug|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.Build.0 = Debug|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x86.ActiveCfg = Debug|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Release|ARM.ActiveCfg = Release|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.ActiveCfg = Release|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.Build.0 = Release|x64
+ {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.ActiveCfg = Release|x64
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|ARM.ActiveCfg = Debug|Win32
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.ActiveCfg = Debug|x64
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.Build.0 = Debug|x64
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.ActiveCfg = Debug|Win32
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.Build.0 = Debug|Win32
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|ARM.ActiveCfg = Release|Win32
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.ActiveCfg = Release|x64
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.Build.0 = Release|x64
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.ActiveCfg = Release|Win32
+ {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {2C22702B-DF56-4CEB-9CA4-C999BD01FD03}
+ EndGlobalSection
+EndGlobal
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj
index bd9421d..040f60c 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj
@@ -1,14 +1,6 @@
-
- Debug
- Win32
-
-
- Release
- Win32
-
Debug
x64
@@ -18,9 +10,6 @@
x64
-
-
-
@@ -31,6 +20,8 @@
+
+
@@ -62,6 +53,7 @@
+
@@ -81,6 +73,7 @@
+
@@ -101,12 +94,14 @@
+
+
@@ -134,17 +129,19 @@
-
+
+
+
@@ -182,6 +179,7 @@
+
@@ -210,6 +208,9 @@
+
+
+
@@ -226,21 +227,39 @@
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -298,6 +317,7 @@
+
@@ -325,6 +345,7 @@
+
@@ -332,9 +353,12 @@
+
+
+
@@ -342,6 +366,7 @@
+
@@ -349,6 +374,8 @@
+
+
@@ -365,13 +392,15 @@
-
+
+
+
@@ -402,30 +431,20 @@
+
+
+
{1F891260-2039-494F-9777-EC5166AF31BC}
ovpn3core
- 8.1
+ 10.0.17134.0
cli
-
- Application
- true
- v140
- MultiByte
-
-
- Application
- false
- v140
- true
- MultiByte
-
Application
true
- v140
+ v141
MultiByte
@@ -442,21 +461,6 @@
-
-
- TurnOffAllWarnings
- Disabled
- false
- $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)
- %(AdditionalOptions)
-
-
- true
- $(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)
- lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)
-
-
TurnOffAllWarnings
@@ -476,24 +480,6 @@
NotSet
-
-
- TurnOffAllWarnings
- MaxSpeed
- true
- true
- false
- _CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)
- $(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)
-
-
- true
- true
- true
- $(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)
- lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)
-
-
TurnOffAllWarnings
diff --git a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters
index dbc6aef..a6ce3b7 100644
--- a/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters
+++ b/Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/win/ovpn3-core.vcxproj.filters
@@ -1,10 +1,6 @@
-