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=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" LIBRARY_SEARCH_PATHS[sdk=macosx*] = "$(VENDORS_DIR)/lz4/lib/macos" "$(VENDORS_DIR)/mbedtls/lib/macos"
OTHER_LDFLAGS = -lmbedtls -lmbedx509 -lmbedcrypto -llz4 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 GCC_WARN_64_TO_32_BIT_CONVERSION = NO

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.1.0</string> <string>0.2.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key> <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 Dependency: https://github.com/OpenVPN/openvpn3
Revision: 3e002c83ce2e9f9f40ddcee750d3cfa664238abe
License type: GNU Affero General Public License - Version 3.0 License type: GNU Affero General Public License - Version 3.0
-------------------------------------------------------------------- --------------------------------------------------------------------
OpenVPN Library 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 Dependency: https://github.com/ARMmbed/mbedtls
Revision: 72ea31b026e1fc61b01662474aa5125817b968bc
License type: Apache License - Version 2.0 License type: Apache License - Version 2.0
-------------------------------------------------------------------- --------------------------------------------------------------------
mbedTLS Library mbedTLS Library
@@ -886,7 +884,6 @@ limitations under the License.
-------------------------------------------------------------------- --------------------------------------------------------------------
Dependency: https://github.com/chriskohlhoff/asio Dependency: https://github.com/chriskohlhoff/asio
Revision: 72ea31b026e1fc61b01662474aa5125817b968bc
License type: Boost Software License - Version 1.0 License type: Boost Software License - Version 1.0
-------------------------------------------------------------------- --------------------------------------------------------------------
ASIO Library ASIO Library
@@ -920,7 +917,6 @@ DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------- --------------------------------------------------------------------
Dependency: https://github.com/lz4/lz4 Dependency: https://github.com/lz4/lz4
Revision: c10863b98e1503af90616ae99725ecd120265dfb
License type: BSD 2-Clause License License type: BSD 2-Clause License
-------------------------------------------------------------------- --------------------------------------------------------------------
LZ4 Library LZ4 Library

View File

@@ -3,7 +3,7 @@ Pod::Spec.new do |s|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.name = "OpenVPNAdapter" 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.summary = "Objective-C wrapper for OpenVPN library. Compatible with iOS and macOS."
s.description = <<-DESC s.description = <<-DESC
OpenVPNAdapter is an Objective-C framework that allows to easily configure and establish VPN connection using OpenVPN protocol. 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 = { openvpn.xcconfig = {
"HEADER_SEARCH_PATHS" => "${PODS_TARGET_SRCROOT}/#{openvpn_path}/**", "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 end

View File

@@ -775,7 +775,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0820; LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 0930; LastUpgradeCheck = 1020;
TargetAttributes = { TargetAttributes = {
C9BB475B1E71663A00F3F98C = { C9BB475B1E71663A00F3F98C = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
@@ -785,7 +785,7 @@
C9BB478D1E71821A00F3F98C = { C9BB478D1E71821A00F3F98C = {
CreatedOnToolsVersion = 8.2.1; CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = 2TWXCGG7R3; DevelopmentTeam = 2TWXCGG7R3;
LastSwiftMigration = 0900; LastSwiftMigration = 1020;
ProvisioningStyle = Manual; ProvisioningStyle = Manual;
}; };
C9D2ABD81EA20F99007EDF9D = { C9D2ABD81EA20F99007EDF9D = {
@@ -793,13 +793,13 @@
}; };
C9D2ABF21EA212A3007EDF9D = { C9D2ABF21EA212A3007EDF9D = {
DevelopmentTeam = 2TWXCGG7R3; DevelopmentTeam = 2TWXCGG7R3;
LastSwiftMigration = 0900; LastSwiftMigration = 1020;
}; };
}; };
}; };
buildConfigurationList = C91030FB1E471D760004DFFE /* Build configuration list for PBXProject "OpenVPNAdapter" */; buildConfigurationList = C91030FB1E471D760004DFFE /* Build configuration list for PBXProject "OpenVPNAdapter" */;
compatibilityVersion = "Xcode 8.0"; compatibilityVersion = "Xcode 8.0";
developmentRegion = English; developmentRegion = en;
hasScannedForEncodings = 0; hasScannedForEncodings = 0;
knownRegions = ( knownRegions = (
en, en,
@@ -1240,7 +1240,7 @@
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0; SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1285,7 +1285,7 @@
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0; SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;
@@ -1437,7 +1437,7 @@
SUPPORTED_PLATFORMS = macosx; SUPPORTED_PLATFORMS = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0; SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -1483,7 +1483,7 @@
SDKROOT = macosx; SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx; SUPPORTED_PLATFORMS = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0; SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;

View File

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

View File

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

View File

@@ -32,11 +32,8 @@ To install OpenVPNAdapter with Cocoapods, add the following lines to your `Podfi
```ruby ```ruby
target 'Your Target Name' do 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! use_frameworks!
pod 'OpenVPNAdapter', :git => 'https://github.com/ss-abramchuk/OpenVPNAdapter.git', :tag => '0.2.0'
# Pods for iOSOpenVPNTunnel
pod 'OpenVPNAdapter', '~> 0.1'
end end
``` ```
@@ -56,7 +53,7 @@ Then we need to create or load a VPN profile. [`NETunnelProviderManager`](https:
```swift ```swift
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
guard error == nil else { guard error == nil else {
// Handle an occured error // Handle an occurred error
return return
} }
@@ -68,7 +65,7 @@ The next step is to provide VPN settings to the instance of [`NETunnelProviderMa
```swift ```swift
self.providerManager?.loadFromPreferences(completionHandler: { (error) in self.providerManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else { guard error == nil else {
// Handle an occured error // Handle an occurred error
return return
} }
@@ -110,7 +107,7 @@ self.providerManager?.loadFromPreferences(completionHandler: { (error) in
// Save configuration in the Network Extension preferences // Save configuration in the Network Extension preferences
self.providerManager?.saveToPreferences(completionHandler: { (error) in self.providerManager?.saveToPreferences(completionHandler: { (error) in
if let error = error { if let error = error {
// Handle an occured error // Handle an occurred error
} }
}) })
} }
@@ -121,14 +118,14 @@ Start VPN by calling the following code.
```swift ```swift
self.providerManager?.loadFromPreferences(completionHandler: { (error) in self.providerManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else { guard error == nil else {
// Handle an occured error // Handle an occurred error
return return
} }
do { do {
try self.providerManager?.connection.startVPNTunnel() try self.providerManager?.connection.startVPNTunnel()
} catch { } catch {
// Handle an occured error // Handle an occurred error
} }
} }
``` ```
@@ -250,7 +247,12 @@ extension PacketTunnelProvider: OpenVPNAdapterDelegate {
// `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so // `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so
// you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and // you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and
// send `self.packetFlow` to `completionHandler` callback. // 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 setTunnelNetworkSettings(settings) { (error) in
completionHandler(error == nil ? self.packetFlow : nil) 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). Any contributions and suggestions are welcome! But before creating a PR or an issue please read the [Contribution Guide](CONTRIBUTING.md).
## Acknowledgments ## 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 ## License
OpenVPNAdapter is available under the AGPLv3 license. See the [LICENSE](LICENSE) file for more info. Also this project has a few dependencies: 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; asio::error_code ec;
const protocol_type protocol = peer_endpoint.protocol(); const protocol_type protocol = peer_endpoint.protocol();
this->get_service().open(this->get_implementation(), protocol, ec); this->get_service().open(this->get_implementation(), protocol, ec);
if (!ec)
async_connect_post_open(protocol, ec);
if (ec) if (ec)
{ {
async_completion<ConnectHandler, async_completion<ConnectHandler,
@@ -1741,6 +1743,11 @@ protected:
} }
private: 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. // Disallow copying and assignment.
basic_socket(const basic_socket&) ASIO_DELETED; basic_socket(const basic_socket&) ASIO_DELETED;
basic_socket& operator=(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 # endif
#elif !defined(ASIO_HAS_GETADDRINFO) #elif !defined(ASIO_HAS_GETADDRINFO)
int error = getaddrinfo_emulation(host, service, &hints, result); 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); return ec = translate_addrinfo_error(error);
#else #else
int error = ::getaddrinfo(host, service, &hints, result); int error = ::getaddrinfo(host, service, &hints, result);

View File

@@ -18,6 +18,7 @@
#include "asio/detail/config.hpp" #include "asio/detail/config.hpp"
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <algorithm>
#include "asio/detail/socket_ops.hpp" #include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
#include "asio/ip/basic_resolver_iterator.hpp" #include "asio/ip/basic_resolver_iterator.hpp"
@@ -299,6 +300,12 @@ public:
return !a.equal(b); return !a.equal(b);
} }
template <typename Random>
void randomize(Random& r)
{
std::shuffle(this->values_->begin(), this->values_->end(), r);
}
private: private:
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
}; };

View File

@@ -1,7 +1,7 @@
/* /*
* LZ4 - Fast LZ compression algorithm * LZ4 - Fast LZ compression algorithm
* Header File * 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) BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@@ -46,7 +46,7 @@ extern "C" {
/** /**
Introduction 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 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. 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), An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md),
take care of encoding standard metadata alongside LZ4-compressed blocks. take care of encoding standard metadata alongside LZ4-compressed blocks.
If your application requires interoperability, it's recommended to use it. Frame format is required for interoperability.
A library is provided to take care of it, see lz4frame.h. It is delivered through a companion API, declared in lz4frame.h.
*/ */
/*^*************************************************************** /*^***************************************************************
@@ -72,24 +72,28 @@ extern "C" {
/* /*
* LZ4_DLL_EXPORT : * LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL * Enable exporting of functions when building a Windows DLL
* LZ4LIB_API : * LZ4LIB_VISIBILITY :
* Control library symbols visibility. * Control library symbols visibility.
*/ */
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) #ifndef LZ4LIB_VISIBILITY
# define LZ4LIB_API __declspec(dllexport) # if defined(__GNUC__) && (__GNUC__ >= 4)
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) # define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
# 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.*/ # else
#elif defined(__GNUC__) && (__GNUC__ >= 4) # define LZ4LIB_VISIBILITY
# define LZ4LIB_API __attribute__ ((__visibility__ ("default"))) # endif
#else #endif
# define LZ4LIB_API #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 #endif
/*------ Version ------*/ /*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */ #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) #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_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) #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 int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; to be used when checking 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 : * LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
* Increasing memory usage improves compression ratio * 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 * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/ */
#ifndef LZ4_MEMORY_USAGE #ifndef LZ4_MEMORY_USAGE
@@ -120,30 +124,29 @@ LZ4LIB_API const char* LZ4_versionString (void); /**< library version string;
* Simple Functions * Simple Functions
**************************************/ **************************************/
/*! LZ4_compress_default() : /*! LZ4_compress_default() :
Compresses 'sourceSize' bytes from buffer 'source' Compresses 'srcSize' bytes from buffer 'src'
into already allocated 'dest' buffer of size 'maxDestSize'. into already allocated 'dst' buffer of size 'dstCapacity'.
Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
It also runs faster, so it's a recommended setting. 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. compression stops *immediately*, and the function result is zero.
As a consequence, 'dest' content is not valid. Note : as a consequence, 'dst' content is not valid.
This function never writes outside 'dest' buffer, nor read outside 'source' buffer. Note 2 : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) dstCapacity : size of buffer 'dst' (which must be already allocated)
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
or 0 if compression fails */ or 0 if compression fails */
LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_safe() : /*! LZ4_decompress_safe() :
compressedSize : is the precise full size of the compressed block. compressedSize : is the exact complete size of the compressed block.
maxDecompressedSize : is the size of destination buffer, which must be already allocated. dstCapacity : is the size of destination buffer, which must be already allocated.
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) 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 (<0). 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. 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. This function is protected against malicious data packets.
It never writes outside output buffer, nor reads outside input buffer.
*/ */
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) 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). 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). 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 inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario 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); LZ4LIB_API int LZ4_compressBound(int inputSize);
/*! /*!
LZ4_compress_fast() : 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. 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. 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() 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. 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, Use LZ4_sizeofState() to know how much memory must be allocated,
and allocate it on 8-bytes boundaries (using malloc() typically). 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_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() :
LZ4_compress_destSize() : * Reverse the logic : compresses as much data as possible from 'src' buffer
Reverse the logic, by compressing as much data as possible from 'source' buffer * into already allocated buffer 'dst', of size >= 'targetDestSize'.
into already allocated buffer 'dest' of size 'targetDestSize'. * This function either compresses the entire 'src' content into 'dst' if it's large enough,
This function either compresses the entire 'source' content into 'dest' if it's large enough, * or fill 'dst' buffer completely with as much data as possible from 'src'.
or fill 'dest' buffer completely with as much data as possible from 'source'. * note: acceleration parameter is fixed to "default".
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'. *
New value is necessarily <= old value. * *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
return : Nb bytes written into 'dest' (necessarily <= targetDestSize) * New value is necessarily <= input value.
or 0 if compression fails * @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() : **unsafe!**
LZ4_decompress_fast() : * This function used to be a bit faster than LZ4_decompress_safe(),
originalSize : is the original and therefore uncompressed size * though situation has changed in recent versions,
return : the number of bytes read from the source buffer (in other words, the compressed size) * and now `LZ4_decompress_safe()` can be as fast and sometimes faster than `LZ4_decompress_fast()`.
If the source stream is detected malformed, the function will stop decoding and return a negative result. * Moreover, LZ4_decompress_fast() is not protected vs malformed input, as it doesn't perform full validation of compressed data.
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes. * As a consequence, this function is no longer recommended, and may be deprecated in future versions.
note : This function fully respect memory boundaries for properly formed compressed data. * It's only remaining specificity is that it can decompress data without knowing its compressed size.
It is a bit faster than LZ4_decompress_safe(). *
However, it does not provide any protection against intentionally modified data stream (malicious input). * originalSize : is the uncompressed size to regenerate.
Use this function in trusted environment only (data to decode comes from a trusted source). * `dst` must be already allocated, its size must be >= 'originalSize' bytes.
*/ * @return : number of bytes read from source buffer (== compressed size).
LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize); * 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() :
LZ4_decompress_safe_partial() : * Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
This function decompress a compressed block of size 'compressedSize' at position 'source' * into destination buffer 'dst' of size 'dstCapacity'.
into destination buffer 'dest' of size 'maxDecompressedSize'. * Up to 'targetOutputSize' bytes will be decoded.
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, * The function stops decoding on reaching this objective,
reducing decompression time. * which can boost performance when only the beginning of a block is required.
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. * @return : the number of bytes decoded in `dst` (necessarily <= dstCapacity)
Always control how many bytes were decoded. * If source stream is detected malformed, function returns a negative result.
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 * Note : @return can be < targetOutputSize, if compressed block contains less data.
*/ *
LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); * 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 * 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() and LZ4_freeStream() :
* LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. * 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() : /*! LZ4_resetStream() :
* An LZ4_stream_t structure can be allocated once and re-used multiple times. * 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); LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
/*! LZ4_loadDict() : /*! 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. * Any previous data will be forgotten, only 'dictionary' will remain in memory.
* Loading a size of 0 is allowed. * Loading a size of 0 is allowed, and is the same as reset.
* Return : dictionary size, in bytes (necessarily <= 64 KB) * @return : dictionary size, in bytes (necessarily <= 64 KB)
*/ */
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_compress_fast_continue() : /*! LZ4_compress_fast_continue() :
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. * Compress 'src' content using data from previously compressed blocks, for better compression ratio.
* Important : Previous data blocks are assumed to remain present and unmodified !
* 'dst' buffer must be already allocated. * 'dst' buffer must be already allocated.
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. * 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); LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_saveDict() : /*! 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). * save it into a safer place (char* safeBuffer).
* Note : it's not necessary to call LZ4_loadDict() after LZ4_saveDict(), dictionary is immediately usable. * This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
* @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. * 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 * Streaming Decompression Functions
* Bufferless synchronous API * 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() : /*! 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 LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
/*! LZ4_setStreamDecode() : /*! LZ4_setStreamDecode() :
* Use this function to instruct where to find the dictionary. * An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
* Setting a size of 0 is allowed (same effect as reset). * Use this function to start decompression of a new stream of blocks.
* @return : 1 if OK, 0 if error * 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); 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() : /*! LZ4_decompress_*_continue() :
* These decoding functions allow decompression of multiple blocks in "streaming" mode. * These decoding functions allow decompression of consecutive blocks in "streaming" mode.
* Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) * A block is an unsplittable entity, it must be presented entirely to a decompression function.
* In the case of a ring buffers, decoding buffer must be either : * Decompression functions only accepts one block at a time.
* - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) * The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
* In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). * If less than 64KB of data has been decoded, all the data must be present.
* - 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. * 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, * 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). * 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, * Whenever these conditions are not possible,
* and encoding ring buffer can have any size, including larger than decoding buffer. * save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
* Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, * then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
* and indicate where it is saved using LZ4_setStreamDecode()
*/ */
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_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* source, char* dest, int originalSize); LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
/*! LZ4_decompress_*_usingDict() : /*! LZ4_decompress_*_usingDict() :
* These decoding functions work the same as * These decoding functions work the same as
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
* They are stand-alone, and don't need an LZ4_streamDecode_t structure. * 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_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* source, char* dest, int originalSize, 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 !!!!!! * !!!!!! 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 * 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 */) #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
#include <stdint.h> #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 hashTable[LZ4_HASH_SIZE_U32];
uint32_t currentOffset; uint32_t currentOffset;
uint32_t initCheck; uint16_t initCheck;
uint16_t tableType;
const uint8_t* dictionary; const uint8_t* dictionary;
uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */ const LZ4_stream_t_internal* dictCtx;
uint32_t dictSize; uint32_t dictSize;
} LZ4_stream_t_internal; };
typedef struct { typedef struct {
const uint8_t* externalDict; const uint8_t* externalDict;
@@ -355,14 +513,16 @@ typedef struct {
#else #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 hashTable[LZ4_HASH_SIZE_U32];
unsigned int currentOffset; unsigned int currentOffset;
unsigned int initCheck; unsigned short initCheck;
unsigned short tableType;
const unsigned char* dictionary; const unsigned char* dictionary;
unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */ const LZ4_stream_t_internal* dictCtx;
unsigned int dictSize; unsigned int dictSize;
} LZ4_stream_t_internal; };
typedef struct { typedef struct {
const unsigned char* externalDict; const unsigned char* externalDict;
@@ -409,21 +569,19 @@ union LZ4_streamDecode_u {
* Obsolete Functions * Obsolete Functions
**************************************/ **************************************/
/*! Deprecation warnings /*! Deprecation warnings
Should deprecation warnings be a problem, Should deprecation warnings be a problem,
it is generally possible to disable them, it is generally possible to disable them,
typically with -Wno-deprecated-declarations for gcc typically with -Wno-deprecated-declarations for gcc
or _CRT_SECURE_NO_WARNINGS in Visual. or _CRT_SECURE_NO_WARNINGS in Visual.
Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS #ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ # define LZ4_DEPRECATED(message) /* disable deprecation warnings */
#else #else
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) # define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# if defined(__clang__) /* clang doesn't handle mixed C++11 and CNU attributes */ # if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) [[deprecated(message)]] # 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))) # define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif (LZ4_GCC_VERSION >= 301) # elif (LZ4_GCC_VERSION >= 301)
# define LZ4_DEPRECATED(message) __attribute__((deprecated)) # define LZ4_DEPRECATED(message) __attribute__((deprecated))
@@ -436,26 +594,34 @@ union LZ4_streamDecode_u {
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ #endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
/* Obsolete compression functions */ /* Obsolete compression functions */
LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize); LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API 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); LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API 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); LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API 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); 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);
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); 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);
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_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 */ /* Obsolete decompression functions */
LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast() instead") int LZ4_uncompress (const char* source, char* dest, int outputSize); LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API 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_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 */ /* Obsolete streaming functions; degraded functionality; do not use!
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); * In order to perform streaming compression, these functions depended on data
LZ4LIB_API LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer); * that is no longer tracked in the state. They have been preserved as well as
LZ4LIB_API LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state); * 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 */ /* 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); LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API 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_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
#endif /* LZ4_H_2983827168210 */ #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=" - 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" - PREFIX="${HOME}/opt"
- ASIO_VERSION="862aed305dcf91387535519c9549c17630339a12" - ASIO_VERSION="862aed305dcf91387535519c9549c17630339a12"
- LZ4_VERSION="1.7.5" - LZ4_VERSION="1.8.3"
- MBEDTLS_VERSION="2.5.1" - MBEDTLS_VERSION="2.7.5"
- MBEDTLS_CFLAGS="-I${PREFIX}/include" - MBEDTLS_CFLAGS="-I${PREFIX}/include"
- MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto" - MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto"
- OPENSSL_VERSION="1.0.2l" - OPENSSL_VERSION="1.0.2l"
@@ -22,11 +22,9 @@ matrix:
include: include:
- env: SSLLIB="openssl" - env: SSLLIB="openssl"
os: osx os: osx
osx_image: xcode8.3
compiler: clang compiler: clang
- env: SSLLIB="mbedtls" - env: SSLLIB="mbedtls"
os: osx os: osx
osx_image: xcode8.3
compiler: clang compiler: clang
- env: SSLLIB="openssl" RUN_COVERITY_SCAN="1" - env: SSLLIB="openssl" RUN_COVERITY_SCAN="1"
os: linux os: linux

View File

@@ -259,10 +259,10 @@ namespace openvpn {
parent = parent_arg; parent = parent_arg;
} }
virtual bool socket_protect(int socket) bool socket_protect(int socket, IP::Addr endpoint) override
{ {
if (parent) if (parent)
return parent->socket_protect(socket); return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6());
else else
return true; return true;
} }
@@ -858,6 +858,9 @@ namespace openvpn {
#endif #endif
Log::Context log_context(this); Log::Context log_context(this);
#endif #endif
OPENVPN_LOG(ClientAPI::OpenVPNClient::platform());
return do_connect(); return do_connect();
} }

View File

@@ -469,7 +469,8 @@ namespace openvpn {
// Callback to "protect" a socket from being routed through the tunnel. // Callback to "protect" a socket from being routed through the tunnel.
// Will be called from the thread executing connect(). // 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. // Primary VPN client connect method, doesn't return until disconnect.
// Should be called by a worker thread. This method will make callbacks // 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_VERSION=asio-1-12-0
export ASIO_CSUM=fa8c3a16dc2163f5b3451f2a14ce95277c971f46700497d4e94af6059c00dc06 export ASIO_CSUM=fa8c3a16dc2163f5b3451f2a14ce95277c971f46700497d4e94af6059c00dc06
export LZ4_VERSION=lz4-1.8.0 export LZ4_VERSION=lz4-1.8.3
export LZ4_CSUM=2ca482ea7a9bb103603108b5a7510b7592b90158c151ff50a28f1ca8389fccf6 export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43
export MBEDTLS_VERSION=mbedtls-2.7.5 export MBEDTLS_VERSION=mbedtls-2.7.5
export MBEDTLS_CSUM=a1302ad9094aabb9880d2755927b466a6bac8e02b68e04dee77321f3859e9b40 export MBEDTLS_CSUM=a1302ad9094aabb9880d2755927b466a6bac8e02b68e04dee77321f3859e9b40

View File

@@ -76,6 +76,7 @@ $GPP_CMD \
-DASIO_NO_DEPRECATED \ -DASIO_NO_DEPRECATED \
-DHAVE_LZ4 \ -DHAVE_LZ4 \
-DOPENVPN_USE_TLS_MD5 \ -DOPENVPN_USE_TLS_MD5 \
-DASIO_HAS_STD_STRING_VIEW \
-I$O3/core/client \ -I$O3/core/client \
-I$O3/core \ -I$O3/core \
$common \ $common \

View File

@@ -557,7 +557,8 @@ namespace openvpn {
init_headroom(headroom); init_headroom(headroom);
} }
void append(const BufferType& other) template <typename B>
void append(const B& other)
{ {
write(other.c_data(), other.size()); 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->stats = cli_stats;
tunconf->stop = config.stop; tunconf->stop = config.stop;
if (config.tun_persist) if (config.tun_persist)
{
tunconf->tun_persist.reset(new TunMac::TunPersist(true, false, nullptr)); 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); client_lifecycle.reset(new MacLifeCycle);
#ifdef OPENVPN_COMMAND_AGENT #ifdef OPENVPN_COMMAND_AGENT
tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt); tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt);
@@ -414,7 +419,12 @@ namespace openvpn {
tunconf->stats = cli_stats; tunconf->stats = cli_stats;
tunconf->stop = config.stop; tunconf->stop = config.stop;
if (config.tun_persist) if (config.tun_persist)
{
tunconf->tun_persist.reset(new TunWin::TunPersist(true, false, nullptr)); 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 #ifdef OPENVPN_COMMAND_AGENT
tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt); tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt);
#endif #endif
@@ -693,6 +703,7 @@ namespace openvpn {
cp->dc_deferred = true; // defer data channel setup until after options pull cp->dc_deferred = true; // defer data channel setup until after options pull
cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>()); cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>());
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<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->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>());
cp->ssl_factory = cc->new_factory(); cp->ssl_factory = cc->new_factory();
cp->load(opt, *proto_context_options, config.default_key_direction, false); 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/count.hpp>
#include <openvpn/common/string.hpp> #include <openvpn/common/string.hpp>
#include <openvpn/common/base64.hpp> #include <openvpn/common/base64.hpp>
#include <openvpn/ip/ptb.hpp>
#include <openvpn/tun/client/tunbase.hpp> #include <openvpn/tun/client/tunbase.hpp>
#include <openvpn/transport/client/transbase.hpp> #include <openvpn/transport/client/transbase.hpp>
#include <openvpn/transport/client/relay.hpp> #include <openvpn/transport/client/relay.hpp>
@@ -376,15 +377,24 @@ namespace openvpn {
// encrypt packet // encrypt packet
if (buf.size()) if (buf.size())
{ {
Base::data_encrypt(buf); const ProtoContext::Config& c = Base::conf();
if (buf.size()) if (c.mss_inter > 0 && buf.size() > c.mss_inter)
{ {
// send packet via transport to destination Ptb::generate_icmp_ptb(buf, c.mss_inter);
OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << Base::dump_packet(buf)); tun->tun_send(buf);
if (transport->transport_send(buf)) }
Base::update_last_sent(); else
else if (halt) {
return; 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 else
OPENVPN_LOG("Options continuation..."); 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")) else if (string::starts_with(msg, "AUTH_FAILED"))
{ {
std::string reason; std::string reason;

View File

@@ -31,9 +31,12 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <thread>
#include <openvpn/io/io.hpp> #include <openvpn/io/io.hpp>
#include <openvpn/asio/asiowork.hpp>
#include <openvpn/common/bigmutex.hpp>
#include <openvpn/common/exception.hpp> #include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp> #include <openvpn/common/rc.hpp>
#include <openvpn/common/options.hpp> #include <openvpn/common/options.hpp>
@@ -45,6 +48,7 @@
#include <openvpn/transport/protocol.hpp> #include <openvpn/transport/protocol.hpp>
#include <openvpn/client/cliconstants.hpp> #include <openvpn/client/cliconstants.hpp>
#include <openvpn/log/sessionstats.hpp> #include <openvpn/log/sessionstats.hpp>
#include <openvpn/client/async_resolve.hpp>
#if OPENVPN_DEBUG_REMOTELIST >= 1 #if OPENVPN_DEBUG_REMOTELIST >= 1
#define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x) #define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x)
@@ -53,7 +57,6 @@
#endif #endif
namespace openvpn { namespace openvpn {
class RemoteList : public RC<thread_unsafe_refcount> class RemoteList : public RC<thread_unsafe_refcount>
{ {
// A single IP address that is part of a list of IP addresses // 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 // This is useful in tun_persist mode, where it may be necessary
// to pre-resolve all potential remote server items prior // to pre-resolve all potential remote server items prior
// to initial tunnel establishment. // to initial tunnel establishment.
class PreResolve : public RC<thread_unsafe_refcount> class PreResolve : public virtual RC<thread_unsafe_refcount>, AsyncResolvableTCP
{ {
public: public:
typedef RCPtr<PreResolve> Ptr; typedef RCPtr<PreResolve> Ptr;
@@ -276,8 +279,7 @@ namespace openvpn {
PreResolve(openvpn_io::io_context& io_context_arg, PreResolve(openvpn_io::io_context& io_context_arg,
const RemoteList::Ptr& remote_list_arg, const RemoteList::Ptr& remote_list_arg,
const SessionStats::Ptr& stats_arg) const SessionStats::Ptr& stats_arg)
: io_context(io_context_arg), : AsyncResolvableTCP(io_context_arg),
resolver(io_context_arg),
notify_callback(nullptr), notify_callback(nullptr),
remote_list(remote_list_arg), remote_list(remote_list_arg),
stats(stats_arg), stats(stats_arg),
@@ -313,7 +315,7 @@ namespace openvpn {
{ {
notify_callback = nullptr; notify_callback = nullptr;
index = 0; index = 0;
resolver.cancel(); async_resolve_cancel();
} }
private: private:
@@ -336,14 +338,8 @@ namespace openvpn {
} }
else else
{ {
// call into Asio to do the resolve operation
OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << item.server_host << " : " << item.server_port); OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << item.server_host << " : " << item.server_port);
resolver.async_resolve(item.server_host, item.server_port, async_resolve_name(item.server_host, item.server_port);
[self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::tcp::resolver::results_type results)
{
OPENVPN_ASYNC_HANDLER;
self->resolve_callback(error, results);
});
return; return;
} }
} }
@@ -364,7 +360,7 @@ namespace openvpn {
// callback on resolve completion // callback on resolve completion
void resolve_callback(const openvpn_io::error_code& error, 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()) 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; NotifyCallback* notify_callback;
RemoteList::Ptr remote_list; RemoteList::Ptr remote_list;
SessionStats::Ptr stats; SessionStats::Ptr stats;

View File

@@ -34,11 +34,13 @@
#include <mutex> #include <mutex>
#include <openvpn/common/extern.hpp>
namespace openvpn { namespace openvpn {
namespace bigmutex { namespace bigmutex {
OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex; OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex;
} }
#ifdef OPENVPN_ENABLE_BIGMUTEX #ifdef OPENVPN_ENABLE_BIGMUTEX
#define OPENVPN_ASYNC_HANDLER \ #define OPENVPN_ASYNC_HANDLER \
std::lock_guard<std::recursive_mutex> lg(bigmutex::the_recursive_mutex); 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. // along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>. // If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_COMMON_ENDIAN_H #pragma once
#define OPENVPN_COMMON_ENDIAN_H
#include <openvpn/common/size.hpp> #include <openvpn/common/endian_platform.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
namespace openvpn { namespace openvpn {
namespace Endian { namespace Endian {
# ifdef OPENVPN_LITTLE_ENDIAN # if defined(OPENVPN_LITTLE_ENDIAN)
inline size_t e16(const size_t v) inline size_t e16(const size_t v)
{ {
return v; return v;
@@ -62,7 +50,7 @@ namespace openvpn {
{ {
return 1-v; return 1-v;
} }
# elif OPENVPN_BIG_ENDIAN # elif defined(OPENVPN_BIG_ENDIAN)
inline size_t e16rev(const size_t v) inline size_t e16rev(const size_t v)
{ {
return v; return v;
@@ -92,5 +80,3 @@ namespace openvpn {
# endif # endif
} }
} // namespace openvpn } // 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__) #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) if (!v)
return 0; return 0;
return __builtin_ffs(v); 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) if (!v)
return 0; 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) #elif defined(_MSC_VER)

View File

@@ -30,7 +30,8 @@
#error atomic file methods not supported on Windows #error atomic file methods not supported on Windows
#endif #endif
#include <stdio.h> // for rename() #include <stdio.h> // for rename()
#include <unistd.h> // for unlink()
#include <errno.h> #include <errno.h>
#include <cstring> #include <cstring>
@@ -63,6 +64,7 @@ namespace openvpn {
if (::rename(tfn.c_str(), fn.c_str()) == -1) if (::rename(tfn.c_str(), fn.c_str()) == -1)
{ {
const int eno = errno; 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)); OPENVPN_THROW(file_unix_error, "error moving '" << tfn << "' -> '" << fn << "' : " << strerror_str(eno));
} }
} }

View File

@@ -26,5 +26,6 @@
#include "json/json.h" // JsonCpp library #include "json/json.h" // JsonCpp library
#elif defined(HAVE_OPENVPN_COMMON) #elif defined(HAVE_OPENVPN_COMMON)
#define HAVE_JSON #define HAVE_JSON
#define OPENVPN_JSON_INTERNAL
#include <openvpn/common/json.hpp> // internal OpenVPN JSON implementation #include <openvpn/common/json.hpp> // internal OpenVPN JSON implementation
#endif #endif

View File

@@ -28,8 +28,12 @@
#include <string> #include <string>
#include <openvpn/common/platform.hpp>
namespace openvpn { namespace openvpn {
#if defined(OPENVPN_PLATFORM_LINUX)
inline int update_file_mod_time_nanoseconds(const std::string& filename, inline int update_file_mod_time_nanoseconds(const std::string& filename,
const std::uint64_t nanoseconds_since_epooch) const std::uint64_t nanoseconds_since_epooch)
{ {
@@ -54,4 +58,20 @@ namespace openvpn {
return 0; 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 "";
} }
// 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) inline std::string ext(const std::string& basename)
{ {
const size_t pos = basename.find_last_of('.'); const size_t pos = basename.find_last_of('.');

View File

@@ -325,7 +325,8 @@ namespace openvpn {
cancel(); 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) if (!error && !halt)
{ {
@@ -346,10 +347,14 @@ namespace openvpn {
signal_rearm(); signal_rearm();
break; break;
#endif #endif
default:
signal_rearm();
break;
} }
} }
} }
private:
void signal_rearm() void signal_rearm()
{ {
signals->register_signals_all([self=Ptr(this)](const openvpn_io::error_code& error, int signal_number) 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 // servlist and related vars protected by mutex
std::vector<ServerThread*> servlist; std::vector<ServerThread*> servlist;
int thread_count = 0; int thread_count = 0;
volatile bool halt = false;
// stop // stop
Stop* async_stop_ = nullptr; Stop* async_stop_ = nullptr;
@@ -404,6 +408,9 @@ namespace openvpn {
// logging // logging
Log::Context log_context; Log::Context log_context;
Log::Context::Wrapper log_wrap; // must be constructed after 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) inline bool contains_non_space_ctrl(const std::string& str)
{ {
for (auto &c : str) for (auto &c : str)
if (!is_space(c) && is_ctrl(c)) if ((!is_space(c) && is_ctrl(c)) || c == 127)
return true; return true;
return false; return false;
} }

View File

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

View File

@@ -26,9 +26,16 @@
#include <openvpn/common/pthreadcond.hpp> #include <openvpn/common/pthreadcond.hpp>
namespace openvpn { 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> template <typename THREAD_COMMON>
inline void event_loop_wait_barrier(THREAD_COMMON& tc, 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 // barrier prior to event-loop entry
switch (tc.event_loop_bar.wait(seconds)) 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, bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len) const unsigned char *payload, const size_t payload_len)
{ {
if (header_len < head_size + output_hmac_size()) hmac_pre(header, header_len, payload, payload_len);
return false; ctx_hmac.final(header + header_len);
hmac_pre(header, payload, payload_len);
ctx_hmac.final(header + head_size);
return true; return true;
} }
@@ -103,13 +100,10 @@ namespace openvpn {
{ {
unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE]; unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE];
if (header_len < head_size + output_hmac_size()) hmac_pre(header, header_len, payload, payload_len);
return false;
hmac_pre(header, payload, payload_len);
ctx_hmac.final(local_hmac); 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, size_t encrypt(const unsigned char *iv, unsigned char *out, const size_t olen,
@@ -132,11 +126,11 @@ namespace openvpn {
private: private:
// assume length check on header has already been performed // assume length check on header has already been performed
void hmac_pre(const unsigned char *header, const unsigned char *payload, void hmac_pre(const unsigned char *header, const size_t header_len,
const size_t payload_len) const unsigned char *payload, const size_t payload_len)
{ {
ctx_hmac.reset(); ctx_hmac.reset();
ctx_hmac.update(header, head_size); ctx_hmac.update(header, header_len);
ctx_hmac.update(payload, payload_len); ctx_hmac.update(payload, payload_len);
} }
@@ -159,19 +153,8 @@ namespace openvpn {
typename CRYPTO_API::HMACContext ctx_hmac; typename CRYPTO_API::HMACContext ctx_hmac;
typename CRYPTO_API::CipherContext ctx_crypt; typename CRYPTO_API::CipherContext ctx_crypt;
int mode; 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 // OvpnHMAC wrapper API using dynamic polymorphism
class TLSCryptInstance : public RC<thread_unsafe_refcount> 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_send() = 0;
virtual TLSCryptInstance::Ptr new_obj_recv() = 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> class TLSCryptFactory : public RC<thread_unsafe_refcount>
{ {
public: public:
@@ -244,21 +238,6 @@ namespace openvpn {
return tls_crypt.output_hmac_size(); 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, bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_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, class Client : public TransportClient,
public TunClient, public TunClient,
public KoRekey::Receiver, public KoRekey::Receiver,
public SessionStats::DCOTransportSource public SessionStats::DCOTransportSource,
public AsyncResolvableUDP
{ {
friend class ClientConfig; friend class ClientConfig;
@@ -473,7 +474,8 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg, Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg, ClientConfig* config_arg,
TransportClientParent* parent_arg) TransportClientParent* parent_arg)
: io_context(io_context_arg), : AsyncResolvableUDP(io_context_arg),
io_context(io_context_arg),
halt(false), halt(false),
state(new TunProp::State()), state(new TunProp::State()),
config(config_arg), config(config_arg),
@@ -498,17 +500,13 @@ namespace openvpn {
else else
{ {
transport_parent->transport_pre_resolve(); transport_parent->transport_pre_resolve();
udp().resolver.async_resolve(server_host, server_port, async_resolve_name(server_host, server_port);
[self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::udp::resolver::results_type results)
{
self->do_resolve_udp(error, results);
});
} }
} }
// called after DNS resolution has succeeded or failed // called after DNS resolution has succeeded or failed
void do_resolve_udp(const openvpn_io::error_code& error, void resolve_callback(const openvpn_io::error_code& error,
openvpn_io::ip::udp::resolver::results_type results) openvpn_io::ip::udp::resolver::results_type results)
{ {
if (!halt) if (!halt)
{ {

View File

@@ -70,6 +70,7 @@ namespace openvpn {
PRIMARY_EXPIRE, // primary key context expired PRIMARY_EXPIRE, // primary key context expired
TLS_VERSION_MIN, // peer cannot handshake at our minimum required TLS version TLS_VERSION_MIN, // peer cannot handshake at our minimum required TLS version
TLS_AUTH_FAIL, // tls-auth HMAC verification failed 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 CERT_VERIFY_FAIL, // peer certificate verification failure
PEM_PASSWORD_FAIL, // incorrect or missing PEM private key decryption password PEM_PASSWORD_FAIL, // incorrect or missing PEM private key decryption password
AUTH_FAILED, // general authentication failure AUTH_FAILED, // general authentication failure
@@ -145,6 +146,7 @@ namespace openvpn {
"PRIMARY_EXPIRE", "PRIMARY_EXPIRE",
"TLS_VERSION_MIN", "TLS_VERSION_MIN",
"TLS_AUTH_FAIL", "TLS_AUTH_FAIL",
"TLS_CRYPT_META_FAIL",
"CERT_VERIFY_FAIL", "CERT_VERIFY_FAIL",
"PEM_PASSWORD_FAIL", "PEM_PASSWORD_FAIL",
"AUTH_FAILED", "AUTH_FAILED",

View File

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

View File

@@ -59,10 +59,6 @@ namespace openvpn {
{ {
base64_uninit_static(); base64_uninit_static();
} }
private:
// initialize SSL library
crypto_init crypto_init_;
}; };
// process-wide singular instance // 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 { namespace openvpn {
struct ICMPv4 { struct ICMPv4 {
enum { enum {
ECHO_REQUEST = 8, ECHO_REQUEST = 8,
ECHO_REPLY = 0, ECHO_REPLY = 0,
DEST_UNREACH = 3,
FRAG_NEEDED = 4,
MIN_DATA_SIZE = 8
}; };
struct IPv4Header head; struct IPv4Header head;
@@ -53,6 +56,10 @@ namespace openvpn {
std::uint16_t id; std::uint16_t id;
std::uint16_t seq_num; 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 { struct ICMPv6 {
enum { enum {
ECHO_REQUEST = 128, ECHO_REQUEST = 128,
ECHO_REPLY = 129, ECHO_REPLY = 129,
PACKET_TOO_BIG = 2
}; };
struct IPv6Header head; struct IPv6Header head;
@@ -54,6 +55,7 @@ namespace openvpn {
std::uint16_t id; std::uint16_t id;
std::uint16_t seq_num; std::uint16_t seq_num;
}; };
std::uint32_t mtu;
}; };
}; };
} }

View File

@@ -36,6 +36,11 @@ namespace openvpn {
UDP = 17, /* UDP protocol */ UDP = 17, /* UDP protocol */
}; };
enum {
IPv4 = 4,
IPv6 = 6
};
inline unsigned int version(const std::uint8_t version_len_prio) inline unsigned int version(const std::uint8_t version_len_prio)
{ {
return (version_len_prio >> 4) & 0x0F; 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/sha1.h>
#include <mbedtls/debug.h> #include <mbedtls/debug.h>
#include <mbedtls/asn1.h> #include <mbedtls/asn1.h>
#include <mbedtls/version.h>
#include <openvpn/common/size.hpp> #include <openvpn/common/size.hpp>
#include <openvpn/common/exception.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 // set our own certificate, supporting chain (i.e. extra-certs), and external private key
if (c.crt_chain) if (c.crt_chain)
{ {
epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len); if (mbedtls_pk_get_type(&c.crt_chain.get()->get()->pk) == MBEDTLS_PK_RSA)
mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get()); {
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 else
throw MbedTLSException("cert is undefined"); throw MbedTLSException("cert is undefined");
@@ -1217,7 +1225,20 @@ namespace openvpn {
{ {
const int SHA_DIGEST_LEN = 20; const int SHA_DIGEST_LEN = 20;
static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LEN, "size inconsistency"); 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); 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 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() static void init_static()
{ {
SSL_library_init();
mydata_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr); mydata_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr);
// We actually override some of the OpenSSL SSLv23 methods here, // We actually override some of the OpenSSL SSLv23 methods here,
@@ -867,7 +869,7 @@ namespace openvpn {
try try
{ {
// Create new SSL_CTX for server or client mode // 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()) if (config->mode.is_server())
{ {
ctx = SSL_CTX_new(ssl23 ? SSL::ssl23_method_server() : TLSv1_server_method()); ctx = SSL_CTX_new(ssl23 ? SSL::ssl23_method_server() : TLSv1_server_method());
@@ -910,20 +912,17 @@ namespace openvpn {
if (ssl23) if (ssl23)
{ {
sslopt |= SSL_OP_NO_SSLv2; 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_SSLv3; sslopt |= SSL_OP_NO_TLSv1;
if (config->tls_version_min > TLSVersion::V1_0) # ifdef SSL_OP_NO_TLSv1_1
sslopt |= SSL_OP_NO_TLSv1; if (config->tls_version_min > TLSVersion::V1_1)
# ifdef SSL_OP_NO_TLSv1_1 sslopt |= SSL_OP_NO_TLSv1_1;
if (config->tls_version_min > TLSVersion::V1_1) # endif
sslopt |= SSL_OP_NO_TLSv1_1; # ifdef SSL_OP_NO_TLSv1_2
# endif if (config->tls_version_min > TLSVersion::V1_2)
# ifdef SSL_OP_NO_TLSv1_2 sslopt |= SSL_OP_NO_TLSv1_2;
if (config->tls_version_min > TLSVersion::V1_2) # endif
sslopt |= SSL_OP_NO_TLSv1_2;
# endif
}
} }
SSL_CTX_set_options(ctx, sslopt); 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") if (d == "tls-crypt")
return true; return true;
if (d == "tls-crypt-v2")
return true;
return false; return false;
} }
} }

View File

@@ -34,6 +34,7 @@ namespace openvpn {
inline bool is_openvpn_protocol(const unsigned char *p, const size_t len) 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_V2 = 7;
const int CONTROL_HARD_RESET_CLIENT_V3 = 10;
const int OPCODE_SHIFT = 3; const int OPCODE_SHIFT = 3;
const int MIN_INITIAL_PKT_SIZE = 14; const int MIN_INITIAL_PKT_SIZE = 14;
@@ -42,7 +43,8 @@ namespace openvpn {
case 3: case 3:
return p[0] == 0 return p[0] == 0
&& p[1] >= MIN_INITIAL_PKT_SIZE && 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: case 2:
return p[0] == 0 && p[1] >= MIN_INITIAL_PKT_SIZE; return p[0] == 0 && p[1] >= MIN_INITIAL_PKT_SIZE;
case 1: case 1:

View File

@@ -48,6 +48,10 @@
#include <openvpn/buffer/buffer.hpp> #include <openvpn/buffer/buffer.hpp>
#include <openvpn/buffer/safestr.hpp> #include <openvpn/buffer/safestr.hpp>
#include <openvpn/buffer/bufcomposed.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/time.hpp>
#include <openvpn/time/durhelper.hpp> #include <openvpn/time/durhelper.hpp>
#include <openvpn/frame/frame.hpp> #include <openvpn/frame/frame.hpp>
@@ -57,6 +61,7 @@
#include <openvpn/crypto/cipher.hpp> #include <openvpn/crypto/cipher.hpp>
#include <openvpn/crypto/ovpnhmac.hpp> #include <openvpn/crypto/ovpnhmac.hpp>
#include <openvpn/crypto/tls_crypt.hpp> #include <openvpn/crypto/tls_crypt.hpp>
#include <openvpn/crypto/tls_crypt_v2.hpp>
#include <openvpn/crypto/packet_id.hpp> #include <openvpn/crypto/packet_id.hpp>
#include <openvpn/crypto/static_key.hpp> #include <openvpn/crypto/static_key.hpp>
#include <openvpn/crypto/bs64_data_limit.hpp> #include <openvpn/crypto/bs64_data_limit.hpp>
@@ -65,6 +70,8 @@
#include <openvpn/ssl/psid.hpp> #include <openvpn/ssl/psid.hpp>
#include <openvpn/ssl/tlsprf.hpp> #include <openvpn/ssl/tlsprf.hpp>
#include <openvpn/ssl/datalimit.hpp> #include <openvpn/ssl/datalimit.hpp>
#include <openvpn/ssl/mssparms.hpp>
#include <openvpn/transport/mssfix.hpp>
#include <openvpn/transport/protocol.hpp> #include <openvpn/transport/protocol.hpp>
#include <openvpn/tun/layer.hpp> #include <openvpn/tun/layer.hpp>
#include <openvpn/tun/tunmtu.hpp> #include <openvpn/tun/tunmtu.hpp>
@@ -171,6 +178,7 @@ namespace openvpn {
// indicates key_method >= 2 // indicates key_method >= 2
CONTROL_HARD_RESET_CLIENT_V2 = 7, // initial key from client, forget previous state 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 CONTROL_HARD_RESET_SERVER_V2 = 8, // initial key from server, forget previous state
// define the range of legal opcodes // define the range of legal opcodes
@@ -291,8 +299,10 @@ namespace openvpn {
// compressor // compressor
CompressContext comp_ctx; CompressContext comp_ctx;
// tls_auth parms // tls_auth/crypt parms
OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt 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; OvpnHMACFactory::Ptr tls_auth_factory;
OvpnHMACContext::Ptr tls_auth_context; OvpnHMACContext::Ptr tls_auth_context;
@@ -301,6 +311,8 @@ namespace openvpn {
TLSCryptFactory::Ptr tls_crypt_factory; TLSCryptFactory::Ptr tls_crypt_factory;
TLSCryptContext::Ptr tls_crypt_context; TLSCryptContext::Ptr tls_crypt_context;
TLSCryptMetadataFactory::Ptr tls_crypt_metadata_factory;
// reliability layer parms // reliability layer parms
reliable::id_t reliable_window = 0; reliable::id_t reliable_window = 0;
size_t max_ack_list = 0; size_t max_ack_list = 0;
@@ -332,13 +344,15 @@ namespace openvpn {
// MTU // MTU
unsigned int tun_mtu = 1500; unsigned int tun_mtu = 1500;
MSSParms mss_parms;
unsigned int mss_inter = 0;
// Debugging // Debugging
int debug_level = 1; int debug_level = 1;
// Compatibility // Compatibility
bool force_aes_cbc_ciphersuites = false; bool force_aes_cbc_ciphersuites = false;
// For compatibility with openvpn2 we send initial options on rekeying, // For compatibility with openvpn2 we send initial options on rekeying,
// instead of possible modifications caused by NCP // instead of possible modifications caused by NCP
std::string initial_options; std::string initial_options;
@@ -433,6 +447,8 @@ namespace openvpn {
{ {
if (tls_auth_context) if (tls_auth_context)
throw proto_option_error("tls-auth and tls-crypt are mutually exclusive"); 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)); tls_key.parse(o->get(1, 0));
@@ -445,6 +461,46 @@ namespace openvpn {
set_tls_crypt_algs(digest, cipher); 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 // key-direction
@@ -507,6 +563,9 @@ namespace openvpn {
// tun-mtu // tun-mtu
tun_mtu = parse_tun_mtu(opt, 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 parameters that can be present in both config file or pushed options
load_common(opt, pco, server ? LOAD_COMMON_SERVER : LOAD_COMMON_CLIENT); load_common(opt, pco, server ? LOAD_COMMON_SERVER : LOAD_COMMON_CLIENT);
} }
@@ -680,13 +739,18 @@ namespace openvpn {
return tls_key.defined() && tls_crypt_context; 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 // generate a string summarizing options that will be
// transmitted to peer for options consistency check // transmitted to peer for options consistency check
std::string options_string() std::string options_string()
{ {
if (!initial_options.empty()) if (!initial_options.empty())
return initial_options; return initial_options;
std::ostringstream out; std::ostringstream out;
const bool server = ssl_factory->mode().is_server(); const bool server = ssl_factory->mode().is_server();
@@ -726,7 +790,7 @@ namespace openvpn {
out << ",tls-server"; out << ",tls-server";
else else
out << ",tls-client"; out << ",tls-client";
initial_options = out.str(); initial_options = out.str();
return initial_options; return initial_options;
@@ -892,6 +956,7 @@ namespace openvpn {
break; break;
} }
case CONTROL_HARD_RESET_CLIENT_V2: case CONTROL_HARD_RESET_CLIENT_V2:
case CONTROL_HARD_RESET_CLIENT_V3:
{ {
if (!proto.is_server()) if (!proto.is_server())
return; return;
@@ -946,6 +1011,8 @@ namespace openvpn {
return "DATA_V2"; return "DATA_V2";
case CONTROL_HARD_RESET_CLIENT_V2: case CONTROL_HARD_RESET_CLIENT_V2:
return "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: case CONTROL_HARD_RESET_SERVER_V2:
return "CONTROL_HARD_RESET_SERVER_V2"; return "CONTROL_HARD_RESET_SERVER_V2";
} }
@@ -1217,6 +1284,8 @@ namespace openvpn {
public: public:
typedef RCPtr<KeyContext> Ptr; typedef RCPtr<KeyContext> Ptr;
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_unwrap_wkc_error);
// KeyContext events occur on two basic key types: // KeyContext events occur on two basic key types:
// Primary Key -- the key we transmit/encrypt on. // Primary Key -- the key we transmit/encrypt on.
// Secondary Key -- new keys and retiring keys. // Secondary Key -- new keys and retiring keys.
@@ -1351,7 +1420,7 @@ namespace openvpn {
send_reset(); send_reset();
set_state(state+1); set_state(state+1);
dirty = true; dirty = true;
} }
} }
// control channel flush // control channel flush
@@ -1466,6 +1535,10 @@ namespace openvpn {
// decompress packet // decompress packet
if (compress) if (compress)
compress->decompress(buf); compress->decompress(buf);
// set MSS for segments server can receive
if (proto.config->mss_inter > 0)
MSSFix::mssfix(buf, proto.config->mss_inter);
} }
else else
buf.reset_size(); // no crypto context available buf.reset_size(); // no crypto context available
@@ -1607,6 +1680,15 @@ namespace openvpn {
{ {
case TLS_AUTH: case TLS_AUTH:
return validate_tls_auth(recv, proto, now); 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: case TLS_CRYPT:
return validate_tls_crypt(recv, proto, now); return validate_tls_crypt(recv, proto, now);
case TLS_PLAIN: case TLS_PLAIN:
@@ -1675,6 +1757,35 @@ namespace openvpn {
// cache op32 for hot path in do_encrypt // cache op32 for hot path in do_encrypt
cache_op32(); 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); work.inc_size(decrypt_bytes);
// verify HMAC // 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; return false;
// verify source PSID // verify source PSID
@@ -1819,6 +1932,10 @@ namespace openvpn {
{ {
bool pid_wrap; 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 // compress packet
if (compress) if (compress)
compress->compress(buf, compress_hint); compress->compress(buf, compress_hint);
@@ -1990,25 +2107,36 @@ namespace openvpn {
set_event(ev); 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_) if (key_id_)
return CONTROL_SOFT_RESET_V1; {
return CONTROL_SOFT_RESET_V1;
}
else 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() void send_reset()
{ {
Packet pkt; 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); pkt.frame_prepare(*proto.config->frame, Frame::WRITE_SSL_INIT);
raw_send(std::move(pkt)); raw_send(std::move(pkt));
} }
void raw_recv(Packet&& raw_pkt) // called by ProtoStackBase 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) switch (state)
{ {
@@ -2265,14 +2393,15 @@ namespace openvpn {
// write opcode // write opcode
work.push_front(op_compose(opcode, key_id_)); work.push_front(op_compose(opcode, key_id_));
// compute HMAC using header fields (from 'work') and plaintext payload (from 'buf') // compute HMAC using header fields (from 'work') and plaintext
proto.tls_crypt_send->hmac_gen(work.data(), work.size(), buf.c_data(), buf.size()); // 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 = TLSCryptContext::hmac_offset + proto.hmac_size;
const size_t data_offset = head_size + proto.hmac_size;
// encrypt the content of 'buf' (packet payload) into 'work' // 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.data() + data_offset,
work.max_size() - data_offset, work.max_size() - data_offset,
buf.c_data(), buf.size()); buf.c_data(), buf.size());
@@ -2283,6 +2412,11 @@ namespace openvpn {
} }
work.inc_size(decrypt_bytes); 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' // 'work' now contains the complete packet ready to go. swap it with 'buf'
buf.swap(work); buf.swap(work);
} }
@@ -2303,6 +2437,7 @@ namespace openvpn {
gen_head_tls_auth(opcode, buf); gen_head_tls_auth(opcode, buf);
break; break;
case TLS_CRYPT: case TLS_CRYPT:
case TLS_CRYPT_V2:
gen_head_tls_crypt(opcode, buf); gen_head_tls_crypt(opcode, buf);
break; break;
case TLS_PLAIN: case TLS_PLAIN:
@@ -2448,15 +2583,14 @@ namespace openvpn {
// skip the hmac // skip the hmac
recv.advance(proto.hmac_size); recv.advance(proto.hmac_size);
const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM); const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size;
const size_t data_offset = head_size + proto.hmac_size;
if (orig_size < data_offset) if (orig_size < data_offset)
return false; return false;
// decrypt payload // decrypt payload
proto.config->frame->prepare(Frame::DECRYPT_WORK, work); 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(), work.data(), work.max_size(),
recv.c_data(), recv.size()); recv.c_data(), recv.size());
if (!decrypt_bytes) if (!decrypt_bytes)
@@ -2470,7 +2604,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes); work.inc_size(decrypt_bytes);
// verify HMAC // 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); proto.stats->error(Error::HMAC_ERROR);
if (proto.is_tcp()) if (proto.is_tcp())
@@ -2528,6 +2663,100 @@ namespace openvpn {
return false; 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 bool decapsulate(Packet& pkt) // called by ProtoStackBase
{ {
try { try {
@@ -2535,6 +2764,20 @@ namespace openvpn {
{ {
case TLS_AUTH: case TLS_AUTH:
return decapsulate_tls_auth(pkt); 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: case TLS_CRYPT:
return decapsulate_tls_crypt(pkt); return decapsulate_tls_crypt(pkt);
case TLS_PLAIN: case TLS_PLAIN:
@@ -2724,15 +2967,14 @@ namespace openvpn {
if (opcode_extract(op) != reset_op || key_id_extract(op) != 0) if (opcode_extract(op) != reset_op || key_id_extract(op) != 0)
return false; return false;
const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM); const size_t data_offset = TLSCryptContext::hmac_offset + tls_crypt_recv->output_hmac_size();
const size_t data_offset = head_size + tls_crypt_recv->output_hmac_size();
if (net_buf.size() < data_offset) if (net_buf.size() < data_offset)
return false; return false;
frame->prepare(Frame::DECRYPT_WORK, work); frame->prepare(Frame::DECRYPT_WORK, work);
// decrypt payload from 'net_buf' into '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(), work.data(), work.max_size(),
net_buf.c_data() + data_offset, net_buf.c_data() + data_offset,
net_buf.size() - data_offset); net_buf.size() - data_offset);
@@ -2742,7 +2984,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes); work.inc_size(decrypt_bytes);
// verify HMAC // 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()); work.data(), work.size());
} }
catch (BufferException&) catch (BufferException&)
@@ -2751,11 +2994,30 @@ namespace openvpn {
return false; return false;
} }
protected:
unsigned int reset_op;
private: private:
TLSCryptInstance::Ptr tls_crypt_recv; TLSCryptInstance::Ptr tls_crypt_recv;
Frame::Ptr frame; Frame::Ptr frame;
BufferAllocated work; 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); OPENVPN_SIMPLE_EXCEPTION(select_key_context_error);
@@ -2771,20 +3033,27 @@ namespace openvpn {
const Config& c = *config; const Config& c = *config;
// tls-auth setup // 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 // 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; tls_wrap_mode = TLS_CRYPT;
// get HMAC size from Digest object // get HMAC size from Digest object
hmac_size = c.tls_crypt_context->digest_size(); 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 else
{ {
tls_wrap_mode = TLS_PLAIN; tls_wrap_mode = TLS_PLAIN;
@@ -2801,6 +3070,43 @@ namespace openvpn {
return 0; 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() void reset()
{ {
const Config& c = *config; const Config& c = *config;
@@ -2820,16 +3126,19 @@ namespace openvpn {
switch (tls_wrap_mode) switch (tls_wrap_mode)
{ {
case TLS_CRYPT: case TLS_CRYPT:
tls_crypt_send = c.tls_crypt_context->new_obj_send(); reset_tls_crypt(c, c.tls_key);
tls_crypt_recv = c.tls_crypt_context->new_obj_recv(); // init tls_crypt packet ID
ta_pid_send.init(PacketID::LONG_FORM);
// static direction assignment - not user configurable ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
key_dir = is_server() ? OpenVPNStaticKey::NORMAL : OpenVPNStaticKey::INVERSE; break;
tls_crypt_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir), case TLS_CRYPT_V2:
c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir)); if (is_server())
tls_crypt_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir), // setup key to be used to unwrap WKc upon client connection.
c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); // 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 // init tls_crypt packet ID
ta_pid_send.init(PacketID::LONG_FORM); ta_pid_send.init(PacketID::LONG_FORM);
ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats); ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
@@ -2860,7 +3169,7 @@ namespace openvpn {
break; break;
case TLS_PLAIN: case TLS_PLAIN:
break; break;
} }
// initialize proto session ID // initialize proto session ID
psid_self.randomize(*c.prng); psid_self.randomize(*c.prng);
@@ -3199,7 +3508,8 @@ namespace openvpn {
enum TLSWrapMode { enum TLSWrapMode {
TLS_PLAIN, TLS_PLAIN,
TLS_AUTH, TLS_AUTH,
TLS_CRYPT TLS_CRYPT,
TLS_CRYPT_V2
}; };
void reset_all() void reset_all()
@@ -3483,6 +3793,13 @@ namespace openvpn {
keepalive_xmit = kx; 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 // BEGIN ProtoContext data members
Config::Ptr config; Config::Ptr config;
@@ -3506,6 +3823,9 @@ namespace openvpn {
TLSCryptInstance::Ptr tls_crypt_send; TLSCryptInstance::Ptr tls_crypt_send;
TLSCryptInstance::Ptr tls_crypt_recv; TLSCryptInstance::Ptr tls_crypt_recv;
TLSCryptInstance::Ptr tls_crypt_server;
TLSCryptMetadata::Ptr tls_crypt_metadata;
PacketIDSend ta_pid_send; PacketIDSend ta_pid_send;
PacketIDReceive ta_pid_recv; PacketIDReceive ta_pid_recv;

View File

@@ -26,6 +26,7 @@
#include <openvpn/openssl/crypto/api.hpp> #include <openvpn/openssl/crypto/api.hpp>
#include <openvpn/openssl/ssl/sslctx.hpp> #include <openvpn/openssl/ssl/sslctx.hpp>
#include <openvpn/openssl/util/rand.hpp> #include <openvpn/openssl/util/rand.hpp>
#include <openvpn/openssl/util/pem.hpp>
#endif #endif
#ifdef USE_APPLE_SSL #ifdef USE_APPLE_SSL
@@ -46,6 +47,7 @@
#ifdef OPENVPN_PLATFORM_UWP #ifdef OPENVPN_PLATFORM_UWP
#include <openvpn/mbedtls/util/uwprand.hpp> #include <openvpn/mbedtls/util/uwprand.hpp>
#endif #endif
#include <openvpn/mbedtls/util/pem.hpp>
#endif #endif
#ifdef USE_MBEDTLS_APPLE_HYBRID #ifdef USE_MBEDTLS_APPLE_HYBRID
@@ -69,6 +71,7 @@ namespace openvpn {
#else #else
typedef MbedTLSRandom RandomAPI; typedef MbedTLSRandom RandomAPI;
#endif #endif
typedef MbedTLSPEM PEMAPI;
#elif defined(USE_MBEDTLS_APPLE_HYBRID) #elif defined(USE_MBEDTLS_APPLE_HYBRID)
// Uses Apple framework for CryptoAPI and MbedTLS for SSLAPI and RandomAPI // Uses Apple framework for CryptoAPI and MbedTLS for SSLAPI and RandomAPI
#define SSL_LIB_NAME "MbedTLSAppleHybrid" #define SSL_LIB_NAME "MbedTLSAppleHybrid"
@@ -85,6 +88,7 @@ namespace openvpn {
typedef OpenSSLCryptoAPI CryptoAPI; typedef OpenSSLCryptoAPI CryptoAPI;
typedef OpenSSLContext SSLAPI; typedef OpenSSLContext SSLAPI;
typedef OpenSSLRandom RandomAPI; typedef OpenSSLRandom RandomAPI;
typedef OpenSSLPEM PEMAPI;
#else #else
#error no SSL library defined #error no SSL library defined
#endif #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; typedef RCPtr<Client> Ptr;
@@ -245,12 +245,8 @@ namespace openvpn {
{ {
// resolve it // resolve it
parent->transport_pre_resolve(); 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) async_resolve_name(proxy_host, proxy_port);
{
OPENVPN_ASYNC_HANDLER;
self->do_resolve_(error, results);
});
} }
} }
} }
@@ -340,7 +336,7 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg, Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg, ClientConfig* config_arg,
TransportClientParent* parent_arg) TransportClientParent* parent_arg)
: io_context(io_context_arg), : AsyncResolvableTCP(io_context_arg),
socket(io_context_arg), socket(io_context_arg),
config(config_arg), config(config_arg),
parent(parent_arg), parent(parent_arg),
@@ -860,12 +856,13 @@ namespace openvpn {
socket.close(); socket.close();
resolver.cancel(); resolver.cancel();
async_resolve_cancel();
} }
} }
// do DNS resolve // do DNS resolve
void do_resolve_(const openvpn_io::error_code& error, 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 (!halt) if (!halt)
{ {
@@ -916,7 +913,7 @@ namespace openvpn {
#ifdef OPENVPN_PLATFORM_TYPE_UNIX #ifdef OPENVPN_PLATFORM_TYPE_UNIX
if (config->socket_protect) 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); config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop(); stop();
@@ -1008,7 +1005,6 @@ namespace openvpn {
std::string server_host; std::string server_host;
std::string server_port; std::string server_port;
openvpn_io::io_context& io_context;
openvpn_io::ip::tcp::socket socket; openvpn_io::ip::tcp::socket socket;
ClientConfig::Ptr config; ClientConfig::Ptr config;
TransportClientParent* parent; TransportClientParent* parent;

View File

@@ -74,7 +74,7 @@ namespace openvpn {
{} {}
}; };
class Client : public TransportClient class Client : public TransportClient, AsyncResolvableTCP
{ {
typedef RCPtr<Client> Ptr; typedef RCPtr<Client> Ptr;
@@ -102,12 +102,8 @@ namespace openvpn {
else else
{ {
parent->transport_pre_resolve(); 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) async_resolve_name(server_host, server_port);
{
OPENVPN_ASYNC_HANDLER;
self->do_resolve_(error, results);
});
} }
} }
} }
@@ -175,7 +171,8 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg, Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg, ClientConfig* config_arg,
TransportClientParent* parent_arg) TransportClientParent* parent_arg)
: io_context(io_context_arg), : AsyncResolvableTCP(io_context_arg),
io_context(io_context_arg),
socket(io_context_arg), socket(io_context_arg),
config(config_arg), config(config_arg),
parent(parent_arg), parent(parent_arg),
@@ -249,12 +246,13 @@ namespace openvpn {
socket.close(); socket.close();
resolver.cancel(); resolver.cancel();
async_resolve_cancel();
} }
} }
// do DNS resolve // do DNS resolve
void do_resolve_(const openvpn_io::error_code& error, 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 (!halt) if (!halt)
{ {
@@ -287,7 +285,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP) #if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect) 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); config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop(); stop();

View File

@@ -91,6 +91,8 @@ namespace openvpn {
// the keepalive parameters (in seconds). // the keepalive parameters (in seconds).
virtual void disable_keepalive(unsigned int& keepalive_ping, virtual void disable_keepalive(unsigned int& keepalive_ping,
unsigned int& keepalive_timeout) = 0; unsigned int& keepalive_timeout) = 0;
virtual ~TransportClientParent() {}
}; };
// Factory for client transport object. // 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; typedef RCPtr<Client> Ptr;
@@ -101,16 +101,11 @@ namespace openvpn {
{ {
openvpn_io::error_code error; openvpn_io::error_code error;
openvpn_io::ip::udp::resolver::results_type results = resolver.resolve(server_host, server_port, 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 else
{ {
resolver.async_resolve(server_host, server_port, async_resolve_name(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);
});
} }
} }
} }
@@ -181,7 +176,7 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg, Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg, ClientConfig* config_arg,
TransportClientParent* parent_arg) TransportClientParent* parent_arg)
: io_context(io_context_arg), : AsyncResolvableUDP(io_context_arg),
socket(io_context_arg), socket(io_context_arg),
config(config_arg), config(config_arg),
parent(parent_arg), parent(parent_arg),
@@ -237,12 +232,13 @@ namespace openvpn {
impl->stop(); impl->stop();
socket.close(); socket.close();
resolver.cancel(); resolver.cancel();
async_resolve_cancel();
} }
} }
// called after DNS resolution has succeeded or failed // called after DNS resolution has succeeded or failed
void do_resolve_(const openvpn_io::error_code& error, void resolve_callback(const openvpn_io::error_code& error,
openvpn_io::ip::udp::resolver::results_type results) openvpn_io::ip::udp::resolver::results_type results) override
{ {
if (!halt) if (!halt)
{ {
@@ -274,7 +270,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP) #if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect) 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); config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop(); stop();
@@ -321,7 +317,6 @@ namespace openvpn {
std::string server_host; std::string server_host;
std::string server_port; std::string server_port;
openvpn_io::io_context& io_context;
openvpn_io::ip::udp::socket socket; openvpn_io::ip::udp::socket socket;
ClientConfig::Ptr config; ClientConfig::Ptr config;
TransportClientParent* parent; 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 #ifndef OPENVPN_TRANSPORT_SOCKET_PROTECT_H
#define OPENVPN_TRANSPORT_SOCKET_PROTECT_H #define OPENVPN_TRANSPORT_SOCKET_PROTECT_H
#include <openvpn/addr/ip.hpp>
#ifdef OPENVPN_PLATFORM_UWP #ifdef OPENVPN_PLATFORM_UWP
#include <openvpn/transport/uwp_socket_protect.hpp> #include <openvpn/transport/uwp_socket_protect.hpp>
#endif #endif
@@ -33,7 +34,7 @@ namespace openvpn {
// the socket from being routed into the VPN tunnel. // the socket from being routed into the VPN tunnel.
class BaseSocketProtect { class BaseSocketProtect {
public: public:
virtual bool socket_protect(int socket) = 0; virtual bool socket_protect(int socket, IP::Addr endpoint) = 0;
}; };
#ifdef OPENVPN_PLATFORM_UWP #ifdef OPENVPN_PLATFORM_UWP

View File

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

View File

@@ -485,7 +485,7 @@ namespace openvpn {
const Option& o = opt[*i]; const Option& o = opt[*i];
try { try {
const std::string& type = o.get(1, 64); const std::string& type = o.get(1, 64);
if (type == "DNS") if (type == "DNS" || type == "DNS6")
{ {
o.exact_args(3); o.exact_args(3);
const IP::Addr ip = IP::Addr::from_string(o.get(2, 256), "dns-server-ip"); 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/builder/setup.hpp>
#include <openvpn/tun/tunio.hpp> #include <openvpn/tun/tunio.hpp>
#include <openvpn/tun/persist/tunpersist.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> #include <openvpn/tun/linux/client/tunsetup.hpp>
#define TUN_LINUX TunLinux
#endif
namespace openvpn { namespace openvpn {
namespace TunLinux { namespace TunLinux {
@@ -114,7 +122,7 @@ namespace openvpn {
if (tun_setup_factory) if (tun_setup_factory)
return tun_setup_factory->new_setup_obj(); return tun_setup_factory->new_setup_obj();
else else
return new TunLinux::Setup(); return new TUN_LINUX::Setup();
} }
private: private:
@@ -129,7 +137,7 @@ namespace openvpn {
typedef Tun<Client*> TunImpl; typedef Tun<Client*> TunImpl;
public: public:
virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override
{ {
if (!impl) if (!impl)
{ {
@@ -184,7 +192,7 @@ namespace openvpn {
tun_setup = config->new_setup_obj(); tun_setup = config->new_setup_obj();
// create config object for tun setup layer // create config object for tun setup layer
Setup::Config tsconf; TUN_LINUX::Setup::Config tsconf;
tsconf.layer = config->tun_prop.layer; tsconf.layer = config->tun_prop.layer;
tsconf.dev_name = config->dev_name; tsconf.dev_name = config->dev_name;
tsconf.txqueuelen = config->txqueuelen; 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); return send(buf);
} }
virtual std::string tun_name() const virtual std::string tun_name() const override
{ {
if (impl) if (impl)
return impl->name(); return impl->name();
@@ -241,7 +249,7 @@ namespace openvpn {
return "UNDEF_TUN"; return "UNDEF_TUN";
} }
virtual std::string vpn_ip4() const virtual std::string vpn_ip4() const override
{ {
if (state->vpn_ip4_addr.specified()) if (state->vpn_ip4_addr.specified())
return state->vpn_ip4_addr.to_string(); return state->vpn_ip4_addr.to_string();
@@ -249,7 +257,7 @@ namespace openvpn {
return ""; return "";
} }
virtual std::string vpn_ip6() const virtual std::string vpn_ip6() const override
{ {
if (state->vpn_ip6_addr.specified()) if (state->vpn_ip6_addr.specified())
return state->vpn_ip6_addr.to_string(); return state->vpn_ip6_addr.to_string();
@@ -273,11 +281,11 @@ namespace openvpn {
return ""; return "";
} }
virtual void set_disconnect() virtual void set_disconnect() override
{ {
} }
virtual void stop() { stop_(); } virtual void stop() override { stop_(); }
virtual ~Client() { stop_(); } virtual ~Client() { stop_(); }
private: 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 #endif
}; };
virtual void destroy(std::ostream &os) virtual void destroy(std::ostream &os) override
{ {
// remove added routes // remove added routes
if (remove_cmds) if (remove_cmds)

View File

@@ -17,7 +17,7 @@ cd $DEP_DIR
rm -rf boost rm -rf boost
mkdir boost mkdir boost
export LINK_MODE=static 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 export SDK_PATH_SCRIPT=$O3/core/vars/android-sdk-path
$O3/core/deps/boost/build-boost $O3/core/deps/boost/build-boost
exit 0 exit 0

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf lzo rm -rf lzo
mkdir 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 echo '***************' TARGET $target
TARGET=$target $O3/core/deps/lzo/build-lzo TARGET=$target $O3/core/deps/lzo/build-lzo
done done

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf minicrypto rm -rf minicrypto
mkdir 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 echo '***************' TARGET $target
TARGET=$target $O3/core/deps/minicrypto/build-minicrypto TARGET=$target $O3/core/deps/minicrypto/build-minicrypto
done done

View File

@@ -18,7 +18,7 @@ mini=0
rm -rf polarssl rm -rf polarssl
mkdir 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 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 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/ mv polarssl-$target polarssl/

View File

@@ -15,31 +15,28 @@ fi
if [ -d "$SDK" ]; then if [ -d "$SDK" ]; then
echo "Android SDK already exists at $SDK. Doing only update" echo "Android SDK already exists at $SDK. Doing only update"
yes | $SDK/tools/bin/sdkmanager --licenses else
$SDK/tools/bin/sdkmanager --update . $O3/core/deps/functions.sh
exit 0
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 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 yes | $SDK/tools/bin/sdkmanager --licenses
$SDK/tools/bin/sdkmanager --update $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' \ 'ndk-bundle' \
'extras;android;m2repository' \ 'extras;android;m2repository' \
'patcher;v4' \ 'patcher;v4' \

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf snappy rm -rf snappy
mkdir 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 echo '***************' TARGET $target
TARGET=$target $O3/core/deps/snappy/build-snappy TARGET=$target $O3/core/deps/snappy/build-snappy
done done

View File

@@ -39,7 +39,7 @@ $NDK/build/tools/make-standalone-toolchain.sh \
--toolchain=$ABI-$ABI_VER \ --toolchain=$ABI-$ABI_VER \
--stl=gnustl \ --stl=gnustl \
--arch=arm \ --arch=arm \
--platform=android-14 \ --platform=android-16 \
--install-dir=$DEST --install-dir=$DEST
cd $DEST/$ABI/bin cd $DEST/$ABI/bin
ln -s ../../bin/$ABI-gcc cc ln -s ../../bin/$ABI-gcc cc
@@ -58,7 +58,7 @@ $NDK/build/tools/make-standalone-toolchain.sh \
--toolchain=$ABI-$ABI_VER \ --toolchain=$ABI-$ABI_VER \
--stl=gnustl \ --stl=gnustl \
--arch=x86 \ --arch=x86 \
--platform=android-14 \ --platform=android-16 \
--install-dir=$DEST --install-dir=$DEST
cd $DEST/$SUB/bin cd $DEST/$SUB/bin
ln -s ../../bin/$SUB-gcc cc ln -s ../../bin/$SUB-gcc cc

View File

@@ -242,8 +242,12 @@ fi
# Cityhash # Cityhash
if [ "$CITY" = "1" ]; then if [ "$CITY" = "1" ]; then
LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" ]; then
CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include" 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" LIBS="$LIBS -lcityhash"
CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH" CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH"
fi 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> #include <openvpn/win/console.hpp>
#endif #endif
#ifdef USE_NETCFG
#include "client/core-client-netcfg.hpp"
#endif
using namespace openvpn; using namespace openvpn;
namespace { namespace {
@@ -141,9 +145,10 @@ public:
#endif #endif
private: 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; return true;
} }
@@ -910,7 +915,13 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
} }
else else
{ {
#if defined(USE_NETCFG)
DBus conn(G_BUS_TYPE_SYSTEM);
conn.Connect();
NetCfgTunBuilder<Client> client(conn.GetConnection());
#else
Client client; Client client;
#endif
const ClientAPI::EvalConfig eval = client.eval_config(config); const ClientAPI::EvalConfig eval = client.eval_config(config);
if (eval.error) if (eval.error)
OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message); 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" [ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000"
[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE" [ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE"
[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK" [ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK"
[ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL"
if [ "$AGENT" = "1" ]; then if [ "$AGENT" = "1" ]; then
GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT" GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT"
fi fi
@@ -23,9 +24,9 @@ export GCC_EXTRA
# determine platform # determine platform
if [ "$(uname)" == "Darwin" ]; then if [ "$(uname)" == "Darwin" ]; then
export PROF=osx64 export PROF=${PROF:-osx64}
elif [ "$(uname)" == "Linux" ]; then elif [ "$(uname)" == "Linux" ]; then
export PROF=linux export PROF=${PROF:-linux}
else else
echo this script only knows how to build on Mac OS or Linux echo this script only knows how to build on Mac OS or Linux
fi fi

View File

@@ -41,7 +41,8 @@
#if !defined(USE_TLS_AUTH) && !defined(USE_TLS_CRYPT) #if !defined(USE_TLS_AUTH) && !defined(USE_TLS_CRYPT)
//#define USE_TLS_AUTH //#define USE_TLS_AUTH
#define USE_TLS_CRYPT //#define USE_TLS_CRYPT
#define USE_TLS_CRYPT_V2
#endif #endif
#define OPENVPN_INSTRUMENTATION #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 server_key = read_text("server.key");
const std::string dh_pem = read_text("dh.pem"); const std::string dh_pem = read_text("dh.pem");
const std::string tls_auth_key = read_text("tls-auth.key"); 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 // client config
ClientSSLAPI::Config::Ptr cc(new ClientSSLAPI::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_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
cp->tls_key.parse(tls_auth_key); cp->tls_key.parse(tls_auth_key);
cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); 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 #endif
cp->reliable_window = 4; cp->reliable_window = 4;
cp->max_ack_list = 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->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST));
sp->key_direction = 1; sp->key_direction = 1;
#endif #endif
#ifdef USE_TLS_CRYPT #if defined(USE_TLS_CRYPT)
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ServerCryptoAPI>()); sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
sp->tls_key.parse(tls_auth_key); sp->tls_key.parse(tls_auth_key);
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); 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 #endif
sp->reliable_window = 4; sp->reliable_window = 4;
sp->max_ack_list = 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"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64"> <ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"> <ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid> <ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid>
<RootNamespace>unittests</RootNamespace> <RootNamespace>unittests</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<ImportGroup Label="Shared"> <ImportGroup Label="Shared">
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <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" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <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" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <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" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <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" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck> <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> <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> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies> <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> <AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck> <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> <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> <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> <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> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies> <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> <AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck> <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> <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> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies> <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> <AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck> <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> <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> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies> <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> <AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="test_log.cpp" /> <ClCompile Include="test_log.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </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_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC" export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm 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 GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc" 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_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC" export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm64 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 GPP_CMD="$TC/bin/aarch64-linux-android-g++"
export GCC_CMD="$TC/bin/aarch64-linux-android-gcc" 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_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC" export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-x86 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 GPP_CMD="$TC/bin/i686-linux-android-g++"
export GCC_CMD="$TC/bin/i686-linux-android-gcc" 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)) sys.exit("Checksum mismatch, expected %s, actual %s" % (parms["ASIO_CSUM"], checksum))
with ModEnv('PATH', "%s\\bin;%s" % (parms.get('GIT'), os.environ['PATH'])): with ModEnv('PATH', "%s\\bin;%s" % (parms.get('GIT'), os.environ['PATH'])):
extract(arch_path, "gz") extract(arch_path, "gz")
rmtree("asio") dist = os.path.realpath('asio')
os.rename("asio-%s" % asio_ver, "asio") rmtree(dist)
os.rename("asio-%s" % asio_ver, dist)
rm(arch_path) 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): def build_mbedtls(parms):
print "**************** MBEDTLS" print "**************** MBEDTLS"
with Cd(build_dir(parms)): with Cd(build_dir(parms)):

View File

@@ -1,44 +1,45 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 15
VisualStudioVersion = 14.0.25420.1 VisualStudioVersion = 15.0.28307.106
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "ovpn3-core.vcxproj", "{1F891260-2039-494F-9777-EC5166AF31BC}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "ovpn3-core.vcxproj", "{1F891260-2039-494F-9777-EC5166AF31BC}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "..\test\unittests\unittests.vcxproj", "{18446924-20CC-4EB7-B639-A76C1422E5C2}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittests", "..\test\unittests\unittests.vcxproj", "{18446924-20CC-4EB7-B639-A76C1422E5C2}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86
Release|ARM = Release|ARM Release|ARM = Release|ARM
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F891260-2039-494F-9777-EC5166AF31BC}.Debug|ARM.ActiveCfg = Debug|Win32 {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.ActiveCfg = Debug|x64
{1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x64.Build.0 = 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.ActiveCfg = Debug|x64
{1F891260-2039-494F-9777-EC5166AF31BC}.Debug|x86.Build.0 = Debug|Win32 {1F891260-2039-494F-9777-EC5166AF31BC}.Release|ARM.ActiveCfg = Release|x64
{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.ActiveCfg = Release|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.Build.0 = Release|x64
{1F891260-2039-494F-9777-EC5166AF31BC}.Release|x64.Build.0 = Release|x64 {1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.ActiveCfg = Release|x64
{1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.ActiveCfg = Release|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|ARM.ActiveCfg = Debug|Win32
{1F891260-2039-494F-9777-EC5166AF31BC}.Release|x86.Build.0 = Release|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.ActiveCfg = Debug|x64
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|ARM.ActiveCfg = Debug|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.Build.0 = Debug|x64
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.ActiveCfg = Debug|x64 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.ActiveCfg = Debug|Win32
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x64.Build.0 = Debug|x64 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.Build.0 = Debug|Win32
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.ActiveCfg = Debug|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|ARM.ActiveCfg = Release|Win32
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Debug|x86.Build.0 = Debug|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.ActiveCfg = Release|x64
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|ARM.ActiveCfg = Release|Win32 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.Build.0 = Release|x64
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.ActiveCfg = Release|x64 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.ActiveCfg = Release|Win32
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x64.Build.0 = Release|x64 {18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.Build.0 = Release|Win32
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.ActiveCfg = Release|Win32 EndGlobalSection
{18446924-20CC-4EB7-B639-A76C1422E5C2}.Release|x86.Build.0 = Release|Win32 GlobalSection(SolutionProperties) = preSolution
EndGlobalSection HideSolutionNode = FALSE
GlobalSection(SolutionProperties) = preSolution EndGlobalSection
HideSolutionNode = FALSE GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection SolutionGuid = {2C22702B-DF56-4CEB-9CA4-C999BD01FD03}
EndGlobal EndGlobalSection
EndGlobal

View File

@@ -1,14 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <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"> <ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
@@ -18,9 +10,6 @@
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClCompile Include="..\test\ovpncli\cli.cpp" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\client\ovpncli.hpp" /> <ClInclude Include="..\client\ovpncli.hpp" />
<ClInclude Include="..\openvpn\addr\addrlist.hpp" /> <ClInclude Include="..\openvpn\addr\addrlist.hpp" />
@@ -31,6 +20,8 @@
<ClInclude Include="..\openvpn\addr\ipv6.hpp" /> <ClInclude Include="..\openvpn\addr\ipv6.hpp" />
<ClInclude Include="..\openvpn\addr\macaddr.hpp" /> <ClInclude Include="..\openvpn\addr\macaddr.hpp" />
<ClInclude Include="..\openvpn\addr\pool.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\range.hpp" />
<ClInclude Include="..\openvpn\addr\regex.hpp" /> <ClInclude Include="..\openvpn\addr\regex.hpp" />
<ClInclude Include="..\openvpn\addr\route.hpp" /> <ClInclude Include="..\openvpn\addr\route.hpp" />
@@ -62,6 +53,7 @@
<ClInclude Include="..\openvpn\asio\asiocontext.hpp" /> <ClInclude Include="..\openvpn\asio\asiocontext.hpp" />
<ClInclude Include="..\openvpn\asio\asioerr.hpp" /> <ClInclude Include="..\openvpn\asio\asioerr.hpp" />
<ClInclude Include="..\openvpn\asio\asiopolysock.hpp" /> <ClInclude Include="..\openvpn\asio\asiopolysock.hpp" />
<ClInclude Include="..\openvpn\asio\asioresolverres.hpp" />
<ClInclude Include="..\openvpn\asio\asiosignal.hpp" /> <ClInclude Include="..\openvpn\asio\asiosignal.hpp" />
<ClInclude Include="..\openvpn\asio\asiostop.hpp" /> <ClInclude Include="..\openvpn\asio\asiostop.hpp" />
<ClInclude Include="..\openvpn\asio\asiowork.hpp" /> <ClInclude Include="..\openvpn\asio\asiowork.hpp" />
@@ -81,6 +73,7 @@
<ClInclude Include="..\openvpn\buffer\bufread.hpp" /> <ClInclude Include="..\openvpn\buffer\bufread.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstr.hpp" /> <ClInclude Include="..\openvpn\buffer\bufstr.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstream.hpp" /> <ClInclude Include="..\openvpn\buffer\bufstream.hpp" />
<ClInclude Include="..\openvpn\buffer\lz4.hpp" />
<ClInclude Include="..\openvpn\buffer\memq.hpp" /> <ClInclude Include="..\openvpn\buffer\memq.hpp" />
<ClInclude Include="..\openvpn\buffer\safestr.hpp" /> <ClInclude Include="..\openvpn\buffer\safestr.hpp" />
<ClInclude Include="..\openvpn\buffer\zlib.hpp" /> <ClInclude Include="..\openvpn\buffer\zlib.hpp" />
@@ -101,12 +94,14 @@
<ClInclude Include="..\openvpn\common\abort.hpp" /> <ClInclude Include="..\openvpn\common\abort.hpp" />
<ClInclude Include="..\openvpn\common\action.hpp" /> <ClInclude Include="..\openvpn\common\action.hpp" />
<ClInclude Include="..\openvpn\common\actionthread.hpp" /> <ClInclude Include="..\openvpn\common\actionthread.hpp" />
<ClInclude Include="..\openvpn\common\appversion.hpp" />
<ClInclude Include="..\openvpn\common\arch.hpp" /> <ClInclude Include="..\openvpn\common\arch.hpp" />
<ClInclude Include="..\openvpn\common\argv.hpp" /> <ClInclude Include="..\openvpn\common\argv.hpp" />
<ClInclude Include="..\openvpn\common\arraysize.hpp" /> <ClInclude Include="..\openvpn\common\arraysize.hpp" />
<ClInclude Include="..\openvpn\common\asyncsleep.hpp" /> <ClInclude Include="..\openvpn\common\asyncsleep.hpp" />
<ClInclude Include="..\openvpn\common\autoreset.hpp" /> <ClInclude Include="..\openvpn\common\autoreset.hpp" />
<ClInclude Include="..\openvpn\common\base64.hpp" /> <ClInclude Include="..\openvpn\common\base64.hpp" />
<ClInclude Include="..\openvpn\common\bigmutex.hpp" />
<ClInclude Include="..\openvpn\common\binprefix.hpp" /> <ClInclude Include="..\openvpn\common\binprefix.hpp" />
<ClInclude Include="..\openvpn\common\circ_list.hpp" /> <ClInclude Include="..\openvpn\common\circ_list.hpp" />
<ClInclude Include="..\openvpn\common\cleanup.hpp" /> <ClInclude Include="..\openvpn\common\cleanup.hpp" />
@@ -134,17 +129,19 @@
<ClInclude Include="..\openvpn\common\hostlist.hpp" /> <ClInclude Include="..\openvpn\common\hostlist.hpp" />
<ClInclude Include="..\openvpn\common\hostname.hpp" /> <ClInclude Include="..\openvpn\common\hostname.hpp" />
<ClInclude Include="..\openvpn\common\hostport.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\lex.hpp" />
<ClInclude Include="..\openvpn\common\likely.hpp" /> <ClInclude Include="..\openvpn\common\likely.hpp" />
<ClInclude Include="..\openvpn\common\link.hpp" /> <ClInclude Include="..\openvpn\common\link.hpp" />
<ClInclude Include="..\openvpn\common\logrotate.hpp" /> <ClInclude Include="..\openvpn\common\logrotate.hpp" />
<ClInclude Include="..\openvpn\common\memneq.hpp" /> <ClInclude Include="..\openvpn\common\memneq.hpp" />
<ClInclude Include="..\openvpn\common\mode.hpp" /> <ClInclude Include="..\openvpn\common\mode.hpp" />
<ClInclude Include="..\openvpn\common\modstat.hpp" />
<ClInclude Include="..\openvpn\common\msgwin.hpp" /> <ClInclude Include="..\openvpn\common\msgwin.hpp" />
<ClInclude Include="..\openvpn\common\number.hpp" /> <ClInclude Include="..\openvpn\common\number.hpp" />
<ClInclude Include="..\openvpn\common\olong.hpp" /> <ClInclude Include="..\openvpn\common\olong.hpp" />
<ClInclude Include="..\openvpn\common\options.hpp" /> <ClInclude Include="..\openvpn\common\options.hpp" />
<ClInclude Include="..\openvpn\common\option_error.hpp" />
<ClInclude Include="..\openvpn\common\ostream.hpp" /> <ClInclude Include="..\openvpn\common\ostream.hpp" />
<ClInclude Include="..\openvpn\common\path.hpp" /> <ClInclude Include="..\openvpn\common\path.hpp" />
<ClInclude Include="..\openvpn\common\peercred.hpp" /> <ClInclude Include="..\openvpn\common\peercred.hpp" />
@@ -182,6 +179,7 @@
<ClInclude Include="..\openvpn\common\usecount.hpp" /> <ClInclude Include="..\openvpn\common\usecount.hpp" />
<ClInclude Include="..\openvpn\common\usergroup.hpp" /> <ClInclude Include="..\openvpn\common\usergroup.hpp" />
<ClInclude Include="..\openvpn\common\userpass.hpp" /> <ClInclude Include="..\openvpn\common\userpass.hpp" />
<ClInclude Include="..\openvpn\common\valgrind.hpp" />
<ClInclude Include="..\openvpn\common\version.hpp" /> <ClInclude Include="..\openvpn\common\version.hpp" />
<ClInclude Include="..\openvpn\common\waitbarrier.hpp" /> <ClInclude Include="..\openvpn\common\waitbarrier.hpp" />
<ClInclude Include="..\openvpn\common\write.hpp" /> <ClInclude Include="..\openvpn\common\write.hpp" />
@@ -210,6 +208,9 @@
<ClInclude Include="..\openvpn\crypto\packet_id.hpp" /> <ClInclude Include="..\openvpn\crypto\packet_id.hpp" />
<ClInclude Include="..\openvpn\crypto\selftest.hpp" /> <ClInclude Include="..\openvpn\crypto\selftest.hpp" />
<ClInclude Include="..\openvpn\crypto\static_key.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\error.hpp" />
<ClInclude Include="..\openvpn\error\excode.hpp" /> <ClInclude Include="..\openvpn\error\excode.hpp" />
<ClInclude Include="..\openvpn\frame\frame.hpp" /> <ClInclude Include="..\openvpn\frame\frame.hpp" />
@@ -226,21 +227,39 @@
<ClInclude Include="..\openvpn\http\urlencode.hpp" /> <ClInclude Include="..\openvpn\http\urlencode.hpp" />
<ClInclude Include="..\openvpn\http\urlparm.hpp" /> <ClInclude Include="..\openvpn\http\urlparm.hpp" />
<ClInclude Include="..\openvpn\http\urlparse.hpp" /> <ClInclude Include="..\openvpn\http\urlparse.hpp" />
<ClInclude Include="..\openvpn\http\validate_uri.hpp" />
<ClInclude Include="..\openvpn\http\webexcept.hpp" /> <ClInclude Include="..\openvpn\http\webexcept.hpp" />
<ClInclude Include="..\openvpn\init\cryptoinit.hpp" /> <ClInclude Include="..\openvpn\init\cryptoinit.hpp" />
<ClInclude Include="..\openvpn\init\engineinit.hpp" /> <ClInclude Include="..\openvpn\init\engineinit.hpp" />
<ClInclude Include="..\openvpn\init\initprocess.hpp" /> <ClInclude Include="..\openvpn\init\initprocess.hpp" />
<ClInclude Include="..\openvpn\io\io.hpp" /> <ClInclude Include="..\openvpn\io\io.hpp" />
<ClInclude Include="..\openvpn\ip\csum.hpp" />
<ClInclude Include="..\openvpn\ip\dhcp.hpp" /> <ClInclude Include="..\openvpn\ip\dhcp.hpp" />
<ClInclude Include="..\openvpn\ip\eth.hpp" /> <ClInclude Include="..\openvpn\ip\eth.hpp" />
<ClInclude Include="..\openvpn\ip\icmp.hpp" /> <ClInclude Include="..\openvpn\ip\icmp4.hpp" />
<ClInclude Include="..\openvpn\ip\ip.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\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\legal\copyright.hpp" />
<ClInclude Include="..\openvpn\linux\core.hpp" /> <ClInclude Include="..\openvpn\linux\core.hpp" />
<ClInclude Include="..\openvpn\linux\daemon_alive.hpp" /> <ClInclude Include="..\openvpn\linux\daemon_alive.hpp" />
<ClInclude Include="..\openvpn\linux\procfs.hpp" />
<ClInclude Include="..\openvpn\log\logbase.hpp" /> <ClInclude Include="..\openvpn\log\logbase.hpp" />
<ClInclude Include="..\openvpn\log\logbasesimple.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\lognull.hpp" />
<ClInclude Include="..\openvpn\log\logperiod.hpp" /> <ClInclude Include="..\openvpn\log\logperiod.hpp" />
<ClInclude Include="..\openvpn\log\logsimple.hpp" /> <ClInclude Include="..\openvpn\log\logsimple.hpp" />
@@ -298,6 +317,7 @@
<ClInclude Include="..\openvpn\proxy\proxyauth.hpp" /> <ClInclude Include="..\openvpn\proxy\proxyauth.hpp" />
<ClInclude Include="..\openvpn\random\devurand.hpp" /> <ClInclude Include="..\openvpn\random\devurand.hpp" />
<ClInclude Include="..\openvpn\random\mtrandapi.hpp" /> <ClInclude Include="..\openvpn\random\mtrandapi.hpp" />
<ClInclude Include="..\openvpn\random\rand2.hpp" />
<ClInclude Include="..\openvpn\random\randapi.hpp" /> <ClInclude Include="..\openvpn\random\randapi.hpp" />
<ClInclude Include="..\openvpn\random\randbytestore.hpp" /> <ClInclude Include="..\openvpn\random\randbytestore.hpp" />
<ClInclude Include="..\openvpn\reliable\relack.hpp" /> <ClInclude Include="..\openvpn\reliable\relack.hpp" />
@@ -325,6 +345,7 @@
<ClInclude Include="..\openvpn\ssl\sslapi.hpp" /> <ClInclude Include="..\openvpn\ssl\sslapi.hpp" />
<ClInclude Include="..\openvpn\ssl\sslchoose.hpp" /> <ClInclude Include="..\openvpn\ssl\sslchoose.hpp" />
<ClInclude Include="..\openvpn\ssl\sslconsts.hpp" /> <ClInclude Include="..\openvpn\ssl\sslconsts.hpp" />
<ClInclude Include="..\openvpn\ssl\ssllog.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsprf.hpp" /> <ClInclude Include="..\openvpn\ssl\tlsprf.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsver.hpp" /> <ClInclude Include="..\openvpn\ssl\tlsver.hpp" />
<ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" /> <ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" />
@@ -332,9 +353,12 @@
<ClInclude Include="..\openvpn\time\asiotimer.hpp" /> <ClInclude Include="..\openvpn\time\asiotimer.hpp" />
<ClInclude Include="..\openvpn\time\coarsetime.hpp" /> <ClInclude Include="..\openvpn\time\coarsetime.hpp" />
<ClInclude Include="..\openvpn\time\durhelper.hpp" /> <ClInclude Include="..\openvpn\time\durhelper.hpp" />
<ClInclude Include="..\openvpn\time\epoch.hpp" />
<ClInclude Include="..\openvpn\time\time.hpp" /> <ClInclude Include="..\openvpn\time\time.hpp" />
<ClInclude Include="..\openvpn\time\timestr.hpp" /> <ClInclude Include="..\openvpn\time\timestr.hpp" />
<ClInclude Include="..\openvpn\transport\altproxy.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\httpcli.hpp" />
<ClInclude Include="..\openvpn\transport\client\relay.hpp" /> <ClInclude Include="..\openvpn\transport\client\relay.hpp" />
<ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" /> <ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" />
@@ -342,6 +366,7 @@
<ClInclude Include="..\openvpn\transport\client\udpcli.hpp" /> <ClInclude Include="..\openvpn\transport\client\udpcli.hpp" />
<ClInclude Include="..\openvpn\transport\dco.hpp" /> <ClInclude Include="..\openvpn\transport\dco.hpp" />
<ClInclude Include="..\openvpn\transport\gremlin.hpp" /> <ClInclude Include="..\openvpn\transport\gremlin.hpp" />
<ClInclude Include="..\openvpn\transport\mssfix.hpp" />
<ClInclude Include="..\openvpn\transport\mutate.hpp" /> <ClInclude Include="..\openvpn\transport\mutate.hpp" />
<ClInclude Include="..\openvpn\transport\pktstream.hpp" /> <ClInclude Include="..\openvpn\transport\pktstream.hpp" />
<ClInclude Include="..\openvpn\transport\protocol.hpp" /> <ClInclude Include="..\openvpn\transport\protocol.hpp" />
@@ -349,6 +374,8 @@
<ClInclude Include="..\openvpn\transport\server\transbase.hpp" /> <ClInclude Include="..\openvpn\transport\server\transbase.hpp" />
<ClInclude Include="..\openvpn\transport\socket_protect.hpp" /> <ClInclude Include="..\openvpn\transport\socket_protect.hpp" />
<ClInclude Include="..\openvpn\transport\tcplink.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\transport\udplink.hpp" />
<ClInclude Include="..\openvpn\tun\builder\base.hpp" /> <ClInclude Include="..\openvpn\tun\builder\base.hpp" />
<ClInclude Include="..\openvpn\tun\builder\capture.hpp" /> <ClInclude Include="..\openvpn\tun\builder\capture.hpp" />
@@ -365,13 +392,15 @@
<ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" /> <ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" />
<ClInclude Include="..\openvpn\tun\layer.hpp" /> <ClInclude Include="..\openvpn\tun\layer.hpp" />
<ClInclude Include="..\openvpn\tun\linux\client\tuncli.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\tuncli.hpp" />
<ClInclude Include="..\openvpn\tun\mac\client\tunsetup.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\gwv4.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns.hpp" /> <ClInclude Include="..\openvpn\tun\mac\macdns.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" /> <ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macgw.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\tunutil.hpp" />
<ClInclude Include="..\openvpn\tun\mac\utun.hpp" /> <ClInclude Include="..\openvpn\tun\mac\utun.hpp" />
<ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" /> <ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" />
@@ -402,30 +431,20 @@
<ClInclude Include="..\openvpn\win\unicode.hpp" /> <ClInclude Include="..\openvpn\win\unicode.hpp" />
<ClInclude Include="..\openvpn\win\winerr.hpp" /> <ClInclude Include="..\openvpn\win\winerr.hpp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClCompile Include="..\test\ovpncli\cli.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{1F891260-2039-494F-9777-EC5166AF31BC}</ProjectGuid> <ProjectGuid>{1F891260-2039-494F-9777-EC5166AF31BC}</ProjectGuid>
<RootNamespace>ovpn3core</RootNamespace> <RootNamespace>ovpn3core</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>cli</ProjectName> <ProjectName>cli</ProjectName>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
@@ -442,21 +461,6 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <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'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>
@@ -476,24 +480,6 @@
<ShowProgress>NotSet</ShowProgress> <ShowProgress>NotSet</ShowProgress>
</Link> </Link>
</ItemDefinitionGroup> </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'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel> <WarningLevel>TurnOffAllWarnings</WarningLevel>

View File

@@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<ClCompile Include="..\test\ovpncli\cli.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\ovpncli.hpp" />
<ClInclude Include="..\openvpn\addr\addrlist.hpp" /> <ClInclude Include="..\openvpn\addr\addrlist.hpp" />
<ClInclude Include="..\openvpn\addr\addrpair.hpp" /> <ClInclude Include="..\openvpn\addr\addrpair.hpp" />
<ClInclude Include="..\openvpn\addr\ip.hpp" /> <ClInclude Include="..\openvpn\addr\ip.hpp" />
@@ -13,6 +9,8 @@
<ClInclude Include="..\openvpn\addr\ipv6.hpp" /> <ClInclude Include="..\openvpn\addr\ipv6.hpp" />
<ClInclude Include="..\openvpn\addr\macaddr.hpp" /> <ClInclude Include="..\openvpn\addr\macaddr.hpp" />
<ClInclude Include="..\openvpn\addr\pool.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\range.hpp" />
<ClInclude Include="..\openvpn\addr\regex.hpp" /> <ClInclude Include="..\openvpn\addr\regex.hpp" />
<ClInclude Include="..\openvpn\addr\route.hpp" /> <ClInclude Include="..\openvpn\addr\route.hpp" />
@@ -44,6 +42,7 @@
<ClInclude Include="..\openvpn\asio\asiocontext.hpp" /> <ClInclude Include="..\openvpn\asio\asiocontext.hpp" />
<ClInclude Include="..\openvpn\asio\asioerr.hpp" /> <ClInclude Include="..\openvpn\asio\asioerr.hpp" />
<ClInclude Include="..\openvpn\asio\asiopolysock.hpp" /> <ClInclude Include="..\openvpn\asio\asiopolysock.hpp" />
<ClInclude Include="..\openvpn\asio\asioresolverres.hpp" />
<ClInclude Include="..\openvpn\asio\asiosignal.hpp" /> <ClInclude Include="..\openvpn\asio\asiosignal.hpp" />
<ClInclude Include="..\openvpn\asio\asiostop.hpp" /> <ClInclude Include="..\openvpn\asio\asiostop.hpp" />
<ClInclude Include="..\openvpn\asio\asiowork.hpp" /> <ClInclude Include="..\openvpn\asio\asiowork.hpp" />
@@ -63,6 +62,7 @@
<ClInclude Include="..\openvpn\buffer\bufread.hpp" /> <ClInclude Include="..\openvpn\buffer\bufread.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstr.hpp" /> <ClInclude Include="..\openvpn\buffer\bufstr.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstream.hpp" /> <ClInclude Include="..\openvpn\buffer\bufstream.hpp" />
<ClInclude Include="..\openvpn\buffer\lz4.hpp" />
<ClInclude Include="..\openvpn\buffer\memq.hpp" /> <ClInclude Include="..\openvpn\buffer\memq.hpp" />
<ClInclude Include="..\openvpn\buffer\safestr.hpp" /> <ClInclude Include="..\openvpn\buffer\safestr.hpp" />
<ClInclude Include="..\openvpn\buffer\zlib.hpp" /> <ClInclude Include="..\openvpn\buffer\zlib.hpp" />
@@ -83,12 +83,14 @@
<ClInclude Include="..\openvpn\common\abort.hpp" /> <ClInclude Include="..\openvpn\common\abort.hpp" />
<ClInclude Include="..\openvpn\common\action.hpp" /> <ClInclude Include="..\openvpn\common\action.hpp" />
<ClInclude Include="..\openvpn\common\actionthread.hpp" /> <ClInclude Include="..\openvpn\common\actionthread.hpp" />
<ClInclude Include="..\openvpn\common\appversion.hpp" />
<ClInclude Include="..\openvpn\common\arch.hpp" /> <ClInclude Include="..\openvpn\common\arch.hpp" />
<ClInclude Include="..\openvpn\common\argv.hpp" /> <ClInclude Include="..\openvpn\common\argv.hpp" />
<ClInclude Include="..\openvpn\common\arraysize.hpp" /> <ClInclude Include="..\openvpn\common\arraysize.hpp" />
<ClInclude Include="..\openvpn\common\asyncsleep.hpp" /> <ClInclude Include="..\openvpn\common\asyncsleep.hpp" />
<ClInclude Include="..\openvpn\common\autoreset.hpp" /> <ClInclude Include="..\openvpn\common\autoreset.hpp" />
<ClInclude Include="..\openvpn\common\base64.hpp" /> <ClInclude Include="..\openvpn\common\base64.hpp" />
<ClInclude Include="..\openvpn\common\bigmutex.hpp" />
<ClInclude Include="..\openvpn\common\binprefix.hpp" /> <ClInclude Include="..\openvpn\common\binprefix.hpp" />
<ClInclude Include="..\openvpn\common\circ_list.hpp" /> <ClInclude Include="..\openvpn\common\circ_list.hpp" />
<ClInclude Include="..\openvpn\common\cleanup.hpp" /> <ClInclude Include="..\openvpn\common\cleanup.hpp" />
@@ -116,17 +118,19 @@
<ClInclude Include="..\openvpn\common\hostlist.hpp" /> <ClInclude Include="..\openvpn\common\hostlist.hpp" />
<ClInclude Include="..\openvpn\common\hostname.hpp" /> <ClInclude Include="..\openvpn\common\hostname.hpp" />
<ClInclude Include="..\openvpn\common\hostport.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\lex.hpp" />
<ClInclude Include="..\openvpn\common\likely.hpp" /> <ClInclude Include="..\openvpn\common\likely.hpp" />
<ClInclude Include="..\openvpn\common\link.hpp" /> <ClInclude Include="..\openvpn\common\link.hpp" />
<ClInclude Include="..\openvpn\common\logrotate.hpp" /> <ClInclude Include="..\openvpn\common\logrotate.hpp" />
<ClInclude Include="..\openvpn\common\memneq.hpp" /> <ClInclude Include="..\openvpn\common\memneq.hpp" />
<ClInclude Include="..\openvpn\common\mode.hpp" /> <ClInclude Include="..\openvpn\common\mode.hpp" />
<ClInclude Include="..\openvpn\common\modstat.hpp" />
<ClInclude Include="..\openvpn\common\msgwin.hpp" /> <ClInclude Include="..\openvpn\common\msgwin.hpp" />
<ClInclude Include="..\openvpn\common\number.hpp" /> <ClInclude Include="..\openvpn\common\number.hpp" />
<ClInclude Include="..\openvpn\common\olong.hpp" /> <ClInclude Include="..\openvpn\common\olong.hpp" />
<ClInclude Include="..\openvpn\common\options.hpp" /> <ClInclude Include="..\openvpn\common\options.hpp" />
<ClInclude Include="..\openvpn\common\option_error.hpp" />
<ClInclude Include="..\openvpn\common\ostream.hpp" /> <ClInclude Include="..\openvpn\common\ostream.hpp" />
<ClInclude Include="..\openvpn\common\path.hpp" /> <ClInclude Include="..\openvpn\common\path.hpp" />
<ClInclude Include="..\openvpn\common\peercred.hpp" /> <ClInclude Include="..\openvpn\common\peercred.hpp" />
@@ -164,6 +168,7 @@
<ClInclude Include="..\openvpn\common\usecount.hpp" /> <ClInclude Include="..\openvpn\common\usecount.hpp" />
<ClInclude Include="..\openvpn\common\usergroup.hpp" /> <ClInclude Include="..\openvpn\common\usergroup.hpp" />
<ClInclude Include="..\openvpn\common\userpass.hpp" /> <ClInclude Include="..\openvpn\common\userpass.hpp" />
<ClInclude Include="..\openvpn\common\valgrind.hpp" />
<ClInclude Include="..\openvpn\common\version.hpp" /> <ClInclude Include="..\openvpn\common\version.hpp" />
<ClInclude Include="..\openvpn\common\waitbarrier.hpp" /> <ClInclude Include="..\openvpn\common\waitbarrier.hpp" />
<ClInclude Include="..\openvpn\common\write.hpp" /> <ClInclude Include="..\openvpn\common\write.hpp" />
@@ -192,6 +197,9 @@
<ClInclude Include="..\openvpn\crypto\packet_id.hpp" /> <ClInclude Include="..\openvpn\crypto\packet_id.hpp" />
<ClInclude Include="..\openvpn\crypto\selftest.hpp" /> <ClInclude Include="..\openvpn\crypto\selftest.hpp" />
<ClInclude Include="..\openvpn\crypto\static_key.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\error.hpp" />
<ClInclude Include="..\openvpn\error\excode.hpp" /> <ClInclude Include="..\openvpn\error\excode.hpp" />
<ClInclude Include="..\openvpn\frame\frame.hpp" /> <ClInclude Include="..\openvpn\frame\frame.hpp" />
@@ -208,6 +216,7 @@
<ClInclude Include="..\openvpn\http\urlencode.hpp" /> <ClInclude Include="..\openvpn\http\urlencode.hpp" />
<ClInclude Include="..\openvpn\http\urlparm.hpp" /> <ClInclude Include="..\openvpn\http\urlparm.hpp" />
<ClInclude Include="..\openvpn\http\urlparse.hpp" /> <ClInclude Include="..\openvpn\http\urlparse.hpp" />
<ClInclude Include="..\openvpn\http\validate_uri.hpp" />
<ClInclude Include="..\openvpn\http\webexcept.hpp" /> <ClInclude Include="..\openvpn\http\webexcept.hpp" />
<ClInclude Include="..\openvpn\init\cryptoinit.hpp" /> <ClInclude Include="..\openvpn\init\cryptoinit.hpp" />
<ClInclude Include="..\openvpn\init\engineinit.hpp" /> <ClInclude Include="..\openvpn\init\engineinit.hpp" />
@@ -215,14 +224,26 @@
<ClInclude Include="..\openvpn\io\io.hpp" /> <ClInclude Include="..\openvpn\io\io.hpp" />
<ClInclude Include="..\openvpn\ip\dhcp.hpp" /> <ClInclude Include="..\openvpn\ip\dhcp.hpp" />
<ClInclude Include="..\openvpn\ip\eth.hpp" /> <ClInclude Include="..\openvpn\ip\eth.hpp" />
<ClInclude Include="..\openvpn\ip\icmp.hpp" /> <ClInclude Include="..\openvpn\ip\icmp4.hpp" />
<ClInclude Include="..\openvpn\ip\ip.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\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\legal\copyright.hpp" />
<ClInclude Include="..\openvpn\linux\core.hpp" /> <ClInclude Include="..\openvpn\linux\core.hpp" />
<ClInclude Include="..\openvpn\linux\daemon_alive.hpp" /> <ClInclude Include="..\openvpn\linux\daemon_alive.hpp" />
<ClInclude Include="..\openvpn\linux\procfs.hpp" />
<ClInclude Include="..\openvpn\log\logbase.hpp" /> <ClInclude Include="..\openvpn\log\logbase.hpp" />
<ClInclude Include="..\openvpn\log\logbasesimple.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\lognull.hpp" />
<ClInclude Include="..\openvpn\log\logperiod.hpp" /> <ClInclude Include="..\openvpn\log\logperiod.hpp" />
<ClInclude Include="..\openvpn\log\logsimple.hpp" /> <ClInclude Include="..\openvpn\log\logsimple.hpp" />
@@ -280,6 +301,7 @@
<ClInclude Include="..\openvpn\proxy\proxyauth.hpp" /> <ClInclude Include="..\openvpn\proxy\proxyauth.hpp" />
<ClInclude Include="..\openvpn\random\devurand.hpp" /> <ClInclude Include="..\openvpn\random\devurand.hpp" />
<ClInclude Include="..\openvpn\random\mtrandapi.hpp" /> <ClInclude Include="..\openvpn\random\mtrandapi.hpp" />
<ClInclude Include="..\openvpn\random\rand2.hpp" />
<ClInclude Include="..\openvpn\random\randapi.hpp" /> <ClInclude Include="..\openvpn\random\randapi.hpp" />
<ClInclude Include="..\openvpn\random\randbytestore.hpp" /> <ClInclude Include="..\openvpn\random\randbytestore.hpp" />
<ClInclude Include="..\openvpn\reliable\relack.hpp" /> <ClInclude Include="..\openvpn\reliable\relack.hpp" />
@@ -307,6 +329,7 @@
<ClInclude Include="..\openvpn\ssl\sslapi.hpp" /> <ClInclude Include="..\openvpn\ssl\sslapi.hpp" />
<ClInclude Include="..\openvpn\ssl\sslchoose.hpp" /> <ClInclude Include="..\openvpn\ssl\sslchoose.hpp" />
<ClInclude Include="..\openvpn\ssl\sslconsts.hpp" /> <ClInclude Include="..\openvpn\ssl\sslconsts.hpp" />
<ClInclude Include="..\openvpn\ssl\ssllog.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsprf.hpp" /> <ClInclude Include="..\openvpn\ssl\tlsprf.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsver.hpp" /> <ClInclude Include="..\openvpn\ssl\tlsver.hpp" />
<ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" /> <ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" />
@@ -314,9 +337,12 @@
<ClInclude Include="..\openvpn\time\asiotimer.hpp" /> <ClInclude Include="..\openvpn\time\asiotimer.hpp" />
<ClInclude Include="..\openvpn\time\coarsetime.hpp" /> <ClInclude Include="..\openvpn\time\coarsetime.hpp" />
<ClInclude Include="..\openvpn\time\durhelper.hpp" /> <ClInclude Include="..\openvpn\time\durhelper.hpp" />
<ClInclude Include="..\openvpn\time\epoch.hpp" />
<ClInclude Include="..\openvpn\time\time.hpp" /> <ClInclude Include="..\openvpn\time\time.hpp" />
<ClInclude Include="..\openvpn\time\timestr.hpp" /> <ClInclude Include="..\openvpn\time\timestr.hpp" />
<ClInclude Include="..\openvpn\transport\altproxy.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\httpcli.hpp" />
<ClInclude Include="..\openvpn\transport\client\relay.hpp" /> <ClInclude Include="..\openvpn\transport\client\relay.hpp" />
<ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" /> <ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" />
@@ -331,6 +357,8 @@
<ClInclude Include="..\openvpn\transport\server\transbase.hpp" /> <ClInclude Include="..\openvpn\transport\server\transbase.hpp" />
<ClInclude Include="..\openvpn\transport\socket_protect.hpp" /> <ClInclude Include="..\openvpn\transport\socket_protect.hpp" />
<ClInclude Include="..\openvpn\transport\tcplink.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\transport\udplink.hpp" />
<ClInclude Include="..\openvpn\tun\builder\base.hpp" /> <ClInclude Include="..\openvpn\tun\builder\base.hpp" />
<ClInclude Include="..\openvpn\tun\builder\capture.hpp" /> <ClInclude Include="..\openvpn\tun\builder\capture.hpp" />
@@ -347,18 +375,21 @@
<ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" /> <ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" />
<ClInclude Include="..\openvpn\tun\layer.hpp" /> <ClInclude Include="..\openvpn\tun\layer.hpp" />
<ClInclude Include="..\openvpn\tun\linux\client\tuncli.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\tuncli.hpp" />
<ClInclude Include="..\openvpn\tun\mac\client\tunsetup.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\gwv4.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns.hpp" /> <ClInclude Include="..\openvpn\tun\mac\macdns.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" /> <ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macgw.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\tunutil.hpp" />
<ClInclude Include="..\openvpn\tun\mac\utun.hpp" /> <ClInclude Include="..\openvpn\tun\mac\utun.hpp" />
<ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" /> <ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" />
<ClInclude Include="..\openvpn\tun\persist\tunwrap.hpp" /> <ClInclude Include="..\openvpn\tun\persist\tunwrap.hpp" />
<ClInclude Include="..\openvpn\tun\persist\tunwrapasio.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\server\tunbase.hpp" />
<ClInclude Include="..\openvpn\tun\tunio.hpp" /> <ClInclude Include="..\openvpn\tun\tunio.hpp" />
<ClInclude Include="..\openvpn\tun\tunlog.hpp" /> <ClInclude Include="..\openvpn\tun\tunlog.hpp" />
@@ -370,10 +401,12 @@
<ClInclude Include="..\openvpn\tun\win\nrpt.hpp" /> <ClInclude Include="..\openvpn\tun\win\nrpt.hpp" />
<ClInclude Include="..\openvpn\tun\win\tunutil.hpp" /> <ClInclude Include="..\openvpn\tun\win\tunutil.hpp" />
<ClInclude Include="..\openvpn\tun\win\wfp.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\call.hpp" />
<ClInclude Include="..\openvpn\win\cmd.hpp" /> <ClInclude Include="..\openvpn\win\cmd.hpp" />
<ClInclude Include="..\openvpn\win\console.hpp" /> <ClInclude Include="..\openvpn\win\console.hpp" />
<ClInclude Include="..\openvpn\win\handle.hpp" /> <ClInclude Include="..\openvpn\win\handle.hpp" />
<ClInclude Include="..\openvpn\win\impersonate.hpp" />
<ClInclude Include="..\openvpn\win\modname.hpp" /> <ClInclude Include="..\openvpn\win\modname.hpp" />
<ClInclude Include="..\openvpn\win\reg.hpp" /> <ClInclude Include="..\openvpn\win\reg.hpp" />
<ClInclude Include="..\openvpn\win\scoped_handle.hpp" /> <ClInclude Include="..\openvpn\win\scoped_handle.hpp" />
@@ -383,5 +416,20 @@
<ClInclude Include="..\openvpn\tun\win\winproxy.hpp" /> <ClInclude Include="..\openvpn\tun\win\winproxy.hpp" />
<ClInclude Include="..\openvpn\tun\proxy.hpp" /> <ClInclude Include="..\openvpn\tun\proxy.hpp" />
<ClInclude Include="..\openvpn\win\impersonate.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> </ItemGroup>
</Project> </Project>

View File

@@ -76,6 +76,7 @@
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire), @"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin), @"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail), @"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
@"TLS_CRYPT_META_FAIL": @(OpenVPNAdapterErrorTLSCryptMetaFail),
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail), @"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail), @"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed), @"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
@@ -152,6 +153,7 @@
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired."; case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version."; case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed."; 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 OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password."; case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure"; case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";

Some files were not shown because too many files have changed in this diff Show More