mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-02-11 00:00:08 +08:00
Merge branch 'release/0.2.0'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<string>0.2.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
4
NOTICE
4
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
21
README.md
21
README.md
@@ -33,7 +33,7 @@ To install OpenVPNAdapter with Cocoapods, add the following lines to your `Podfi
|
||||
```ruby
|
||||
target 'Your Target Name' do
|
||||
use_frameworks!
|
||||
pod 'OpenVPNAdapter', :git => '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:
|
||||
|
||||
@@ -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_completion<ConnectHandler,
|
||||
@@ -1741,6 +1743,11 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
// optional user code hook immediately after socket open in async_connect
|
||||
virtual void async_connect_post_open(const protocol_type& protocol, asio::error_code& ec)
|
||||
{
|
||||
}
|
||||
|
||||
// Disallow copying and assignment.
|
||||
basic_socket(const basic_socket&) ASIO_DELETED;
|
||||
basic_socket& operator=(const basic_socket&) ASIO_DELETED;
|
||||
|
||||
@@ -3338,6 +3338,23 @@ asio::error_code getaddrinfo(const char* host,
|
||||
# endif
|
||||
#elif !defined(ASIO_HAS_GETADDRINFO)
|
||||
int error = getaddrinfo_emulation(host, service, &hints, result);
|
||||
return ec = translate_addrinfo_error(error);
|
||||
#elif defined(ASIO_HAS_GETADDRINFO) && defined(ASIO_APPLE_NAT64)
|
||||
// For NAT64 compatibility, Apple recommends to set AI_DEFAULT flags
|
||||
addrinfo_type new_hints = hints;
|
||||
new_hints.ai_flags |= AI_DEFAULT;
|
||||
int error = ::getaddrinfo(host, service, &new_hints, result);
|
||||
|
||||
// iOS bug workaround: sometimes iOS getaddrinfo() returns a non-zero scope ID
|
||||
// for non-link-local addresses. Workaround by forcing scope ID to 0 for
|
||||
// non-link-local addresses.
|
||||
if (!error && (*result)->ai_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);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#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 <typename Random>
|
||||
void randomize(Random& r)
|
||||
{
|
||||
std::shuffle(this->values_->begin(), this->values_->end(), r);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
|
||||
};
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -557,7 +557,8 @@ namespace openvpn {
|
||||
init_headroom(headroom);
|
||||
}
|
||||
|
||||
void append(const BufferType& other)
|
||||
template <typename B>
|
||||
void append(const B& other)
|
||||
{
|
||||
write(other.c_data(), other.size());
|
||||
}
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_H
|
||||
#define OPENVPN_CLIENT_ASYNC_RESOLVE_H
|
||||
|
||||
#ifdef USE_ASIO
|
||||
#include <openvpn/client/async_resolve/asio.hpp>
|
||||
#else
|
||||
#include <openvpn/client/async_resolve/generic.hpp>
|
||||
#endif
|
||||
|
||||
// create shortcuts for common templated classes
|
||||
namespace openvpn {
|
||||
typedef AsyncResolvable<openvpn_io::ip::udp::resolver> AsyncResolvableUDP;
|
||||
typedef AsyncResolvable<openvpn_io::ip::tcp::resolver> AsyncResolvableTCP;
|
||||
}
|
||||
|
||||
#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_H */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
|
||||
#define OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H
|
||||
|
||||
#include <openvpn/io/io.hpp>
|
||||
#include <openvpn/asio/asiowork.hpp>
|
||||
|
||||
#include <openvpn/common/bigmutex.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/hostport.hpp>
|
||||
|
||||
|
||||
namespace openvpn {
|
||||
template<typename RESOLVER_TYPE>
|
||||
class AsyncResolvable: public virtual RC<thread_unsafe_refcount>
|
||||
{
|
||||
private:
|
||||
typedef RCPtr<AsyncResolvable> Ptr;
|
||||
|
||||
openvpn_io::io_context& io_context;
|
||||
|
||||
class ResolveThread : public RC<thread_safe_refcount>
|
||||
{
|
||||
friend class AsyncResolvable<RESOLVER_TYPE>;
|
||||
|
||||
private:
|
||||
typedef RCPtr<ResolveThread> Ptr;
|
||||
|
||||
std::unique_ptr<AsioWork> asio_work;
|
||||
openvpn_io::io_context& io_context;
|
||||
AsyncResolvable<RESOLVER_TYPE> *resolvable;
|
||||
|
||||
ResolveThread(openvpn_io::io_context &io_context_arg,
|
||||
AsyncResolvable<RESOLVER_TYPE> *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 */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H
|
||||
#define OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H
|
||||
|
||||
#include <openvpn/common/bigmutex.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/hostport.hpp>
|
||||
|
||||
|
||||
namespace openvpn {
|
||||
template<typename RESOLVER_TYPE>
|
||||
class AsyncResolvable: public virtual RC<thread_unsafe_refcount>
|
||||
{
|
||||
private:
|
||||
typedef RCPtr<AsyncResolvable> 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 */
|
||||
@@ -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<SSLLib::CryptoAPI>());
|
||||
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>());
|
||||
cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
|
||||
cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>());
|
||||
cp->ssl_factory = cc->new_factory();
|
||||
cp->load(opt, *proto_context_options, config.default_key_direction, false);
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <openvpn/common/count.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
#include <openvpn/common/base64.hpp>
|
||||
#include <openvpn/ip/ptb.hpp>
|
||||
#include <openvpn/tun/client/tunbase.hpp>
|
||||
#include <openvpn/transport/client/transbase.hpp>
|
||||
#include <openvpn/transport/client/relay.hpp>
|
||||
@@ -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;
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <thread>
|
||||
|
||||
#include <openvpn/io/io.hpp>
|
||||
#include <openvpn/asio/asiowork.hpp>
|
||||
|
||||
#include <openvpn/common/bigmutex.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/options.hpp>
|
||||
@@ -45,6 +48,7 @@
|
||||
#include <openvpn/transport/protocol.hpp>
|
||||
#include <openvpn/client/cliconstants.hpp>
|
||||
#include <openvpn/log/sessionstats.hpp>
|
||||
#include <openvpn/client/async_resolve.hpp>
|
||||
|
||||
#if OPENVPN_DEBUG_REMOTELIST >= 1
|
||||
#define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x)
|
||||
@@ -53,7 +57,6 @@
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class RemoteList : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
// 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<thread_unsafe_refcount>
|
||||
class PreResolve : public virtual RC<thread_unsafe_refcount>, AsyncResolvableTCP
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<PreResolve> 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;
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <openvpn/common/extern.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace bigmutex {
|
||||
OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex;
|
||||
}
|
||||
|
||||
|
||||
#ifdef OPENVPN_ENABLE_BIGMUTEX
|
||||
#define OPENVPN_ASYNC_HANDLER \
|
||||
std::lock_guard<std::recursive_mutex> lg(bigmutex::the_recursive_mutex);
|
||||
|
||||
@@ -19,25 +19,13 @@
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_COMMON_ENDIAN_H
|
||||
#define OPENVPN_COMMON_ENDIAN_H
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
|
||||
// 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 <openvpn/common/endian_platform.hpp>
|
||||
|
||||
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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
|
||||
// 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
|
||||
@@ -32,18 +32,88 @@ namespace openvpn {
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
inline int find_first_set(unsigned int v)
|
||||
template <typename T>
|
||||
inline constexpr int n_bits_type()
|
||||
{
|
||||
return sizeof(T) * 8;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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<unsigned int>(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<unsigned int>(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<unsigned long>(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<unsigned long>(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<unsigned long long>(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<unsigned long long>(v));
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
#error atomic file methods not supported on Windows
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // for rename()
|
||||
#include <stdio.h> // for rename()
|
||||
#include <unistd.h> // for unlink()
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@
|
||||
#include "json/json.h" // JsonCpp library
|
||||
#elif defined(HAVE_OPENVPN_COMMON)
|
||||
#define HAVE_JSON
|
||||
#define OPENVPN_JSON_INTERNAL
|
||||
#include <openvpn/common/json.hpp> // internal OpenVPN JSON implementation
|
||||
#endif
|
||||
|
||||
@@ -28,8 +28,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/platform.hpp>
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
@@ -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('.');
|
||||
|
||||
@@ -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<ServerThread*> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef OPENVPN_VERSION
|
||||
#define OPENVPN_VERSION "3.git:master"
|
||||
#define OPENVPN_VERSION "3.2 (qa:d87f5bbc04)"
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,16 @@
|
||||
#include <openvpn/common/pthreadcond.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
#ifdef HAVE_VALGRIND
|
||||
static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 300;
|
||||
#else
|
||||
static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 30;
|
||||
#endif
|
||||
|
||||
template <typename THREAD_COMMON>
|
||||
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))
|
||||
|
||||
@@ -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 <typename CRYPTO_API>
|
||||
const size_t TLSCrypt<CRYPTO_API>::head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
|
||||
|
||||
// OvpnHMAC wrapper API using dynamic polymorphism
|
||||
|
||||
class TLSCryptInstance : public RC<thread_unsafe_refcount>
|
||||
@@ -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<thread_unsafe_refcount>
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Classes for handling OpenVPN tls-crypt-v2 internals
|
||||
|
||||
#ifndef OPENVPN_CRYPTO_TLS_CRYPT_V2_H
|
||||
#define OPENVPN_CRYPTO_TLS_CRYPT_V2_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/crypto/static_key.hpp>
|
||||
#include <openvpn/crypto/tls_crypt.hpp>
|
||||
#include <openvpn/ssl/sslchoose.hpp>
|
||||
|
||||
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<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<TLSCryptMetadata> 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<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef RCPtr<TLSCryptMetadataFactory> 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 */
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -93,7 +93,6 @@ namespace openvpn {
|
||||
|
||||
public:
|
||||
enum status {
|
||||
undefined,
|
||||
pending,
|
||||
fail,
|
||||
success,
|
||||
|
||||
@@ -59,10 +59,6 @@ namespace openvpn {
|
||||
{
|
||||
base64_uninit_static();
|
||||
}
|
||||
|
||||
private:
|
||||
// initialize SSL library
|
||||
crypto_init crypto_init_;
|
||||
};
|
||||
|
||||
// process-wide singular instance
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// IP checksum based on Linux kernel implementation
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <openvpn/common/endian.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/common/size.hpp>
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
#include <openvpn/ip/ipcommon.hpp>
|
||||
#include <openvpn/ip/icmp4.hpp>
|
||||
#include <openvpn/ip/csum.hpp>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/addr/ipv6.hpp>
|
||||
#include <openvpn/ip/ipcommon.hpp>
|
||||
#include <openvpn/ip/icmp6.hpp>
|
||||
#include <openvpn/ip/csum.hpp>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Generates ICMP "packet too big" response
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/ip/csum.hpp>
|
||||
#include <openvpn/ip/ip4.hpp>
|
||||
#include <openvpn/ip/ip6.hpp>
|
||||
#include <openvpn/ip/icmp4.hpp>
|
||||
#include <openvpn/ip/icmp6.hpp>
|
||||
#include <openvpn/ip/ping6.hpp>
|
||||
#include <openvpn/ip/ipcommon.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/endian.hpp>
|
||||
#include <openvpn/ip/ipcommon.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/debug.h>
|
||||
#include <mbedtls/asn1.h>
|
||||
#include <mbedtls/version.h>
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
@@ -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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Wrap the mbedTLS PEM API defined in <mbedtls/pem.h> 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 <mbedtls/pem.h>
|
||||
|
||||
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 */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Find default gateways on Linux using ip route command
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
#include <openvpn/addr/ipv6.hpp>
|
||||
#include <openvpn/tun/linux/client/sitnl.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Wrap the OpenSSL PEM API defined in <openssl/pem.h> 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 <openvpn/openssl/util/error.hpp>
|
||||
|
||||
#include <openssl/pem.h>
|
||||
|
||||
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 */
|
||||
@@ -422,6 +422,8 @@ namespace openvpn {
|
||||
}
|
||||
if (d == "tls-crypt")
|
||||
return true;
|
||||
if (d == "tls-crypt-v2")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/buffer/safestr.hpp>
|
||||
#include <openvpn/buffer/bufcomposed.hpp>
|
||||
#include <openvpn/ip/ip4.hpp>
|
||||
#include <openvpn/ip/ip6.hpp>
|
||||
#include <openvpn/ip/udp.hpp>
|
||||
#include <openvpn/ip/tcp.hpp>
|
||||
#include <openvpn/time/time.hpp>
|
||||
#include <openvpn/time/durhelper.hpp>
|
||||
#include <openvpn/frame/frame.hpp>
|
||||
@@ -57,6 +61,7 @@
|
||||
#include <openvpn/crypto/cipher.hpp>
|
||||
#include <openvpn/crypto/ovpnhmac.hpp>
|
||||
#include <openvpn/crypto/tls_crypt.hpp>
|
||||
#include <openvpn/crypto/tls_crypt_v2.hpp>
|
||||
#include <openvpn/crypto/packet_id.hpp>
|
||||
#include <openvpn/crypto/static_key.hpp>
|
||||
#include <openvpn/crypto/bs64_data_limit.hpp>
|
||||
@@ -65,6 +70,8 @@
|
||||
#include <openvpn/ssl/psid.hpp>
|
||||
#include <openvpn/ssl/tlsprf.hpp>
|
||||
#include <openvpn/ssl/datalimit.hpp>
|
||||
#include <openvpn/ssl/mssparms.hpp>
|
||||
#include <openvpn/transport/mssfix.hpp>
|
||||
#include <openvpn/transport/protocol.hpp>
|
||||
#include <openvpn/tun/layer.hpp>
|
||||
#include <openvpn/tun/tunmtu.hpp>
|
||||
@@ -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<KeyContext> 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;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <openvpn/openssl/crypto/api.hpp>
|
||||
#include <openvpn/openssl/ssl/sslctx.hpp>
|
||||
#include <openvpn/openssl/util/rand.hpp>
|
||||
#include <openvpn/openssl/util/pem.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef USE_APPLE_SSL
|
||||
@@ -46,6 +47,7 @@
|
||||
#ifdef OPENVPN_PLATFORM_UWP
|
||||
#include <openvpn/mbedtls/util/uwprand.hpp>
|
||||
#endif
|
||||
#include <openvpn/mbedtls/util/pem.hpp>
|
||||
#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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/time/asiotimer.hpp>
|
||||
|
||||
// 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 <typename F>
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace openvpn {
|
||||
{}
|
||||
};
|
||||
|
||||
class Client : public TransportClient
|
||||
class Client : public TransportClient, AsyncResolvableTCP
|
||||
{
|
||||
typedef RCPtr<Client> 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;
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace openvpn {
|
||||
{}
|
||||
};
|
||||
|
||||
class Client : public TransportClient
|
||||
class Client : public TransportClient, AsyncResolvableTCP
|
||||
{
|
||||
typedef RCPtr<Client> 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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace openvpn {
|
||||
{}
|
||||
};
|
||||
|
||||
class Client : public TransportClient
|
||||
class Client : public TransportClient, AsyncResolvableUDP
|
||||
{
|
||||
typedef RCPtr<Client> 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;
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/ip/ipcommon.hpp>
|
||||
#include <openvpn/ip/ip4.hpp>
|
||||
#include <openvpn/ip/ip6.hpp>
|
||||
#include <openvpn/ip/tcp.hpp>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
#ifndef OPENVPN_TRANSPORT_SOCKET_PROTECT_H
|
||||
#define OPENVPN_TRANSPORT_SOCKET_PROTECT_H
|
||||
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#ifdef OPENVPN_PLATFORM_UWP
|
||||
#include <openvpn/transport/uwp_socket_protect.hpp>
|
||||
#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
|
||||
|
||||
@@ -342,7 +342,7 @@ namespace openvpn {
|
||||
{
|
||||
try {
|
||||
if (defined())
|
||||
URL::Parse(url);
|
||||
(URL::Parse(url));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 <antonio@openvpn.net>
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
#include <openvpn/addr/ipv6.hpp>
|
||||
#include <openvpn/addr/route.hpp>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,15 @@
|
||||
#include <openvpn/tun/builder/setup.hpp>
|
||||
#include <openvpn/tun/tunio.hpp>
|
||||
#include <openvpn/tun/persist/tunpersist.hpp>
|
||||
|
||||
// check if Netlink has been selected at compile time
|
||||
#ifdef OPENVPN_USE_SITNL
|
||||
#include <openvpn/tun/linux/client/tunnetlink.hpp>
|
||||
#define TUN_LINUX TunNetlink
|
||||
#else
|
||||
#include <openvpn/tun/linux/client/tunsetup.hpp>
|
||||
#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<Client*> 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:
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
|
||||
#include <openvpn/netconf/linux/gwnetlink.hpp>
|
||||
#include <openvpn/common/action.hpp>
|
||||
#include <openvpn/tun/linux/client/sitnl.hpp>
|
||||
#include <openvpn/tun/client/tunbase.hpp>
|
||||
|
||||
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<NetlinkLinkSet> 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<NetlinkAddr4> 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<NetlinkAddr6> 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<NetlinkAddr4PtP> 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<NetlinkRoute4> 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<NetlinkRoute6> 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<IP::Route>* 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<IP::Route>* 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<IP::Route>* 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<IP::Route>* 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<Setup> 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 *>(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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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' \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
51
Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/update-copyright
Executable file
51
Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/scripts/update-copyright
Executable file
@@ -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 <davids@openvpn.net>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# Basic shell sanity
|
||||
set -eu
|
||||
|
||||
# Simple argument control
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <New Copyright Year>"
|
||||
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
|
||||
@@ -80,6 +80,10 @@
|
||||
#include <openvpn/win/console.hpp>
|
||||
#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> 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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ClientCryptoAPI>());
|
||||
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<ClientCryptoAPI>());
|
||||
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<ServerCryptoAPI>());
|
||||
#if defined(USE_TLS_CRYPT)
|
||||
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
|
||||
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<ClientCryptoAPI>());
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -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-----
|
||||
@@ -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-----
|
||||
@@ -1,143 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid>
|
||||
<RootNamespace>unittests</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="test_log.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid>
|
||||
<RootNamespace>unittests</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="test_log.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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)):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
@@ -18,9 +10,6 @@
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test\ovpncli\cli.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\client\ovpncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\addrlist.hpp" />
|
||||
@@ -31,6 +20,8 @@
|
||||
<ClInclude Include="..\openvpn\addr\ipv6.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\macaddr.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\pool.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\quoteip.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\randaddr.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\range.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\regex.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\route.hpp" />
|
||||
@@ -62,6 +53,7 @@
|
||||
<ClInclude Include="..\openvpn\asio\asiocontext.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asioerr.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiopolysock.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asioresolverres.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiosignal.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiostop.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiowork.hpp" />
|
||||
@@ -81,6 +73,7 @@
|
||||
<ClInclude Include="..\openvpn\buffer\bufread.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\bufstr.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\bufstream.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\lz4.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\memq.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\safestr.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\zlib.hpp" />
|
||||
@@ -101,12 +94,14 @@
|
||||
<ClInclude Include="..\openvpn\common\abort.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\action.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\actionthread.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\appversion.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\arch.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\argv.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\arraysize.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\asyncsleep.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\autoreset.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\base64.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\bigmutex.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\binprefix.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\circ_list.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\cleanup.hpp" />
|
||||
@@ -134,17 +129,19 @@
|
||||
<ClInclude Include="..\openvpn\common\hostlist.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\hostname.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\hostport.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\inotify.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\jsonlib.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\lex.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\likely.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\link.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\logrotate.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\memneq.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\mode.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\modstat.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\msgwin.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\number.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\olong.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\options.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\option_error.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\ostream.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\path.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\peercred.hpp" />
|
||||
@@ -182,6 +179,7 @@
|
||||
<ClInclude Include="..\openvpn\common\usecount.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\usergroup.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\userpass.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\valgrind.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\version.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\waitbarrier.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\write.hpp" />
|
||||
@@ -210,6 +208,9 @@
|
||||
<ClInclude Include="..\openvpn\crypto\packet_id.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\selftest.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\static_key.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\tls_crypt.hpp" />
|
||||
<ClInclude Include="..\openvpn\dco\dcocli.hpp" />
|
||||
<ClInclude Include="..\openvpn\dco\ipcollbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\error\error.hpp" />
|
||||
<ClInclude Include="..\openvpn\error\excode.hpp" />
|
||||
<ClInclude Include="..\openvpn\frame\frame.hpp" />
|
||||
@@ -226,21 +227,39 @@
|
||||
<ClInclude Include="..\openvpn\http\urlencode.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\urlparm.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\urlparse.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\validate_uri.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\webexcept.hpp" />
|
||||
<ClInclude Include="..\openvpn\init\cryptoinit.hpp" />
|
||||
<ClInclude Include="..\openvpn\init\engineinit.hpp" />
|
||||
<ClInclude Include="..\openvpn\init\initprocess.hpp" />
|
||||
<ClInclude Include="..\openvpn\io\io.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\csum.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\dhcp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\eth.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ipcommon.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ping4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ping6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ptb.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\tcp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\udp.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kocrypto.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kodev.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\korekey.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\koroute.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kostats.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kovpn.hpp" />
|
||||
<ClInclude Include="..\openvpn\legal\copyright.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\core.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\daemon_alive.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\procfs.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbasesimple.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbasesimplemac.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logdatetime.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\lognull.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logperiod.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logsimple.hpp" />
|
||||
@@ -298,6 +317,7 @@
|
||||
<ClInclude Include="..\openvpn\proxy\proxyauth.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\devurand.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\mtrandapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\rand2.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\randapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\randbytestore.hpp" />
|
||||
<ClInclude Include="..\openvpn\reliable\relack.hpp" />
|
||||
@@ -325,6 +345,7 @@
|
||||
<ClInclude Include="..\openvpn\ssl\sslapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\sslchoose.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\sslconsts.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\ssllog.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tlsprf.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tlsver.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" />
|
||||
@@ -332,9 +353,12 @@
|
||||
<ClInclude Include="..\openvpn\time\asiotimer.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\coarsetime.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\durhelper.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\epoch.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\time.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\timestr.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\altproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\extern\config.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\extern\fw.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\httpcli.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\relay.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" />
|
||||
@@ -342,6 +366,7 @@
|
||||
<ClInclude Include="..\openvpn\transport\client\udpcli.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\dco.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\gremlin.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\mssfix.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\mutate.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\pktstream.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\protocol.hpp" />
|
||||
@@ -349,6 +374,8 @@
|
||||
<ClInclude Include="..\openvpn\transport\server\transbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\socket_protect.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplink.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplinkbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplinkcommon.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\udplink.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\builder\base.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\builder\capture.hpp" />
|
||||
@@ -365,13 +392,15 @@
|
||||
<ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\layer.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\client\tuncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\tun.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\client\tunsetup.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\client\tuncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\client\tunsetup.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\dsdict.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\gwv4.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macdns.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macgw.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\tunutil.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\utun.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" />
|
||||
@@ -402,30 +431,20 @@
|
||||
<ClInclude Include="..\openvpn\win\unicode.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\winerr.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test\ovpncli\cli.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{1F891260-2039-494F-9777-EC5166AF31BC}</ProjectGuid>
|
||||
<RootNamespace>ovpn3core</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>cli</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
@@ -442,21 +461,6 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
@@ -476,24 +480,6 @@
|
||||
<ShowProgress>NotSet</ShowProgress>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test\ovpncli\cli.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\client\ovpncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\addrlist.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\addrpair.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\ip.hpp" />
|
||||
@@ -13,6 +9,8 @@
|
||||
<ClInclude Include="..\openvpn\addr\ipv6.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\macaddr.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\pool.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\quoteip.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\randaddr.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\range.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\regex.hpp" />
|
||||
<ClInclude Include="..\openvpn\addr\route.hpp" />
|
||||
@@ -44,6 +42,7 @@
|
||||
<ClInclude Include="..\openvpn\asio\asiocontext.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asioerr.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiopolysock.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asioresolverres.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiosignal.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiostop.hpp" />
|
||||
<ClInclude Include="..\openvpn\asio\asiowork.hpp" />
|
||||
@@ -63,6 +62,7 @@
|
||||
<ClInclude Include="..\openvpn\buffer\bufread.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\bufstr.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\bufstream.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\lz4.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\memq.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\safestr.hpp" />
|
||||
<ClInclude Include="..\openvpn\buffer\zlib.hpp" />
|
||||
@@ -83,12 +83,14 @@
|
||||
<ClInclude Include="..\openvpn\common\abort.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\action.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\actionthread.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\appversion.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\arch.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\argv.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\arraysize.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\asyncsleep.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\autoreset.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\base64.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\bigmutex.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\binprefix.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\circ_list.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\cleanup.hpp" />
|
||||
@@ -116,17 +118,19 @@
|
||||
<ClInclude Include="..\openvpn\common\hostlist.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\hostname.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\hostport.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\inotify.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\jsonlib.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\lex.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\likely.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\link.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\logrotate.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\memneq.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\mode.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\modstat.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\msgwin.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\number.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\olong.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\options.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\option_error.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\ostream.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\path.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\peercred.hpp" />
|
||||
@@ -164,6 +168,7 @@
|
||||
<ClInclude Include="..\openvpn\common\usecount.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\usergroup.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\userpass.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\valgrind.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\version.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\waitbarrier.hpp" />
|
||||
<ClInclude Include="..\openvpn\common\write.hpp" />
|
||||
@@ -192,6 +197,9 @@
|
||||
<ClInclude Include="..\openvpn\crypto\packet_id.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\selftest.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\static_key.hpp" />
|
||||
<ClInclude Include="..\openvpn\crypto\tls_crypt.hpp" />
|
||||
<ClInclude Include="..\openvpn\dco\dcocli.hpp" />
|
||||
<ClInclude Include="..\openvpn\dco\ipcollbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\error\error.hpp" />
|
||||
<ClInclude Include="..\openvpn\error\excode.hpp" />
|
||||
<ClInclude Include="..\openvpn\frame\frame.hpp" />
|
||||
@@ -208,6 +216,7 @@
|
||||
<ClInclude Include="..\openvpn\http\urlencode.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\urlparm.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\urlparse.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\validate_uri.hpp" />
|
||||
<ClInclude Include="..\openvpn\http\webexcept.hpp" />
|
||||
<ClInclude Include="..\openvpn\init\cryptoinit.hpp" />
|
||||
<ClInclude Include="..\openvpn\init\engineinit.hpp" />
|
||||
@@ -215,14 +224,26 @@
|
||||
<ClInclude Include="..\openvpn\io\io.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\dhcp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\eth.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ipcommon.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\udp.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kocrypto.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kodev.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\korekey.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\koroute.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kostats.hpp" />
|
||||
<ClInclude Include="..\openvpn\kovpn\kovpn.hpp" />
|
||||
<ClInclude Include="..\openvpn\legal\copyright.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\core.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\daemon_alive.hpp" />
|
||||
<ClInclude Include="..\openvpn\linux\procfs.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbasesimple.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logbasesimplemac.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logdatetime.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\lognull.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logperiod.hpp" />
|
||||
<ClInclude Include="..\openvpn\log\logsimple.hpp" />
|
||||
@@ -280,6 +301,7 @@
|
||||
<ClInclude Include="..\openvpn\proxy\proxyauth.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\devurand.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\mtrandapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\rand2.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\randapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\random\randbytestore.hpp" />
|
||||
<ClInclude Include="..\openvpn\reliable\relack.hpp" />
|
||||
@@ -307,6 +329,7 @@
|
||||
<ClInclude Include="..\openvpn\ssl\sslapi.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\sslchoose.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\sslconsts.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\ssllog.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tlsprf.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tlsver.hpp" />
|
||||
<ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" />
|
||||
@@ -314,9 +337,12 @@
|
||||
<ClInclude Include="..\openvpn\time\asiotimer.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\coarsetime.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\durhelper.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\epoch.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\time.hpp" />
|
||||
<ClInclude Include="..\openvpn\time\timestr.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\altproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\extern\config.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\extern\fw.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\httpcli.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\relay.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" />
|
||||
@@ -331,6 +357,8 @@
|
||||
<ClInclude Include="..\openvpn\transport\server\transbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\socket_protect.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplink.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplinkbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\tcplinkcommon.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\udplink.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\builder\base.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\builder\capture.hpp" />
|
||||
@@ -347,18 +375,21 @@
|
||||
<ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\layer.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\client\tuncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\tun.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\linux\client\tunsetup.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\client\tuncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\client\tunsetup.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\dsdict.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\gwv4.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macdns.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macgw.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\macproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\tunutil.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\mac\utun.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\persist\tunwrap.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\persist\tunwrapasio.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\proxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\server\tunbase.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\tunio.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\tunlog.hpp" />
|
||||
@@ -370,10 +401,12 @@
|
||||
<ClInclude Include="..\openvpn\tun\win\nrpt.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\win\tunutil.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\win\wfp.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\win\winproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\call.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\cmd.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\console.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\handle.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\impersonate.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\modname.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\reg.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\scoped_handle.hpp" />
|
||||
@@ -383,5 +416,20 @@
|
||||
<ClInclude Include="..\openvpn\tun\win\winproxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\tun\proxy.hpp" />
|
||||
<ClInclude Include="..\openvpn\win\impersonate.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\icmp6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ip6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ipcommon.hpp" />
|
||||
<ClInclude Include="..\client\ovpncli.hpp" />
|
||||
<ClInclude Include="..\openvpn\transport\mssfix.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\tcp.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ptb.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ping4.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\ping6.hpp" />
|
||||
<ClInclude Include="..\openvpn\ip\csum.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test\ovpncli\cli.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -76,6 +76,7 @@
|
||||
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
|
||||
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
|
||||
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
|
||||
@"TLS_CRYPT_META_FAIL": @(OpenVPNAdapterErrorTLSCryptMetaFail),
|
||||
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
|
||||
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
|
||||
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
|
||||
@@ -152,6 +153,7 @@
|
||||
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
|
||||
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
|
||||
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed.";
|
||||
case OpenVPNAdapterErrorTLSCryptMetaFail: return @"tls-crypt-v2 metadata verification failed.";
|
||||
case OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
|
||||
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
|
||||
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user