34 Commits
0.1.0 ... 0.2.0

Author SHA1 Message Date
Sergey Abramchuk
36de2fc09c Merge branch 'release/0.2.0' 2019-04-10 12:21:10 +03:00
Sergey Abramchuk
45723d7ee1 Delete outdated revisions 2019-04-10 12:18:05 +03:00
Sergey Abramchuk
f3caddf509 Update Acknowledgments section 2019-04-10 12:16:40 +03:00
Sergey Abramchuk
f0844e998f Update Usage section 2019-04-10 12:14:04 +03:00
Sergey Abramchuk
208d87f258 Fix typos 2019-04-10 12:02:56 +03:00
Sergey Abramchuk
b38a8050e0 Update version in Cocoapods section 2019-04-10 12:02:42 +03:00
Sergey Abramchuk
7b2320fbe3 Update podspec 2019-04-10 11:59:05 +03:00
Sergey Abramchuk
9eac433665 Bump version number 2019-04-10 11:53:08 +03:00
Sergey Abramchuk
b00951ceae Update project settings 2019-04-10 11:50:13 +03:00
Sergey Abramchuk
bd98a18fb3 Merge branch 'feature/reset-tunnel' into develop 2019-03-18 13:16:17 +03:00
Sergey Abramchuk
4e2bb966c2 Merge branch 'develop' into feature/reset-tunnel
* develop:
  Fix incorrect architecture of libraries
2019-03-18 11:21:31 +03:00
Sergey Abramchuk
6766fb52f9 Fix incorrect architecture of libraries 2019-03-18 11:21:23 +03:00
Sergey Abramchuk
74f56bf680 Merge branch 'develop' into feature/reset-tunnel
* develop:
  Explicitly set the define to use <string_view>
  Apply asio patches
  Squashed 'Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/' changes from 934f4e741f..daf575ff50
2019-03-15 12:54:45 +03:00
Sergey Abramchuk
aa67ea253f Merge branch 'feature/update-dependencies' into develop 2019-03-15 12:53:18 +03:00
Sergey Abramchuk
9686d3295a Explicitly set the define to use <string_view> 2019-03-15 12:23:15 +03:00
Sergey Abramchuk
a58d48b88b Apply asio patches 2019-03-15 12:20:19 +03:00
Sergey Abramchuk
9243263fcd Merge commit 'e9b9b66317298258a27ad20c5a4ed7cac300acaa' into feature/update-dependencies 2019-03-15 11:55:16 +03:00
Sergey Abramchuk
e9b9b66317 Squashed 'Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/' changes from 934f4e741f..daf575ff50
daf575ff50 Merge remote-tracking branch 'origin/qa'
e3a2425be4 [UCONNECT-1027] remotelist: create standalone object for resolve thread
e487b75860 async-resolve: use native GCD implementation on iOS
346ed043fa Merge remote-tracking branch 'origin/qa'
3f55dcd266 remotelist: add missing includes
073b3993f4 Fix commit 8b22a7b2 (mbed TLS compatibility)
8b22a7b209 Fix compatibility with mbed TLS < 2.7.0

git-subtree-dir: Sources/OpenVPNAdapter/Libraries/Vendors/openvpn
git-subtree-split: daf575ff5099eebb10109e52be94253507fd253b
2019-03-15 11:55:16 +03:00
Sergey Abramchuk
9b51c260a1 Clear out tunPersist mentions 2019-02-24 16:10:45 +03:00
Sergey Abramchuk
4889f3b8cd Delete tunPersist property because tun builder doesn't use this option 2019-02-24 16:08:24 +03:00
Sergey Abramchuk
399ce8435d Reset tunnel on disconnect 2019-02-24 16:06:24 +03:00
Sergey Abramchuk
e7084c56c6 Merge commit 'ed98f2568b15d5548ef8f373b45a3f7078ce7a7e' into feature/update-dependencies 2019-02-24 15:02:57 +03:00
Sergey Abramchuk
ed98f2568b Squashed 'Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/' changes from 6608878d5..934f4e741
934f4e741 Merge remote-tracking branch 'origin/qa'
8c87c7696 [UCONNECT-1027] use proper io_context when initializing AsyncResolve class
c3026c65a Merge remote-tracking branch 'origin/qa'
f33fe7665 [UCONNECT-1027] perform async DNS resolution in a detached thread
0c0af6781 [OVPN3-342] Generate ICMP "packet too big" reply
c93af60a7 Move files from ovpn3-common to openvpn3 repo
d5eeb78ed ClientAPI: print core version when starting
04de9c425 Merge branch 'qa'
2c0dbc6c3 buildep.py: add asio patching
600c68012 Allow updating auth-token during session
7391096b9 [OC-85] tunprop: exclude routes for additional remotes also on macOS
3587628d7 [OC-84] tunprop: exclude routes for additional remotes also on Windows
25471635d Revert "[UCONNECT-868] When no network is present pause instead of stopping"
5713ff34a Fixed some breakage caused by recent endian/ffs commits
a9ce44a22 endian.hpp: break out endian compile-time tests to endian_platform.hpp
72181f9e7 [UCONNECT-868] When no network is present pause instead of stopping
10d636cfe version: switch to 3.2

git-subtree-dir: Sources/OpenVPNAdapter/Libraries/Vendors/openvpn
git-subtree-split: 934f4e741f760160dc65a6f4b29af57bb5be8f93
2019-02-24 15:02:57 +03:00
Sergey Abramchuk
72bf0c306d Update lz4 library to version 1.8.3 2019-02-24 15:01:59 +03:00
Sergey Abramchuk
16c2801168 Add retryOnAuthFailed property 2019-01-13 14:30:52 +03:00
Sergey Abramchuk
fa25b668e0 Add port property and test get/set its value 2019-01-13 14:24:25 +03:00
Sergey Abramchuk
b578e282f5 Update client methods and prepare it for remote overriding 2019-01-13 13:56:51 +03:00
Sergey Abramchuk
c514bf7312 Add new events: AUTH_PENDING, WARN, UNSUPPORTED_FEATURE 2019-01-13 13:36:25 +03:00
Sergey Abramchuk
ece80f63a9 Add TLS_CRYPT_META_FAIL error 2019-01-13 13:29:07 +03:00
Sergey Abramchuk
9c09e6f507 Merge commit 'f5fda0fa735dc13c5bd18362133467818921bb1b' into feature/update-dependencies 2019-01-13 13:08:43 +03:00
Sergey Abramchuk
f5fda0fa73 Squashed 'Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/' changes from cc90cde57..6608878d5
6608878d5 [OVPN3-341] implement mssfix support
1bf3fc0e4 win: update project files
f8d209435 travis: update to default osx image: xcode9.4
31eb246a8 travis.yml: align deps version to lib-version
996f86635 RunContext: fixed rebase issue that added two "default: signal_rearm();" clauses
aebea6456 build script: minor changes to Cityhash inclusion
1d754072c modstat: make update_file_mod_time_nanoseconds() a no-op on non-Linux
7974c9867 Fixed some breakage caused by recent endian/ffs commits
a0dd7fe8b endian.hpp: break out endian compile-time tests to endian_platform.hpp
c8bdf5a34 ffs.hpp: support additional numeric types
dcb0c9452 BufferType: append() argument can now be a flexible buffer type
2009a8a25 Added AsioTimerSafe
39e71b7dd event_loop_wait_barrier: use a longer default timeout when running under valgrind
8b7e08e9b string::contains_non_space_ctrl: consider ASCII char 127 (DEL) to be a control char
e43024d7c RunContext: rearm non-terminating signals
6ab379323 write_binary_atomic: remove temporary file on move failure
55dc653cd path: added is_contained()
02bf235c6 Reverted previous commit: "ReplyParser: added undefined status"
84dbc5b9b Allow test/cli.cpp to be used with NetCfg Tunbuilder client
80fed2c55 Allow updating auth-token during session
ad7da751e don't print time in debug message and use OPENVPN_LOG_PROTO_VERBOSE
981407994 tls-crypt-v2: implement abstract metadata parser
be38bbeb8 tls-crypt-v2: test/ssl/proto.cpp - extend protocol test
60fcf374f tls-crypt-v2: implement WKc appending/unwrapping logic
51f4a3a29 tls-crypt-v2: introduce CONTROL_HARD_RESET_V3 packet type
156a6e58b tls-crypt-v2: implement client key parser and renderer
54a97b381 ssl: add support for encoding/decoding PEM format
f090fcda4 tls-crypt: make HMAC API more generic
d87f5bbc0 OpenSSL: init library
2ea88a93b Add Remote endpoint information to protect_socket call
0a081ee17 [OVPN3-315] cli/go: add option to compile SITNL component
5bbfb57c0 [OVPN3-315] TunLinux::Client: allow user to select netlink at compile time
e8458a68e [OVPN3-315] GW: add netlink support
4e77edb9e [OVPN3-315] TunLinux: add Netlink implementation for Tun setup methods
68508fe56 bigmutex: include missing extern.hpp header
a7b923e1e Fix logic inversion from commit 2de9aebc
923e10d13 runcontext: arrange members to allow inheritance
2de9aebc7 Replace deprecated mbedtls_sha1 with mbedtls_sha1_ret
e9c0bd00b Remove unused private field
ee17c33c2 Add virtual deconstructor to TransportClientParent
fab64ba0f Fix clang warning about unused attributes and missing overrides
2624d9ddf Also parse dhcp-option DNS6 as DNS server for compatibility with OpenVPN 2
6d12c9cc2 Refuse external pki with non RSA keys
4a25059f5 test/ovpncli: Don't override PROF env variable
f241c4c5f scripts: Add tool to update copyright years
27beeb03d Update lz4 version to 1.8.3
17e356858 Define DASIO_HAS_STD_STRING_VIEW on Android build
b107fd994 Remove unsupported platforms from Android build
6a200f72e Ensure all Android components are always installed
fbcd374a4 [OVPN3-327] OpenSSL: ensure >TLS1.0 is negotiated by default
d9b1f78b6 JSON: #define OPENVPN_JSON_INTERNAL when internal JSON library is used
39290f19d Fix build issues with #if macro on big-endian hardware
d4f62d9ed Fix instantiating a new URL instead of parsing the URL

git-subtree-dir: Sources/OpenVPNAdapter/Libraries/Vendors/openvpn
git-subtree-split: 6608878d57eec1c64c16c5a13ee65b2cf0418ca1
2019-01-13 13:08:42 +03:00
Sergey Abramchuk
008678734f Use full git path and tag in instruction 2018-10-27 14:06:11 +03:00
Sergey Abramchuk
1e010202f7 Delete comments 2018-10-27 13:14:49 +03:00
Sergey Abramchuk
4d36dbddd1 Merge tag '0.1.0' into develop
no message
2018-10-27 13:12:25 +03:00
110 changed files with 5071 additions and 753 deletions

View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -32,11 +32,8 @@ To install OpenVPNAdapter with Cocoapods, add the following lines to your `Podfi
```ruby
target 'Your Target Name' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for iOSOpenVPNTunnel
pod 'OpenVPNAdapter', '~> 0.1'
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.2.0'
end
```
@@ -56,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
}
@@ -68,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
}
@@ -110,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
}
})
}
@@ -121,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
}
}
```
@@ -250,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)
}
@@ -323,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:

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -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 */

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 \

View File

@@ -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());
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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));
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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('.');

View File

@@ -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;
};
}

View File

@@ -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;
}

View File

@@ -24,5 +24,5 @@
#pragma once
#ifndef OPENVPN_VERSION
#define OPENVPN_VERSION "3.git:master"
#define OPENVPN_VERSION "3.2 (qa:d87f5bbc04)"
#endif

View File

@@ -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))

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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)
{

View File

@@ -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",

View File

@@ -93,7 +93,6 @@ namespace openvpn {
public:
enum status {
undefined,
pending,
fail,
success,

View File

@@ -59,10 +59,6 @@ namespace openvpn {
{
base64_uninit_static();
}
private:
// initialize SSL library
crypto_init crypto_init_;
};
// process-wide singular instance

View File

@@ -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));
}
}
}

View File

@@ -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;
};
};
};
}

View File

@@ -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;
};
};
}

View File

@@ -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;

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
};
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;
};
}

View File

@@ -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);

View File

@@ -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 */

View File

@@ -422,6 +422,8 @@ namespace openvpn {
}
if (d == "tls-crypt")
return true;
if (d == "tls-crypt-v2")
return true;
return false;
}
}

View File

@@ -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:

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
};
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}
}
}
}
}
};
}

View File

@@ -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

View File

@@ -342,7 +342,7 @@ namespace openvpn {
{
try {
if (defined())
URL::Parse(url);
(URL::Parse(url));
}
catch (const std::exception& e)
{

View File

@@ -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");

View File

@@ -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);
}
};
}
}

View File

@@ -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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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/

View File

@@ -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' \

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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-----

View File

@@ -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-----

View File

@@ -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>

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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)):

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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