diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4eb9a75 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Sources/OpenVPN3"] + path = Sources/OpenVPN3 + url = https://github.com/amnezia-vpn/openvpn3 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e3ec660 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "sstream": "cpp", + "*.ipp": "cpp" + } +} \ No newline at end of file diff --git a/Configuration/Project.xcconfig b/Configuration/Project.xcconfig index 2029cd2..cafabce 100755 --- a/Configuration/Project.xcconfig +++ b/Configuration/Project.xcconfig @@ -10,22 +10,23 @@ CLANG_CXX_LIBRARY = libc++ // // iOS-specific settings // -IPHONEOS_DEPLOYMENT_TARGET = 9.0 +IPHONEOS_DEPLOYMENT_TARGET = 10.0 SDKROOT[arch=arm64] = iphoneos -SDKROOT[arch=armv7] = iphoneos -SDKROOT[arch=armv7s] = iphoneos +//SDKROOT[arch=armv7] = iphoneos +//SDKROOT[arch=armv7s] = iphoneos -VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s -VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 +VALID_ARCHS[sdk=iphoneos*] = arm64 +// armv7 armv7s +//VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 //////////////////////////////////////////////////////////////////////////////// // // macOS-specific settings // -MACOSX_DEPLOYMENT_TARGET = 10.11 - -SDKROOT[arch=i386] = macosx -SDKROOT[arch=x86_64] = macosx - -VALID_ARCHS[sdk=macosx*] = i386 x86_64 +//MACOSX_DEPLOYMENT_TARGET = 10.11 +// +//SDKROOT[arch=i386] = macosx +//SDKROOT[arch=x86_64] = macosx +// +//VALID_ARCHS[sdk=macosx*] = i386 x86_64 diff --git a/Configuration/amnezia.xcconfig b/Configuration/amnezia.xcconfig new file mode 100644 index 0000000..25bdd40 --- /dev/null +++ b/Configuration/amnezia.xcconfig @@ -0,0 +1,35 @@ +SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx +TARGETED_DEVICE_FAMILY = 1,2 + +HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/Sources/OpenVPNAdapter/include $(SRCROOT)/Sources/OpenVPNClient/include $(SRCROOT)/Sources/LZ4/include $(SRCROOT)/Sources/mbedTLS/include $(SRCROOT)/Sources/ASIO/asio/include $(SRCROOT)/Sources/OpenVPN3 + +CLANG_CXX_LANGUAGE_STANDARD = gnu++14 +CLANG_CXX_LIBRARY = libc++ + +//////////////////////////////////////////////////////////////////////////////// +// +// iOS-specific settings +// +IPHONEOS_DEPLOYMENT_TARGET = 10.0 + +SDKROOT[arch=arm64] = iphoneos +//SDKROOT[arch=armv7] = iphoneos +//SDKROOT[arch=armv7s] = iphoneos + +VALID_ARCHS[sdk=iphoneos*] = arm64 +// armv7 armv7s +//VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 + +//////////////////////////////////////////////////////////////////////////////// +// +// macOS-specific settings +// +//MACOSX_DEPLOYMENT_TARGET = 10.11 +// +//SDKROOT[arch=i386] = macosx +//SDKROOT[arch=x86_64] = macosx +// +//VALID_ARCHS[sdk=macosx*] = i386 x86_64 + PROJECT_TEMP_DIR = /Users/anhviet/Documents/VPN/amnezia-client/client/3rd/OpenVPNAdapter/build/OpenVPNAdapter.build + CONFIGURATION_BUILD_DIR = /Users/anhviet/Documents/VPN/amnezia-client/client/3rd/OpenVPNAdapter/build/Release-iphoneos + BUILT_PRODUCTS_DIR = /Users/anhviet/Documents/VPN/amnezia-client/client/3rd/OpenVPNAdapter/build/Release-iphoneos diff --git a/Lib/ios/arm64/ck-ovpn-plugin.a b/Lib/ios/arm64/ck-ovpn-plugin.a new file mode 100644 index 0000000..cbc5ff0 Binary files /dev/null and b/Lib/ios/arm64/ck-ovpn-plugin.a differ diff --git a/Lib/ios/arm64/ck-ovpn-plugin.a.sha256 b/Lib/ios/arm64/ck-ovpn-plugin.a.sha256 new file mode 100644 index 0000000..fc0b787 --- /dev/null +++ b/Lib/ios/arm64/ck-ovpn-plugin.a.sha256 @@ -0,0 +1 @@ +34d8fa038ad8b1de03c31574a98a227673a3e52cbe1e1a607bcb5fb260e542f0 diff --git a/OpenVPNAdapter.xcodeproj/project.pbxproj b/OpenVPNAdapter.xcodeproj/project.pbxproj index ec06ea3..9392907 100644 --- a/OpenVPNAdapter.xcodeproj/project.pbxproj +++ b/OpenVPNAdapter.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 4E51D4962BCE7A63006977DA /* ck-ovpn-plugin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B7795A329DC896200D15D50 /* ck-ovpn-plugin.a */; }; + 7B7E1EA129E70FB400E76E6D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B7E1EA029E70FB400E76E6D /* UIKit.framework */; }; + 7BFD7A8029E5BEF90066D7CC /* ovpncli.mm in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_73 /* ovpncli.mm */; }; C910EAE524EBB1DA0081AF13 /* OpenVPNReachabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97E5FD624123F48005C2EBC /* OpenVPNReachabilityTests.swift */; }; C910EAE724EBB5210081AF13 /* OpenVPNConfigurationEvaluation.h in Headers */ = {isa = PBXBuildFile; fileRef = C910EAE624EBB5210081AF13 /* OpenVPNConfigurationEvaluation.h */; settings = {ATTRIBUTES = (Public, ); }; }; C910EAEE24EBBFB60081AF13 /* client.crt in Resources */ = {isa = PBXBuildFile; fileRef = C910EAEB24EBBFB60081AF13 /* client.crt */; }; @@ -57,10 +60,9 @@ C97E5FE024123F48005C2EBC /* VPNProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97E5FDA24123F48005C2EBC /* VPNProfile.swift */; }; C97E5FE124123F48005C2EBC /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C97E5FDB24123F48005C2EBC /* Bundle.swift */; }; C97E5FE624124B0E005C2EBC /* Umbrella-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = C97E5FBA2412344D005C2EBC /* Umbrella-Header.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C97E5FE724124B6F005C2EBC /* LZ4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::LZ4::Product" /* LZ4.framework */; }; - C97E5FEC24124B73005C2EBC /* mbedTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::mbedTLS::Product" /* mbedTLS.framework */; }; + C97E5FE724124B6F005C2EBC /* LZ4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::LZ4::Product" /* LZ4.framework */; platformFilter = ios; }; + C97E5FEC24124B73005C2EBC /* mbedTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::mbedTLS::Product" /* mbedTLS.framework */; platformFilter = ios; }; C9EABF3124110BE200D828D4 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9EABF3024110BE200D828D4 /* SystemConfiguration.framework */; }; - C9EABF772411215C00D828D4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9EABF642411189800D828D4 /* UIKit.framework */; platformFilter = ios; }; OBJ_250 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* lz4.c */; }; OBJ_251 /* lz4frame.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* lz4frame.c */; }; OBJ_252 /* lz4hc.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* lz4hc.c */; }; @@ -106,9 +108,8 @@ OBJ_301 /* OpenVPNSessionToken.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_69 /* OpenVPNSessionToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; OBJ_302 /* OpenVPNCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = OBJ_70 /* OpenVPNCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; }; OBJ_304 /* OpenVPNClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::OpenVPNClient::Product" /* OpenVPNClient.framework */; }; - OBJ_322 /* ovpncli.mm in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_73 /* ovpncli.mm */; }; - OBJ_324 /* mbedTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::mbedTLS::Product" /* mbedTLS.framework */; }; - OBJ_325 /* LZ4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::LZ4::Product" /* LZ4.framework */; }; + OBJ_324 /* mbedTLS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::mbedTLS::Product" /* mbedTLS.framework */; platformFilter = ios; }; + OBJ_325 /* LZ4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "OpenVPNAdapter::LZ4::Product" /* LZ4.framework */; platformFilter = ios; }; OBJ_332 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_85 /* aes.c */; }; OBJ_333 /* aesni.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_86 /* aesni.c */; }; OBJ_334 /* arc4.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_87 /* arc4.c */; }; @@ -229,6 +230,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 7B7795A329DC896200D15D50 /* ck-ovpn-plugin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "ck-ovpn-plugin.a"; path = "Lib/ios/arm64/ck-ovpn-plugin.a"; sourceTree = ""; }; + 7B7E1EA029E70FB400E76E6D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; C910EAE624EBB5210081AF13 /* OpenVPNConfigurationEvaluation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = OpenVPNConfigurationEvaluation.h; sourceTree = ""; }; C910EAEB24EBBFB60081AF13 /* client.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = client.crt; sourceTree = ""; }; C910EAEC24EBBFB60081AF13 /* ca.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ca.crt; sourceTree = ""; }; @@ -285,7 +288,6 @@ C9EABF3224110E7500D828D4 /* ovpnapi.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ovpnapi.hpp; sourceTree = ""; }; C9EABF3324110E7500D828D4 /* ovpncli.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = ovpncli.hpp; sourceTree = ""; }; C9EABF492411133400D828D4 /* Project.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Project.xcconfig; sourceTree = ""; }; - C9EABF642411189800D828D4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; C9EABF7324111AEE00D828D4 /* OpenVPNClient.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = OpenVPNClient.xcconfig; sourceTree = ""; }; C9EABF7424111D6100D828D4 /* OpenVPNAdapter.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = OpenVPNAdapter.xcconfig; sourceTree = ""; }; C9EABF7524111E9C00D828D4 /* LZ4.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = LZ4.xcconfig; sourceTree = ""; }; @@ -508,9 +510,10 @@ buildActionMask = 0; files = ( OBJ_304 /* OpenVPNClient.framework in Frameworks */, + 7B7E1EA129E70FB400E76E6D /* UIKit.framework in Frameworks */, C9EABF3124110BE200D828D4 /* SystemConfiguration.framework in Frameworks */, + 4E51D4962BCE7A63006977DA /* ck-ovpn-plugin.a in Frameworks */, C97E5FEC24124B73005C2EBC /* mbedTLS.framework in Frameworks */, - C9EABF772411215C00D828D4 /* UIKit.framework in Frameworks */, C97E5FE724124B6F005C2EBC /* LZ4.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -562,7 +565,8 @@ C9EABF2F24110BE100D828D4 /* Frameworks */ = { isa = PBXGroup; children = ( - C9EABF642411189800D828D4 /* UIKit.framework */, + 7B7E1EA029E70FB400E76E6D /* UIKit.framework */, + 7B7795A329DC896200D15D50 /* ck-ovpn-plugin.a */, C9EABF3024110BE200D828D4 /* SystemConfiguration.framework */, ); name = Frameworks; @@ -1230,7 +1234,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( - OBJ_322 /* ovpncli.mm in Sources */, + 7BFD7A8029E5BEF90066D7CC /* ovpncli.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1323,11 +1327,13 @@ }; C97E5FEA24124B6F005C2EBC /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = "OpenVPNAdapter::LZ4" /* LZ4 */; targetProxy = C97E5FE924124B6F005C2EBC /* PBXContainerItemProxy */; }; C97E5FEF24124B73005C2EBC /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = "OpenVPNAdapter::mbedTLS" /* mbedTLS */; targetProxy = C97E5FEE24124B73005C2EBC /* PBXContainerItemProxy */; }; @@ -1338,11 +1344,13 @@ }; OBJ_326 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = "OpenVPNAdapter::mbedTLS" /* mbedTLS */; targetProxy = C9EABF2A2411076400D828D4 /* PBXContainerItemProxy */; }; OBJ_327 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = "OpenVPNAdapter::LZ4" /* LZ4 */; targetProxy = C9EABF2B2411076400D828D4 /* PBXContainerItemProxy */; }; @@ -1378,7 +1386,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1440,7 +1448,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1535,8 +1543,11 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1547,14 +1558,28 @@ "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Lib/ios/arm64", + ); MARKETING_VERSION = 0.8.0; + OPENVPN_PLUGGABLE_TRANSPORTS = 1; OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = OpenVPNAdapter; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; + TARGETED_DEVICE_FAMILY = "1,2"; TARGET_NAME = OpenVPNAdapter; + VALID_ARCHS = arm64; + "VALID_ARCHS[arch=*]" = arm64; + "VALID_ARCHS[sdk=iphoneos*]" = arm64; }; name = Debug; }; @@ -1564,8 +1589,11 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1576,14 +1604,28 @@ "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + "$(PROJECT_DIR)/Lib/ios/arm64", + ); MARKETING_VERSION = 0.8.0; + OPENVPN_PLUGGABLE_TRANSPORTS = 1; OTHER_SWIFT_FLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = OpenVPNAdapter; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; + TARGETED_DEVICE_FAMILY = "1,2"; TARGET_NAME = OpenVPNAdapter; + VALID_ARCHS = arm64; + "VALID_ARCHS[arch=*]" = arm64; + "VALID_ARCHS[sdk=iphoneos*]" = arm64; }; name = Release; }; @@ -1617,8 +1659,11 @@ baseConfigurationReference = C9EABF7324111AEE00D828D4 /* OpenVPNClient.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1629,6 +1674,10 @@ "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); MACH_O_TYPE = staticlib; MARKETING_VERSION = 3.5.6; OTHER_CFLAGS = "$(inherited)"; @@ -1637,9 +1686,14 @@ PRODUCT_BUNDLE_IDENTIFIER = OpenVPNClient; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; TARGET_NAME = OpenVPNClient; + VALID_ARCHS = arm64; + a = ""; }; name = Debug; }; @@ -1648,8 +1702,11 @@ baseConfigurationReference = C9EABF7324111AEE00D828D4 /* OpenVPNClient.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1660,6 +1717,10 @@ "$(inherited)", "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx", ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); MACH_O_TYPE = staticlib; MARKETING_VERSION = 3.5.6; OTHER_CFLAGS = "$(inherited)"; @@ -1668,9 +1729,14 @@ PRODUCT_BUNDLE_IDENTIFIER = OpenVPNClient; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; TARGET_NAME = OpenVPNClient; + VALID_ARCHS = arm64; + a = ""; }; name = Release; }; @@ -1679,8 +1745,11 @@ baseConfigurationReference = C9EABF7624111F1600D828D4 /* mbedTLS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1697,6 +1766,7 @@ PRODUCT_BUNDLE_IDENTIFIER = mbedTLS; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; TARGET_NAME = mbedTLS; @@ -1708,8 +1778,11 @@ baseConfigurationReference = C9EABF7624111F1600D828D4 /* mbedTLS.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "$(CODE_SIGN_IDENTITY_$(_DEVELOPMENT_TEAM_IS_EMPTY))"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = ""; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1726,6 +1799,7 @@ PRODUCT_BUNDLE_IDENTIFIER = mbedTLS; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; TARGET_NAME = mbedTLS; diff --git a/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter.xcscheme b/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter.xcscheme index 4f93665..b40b132 100644 --- a/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter.xcscheme +++ b/OpenVPNAdapter.xcodeproj/xcshareddata/xcschemes/OpenVPNAdapter.xcscheme @@ -62,16 +62,12 @@ ReferencedContainer = "container:OpenVPNAdapter.xcodeproj"> - - - - - + - - - - - + + + + + "${PREFIX}/.lz4-version" - fi -} - -download_mbedtls () { - if [ ! -f "download-cache/mbedtls-${MBEDTLS_VERSION}-apache.tgz" ]; then - wget -P download-cache/ \ - "https://tls.mbed.org/download/mbedtls-${MBEDTLS_VERSION}-apache.tgz" - fi -} - -build_mbedtls () { - if [ "$(cat ${PREFIX}/.mbedtls-version)" != "${MBEDTLS_VERSION}" ]; then - tar zxf download-cache/mbedtls-${MBEDTLS_VERSION}-apache.tgz - ( - cd "mbedtls-${MBEDTLS_VERSION}" - make CC=$CC CXX=$CXX - make install DESTDIR="${PREFIX}" - ) - echo "${MBEDTLS_VERSION}" > "${PREFIX}/.mbedtls-version" - fi -} - -download_openssl () { - if [ ! -f "download-cache/openssl-${OPENSSL_VERSION}.tar.gz" ]; then - wget -P download-cache/ \ - "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" - fi -} - -build_openssl_linux () { - ( - cd "openssl-${OPENSSL_VERSION}/" - ./config shared --prefix="${PREFIX}" --openssldir="${PREFIX}" -DPURIFY - make all install_sw - ) -} - -build_openssl_osx () { - ( - cd "openssl-${OPENSSL_VERSION}/" - ./Configure darwin64-x86_64-cc shared \ - --prefix="${PREFIX}" --openssldir="${PREFIX}" -DPURIFY - make depend all install_sw - ) -} - -build_openssl () { - if [ "$(cat ${PREFIX}/.openssl-version)" != "${OPENSSL_VERSION}" ]; then - tar zxf "download-cache/openssl-${OPENSSL_VERSION}.tar.gz" - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then - build_openssl_osx - elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then - build_openssl_linux - fi - echo "${OPENSSL_VERSION}" > "${PREFIX}/.openssl-version" - fi -} - -# Enable ccache -if [ "${TRAVIS_OS_NAME}" != "osx" ] && [ -z ${CHOST+x} ]; then - # ccache not available on osx, see: - # https://github.com/travis-ci/travis-ci/issues/5567 - # also ccache not enabled for cross builds - mkdir -p "${HOME}/bin" - ln -s "$(which ccache)" "${HOME}/bin/${CXX}" - ln -s "$(which ccache)" "${HOME}/bin/${CC}" - PATH="${HOME}/bin:${PATH}" -fi - -# Download and build crypto lib -if [ "${SSLLIB}" = "openssl" ]; then - download_openssl - build_openssl -elif [ "${SSLLIB}" = "mbedtls" ]; then - download_mbedtls - build_mbedtls -else - echo "Invalid crypto lib: ${SSLLIB}" - exit 1 -fi - -download_asio -build_asio - -download_lz4 -build_lz4 diff --git a/Sources/OpenVPN3/CLA.rst b/Sources/OpenVPN3/CLA.rst deleted file mode 100644 index a762f6d..0000000 --- a/Sources/OpenVPN3/CLA.rst +++ /dev/null @@ -1,63 +0,0 @@ -Contributor agreement for the OpenVPN project version 1.3 - December 2017 -######################################################################### - -This Contributor Agreement consists of two parts. Part I is the -Developer Certificate of Origin available at -http://developercertificate.org/. - -In this contributor agreement, "This project" refers to the OpenVPN -project and -"open source license indicated in `the file `_" refers to -the AGPLv3 license with an additional permission that allows linking -the OpenSSL software, https://www.openssl.org/, with the OpenVPN -software. - -Part I -###### - -Developer Certificate of Origin Version 1.1 - -Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 -Letterman Drive Suite D4700 San Francisco, CA, 94129 - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -(a) The contribution was created in whole or in part by me and I have -the right to submit it under the open source license indicated in the -file; or - -(b) The contribution is based upon previous work that, to the best of -my knowledge, is covered under an appropriate open source license and -I have the right under that license to submit that work with -modifications, whether created in whole or in part by me, under the -same open source license (unless I am permitted to submit under a -different license), as indicated in the file; or - -(c) The contribution was provided directly to me by some other person -who certified (a), (b) or (c) and I have not modified it. - -(d) I understand and agree that this project and the contribution are -public and that a record of the contribution (including all personal -information I submit with it, including my sign-off) is maintained -indefinitely and may be redistributed consistent with this project or -the open source license(s) involved. - -Part II -####### - -Copyright (C) 2017-2020 OpenVPN Inc. - -In addition: - -(e) I understand that OpenVPN Inc. may relicense this project, this -contribution, and any modification to it under any license. I certify that I, -or the person on whose behalf I am submitting the contribution, have the -right to grant and hereby grant OpenVPN Inc. a license to do so for this -contribution. My grant is made on the condition that OpenVPN Inc. will make -any modification to this contribution available to the OpenVPN project under -the open source license indicated in the file. diff --git a/Sources/OpenVPN3/CMakeLists.txt b/Sources/OpenVPN3/CMakeLists.txt deleted file mode 100644 index 76e09f3..0000000 --- a/Sources/OpenVPN3/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Cmake in OpenVPN3 core is mainly used to get Clion editior support and to run unit tests. For normal -# Build instructions see the README.rst - -cmake_policy(SET CMP0048 NEW) -project(OpenVPN3-core VERSION 3) - -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}") - - -cmake_minimum_required(VERSION 3.5) - -add_subdirectory(test/unittests) -add_subdirectory(test/ovpncli) -add_subdirectory(test/ssl) - - -if (WIN32) - add_subdirectory(openvpn/omi) - add_subdirectory(openvpn/ovpnagent/win) -endif () - diff --git a/Sources/OpenVPN3/CONTRIBUTING.rst b/Sources/OpenVPN3/CONTRIBUTING.rst deleted file mode 100644 index 48213fd..0000000 --- a/Sources/OpenVPN3/CONTRIBUTING.rst +++ /dev/null @@ -1,7 +0,0 @@ -Contributing to OpenVPN 3 -========================= - -Patches can be sent as GitHub pull requests. - -Note that by contributing to the OpenVPN 3 project you accept the Contributor -License Agreement described in `CLA.rst `_. diff --git a/Sources/OpenVPN3/COPYRIGHT.AGPLV3 b/Sources/OpenVPN3/COPYRIGHT.AGPLV3 deleted file mode 100644 index dba13ed..0000000 --- a/Sources/OpenVPN3/COPYRIGHT.AGPLV3 +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - 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. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/Sources/OpenVPN3/LICENSE.rst b/Sources/OpenVPN3/LICENSE.rst deleted file mode 100644 index 8bf238b..0000000 --- a/Sources/OpenVPN3/LICENSE.rst +++ /dev/null @@ -1,15 +0,0 @@ -OpenVPN 3 is distributed under -`GNU Affero General Public License version 3 `_ -with a special permission to link against OpenSSL: - -:: - - Additional permission under GNU AGPL version 3 section 7 - - If you modify this Program, or any covered work, by linking or combining - it with OpenSSL (or a modified version of that library), containing parts - covered by the terms of the OpenSSL License or the Original SSLeay License, - the licensors of this Program grant you additional permission to convey the - resulting work. Corresponding Source for a non-source form of such a - combination shall include the source code for the parts of OpenSSL used as - well as that of the covered work. diff --git a/Sources/OpenVPN3/README.rst b/Sources/OpenVPN3/README.rst deleted file mode 100644 index 4641532..0000000 --- a/Sources/OpenVPN3/README.rst +++ /dev/null @@ -1,653 +0,0 @@ -OpenVPN 3 -========= - -OpenVPN 3 is a C++ class library that implements the functionality -of an OpenVPN client, and is protocol-compatible with the OpenVPN -2.x branch. - -OpenVPN 3 includes a minimal client wrapper (``cli``) that links in with -the library and provides basic command line functionality. - -OpenVPN 3 is currently used in production as the core of the -OpenVPN Connect clients for iOS, Android, Linux, Windows, and Mac OS X. - -NOTE: As of 2017, OpenVPN 3 is primarily of interest to developers, -as it does not yet replicate the full functionality of OpenVPN 2.x. -In particular, server functionality is not yet implemented. - -.. contents:: Table of Contents - -OpenVPN 3 Client API --------------------- - -OpenVPN 3 is organized as a C++ class library, and the API is defined in -``_. - -A simple command-line wrapper for the API is provided in -``_. - -Building the OpenVPN 3 client on Linux --------------------------------------- - -These instructions were tested on Ubuntu 20. - -Prepare directory structure: -:: - - $ sudo apt install g++ make libmbedtls-dev libssl-dev liblz4-dev cmake - $ export O3=~/O3 && mkdir $O3 - $ export DEP_DIR=$O3/deps && mkdir $DEP_DIR - $ export DL=$O3/dl && mkdir $DL - -Clone the OpenVPN 3 source repo: -:: - - $ cd $O3 - $ git clone https://github.com/OpenVPN/openvpn3.git core - -Build dependencies: -:: - - $ cd core/scripts/linux/ - $ ./build-all - -Build the OpenVPN 3 client wrapper (cli) with OpenSSL library: -:: - - $ cd $O3/core && mkdir build && cd build - $ cmake .. - $ cmake --build . - -To use mbed TLS, use: -:: - - $ cmake -DUSE_MBEDTLS=on .. - -Run OpenVPN 3 client: -:: - - $ sudo test/ovpncli/ovpncli myprofile.ovpn route-nopull - -Options used: - -- :code:`myprofile.ovpn` : OpenVPN config file (must have .ovpn extension) -- :code:`route-nopull` : if you are connected via ssh, prevent ssh session lockout - -Using cli with ovpn-dco -""""""""""""""""""""""" - -ovpn-dco is a kernel module which optimises data channel encryption and -transport, providing better performance. - -Download, build and install ovpn-dco: -:: - - $ cd $O3 - $ git clone https://github.com/OpenVPN/ovpn-dco.git - $ cd ovpn-dco - $ make && sudo make install - $ sudo modprobe ovpn-dco - -Install core dependencies: -:: - - $ sudo apt install pkg-config libnl-genl-3-dev - -Build cli with ovpn-dco support: -:: - - $ cd $O3/core/build - $ cmake -DCLI_OVPNDCO=on .. && make - $ sudo test/ovpncli/ovpncliovpndco --dco myprofile.ovpn - -Options used: - -- :code:`myprofile.ovpn` : OpenVPN config file (must have .ovpn extension) -- :code:`--dco` : enable data channel offload - - -Building the OpenVPN 3 client on Mac OS X ------------------------------------------ - -OpenVPN 3 should be built in a non-root Mac OS X account. -Make sure that Xcode is installed with optional command-line tools. -(These instructions have been tested with Xcode 5.1.1). - -Create the directories ``~/src`` and ``~/src/mac``: -:: - - $ mkdir -p ~/src/mac - -Clone the OpenVPN 3 repo: -:: - - $ cd ~/src - $ mkdir ovpn3 - $ cd ovpn3 - $ git clone https://github.com/OpenVPN/openvpn3.git core - -Export the shell variable ``O3`` to point to the OpenVPN 3 top level -directory: -:: - - $ export O3=~/src/ovpn3 - -Download source tarballs (``.tar.gz`` or ``.tgz``) for these dependency -libraries into ``~/Downloads`` - -See the file ``$O3/core/deps/lib-versions`` for the expected -version numbers of each dependency. If you want to use a different -version of the library than listed here, you can edit this file. - -1. Asio - https://github.com/chriskohlhoff/asio -2. mbed TLS (2.3.0 or higher) - https://tls.mbed.org/ -3. LZ4 - https://github.com/Cyan4973/lz4 - -For dependencies that are typically cloned from github vs. -provided as a .tar.gz file, tools are provided to convert -the github to a .tar.gz file. See "snapshot" scripts under -``$O3/core/deps`` - -Note that while OpenSSL is listed in lib-versions, it is -not required for Mac builds. - -Build the dependencies: -:: - - $ DL=~/Downloads - $ OSX_ONLY=1 $O3/core/scripts/mac/build-all - -Now build the OpenVPN 3 client executable: -:: - - $ cd $O3/core - $ . vars/vars-osx64 - $ . vars/setpath - $ cd test/ovpncli - $ MTLS=1 LZ4=1 ASIO=1 build cli - -This will build the OpenVPN 3 client library with a small client -wrapper (``cli``). It will also statically link in all external -dependencies (Asio, mbed TLS, and LZ4), so ``cli`` may be distributed -to other Macs and will run as a standalone executable. - -These build scripts will create a **x86_x64** Mac OS X executable, -with a minimum deployment target of 10.8.x. The Mac OS X tuntap driver is not -required, as OpenVPN 3 can use the integrated utun interface if -available. - -To view the client wrapper options: -:: - - $ ./cli -h - -To connect: -:: - - $ ./cli client.ovpn - - -Building the OpenVPN 3 client on Windows ----------------------------------------- - -Prerequisites: - -* Visual Studio 2019 -* CMake -* vcpkg - -Download and build dependencies: -:: - - > git clone https://github.com/Microsoft/vcpkg.git - > cd vcpkg - > bootstrap-vcpkg.bat - > vcpkg integrate install - > vcpkg install openssl-windows:x64-windows asio:x64-windows tap-windows6:x64-windows lz4:x64-windows gtest:x64-windows - -Download and build core test client: -:: - - > git clone https://github.com/OpenVPN/openvpn3.git - > cmake -DCMAKE_TOOLCHAIN_FILE=\scripts\buildsystems\vcpkg.cmake -A x64 -B build openvpn3 - > cmake --build build --config Release --target ovpncli - -Testing -------- - -The OpenVPN 3 core includes a stress/performance test of -the OpenVPN protocol implementation. The test basically -creates a virtualized lossy network between two OpenVPN -protocol objects, triggers TLS negotiations between them, -passes control/data channel messages, and measures the ability -of the OpenVPN protocol objects to perform and remain in -a valid state. - -The OpenVPN protocol implementation that is being tested -is here: ``_ - -The test code itself is here: ``_ - -Build the test: -:: - - $ cd ovpn3/core/test/ssl - $ ECHO=1 PROF=linux ASIO_DIR=~/asio MTLS_SYS=1 NOSSL=1 $O3/core/scripts/build proto - -Run the test: -:: - - $ time ./proto - *** app bytes=72777936 net_bytes=122972447 data_bytes=415892854 prog=0000216599/0000216598 D=12700/600/12700/600 N=109/109 SH=17400/15300 HE=0/0 - - real 0m15.813s - user 0m15.800s - sys 0m0.004s - -The OpenVPN 3 core also includes unit tests, which are based on -Google Test framework. To run unit tests, you need to install -CMake and build Google Test. - -Building Google Test on Linux: -:: - - $ git clone https://github.com/google/googletest.git - $ cd googletest - $ cmake . && cmake --build . - -Building Google Test on Windows: -:: - - > git clone https://github.com/google/googletest.git - > cd googletest - > cmake -G "Visual Studio 14 2015 Win64" . - > cmake --build . - -After Google Test is built you are ready to build and run unit tests. - -Build and run tests on Linux: -:: - - $ cd ovpn3/core/test/unittests - $ GTEST_DIR=~/googletest ECHO=1 PROF=linux ASIO_DIR=~/asio MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build test_log - $ ./test_log - -Build and run tests on Windows: -:: - - $ cd ovpn3/core/win - $ python build.py ../test/unittests/test_log.cpp unittest - $ test_log.exe - - -Developer Guide ---------------- - -OpenVPN 3 is written in C++11 and developers who are moving -from C to C++ should take some time to familiarize themselves with -key C++ design patterns such as *RAII*: - -https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization - -OpenVPN 3 Client Core -""""""""""""""""""""" - -OpenVPN 3 is designed as a class library, with an API that -is essentially defined inside of namespace ``ClientAPI`` -with headers and implementation in ``_ and -header-only library files under ``_. - -The consise definition of the client API is essentially ``class OpenVPNClient`` -in ``_ with several imporant extensions to -the API found in: - -* :code:`class TunBuilderBase` in ``_ — - Provides an abstraction layer defining the *tun* interface, - and is especially useful for interfacing with an OS-layer VPN API. - -* :code:`class ExternalPKIBase` in ``_ — - Provides a callback for external private key operations, and - is useful for interfacing with an OS-layer Keychain such as - the Keychain on iOS, Mac OS X, and Android, and the Crypto API - on Windows. - -* :code:`class LogReceiver` in ``_ — - Provides an abstraction layer for the delivery of logging messages. - -OpenVPN 3 includes a command-line reference client (``cli``) for -testing the API. See ``_. - -The basic approach to building an OpenVPN 3 client is -to define a client class that derives from -:code:`ClientAPI::OpenVPNClient`, then provide implementations -for callbacks including event and logging notifications: -:: - - class Client : public ClientAPI::OpenVPNClient - { - public: - virtual void event(const Event&) override { // events delivered here - ... - } - virtual void log(const LogInfo&) override { // logging delivered here - ... - } - - ... - }; - -To start the client, first create a :code:`ClientAPI::Config` object -and initialize it with the OpenVPN config file and other options: -:: - - ClientAPI::Config config; - config.content = ; - ... - -Next, create a client object and evaluate the configuration: -:: - - Client client; - ClientAPI::EvalConfig eval = client.eval_config(config); - if (eval.error) - throw ...; - -Finally, in a new worker thread, start the connection: -:: - - ClientAPI::Status connect_status = client.connect(); - -Note that :code:`client.connect()` will not return until -the session has terminated. - -Top Layer -""""""""" - -The top layer of the OpenVPN 3 client is implemented -in ``_ and ``_. -Most of what this code does is marshalling the configuration and -dispatching the higher-level objects that implement the OpenVPN -client session. - -Connection -"""""""""" - -:code:`class ClientConnect` in ``_ -implements the top-level connection logic for an OpenVPN client -connection. It is concerned with starting, stopping, pausing, and resuming -OpenVPN client connections. It deals with retrying a connection and handles -the connection timeout. It also deals with connection exceptions and understands -the difference between an exception that should halt any further reconnection -attempts (such as ``AUTH_FAILED``), and other exceptions such as network errors -that would justify a retry. - -Some of the methods in the class -(such as ``stop``, ``pause``, and ``reconnect``) are often -called by another thread that is controlling the connection, therefore -thread-safe methods are provided where the thread-safe function posts a message -to the actual connection thread. - -In an OpenVPN client connection, the following object stack would be used: - -1. :code:`class ClientConnect` in ``_ — - The top-layer object in an OpenVPN client connection. -2. :code:`class ClientProto::Session` in ``_ — - The OpenVPN client protocol object that subinstantiates the transport - and tun layer objects. -3. :code:`class ProtoContext` in ``_ — - The core OpenVPN protocol implementation that is common to both - client and server. -4. :code:`class ProtoStackBase` in ``_ — - The bottom-layer class that implements - the basic functionality of tunneling a protocol over a reliable or - unreliable transport layer, but isn't specific to OpenVPN per-se. - - -Transport Layer -""""""""""""""" - -OpenVPN 3 defines abstract base classes for Transport layer -implementations in ``_. - -Currently, transport layer implementations are provided for: - -* **UDP** — ``_ -* **TCP** — ``_ -* **HTTP Proxy** — ``_ - - -Tun Layer -""""""""" - -OpenVPN 3 defines abstract base classes for Tun layer -implementations in ``_. - -There are two possible approaches to define a Tun -layer implementation: - -1. Use a VPN API-centric model (such as for Android - or iOS). These models derive from **class TunBuilderBase** - in ``_ - -2. Use an OS-specific model such as: - - * **Linux** — ``_ - * **Windows** — ``_ - * **Mac OS X** — ``_ - - -Protocol Layer -"""""""""""""" - -The OpenVPN protocol is implemented in **class ProtoContext** -in ``_. - - -Options Processing -"""""""""""""""""" - -The parsing and query of the OpenVPN config file -is implemented by :code:`class OptionList` in -``_. - -Note that OpenVPN 3 always assumes an *inline* style of -configuration, where all certs, keys, etc. are -defined inline rather than through an external file -reference. - -For config files that do use external file references, -:code:`class ProfileMerge` in ``_ -is provided to merge those external -file references into an inline form. - -Calling the Client API from other languages -""""""""""""""""""""""""""""""""""""""""""" - -The OpenVPN 3 client API, as defined by :code:`class OpenVPNClient` -in ``_, can be wrapped by the -Swig_ tool to create bindings for other languages. - -.. _Swig: http://www.swig.org/ - -For example, OpenVPN Connect for Android creates a Java -binding of the API using ``_. - -Security --------- - -When developing security software in C++, it's very important to -take advantage of the language and OpenVPN library code -to insulate code from the kinds of -bugs that can introduce security vulnerabilities. - -Here is a brief set of guidelines: - -* When dealing with strings, use a :code:`std::string` - rather than a :code:`char *`. - -* When dealing with binary data or buffers, always try to use a - :code:`Buffer`, :code:`ConstBuffer`, :code:`BufferAllocated`, or - :code:`BufferPtr` object to provide managed access to the buffer, to - protect against security bugs that arise when using raw buffer pointers. - See ``_ for the OpenVPN :code:`Buffer` classes. - -* When it's necessary to have a pointer to an object, use - :code:`std::unique_ptr<>` for non-shared objects and reference-counted - smart pointers for shared objects. For shared-pointers, - OpenVPN code should use the smart pointer classes defined - in ``_. Please see the comments in - this file for documentation. - -* Never use :code:`malloc` or :code:`free`. When allocating objects, - use the C++ :code:`new` operator and then immediately construct - a smart pointer to reference the object: - :: - - std::unique_ptr ptr = new MyObject(); - ptr->method(); - -* When interfacing with C functions that deal with - raw pointers, memory allocation, etc., consider wrapping - the functionality in C++. For an example, see :code:`enum_dir()` - in ``_, - a function that returns a list of files in - a directory (Unix only) via a high-level - string vector, while internally calling - the low level libc methods - :code:`opendir`, :code:`readdir`, and :code:`closedir`. - Notice how :code:`unique_ptr_del` is used to wrap the - ``DIR`` struct in a smart pointer with a custom - deletion function. - -* When grabbing random entropy that is to be used - for cryptographic purposes (i.e. for keys, tokens, etc.), - always ensure that the RNG is crypto-grade by calling - :code:`assert_crypto()` on the RNG. This will throw - an exception if the RNG is not crypto-grade: - :: - - void set_rng(RandomAPI::Ptr rng_arg) { - rng_arg->assert_crypto(); - rng = std::move(rng_arg); - } - -* Any variable whose value is not expected to change should - be declared :code:`const`. - -* Don't use non-const global or static variables unless absolutely - necessary. - -* When formatting strings, don't use :code:`snprintf`. Instead, use - :code:`std::ostringstream` or build the string using the :code:`+` - :code:`std::string` operator: - :: - - std::string format_reconnecting(const int n_seconds) { - return "Reconnecting in " + openvpn::to_string(n_seconds) + " seconds."; - } - - or: - :: - - std::string format_reconnecting(const int n_seconds) { - std::ostringstream os; - os << "Reconnecting in " << n_seconds << " seconds."; - return os.str(); - } - -* OpenVPN 3 is a "header-only" library, therefore all free functions - outside of classes should have the :code:`inline` attribute. - -Conventions -""""""""""" - -* Use the **Asio** library for I/O and timers. - Don't deal with sockets directly. - -* Never block. If you need to wait for something, use **Asio** timers - or sockets. - -* Use the :code:`OPENVPN_LOG()` macro to log stuff. Don't use :code:`printf`. - -* Don't call crypto/ssl libraries directly. Instead use the abstraction - layers (``_ and ``_) that allow OpenVPN - to link with different crypto/ssl libraries (such as **OpenSSL** - or **mbed TLS**). - -* Use :code:`RandomAPI` as a wrapper for random number - generators (``_). - -* If you need to deal with configuration file options, - see :code:`class OptionList` in ``_. - -* If you need to deal with time or time durations, use the - classes under ``_. - -* If you need to deal with IP addresses, see the comprehensive classes - under ``_. - -* In general, if you need a general-purpose library class or function, - look under ``_. Chances are good that it's already - been implemented. - -* The OpenVPN 3 approach to errors is to count them, rather than - unconditionally log them. If you need to add a new error - counter, see ``_. - -* If you need to create a new event type which can be transmitted - as a notification back to the client API user, see - ``_. - -* Raw pointers or references can be okay when used by an object to - point back to its parent (or container), if you can guarantee that - the object will not outlive its parent. Backreferences to a parent - object is also a common use case for weak pointers. - -* Use C++ exceptions for error handling and as an alternative - to :code:`goto`. See OpenVPN's general exception classes - and macros in ``_. - -* Use C++ destructors for automatic object cleanup, and so - that thrown exceptions will not leak objects. Alternatively, - use :code:`Cleanup` in ``_ when - you need to specify a code block to execute prior to scope - exit. For example, ensure that the file :code:`pid_fn` is - deleted before scope exit: - :: - - auto clean = Cleanup([pid_fn]() { - if (pid_fn) - ::unlink(pid_fn); - }); - -* When calling global methods (such as libc :code:`fork`), - prepend :code:`::` to the symbol name, e.g.: - :: - - struct dirent *e; - while ((e = ::readdir(dir.get())) != nullptr) { - ... - } - -* Use :code:`nullptr` instead of :code:`NULL`. - -Threading -""""""""" - -The OpenVPN 3 client core is designed to run in a single thread, with -the UI or controller driving the OpenVPN API running in a different -thread. - -It's almost never necessary to create additional threads within -the OpenVPN 3 client core. - - -Contributing ------------- - -See ``_. - -License -------- - -See ``_. diff --git a/Sources/OpenVPN3/VersionNumbering.rst b/Sources/OpenVPN3/VersionNumbering.rst deleted file mode 100644 index 0d32e58..0000000 --- a/Sources/OpenVPN3/VersionNumbering.rst +++ /dev/null @@ -1,63 +0,0 @@ -OpenVPN 3 version numbering and release process -=============================================== - -OpenVPN 3 version numbers will always be prefixed with ``3.`` which -indicates the OpenVPN generation. This library is the third -generation of the OpenVPN protocol implementation. - -As of OpenVPN 3.2, we will use a single positive integer indicating a -release number as the version reference. - - -Git branches and versioning ---------------------------- -Main development will happen on the git master branch. This will not -contain any specific version. It is will be set to ``3.git:master``. -This branch will contain both stable and unstable code, which will be -bleeding edge at any time. Do not depend on git master for production code. - -Once features and fixes in git master has stabilized, they will be -merged into the ``stable`` branch. Code extracted from the stable branch -will contain the release number of the last release. The stable -branch is suitable for production code. - -It is not set up a specific plan for when releases will occur. We -might want to collect up a smaller set of features before defining it -ready as a release, depending on the size of the changes. At the -release time, the version string will be updated and tagged (with -a PGP signature). - -We should not pile up too many features for each release. It is -better to release often with smaller changesets. - - -Hot-fixes ---------- - -We will not do any patch number releases unless strictly needed for -older releases numbers. Such releases will be called hot-fixes and -will be handled in separate branches only when needed. These branches -will be named ``hotfix/3.X``; where X denotes the release number the -hotfix targets. Hotfixes need to update the version string as well -as attaching a git tag with the proper version number. - -**Hot-fixes should be avoided as much as possible** and we should -**encourage users to base their work on the stable branch** primarily. -Hot-fixes will only be used for highly critical issues which cannot -wait for a release or the feature gap to move to a newer release is -considered too big. But it should also only occur for releases which -are still relevant. - - -Examples --------- - -git ``master`` branch: version string will be ``3.git:master`` - -git ``stable`` branch: version string will be ``3.2``, ``3.3``, etc - -hotfix for v3.2 will be in ``hotfix/3.2`` and the version string will be -``3.2.1`` - -Similarly, hotfix for v3.3 will be found in ``hotfix/3.3`` and the version -string will be ``3.3.1``. diff --git a/Sources/OpenVPN3/appveyor.yml b/Sources/OpenVPN3/appveyor.yml deleted file mode 100644 index 9a26e04..0000000 --- a/Sources/OpenVPN3/appveyor.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: 1.0.{build} - -image: Visual Studio 2019 - -cache: c:\tools\vcpkg\installed\ - -clone_folder: c:\ovpn3\core - -install: - - cd C:\Tools\vcpkg - - git pull - - .\bootstrap-vcpkg.bat - - .\vcpkg upgrade --no-dry-run --overlay-ports=%APPVEYOR_BUILD_FOLDER%\deps\vcpkg-ports - - .\vcpkg install asio:x64-windows openssl-windows:x64-windows tap-windows6:x64-windows lz4:x64-windows gtest:x64-windows jsoncpp:x64-windows --overlay-ports=%APPVEYOR_BUILD_FOLDER%\deps\vcpkg-ports" - - cd %APPVEYOR_BUILD_FOLDER% - -build_script: - - cmake -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -A x64 -B build . - - cmake --build build --config Release - -artifacts: - - path: build\test\ovpncli\Release\* - - path: build\openvpn\omi\Release\* - - path: build\openvpn\ovpnagent\win\Release\* - - diff --git a/Sources/OpenVPN3/client/ovpncli.cpp b/Sources/OpenVPN3/client/ovpncli.cpp deleted file mode 100644 index 22f78ff..0000000 --- a/Sources/OpenVPN3/client/ovpncli.cpp +++ /dev/null @@ -1,1427 +0,0 @@ -// 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-2020 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 . - -// Implementation file for OpenVPNClient API defined in ovpncli.hpp. - -#include -#include -#include -#include -#include - -#include - -// Set up export of our public interface unless -// OPENVPN_CORE_API_VISIBILITY_HIDDEN is defined -#if defined(__GNUC__) -#define OPENVPN_CLIENT_EXPORT -#ifndef OPENVPN_CORE_API_VISIBILITY_HIDDEN -#pragma GCC visibility push(default) -#endif -#include "ovpncli.hpp" // public interface -#ifndef OPENVPN_CORE_API_VISIBILITY_HIDDEN -#pragma GCC visibility pop -#endif -#else -// no public interface export defined for this compiler -#define OPENVPN_CLIENT_EXPORT -#include "ovpncli.hpp" // public interface -#endif - -// debug settings (production setting in parentheses) - -//#define OPENVPN_DUMP_CONFIG // dump parsed configuration (comment out) -//#define OPENVPN_DEBUG_CLIPROTO // shows packets in/out (comment out) -#define OPENVPN_DEBUG_PROTO 1 // increases low-level protocol verbosity (1) -//#define OPENVPN_DEBUG_PROTO_DUMP // dump hex of transport-layer packets, requires OPENVPN_DEBUG_CLIPROTO (comment out) -//#define OPENVPN_DEBUG_VERBOSE_ERRORS // verbosely log Error::Type errors (comment out) -#define OPENVPN_DEBUG_TUN 2 // debug level for tun object (2) -#define OPENVPN_DEBUG_UDPLINK 2 // debug level for UDP link object (2) -#define OPENVPN_DEBUG_TCPLINK 2 // debug level for TCP link object (2) -#define OPENVPN_DEBUG_COMPRESS 1 // debug level for compression objects (1) -#define OPENVPN_DEBUG_REMOTELIST 0 // debug level for RemoteList object (0) -#define OPENVPN_DEBUG_TUN_BUILDER 0 // debug level for tun/builder/client.hpp (0) -//#define OPENVPN_SHOW_SESSION_TOKEN // show server-pushed auth-token (comment out) -//#define OPENVPN_DEBUG_TAPWIN // shows Windows TAP driver debug logging (comment out) - -// enable assertion checks (can safely be disabled in production) -//#define OPENVPN_ENABLE_ASSERT - -// force null tun device (useful for testing) -//#define OPENVPN_FORCE_TUN_NULL - -// log cleartext tunnel packets to file for debugging/analysis -//#define OPENVPN_PACKET_LOG "pkt.log" - -#ifndef OPENVPN_LOG -// log thread settings -#define OPENVPN_LOG_CLASS openvpn::ClientAPI::LogReceiver -#define OPENVPN_LOG_INFO openvpn::ClientAPI::LogInfo -#include // should be included early -#endif - -// log SSL handshake messages -#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x) - -// on Android and iOS, use TunBuilderBase abstraction -#include -#if (defined(OPENVPN_PLATFORM_ANDROID) || defined(OPENVPN_PLATFORM_IPHONE)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY) -#define USE_TUN_BUILDER -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// copyright -#include - -namespace openvpn { - namespace ClientAPI { - - OPENVPN_SIMPLE_EXCEPTION(app_expired); - - class MySessionStats : public SessionStats - { - public: - typedef RCPtr Ptr; - - MySessionStats(OpenVPNClient* parent_arg) - : parent(parent_arg) - { - std::memset(errors, 0, sizeof(errors)); -#ifdef OPENVPN_DEBUG_VERBOSE_ERRORS - session_stats_set_verbose(true); -#endif - } - - static size_t combined_n() - { - return N_STATS + Error::N_ERRORS; - } - - static std::string combined_name(const size_t index) - { - if (index < N_STATS + Error::N_ERRORS) - { - if (index < N_STATS) - return stat_name(index); - else - return Error::name(index - N_STATS); - } - else - return ""; - } - - count_t combined_value(const size_t index) const - { - if (index < N_STATS + Error::N_ERRORS) - { - if (index < N_STATS) - return get_stat(index); - else - return errors[index - N_STATS]; - } - else - return 0; - } - - count_t stat_count(const size_t index) const - { - return get_stat_fast(index); - } - - count_t error_count(const size_t index) const - { - return errors[index]; - } - - void detach_from_parent() - { - parent = nullptr; - } - - virtual void error(const size_t err, const std::string* text=nullptr) - { - if (err < Error::N_ERRORS) - { -#ifdef OPENVPN_DEBUG_VERBOSE_ERRORS - if (text) - OPENVPN_LOG("ERROR: " << Error::name(err) << " : " << *text); - else - OPENVPN_LOG("ERROR: " << Error::name(err)); -#endif - ++errors[err]; - } - } - - private: - OpenVPNClient* parent; - count_t errors[Error::N_ERRORS]; - }; - - class MyClientEvents : public ClientEvent::Queue - { - public: - typedef RCPtr Ptr; - - MyClientEvents(OpenVPNClient* parent_arg) : parent(parent_arg) {} - - virtual void add_event(ClientEvent::Base::Ptr event) override - { - if (parent) - { - Event ev; - ev.name = event->name(); - ev.info = event->render(); - ev.error = event->is_error(); - ev.fatal = event->is_fatal(); - - // save connected event - if (event->id() == ClientEvent::CONNECTED) - last_connected = std::move(event); - else if (event->id() == ClientEvent::DISCONNECTED) - parent->on_disconnect(); - parent->event(ev); - } - } - - void get_connection_info(ConnectionInfo& ci) - { - ClientEvent::Base::Ptr connected = last_connected; - if (connected) - { - const ClientEvent::Connected* c = connected->connected_cast(); - if (c) - { - ci.user = c->user; - ci.serverHost = c->server_host; - ci.serverPort = c->server_port; - ci.serverProto = c->server_proto; - ci.serverIp = c->server_ip; - ci.vpnIp4 = c->vpn_ip4; - ci.vpnIp6 = c->vpn_ip6; - ci.gw4 = c->vpn_gw4; - ci.gw6 = c->vpn_gw6; - ci.clientIp = c->client_ip; - ci.tunName = c->tun_name; - ci.defined = true; - return; - } - } - ci.defined = false; - } - - void detach_from_parent() - { - parent = nullptr; - } - - private: - OpenVPNClient* parent; - ClientEvent::Base::Ptr last_connected; - }; - - class MySocketProtect : public SocketProtect - { - public: - MySocketProtect() : parent(nullptr) {} - - void set_parent(OpenVPNClient* parent_arg) - { - parent = parent_arg; - } - - void set_rg_local(bool rg_local_arg) - { - rg_local = rg_local_arg; - } - - bool socket_protect(int socket, IP::Addr endpoint) override - { - if (parent) - { -#if defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_WIN) - return rg_local ? true : WinCommandAgent::add_bypass_route(endpoint); -#elif defined(OPENVPN_COMMAND_AGENT) && defined(OPENVPN_PLATFORM_MAC) - return rg_local ? true : UnixCommandAgent::add_bypass_route(endpoint); -#else - return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6()); -#endif - } - else - return true; - } - - void detach_from_parent() - { - parent = nullptr; - } - - private: - OpenVPNClient* parent; - bool rg_local = false; // do not add bypass route if true - }; - - class MyReconnectNotify : public ReconnectNotify - { - public: - MyReconnectNotify() : parent(nullptr) {} - - void set_parent(OpenVPNClient* parent_arg) - { - parent = parent_arg; - } - - void detach_from_parent() - { - parent = nullptr; - } - - virtual bool pause_on_connection_timeout() - { - if (parent) - return parent->pause_on_connection_timeout(); - else - return false; - } - - private: - OpenVPNClient* parent; - }; - - class MyRemoteOverride : public RemoteList::RemoteOverride - { - public: - void set_parent(OpenVPNClient* parent_arg) - { - parent = parent_arg; - } - - void detach_from_parent() - { - parent = nullptr; - } - - virtual RemoteList::Item::Ptr get() override - { - if (parent) - { - const std::string title = "remote-override"; - ClientAPI::RemoteOverride ro; - try { - parent->remote_override(ro); - } - catch (const std::exception& e) - { - ro.error = e.what(); - } - RemoteList::Item::Ptr ri(new RemoteList::Item); - if (ro.error.empty()) - { - if (!ro.ip.empty()) - ri->set_ip_addr(IP::Addr(ro.ip, title)); - if (ro.host.empty()) - ro.host = ro.ip; - HostPort::validate_host(ro.host, title); - HostPort::validate_port(ro.port, title); - ri->server_host = std::move(ro.host); - ri->server_port = std::move(ro.port); - ri->transport_protocol = Protocol::parse(ro.proto, Protocol::CLIENT_SUFFIX, title.c_str()); - } - else - throw Exception("remote override exception: " + ro.error); - return ri; - } - else - return RemoteList::Item::Ptr(); - } - - private: - OpenVPNClient* parent = nullptr; - }; - - class MyClockTick - { - public: - MyClockTick(openvpn_io::io_context& io_context, - OpenVPNClient* parent_arg, - const unsigned int ms) - : timer(io_context), - parent(parent_arg), - period(Time::Duration::milliseconds(ms)) - { - } - - void cancel() - { - timer.cancel(); - } - - void detach_from_parent() - { - parent = nullptr; - } - - void schedule() - { - timer.expires_after(period); - timer.async_wait([this](const openvpn_io::error_code& error) - { - if (!parent || error) - return; - try { - parent->clock_tick(); - } - catch (...) - { - } - schedule(); - }); - } - - private: - AsioTimer timer; - OpenVPNClient* parent; - const Time::Duration period; - }; - - namespace Private { - class ClientState - { - public: - // state objects - OptionList options; - EvalConfig eval; - MySocketProtect socket_protect; - MyReconnectNotify reconnect_notify; - MyRemoteOverride remote_override; - ClientCreds::Ptr creds; - MySessionStats::Ptr stats; - MyClientEvents::Ptr events; - ClientConnect::Ptr session; - std::unique_ptr clock_tick; - - // extra settings submitted by API client - std::string server_override; - std::string port_override; - Protocol proto_override; - IPv6Setting ipv6; - int conn_timeout = 0; - bool tun_persist = false; - bool wintun = false; - bool google_dns_fallback = false; - bool synchronous_dns_lookup = false; - bool autologin_sessions = false; - bool retry_on_auth_failed = false; - std::string private_key_password; - std::string external_pki_alias; - bool disable_client_cert = false; - int ssl_debug_level = 0; - int default_key_direction = -1; - std::string tls_version_min_override; - std::string tls_cert_profile_override; - std::string tls_cipher_list; - std::string tls_ciphersuite_list; - std::string gui_version; - std::string sso_methods; - bool allow_local_lan_access; - std::string hw_addr_override; - std::string platform_version; - ProtoContextOptions::Ptr proto_context_options; - PeerInfo::Set::Ptr extra_peer_info; - HTTPProxyTransport::Options::Ptr http_proxy_options; - unsigned int clock_tick_ms = 0; -#ifdef OPENVPN_GREMLIN - Gremlin::Config::Ptr gremlin_config; -#endif - bool alt_proxy = false; - bool dco = false; - bool echo = false; - bool info = false; - - // Ensure that init is called - InitProcess::Init init; - - template - void attach(OpenVPNClient* parent, - openvpn_io::io_context* io_context, - Stop* async_stop_global) - { - // only one attachment per instantiation allowed - if (attach_called) - throw Exception("ClientState::attach() can only be called once per ClientState instantiation"); - attach_called = true; - - // async stop - async_stop_global_ = async_stop_global; - - // io_context - if (io_context) - io_context_ = io_context; - else - { - io_context_ = new openvpn_io::io_context(1); // concurrency hint=1 - io_context_owned = true; - } - - // client stats - stats.reset(new SESSION_STATS(parent)); - - // client events - events.reset(new CLIENT_EVENTS(parent)); - - // socket protect - socket_protect.set_parent(parent); - RedirectGatewayFlags rg_flags{ options }; - socket_protect.set_rg_local(rg_flags.redirect_gateway_local()); - - // reconnect notifications - reconnect_notify.set_parent(parent); - - // remote override - remote_override.set_parent(parent); - } - - ClientState() {} - - ~ClientState() - { - stop_scope_local.reset(); - stop_scope_global.reset(); - socket_protect.detach_from_parent(); - reconnect_notify.detach_from_parent(); - remote_override.detach_from_parent(); - if (clock_tick) - clock_tick->detach_from_parent(); - if (stats) - stats->detach_from_parent(); - if (events) - events->detach_from_parent(); - session.reset(); - if (io_context_owned) - delete io_context_; - } - - // foreign thread access - - void enable_foreign_thread_access() - { - foreign_thread_ready.store(true, std::memory_order_release); - } - - bool is_foreign_thread_access() - { - return foreign_thread_ready.load(std::memory_order_acquire); - } - - // io_context - - openvpn_io::io_context* io_context() - { - return io_context_; - } - - // async stop - - Stop* async_stop_local() - { - return &async_stop_local_; - } - - Stop* async_stop_global() - { - return async_stop_global_; - } - - void trigger_async_stop_local() - { - async_stop_local_.stop(); - } - - // disconnect - void on_disconnect() - { - if (clock_tick) - clock_tick->cancel(); - } - - void setup_async_stop_scopes() - { - stop_scope_local.reset(new AsioStopScope(*io_context(), async_stop_local(), [this]() { - OPENVPN_ASYNC_HANDLER; - session->graceful_stop(); - })); - - stop_scope_global.reset(new AsioStopScope(*io_context(), async_stop_global(), [this]() { - OPENVPN_ASYNC_HANDLER; - trigger_async_stop_local(); - })); - } - - private: - ClientState(const ClientState&) = delete; - ClientState& operator=(const ClientState&) = delete; - - bool attach_called = false; - - Stop async_stop_local_; - Stop* async_stop_global_ = nullptr; - - std::unique_ptr stop_scope_local; - std::unique_ptr stop_scope_global; - - openvpn_io::io_context* io_context_ = nullptr; - bool io_context_owned = false; - - std::atomic foreign_thread_ready{false}; - }; - }; - - OPENVPN_CLIENT_EXPORT OpenVPNClient::OpenVPNClient() - { -#ifndef OPENVPN_NORESET_TIME - // We keep track of time as binary milliseconds since a time base, and - // this can wrap after ~48 days on 32 bit systems, so it's a good idea - // to periodically reinitialize the base. - Time::reset_base_conditional(); -#endif - - state = new Private::ClientState(); - state->proto_context_options.reset(new ProtoContextOptions()); - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::parse_config(const Config& config, EvalConfig& eval, OptionList& options) - { - try { - // validate proto_override - if (!config.protoOverride.empty()) - Protocol::parse(config.protoOverride, Protocol::NO_SUFFIX); - - // validate IPv6 setting - if (!config.ipv6.empty()) - IPv6Setting::parse(config.ipv6); - - // parse config - OptionList::KeyValueList kvl; - kvl.reserve(config.contentList.size()); - for (size_t i = 0; i < config.contentList.size(); ++i) - { - const KeyValue& kv = config.contentList[i]; - kvl.push_back(new OptionList::KeyValue(kv.key, kv.value)); - } - const ParseClientConfig cc = ParseClientConfig::parse(config.content, &kvl, options); -#ifdef OPENVPN_DUMP_CONFIG - std::cout << "---------- ARGS ----------" << std::endl; - std::cout << options.render(Option::RENDER_PASS_FMT|Option::RENDER_NUMBER|Option::RENDER_BRACKET) << std::endl; - std::cout << "---------- MAP ----------" << std::endl; - std::cout << options.render_map() << std::endl; -#endif - eval.error = cc.error(); - eval.message = cc.message(); - eval.userlockedUsername = cc.userlockedUsername(); - eval.profileName = cc.profileName(); - eval.friendlyName = cc.friendlyName(); - eval.autologin = cc.autologin(); - eval.externalPki = cc.externalPki(); - eval.staticChallenge = cc.staticChallenge(); - eval.staticChallengeEcho = cc.staticChallengeEcho(); - eval.privateKeyPasswordRequired = cc.privateKeyPasswordRequired(); - eval.allowPasswordSave = cc.allowPasswordSave(); - eval.remoteHost = config.serverOverride.empty() ? cc.firstRemoteListItem().host : config.serverOverride; - eval.remotePort = cc.firstRemoteListItem().port; - eval.remoteProto = cc.firstRemoteListItem().proto; - eval.windowsDriver = cc.windowsDriver(); - for (ParseClientConfig::ServerList::const_iterator i = cc.serverList().begin(); i != cc.serverList().end(); ++i) - { - ServerEntry se; - se.server = i->server; - se.friendlyName = i->friendlyName; - eval.serverList.push_back(se); - } - } - catch (const std::exception& e) - { - eval.error = true; - eval.message = Unicode::utf8_printable(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::parse_extras(const Config& config, EvalConfig& eval) - { - try { - state->server_override = config.serverOverride; - state->port_override = config.portOverride; - state->conn_timeout = config.connTimeout; - state->tun_persist = config.tunPersist; - state->wintun = config.wintun; - state->google_dns_fallback = config.googleDnsFallback; - state->synchronous_dns_lookup = config.synchronousDnsLookup; - state->autologin_sessions = config.autologinSessions; - state->retry_on_auth_failed = config.retryOnAuthFailed; - state->private_key_password = config.privateKeyPassword; - if (!config.protoOverride.empty()) - state->proto_override = Protocol::parse(config.protoOverride, Protocol::NO_SUFFIX); - if (!config.ipv6.empty()) - state->ipv6 = IPv6Setting::parse(config.ipv6); - if (!config.compressionMode.empty()) - state->proto_context_options->parse_compression_mode(config.compressionMode); - if (eval.externalPki) - state->external_pki_alias = config.externalPkiAlias; - state->disable_client_cert = config.disableClientCert; - state->ssl_debug_level = config.sslDebugLevel; - state->default_key_direction = config.defaultKeyDirection; - state->tls_version_min_override = config.tlsVersionMinOverride; - state->tls_cert_profile_override = config.tlsCertProfileOverride; - state->tls_cipher_list = config.tlsCipherList; - state->tls_ciphersuite_list = config.tlsCiphersuitesList; - state->allow_local_lan_access = config.allowLocalLanAccess; - state->gui_version = config.guiVersion; - state->sso_methods = config.ssoMethods; - state->platform_version = config.platformVersion; - state->hw_addr_override = config.hwAddrOverride; - state->alt_proxy = config.altProxy; - state->dco = config.dco; - state->echo = config.echo; - state->info = config.info; - state->clock_tick_ms = config.clockTickMS; - if (!config.gremlinConfig.empty()) - { -#ifdef OPENVPN_GREMLIN - state->gremlin_config.reset(new Gremlin::Config(config.gremlinConfig)); -#else - throw Exception("client not built with OPENVPN_GREMLIN"); -#endif - } - state->extra_peer_info = PeerInfo::Set::new_from_foreign_set(config.peerInfo); - if (!config.proxyHost.empty()) - { - HTTPProxyTransport::Options::Ptr ho(new HTTPProxyTransport::Options()); - ho->set_proxy_server(config.proxyHost, config.proxyPort); - ho->username = config.proxyUsername; - ho->password = config.proxyPassword; - ho->allow_cleartext_auth = config.proxyAllowCleartextAuth; - state->http_proxy_options = ho; - } - } - catch (const std::exception& e) - { - eval.error = true; - eval.message = Unicode::utf8_printable(e.what(), 256); - } - } - - OPENVPN_CLIENT_EXPORT long OpenVPNClient::max_profile_size() - { - return ProfileParseLimits::MAX_PROFILE_SIZE; - } - - OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::merge_config_static(const std::string& path, - bool follow_references) - { - ProfileMerge pm(path, "ovpn", "", follow_references ? ProfileMerge::FOLLOW_PARTIAL : ProfileMerge::FOLLOW_NONE, - ProfileParseLimits::MAX_LINE_SIZE, ProfileParseLimits::MAX_PROFILE_SIZE); - return build_merge_config(pm); - } - - OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::merge_config_string_static(const std::string& config_content) - { - ProfileMergeFromString pm(config_content, "", ProfileMerge::FOLLOW_NONE, - ProfileParseLimits::MAX_LINE_SIZE, ProfileParseLimits::MAX_PROFILE_SIZE); - return build_merge_config(pm); - } - - OPENVPN_CLIENT_EXPORT MergeConfig OpenVPNClient::build_merge_config(const ProfileMerge& pm) - { - MergeConfig ret; - ret.status = pm.status_string(); - ret.basename = pm.basename(); - if (pm.status() == ProfileMerge::MERGE_SUCCESS) - { - ret.refPathList = pm.ref_path_list(); - ret.profileContent = pm.profile_content(); - } - else - { - ret.errorText = pm.error(); - } - return ret; - } - - OPENVPN_CLIENT_EXPORT EvalConfig OpenVPNClient::eval_config_static(const Config& config) - { - EvalConfig eval; - OptionList options; - parse_config(config, eval, options); - return eval; - } - - // API client submits the configuration here before calling connect() - OPENVPN_CLIENT_EXPORT EvalConfig OpenVPNClient::eval_config(const Config& config) - { - // parse and validate configuration file - EvalConfig eval; - parse_config(config, eval, state->options); - if (eval.error) - return eval; - - // handle extra settings in config - parse_extras(config, eval); - state->eval = eval; - return eval; - } - - OPENVPN_CLIENT_EXPORT Status OpenVPNClient::provide_creds(const ProvideCreds& creds) - { - Status ret; - try { - ClientCreds::Ptr cc = new ClientCreds(); - cc->set_username(creds.username); - cc->set_password(creds.password); - cc->set_response(creds.response); - cc->set_dynamic_challenge_cookie(creds.dynamicChallengeCookie, creds.username); - cc->set_replace_password_with_session_id(creds.replacePasswordWithSessionID); - cc->enable_password_cache(creds.cachePassword); - state->creds = cc; - } - catch (const std::exception& e) - { - ret.error = true; - ret.message = Unicode::utf8_printable(e.what(), 256); - } - return ret; - } - - OPENVPN_CLIENT_EXPORT bool OpenVPNClient::socket_protect(int socket, std::string remote, bool ipv6) - { - return true; - } - - OPENVPN_CLIENT_EXPORT bool OpenVPNClient::parse_dynamic_challenge(const std::string& cookie, DynamicChallenge& dc) - { - try { - ChallengeResponse cr(cookie); - dc.challenge = cr.get_challenge_text(); - dc.echo = cr.get_echo(); - dc.responseRequired = cr.get_response_required(); - dc.stateID = cr.get_state_id(); - return true; - } - catch (const std::exception&) - { - return false; - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::process_epki_cert_chain(const ExternalPKICertRequest& req) - { - // Get cert and add to options list - if (!req.cert.empty()) - { - Option o; - o.push_back("cert"); - o.push_back(req.cert); - state->options.add_item(o); - } - - // Get the supporting chain, if it exists, and use - // it for ca (if ca isn't defined), or otherwise use - // it for extra-certs (if ca is defined but extra-certs - // is not). - if (!req.supportingChain.empty()) - { - if (!state->options.exists("ca")) - { - Option o; - o.push_back("ca"); - o.push_back(req.supportingChain); - state->options.add_item(o); - } - else if (!state->options.exists("extra-certs")) - { - Option o; - o.push_back("extra-certs"); - o.push_back(req.supportingChain); - state->options.add_item(o); - } - } - } - - OPENVPN_CLIENT_EXPORT Status OpenVPNClient::connect() - { -#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD) - openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread -#endif -#if defined(OPENVPN_LOG_LOGTHREAD_H) && !defined(OPENVPN_LOG_LOGBASE_H) -#ifdef OPENVPN_LOG_GLOBAL -#error ovpn3 core logging object only supports thread-local scope -#endif - Log::Context log_context(this); -#endif - - OPENVPN_LOG(ClientAPI::OpenVPNClient::platform()); - - return do_connect(); - } - - OPENVPN_CLIENT_EXPORT Status OpenVPNClient::do_connect() - { - Status status; - bool session_started = false; - try { - connect_attach(); -#if defined(OPENVPN_OVPNCLI_ASYNC_SETUP) - openvpn_io::post(*state->io_context(), [this]() { - do_connect_async(); - }); -#else - connect_setup(status, session_started); -#endif - connect_run(); - return status; - } - catch (const std::exception& e) - { - if (session_started) - connect_session_stop(); - return status_from_exception(e); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::do_connect_async() - { - enum StopType { - NONE, - SESSION, - EXPLICIT, - }; - StopType stop_type = NONE; - Status status; - bool session_started = false; - try { - connect_setup(status, session_started); - } - catch (const std::exception& e) - { - stop_type = session_started ? SESSION : EXPLICIT; - status = status_from_exception(e); - } - if (status.error) - { - ClientEvent::Base::Ptr ev = new ClientEvent::ClientSetup(status.status, status.message); - state->events->add_event(std::move(ev)); - } - if (stop_type == SESSION) - connect_session_stop(); -#ifdef OPENVPN_IO_REQUIRES_STOP - if (stop_type == EXPLICIT) - state->io_context()->stop(); -#endif - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_setup(Status& status, bool& session_started) - { - // set global MbedTLS debug level -#if defined(USE_MBEDTLS) || defined(USE_MBEDTLS_APPLE_HYBRID) - mbedtls_debug_set_threshold(state->ssl_debug_level); // fixme -- using a global method for this seems wrong -#endif - - // load options - ClientOptions::Config cc; - cc.cli_stats = state->stats; - cc.cli_events = state->events; - cc.server_override = state->server_override; - cc.port_override = state->port_override; - cc.proto_override = state->proto_override; - cc.ipv6 = state->ipv6; - cc.conn_timeout = state->conn_timeout; - cc.tun_persist = state->tun_persist; - cc.wintun = state->wintun; - cc.google_dns_fallback = state->google_dns_fallback; - cc.synchronous_dns_lookup = state->synchronous_dns_lookup; - cc.autologin_sessions = state->autologin_sessions; - cc.retry_on_auth_failed = state->retry_on_auth_failed; - cc.proto_context_options = state->proto_context_options; - cc.http_proxy_options = state->http_proxy_options; - cc.alt_proxy = state->alt_proxy; - cc.dco = state->dco; - cc.echo = state->echo; - cc.info = state->info; - cc.reconnect_notify = &state->reconnect_notify; - if (remote_override_enabled()) - cc.remote_override = &state->remote_override; - cc.private_key_password = state->private_key_password; - cc.disable_client_cert = state->disable_client_cert; - cc.ssl_debug_level = state->ssl_debug_level; - cc.default_key_direction = state->default_key_direction; - cc.tls_version_min_override = state->tls_version_min_override; - cc.tls_cert_profile_override = state->tls_cert_profile_override; - cc.tls_cipher_list = state->tls_cipher_list; - cc.tls_ciphersuite_list = state->tls_ciphersuite_list; - cc.gui_version = state->gui_version; - cc.sso_methods = state->sso_methods; - cc.hw_addr_override = state->hw_addr_override; - cc.platform_version = state->platform_version; - cc.extra_peer_info = state->extra_peer_info; - cc.stop = state->async_stop_local(); - cc.allow_local_lan_access = state->allow_local_lan_access; -#ifdef OPENVPN_GREMLIN - cc.gremlin_config = state->gremlin_config; -#endif - cc.socket_protect = &state->socket_protect; -#if defined(USE_TUN_BUILDER) - cc.builder = this; -#endif -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) - cc.extern_tun_factory = this; -#endif -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) - cc.extern_transport_factory = this; -#endif - // force Session ID use and disable password cache if static challenge is enabled - if (state->creds - && !state->creds->get_replace_password_with_session_id() - && !state->eval.autologin - && !state->eval.staticChallenge.empty()) - { - state->creds->set_replace_password_with_session_id(true); - state->creds->enable_password_cache(false); - } - - // external PKI -#if !defined(USE_APPLE_SSL) - if (state->eval.externalPki && !state->disable_client_cert) - { - if (!state->external_pki_alias.empty()) - { - ExternalPKICertRequest req; - req.alias = state->external_pki_alias; - external_pki_cert_request(req); - if (!req.error) - { - cc.external_pki = this; - process_epki_cert_chain(req); - } - else - { - external_pki_error(req, Error::EPKI_CERT_ERROR); - return; - } - } - else - { - status.error = true; - status.message = "Missing External PKI alias"; - return; - } - } -#endif - -#ifdef USE_OPENSSL - if (state->options.exists("allow-name-constraints")) - { - ClientEvent::Base::Ptr ev = new ClientEvent::UnsupportedFeature("allow-name-constraints", - "Always verified correctly with OpenSSL", false); - state->events->add_event(std::move(ev)); - } -#endif - - // build client options object - ClientOptions::Ptr client_options = new ClientOptions(state->options, cc); - - // configure creds in options - client_options->submit_creds(state->creds); - - // instantiate top-level client session - state->session.reset(new ClientConnect(*state->io_context(), client_options)); - - // convenience clock tick - if (state->clock_tick_ms) - { - state->clock_tick.reset(new MyClockTick(*state->io_context(), this, state->clock_tick_ms)); - state->clock_tick->schedule(); - } - - // raise an exception if app has expired - check_app_expired(); - - // start VPN - state->session->start(); // queue reads on socket/tun - session_started = true; - - // wire up async stop - state->setup_async_stop_scopes(); - - // prepare to start reactor - connect_pre_run(); - state->enable_foreign_thread_access(); - } - - OPENVPN_CLIENT_EXPORT Status OpenVPNClient::status_from_exception(const std::exception& e) - { - Status ret; - ret.error = true; - ret.message = Unicode::utf8_printable(e.what(), 256); - - // if exception is an ExceptionCode, translate the code - // to return status string - { - const ExceptionCode *ec = dynamic_cast(&e); - if (ec && ec->code_defined()) - ret.status = Error::name(ec->code()); - } - return ret; - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_attach() - { - state->attach(this, - nullptr, - get_async_stop()); - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_pre_run() - { - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_run() - { - state->io_context()->run(); - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::connect_session_stop() - { - state->session->stop(); // On exception, stop client... - state->io_context()->poll(); // and execute completion handlers. - } - - OPENVPN_CLIENT_EXPORT ConnectionInfo OpenVPNClient::connection_info() - { - ConnectionInfo ci; - if (state->is_foreign_thread_access()) - { - MyClientEvents* events = state->events.get(); - if (events) - events->get_connection_info(ci); - } - return ci; - } - - OPENVPN_CLIENT_EXPORT bool OpenVPNClient::session_token(SessionToken& tok) - { - if (state->is_foreign_thread_access()) - { - ClientCreds* cc = state->creds.get(); - if (cc && cc->session_id_defined()) - { - tok.username = cc->get_username(); - tok.session_id = cc->get_password(); - return true; - } - } - return false; - } - - OPENVPN_CLIENT_EXPORT Stop* OpenVPNClient::get_async_stop() - { - return nullptr; - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::external_pki_error(const ExternalPKIRequestBase& req, const size_t err_type) - { - if (req.error) - { - if (req.invalidAlias) - { - ClientEvent::Base::Ptr ev = new ClientEvent::EpkiInvalidAlias(req.alias); - state->events->add_event(std::move(ev)); - } - - ClientEvent::Base::Ptr ev = new ClientEvent::EpkiError(req.errorText); - state->events->add_event(std::move(ev)); - - state->stats->error(err_type); - if (state->session) - state->session->dont_restart(); - } - } - - OPENVPN_CLIENT_EXPORT bool OpenVPNClient::sign(const std::string& data, std::string& sig, const std::string& algorithm) - { - ExternalPKISignRequest req; - req.data = data; - req.alias = state->external_pki_alias; - req.algorithm = algorithm; - external_pki_sign_request(req); // call out to derived class for RSA signature - if (!req.error) - { - sig = req.sig; - return true; - } - else - { - external_pki_error(req, Error::EPKI_SIGN_ERROR); - return false; - } - } - - OPENVPN_CLIENT_EXPORT bool OpenVPNClient::remote_override_enabled() - { - return false; - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::remote_override(RemoteOverride&) - { - } - - OPENVPN_CLIENT_EXPORT int OpenVPNClient::stats_n() - { - return (int)MySessionStats::combined_n(); - } - - OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::stats_name(int index) - { - return MySessionStats::combined_name(index); - } - - OPENVPN_CLIENT_EXPORT long long OpenVPNClient::stats_value(int index) const - { - if (state->is_foreign_thread_access()) - { - MySessionStats* stats = state->stats.get(); - if (stats) - { - if (index == SessionStats::BYTES_IN || index == SessionStats::BYTES_OUT) - stats->dco_update(); - return stats->combined_value(index); - } - } - return 0; - } - - OPENVPN_CLIENT_EXPORT std::vector OpenVPNClient::stats_bundle() const - { - std::vector sv; - const size_t n = MySessionStats::combined_n(); - sv.reserve(n); - if (state->is_foreign_thread_access()) - { - MySessionStats* stats = state->stats.get(); - if (stats) - stats->dco_update(); - for (size_t i = 0; i < n; ++i) - sv.push_back(stats ? stats->combined_value(i) : 0); - } - else - { - for (size_t i = 0; i < n; ++i) - sv.push_back(0); - } - return sv; - } - - OPENVPN_CLIENT_EXPORT InterfaceStats OpenVPNClient::tun_stats() const - { - InterfaceStats ret; - if (state->is_foreign_thread_access()) - { - MySessionStats* stats = state->stats.get(); - - // The reason for the apparent inversion between in/out below is - // that TUN_*_OUT stats refer to data written to tun device, - // but from the perspective of tun interface, this is incoming - // data. Vice versa for TUN_*_IN. - if (stats) - { - ret.bytesOut = stats->stat_count(SessionStats::TUN_BYTES_IN); - ret.bytesIn = stats->stat_count(SessionStats::TUN_BYTES_OUT); - ret.packetsOut = stats->stat_count(SessionStats::TUN_PACKETS_IN); - ret.packetsIn = stats->stat_count(SessionStats::TUN_PACKETS_OUT); - ret.errorsOut = stats->error_count(Error::TUN_READ_ERROR); - ret.errorsIn = stats->error_count(Error::TUN_WRITE_ERROR); - return ret; - } - } - - ret.bytesOut = 0; - ret.bytesIn = 0; - ret.packetsOut = 0; - ret.packetsIn = 0; - ret.errorsOut = 0; - ret.errorsIn = 0; - return ret; - } - - OPENVPN_CLIENT_EXPORT TransportStats OpenVPNClient::transport_stats() const - { - TransportStats ret; - ret.lastPacketReceived = -1; // undefined - - if (state->is_foreign_thread_access()) - { - MySessionStats* stats = state->stats.get(); - if (stats) - { - stats->dco_update(); - ret.bytesOut = stats->stat_count(SessionStats::BYTES_OUT); - ret.bytesIn = stats->stat_count(SessionStats::BYTES_IN); - ret.packetsOut = stats->stat_count(SessionStats::PACKETS_OUT); - ret.packetsIn = stats->stat_count(SessionStats::PACKETS_IN); - - // calculate time since last packet received - { - const Time& lpr = stats->last_packet_received(); - if (lpr.defined()) - { - const Time::Duration dur = Time::now() - lpr; - const unsigned int delta = (unsigned int)dur.to_binary_ms(); - if (delta <= 60*60*24*1024) // only define for time periods <= 1 day - ret.lastPacketReceived = delta; - } - } - return ret; - } - } - - ret.bytesOut = 0; - ret.bytesIn = 0; - ret.packetsOut = 0; - ret.packetsIn = 0; - return ret; - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::stop() - { - if (state->is_foreign_thread_access()) - state->trigger_async_stop_local(); - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::pause(const std::string& reason) - { - if (state->is_foreign_thread_access()) - { - ClientConnect* session = state->session.get(); - if (session) - session->thread_safe_pause(reason); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::resume() - { - if (state->is_foreign_thread_access()) - { - ClientConnect* session = state->session.get(); - if (session) - session->thread_safe_resume(); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::reconnect(int seconds) - { - if (state->is_foreign_thread_access()) - { - ClientConnect* session = state->session.get(); - if (session) - session->thread_safe_reconnect(seconds); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::post_cc_msg(const std::string& msg) - { - if (state->is_foreign_thread_access()) - { - ClientConnect* session = state->session.get(); - if (session) - session->thread_safe_post_cc_msg(msg); - } - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::clock_tick() - { - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::on_disconnect() - { - state->on_disconnect(); - } - - OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::crypto_self_test() - { - return SelfTest::crypto_self_test(); - } - - OPENVPN_CLIENT_EXPORT int OpenVPNClient::app_expire() - { -#ifdef APP_EXPIRE_TIME - return APP_EXPIRE_TIME; -#else - return 0; -#endif - } - - OPENVPN_CLIENT_EXPORT void OpenVPNClient::check_app_expired() - { -#ifdef APP_EXPIRE_TIME - if (Time::now().seconds_since_epoch() >= APP_EXPIRE_TIME) - throw app_expired(); -#endif - } - - OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::copyright() - { - return openvpn_copyright; - } - - OPENVPN_CLIENT_EXPORT std::string OpenVPNClient::platform() - { - std::string ret = platform_string(); -#ifdef PRIVATE_TUNNEL_PROXY - ret += " PT_PROXY"; -#endif -#ifdef ENABLE_KOVPN - ret += " KOVPN"; -#elif ENABLE_OVPNDCO - ret += " OVPN-DCO"; -#endif -#ifdef OPENVPN_GREMLIN - ret += " GREMLIN"; -#endif -#ifdef OPENVPN_DEBUG - ret += " built on " __DATE__ " " __TIME__; -#endif - return ret; - } - - OPENVPN_CLIENT_EXPORT OpenVPNClient::~OpenVPNClient() - { - delete state; - } - } -} diff --git a/Sources/OpenVPN3/client/ovpncli.hpp b/Sources/OpenVPN3/client/ovpncli.hpp deleted file mode 100644 index c711dc0..0000000 --- a/Sources/OpenVPN3/client/ovpncli.hpp +++ /dev/null @@ -1,636 +0,0 @@ -// 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-2020 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 . - -// API for OpenVPN Client, may be used standalone or wrapped by swig. -// Use ovpncli.i to wrap the API for swig. -// The crux of the API is defined in OpenVPNClient (below) -// and TunBuilderBase. - -#include -#include -#include - -#include -#include -#include -#include - -namespace openvpn { - class OptionList; - class ProfileMerge; - class Stop; - - namespace ClientAPI { - // Represents an OpenVPN server and its friendly name - // (client reads) - struct ServerEntry - { - std::string server; - std::string friendlyName; - }; - - // return properties of config - // (client reads) - struct EvalConfig - { - // true if error - bool error = false; - - // if error, message given here - std::string message; - - // this username must be used with profile - std::string userlockedUsername; - - // profile name of config - std::string profileName; - - // "friendly" name of config - std::string friendlyName; - - // true: no creds required, false: username/password required - bool autologin = false; - - // if true, this is an External PKI profile (no cert or key directives) - bool externalPki = false; - - // static challenge, may be empty, ignored if autologin - std::string staticChallenge; - - // true if static challenge response should be echoed to UI, ignored if autologin - bool staticChallengeEcho = false; - - // true if this profile requires a private key password - bool privateKeyPasswordRequired = false; - - // true if user is allowed to save authentication password in UI - bool allowPasswordSave = false; - - // information about the first remote item in config - std::string remoteHost; // will be overridden by Config::serverOverride if defined - std::string remotePort; - std::string remoteProto; - - // optional list of user-selectable VPN servers - std::vector serverList; - - // optional, values are "tap-windows6" and "wintun" - std::string windowsDriver; - }; - - // used to pass credentials to VPN core - // (client writes) - struct ProvideCreds - { - std::string username; - std::string password; - - // response to challenge - std::string response; - - // Dynamic challenge/response cookie - std::string dynamicChallengeCookie; - - // If true, on successful connect, we will replace the password - // with the session ID we receive from the server (if provided). - // If false, the password will be cached for future reconnects - // and will not be replaced with a session ID, even if the - // server provides one. - bool replacePasswordWithSessionID = false; - - // If true, and if replacePasswordWithSessionID is true, and if - // we actually receive a session ID from the server, cache - // the user-provided password for future use before replacing - // the active password with the session ID. - bool cachePassword = false; - }; - - // used to get session token from VPN core - // (client reads) - struct SessionToken - { - std::string username; - std::string session_id; // an OpenVPN Session ID, used as a proxy for password - }; - - // used to query challenge/response from user - // (client reads) - struct DynamicChallenge - { - std::string challenge; - bool echo = false; - bool responseRequired = false; - - std::string stateID; - }; - - // a basic key/value pair, used in Config below when OpenVPN profile is - // passed as a dictionary - struct KeyValue - { - KeyValue() {} - - KeyValue(std::string key_arg, std::string value_arg) - : key(std::move(key_arg)), - value(std::move(value_arg)) {} - - std::string key; - std::string value; - }; - - // OpenVPN config-file/profile - // (client writes) - struct Config - { - // OpenVPN profile as a string - std::string content; - - // OpenVPN profile as series of key/value pairs (may be provided exclusively - // or in addition to content string above). - std::vector contentList; - - // Set to identity OpenVPN GUI version. - // Format should be "" - // Passed to server as IV_GUI_VER. - std::string guiVersion; - - // Set to a comma seperated list of supported SSO mechanisms that may - // be signalled via INFO_PRE to the client. - // "openurl" is to continue authentication by opening an url in a browser - // "crtext" gives a challenge response in text format that needs to - // responded via control channel. ( - // Passed to the server as IV_SSO - std::string ssoMethods; - - // Override the string that is passed as IV_HWADDR to the server - std::string hwAddrOverride; - - // Set the string that is passed to the server as IV_PLAT_VER - std::string platformVersion; - - // Use a different server than that specified in "remote" - // option of profile - std::string serverOverride; - - // Use a different port than that specified in "remote" - // option of profile - std::string portOverride; - - // Force a given transport protocol - // Should be tcp, udp, or adaptive. - std::string protoOverride; - - // IPv6 preference - // no -- disable IPv6, so tunnel will be IPv4-only - // yes -- request combined IPv4/IPv6 tunnel - // default (or empty string) -- leave decision to server - std::string ipv6; - - // Connection timeout in seconds, or 0 to retry indefinitely - int connTimeout = 0; - - // Keep tun interface active during pauses or reconnections - bool tunPersist = false; - - // If true and a redirect-gateway profile doesn't also define - // DNS servers, use the standard Google DNS servers. - bool googleDnsFallback = false; - - // if true, do synchronous DNS lookup. - bool synchronousDnsLookup = false; - - // Enable autologin sessions - bool autologinSessions = true; - - // If true, consider AUTH_FAILED to be a non-fatal error, - // and retry the connection after a pause. - bool retryOnAuthFailed = false; - - // An ID used for get-certificate and RSA signing callbacks - // for External PKI profiles. - std::string externalPkiAlias; - - // If true, don't send client cert/key to peer. - bool disableClientCert = false; - - // SSL library debug level - int sslDebugLevel = 0; - - // Compression mode, one of: - // yes -- allow compression on both uplink and downlink - // asym -- allow compression on downlink only (i.e. server -> client) - // no (default if empty) -- support compression stubs only - std::string compressionMode; - - // private key password (optional) - std::string privateKeyPassword; - - // Default key direction parameter for tls-auth (0, 1, or - // -1 (bidirectional -- default)) if no key-direction parameter - // defined in profile. Generally should be -1 (bidirectional) - // for compatibility with 2.x branch - int defaultKeyDirection = -1; - - // If true, force ciphersuite to be one of: - // 1. TLS_DHE_RSA_WITH_AES_256_CBC_SHA, or - // 2. TLS_DHE_RSA_WITH_AES_128_CBC_SHA - // and disable setting TLS minimum version. - // This is intended for compatibility with legacy systems. - bool forceAesCbcCiphersuites = false; - - // Override the minimum TLS version: - // disabled -- don't specify a minimum, and disable any minimum - // specified in profile - // default or "" -- use profile minimum - // tls_1_0 -- use TLS 1.0 minimum (overrides profile) - // tls_1_1 -- use TLS 1.1 minimum (overrides profile) - // tls_1_2 -- use TLS 1.2 minimum (overrides profile) - std::string tlsVersionMinOverride; - - // Override or default the tls-cert-profile setting: - // default or "" -- use profile default - // legacy -- allow 1024-bit RSA certs signed with SHA1 - // preferred -- require at least 2048-bit RSA certs signed - // with SHA256 or higher - // suiteb -- require NSA Suite-B - // legacy-default -- use legacy as the default if profile - // doesn't specify tls-cert-profile - // preferred-default -- use preferred as the default if profile - // doesn't specify tls-cert-profile - std::string tlsCertProfileOverride; - - // Overrides the list of tls ciphers like the tls-cipher option - std::string tlsCipherList; - - // Overrides the list of TLS 1.3 ciphersuites like the tls-ciphersuites - // option - std::string tlsCiphersuitesList; - - // Pass custom key/value pairs to OpenVPN server. - std::vector peerInfo; - - // HTTP Proxy parameters (optional) - std::string proxyHost; // hostname or IP address of proxy - std::string proxyPort; // port number of proxy - std::string proxyUsername; // proxy credentials (optional) - std::string proxyPassword; // proxy credentials (optional) - bool proxyAllowCleartextAuth = false; // enables HTTP Basic auth - - // Custom proxy implementation - bool altProxy = false; - - // Custom Data Channel Offload implementation - bool dco = false; - - // pass through pushed "echo" directives via "ECHO" event - bool echo = false; - - // pass through control channel INFO notifications via "INFO" event - bool info = false; - - // Allow access to local LAN. This is for platforms like - // Android that disable local LAN access by default. - bool allowLocalLanAccess = false; - - // Periodic convenience clock tick in milliseconds. - // Will call clock_tick() at a frequency defined by this parameter. - // Set to 0 to disable. - unsigned int clockTickMS = 0; - - // Gremlin configuration (requires that the core is built with OPENVPN_GREMLIN) - std::string gremlinConfig; - - // Use wintun instead of tap-windows6 on Windows - bool wintun = false; - }; - - // used to communicate VPN events such as connect, disconnect, etc. - // (client reads) - struct Event - { - bool error = false; // true if error (fatal or nonfatal) - bool fatal = false; // true if fatal error (will disconnect) - std::string name; // event name - std::string info; // additional event info - }; - - // used to communicate extra details about successful connection - // (client reads) - struct ConnectionInfo - { - bool defined = false; - std::string user; - std::string serverHost; - std::string serverPort; - std::string serverProto; - std::string serverIp; - std::string vpnIp4; - std::string vpnIp6; - std::string gw4; - std::string gw6; - std::string clientIp; - std::string tunName; - }; - - // returned by some methods as a status/error indication - // (client reads) - struct Status - { - bool error = false; // true if error - std::string status; // an optional short error label that identifies the error - std::string message; // if error, message given here - }; - - // used to pass log lines - // (client reads) - struct LogInfo - { - LogInfo() {} - LogInfo(std::string str) - : text(std::move(str)) {} - std::string text; // log output (usually but not always one line) - }; - - // receives log messages - struct LogReceiver - { - virtual void log(const LogInfo&) = 0; - virtual ~LogReceiver() {} - }; - - // used to pass stats for an interface - struct InterfaceStats - { - long long bytesIn; - long long packetsIn; - long long errorsIn; - long long bytesOut; - long long packetsOut; - long long errorsOut; - }; - - // used to pass basic transport stats - struct TransportStats - { - long long bytesIn; - long long bytesOut; - long long packetsIn; - long long packetsOut; - - // number of binary milliseconds (1/1024th of a second) since - // last packet was received, or -1 if undefined - int lastPacketReceived; - }; - - // return value of merge_config methods - struct MergeConfig - { - std::string status; // ProfileMerge::Status codes rendered as string - std::string errorText; // error string (augments status) - std::string basename; // profile basename - std::string profileContent; // unified profile - std::vector refPathList; // list of all reference paths successfully read - }; - - // base class for External PKI queries - struct ExternalPKIRequestBase - { - bool error = false; // true if error occurred (client writes) - std::string errorText; // text describing error (client writes) - bool invalidAlias = false; // true if the error is caused by an invalid alias (client writes) - std::string alias; // the alias string, used to query cert/key (client reads) - }; - - // used to query for External PKI certificate - struct ExternalPKICertRequest : public ExternalPKIRequestBase - { - // leaf cert - std::string cert; // (client writes) - - // chain of intermediates and root (optional) - std::string supportingChain; // (client writes) - }; - - // Used to request an RSA signature. - // algorithm will determinate what signature is expected: - // RSA_PKCS1_PADDING means that - // data will be prefixed by an optional PKCS#1 digest prefix - // per RFC 3447. - // RSA_NO_PADDING mean so no padding should be done be the callee - struct ExternalPKISignRequest : public ExternalPKIRequestBase - { - std::string data; // data rendered as base64 (client reads) - std::string sig; // RSA signature, rendered as base64 (client writes) - std::string algorithm; - }; - - // used to override "remote" directives - struct RemoteOverride - { - // components of "remote" directive (client writes), - std::string host; // either one of host - std::string ip; // or ip must be defined (or both) - std::string port; - std::string proto; - std::string error; // if non-empty, indicates an error - }; - - namespace Private { - class ClientState; - }; - - // Top-level OpenVPN client class. - class OpenVPNClient : public TunBuilderBase, // expose tun builder virtual methods - public LogReceiver, // log message notification - public ExternalTun::Factory, // low-level tun override - public ExternalTransport::Factory,// low-level transport override - private ExternalPKIBase - { - public: - OpenVPNClient(); - virtual ~OpenVPNClient(); - - // Read an OpenVPN profile that might contain external - // file references, returning a unified profile. - static MergeConfig merge_config_static(const std::string& path, bool follow_references); - - // Read an OpenVPN profile that might contain external - // file references, returning a unified profile. - static MergeConfig merge_config_string_static(const std::string& config_content); - - // Parse profile and determine needed credentials statically. - static EvalConfig eval_config_static(const Config& config); - - // Maximum size of profile that should be allowed - static long max_profile_size(); - - // Parse a dynamic challenge cookie, placing the result in dc. - // Return true on success or false if parse error. - static bool parse_dynamic_challenge(const std::string& cookie, DynamicChallenge& dc); - - // Parse OpenVPN configuration file. - EvalConfig eval_config(const Config&); - - // Provide credentials and other options. Call before connect(). - Status provide_creds(const ProvideCreds&); - - // Callback to "protect" a socket from being routed through the tunnel. - // Will be called from the thread executing connect(). - // The remote and ipv6 are the remote host this socket will connect to - virtual bool socket_protect(int socket, std::string remote, bool ipv6); - - // Primary VPN client connect method, doesn't return until disconnect. - // Should be called by a worker thread. This method will make callbacks - // to event() and log() functions. Make sure to call eval_config() - // and possibly provide_creds() as well before this function. - Status connect(); - - // Return information about the most recent connection. Should be called - // after an event of type "CONNECTED". - ConnectionInfo connection_info(); - - // Writes current session token to tok and returns true. - // If session token is unavailable, false is returned and - // tok is unmodified. - bool session_token(SessionToken& tok); - - // Stop the client. Only meaningful when connect() is running. - // May be called asynchronously from a different thread - // when connect() is running. - void stop(); - - // Pause the client -- useful to avoid continuous reconnection attempts - // when network is down. May be called from a different thread - // when connect() is running. - void pause(const std::string& reason); - - // Resume the client after it has been paused. May be called from a - // different thread when connect() is running. - void resume(); - - // Do a disconnect/reconnect cycle n seconds from now. May be called - // from a different thread when connect() is running. - void reconnect(int seconds); - - // When a connection is close to timeout, the core will call this - // method. If it returns false, the core will disconnect with a - // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE - // state. - virtual bool pause_on_connection_timeout() = 0; - - // Get stats/error info. May be called from a different thread - // when connect() is running. - - // number of stats - static int stats_n(); - - // return a stats name, index should be >= 0 and < stats_n() - static std::string stats_name(int index); - - // return a stats value, index should be >= 0 and < stats_n() - long long stats_value(int index) const; - - // return all stats in a bundle - std::vector stats_bundle() const; - - // return tun stats only - InterfaceStats tun_stats() const; - - // return transport stats only - TransportStats transport_stats() const; - - // post control channel message - void post_cc_msg(const std::string& msg); - - // Callback for delivering events during connect() call. - // Will be called from the thread executing connect(). - virtual void event(const Event&) = 0; - - // Callback for logging. - // Will be called from the thread executing connect(). - virtual void log(const LogInfo&) = 0; - - // External PKI callbacks - // Will be called from the thread executing connect(). - virtual void external_pki_cert_request(ExternalPKICertRequest&) = 0; - virtual void external_pki_sign_request(ExternalPKISignRequest&) = 0; - - // Remote override callback (disabled by default). - virtual bool remote_override_enabled(); - virtual void remote_override(RemoteOverride&); - - // Periodic convenience clock tick, controlled by Config::clockTickMS - virtual void clock_tick(); - - // Do a crypto library self test - static std::string crypto_self_test(); - - // Returns date/time of app expiration as a unix time value - static int app_expire(); - - // Returns platform description string - static std::string platform(); - - // Returns core copyright - static std::string copyright(); - - // Hide protected methods/data from SWIG -#ifdef SWIGJAVA - private: -#else - protected: -#endif - - Status do_connect(); - - virtual void connect_attach(); - virtual void connect_pre_run(); - virtual void connect_run(); - virtual void connect_session_stop(); - - virtual Stop* get_async_stop(); - - Private::ClientState* state; - - private: - void connect_setup(Status&, bool&); - void do_connect_async(); - static Status status_from_exception(const std::exception&); - static void parse_config(const Config&, EvalConfig&, OptionList&); - void parse_extras(const Config&, EvalConfig&); - void external_pki_error(const ExternalPKIRequestBase&, const size_t); - void process_epki_cert_chain(const ExternalPKICertRequest&); - void check_app_expired(); - static MergeConfig build_merge_config(const ProfileMerge&); - - friend class MyClientEvents; - void on_disconnect(); - - // from ExternalPKIBase - virtual bool sign(const std::string& data, std::string& sig, const std::string& algorithm); - - // disable copy and assignment - OpenVPNClient(const OpenVPNClient&) = delete; - OpenVPNClient& operator=(const OpenVPNClient&) = delete; - }; - - } -} diff --git a/Sources/OpenVPN3/cmake/CMakeLists.txt.in b/Sources/OpenVPN3/cmake/CMakeLists.txt.in deleted file mode 100644 index dddcb36..0000000 --- a/Sources/OpenVPN3/cmake/CMakeLists.txt.in +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(googletest-download NONE) - -include(ExternalProject) -ExternalProject_Add(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.10.0 - SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" - BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - TEST_COMMAND "" - ) diff --git a/Sources/OpenVPN3/cmake/FindLZ4.cmake b/Sources/OpenVPN3/cmake/FindLZ4.cmake deleted file mode 100644 index 761b275..0000000 --- a/Sources/OpenVPN3/cmake/FindLZ4.cmake +++ /dev/null @@ -1,9 +0,0 @@ -find_path(LZ4_INCLUDE_DIR NAMES lz4.h) -find_library(LZ4_LIBRARY NAMES lz4) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS( - LZ4 DEFAULT_MSG - LZ4_LIBRARY LZ4_INCLUDE_DIR) - -mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY) \ No newline at end of file diff --git a/Sources/OpenVPN3/cmake/FindmbedTLS.cmake b/Sources/OpenVPN3/cmake/FindmbedTLS.cmake deleted file mode 100644 index a262eaf..0000000 --- a/Sources/OpenVPN3/cmake/FindmbedTLS.cmake +++ /dev/null @@ -1,63 +0,0 @@ -# - Try to find mbedTLS -# Once done this will define -# -# Read-Only variables -# MBEDTLS_FOUND - system has mbedTLS -# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory -# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory -# MBEDTLS_LIBRARIES - Link these to use mbedTLS -# MBEDTLS_LIBRARY - path to mbedTLS library -# MBEDX509_LIBRARY - path to mbedTLS X.509 library -# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library - -FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/version.h) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) - # Already in cache, be silent - SET(MBEDTLS_FIND_QUIETLY TRUE) -ENDIF() - -FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509) -FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509) -FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto) - -IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) - SET(MBEDTLS_FOUND TRUE) -ELSEIF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND NOT MBEDX509_LIBRARY AND NOT MBEDCRYPTO_LIBRARY) - SET(MBEDTLS_FOUND TRUE) - SET(HACKY_OVPN_MBEDTLS TRUE) -ENDIF() - -IF(MBEDTLS_FOUND) - IF(HACKY_OVPN_MBEDTLS) - SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY}) - ELSE() - SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) - endif() - - IF(NOT MBEDTLS_FIND_QUIETLY) - MESSAGE(STATUS "Found mbedTLS:") - FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) - STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) - IF (MBEDTLSMATCH) - STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) - MESSAGE(STATUS " version ${MBEDTLS_VERSION}") - ENDIF(MBEDTLSMATCH) - MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") - MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") - MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") - ENDIF(NOT MBEDTLS_FIND_QUIETLY) -ELSE(MBEDTLS_FOUND) - IF(mbedTLS_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find mbedTLS") - ENDIF(mbedTLS_FIND_REQUIRED) -ENDIF(MBEDTLS_FOUND) - -MARK_AS_ADVANCED( - MBEDTLS_INCLUDE_DIR - MBEDTLS_LIBRARY_DIR - MBEDTLS_LIBRARIES - MBEDTLS_LIBRARY - MBEDX509_LIBRARY - MBEDCRYPTO_LIBRARY -) \ No newline at end of file diff --git a/Sources/OpenVPN3/cmake/dlgoogletest.cmake b/Sources/OpenVPN3/cmake/dlgoogletest.cmake deleted file mode 100644 index 5b28d83..0000000 --- a/Sources/OpenVPN3/cmake/dlgoogletest.cmake +++ /dev/null @@ -1,43 +0,0 @@ -if (MSVC) - find_package(GTest CONFIG REQUIRED) - set(GTEST_LIB GTest::gtest_main) -else() - -set(GTEST_LIB gtest_main) - -# Google Test Unit testing -# Download and unpack googletest at configure time - -# Ensure that this only downloaded and added once -#include_guard(GLOBAL) -# Unfortunately include_guard requires cmake >= 3.10 -include(mypragmaonce) - -my_pragma_once() - - -configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in googletest-download/CMakeLists.txt) -execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) -if(result) - message(FATAL_ERROR "CMake step for googletest failed: ${result}") -endif() -execute_process(COMMAND ${CMAKE_COMMAND} --build . - RESULT_VARIABLE result - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) -if(result) - message(FATAL_ERROR "Build step for googletest failed: ${result}") -endif() - -# Prevent overriding the parent project's compiler/linker -# settings on Windows -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - -# Add googletest directly to our build. This defines -# the gtest and gtest_main targets. -add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src - ${CMAKE_CURRENT_BINARY_DIR}/googletest-build - EXCLUDE_FROM_ALL) - -endif () \ No newline at end of file diff --git a/Sources/OpenVPN3/cmake/findcoredeps.cmake b/Sources/OpenVPN3/cmake/findcoredeps.cmake deleted file mode 100644 index 0508477..0000000 --- a/Sources/OpenVPN3/cmake/findcoredeps.cmake +++ /dev/null @@ -1,155 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -set(CMAKE_CXX_STANDARD 14) - -#cmake_policy(SET CMP0079 NEW) - -set(CORE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) - - -set(DEP_DIR ${CORE_DIR}/../deps CACHE PATH "Dependencies") -option(USE_MBEDTLS "Use mbed TLS instead of OpenSSL") - -option(USE_WERROR "Treat compiler warnings as errors (-Werror)") - -if (DEFINED ENV{DEP_DIR}) - message("Overriding DEP_DIR setting with environment variable $ENV{DEP_DIR}") - set(DEP_DIR $ENV{DEP_DIR}) -endif () - -# Include our DEP_DIR in path used to find libraries - -if (APPLE) - set(OPENVPN_PLAT osx) -elseif (WIN32) - set(OPENVPN_PLAT amd64) -else () - set(OPENVPN_PLAT linux) -endif () - - -function(add_core_dependencies target) - set(PLAT ${OPENVPN_PLAT}) - - set(CORE_INCLUDES - ${CORE_DIR} - ) - set(CORE_DEFINES - -DASIO_STANDALONE - -DUSE_ASIO - -DHAVE_LZ4 - -DLZ4_DISABLE_DEPRECATE_WARNINGS - -DMBEDTLS_DEPRECATED_REMOVED - ) - - if (WIN32) - list(APPEND CORE_DEFINES - -D_WIN32_WINNT=0x0600 - -DTAP_WIN_COMPONENT_ID=tap0901 - -D_CRT_SECURE_NO_WARNINGS - ) - set(EXTRA_LIBS fwpuclnt.lib iphlpapi.lib wininet.lib setupapi.lib rpcrt4.lib wtsapi32.lib) - if ("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64") - # by some reasons CMake doesn't add those for ARM64 - list(APPEND EXTRA_LIBS advapi32.lib Ole32.lib Shell32.lib) - endif () - - if (MSVC) - target_compile_options(${target} PRIVATE "/bigobj") - find_package(lz4 CONFIG REQUIRED) - set(LZ4_LIBRARY lz4::lz4) - list(APPEND CORE_INCLUDES ${ASIO_INCLUDE_DIR}) - else () - find_package(Threads REQUIRED) - target_compile_options(${target} PRIVATE "-Wa,-mbig-obj") - list(APPEND EXTRA_LIBS ws2_32 wsock32 ${CMAKE_THREAD_LIBS_INIT}) - list(APPEND CMAKE_PREFIX_PATH - ${DEP_DIR} - ) - find_package(LZ4 REQUIRED) - list(APPEND CORE_INCLUDES ${DEP_DIR}/asio/asio/include) - endif () - else () - list(APPEND CORE_INCLUDES - ${DEP_DIR}/asio/asio/include - ) - list(APPEND CMAKE_PREFIX_PATH - ${DEP_DIR}/mbedtls/mbedtls-${PLAT} - ${DEP_DIR}/lz4/lz4-${PLAT} - ) - list(APPEND CMAKE_LIBRARY_PATH - ${DEP_DIR}/mbedtls/mbedtls-${PLAT}/library - ) - - find_package(LZ4 REQUIRED) - endif () - - if (${USE_MBEDTLS}) - find_package(mbedTLS REQUIRED) - - set(SSL_LIBRARY ${MBEDTLS_LIBRARIES}) - - list(APPEND CORE_DEFINES -DUSE_MBEDTLS) - - # The findmbedTLS does not set these automatically :( - list(APPEND CORE_INCLUDES ${MBEDTLS_INCLUDE_DIR}) - else () - find_package(OpenSSL REQUIRED) - SET(SSL_LIBRARY OpenSSL::SSL) - list(APPEND CORE_DEFINES -DUSE_OPENSSL) - endif () - - if (APPLE) - find_library(coreFoundation CoreFoundation) - find_library(iokit IOKit) - find_library(coreServices CoreServices) - find_library(systemConfiguration SystemConfiguration) - target_link_libraries(${target} ${coreFoundation} ${iokit} ${coreServices} ${systemConfiguration} ${lz4} ${SSL_LIBRARY}) - endif() - - if(UNIX) - target_link_libraries(${target} pthread) - endif() - - list(APPEND CORE_INCLUDES ${LZ4_INCLUDE_DIR}) - - target_include_directories(${target} PRIVATE ${CORE_INCLUDES}) - target_compile_definitions(${target} PRIVATE ${CORE_DEFINES}) - target_link_libraries(${target} ${SSL_LIBRARY} ${EXTRA_LIBS} ${LZ4_LIBRARY}) - - if (USE_WERROR) - if (MSVC) - target_compile_options(${target} PRIVATE /WX) - else () - target_compile_options(${target} PRIVATE -Werror) - endif () - endif () - - if (MSVC) - # I think this is too much currently - # target_compile_options(${target} PRIVATE /W4) - else() - target_compile_options(${target} PRIVATE -Wall -Wsign-compare) - endif() - -endfunction() - -function (add_json_library target) - if (MSVC) - find_package(jsoncpp CONFIG REQUIRED) - target_link_libraries(${target} jsoncpp_lib) - target_compile_definitions(${target} PRIVATE -DHAVE_JSONCPP) - message("Adding jsoncpp to " ${target}) - else () - find_package(PkgConfig REQUIRED) - if (MINGW) - # due to cmake bug, APPEND doesn't work for mingw - # https://github.com/Kitware/CMake/commit/f92a4b23994fa7516f16fbb5b3c02caa07534b3f - set(CMAKE_PREFIX_PATH ${DEP_DIR}) - endif () - pkg_check_modules(JSONCPP jsoncpp) - target_link_libraries(${target} ${JSONCPP_LDFLAGS}) - target_include_directories(${target} PRIVATE ${JSONCPP_INCLUDE_DIRS}) - target_compile_definitions(${target} PRIVATE -DHAVE_JSONCPP) - endif () -endfunction () diff --git a/Sources/OpenVPN3/cmake/mypragmaonce.cmake b/Sources/OpenVPN3/cmake/mypragmaonce.cmake deleted file mode 100644 index bcc5469..0000000 --- a/Sources/OpenVPN3/cmake/mypragmaonce.cmake +++ /dev/null @@ -1,8 +0,0 @@ -macro(my_pragma_once) - set(__filename "${CMAKE_CURRENT_LIST_FILE}") - get_property(already_included GLOBAL PROPERTY "pr_${__filename}") - if(already_included) - return() - endif() - set_property(GLOBAL PROPERTY "pr_${__filename}" TRUE) -endmacro() diff --git a/Sources/OpenVPN3/deps/asio/build-asio b/Sources/OpenVPN3/deps/asio/build-asio deleted file mode 100755 index 91d96a8..0000000 --- a/Sources/OpenVPN3/deps/asio/build-asio +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -PACKAGE=${ASIO_VERSION} -FNAME=${ASIO_VERSION}.tar.gz -URL=https://github.com/chriskohlhoff/asio/archive/${ASIO_VERSION}.tar.gz -CSUM=${ASIO_CSUM} -DIST=asio - -download - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source -else - echo WIPE and reunzip source - cd $DEP_DIR - rm -rf $DIST asio-$ASIO_VERSION - tar xfz $DL/$FNAME - cd asio-$ASIO_VERSION - - apply_patches "asio" - - cd .. - - cp -a asio-$ASIO_VERSION $DIST -fi diff --git a/Sources/OpenVPN3/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch b/Sources/OpenVPN3/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch deleted file mode 100644 index becea4e..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 00c0b1b7076ebc24735071f587f9501c1595a02b Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Mon, 19 Mar 2018 11:24:10 +0800 -Subject: [PATCH] Added Apple NAT64 support when both ASIO_HAS_GETADDRINFO and - ASIO_APPLE_NAT64 ar defined - -* When calling getaddrinfo(), Apple recommends to set - AI_DEFAULT flags in hint. - -* 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. ---- - asio/include/asio/detail/impl/socket_ops.ipp | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/asio/include/asio/detail/impl/socket_ops.ipp b/asio/include/asio/detail/impl/socket_ops.ipp -index ad203b74..b17a60ed 100644 ---- a/asio/include/asio/detail/impl/socket_ops.ipp -+++ b/asio/include/asio/detail/impl/socket_ops.ipp -@@ -3339,6 +3339,23 @@ asio::error_code getaddrinfo(const char* host, - # endif - #elif !defined(ASIO_HAS_GETADDRINFO) - int error = getaddrinfo_emulation(host, service, &hints, result); -+ return ec = translate_addrinfo_error(error); -+#elif defined(ASIO_HAS_GETADDRINFO) && defined(ASIO_APPLE_NAT64) -+ // For NAT64 compatibility, Apple recommends to set AI_DEFAULT flags -+ addrinfo_type new_hints = hints; -+ new_hints.ai_flags |= AI_DEFAULT; -+ int error = ::getaddrinfo(host, service, &new_hints, result); -+ -+ // iOS bug workaround: sometimes iOS getaddrinfo() returns a non-zero scope ID -+ // for non-link-local addresses. Workaround by forcing scope ID to 0 for -+ // non-link-local addresses. -+ if (!error && (*result)->ai_family == AF_INET6) -+ { -+ sockaddr_in6* a6 = (sockaddr_in6*)(*result)->ai_addr; -+ if (a6->sin6_scope_id && !(IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&a6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&a6->sin6_addr))) -+ a6->sin6_scope_id = 0; -+ } -+ - return ec = translate_addrinfo_error(error); - #else - int error = ::getaddrinfo(host, service, &hints, result); --- -2.21.0 - diff --git a/Sources/OpenVPN3/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch b/Sources/OpenVPN3/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch deleted file mode 100644 index 18ae1f7..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch +++ /dev/null @@ -1,38 +0,0 @@ -From fe57c9127cfc95b4673c6530f86edab5e6538425 Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Wed, 2 Sep 2015 12:18:48 -0700 -Subject: [PATCH] Added randomize() method to - asio::ip::tcp::resolver::results_type. - ---- - asio/include/asio/ip/basic_resolver_results.hpp | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp -index 3b3fad49..c070f7da 100644 ---- a/asio/include/asio/ip/basic_resolver_results.hpp -+++ b/asio/include/asio/ip/basic_resolver_results.hpp -@@ -18,6 +18,7 @@ - #include "asio/detail/config.hpp" - #include - #include -+#include - #include "asio/detail/socket_ops.hpp" - #include "asio/detail/socket_types.hpp" - #include "asio/ip/basic_resolver_iterator.hpp" -@@ -299,6 +300,12 @@ public: - return !a.equal(b); - } - -+ template -+ void randomize(Random& r) -+ { -+ std::shuffle(this->values_->begin(), this->values_->end(), r); -+ } -+ - private: - typedef std::vector > values_type; - }; --- -2.21.0 - diff --git a/Sources/OpenVPN3/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch b/Sources/OpenVPN3/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch deleted file mode 100644 index b377a0d..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 5e0153dd0826185575242fe594dac4777874c433 Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Mon, 27 Feb 2017 13:01:26 -0700 -Subject: [PATCH] Added user code hook async_connect_post_open() to be called - immediately after socket open in async_connect. - ---- - asio/include/asio/basic_socket.hpp | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/asio/include/asio/basic_socket.hpp b/asio/include/asio/basic_socket.hpp -index e0269678..33df2f98 100644 ---- a/asio/include/asio/basic_socket.hpp -+++ b/asio/include/asio/basic_socket.hpp -@@ -953,6 +953,8 @@ public: - { - const protocol_type protocol = peer_endpoint.protocol(); - impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); -+ if (!open_ec) -+ async_connect_post_open(protocol, open_ec); - } - - return async_initiate( -@@ -1791,7 +1793,7 @@ protected: - * This function destroys the socket, cancelling any outstanding asynchronous - * operations associated with the socket as if by calling @c cancel. - */ -- ~basic_socket() -+ virtual ~basic_socket() - { - } - -@@ -1807,6 +1809,11 @@ protected: - #endif - - private: -+ // optional user code hook immediately after socket open in async_connect -+ virtual void async_connect_post_open(const protocol_type& protocol, asio::error_code& ec) -+ { -+ } -+ - // Disallow copying and assignment. - basic_socket(const basic_socket&) ASIO_DELETED; - basic_socket& operator=(const basic_socket&) ASIO_DELETED; --- -2.26.0 - diff --git a/Sources/OpenVPN3/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch b/Sources/OpenVPN3/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch deleted file mode 100644 index 81693de..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0004-error_code.ipp-Use-English-for-Windows-error-message.patch +++ /dev/null @@ -1,29 +0,0 @@ -From af733fe9ce8345e06947dcf8b395d4736b1cb98c Mon Sep 17 00:00:00 2001 -From: Lev Stipakov -Date: Mon, 29 Apr 2019 10:26:13 +0300 -Subject: [PATCH] error_code.ipp: Use English for Windows error messages - -FormatMessageA doesn't work well with non-ASCII chars -so make it return error message in English. - -Signed-off-by: Lev Stipakov ---- - asio/include/asio/impl/error_code.ipp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/asio/include/asio/impl/error_code.ipp b/asio/include/asio/impl/error_code.ipp -index 55f5b361..3ef34fcd 100644 ---- a/asio/include/asio/impl/error_code.ipp -+++ b/asio/include/asio/impl/error_code.ipp -@@ -80,7 +80,7 @@ public: - DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, -- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); -+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (char*)&msg, 0, 0); - detail::local_free_on_block_exit local_free_obj(msg); - if (length && msg[length - 1] == '\n') - msg[--length] = '\0'; --- -2.16.2.windows.1 - diff --git a/Sources/OpenVPN3/deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch b/Sources/OpenVPN3/deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch deleted file mode 100644 index a386097..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0005-Added-kovpn-route_id-support-to-endpoints-for-sendto.patch +++ /dev/null @@ -1,155 +0,0 @@ -From df7759c141a31159d0ca4267b63f64dfd2a385b1 Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Wed, 27 Jun 2018 23:12:31 -0600 -Subject: Added kovpn route_id support to endpoints for sendto/recvfrom. - -Signed-off-by: James Yonan ---- - asio/include/asio/ip/basic_endpoint.hpp | 12 ++++++ - asio/include/asio/ip/detail/endpoint.hpp | 55 +++++++++++++++++++++++++++ - asio/include/asio/ip/detail/impl/endpoint.ipp | 12 ++++++ - 3 files changed, 79 insertions(+) - -diff --git a/asio/include/asio/ip/basic_endpoint.hpp b/asio/include/asio/ip/basic_endpoint.hpp -index 4418ee7..179a021 100644 ---- a/asio/include/asio/ip/basic_endpoint.hpp -+++ b/asio/include/asio/ip/basic_endpoint.hpp -@@ -185,6 +185,18 @@ public: - impl_.address(addr); - } - -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ int get_route_id() const -+ { -+ return impl_.get_route_id(); -+ } -+ -+ void set_route_id(const int route_id) -+ { -+ impl_.set_route_id(route_id); -+ } -+#endif -+ - /// Compare two endpoints for equality. - friend bool operator==(const basic_endpoint& e1, - const basic_endpoint& e2) ASIO_NOEXCEPT -diff --git a/asio/include/asio/ip/detail/endpoint.hpp b/asio/include/asio/ip/detail/endpoint.hpp -index 9acefe5..7ba5983 100644 ---- a/asio/include/asio/ip/detail/endpoint.hpp -+++ b/asio/include/asio/ip/detail/endpoint.hpp -@@ -24,6 +24,11 @@ - - #include "asio/detail/push_options.hpp" - -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+#include -+#include -+#endif -+ - namespace asio { - namespace ip { - namespace detail { -@@ -116,6 +121,47 @@ public: - ASIO_DECL std::string to_string() const; - #endif // !defined(ASIO_NO_IOSTREAM) - -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ int get_route_id() const -+ { -+ if (is_v4()) -+ { -+ if (data_.v4_sin_ovpn_magic == SIN_OVPN_MAGIC) -+ return OVPN_MARK_ROUTE_ID(data_.v4_sin_ovpn_route_id); -+ } -+ else -+ { -+ if ((data_.v6.sin6_flowinfo & htonl(SIN6_FLOWINFO_OVPN_MASK)) == htonl(SIN6_FLOWINFO_OVPN_MAGIC)) -+ return OVPN_MARK_ROUTE_ID(ntohl(data_.v6.sin6_flowinfo)); -+ } -+ return -1; -+ } -+ -+ void set_route_id(const int route_id) -+ { -+ if (is_v4()) -+ { -+ if (route_id >= 0) -+ { -+ data_.v4_sin_ovpn_magic = SIN_OVPN_MAGIC; -+ data_.v4_sin_ovpn_route_id = OVPN_MARK_ROUTE_ID(route_id); -+ } -+ else -+ { -+ data_.v4_sin_ovpn_magic = 0; -+ data_.v4_sin_ovpn_route_id = 0; -+ } -+ } -+ else -+ { -+ if (route_id >= 0) -+ data_.v6.sin6_flowinfo = htonl(OVPN_MARK_ROUTE_ID(route_id) | SIN6_FLOWINFO_OVPN_MAGIC); -+ else -+ data_.v6.sin6_flowinfo = 0; -+ } -+ } -+#endif -+ - private: - // The underlying IP socket address. - union data_union -@@ -123,6 +169,15 @@ private: - asio::detail::socket_addr_type base; - asio::detail::sockaddr_in4_type v4; - asio::detail::sockaddr_in6_type v6; -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ struct { -+ std::uint8_t head_[8]; -+ -+ // mirrors definition in /include/uapi/linux/in.h -+ std::uint32_t v4_sin_ovpn_magic; -+ std::uint32_t v4_sin_ovpn_route_id; -+ }; -+#endif - } data_; - }; - -diff --git a/asio/include/asio/ip/detail/impl/endpoint.ipp b/asio/include/asio/ip/detail/impl/endpoint.ipp -index 304bdf3..a72fefc 100644 ---- a/asio/include/asio/ip/detail/impl/endpoint.ipp -+++ b/asio/include/asio/ip/detail/impl/endpoint.ipp -@@ -37,6 +37,10 @@ endpoint::endpoint() - data_.v4.sin_family = ASIO_OS_DEF(AF_INET); - data_.v4.sin_port = 0; - data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ data_.v4_sin_ovpn_magic = 0; -+ data_.v4_sin_ovpn_route_id = 0; -+#endif - } - - endpoint::endpoint(int family, unsigned short port_num) ASIO_NOEXCEPT -@@ -49,6 +53,10 @@ endpoint::endpoint(int family, unsigned short port_num) - data_.v4.sin_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ data_.v4_sin_ovpn_magic = 0; -+ data_.v4_sin_ovpn_route_id = 0; -+#endif - } - else - { -@@ -81,6 +89,10 @@ endpoint::endpoint(const asio::ip::address& addr, - data_.v4.sin_addr.s_addr = - asio::detail::socket_ops::host_to_network_long( - addr.to_v4().to_uint()); -+#if defined(ASIO_USE_KOVPN_ROUTE_ID) -+ data_.v4_sin_ovpn_magic = 0; -+ data_.v4_sin_ovpn_route_id = 0; -+#endif - } - else - { --- -2.7.4 - diff --git a/Sources/OpenVPN3/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch b/Sources/OpenVPN3/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch deleted file mode 100644 index 229d0f9..0000000 --- a/Sources/OpenVPN3/deps/asio/patches/0006-basic_resolver_results-added-data-and-cdata-members-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b8f6e3c4db6cd86657a3cbc97d17f268c7d6555a Mon Sep 17 00:00:00 2001 -From: James Yonan -Date: Sun, 19 Jul 2020 18:38:07 -0600 -Subject: basic_resolver_results: added data() and cdata() members for access - to underlying storage vector - -This commit also removes the randomize() method -since data() provides a more general solution -for arbitrary mutate methods. - -Signed-off-by: James Yonan ---- - asio/include/asio/ip/basic_resolver_results.hpp | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/asio/include/asio/ip/basic_resolver_results.hpp b/asio/include/asio/ip/basic_resolver_results.hpp -index 29898542..9483a774 100644 ---- a/asio/include/asio/ip/basic_resolver_results.hpp -+++ b/asio/include/asio/ip/basic_resolver_results.hpp -@@ -300,10 +300,18 @@ public: - return !a.equal(b); - } - -- template -- void randomize(Random& r) -+#define HAVE_ASIO_RESOLVER_RESULTS_DATA -+ -+ /// Return a pointer to the underlying results vector. -+ auto* data() -+ { -+ return this->values_.get(); -+ } -+ -+ /// Return a const pointer to the underlying results vector. -+ const auto* cdata() const - { -- std::shuffle(this->values_->begin(), this->values_->end(), r); -+ return this->values_.get(); - } - - private: --- -2.25.1 - diff --git a/Sources/OpenVPN3/deps/asio/snapshot-asio b/Sources/OpenVPN3/deps/asio/snapshot-asio deleted file mode 100755 index 2bd3e69..0000000 --- a/Sources/OpenVPN3/deps/asio/snapshot-asio +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -export NAME=asio -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -$DIR/../../scripts/snapshot diff --git a/Sources/OpenVPN3/deps/boost/atomic-1.55.0.patch b/Sources/OpenVPN3/deps/boost/atomic-1.55.0.patch deleted file mode 100644 index 021ee81..0000000 --- a/Sources/OpenVPN3/deps/boost/atomic-1.55.0.patch +++ /dev/null @@ -1,87 +0,0 @@ ---- boost/atomic/detail/cas128strong.hpp -+++ boost/atomic/detail/cas128strong.hpp -@@ -196,15 +196,17 @@ class base_atomic - - public: - BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) -- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0) -+ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT - { -+ memset(&v_, 0, sizeof(v_)); - memcpy(&v_, &v, sizeof(value_type)); - } - - void - store(value_type const& value, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { -- storage_type value_s = 0; -+ storage_type value_s; -+ memset(&value_s, 0, sizeof(value_s)); - memcpy(&value_s, &value, sizeof(value_type)); - platform_fence_before_store(order); - platform_store128(value_s, &v_); -@@ -247,7 +249,9 @@ class base_atomic - memory_order success_order, - memory_order failure_order) volatile BOOST_NOEXCEPT - { -- storage_type expected_s = 0, desired_s = 0; -+ storage_type expected_s, desired_s; -+ memset(&expected_s, 0, sizeof(expected_s)); -+ memset(&desired_s, 0, sizeof(desired_s)); - memcpy(&expected_s, &expected, sizeof(value_type)); - memcpy(&desired_s, &desired, sizeof(value_type)); - ---- boost/atomic/detail/gcc-atomic.hpp -+++ boost/atomic/detail/gcc-atomic.hpp -@@ -958,14 +958,16 @@ class base_atomic - - public: - BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) -- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0) -+ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT - { -+ memset(&v_, 0, sizeof(v_)); - memcpy(&v_, &v, sizeof(value_type)); - } - - void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { -- storage_type tmp = 0; -+ storage_type tmp; -+ memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp, &v, sizeof(value_type)); - __atomic_store_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order)); - } -@@ -980,7 +982,8 @@ class base_atomic - - value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT - { -- storage_type tmp = 0; -+ storage_type tmp; -+ memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp, &v, sizeof(value_type)); - tmp = __atomic_exchange_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order)); - value_type res; -@@ -994,7 +997,9 @@ class base_atomic - memory_order success_order, - memory_order failure_order) volatile BOOST_NOEXCEPT - { -- storage_type expected_s = 0, desired_s = 0; -+ storage_type expected_s, desired_s; -+ memset(&expected_s, 0, sizeof(expected_s)); -+ memset(&desired_s, 0, sizeof(desired_s)); - memcpy(&expected_s, &expected, sizeof(value_type)); - memcpy(&desired_s, &desired, sizeof(value_type)); - const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, false, -@@ -1010,7 +1015,9 @@ class base_atomic - memory_order success_order, - memory_order failure_order) volatile BOOST_NOEXCEPT - { -- storage_type expected_s = 0, desired_s = 0; -+ storage_type expected_s, desired_s; -+ memset(&expected_s, 0, sizeof(expected_s)); -+ memset(&desired_s, 0, sizeof(desired_s)); - memcpy(&expected_s, &expected, sizeof(value_type)); - memcpy(&desired_s, &desired, sizeof(value_type)); - const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, true, --- diff --git a/Sources/OpenVPN3/deps/boost/build-boost b/Sources/OpenVPN3/deps/boost/build-boost deleted file mode 100755 index fcd10e5..0000000 --- a/Sources/OpenVPN3/deps/boost/build-boost +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash -# -# Parameters: -# SDK_PATH_SCRIPT -- optional script to set SDK path - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGETS" ]; then - echo TARGETS var must be defined - exit 1 -fi - -# NOTE: in Boost 1.55 and earlier, set BCONF=tools/build/v2 -BCONF=tools/build/src - -. $O3/core/deps/lib-versions -[ -z "$DL" ] && DL=~/Downloads -[ -z "$GPP_CMD" ] && export GPP_CMD=g++ -[ -z "$GCC_CMD" ] && export GCC_CMD=gcc -if [ "$NO_WIPE" != "1" ]; then - echo WIPE and reunzip source - rm -rf boost $BOOST_VERSION - mkdir boost - tar xfz $DL/$BOOST_VERSION.tar.gz - cd $BOOST_VERSION - #patch -p1 <$DL/asio-engine.patch - #patch -p0 <$O3/core/deps/boost/atomic-1.55.0.patch - patch -p1 <$O3/core/deps/boost/intrusive_ptr.patch - patch -p1 <$O3/core/deps/boost/page_size.patch - - ./bootstrap.sh - - for T in $TARGETS ; do - TS="${T//-/}" - . $O3/core/vars/vars-$T - cat >>$BCONF/user-config.jam <"-Wno-unused-function $PLATFORM_FLAGS $CXX_COMPILER_FLAGS $OTHER_COMPILER_FLAGS $LIB_FPIC $LIB_OPT_LEVEL" - ; -EOF - done - echo '********** BOOST CONFIG' - tail -30 $BCONF/user-config.jam - echo '********** END BOOST CONFIG' -else - echo RETAIN existing source - cd $BOOST_VERSION - for T in $TARGETS ; do - TS="${T//-/}" - . $O3/core/vars/vars-$T - done -fi -[ "$SDK_PATH_SCRIPT" ] && . $SDK_PATH_SCRIPT -for T in $TARGETS ; do - . $O3/core/vars/vars-$T - target="${T//-/}" - stage=stage-$T - if [ "${target:(-3)}" == "dbg" ]; then - variant=debug - else - variant=release - fi - [ -z "$LINK_MODE" ] && LINK_MODE=static - echo "************************ $target $variant $stage" - cmd="./bjam -d2 toolset=${GCC_CMD}-${target} --stagedir=$stage --with-system --with-thread --with-atomic variant=$variant link=$LINK_MODE threading=multi runtime-link=$LINK_MODE" - echo $cmd - $cmd -done -mv stage-* ../boost/ -cp -a boost ../boost/ -exit 0 diff --git a/Sources/OpenVPN3/deps/boost/intrusive_ptr.patch b/Sources/OpenVPN3/deps/boost/intrusive_ptr.patch deleted file mode 100644 index 19717d9..0000000 --- a/Sources/OpenVPN3/deps/boost/intrusive_ptr.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff -ur boost_1_56_0.orig/boost/smart_ptr/intrusive_ptr.hpp boost_1_56_0/boost/smart_ptr/intrusive_ptr.hpp ---- boost_1_56_0.orig/boost/smart_ptr/intrusive_ptr.hpp 2014-07-26 00:44:34.000000000 -0600 -+++ boost_1_56_0/boost/smart_ptr/intrusive_ptr.hpp 2014-08-15 19:51:11.000000000 -0600 -@@ -63,7 +63,7 @@ - { - } - -- intrusive_ptr( T * p, bool add_ref = true ): px( p ) -+ intrusive_ptr( T * p, bool add_ref = true ) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( p ) - { - if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); - } -@@ -80,14 +80,14 @@ - intrusive_ptr( intrusive_ptr const & rhs ) - - #endif -- : px( rhs.get() ) -+ BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( rhs.get() ) - { - if( px != 0 ) intrusive_ptr_add_ref( px ); - } - - #endif - -- intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) -+ intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(intrusive_ptr_add_ref(static_cast(nullptr)))) : px( rhs.px ) - { - if( px != 0 ) intrusive_ptr_add_ref( px ); - } diff --git a/Sources/OpenVPN3/deps/boost/page_size.patch b/Sources/OpenVPN3/deps/boost/page_size.patch deleted file mode 100644 index 077015f..0000000 --- a/Sources/OpenVPN3/deps/boost/page_size.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -ur boost_1_57_0/boost/thread/pthread/thread_data.hpp boost_1_57_0.new/boost/thread/pthread/thread_data.hpp ---- boost_1_57_0/boost/thread/pthread/thread_data.hpp 2014-10-24 10:43:26.000000000 -0600 -+++ boost_1_57_0.new/boost/thread/pthread/thread_data.hpp 2015-02-26 00:43:26.000000000 -0700 -@@ -24,8 +24,10 @@ - #include - #include - --#if defined(__ANDROID__) --#include // http://code.google.com/p/android/issues/detail?id=39983 -+// JY modified -+#if defined(__ANDROID__) && !defined(PAGE_SIZE) -+#define PAGE_SIZE 4096 -+//#include // http://code.google.com/p/android/issues/detail?id=39983 - #endif - - #include diff --git a/Sources/OpenVPN3/deps/cityhash/build-cityhash b/Sources/OpenVPN3/deps/cityhash/build-cityhash deleted file mode 100755 index ebbdc06..0000000 --- a/Sources/OpenVPN3/deps/cityhash/build-cityhash +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=cityhash-${CITYHASH_VERSION}.tar.gz -PN=${CITYHASH_VERSION#*-} -URL=https://codeload.github.com/google/cityhash/tar.gz/${CITYHASH_VERSION} -CSUM=${CITYHASH_CSUM} - -download - -CXX=c++ -LD=ld -AR=ar -RANLIB=ranlib -[ "$GPP_CMD" ] && CXX=$GPP_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR=$AR_CMD -[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD - -if [ "$NO_WIPE" != "1" ]; then - rm -rf $CITYHASH_VERSION - tar xfz $DL/cityhash-$CITYHASH_VERSION.tar.gz -fi - -DIST=$(pwd)/cityhash/cityhash-$PLATFORM -rm -rf $DIST -mkdir -p $DIST/include -mkdir $DIST/lib -cd cityhash-$CITYHASH_VERSION - -# The autconf tools in cityhash are from 2009 and have no idea what arm64 is and fail. -# The configure otherwise not really useful anyway, as only HAVE_BUILTIN_EXPECT -# and if the arch is big endian is used by cityhash source code -#CMD=./configure -#echo $CMD -# fake config.h -touch config.h - -$CMD -CMD="$CXX $CXX_COMPILER_FLAGS $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -DHAVE_BUILTIN_EXPECT=1 -I. -Isrc -c src/city.cc" -echo $CMD -$CMD -$AR rc $DIST/lib/libcityhash.a city.o -$RANLIB $DIST/lib/libcityhash.a -cp src/city.h $DIST/include/ -exit 0 diff --git a/Sources/OpenVPN3/deps/functions.sh b/Sources/OpenVPN3/deps/functions.sh deleted file mode 100644 index a9e932b..0000000 --- a/Sources/OpenVPN3/deps/functions.sh +++ /dev/null @@ -1,47 +0,0 @@ -function check_download() -{ - if [ -f $DL/$FNAME ]; then - CHECK=$(shasum -a 256 $DL/$FNAME |awk '{printf $1};') - if [ "$CHECK" == "$CSUM" ]; then - return 0 - else - echo "Checksum mismatch for $FNAME. Was $CHECK, expected $CSUM" - fi - else - echo "$FNAME not found." - fi - - return -1 -} - -function download() -{ - check_download && return 0 - - rm -f $DL/$FNAME - if [ -n "$URL" ]; then - wget $URL -O $DL/$FNAME - else - echo URL must be specified - exit 1 - fi - - check_download || return -1 -} - -function apply_patches() -{ - DEP_NAME=$1 - - # change directory since git apply got confused when - # applying patches to files which are not found in index - DIR=$(pwd) - pushd ${DIR} - cd /tmp - # apply pre-generated patches - for file in $O3/core/deps/${DEP_NAME}/patches/*.patch; do - echo Applying patch: $file - git apply --directory ${DIR} --unsafe-path $file - done - popd -} diff --git a/Sources/OpenVPN3/deps/lib-versions b/Sources/OpenVPN3/deps/lib-versions deleted file mode 100644 index f9fe331..0000000 --- a/Sources/OpenVPN3/deps/lib-versions +++ /dev/null @@ -1,25 +0,0 @@ -export ASIO_VERSION=asio-1-16-1 -export ASIO_CSUM=e40bbd531530f08318b7c7d7e84e457176d8eae6f5ad2e3714dc27b9131ecd35 - -export LZ4_VERSION=lz4-1.8.3 -export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43 - -export MBEDTLS_VERSION=mbedtls-2.7.13 -export MBEDTLS_CSUM=6772fe21c7755dc513920e84adec629d39188b6451542ebaece428f0eba655c9 - -export JSONCPP_VERSION=1.8.4 -export JSONCPP_CSUM=c49deac9e0933bcb7044f08516861a2d560988540b23de2ac1ad443b219afdb6 - -export TAP_VERSION=0e30f5c13b3c7b0bdd60da915350f653e4c14d92 -export TAP_CSUM=8ff65f9e741c5ecfe1af904eaa38713f05639ce9457ef92041fd8e6b2a170315 - -export CITYHASH_VERSION=8af9b8c2b889d80c22d6bc26ba0df1afb79a30db -export CITYHASH_CSUM=f70368facd15735dffc77fe2b27ab505bfdd05be5e9166d94149a8744c212f49 - -export LZO_VERSION=lzo-2.10 -export LZO_CSUM=c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072 - -export OPENSSL_VERSION=openssl-1.1.1j -export OPENSSL_CSUM=aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf - - diff --git a/Sources/OpenVPN3/deps/lz4/build-lz4 b/Sources/OpenVPN3/deps/lz4/build-lz4 deleted file mode 100755 index 53777d0..0000000 --- a/Sources/OpenVPN3/deps/lz4/build-lz4 +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=${LZ4_VERSION}.tar.gz -PN=${LZ4_VERSION#*-} -URL=https://github.com/lz4/lz4/archive/v${PN}.tar.gz -CSUM=${LZ4_CSUM} - -download - -CC=cc -LD=ld -AR=ar -RANLIB=ranlib -[ "$GCC_CMD" ] && CC=$GCC_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR=$AR_CMD -[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD - -if [ "$NO_WIPE" != "1" ]; then - rm -rf $LZ4_VERSION - tar xfz $DL/$LZ4_VERSION.tar.gz -fi - -if [ "x$NO_BUILD" == x1 ]; then - echo "Not building" - exit -fi - -DIST=$(pwd)/lz4/lz4-$PLATFORM -rm -rf $DIST -mkdir -p $DIST/include -mkdir $DIST/lib -cd $LZ4_VERSION/lib -CMD="$CC $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c lz4.c" -echo $CMD -$CMD -$AR rc $DIST/lib/liblz4.a lz4.o -$RANLIB $DIST/lib/liblz4.a -cp lz4.h $DIST/include/ -exit 0 diff --git a/Sources/OpenVPN3/deps/lz4/snapshot-lz4 b/Sources/OpenVPN3/deps/lz4/snapshot-lz4 deleted file mode 100755 index 1074081..0000000 --- a/Sources/OpenVPN3/deps/lz4/snapshot-lz4 +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -export NAME=lz4 -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -$DIR/../../scripts/snapshot diff --git a/Sources/OpenVPN3/deps/lzo/build-lzo b/Sources/OpenVPN3/deps/lzo/build-lzo deleted file mode 100755 index df96fb7..0000000 --- a/Sources/OpenVPN3/deps/lzo/build-lzo +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -[ -z "$DL" ] && DL=~/Downloads - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=${LZO_VERSION}.tar.gz -PN=${LZO_VERSION#*-} -URL=http://www.oberhumer.com/opensource/lzo/download/${LZO_VERSION}.tar.gz -CSUM=${LZO_CSUM} - -download - -CC=cc -LD=ld -AR=ar -RANLIB=ranlib -[ "$GCC_CMD" ] && CC=$GCC_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR=$AR_CMD -[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD - -case $PLATFORM in -android*) - echo PLATFORM android - host=arm - target=arm - ;; -ios*) - echo PLATFORM ios - host="x86_64-apple-darwin" - target=arm - ;; -*) - host="" - target="" - ;; -esac - -if [ "$target" ]; then - targ_opt="--target=$target" -fi - -if [ "$host" ]; then - host_opt="--host=$host" -fi - -if [ "$NO_WIPE" != "1" ]; then - rm -rf $LZO_VERSION - tar xfz $DL/$LZO_VERSION.tar.gz -fi - -DIST=$(pwd)/lzo/lzo-$PLATFORM -rm -rf $DIST -mkdir -p $DIST -cd $LZO_VERSION -echo 'OPTIONS' $CC $LD $AR $RANLIB $host_opt $targ_opt -CFLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" ./configure --prefix=$DIST $host_opt $targ_opt -make -make install -exit 0 diff --git a/Sources/OpenVPN3/deps/mbedtls/build-mbedtls b/Sources/OpenVPN3/deps/mbedtls/build-mbedtls deleted file mode 100755 index a962ad9..0000000 --- a/Sources/OpenVPN3/deps/mbedtls/build-mbedtls +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to dependency build folder - exit 1 -fi -if [ -z "$DL" ]; then - echo DL var must point to the download folder - exit 1 -fi - -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=${MBEDTLS_VERSION}-apache.tgz -PN=${MBEDTLS_VERSION#*-} -URL=https://tls.mbed.org/download/$MBEDTLS_VERSION-apache.tgz -CSUM=${MBEDTLS_CSUM} - -download - -# put build targets here -DIST=$(pwd)/mbedtls/mbedtls-$PLATFORM -rm -rf $DIST -mkdir -p $DIST - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source - cd $MBEDTLS_VERSION -else - echo WIPE and reunzip source - rm -rf $MBEDTLS_VERSION - [ -z "$DL" ] && DL=~/Downloads - tar xfz $DL/$MBEDTLS_VERSION-apache.tgz - cd $MBEDTLS_VERSION - - # enable MD4 (needed for NTLM auth) - perl -pi -e 's/^\/\/// if /#define MBEDTLS_MD4_C/' include/mbedtls/config.h - - apply_patches "mbedtls" -fi - -if [ "x$NO_BUILD" == x1 ]; then - echo "Not building" - exit 0 -fi - -if [[ "x$TARGET" == xlinux* || "x$TARGET" == xosx* ]]; then - # run unit tests and then clean - echo RUNNING CHECK - make check - echo CLEANING - make clean -fi - -echo BUILDING - -# compiler vars -CC=cc -LD=ld -AR=ar -RANLIB=ranlib -[ "$GCC_CMD" ] && CC=$GCC_CMD -[ "$LD_CMD" ] && LD=$LD_CMD -[ "$AR_CMD" ] && AR=$AR_CMD -[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD - -# build it -SRC=$(pwd) -cd library -rm -f *.o -for c in *.c ; do - CMD="$CC -I../include -DMBEDTLS_RELAXED_X509_DATE \ - $PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -c $c" - echo $CMD - $CMD -done - -# create archive -cd $DIST -mkdir library -$AR rc library/libmbedtls.a $SRC/library/*.o -$RANLIB library/libmbedtls.a 2>&1 | grep -v "has no symbols" || true - -# copy headers -mkdir -p include/mbedtls -cp $SRC/include/mbedtls/*.h include/mbedtls/ -exit 0 diff --git a/Sources/OpenVPN3/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch b/Sources/OpenVPN3/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch deleted file mode 100644 index d5406e9..0000000 --- a/Sources/OpenVPN3/deps/mbedtls/patches/0001-relax-x509-date-format-check.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0554efae4e27b6a764def80f600394519ef1addb Mon Sep 17 00:00:00 2001 -From: Antonio Quartulli -Date: Tue, 20 Mar 2018 09:35:47 +0800 -Subject: [PATCH 1/2] relax x509 date format check - -Signed-off-by: Antonio Quartulli ---- - library/x509.c | 18 +++++++++++++++++- - 1 file changed, 17 insertions(+), 1 deletion(-) - -diff --git a/library/x509.c b/library/x509.c -index 264c7fb0c..9372bcb92 100644 ---- a/library/x509.c -+++ b/library/x509.c -@@ -556,13 +556,20 @@ static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, - /* - * Parse seconds if present - */ -- if ( len >= 2 ) -+ if ( len >= 2 && **p >= '0' && **p <= '9' ) - { - CHECK( x509_parse_int( p, 2, &tm->sec ) ); - len -= 2; - } - else -+ { -+#if defined(MBEDTLS_RELAXED_X509_DATE) -+ /* if relaxed mode, allow seconds to be absent */ -+ tm->sec = 0; -+#else - return ( MBEDTLS_ERR_X509_INVALID_DATE ); -+#endif -+ } - - /* - * Parse trailing 'Z' if present -@@ -572,6 +579,15 @@ static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, - (*p)++; - len--; - } -+#if defined(MBEDTLS_RELAXED_X509_DATE) -+ else if ( len == 5 && **p == '+' ) -+ { -+ int tz; /* throwaway timezone */ -+ (*p)++; -+ CHECK( x509_parse_int( p, 4, &tz ) ); -+ return 0; -+ } -+#endif - - /* - * We should have parsed all characters at this point --- -2.18.0 - diff --git a/Sources/OpenVPN3/deps/minicrypto/aes-armv4.pl.patch b/Sources/OpenVPN3/deps/minicrypto/aes-armv4.pl.patch deleted file mode 100644 index 8578ec9..0000000 --- a/Sources/OpenVPN3/deps/minicrypto/aes-armv4.pl.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- aes-armv4.pl.orig 2012-09-03 00:16:20.000000000 -0600 -+++ aes-armv4.pl 2012-09-03 00:17:22.000000000 -0600 -@@ -171,7 +170,8 @@ - stmdb sp!,{r1,r4-r12,lr} - mov $rounds,r0 @ inp - mov $key,r2 -- sub $tbl,r3,#AES_encrypt-AES_Te @ Te -+ad1=AES_encrypt-AES_Te -+ sub $tbl,r3,#ad1 @ Te - #if __ARM_ARCH__<7 - ldrb $s0,[$rounds,#3] @ load input data in endian-neutral - ldrb $t1,[$rounds,#2] @ manner... -@@ -426,7 +426,8 @@ - bne .Labrt - - .Lok: stmdb sp!,{r4-r12,lr} -- sub $tbl,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 -+ad2=_armv4_AES_set_encrypt_key-AES_Te-1024 -+ sub $tbl,r3,#ad2 @ Te4 - - mov $rounds,r0 @ inp - mov lr,r1 @ bits -@@ -887,7 +888,8 @@ - stmdb sp!,{r1,r4-r12,lr} - mov $rounds,r0 @ inp - mov $key,r2 -- sub $tbl,r3,#AES_decrypt-AES_Td @ Td -+ad3=AES_decrypt-AES_Td -+ sub $tbl,r3,#ad3 @ Td - #if __ARM_ARCH__<7 - ldrb $s0,[$rounds,#3] @ load input data in endian-neutral - ldrb $t1,[$rounds,#2] @ manner... diff --git a/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios b/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios deleted file mode 100755 index 0fe6d06..0000000 --- a/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios +++ /dev/null @@ -1,759 +0,0 @@ -#!/usr/bin/env python -# -# arm-as-to-ios Modify ARM assembly code for the iOS assembler -# -# Copyright (c) 2012 Psellos http://psellos.com/ -# Licensed under the MIT License: -# http://www.opensource.org/licenses/mit-license.php -# -# Resources for running OCaml on iOS: http://psellos.com/ocaml/ -# -import sys -import re - -VERSION = '1.4.0' - -initial_glosyms = [] -initial_defsyms = [] - -# Character classes for expression lexing. -# -g_ccid0 = '[$.A-Z_a-z\x80-\xff]' # Beginning of id -g_ccid = '[$.0-9A-Z_a-z\x80-\xff]' # Later in id -def ccc(cc): # Complement the class - if cc[1] == '^': - return cc[0] + cc[2:] - return cc[0] + '^' + cc[1:] -def ccce(cc): # Complement the class, include EOL - return '(?:' + ccc(cc) + '|$)' - -# Prefixes for pooled symbol labels and jump table base labels. They're -# in the space of Linux assembler local symbols. Later rules will -# modify them to the Loc() form. -# -g_poolpfx = '.LP' -g_basepfx = '.LB' - - -def exists(p, l): - for l1 in l: - if p(l1): - return True - return False - - -def forall(p, l): - for l1 in l: - if not p(l1): - return False - return True - - -def add_prefix(instrs): - # Add compatibility macros for all systems, plus hardware - # definitions and compatibility macros for iOS. - # - # All systems: - # - # Glo() cpp macro for making global symbols (xxx vs _xxx) - # Loc() cpp macro for making local symbols (.Lxxx vs Lxxx) - # .funtype Expands to .thumb_func for iOS armv7 (null for armv6) - # Expands to .type %function for others - # - # iOS: - # - # .machine armv6/armv7 - # .thumb (for armv7) - # cbz Expands to cmp/beq for armv6 (Thumb-only instr) - # .type Not supported by Apple assembler - # .size Not supported by Apple assembler - # - defre = '#[ \t]*if.*def.*SYS' # Add new defs near first existing ones - skipre = '$|\.syntax[ \t]' # Skip comment lines (and .syntax) - - for i in range(len(instrs)): - if re.match(defre, instrs[i][1]): - break - else: - i = 0 - for i in range(i, len(instrs)): - if not re.match(skipre, instrs[i][1]): - break - instrs[i:0] = [ - ('', '', '\n'), - ('/* Apple compatibility macros */', '', '\n'), - ('', '#if defined(SYS_macosx)', '\n'), - ('', '#define Glo(s) _##s', '\n'), - ('', '#define Loc(s) L##s', '\n'), - ('', '#if defined(MODEL_armv6)', '\n'), - (' ', '.machine armv6', '\n'), - (' ', '.macro .funtype', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro cbz', '\n'), - (' ', 'cmp $0, #0', '\n'), - (' ', 'beq $1', '\n'), - (' ', '.endm', '\n'), - ('', '#else', '\n'), - (' ', '.machine armv7', '\n'), - ('', '#if !defined(NO_THUMB)', '\n'), - (' ', '.thumb', '\n'), - ('', '#endif', '\n'), - (' ', '.macro .funtype', '\n'), - ('', '#if !defined(NO_THUMB)', '\n'), - (' ', '.thumb_func $0', '\n'), - ('', '#endif', '\n'), - (' ', '.endm', '\n'), - ('', '#endif', '\n'), - (' ', '.macro .type', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro .size', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro .skip', '\n'), - (' ', '.space $0', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro .fpu', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro .global', '\n'), - (' ', '.globl $0', '\n'), - (' ', '.endm', '\n'), - ('', '#else', '\n'), - ('', '#define Glo(s) s', '\n'), - ('', '#define Loc(s) .L##s', '\n'), - (' ', '.macro .funtype symbol', '\n'), - (' ', '.type \\symbol, %function', '\n'), - (' ', '.endm', '\n'), - ('', '#endif', '\n'), - ('/* End Apple compatibility macros */', '', '\n'), - ('', '', '\n') - ] - return instrs - - -# Regular expression for modified ldr lines -# -g_ldre = '(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)' - - -def explicit_address_loads(instrs): - # Linux assemblers allow the following: - # - # ldr rM, =symbol - # - # which loads rM with [mov] (immediately) if possible, or creates an - # entry in memory for the symbol value and loads it PC-relatively - # with [ldr]. - # - # The Apple assembler doesn't seem to support this notation. If the - # value is a suitable constant, it emits a valid [mov]. Otherwise - # it seems to emit an invalid [ldr] that always generates an error. - # (At least I have not been able to make it work). So, change uses - # of =symbol to explicit PC-relative loads. - # - # This requires a pool containing the addresses to be loaded. For - # now, we just keep track of it ourselves and emit it into the text - # segment at the end of the file. - # - syms = {} - result = [] - - def repl1((syms, result), (a, b, c)): - global g_poolpfx - global g_ldre - (b1, b2, b3) = parse_iparts(b) - mo = re.match(g_ldre, b3, re.DOTALL) - if mo: - if mo.group(2) not in syms: - syms[mo.group(2)] = len(syms) - psym = mo.group(2) - if psym[0:2] == '.L': - psym = psym[2:] - newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4) - result.append((a, b1 + b2 + newb3, c)) - else: - result.append((a, b, c)) - return (syms, result) - - def pool1(result, s): - global g_poolpfx - psym = s - if psym[0:2] == '.L': - psym = psym[2:] - result.append(('', g_poolpfx + psym + ':', '\n')) - result.append((' ', '.long ' + s, '\n')) - return result - - reduce(repl1, instrs, (syms, result)) - if len(syms) > 0: - result.append(('', '', '\n')) - result.append(('/* Pool of addresses loaded into registers */', - '', '\n')) - result.append(('', '', '\n')) - result.append((' ', '.text', '\n')) - result.append((' ', '.align 2', '\n')) - reduce(pool1, sorted(syms, key=syms.get), result) - return result - - -def global_symbols(instrs): - # The form of a global symbol differs between Linux assemblers and - # the Apple assember: - # - # Linux: xxx - # Apple: _xxx - # - # Change occurrences of global symbols to use the Glo() cpp macro - # defined in our prefix. - # - # We consider a symbol to be global if: - # - # a. It appears in a .globl declaration; or - # b. It is referenced, has global form, and is not defined - # - glosyms = set(initial_glosyms) - refsyms = set() - defsyms = set(initial_defsyms) - result = [] - - def findglo1 (glosyms, (a, b, c)): - if re.match('#', b): - # Preprocessor line; nothing to do - return glosyms - (b1, b2, b3) = parse_iparts(b) - mo = re.match('(\.globa?l)' + ccce(g_ccid), b3) - if mo: - tokens = parse_expr(b3[len(mo.group(1)):]) - if forall(lambda t: token_type(t) in ['space', 'id', ','], tokens): - for t in tokens: - if token_type(t) == 'id': - glosyms.add(t) - return glosyms - - def findref1 ((refsyms, skipct), (a, b, c)): - - def looksglobal(s): - if re.match('(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$', s, re.I): - return False # numbered registers - if re.match('(wr|sb|sl|fp|ip|sp|lr|pc)$', s, re.I): - return False # named registers - if re.match('(fpsid|fpscr|fpexc|mvfr1|mvfr0)$', s, re.I): - return False # more named registers - if re.match('(mvf|mvd|mvfx|mvdx|dspsc)$', s, re.I): - return False # even more named registers - if re.match('(wcid|wcon|wcssf|wcasf|acc)$', s, re.I): - return False # even more named registers - if re.match('\.$|\.L|[0-9]|#', s): - return False # dot, local symbol, or number - if re.match('(asl|lsl|lsr|asr|ror|rrx)$', s, re.I): - return False # shift names - return True - - if re.match('#', b): - # Preprocessor line; nothing to do - return (refsyms, skipct) - - # Track nesting of .macro/.endm. For now, we don't look for - # global syms in macro defs. (Avoiding scoping probs etc.) - # - if skipct > 0 and re.match('\.(endm|endmacro)' + ccce(g_ccid), b): - return (refsyms, skipct - 1) - if re.match('\.macro' + ccce(g_ccid), b): - return (refsyms, skipct + 1) - if skipct > 0: - return (refsyms, skipct) - if re.match('\.(type|size|syntax|arch|fpu)' + ccce(g_ccid), b): - return (refsyms, skipct) - - (b1, b2, b3) = parse_iparts(b) - rtokens = parse_rexpr(b3) - if len(rtokens) > 1 and rtokens[1] == '.req': - # .req has atypical syntax; no symbol refs there anyway - return (refsyms, skipct) - for t in rtokens[1:]: - if token_type(t) == 'id' and looksglobal(t): - refsyms.add(t) - return (refsyms, skipct) - - def finddef1(defsyms, (a, b, c)): - if re.match('#', b): - # Preprocessor line - return defsyms - (b1, b2, b3) = parse_iparts(b) - rtokens = parse_rexpr(b3) - if b1 != '': - defsyms.add(b1) - if len(rtokens) > 1 and rtokens[1] == '.req': - defsyms.add(rtokens[0]) - return defsyms - - def repl1((glosyms, result), (a, b, c)): - if re.match('#', b): - # Preprocessor line - result.append((a, b, c)) - return (glosyms, result) - toglo = lambda s: 'Glo(' + s + ')' - (b1, b2, b3) = parse_iparts(b) - tokens = parse_expr(b3) - - if b1 in glosyms: - b1 = toglo(b1) - for i in range(len(tokens)): - if token_type(tokens[i]) == 'id' and tokens[i] in glosyms: - tokens[i] = toglo(tokens[i]) - result.append((a, b1 + b2 + ''.join(tokens), c)) - return (glosyms, result) - - reduce(findglo1, instrs, glosyms) - reduce(findref1, instrs, (refsyms, 0)) - reduce(finddef1, instrs, defsyms) - glosyms |= (refsyms - defsyms) - reduce(repl1, instrs, (glosyms, result)) - return result - - -def local_symbols(instrs): - # The form of a local symbol differs between Linux assemblers and - # the Apple assember: - # - # Linux: .Lxxx - # Apple: Lxxx - # - # Change occurrences of local symbols to use the Loc() cpp macro - # defined in our prefix. - # - lsyms = set() - result = [] - - def find1 (lsyms, (a, b, c)): - mo = re.match('(\.L[^ \t:]*)[ \t]*:', b) - if mo: - lsyms.add(mo.group(1)) - return lsyms - - def repl1((lsyms, result), (a, b, c)): - matches = list(re.finditer('\.L[^ \t@:,+*/\-()]+', b)) - if matches != []: - matches.reverse() - newb = b - for mo in matches: - if mo.group() in lsyms: - newb = newb[0:mo.start()] + \ - 'Loc(' + mo.group()[2:] + ')' + \ - newb[mo.end():] - result.append((a, newb, c)) - else: - result.append((a, b, c)) - return (lsyms, result) - - reduce(find1, instrs, lsyms) - reduce(repl1, instrs, (lsyms, result)) - return result - - -def funtypes(instrs): - # Linux assemblers accept declarations like this: - # - # .type symbol, %function - # - # For Thumb functions, the Apple assembler wants to see: - # - # .thumb_func symbol - # - # Handle this by converting declarations to this: - # - # .funtype symbol - # - # Our prefix defines an appropriate .funtype macro for each - # environment. - # - result = [] - - def repl1(result, (a, b, c)): - mo = re.match('.type[ \t]+([^ \t,]*),[ \t]*%function', b) - if mo: - result.append((a, '.funtype ' + mo.group(1), c)) - else: - result.append((a, b, c)) - return result - - reduce(repl1, instrs, result) - return result - - -def jump_tables(instrs): - # Jump tables for Linux assemblers often look like this: - # - # tbh [pc, rM, lsl #1] - # .short (.Labc-.)/2+0 - # .short (.Ldef-.)/2+1 - # .short (.Lghi-.)/2+2 - # - # The Apple assembler disagrees about the meaning of this code, - # producing jump tables that don't work. Convert to the following: - # - # tbh [pc, rM, lsl #1] - # .LBxxx: - # .short (.Labc-.LBxxx)/2 - # .short (.Ldef-.LBxxx)/2 - # .short (.Lghi-.LBxxx)/2 - # - # In fact we just convert sequences of .short pseudo-ops of the - # right form. There's no requirement that they follow a tbh - # instruction. - # - baselabs = [] - result = [] - - def short_match(seq, op): - # Determine whether the op is a .short of the form that needs to - # be converted: .short (symbol-.)/2+k. If so, return a pair - # containing the symbol and the value of k. If not, return - # None. The short can only be converted if there were at least - # k other .shorts in sequence before the current one. A summary - # of the previous .shorts is in seq. - # - # (A real parser would do a better job, but this was quick to - # get working.) - # - sp = '([ \t]|/\*.*?\*/)*' # space - sp1 = '([ \t]|/\*.*?\*/)+' # at least 1 space - spe = '([ \t]|/\*.*?\*/|@[^\n]*)*$' # end-of-instr space - expr_re0 = ( - '\.short' + sp + '\(' + sp + # .short ( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + spe # /2 END - ) - expr_re1 = ( - '\.short' + sp + '\(' + sp + # .short ( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + sp + # /2 - '\+' + sp + # + - '((0[xX])?[0-9]+)' + spe # k END - ) - expr_re2 = ( - '\.short' + sp1 + # .short - '((0[xX])?[0-9]+)' + sp + # k - '\+' + sp + '\(' + sp + # +( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + spe # /2 END - ) - mo = re.match(expr_re0, op) - if mo: - return(mo.group(3), 0) - mo = re.match(expr_re1, op) - if mo: - k = int(mo.group(11), 0) - if k > len(seq): - return None - return (mo.group(3), k) - mo = re.match(expr_re2, op) - if mo: - k = int(mo.group(2), 0) - if k > len(seq): - return None - return (mo.group(7), k) - return None - - def conv1 ((baselabs, shortseq, label, result), (a, b, c)): - # Convert current instr (a,b,c) if it's a .short of the right - # form that spans a previous sequence of .shorts. - # - (b1, b2, b3) = parse_iparts(b) - - if b3 == '': - # No operation: just note label if present. - result.append((a, b, c)) - if re.match('\.L.', b1): - return (baselabs, shortseq, b1, result) - return (baselabs, shortseq, label, result) - - if not re.match('.short[ \t]+[^ \t@]', b3): - # Not a .short: clear shortseq and label - result.append((a, b, c)) - return (baselabs, [], '', result) - - # We have a .short: figure out the label if any - if re.match('\.L', b1): - sl = b1 - else: - sl = label - - mpair = short_match(shortseq, b3) - if not mpair: - # A .short, but not of right form - shortseq.append((len(result), sl)) - result.append((a, b, c)) - return (baselabs, shortseq, '', result) - - # OK, we have a .short to convert! - (sym, k) = mpair - shortseq.append((len(result), sl)) - - # Figure out base label (create one if necessary). - bx = len(shortseq) - 1 - k - bl = shortseq[bx][1] - if bl == '': - bl = g_basepfx + str(shortseq[bx][0]) - shortseq[bx] = (shortseq[bx][0], bl) - baselabs.append(shortseq[bx]) - - op = '.short\t(' + sym + '-' + bl + ')/2' - - result.append ((a, b1 + b2 + op, c)) - return (baselabs, shortseq, '', result) - - # Convert, accumulate result and new labels. - reduce(conv1, instrs, (baselabs, [], '', result)) - - # Add labels created here to the instruction stream. - baselabs.reverse() - for (ix, lab) in baselabs: - result[ix:0] = [('', lab + ':', '\n')] - - # That does it - return result - - -def dot_relative(instrs): - # The Apple assembler (or possibly the linker) has trouble with code - # that looks like this: - # - # .word .Label - . + 0x80000000 - # .word 0x1966 - # .Label: - # .word 0x1967 - # - # One way to describe the problem is that the assembler marks the - # first .word for relocation when in fact it's an assembly-time - # constant. Translate to the following form, which doesn't generate - # a relocation marking: - # - # DR0 = .Label - . + 0x80000000 - # .word DR0 - # .word 0x1966 - # .Label: - # .word 0x1967 - # - prefix = 'DR' - pseudos = '(\.byte|\.short|\.word|\.long|\.quad)' - result = [] - - def tok_ok(t): - return t in ['.', '+', '-', '(', ')'] or \ - token_type(t) in ['space', 'locid', 'number'] - - def dotrel_match(expr): - # Determine whether the expression is one that needs to be - # translated. - tokens = parse_expr(expr) - return forall(tok_ok, tokens) and \ - exists(lambda t: token_type(t) == 'locid', tokens) and \ - exists(lambda t: token_type(t) == 'number', tokens) and \ - exists(lambda t: t == '-', tokens) and \ - exists(lambda t: t == '.', tokens) - - def conv1(result, (a, b, c)): - if re.match('#', b): - # Preprocessor line - result.append((a, b, c)) - else: - (b1, b2, b3) = parse_iparts(b) - mo = re.match(pseudos + ccce(g_ccid), b3) - if mo: - p = mo.group(1) - expr = b3[len(p):] - if dotrel_match(expr): - sym = prefix + str(len(result)) - instr = sym + ' =' + expr - result.append(('', instr, '\n')) - result.append((a, b1 + b2 + p + ' ' + sym, c)) - else: - result.append((a, b, c)) - else: - result.append((a, b, c)) - return result - - reduce(conv1, instrs, result) - return result - - -def read_input(): - # Concatenate all the input files into a string. - # - def fnl(s): - if s == '' or s[-1] == '\n': - return s - else: - return s + '\n' - - if len(sys.argv) < 2: - return fnl(sys.stdin.read()) - else: - input = "" - for f in sys.argv[1:]: - # allow global symbols to be enabled or disabled, eg: - # --global=foo,!bar - # foo is forced to be global - # bar is forced to be non-global - if f.startswith('--global='): - glist = f[9:].split(',') - for g in glist: - if g.startswith('!'): - initial_defsyms.append(g[1:]) - else: - initial_glosyms.append(g) - elif f.startswith('--stdin'): - input = input + fnl(sys.stdin.read()) - else: - try: - fd = open(f) - input = input + fnl(fd.read()) - fd.close() - except: - sys.stderr.write('arm-as-to-ios: cannot open ' + f + '\n') - return input - - -def parse_instrs(s): - # Parse the string into assembly instructions, also noting C - # preprocessor lines. Each instruction is represented as a triple: - # (space/comments, instruction, end). The end is either ';' or - # '\n'. - # - def goodmo(mo): - if mo == None: - # Should never happen - sys.stderr.write('arm-as-to-ios: internal parsing error\n') - sys.exit(1) - - cpp_re = '([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n' - comment_re = '[ \t]*#[^\n]*' - instr_re = ( - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - '(([ \t]|/\*.*?\*/|[^;\n])*)' # "Instruction" - '([;\n])' # End - ) - instrs = [] - while s != '': - if re.match('[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)', s): - mo = re.match(cpp_re, s) - goodmo(mo) - instrs.append((mo.group(1), mo.group(2), '\n')) - elif re.match('[ \t]*#', s): - mo = re.match(comment_re, s) - goodmo(mo) - instrs.append((mo.group(0), '', '\n')) - else: - mo = re.match(instr_re, s, re.DOTALL) - goodmo(mo) - instrs.append((mo.group(1), mo.group(3), mo.group(5))) - s = s[len(mo.group(0)):] - return instrs - - -def parse_iparts(i): - # Parse an instruction into smaller parts, returning a triple of - # strings (label, colon, operation). The colon part also contains - # any surrounding spaces and comments (making the label and the - # operation cleaner to process). - # - # (Caller warrants that the given string doesn't start with space or - # a comment. This is true for strings returned by the instruction - # parser.) - # - lab_re = ( - '([^ \t:/@]+)' # Label - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - ':' # Colon - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - '([^\n]*)' # Operation - ) - - if len(i) > 0 and i[0] == '#': - # C preprocessor line; treat as operation. - return ('', '', i) - mo = re.match(lab_re, i) - if mo: - return (mo.group(1), mo.group(2) + ':' + mo.group(4), mo.group(6)) - # No label, just an operation - return ('', '', i) - - -def parse_expr(s): - # Parse a string into a sequence of tokens. A segment of white - # space (including comments) is treated as a token, so that the - # tokens can be reassembled into the string again. - # - result = [] - while s != '': - mo = re.match('([ \t]|/\*.*?\*/|@.*)+', s) - if not mo: - # Glo(...) and Loc(...) are single tokens - mo = re.match('(Glo|Loc)\([^()]*\)', s) - if not mo: - mo = re.match('"([^\\\\"]|\\\\.)*"', s) - if not mo: - mo = re.match(g_ccid0 + g_ccid + '*', s) - if not mo: - mo = re.match('[0-9]+[bf]', s) - if not mo: - mo = re.match('0[Xx][0-9a-fA-F]+|[0-9]+', s) - if not mo: - mo = re.match('.', s) - result.append(mo.group(0)) - s = s[len(mo.group(0)):] - return result - - -def parse_rexpr(s): - # Like parse_expr(), but return only "real" tokens, not the - # intervening space. - # - return filter(lambda t: token_type(t) != 'space', parse_expr(s)) - - -def token_type(t): - # Determine the type of a token. Caller warrants that it was - # returned by parse_expr() or parse_rexpr(). - # - if re.match('[ \t]|/\*|@', t): - return 'space' - if re.match('Glo\(', t): - return 'gloid' - if re.match('Loc\(', t): - return 'locid' - if re.match('"', t): - return 'string' - if re.match(g_ccid0, t): - return 'id' - if re.match('[0-9]+[bf]', t): - return 'label' - if re.match('[0-9]', t): - return 'number' - return t # Sui generis - - -def debug_parse(a, b, c): - # Show results of instuction stream parse. - # - (b1, b2, b3) = parse_iparts(b) - newb = '{' + b1 + '}' + '{' + b2 + '}' + '{' + b3 + '}' - sys.stdout.write('{' + a + '}' + newb + c) - - -def main(): - instrs = parse_instrs(read_input()) - instrs = explicit_address_loads(instrs) - instrs = funtypes(instrs) - instrs = jump_tables(instrs) - instrs = global_symbols(instrs) - instrs = local_symbols(instrs) - instrs = dot_relative(instrs) - instrs = add_prefix(instrs) - for (a, b, c) in instrs: - sys.stdout.write(a + b + c) - - -main() diff --git a/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios.orig b/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios.orig deleted file mode 100755 index a049bca..0000000 --- a/Sources/OpenVPN3/deps/minicrypto/arm-as-to-ios.orig +++ /dev/null @@ -1,730 +0,0 @@ -#!/usr/bin/env python -# -# arm-as-to-ios Modify ARM assembly code for the iOS assembler -# -# Copyright (c) 2012 Psellos http://psellos.com/ -# Licensed under the MIT License: -# http://www.opensource.org/licenses/mit-license.php -# -# Resources for running OCaml on iOS: http://psellos.com/ocaml/ -# -import sys -import re - -VERSION = '1.4.0' - -# Character classes for expression lexing. -# -g_ccid0 = '[$.A-Z_a-z\x80-\xff]' # Beginning of id -g_ccid = '[$.0-9A-Z_a-z\x80-\xff]' # Later in id -def ccc(cc): # Complement the class - if cc[1] == '^': - return cc[0] + cc[2:] - return cc[0] + '^' + cc[1:] -def ccce(cc): # Complement the class, include EOL - return '(?:' + ccc(cc) + '|$)' - -# Prefixes for pooled symbol labels and jump table base labels. They're -# in the space of Linux assembler local symbols. Later rules will -# modify them to the Loc() form. -# -g_poolpfx = '.LP' -g_basepfx = '.LB' - - -def exists(p, l): - for l1 in l: - if p(l1): - return True - return False - - -def forall(p, l): - for l1 in l: - if not p(l1): - return False - return True - - -def add_prefix(instrs): - # Add compatibility macros for all systems, plus hardware - # definitions and compatibility macros for iOS. - # - # All systems: - # - # Glo() cpp macro for making global symbols (xxx vs _xxx) - # Loc() cpp macro for making local symbols (.Lxxx vs Lxxx) - # .funtype Expands to .thumb_func for iOS armv7 (null for armv6) - # Expands to .type %function for others - # - # iOS: - # - # .machine armv6/armv7 - # .thumb (for armv7) - # cbz Expands to cmp/beq for armv6 (Thumb-only instr) - # .type Not supported by Apple assembler - # .size Not supported by Apple assembler - # - defre = '#[ \t]*if.*def.*SYS' # Add new defs near first existing ones - skipre = '$|\.syntax[ \t]' # Skip comment lines (and .syntax) - - for i in range(len(instrs)): - if re.match(defre, instrs[i][1]): - break - else: - i = 0 - for i in range(i, len(instrs)): - if not re.match(skipre, instrs[i][1]): - break - instrs[i:0] = [ - ('', '', '\n'), - ('/* Apple compatibility macros */', '', '\n'), - ('', '#if defined(SYS_macosx)', '\n'), - ('', '#define Glo(s) _##s', '\n'), - ('', '#define Loc(s) L##s', '\n'), - ('', '#if defined(MODEL_armv6)', '\n'), - (' ', '.machine armv6', '\n'), - (' ', '.macro .funtype', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro cbz', '\n'), - (' ', 'cmp $0, #0', '\n'), - (' ', 'beq $1', '\n'), - (' ', '.endm', '\n'), - ('', '#else', '\n'), - (' ', '.machine armv7', '\n'), - (' ', '.thumb', '\n'), - (' ', '.macro .funtype', '\n'), - (' ', '.thumb_func $0', '\n'), - (' ', '.endm', '\n'), - ('', '#endif', '\n'), - (' ', '.macro .type', '\n'), - (' ', '.endm', '\n'), - (' ', '.macro .size', '\n'), - (' ', '.endm', '\n'), - ('', '#else', '\n'), - ('', '#define Glo(s) s', '\n'), - ('', '#define Loc(s) .L##s', '\n'), - (' ', '.macro .funtype symbol', '\n'), - (' ', '.type \\symbol, %function', '\n'), - (' ', '.endm', '\n'), - ('', '#endif', '\n'), - ('/* End Apple compatibility macros */', '', '\n'), - ('', '', '\n') - ] - return instrs - - -# Regular expression for modified ldr lines -# -g_ldre = '(ldr[ \t][^,]*,[ \t]*)=(([^ \t\n@,/]|/(?!\*))*)(.*)' - - -def explicit_address_loads(instrs): - # Linux assemblers allow the following: - # - # ldr rM, =symbol - # - # which loads rM with [mov] (immediately) if possible, or creates an - # entry in memory for the symbol value and loads it PC-relatively - # with [ldr]. - # - # The Apple assembler doesn't seem to support this notation. If the - # value is a suitable constant, it emits a valid [mov]. Otherwise - # it seems to emit an invalid [ldr] that always generates an error. - # (At least I have not been able to make it work). So, change uses - # of =symbol to explicit PC-relative loads. - # - # This requires a pool containing the addresses to be loaded. For - # now, we just keep track of it ourselves and emit it into the text - # segment at the end of the file. - # - syms = {} - result = [] - - def repl1((syms, result), (a, b, c)): - global g_poolpfx - global g_ldre - (b1, b2, b3) = parse_iparts(b) - mo = re.match(g_ldre, b3, re.DOTALL) - if mo: - if mo.group(2) not in syms: - syms[mo.group(2)] = len(syms) - psym = mo.group(2) - if psym[0:2] == '.L': - psym = psym[2:] - newb3 = mo.group(1) + g_poolpfx + psym + mo.group(4) - result.append((a, b1 + b2 + newb3, c)) - else: - result.append((a, b, c)) - return (syms, result) - - def pool1(result, s): - global g_poolpfx - psym = s - if psym[0:2] == '.L': - psym = psym[2:] - result.append(('', g_poolpfx + psym + ':', '\n')) - result.append((' ', '.long ' + s, '\n')) - return result - - reduce(repl1, instrs, (syms, result)) - if len(syms) > 0: - result.append(('', '', '\n')) - result.append(('/* Pool of addresses loaded into registers */', - '', '\n')) - result.append(('', '', '\n')) - result.append((' ', '.text', '\n')) - result.append((' ', '.align 2', '\n')) - reduce(pool1, sorted(syms, key=syms.get), result) - return result - - -def global_symbols(instrs): - # The form of a global symbol differs between Linux assemblers and - # the Apple assember: - # - # Linux: xxx - # Apple: _xxx - # - # Change occurrences of global symbols to use the Glo() cpp macro - # defined in our prefix. - # - # We consider a symbol to be global if: - # - # a. It appears in a .globl declaration; or - # b. It is referenced, has global form, and is not defined - # - glosyms = set() - refsyms = set() - defsyms = set() - result = [] - - def findglo1 (glosyms, (a, b, c)): - if re.match('#', b): - # Preprocessor line; nothing to do - return glosyms - (b1, b2, b3) = parse_iparts(b) - mo = re.match('(\.globl)' + ccce(g_ccid), b3) - if mo: - tokens = parse_expr(b3[len(mo.group(1)):]) - if forall(lambda t: token_type(t) in ['space', 'id', ','], tokens): - for t in tokens: - if token_type(t) == 'id': - glosyms.add(t) - return glosyms - - def findref1 ((refsyms, skipct), (a, b, c)): - - def looksglobal(s): - if re.match('(r|a|v|p|c|cr|f|s|d|q|mvax|wcgr)[0-9]+$', s, re.I): - return False # numbered registers - if re.match('(wr|sb|sl|fp|ip|sp|lr|pc)$', s, re.I): - return False # named registers - if re.match('(fpsid|fpscr|fpexc|mvfr1|mvfr0)$', s, re.I): - return False # more named registers - if re.match('(mvf|mvd|mvfx|mvdx|dspsc)$', s, re.I): - return False # even more named registers - if re.match('(wcid|wcon|wcssf|wcasf|acc)$', s, re.I): - return False # even more named registers - if re.match('\.$|\.L|[0-9]|#', s): - return False # dot, local symbol, or number - if re.match('(asl|lsl|lsr|asr|ror|rrx)$', s, re.I): - return False # shift names - return True - - if re.match('#', b): - # Preprocessor line; nothing to do - return (refsyms, skipct) - - # Track nesting of .macro/.endm. For now, we don't look for - # global syms in macro defs. (Avoiding scoping probs etc.) - # - if skipct > 0 and re.match('\.(endm|endmacro)' + ccce(g_ccid), b): - return (refsyms, skipct - 1) - if re.match('\.macro' + ccce(g_ccid), b): - return (refsyms, skipct + 1) - if skipct > 0: - return (refsyms, skipct) - if re.match('\.(type|size|syntax|arch|fpu)' + ccce(g_ccid), b): - return (refsyms, skipct) - - (b1, b2, b3) = parse_iparts(b) - rtokens = parse_rexpr(b3) - if len(rtokens) > 1 and rtokens[1] == '.req': - # .req has atypical syntax; no symbol refs there anyway - return (refsyms, skipct) - for t in rtokens[1:]: - if token_type(t) == 'id' and looksglobal(t): - refsyms.add(t) - return (refsyms, skipct) - - def finddef1(defsyms, (a, b, c)): - if re.match('#', b): - # Preprocessor line - return defsyms - (b1, b2, b3) = parse_iparts(b) - rtokens = parse_rexpr(b3) - if b1 != '': - defsyms.add(b1) - if len(rtokens) > 1 and rtokens[1] == '.req': - defsyms.add(rtokens[0]) - return defsyms - - def repl1((glosyms, result), (a, b, c)): - if re.match('#', b): - # Preprocessor line - result.append((a, b, c)) - return (glosyms, result) - toglo = lambda s: 'Glo(' + s + ')' - (b1, b2, b3) = parse_iparts(b) - tokens = parse_expr(b3) - - if b1 in glosyms: - b1 = toglo(b1) - for i in range(len(tokens)): - if token_type(tokens[i]) == 'id' and tokens[i] in glosyms: - tokens[i] = toglo(tokens[i]) - result.append((a, b1 + b2 + ''.join(tokens), c)) - return (glosyms, result) - - reduce(findglo1, instrs, glosyms) - reduce(findref1, instrs, (refsyms, 0)) - reduce(finddef1, instrs, defsyms) - glosyms |= (refsyms - defsyms) - reduce(repl1, instrs, (glosyms, result)) - return result - - -def local_symbols(instrs): - # The form of a local symbol differs between Linux assemblers and - # the Apple assember: - # - # Linux: .Lxxx - # Apple: Lxxx - # - # Change occurrences of local symbols to use the Loc() cpp macro - # defined in our prefix. - # - lsyms = set() - result = [] - - def find1 (lsyms, (a, b, c)): - mo = re.match('(\.L[^ \t:]*)[ \t]*:', b) - if mo: - lsyms.add(mo.group(1)) - return lsyms - - def repl1((lsyms, result), (a, b, c)): - matches = list(re.finditer('\.L[^ \t@:,+*/\-()]+', b)) - if matches != []: - matches.reverse() - newb = b - for mo in matches: - if mo.group() in lsyms: - newb = newb[0:mo.start()] + \ - 'Loc(' + mo.group()[2:] + ')' + \ - newb[mo.end():] - result.append((a, newb, c)) - else: - result.append((a, b, c)) - return (lsyms, result) - - reduce(find1, instrs, lsyms) - reduce(repl1, instrs, (lsyms, result)) - return result - - -def funtypes(instrs): - # Linux assemblers accept declarations like this: - # - # .type symbol, %function - # - # For Thumb functions, the Apple assembler wants to see: - # - # .thumb_func symbol - # - # Handle this by converting declarations to this: - # - # .funtype symbol - # - # Our prefix defines an appropriate .funtype macro for each - # environment. - # - result = [] - - def repl1(result, (a, b, c)): - mo = re.match('.type[ \t]+([^ \t,]*),[ \t]*%function', b) - if mo: - result.append((a, '.funtype ' + mo.group(1), c)) - else: - result.append((a, b, c)) - return result - - reduce(repl1, instrs, result) - return result - - -def jump_tables(instrs): - # Jump tables for Linux assemblers often look like this: - # - # tbh [pc, rM, lsl #1] - # .short (.Labc-.)/2+0 - # .short (.Ldef-.)/2+1 - # .short (.Lghi-.)/2+2 - # - # The Apple assembler disagrees about the meaning of this code, - # producing jump tables that don't work. Convert to the following: - # - # tbh [pc, rM, lsl #1] - # .LBxxx: - # .short (.Labc-.LBxxx)/2 - # .short (.Ldef-.LBxxx)/2 - # .short (.Lghi-.LBxxx)/2 - # - # In fact we just convert sequences of .short pseudo-ops of the - # right form. There's no requirement that they follow a tbh - # instruction. - # - baselabs = [] - result = [] - - def short_match(seq, op): - # Determine whether the op is a .short of the form that needs to - # be converted: .short (symbol-.)/2+k. If so, return a pair - # containing the symbol and the value of k. If not, return - # None. The short can only be converted if there were at least - # k other .shorts in sequence before the current one. A summary - # of the previous .shorts is in seq. - # - # (A real parser would do a better job, but this was quick to - # get working.) - # - sp = '([ \t]|/\*.*?\*/)*' # space - sp1 = '([ \t]|/\*.*?\*/)+' # at least 1 space - spe = '([ \t]|/\*.*?\*/|@[^\n]*)*$' # end-of-instr space - expr_re0 = ( - '\.short' + sp + '\(' + sp + # .short ( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + spe # /2 END - ) - expr_re1 = ( - '\.short' + sp + '\(' + sp + # .short ( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + sp + # /2 - '\+' + sp + # + - '((0[xX])?[0-9]+)' + spe # k END - ) - expr_re2 = ( - '\.short' + sp1 + # .short - '((0[xX])?[0-9]+)' + sp + # k - '\+' + sp + '\(' + sp + # +( - '([^ \t+\-*/@()]+)' + sp + # symbol - '-' + sp + '\.' + sp + '\)' + sp + # -.) - '/' + sp + '2' + spe # /2 END - ) - mo = re.match(expr_re0, op) - if mo: - return(mo.group(3), 0) - mo = re.match(expr_re1, op) - if mo: - k = int(mo.group(11), 0) - if k > len(seq): - return None - return (mo.group(3), k) - mo = re.match(expr_re2, op) - if mo: - k = int(mo.group(2), 0) - if k > len(seq): - return None - return (mo.group(7), k) - return None - - def conv1 ((baselabs, shortseq, label, result), (a, b, c)): - # Convert current instr (a,b,c) if it's a .short of the right - # form that spans a previous sequence of .shorts. - # - (b1, b2, b3) = parse_iparts(b) - - if b3 == '': - # No operation: just note label if present. - result.append((a, b, c)) - if re.match('\.L.', b1): - return (baselabs, shortseq, b1, result) - return (baselabs, shortseq, label, result) - - if not re.match('.short[ \t]+[^ \t@]', b3): - # Not a .short: clear shortseq and label - result.append((a, b, c)) - return (baselabs, [], '', result) - - # We have a .short: figure out the label if any - if re.match('\.L', b1): - sl = b1 - else: - sl = label - - mpair = short_match(shortseq, b3) - if not mpair: - # A .short, but not of right form - shortseq.append((len(result), sl)) - result.append((a, b, c)) - return (baselabs, shortseq, '', result) - - # OK, we have a .short to convert! - (sym, k) = mpair - shortseq.append((len(result), sl)) - - # Figure out base label (create one if necessary). - bx = len(shortseq) - 1 - k - bl = shortseq[bx][1] - if bl == '': - bl = g_basepfx + str(shortseq[bx][0]) - shortseq[bx] = (shortseq[bx][0], bl) - baselabs.append(shortseq[bx]) - - op = '.short\t(' + sym + '-' + bl + ')/2' - - result.append ((a, b1 + b2 + op, c)) - return (baselabs, shortseq, '', result) - - # Convert, accumulate result and new labels. - reduce(conv1, instrs, (baselabs, [], '', result)) - - # Add labels created here to the instruction stream. - baselabs.reverse() - for (ix, lab) in baselabs: - result[ix:0] = [('', lab + ':', '\n')] - - # That does it - return result - - -def dot_relative(instrs): - # The Apple assembler (or possibly the linker) has trouble with code - # that looks like this: - # - # .word .Label - . + 0x80000000 - # .word 0x1966 - # .Label: - # .word 0x1967 - # - # One way to describe the problem is that the assembler marks the - # first .word for relocation when in fact it's an assembly-time - # constant. Translate to the following form, which doesn't generate - # a relocation marking: - # - # DR0 = .Label - . + 0x80000000 - # .word DR0 - # .word 0x1966 - # .Label: - # .word 0x1967 - # - prefix = 'DR' - pseudos = '(\.byte|\.short|\.word|\.long|\.quad)' - result = [] - - def tok_ok(t): - return t in ['.', '+', '-', '(', ')'] or \ - token_type(t) in ['space', 'locid', 'number'] - - def dotrel_match(expr): - # Determine whether the expression is one that needs to be - # translated. - tokens = parse_expr(expr) - return forall(tok_ok, tokens) and \ - exists(lambda t: token_type(t) == 'locid', tokens) and \ - exists(lambda t: token_type(t) == 'number', tokens) and \ - exists(lambda t: t == '-', tokens) and \ - exists(lambda t: t == '.', tokens) - - def conv1(result, (a, b, c)): - if re.match('#', b): - # Preprocessor line - result.append((a, b, c)) - else: - (b1, b2, b3) = parse_iparts(b) - mo = re.match(pseudos + ccce(g_ccid), b3) - if mo: - p = mo.group(1) - expr = b3[len(p):] - if dotrel_match(expr): - sym = prefix + str(len(result)) - instr = sym + ' =' + expr - result.append(('', instr, '\n')) - result.append((a, b1 + b2 + p + ' ' + sym, c)) - else: - result.append((a, b, c)) - else: - result.append((a, b, c)) - return result - - reduce(conv1, instrs, result) - return result - - -def read_input(): - # Concatenate all the input files into a string. - # - def fnl(s): - if s == '' or s[-1] == '\n': - return s - else: - return s + '\n' - - if len(sys.argv) < 2: - return fnl(sys.stdin.read()) - else: - input = "" - for f in sys.argv[1:]: - try: - fd = open(f) - input = input + fnl(fd.read()) - fd.close() - except: - sys.stderr.write('arm-as-to-ios: cannot open ' + f + '\n') - return input - - -def parse_instrs(s): - # Parse the string into assembly instructions, also noting C - # preprocessor lines. Each instruction is represented as a triple: - # (space/comments, instruction, end). The end is either ';' or - # '\n'. - # - def goodmo(mo): - if mo == None: - # Should never happen - sys.stderr.write('arm-as-to-ios: internal parsing error\n') - sys.exit(1) - - cpp_re = '([ \t]*)(#([^\n]*\\\\\n)*[^\n]*[^\\\\\n])\n' - comment_re = '[ \t]*#[^\n]*' - instr_re = ( - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - '(([ \t]|/\*.*?\*/|[^;\n])*)' # "Instruction" - '([;\n])' # End - ) - instrs = [] - while s != '': - if re.match('[ \t]*#[ \t]*(if|ifdef|elif|else|endif|define)', s): - mo = re.match(cpp_re, s) - goodmo(mo) - instrs.append((mo.group(1), mo.group(2), '\n')) - elif re.match('[ \t]*#', s): - mo = re.match(comment_re, s) - goodmo(mo) - instrs.append((mo.group(0), '', '\n')) - else: - mo = re.match(instr_re, s, re.DOTALL) - goodmo(mo) - instrs.append((mo.group(1), mo.group(3), mo.group(5))) - s = s[len(mo.group(0)):] - return instrs - - -def parse_iparts(i): - # Parse an instruction into smaller parts, returning a triple of - # strings (label, colon, operation). The colon part also contains - # any surrounding spaces and comments (making the label and the - # operation cleaner to process). - # - # (Caller warrants that the given string doesn't start with space or - # a comment. This is true for strings returned by the instruction - # parser.) - # - lab_re = ( - '([^ \t:/@]+)' # Label - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - ':' # Colon - '(([ \t]|/\*.*?\*/|@[^\n]*)*)' # Spaces & comments - '([^\n]*)' # Operation - ) - - if len(i) > 0 and i[0] == '#': - # C preprocessor line; treat as operation. - return ('', '', i) - mo = re.match(lab_re, i) - if mo: - return (mo.group(1), mo.group(2) + ':' + mo.group(4), mo.group(6)) - # No label, just an operation - return ('', '', i) - - -def parse_expr(s): - # Parse a string into a sequence of tokens. A segment of white - # space (including comments) is treated as a token, so that the - # tokens can be reassembled into the string again. - # - result = [] - while s != '': - mo = re.match('([ \t]|/\*.*?\*/|@.*)+', s) - if not mo: - # Glo(...) and Loc(...) are single tokens - mo = re.match('(Glo|Loc)\([^()]*\)', s) - if not mo: - mo = re.match('"([^\\\\"]|\\\\.)*"', s) - if not mo: - mo = re.match(g_ccid0 + g_ccid + '*', s) - if not mo: - mo = re.match('[0-9]+[bf]', s) - if not mo: - mo = re.match('0[Xx][0-9a-fA-F]+|[0-9]+', s) - if not mo: - mo = re.match('.', s) - result.append(mo.group(0)) - s = s[len(mo.group(0)):] - return result - - -def parse_rexpr(s): - # Like parse_expr(), but return only "real" tokens, not the - # intervening space. - # - return filter(lambda t: token_type(t) != 'space', parse_expr(s)) - - -def token_type(t): - # Determine the type of a token. Caller warrants that it was - # returned by parse_expr() or parse_rexpr(). - # - if re.match('[ \t]|/\*|@', t): - return 'space' - if re.match('Glo\(', t): - return 'gloid' - if re.match('Loc\(', t): - return 'locid' - if re.match('"', t): - return 'string' - if re.match(g_ccid0, t): - return 'id' - if re.match('[0-9]+[bf]', t): - return 'label' - if re.match('[0-9]', t): - return 'number' - return t # Sui generis - - -def debug_parse(a, b, c): - # Show results of instuction stream parse. - # - (b1, b2, b3) = parse_iparts(b) - newb = '{' + b1 + '}' + '{' + b2 + '}' + '{' + b3 + '}' - sys.stdout.write('{' + a + '}' + newb + c) - - -def main(): - instrs = parse_instrs(read_input()) - instrs = explicit_address_loads(instrs) - instrs = funtypes(instrs) - instrs = jump_tables(instrs) - instrs = global_symbols(instrs) - instrs = local_symbols(instrs) - instrs = dot_relative(instrs) - instrs = add_prefix(instrs) - for (a, b, c) in instrs: - sys.stdout.write(a + b + c) - - -main() diff --git a/Sources/OpenVPN3/deps/minicrypto/build-minicrypto b/Sources/OpenVPN3/deps/minicrypto/build-minicrypto deleted file mode 100755 index f229b5d..0000000 --- a/Sources/OpenVPN3/deps/minicrypto/build-minicrypto +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -[ -z "$DL" ] && DL=~/Downloads - -. $O3/core/vars/vars-$TARGET -. $O3/core/deps/lib-versions - -# Build ASM files with clang 3.0 -if [ "$APPLE_FAMILY" = "1" ]; then - GCC_AS_CMD=$HOME/clang3/clang - if ! [ -f "$GCC_AS_CMD" ]; then - echo "clang 3.0 binary must be present in $GCC_AS_CMD to assemble ARM crypto algorithms" - exit 1 - fi -fi - -DEST=minicrypto/minicrypto-$PLATFORM - -GLOBAL_COMPILE_FLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC -DSHA1_ASM -DBF_PTR -DOPENSSL_VERSION_PTEXT= -D__LP32__" - -[ -z "$GCC_CMD" ] && GCC_CMD=gcc -[ -z "$GCC_AS_CMD" ] && GCC_AS_CMD="$GCC_CMD" -[ -z "$AR_CMD" ] && AR_CMD=ar -# the directory where this script lives -H=$O3/core/deps/minicrypto - -if [ "$NO_WIPE" != "1" ]; then - # unzip OpenSSL - rm -rf $OPENSSL_VERSION - tar xfz $DL/$OPENSSL_VERSION.tar.gz -fi - -OPENSSL_DIR=$(pwd)/$OPENSSL_VERSION - -# make build directory -mkdir -p minicrypto -rm -rf minicrypto/minicrypto-$PLATFORM -mkdir -p minicrypto/minicrypto-$PLATFORM/build.tmp -cd minicrypto/minicrypto-$PLATFORM/build.tmp -mkdir openssl - -# copy files from OpenSSL tree - -# ARM -cp $OPENSSL_DIR/crypto/arm_arch.h . - -# SHA general -cp $OPENSSL_DIR/crypto/md32_common.h . -cp $OPENSSL_DIR/crypto/sha/sha.h openssl - -# AES -cp $OPENSSL_DIR/crypto/aes/asm/aes-armv4.pl . - -# SHA1 -cp $OPENSSL_DIR/crypto/sha/asm/sha1-armv4-large.pl . -cp $OPENSSL_DIR/crypto/sha/sha_locl.h . -cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . - -# SHA2 -cp $OPENSSL_DIR/crypto/sha/sha256.c . -cp $OPENSSL_DIR/crypto/sha/asm/sha256-armv4.pl . - -# SHA4 -cp $OPENSSL_DIR/crypto/sha/sha512.c . -cp $OPENSSL_DIR/crypto/sha/asm/sha512-armv4.pl . - -# note that OPENSSL_cleanse is not used by any -# of the functions we are interested in -cat >openssl/crypto.h <armv4cpuid.S -#CMD="$GCC_AS_CMD $GLOBAL_COMPILE_FLAGS -DSYS_macosx -DNO_THUMB -c armv4cpuid.S" -#echo $CMD -#$CMD - -# build the ASM files given as perl source -for f in *.pl ; do - bn=${f%%.pl} - S=$bn.S - COMPILE_FLAGS="" - CVT_FLAGS="" - if [ "$APPLE_FAMILY" = "1" ]; then - COMPILE_FLAGS="$COMPILE_FLAGS -DNO_THUMB" - [ "$bn" = "aes-armv4" ] && CVT_FLAGS="$CVT_FLAGS --global=!ad1,!ad2,!ad3" - [ "$bn" = "sha512-armv4" ] && CVT_FLAGS="$CVT_FLAGS --global=!HI,!LO" - perl $f | $O3/core/deps/minicrypto/arm-as-to-ios --stdin $CVT_FLAGS >$S - else - perl $f >$S - fi - CMD="$GCC_AS_CMD $GLOBAL_COMPILE_FLAGS $COMPILE_FLAGS -DSYS_macosx -c $S" - echo $CMD - $CMD -done - -CMD="$AR_CMD crs ../libminicrypto.a *.o" -echo $CMD -$CMD -exit 0 diff --git a/Sources/OpenVPN3/deps/minicrypto/build-minicrypto-osx b/Sources/OpenVPN3/deps/minicrypto/build-minicrypto-osx deleted file mode 100755 index 5773833..0000000 --- a/Sources/OpenVPN3/deps/minicrypto/build-minicrypto-osx +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi -if [ -z "$ARCH" ]; then - echo "ARCH var must be defined (x86_64|i386)" - exit 1 -fi - -[ -z "$DL" ] && DL=~/Downloads - -. $O3/core/vars-$TARGET -. $O3/core/deps/lib-versions - -DEST=minicrypto/minicrypto-$PLATFORM - -GLOBAL_COMPILE_FLAGS="$MIN_DEPLOY_TARGET $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" - -[ -z "$GCC_CMD" ] && GCC_CMD=gcc -[ -z "$GCC_AS_CMD" ] && GCC_AS_CMD="$GCC_CMD" -[ -z "$AR_CMD" ] && AR_CMD=ar - -# the directory where this script lives -H=$O3/core/deps/minicrypto - -if [ "$NO_WIPE" != "1" ]; then - # unzip OpenSSL - rm -rf $OPENSSL_VERSION - tar xfz $DL/$OPENSSL_VERSION.tar.gz -fi - -OPENSSL_DIR=$(pwd)/$OPENSSL_VERSION - -# make build directory -mkdir -p minicrypto -rm -rf minicrypto/minicrypto-$PLATFORM/$ARCH -mkdir -p minicrypto/minicrypto-$PLATFORM/$ARCH/build.tmp -cd minicrypto/minicrypto-$PLATFORM/$ARCH/build.tmp -mkdir openssl - -# copy files from OpenSSL tree - -# AES (not necessary now that PolarSSL has AES optimizations) -#cp $OPENSSL_DIR/crypto/aes/asm/aesni-x86_64.pl . - -if [ "$ARCH" = "x86_64" ]; then - # General - cp $O3/core/deps/polarssl/intel_cpu.c . - cp $OPENSSL_DIR/crypto/perlasm/x86_64-xlate.pl . - cp $OPENSSL_DIR/crypto/x86_64cpuid.pl . - - # SHA general - cp $OPENSSL_DIR/crypto/md32_common.h . - cp $OPENSSL_DIR/crypto/sha/sha.h openssl - - # SHA1 - cp $OPENSSL_DIR/crypto/sha/sha_locl.h . - cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . - cp $OPENSSL_DIR/crypto/sha/asm/sha1-x86_64.pl . - - # SHA256 - cp $OPENSSL_DIR/crypto/sha/sha256.c . - - # SHA512 - cp $OPENSSL_DIR/crypto/sha/sha512.c . - cp $OPENSSL_DIR/crypto/sha/asm/sha512-x86_64.pl . - - # convert perl ASM to .s - for f in x86_64cpuid sha1-x86_64 ; do - perl $f.pl macosx >$f.s - done - perl sha512-x86_64.pl macosx sha512-x86_64.s - perl sha512-x86_64.pl macosx sha256-x86_64.s -elif [ "$ARCH" = "i386" ]; then - # General - cp $O3/core/deps/polarssl/intel_cpu.c . - cp $OPENSSL_DIR/crypto/perlasm/x86asm.pl . - cp $OPENSSL_DIR/crypto/perlasm/x86gas.pl . - cp $OPENSSL_DIR/crypto/x86cpuid.pl . - - # SHA general - cp $OPENSSL_DIR/crypto/md32_common.h . - cp $OPENSSL_DIR/crypto/sha/sha.h openssl - - # SHA1 - cp $OPENSSL_DIR/crypto/sha/sha_locl.h . - cp $OPENSSL_DIR/crypto/sha/sha1dgst.c . - cp $OPENSSL_DIR/crypto/sha/asm/sha1-586.pl . - - # SHA256 - cp $OPENSSL_DIR/crypto/sha/sha256.c . - cp $OPENSSL_DIR/crypto/sha/asm/sha256-586.pl . - - # SHA512 - cp $OPENSSL_DIR/crypto/sha/sha512.c . - cp $OPENSSL_DIR/crypto/sha/asm/sha512-586.pl . - - # convert perl ASM to .s - for f in x86cpuid sha1-586 sha256-586 sha512-586 ; do - perl $f.pl macosx >$f.s - done -fi - -cat >openssl/crypto.h <=7 -- ldr r12,.LOPENSSL_armcap -- ldr r12,[r3,r12] @ OPENSSL_armcap_P -- tst r12,#1 -- bne .LNEON -+ b .LNEON @ JY -- assume ARM v7 always supports NEON - #endif - stmdb sp!,{r4-r12,lr} - sub $Ktbl,r3,#672 @ K512 -@@ -573,7 +567,6 @@ - .size sha512_block_data_order,.-sha512_block_data_order - .asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " - .align 2 --.comm OPENSSL_armcap_P,4,4 - ___ - - $code =~ s/\`([^\`]*)\`/eval $1/gem; diff --git a/Sources/OpenVPN3/deps/openssl/build-openssl b/Sources/OpenVPN3/deps/openssl/build-openssl deleted file mode 100755 index ea15ffa..0000000 --- a/Sources/OpenVPN3/deps/openssl/build-openssl +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi -if [ -z "$OPENSSL_TARGET" ]; then - echo "OPENSSL_TARGET var must be defined" - exit 1 -fi - -# GNU sed differs from BSD sed -if sed --version 2>&1 | grep -q GNU ; then - mysed='sed -i' -else - mysed='sed -i ""' -fi - -[ -z "$GCC_CMD" ] && GCC_CMD=gcc - -[ -z "$LINK_MODE" ] && LINK_MODE=static -[ "$LINK_MODE" = "static" ] && LINK_MODE=no-shared - -[ -z "$DL" ] && DL=~/Downloads - -. $O3/core/vars/vars-$TARGET -. $O3/core/deps/lib-versions - - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# source helper functions -. $O3/core/deps/functions.sh - -FNAME=openssl-${OPENSSL_VERSION}.tar.gz -URL=https://www.openssl.org/source/${OPENSSL_VERSION}.tar.gz -CSUM=${OPENSSL_CSUM} - -download - -AR=ar -RANLIB=ranlib -[ "$AR_CMD" ] && AR=$AR_CMD -[ "$RANLIB_CMD" ] && RANLIB=$RANLIB_CMD - -# special hack because OpenSSL build system doesn't use rc options for ar -[ "$AR" = "gcc-ar" ] && AR="gcc-ar rc" -[ "$AR" = "gcc-ar-5" ] && AR="gcc-ar-5 rc" - -OPENSSL=$OPENSSL_VERSION -DIST=$(pwd)/openssl/openssl-$PLATFORM -[ "$ARCH" ] && DIST=$DIST/$ARCH -rm -rf $OPENSSL $DIST -mkdir -p $DIST -tar xfz $DL/$FNAME -pushd $OPENSSL -CMD="./Configure $OPENSSL_TARGET $LINK_MODE threads no-idea no-mdc2 no-rc5 --prefix=$DIST" -echo $CMD -$CMD -$mysed -e "s|-O3|$LIB_OPT_LEVEL $MIN_DEPLOY_TARGET $OTHER_COMPILER_FLAGS $LIB_FPIC|" Makefile -#$mysed -e "s|ERR_load_COMP_strings()|//ERR_load_COMP_strings()|" crypto/err/err_all.c -make depend -make CC="$GCC_CMD" AR="$AR" RANLIB="$RANLIB" -j ${MAKE_JOBS:-1} build_libs -touch apps/openssl -touch openssl.pc -touch libcrypto.pc -touch libssl.pc -make install_sw -popd - -exit 0 diff --git a/Sources/OpenVPN3/deps/polarssl/.gitignore b/Sources/OpenVPN3/deps/polarssl/.gitignore deleted file mode 100644 index 75ea0b2..0000000 --- a/Sources/OpenVPN3/deps/polarssl/.gitignore +++ /dev/null @@ -1 +0,0 @@ -polartmp diff --git a/Sources/OpenVPN3/deps/polarssl/CMakeLists.txt b/Sources/OpenVPN3/deps/polarssl/CMakeLists.txt deleted file mode 100644 index d98aca5..0000000 --- a/Sources/OpenVPN3/deps/polarssl/CMakeLists.txt +++ /dev/null @@ -1,86 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(POLARSSL C) - -enable_testing() - -if(CMAKE_COMPILER_IS_GNUCC) - # JY Added - set(CMAKE_OSX_ARCHITECTURES "") - set(CMAKE_OSX_DEPLOYMENT_TARGET "") - set(CMAKE_OSX_SYSROOT "") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} $ENV{LIB_FPIC} $ENV{LIB_OPT_LEVEL} $ENV{PLATFORM_FLAGS} $ENV{OTHER_COMPILER_FLAGS} -Wall -W -Wdeclaration-after-statement") - if (NOT "$ENV{GCC_CMD}" STREQUAL "") - set(CMAKE_C_COMPILER "$ENV{GCC_CMD}") - endif() - if (NOT "$ENV{GPP_CMD}" STREQUAL "") - set(CMAKE_CXX_COMPILER "$ENV{GPP_CMD}") - endif() - if (NOT "$ENV{AR_CMD}" STREQUAL "") - set(CMAKE_AR "$ENV{AR_CMD}") - endif() - if (NOT "$ENV{RANLIB_CMD}" STREQUAL "") - set(CMAKE_RANLIB "$ENV{RANLIB_CMD}") - endif() - - # JY Commented out - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -Wall -Wextra -W -Wdeclaration-after-statement") - #set(CMAKE_C_FLAGS_DEBUG "-g3 -O0") - #set(CMAKE_C_FLAGS_COVERAGE "-g3 -O0 -fprofile-arcs -ftest-coverage -lgcov") -endif(CMAKE_COMPILER_IS_GNUCC) - -if(CMAKE_BUILD_TYPE STREQUAL "Coverage") - if(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_SHARED_LINKER_FLAGS "-fprofile-arcs -ftest-coverage") - endif(CMAKE_COMPILER_IS_GNUCC) -endif(CMAKE_BUILD_TYPE STREQUAL "Coverage") - -option(USE_PKCS11_HELPER_LIBRARY "Build PolarSSL with the pkcs11-helper library." OFF) - -option(ENABLE_ZLIB_SUPPORT "Build PolarSSL with zlib library." OFF) - -# JY added -if(MINICRYPTO) - if(MINICRYPTO_DIR) - add_library(minicrypto STATIC IMPORTED) - set_property(TARGET minicrypto PROPERTY IMPORTED_LOCATION "${MINICRYPTO_DIR}/libminicrypto.a") - endif() - if(OSSLCRYPTO_DIR) - add_library(crypto STATIC IMPORTED) - set_property(TARGET crypto PROPERTY IMPORTED_LOCATION "${OSSLCRYPTO_DIR}/libcrypto.a") - endif() -endif() - -# include full testing infrastructure (JY added) -if(ENABLE_TESTING) - enable_testing() -endif() - -if(LIB_INSTALL_DIR) -else() -set(LIB_INSTALL_DIR lib) -endif() - -include_directories(include/) - -if(ENABLE_ZLIB_SUPPORT) - find_package(ZLIB) - - if(ZLIB_FOUND) - include_directories(ZLIB_INCLUDE_DIR) - endif(ZLIB_FOUND) -endif(ENABLE_ZLIB_SUPPORT) - -add_subdirectory(library) -add_subdirectory(include) - -# include full testing infrastructure (JY modified) -if(ENABLE_TESTING) - if(CMAKE_COMPILER_IS_GNUCC) - add_subdirectory(tests) - endif(CMAKE_COMPILER_IS_GNUCC) - add_subdirectory(programs) -endif() - -ADD_CUSTOM_TARGET(apidoc - COMMAND doxygen doxygen/polarssl.doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/Sources/OpenVPN3/deps/polarssl/README.txt b/Sources/OpenVPN3/deps/polarssl/README.txt deleted file mode 100644 index 2c58a3d..0000000 --- a/Sources/OpenVPN3/deps/polarssl/README.txt +++ /dev/null @@ -1,12 +0,0 @@ -Building PolarSSL for android. - -First, build static OpenSSL for PolarSSL/OpenSSL bridge -(the build-openssl-small script may be used). - -Next build libminicrypto.a from libcrypto.a : - - $O3/polarssl/build-mini-openssl ref - -Finally, build PolarSSL: - - TARGET=android $O3/polarssl/build-polarssl diff --git a/Sources/OpenVPN3/deps/polarssl/android.cmake b/Sources/OpenVPN3/deps/polarssl/android.cmake deleted file mode 100644 index 0f1d04f..0000000 --- a/Sources/OpenVPN3/deps/polarssl/android.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# this one is important -SET(CMAKE_SYSTEM_NAME Linux) -#this one not so much -SET(CMAKE_SYSTEM_VERSION 1) - -# specify the cross compiler (assumes that PATH already points to android toolchain) -SET(CMAKE_C_COMPILER gcc) -SET(CMAKE_CXX_COMPILER g++) - -# where is the target environment -#SET(CMAKE_FIND_ROOT_PATH /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst) - -# search for programs in the build host directories -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -# for libraries and headers in the target directories -SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/Sources/OpenVPN3/deps/polarssl/apple.cmake b/Sources/OpenVPN3/deps/polarssl/apple.cmake deleted file mode 100644 index 2b58f24..0000000 --- a/Sources/OpenVPN3/deps/polarssl/apple.cmake +++ /dev/null @@ -1,4 +0,0 @@ -# specify the cross compiler -SET(CMAKE_C_COMPILER clang) -SET(CMAKE_CXX_COMPILER clang++) -SET(CMAKE_COMPILER_IS_GNUCC 1) diff --git a/Sources/OpenVPN3/deps/polarssl/bignum-arm.patch b/Sources/OpenVPN3/deps/polarssl/bignum-arm.patch deleted file mode 100644 index 12178ae..0000000 --- a/Sources/OpenVPN3/deps/polarssl/bignum-arm.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff -uNr polarssl-1.2.7/include/polarssl/bn_mul.h polarssl-1.2.7.new/include/polarssl/bn_mul.h ---- polarssl-1.2.7/include/polarssl/bn_mul.h 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl-1.2.7.new/include/polarssl/bn_mul.h 2013-06-13 16:30:35.000000000 -0600 -@@ -548,7 +548,7 @@ - - #if defined(__arm__) - --#if defined(__thumb__) -+#if defined(__thumb__) && !defined(__thumb2__) - - #define MULADDC_INIT \ - asm( \ -diff -uNr polarssl-1.2.7/library/bignum.c polarssl-1.2.7.new/library/bignum.c ---- polarssl-1.2.7/library/bignum.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl-1.2.7.new/library/bignum.c 2013-06-13 16:30:35.000000000 -0600 -@@ -935,7 +935,15 @@ - /* - * Helper for mpi multiplication - */ --static void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) -+static -+#if defined(__APPLE__) && defined(__arm__) -+/* -+ * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) -+ * appears to need this to prevent bad ARM code generation at -O3. -+ */ -+__attribute__ ((noinline)) -+#endif -+void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) - { - t_uint c = 0, t = 0; - diff --git a/Sources/OpenVPN3/deps/polarssl/build-detail-patch b/Sources/OpenVPN3/deps/polarssl/build-detail-patch deleted file mode 100755 index a71e342..0000000 --- a/Sources/OpenVPN3/deps/polarssl/build-detail-patch +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -e -. $O3/core/deps/lib-versions -POLARSSL_SRC=$HOME/src/mac/$POLARSSL_VERSION -PD=$O3/core/deps/polarssl -PB=$(basename $POLARSSL_SRC) - -rm -rf polartmp -mkdir polartmp -cd polartmp -cp -a $POLARSSL_SRC polarssl.new - -# extract the PolarSSL source -tar xfz $DL/$PB-gpl.tgz - -cd $PB -rm $(find . -type f | grep -E 'Makefile|\.orig$|\.rej$') -rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h - -cd ../polarssl.new -rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h -cd .. - -diff -ur $PB polarssl.new | grep -v '^Only in' diff --git a/Sources/OpenVPN3/deps/polarssl/build-mini-openssl b/Sources/OpenVPN3/deps/polarssl/build-mini-openssl deleted file mode 100755 index 6ecf736..0000000 --- a/Sources/OpenVPN3/deps/polarssl/build-mini-openssl +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -# Examples: -# $O3/core/deps/polarssl/build-mini-openssl ref -# $O3/core/deps/polarssl/build-mini-openssl ref-aesni - -set -e -if [ -z "$1" ]; then - echo "usage: build-mini-openssl " - exit 1 -fi -if [ -z "$OPENSSL_DIR" ]; then - echo OPENSSL_DIR must be defined - exit 1 -fi - -if [ "$APPLE_FAMILY" = "1" ] && [ -z "$GCC_CMD" ]; then - GCC_CMD=clang -fi - -if [ "$APPLE_FAMILY" = "1" ]; then - NM_FLAGS=-P - BSD_SYMBOLS="1" - VISIBILITY="-fvisibility=hidden" -else - NM_FLAGS="-f posix" - BSD_SYMBOLS="0" - VISIBILITY="" -fi - -[ -z "$NM_CMD" ] && NM_CMD=nm -[ -z "$AR_CMD" ] && AR_CMD=ar -[ -z "$GCC_CMD" ] && GCC_CMD=gcc -PD=$O3/core/deps/polarssl -cd $OPENSSL_DIR -cd lib -rm -rf tmp -mkdir tmp -$NM_CMD $NM_FLAGS libcrypto.a >tmp/nm-file -echo "NOTE: on BSD systems, don't worry about any 'no name list' errors above" -cd tmp -python $O3/common/scripts/sym.py $PD/$1 nm-file $AR_CMD ../libcrypto.a libminicrypto.a buildmini ../mini-undef.sh $BSD_SYMBOLS -. buildmini - -# need any special initialization? -. ../mini-undef.sh -if [ "$SYM_UNDEF_OPENSSL_ia32cap_P" ] && [ "$SYM_UNDEF_OPENSSL_cpuid_setup" ]; then - echo BUILDING STUB intel_cpu.c - $GCC_CMD $VISIBILITY $LIB_OPT_LEVEL $LIB_FPIC -c $PD/intel_cpu.c - $AR_CMD rs libminicrypto.a intel_cpu.o -fi - -mv libminicrypto.a .. diff --git a/Sources/OpenVPN3/deps/polarssl/build-polarssl b/Sources/OpenVPN3/deps/polarssl/build-polarssl deleted file mode 100755 index dad7a23..0000000 --- a/Sources/OpenVPN3/deps/polarssl/build-polarssl +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env bash -# -# Parameters: -# CMAKE_TARGET -- use $CMAKE_TARGET.cmake as toolchain file -# AES_NI=1 -- enable AES_NI processor optimization -# EXTERNAL_RNG=1 -- disable all internal RNG implementations (caller must provide) -# ENABLE_TESTING=1 -- run PolarSSL test scripts after build -# DEBUG_BUILD=1 or SELF_TEST=1 -- enable minimal testing on target -# ENABLE_SERVER=1 -- enable SSL/TLS server code -# ENABLE_FS_IO=1 -- enable PolarSSL file I/O -# VERBOSE=1 -- see build commands -# USE_MINICRYPTO=1 -- use minicrypto library -# NO_WIPE=1 -- don't wipe source tree and reunzip tarball -# STOCK_CONFIG=1 -- use stock PolarSSL config.h - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -# extract the PolarSSL source -PD=$O3/core/deps/polarssl -DIST=polarssl-$PLATFORM - -rm -rf $DIST -mkdir $DIST - -if [ "$NO_WIPE" = "1" ]; then - echo RETAIN existing source - cd $POLARSSL_VERSION -elif [ "$NO_WIPE" = "partial" ]; then - echo RETAIN existing source but copy config.h and CMakeLists.txt - cd $POLARSSL_VERSION - - # define configs - if [ "$STOCK_CONFIG" != "1" ]; then - cp $PD/config.h include/polarssl/ - fi - cp $PD/CMakeLists.txt . -else - echo WIPE and reunzip source - rm -rf $POLARSSL_VERSION $POLARSSL_VERSION-prerelease - [ -z "$DL" ] && DL=~/Downloads - tar xfz $DL/$POLARSSL_VERSION-gpl.tgz - - [ -d $POLARSSL_VERSION-prerelease ] && mv $POLARSSL_VERSION-prerelease $POLARSSL_VERSION - cd $POLARSSL_VERSION - - # delete makefiles (apparently not needed) - rm $(find . -type f | grep Makefile) - - patch -p1 <$PD/relaxed-x509-date.patch - #patch -p1 <$PD/dhm.patch - #patch -p1 <$PD/entropy-printf.patch - - if [ "$USE_MINICRYPTO" = "1" ]; then - # do the big polar-openssl patch - echo MERGING polarssl-minicrypto.patch - patch -p1 <$PD/polarssl-minicrypto.patch - fi - - # define configs - cp include/polarssl/config.h include/polarssl/config.h.orig - cp CMakeLists.txt CMakeLists.txt.orig - cp $PD/config.h include/polarssl/ - cp $PD/CMakeLists.txt . -fi - -# dynamically generated header file with options, -# included by config.h -OPC=include/polarssl/openvpn-polarssl.h -echo '/* Automatically generated by ovpn3/core/deps/polarssl/build-polarssl, do not edit */' >$OPC - -# set options -OPT="" - -# relaxed cert checking -echo "#define POLARSSL_RELAXED_X509_DATE" >>$OPC - -# RNG -if [ "$EXTERNAL_RNG" = "1" ]; then - echo "#define EXTERNAL_RNG" >>$OPC -fi - -# enable full testing infrastructure -if [ "$ENABLE_TESTING" = "1" ]; then - OPT="$OPT -DENABLE_TESTING=1" - echo "#define ENABLE_TESTING" >>$OPC -fi - -# enable minimal testing on target -if [ "$DEBUG_BUILD" = "1" ] || [ "$SELF_TEST" = "1" ]; then - echo "#define POLARSSL_SELF_TEST" >>$OPC -fi - -# configure target -if [ "$CMAKE_TARGET" ]; then - OPT="$OPT -DCMAKE_TOOLCHAIN_FILE=$PD/$CMAKE_TARGET.cmake" -elif [ "$APPLE_FAMILY" = "1" ]; then - OPT="$OPT -DCMAKE_TOOLCHAIN_FILE=$PD/apple.cmake" -fi - -# Minicrypto -if [ "$USE_MINICRYPTO" = "1" ]; then - OPT="$OPT -DMINICRYPTO=1" - if [ "$MINICRYPTO_DIR" ]; then - OPT="$OPT -DMINICRYPTO_DIR=$MINICRYPTO_DIR" - fi - if [ "$OSSLCRYPTO_DIR" ]; then - OPT="$OPT -DOSSLCRYPTO_DIR=$OSSLCRYPTO_DIR" - fi - if [ "$MINICRYPTO_NO_AES" != "1" ]; then - echo "#define POLARSSL_AES_ALT" >>$OPC - fi - echo "#define POLARSSL_SHA1_ALT" >>$OPC - echo "#define POLARSSL_SHA256_ALT" >>$OPC - echo "#define POLARSSL_SHA512_ALT" >>$OPC - if [ "$AES_NI" = "1" ] && [ "$MINICRYPTO_NO_AES" != "1" ]; then - echo "#define POLARSSL_USE_OPENSSL_AES_NI" >>$OPC - fi -fi - -# Enable SSL/TLS server -if [ "$ENABLE_SERVER" = "1" ]; then - echo "#define POLARSSL_SSL_SRV_C" >>$OPC -fi - -# enable PolarSSL file I/O -if [ "$ENABLE_FS_IO" = "1" ]; then - echo "#define POLARSSL_FS_IO" >>$OPC -fi - -# Build shared library -if [ "$SHARED" = "1" ]; then - OPT="$OPT -DUSE_SHARED_POLARSSL_LIBRARY=1" -fi - -# echo options -echo OPTIONS $OPT - -# build it -pwd -cd ../$DIST -cmake $OPT ../$POLARSSL_VERSION -if [ "$VERBOSE" = "1" ]; then - make VERBOSE=1 -else - make -fi - -# test it -if [ "$ENABLE_TESTING" = "1" ]; then - make test -fi - -# copy headers -cp -a ../$POLARSSL_VERSION/include/polarssl include/ -exit 0 diff --git a/Sources/OpenVPN3/deps/polarssl/build-polarssl-patch b/Sources/OpenVPN3/deps/polarssl/build-polarssl-patch deleted file mode 100755 index 1562ac2..0000000 --- a/Sources/OpenVPN3/deps/polarssl/build-polarssl-patch +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -e -. $O3/core/deps/lib-versions -POLARSSL_SRC=$HOME/src/mac/$POLARSSL_VERSION -PD=$O3/core/deps/polarssl -PB=$(basename $POLARSSL_SRC) - -rm -rf polartmp -mkdir polartmp -cd polartmp -cp -a $POLARSSL_SRC polarssl.new - -# extract the PolarSSL source -tar xfz $DL/$PB-gpl.tgz - -cd $PB -rm $(find . -type f | grep -E 'Makefile|\.orig$|\.rej$') -rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h - -cd ../polarssl.new -rm -f CMakeLists.txt include/polarssl/config.h include/polarssl/openvpn-polarssl.h -cd .. - -if [ "$CRYPTO_ALT_PATCH" = "1" ]; then - diff -uNr $PB polarssl.new >$PD/polar-openssl.patch - cp $PD/crypto-alt.txt $PD/polarssl-crypto-alt.patch - diff -ur $PB polarssl.new | grep -v '^Only in' >>$PD/polarssl-crypto-alt.patch -else - diff -ur $PB polarssl.new | grep -v '^Only in' -fi diff --git a/Sources/OpenVPN3/deps/polarssl/config.h b/Sources/OpenVPN3/deps/polarssl/config.h deleted file mode 100644 index 482b3ed..0000000 --- a/Sources/OpenVPN3/deps/polarssl/config.h +++ /dev/null @@ -1,2227 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#include - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def POLARSSL_HAVE_INT8 - * - * The system uses 8-bit wide native integers. - * - * Uncomment if native integers are 8-bit wide. - */ -//#define POLARSSL_HAVE_INT8 - -/** - * \def POLARSSL_HAVE_INT16 - * - * The system uses 16-bit wide native integers. - * - * Uncomment if native integers are 16-bit wide. - */ -//#define POLARSSL_HAVE_INT16 - -/** - * \def POLARSSL_HAVE_LONGLONG - * - * The compiler supports the 'long long' type. - * (Only used on 32-bit platforms) - */ -#define POLARSSL_HAVE_LONGLONG - -/** - * \def POLARSSL_HAVE_ASM - * - * The compiler has support for asm(). - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - * Comment to disable the use of assembly code. - */ -#define POLARSSL_HAVE_ASM - -/** - * \def POLARSSL_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - */ -//#define POLARSSL_HAVE_SSE2 - -/** - * \def POLARSSL_HAVE_TIME - * - * System has time.h and time() / localtime() / gettimeofday(). - * - * Comment if your system does not support time functions - */ -#define POLARSSL_HAVE_TIME - -/** - * \def POLARSSL_HAVE_IPV6 - * - * System supports the basic socket interface for IPv6 (RFC 3493), - * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. - * - * Note: on Windows/MingW, XP or higher is required. - * - * Comment if your system does not support the IPv6 socket interface - */ -#define POLARSSL_HAVE_IPV6 - -/** - * \def POLARSSL_PLATFORM_MEMORY - * - * Enable the memory allocation layer. - * - * By default PolarSSL uses the system-provided malloc() and free(). - * This allows different allocators (self-implemented or provided) to be - * provided to the platform abstraction layer. - * - * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()" - * to allow you to set an alternative malloc() and free() function pointer. - * - * Requires: POLARSSL_PLATFORM_C - * - * Enable this layer to allow use of alternative memory allocators. - */ -//#define POLARSSL_PLATFORM_MEMORY - -/** - * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS - * - * Do not assign standard functions in the platform layer (e.g. malloc() to - * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) - * - * This makes sure there are no linking errors on platforms that do not support - * these functions. You will HAVE to provide alternatives, either at runtime - * via the platform_set_xxx() functions or at compile time by setting - * the POLARSSL_PLATFORM_STD_XXX defines. - * - * Requires: POLARSSL_PLATFORM_C - * - * Uncomment to prevent default assignment of standard functions in the - * platform layer. - */ -//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS - -/** - * \def POLARSSL_PLATFORM_XXX_ALT - * - * Uncomment a macro to let PolarSSL support the function in the platform - * abstraction layer. - * - * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will - * provide a function "platform_set_printf()" that allows you to set an - * alternative printf function pointer. - * - * All these define require POLARSSL_PLATFORM_C to be defined! - * - * Uncomment a macro to enable alternate implementation of specific base - * platform function - */ -//#define POLARSSL_PLATFORM_PRINTF_ALT -//#define POLARSSL_PLATFORM_FPRINTF_ALT -/* \} name SECTION: System support */ - -/** - * \name SECTION: PolarSSL feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def POLARSSL_TIMING_ALT - * - * Uncomment to provide your own alternate implementation for hardclock(), - * get_timer(), set_alarm() and m_sleep(). - * - * Only works if you have POLARSSL_TIMING_C enabled. - * - * You will need to provide a header "timing_alt.h" and an implementation at - * compile time. - */ -//#define POLARSSL_TIMING_ALT - -/** - * \def POLARSSL_XXX_ALT - * - * Uncomment a macro to let PolarSSL use your alternate core implementation of - * a symmetric or hash algorithm (e.g. platform specific assembly optimized - * implementations). Keep in mind that the function prototypes should remain - * the same. - * - * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer - * provide the "struct aes_context" definition and omit the base function - * declarations and implementations. "aes_alt.h" will be included from - * "aes.h" to include the new function definitions. - * - * Uncomment a macro to enable alternate implementation for core algorithm - * functions - */ -//#define POLARSSL_AES_ALT -//#define POLARSSL_ARC4_ALT -//#define POLARSSL_BLOWFISH_ALT -//#define POLARSSL_CAMELLIA_ALT -//#define POLARSSL_DES_ALT -//#define POLARSSL_XTEA_ALT -//#define POLARSSL_MD2_ALT -//#define POLARSSL_MD4_ALT -//#define POLARSSL_MD5_ALT -//#define POLARSSL_RIPEMD160_ALT -//#define POLARSSL_SHA1_ALT -//#define POLARSSL_SHA256_ALT -//#define POLARSSL_SHA512_ALT - -/** - * \def POLARSSL_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - * - */ -//#define POLARSSL_AES_ROM_TABLES - -/** - * \def POLARSSL_CIPHER_MODE_CBC - * - * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CBC - -/** - * \def POLARSSL_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -// JY removed -//#define POLARSSL_CIPHER_MODE_CFB - -/** - * \def POLARSSL_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CTR - -/** - * \def POLARSSL_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * TLS_ECDH_ECDSA_WITH_NULL_SHA - * TLS_ECDH_RSA_WITH_NULL_SHA - * TLS_ECDHE_ECDSA_WITH_NULL_SHA - * TLS_ECDHE_RSA_WITH_NULL_SHA - * TLS_ECDHE_PSK_WITH_NULL_SHA384 - * TLS_ECDHE_PSK_WITH_NULL_SHA256 - * TLS_ECDHE_PSK_WITH_NULL_SHA - * TLS_DHE_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_NULL_SHA256 - * TLS_DHE_PSK_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_SHA256 - * TLS_RSA_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_MD5 - * TLS_RSA_PSK_WITH_NULL_SHA384 - * TLS_RSA_PSK_WITH_NULL_SHA256 - * TLS_RSA_PSK_WITH_NULL_SHA - * TLS_PSK_WITH_NULL_SHA384 - * TLS_PSK_WITH_NULL_SHA256 - * TLS_PSK_WITH_NULL_SHA - * - * Uncomment this macro to enable the NULL cipher and ciphersuites - */ -//#define POLARSSL_CIPHER_NULL_CIPHER - -/** - * \def POLARSSL_CIPHER_PADDING_XXX - * - * Uncomment or comment macros to add support for specific padding modes - * in the cipher layer with cipher modes that support padding (e.g. CBC) - * - * If you disable all padding modes, only full blocks can be used with CBC. - * - * Enable padding modes in the cipher layer. - */ -#define POLARSSL_CIPHER_PADDING_PKCS7 -#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS -#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN -#define POLARSSL_CIPHER_PADDING_ZEROS - -/** - * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS. - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * TLS_RSA_WITH_DES_CBC_SHA - * TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites - */ -//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES - -/** - * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES - * - * Remove RC4 ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on RC4 from the default list as - * returned by ssl_list_ciphersuites(). However, it is still possible to - * enable (some of) them with ssl_set_ciphersuites() by including them - * explicitly. - * - * Uncomment this macro to remove RC4 ciphersuites by default. - */ -// JY added -- crypto -#define POLARSSL_REMOVE_ARC4_CIPHERSUITES - -/** - * \def POLARSSL_ECP_XXXX_ENABLED - * - * Enables specific curves within the Elliptic Curve module. - * By default all supported curves are enabled. - * - * Comment macros to disable the curve and functions for it - */ -#define POLARSSL_ECP_DP_SECP192R1_ENABLED -#define POLARSSL_ECP_DP_SECP224R1_ENABLED -#define POLARSSL_ECP_DP_SECP256R1_ENABLED -#define POLARSSL_ECP_DP_SECP384R1_ENABLED -#define POLARSSL_ECP_DP_SECP521R1_ENABLED -#define POLARSSL_ECP_DP_SECP192K1_ENABLED -#define POLARSSL_ECP_DP_SECP224K1_ENABLED -#define POLARSSL_ECP_DP_SECP256K1_ENABLED -#define POLARSSL_ECP_DP_BP256R1_ENABLED -#define POLARSSL_ECP_DP_BP384R1_ENABLED -#define POLARSSL_ECP_DP_BP512R1_ENABLED -//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! -#define POLARSSL_ECP_DP_M255_ENABLED -//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! -//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! - -/** - * \def POLARSSL_ECP_NIST_OPTIM - * - * Enable specific 'modulo p' routines for each NIST prime. - * Depending on the prime and architecture, makes operations 4 to 8 times - * faster on the corresponding curve. - * - * Comment this macro to disable NIST curves optimisation. - */ -#define POLARSSL_ECP_NIST_OPTIM - -/** - * \def POLARSSL_ECDSA_DETERMINISTIC - * - * Enable deterministic ECDSA (RFC 6979). - * Standard ECDSA is "fragile" in the sense that lack of entropy when signing - * may result in a compromise of the long-term signing key. This is avoided by - * the deterministic variant. - * - * Requires: POLARSSL_HMAC_DRBG_C - * - * Comment this macro to disable deterministic ECDSA. - */ -#define POLARSSL_ECDSA_DETERMINISTIC - -/** - * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED - * - * Enable the PSK based ciphersuite modes in SSL / TLS. - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -// JY removed -- PSK -//#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - * - * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - */ -// JY removed -- PSK -//#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - * - * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - */ -// JY removed -- PSK -//#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - * - * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_RC4_128_SHA - */ -// JY removed -- PSK -//#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED - * - * Enable the RSA-only based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - */ -#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - * - * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - */ -#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - * - * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - * - * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - * - * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - * - * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - -/** - * \def POLARSSL_PK_PARSE_EC_EXTENDED - * - * Enhance support for reading EC keys using variants of SEC1 not allowed by - * RFC 5915 and RFC 5480. - * - * Currently this means parsing the SpecifiedECDomain choice of EC - * parameters (only known groups are supported, not arbitrary domains, to - * avoid validation issues). - * - * Disable if you only need to support RFC 5915 + 5480 key formats. - */ -#define POLARSSL_PK_PARSE_EC_EXTENDED - -/** - * \def POLARSSL_ERROR_STRERROR_BC - * - * Make available the backward compatible error_strerror() next to the - * current polarssl_strerror(). - * - * For new code, it is recommended to use polarssl_strerror() instead and - * disable this. - * - * Disable if you run into name conflicts and want to really remove the - * error_strerror() - */ -// JY removed -//#define POLARSSL_ERROR_STRERROR_BC - -/** - * \def POLARSSL_ERROR_STRERROR_DUMMY - * - * Enable a dummy error function to make use of polarssl_strerror() in - * third party libraries easier when POLARSSL_ERROR_C is disabled - * (no effect when POLARSSL_ERROR_C is enabled). - * - * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're - * not using polarssl_strerror() or error_strerror() in your application. - * - * Disable if you run into name conflicts and want to really remove the - * polarssl_strerror() - */ -#define POLARSSL_ERROR_STRERROR_DUMMY - -/** - * \def POLARSSL_GENPRIME - * - * Enable the prime-number generation code. - * - * Requires: POLARSSL_BIGNUM_C - */ -#define POLARSSL_GENPRIME - -/** - * \def POLARSSL_FS_IO - * - * Enable functions that use the filesystem. - */ -// JY removed -//#define POLARSSL_FS_IO - -/** - * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. - */ -//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - -/** - * \def POLARSSL_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. - */ -//#define POLARSSL_NO_PLATFORM_ENTROPY - -// JY added -#ifdef EXTERNAL_RNG -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES -#define POLARSSL_NO_PLATFORM_ENTROPY -#endif - -/** - * \def POLARSSL_ENTROPY_FORCE_SHA256 - * - * Force the entropy accumulator to use a SHA-256 accumulator instead of the - * default SHA-512 based one (if both are available). - * - * Requires: POLARSSL_SHA256_C - * - * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option - * if you have performance concerns. - * - * This option is only useful if both POLARSSL_SHA256_C and - * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. - */ -//#define POLARSSL_ENTROPY_FORCE_SHA256 - -/** - * \def POLARSSL_MEMORY_DEBUG - * - * Enable debugging of buffer allocator memory issues. Automatically prints - * (to stderr) all (fatal) messages on memory allocation issues. Enables - * function for 'debug output' of allocated memory. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Uncomment this macro to let the buffer allocator print out error messages. - */ -//#define POLARSSL_MEMORY_DEBUG - -/** - * \def POLARSSL_MEMORY_BACKTRACE - * - * Include backtrace information with each allocated block. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * GLIBC-compatible backtrace() an backtrace_symbols() support - * - * Uncomment this macro to include backtrace information - */ -//#define POLARSSL_MEMORY_BACKTRACE - -/** - * \def POLARSSL_PKCS1_V15 - * - * Enable support for PKCS#1 v1.5 encoding. - * - * Requires: POLARSSL_RSA_C - * - * This enables support for PKCS#1 v1.5 operations. - */ -#define POLARSSL_PKCS1_V15 - -/** - * \def POLARSSL_PKCS1_V21 - * - * Enable support for PKCS#1 v2.1 encoding. - * - * Requires: POLARSSL_MD_C, POLARSSL_RSA_C - * - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -#define POLARSSL_PKCS1_V21 - -/** - * \def POLARSSL_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * - */ -//#define POLARSSL_RSA_NO_CRT - -/** - * \def POLARSSL_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -// JY changed -#if defined(ENABLE_TESTING) && !defined(POLARSSL_SELF_TEST) -#define POLARSSL_SELF_TEST -#endif - -/** - * \def POLARSSL_SSL_ALL_ALERT_MESSAGES - * - * Enable sending of alert messages in case of encountered errors as per RFC. - * If you choose not to send the alert messages, PolarSSL can still communicate - * with other servers, only debugging of failures is harder. - * - * The advantage of not sending alert messages, is that no information is given - * about reasons for failures thus preventing adversaries of gaining intel. - * - * Enable sending of all alert messages - */ -#define POLARSSL_SSL_ALERT_MESSAGES - -/** - * \def POLARSSL_SSL_DEBUG_ALL - * - * Enable the debug messages in SSL module for all issues. - * Debug messages have been disabled in some places to prevent timing - * attacks due to (unbalanced) debugging function calls. - * - * If you need all error reporting you should enable this during debugging, - * but remove this for production servers that should log as well. - * - * Uncomment this macro to report all debug messages on errors introducing - * a timing side-channel. - * - */ -//#define POLARSSL_SSL_DEBUG_ALL - -/** - * \def POLARSSL_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * Uncomment this macro to enable hooking functions. - */ -//#define POLARSSL_SSL_HW_RECORD_ACCEL - -/** - * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (POLARSSL_SSL_SRV_C). - * - * Comment this macro to disable support for SSLv2 Client Hello messages. - */ -// JY removed -//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - -/** - * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - * - * Pick the ciphersuite according to the client's preferences rather than ours - * in the SSL Server module (POLARSSL_SSL_SRV_C). - * - * Uncomment this macro to respect client's ciphersuite order - */ -//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - -/** - * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH - * - * Enable support for RFC 6066 max_fragment_length extension in SSL. - * - * Comment this macro to disable support for the max_fragment_length extension - */ -#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH - -/** - * \def POLARSSL_SSL_PROTO_SSL3 - * - * Enable support for SSL 3.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for SSL 3.0 - */ -#define POLARSSL_SSL_PROTO_SSL3 - -/** - * \def POLARSSL_SSL_PROTO_TLS1 - * - * Enable support for TLS 1.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.0 - */ -#define POLARSSL_SSL_PROTO_TLS1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_1 - * - * Enable support for TLS 1.1. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.1 - */ -#define POLARSSL_SSL_PROTO_TLS1_1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_2 - * - * Enable support for TLS 1.2. - * - * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C - * (Depends on ciphersuites) - * - * Comment this macro to disable support for TLS 1.2 - */ -#define POLARSSL_SSL_PROTO_TLS1_2 - -/** - * \def POLARSSL_SSL_ALPN - * - * Enable support for Application Layer Protocol Negotiation. - * draft-ietf-tls-applayerprotoneg-05 - * - * Comment this macro to disable support for ALPN. - */ -#define POLARSSL_SSL_ALPN - -/** - * \def POLARSSL_SSL_SESSION_TICKETS - * - * Enable support for RFC 5077 session tickets in SSL. - * - * Requires: POLARSSL_AES_C - * POLARSSL_SHA256_C - * POLARSSL_CIPHER_MODE_CBC - * - * Comment this macro to disable support for SSL session tickets - */ -// JY removed -//#define POLARSSL_SSL_SESSION_TICKETS - -/** - * \def POLARSSL_SSL_SERVER_NAME_INDICATION - * - * Enable support for RFC 6066 server name indication (SNI) in SSL. - * - * Comment this macro to disable support for server name indication in SSL - */ -#define POLARSSL_SSL_SERVER_NAME_INDICATION - -/** - * \def POLARSSL_SSL_TRUNCATED_HMAC - * - * Enable support for RFC 6066 truncated HMAC in SSL. - * - * Comment this macro to disable support for truncated HMAC in SSL - */ -#define POLARSSL_SSL_TRUNCATED_HMAC - -/** - * \def POLARSSL_SSL_SET_CURVES - * - * Enable ssl_set_curves(). - * - * This is disabled by default since it breaks binary compatibility with the - * 1.3.x line. If you choose to enable it, you will need to rebuild your - * application against the new header files, relinking will not be enough. - * It will be enabled by default, or no longer an option, in the 1.4 branch. - * - * Uncomment to make ssl_set_curves() available. - */ -//#define POLARSSL_SSL_SET_CURVES - -/** - * \def POLARSSL_THREADING_ALT - * - * Provide your own alternate threading implementation. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to allow your own alternate threading implementation. - */ -//#define POLARSSL_THREADING_ALT - -/** - * \def POLARSSL_THREADING_PTHREAD - * - * Enable the pthread wrapper layer for the threading layer. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to enable pthread mutexes. - */ -//#define POLARSSL_THREADING_PTHREAD - -/** - * \def POLARSSL_VERSION_FEATURES - * - * Allow run-time checking of compile-time enabled features. Thus allowing users - * to check at run-time if the library is for instance compiled with threading - * support via version_check_feature(). - * - * Requires: POLARSSL_VERSION_C - * - * Comment this to disable run-time checking and save ROM space - */ -#define POLARSSL_VERSION_FEATURES - -/** - * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an extension in a v1 or v2 certificate. - * - * Uncomment to prevent an error. - */ -// JY Added -#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - -/** - * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * Uncomment to prevent an error. - */ -// JY Added -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - -/** - * \def POLARSSL_X509_CHECK_KEY_USAGE - * - * Enable verification of the keyUsage extension (CA and leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused - * (intermediate) CA and leaf certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip keyUsage checking for both CA and leaf certificates. - */ -#define POLARSSL_X509_CHECK_KEY_USAGE - -/** - * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - * - * Enable verification of the extendedKeyUsage extension (leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip extendedKeyUsage checking for certificates. - */ -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - -/** - * \def POLARSSL_X509_RSASSA_PSS_SUPPORT - * - * Enable parsing and verification of X.509 certificates, CRLs and CSRS - * signed with RSASSA-PSS (aka PKCS#1 v2.1). - * - * Comment this macro to disallow using RSASSA-PSS in certificates. - */ -#define POLARSSL_X509_RSASSA_PSS_SUPPORT - -/** - * \def POLARSSL_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * \warning TLS-level compression MAY REDUCE SECURITY! See for example the - * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be a applicable to your use case. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB - */ -//#define POLARSSL_ZLIB_SUPPORT -/* \} name SECTION: PolarSSL feature support */ - -/** - * \name SECTION: PolarSSL modules - * - * This section enables or disables entire modules in PolarSSL - * \{ - */ - -/** - * \def POLARSSL_AESNI_C - * - * Enable AES-NI support on x86-64. - * - * Module: library/aesni.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the AES-NI instructions on x86-64 - */ -// JY added -#ifndef POLARSSL_AES_ALT -#define POLARSSL_AESNI_C -#endif - -/** - * \def POLARSSL_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * - * PEM_PARSE uses AES for decrypting encrypted keys. - */ -#define POLARSSL_AES_C - -/** - * \def POLARSSL_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - * TLS_RSA_PSK_WITH_RC4_128_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -// JY removed -- crypto -//#define POLARSSL_ARC4_C - -/** - * \def POLARSSL_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509.c - * library/dhm.c - * library/pkcs12.c - * library/pkcs5.c - * library/pkparse.c - */ -#define POLARSSL_ASN1_PARSE_C - -/** - * \def POLARSSL_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - * Caller: library/ecdsa.c - * library/pkwrite.c - * library/x509_create.c - * library/x509write_crt.c - * library/x509write_csr.c - */ -#define POLARSSL_ASN1_WRITE_C - -/** - * \def POLARSSL_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -#define POLARSSL_BASE64_C - -/** - * \def POLARSSL_BIGNUM_C - * - * Enable the multi-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/ecp.c - * library/ecdsa.c - * library/rsa.c - * library/ssl_tls.c - * - * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. - */ -#define POLARSSL_BIGNUM_C - -/** - * \def POLARSSL_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define POLARSSL_BLOWFISH_C - -/** - * \def POLARSSL_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - */ -// JY removed -- crypto -//#define POLARSSL_CAMELLIA_C - -/** - * \def POLARSSL_CCM_C - * - * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. - * - * Module: library/ccm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-CCM ciphersuites, if other requisites are - * enabled as well. - */ -#define POLARSSL_CCM_C - -/** - * \def POLARSSL_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * Requires: POLARSSL_PEM_PARSE_C - * - * This module is used for testing (ssl_client/server). - */ -// JY changed -#ifdef ENABLE_TESTING -#define POLARSSL_CERTS_C -#endif - -/** - * \def POLARSSL_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: library/ssl_tls.c - * - * Uncomment to enable generic cipher wrappers. - */ -#define POLARSSL_CIPHER_C - -/** - * \def POLARSSL_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator. - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: POLARSSL_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -// JY added -#ifndef EXTERNAL_RNG -#define POLARSSL_CTR_DRBG_C -#endif - -/** - * \def POLARSSL_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define POLARSSL_DEBUG_C - -/** - * \def POLARSSL_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/pem.c - * library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * - * PEM_PARSE uses DES/3DES for decrypting encrypted keys. - */ -#define POLARSSL_DES_C - -/** - * \def POLARSSL_DHM_C - * - * Enable the Diffie-Hellman-Merkle module. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * DHE-RSA, DHE-PSK - */ -#define POLARSSL_DHM_C - -/** - * \def POLARSSL_ECDH_C - * - * Enable the elliptic curve Diffie-Hellman library. - * - * Module: library/ecdh.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK - * - * Requires: POLARSSL_ECP_C - */ -#define POLARSSL_ECDH_C - -/** - * \def POLARSSL_ECDSA_C - * - * Enable the elliptic curve DSA library. - * - * Module: library/ecdsa.c - * Caller: - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA - * - * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C - */ -#define POLARSSL_ECDSA_C - -/** - * \def POLARSSL_ECP_C - * - * Enable the elliptic curve over GF(p) library. - * - * Module: library/ecp.c - * Caller: library/ecdh.c - * library/ecdsa.c - * - * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED - */ -#define POLARSSL_ECP_C - -/** - * \def POLARSSL_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C - * - * This module provides a generic entropy pool - */ -#define POLARSSL_ENTROPY_C - -/** - * \def POLARSSL_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables polarssl_strerror(). - */ -#define POLARSSL_ERROR_C - -/** - * \def POLARSSL_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES. - * - * Module: library/gcm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other - * requisites are enabled as well. - */ -#define POLARSSL_GCM_C - -/** - * \def POLARSSL_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments - * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. - * - * Module: library/havege.c - * Caller: - * - * Requires: POLARSSL_TIMING_C - * - * Uncomment to enable the HAVEGE random generator. - */ -//#define POLARSSL_HAVEGE_C - -/** - * \def POLARSSL_HMAC_DRBG_C - * - * Enable the HMAC_DRBG random generator. - * - * Module: library/hmac_drbg.c - * Caller: - * - * Requires: POLARSSL_MD_C - * - * Uncomment to enable the HMAC_DRBG random number geerator. - */ -#define POLARSSL_HMAC_DRBG_C - -/** - * \def POLARSSL_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define POLARSSL_MD_C - -/** - * \def POLARSSL_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - */ -//#define POLARSSL_MD2_C - -/** - * \def POLARSSL_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - */ -// JY Added for NTLM proxy auth -#define POLARSSL_MD4_C - -/** - * \def POLARSSL_MD5_C - * - * Enable the MD5 hash algorithm. - * - * Module: library/md5.c - * Caller: library/md.c - * library/pem.c - * library/ssl_tls.c - * - * This module is required for SSL/TLS and X.509. - * PEM_PARSE uses MD5 for decrypting encrypted keys. - */ -#define POLARSSL_MD5_C - -/** - * \def POLARSSL_MEMORY_C - * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. - */ -//#define POLARSSL_MEMORY_C - -/** - * \def POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Enable the buffer allocator implementation that makes use of a (stack) - * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() - * calls) - * - * Module: library/memory_buffer_alloc.c - * - * Requires: POLARSSL_PLATFORM_C - * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) - * - * Enable this module to enable the buffer memory allocator. - */ -//#define POLARSSL_MEMORY_BUFFER_ALLOC_C - -/** - * \def POLARSSL_NET_C - * - * Enable the TCP/IP networking routines. - * - * Module: library/net.c - * - * This module provides TCP/IP networking routines. - */ -// JY removed -//#define POLARSSL_NET_C - -/** - * \def POLARSSL_OID_C - * - * Enable the OID database. - * - * Module: library/oid.c - * Caller: library/asn1write.c - * library/pkcs5.c - * library/pkparse.c - * library/pkwrite.c - * library/rsa.c - * library/x509.c - * library/x509_create.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * This modules translates between OIDs and internal values. - */ -#define POLARSSL_OID_C - -/** - * \def POLARSSL_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the VIA PadLock on x86. - */ -// JY removed -//#define POLARSSL_PADLOCK_C - -/** - * \def POLARSSL_PBKDF2_C - * - * Enable PKCS#5 PBKDF2 key derivation function. - * DEPRECATED: Use POLARSSL_PKCS5_C instead - * - * Module: library/pbkdf2.c - * - * Requires: POLARSSL_PKCS5_C - * - * This module adds support for the PKCS#5 PBKDF2 key derivation function. - */ -#define POLARSSL_PBKDF2_C - -/** - * \def POLARSSL_PEM_PARSE_C - * - * Enable PEM decoding / parsing. - * - * Module: library/pem.c - * Caller: library/dhm.c - * library/pkparse.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for decoding / parsing PEM files. - */ -#define POLARSSL_PEM_PARSE_C - -/** - * \def POLARSSL_PEM_WRITE_C - * - * Enable PEM encoding / writing. - * - * Module: library/pem.c - * Caller: library/pkwrite.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for encoding / writing PEM files. - */ -#define POLARSSL_PEM_WRITE_C - -/** - * \def POLARSSL_PK_C - * - * Enable the generic public (asymetric) key layer. - * - * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C - * - * Uncomment to enable generic public key wrappers. - */ -#define POLARSSL_PK_C - -/** - * \def POLARSSL_PK_PARSE_C - * - * Enable the generic public (asymetric) key parser. - * - * Module: library/pkparse.c - * Caller: library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key parse functions. - */ -#define POLARSSL_PK_PARSE_C - -/** - * \def POLARSSL_PK_WRITE_C - * - * Enable the generic public (asymetric) key writer. - * - * Module: library/pkwrite.c - * Caller: library/x509write.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key write functions. - */ -// JY removed -- PKI -//#define POLARSSL_PK_WRITE_C - -/** - * \def POLARSSL_PKCS5_C - * - * Enable PKCS#5 functions. - * - * Module: library/pkcs5.c - * - * Requires: POLARSSL_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define POLARSSL_PKCS5_C - -/** - * \def POLARSSL_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support. - * - * Module: library/pkcs11.c - * Caller: library/pk.c - * - * Requires: POLARSSL_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) - */ -//#define POLARSSL_PKCS11_C - -/** - * \def POLARSSL_PKCS12_C - * - * Enable PKCS#12 PBE functions. - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/pkparse.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C - * Can use: POLARSSL_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define POLARSSL_PKCS12_C - -/** - * \def POLARSSL_PLATFORM_C - * - * Enable the platform abstraction layer that allows you to re-assign - * functions like malloc(), free(), printf(), fprintf() - * - * Module: library/platform.c - * Caller: Most other .c files - * - * This module enables abstraction of common (libc) functions. - */ -#define POLARSSL_PLATFORM_C - -/** - * \def POLARSSL_RIPEMD160_C - * - * Enable the RIPEMD-160 hash algorithm. - * - * Module: library/ripemd160.c - * Caller: library/md.c - * - */ -// JY removed -//#define POLARSSL_RIPEMD160_C - -/** - * \def POLARSSL_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is used by the following key exchanges: - * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C - */ -#define POLARSSL_RSA_C - -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/** - * \def POLARSSL_SHA256_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA2_C) - * - * Module: library/sha256.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define POLARSSL_SHA256_C - -/** - * \def POLARSSL_SHA512_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA4_C) - * - * Module: library/sha512.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA512_C - -/** - * \def POLARSSL_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: POLARSSL_SSL_CACHE_C - */ -// JY removed -//#define POLARSSL_SSL_CACHE_C - -/** - * \def POLARSSL_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/** - * \def POLARSSL_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -// JY removed -- server -//#define POLARSSL_SSL_SRV_C - -/** - * \def POLARSSL_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C - * and at least one of the POLARSSL_SSL_PROTO_* defines - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/** - * \def POLARSSL_THREADING_C - * - * Enable the threading abstraction layer. - * By default PolarSSL assumes it is used in a non-threaded environment or that - * contexts are not shared between threads. If you do intend to use contexts - * between threads, you will need to enable this layer to prevent race - * conditions. - * - * Module: library/threading.c - * - * This allows different threading implementations (self-implemented or - * provided). - * - * You will have to enable either POLARSSL_THREADING_ALT or - * POLARSSL_THREADING_PTHREAD. - * - * Enable this layer to allow use of mutexes within PolarSSL - */ -//#define POLARSSL_THREADING_C - -/** - * \def POLARSSL_TIMING_C - * - * Enable the portable timing interface. - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -// JY removed -//#define POLARSSL_TIMING_C - -/** - * \def POLARSSL_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define POLARSSL_VERSION_C - -/** - * \def POLARSSL_X509_USE_C - * - * Enable X.509 core for using certificates. - * - * Module: library/x509.c - * Caller: library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, - * POLARSSL_PK_PARSE_C - * - * This module is required for the X.509 parsing modules. - */ -#define POLARSSL_X509_USE_C - -/** - * \def POLARSSL_X509_CRT_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_CRT_PARSE_C - -/** - * \def POLARSSL_X509_CRL_PARSE_C - * - * Enable X.509 CRL parsing. - * - * Module: library/x509_crl.c - * Caller: library/x509_crt.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 CRL parsing. - */ -#define POLARSSL_X509_CRL_PARSE_C - -/** - * \def POLARSSL_X509_CSR_PARSE_C - * - * Enable X.509 Certificate Signing Request (CSR) parsing. - * - * Module: library/x509_csr.c - * Caller: library/x509_crt_write.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is used for reading X.509 certificate request. - */ -// JY removed -- PKI -//#define POLARSSL_X509_CSR_PARSE_C - -/** - * \def POLARSSL_X509_CREATE_C - * - * Enable X.509 core for creating certificates. - * - * Module: library/x509_create.c - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C - * - * This module is the basis for creating X.509 certificates and CSRs. - */ -// JY removed -- PKI -//#define POLARSSL_X509_CREATE_C - -/** - * \def POLARSSL_X509_CRT_WRITE_C - * - * Enable creating X.509 certificates. - * - * Module: library/x509_crt_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate creation. - */ -// JY removed -- PKI -//#define POLARSSL_X509_CRT_WRITE_C - -/** - * \def POLARSSL_X509_CSR_WRITE_C - * - * Enable creating X.509 Certificate Signing Requests (CSR). - * - * Module: library/x509_csr_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate request writing. - */ -// JY removed -- PKI -//#define POLARSSL_X509_CSR_WRITE_C - -/** - * \def POLARSSL_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -// JY removed -- crypto -//#define POLARSSL_XTEA_C - -/* \} name SECTION: PolarSSL modules */ - -/** - * \name SECTION: Module configuration options - * - * This section allows for the setting of module specific sizes and - * configuration options. The default values are already present in the - * relevant header files and should suffice for the regular use cases. - * - * Our advice is to enable options and change their values here - * only if you have a good reason and know the consequences. - * - * Please check the respective header file for documentation on these - * parameters (to prevent duplicate documentation). - * \{ - */ - -/* MPI / BIGNUM options */ -//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -//#define POLARSSL_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ - -/* CTR_DRBG options */ -//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* HMAC_DRBG options */ -//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* ECP options */ -//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ - -/* Entropy options */ -//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ - -/* Memory buffer allocator options */ -//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ - -/* Platform options */ -//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ - -/* SSL Cache options */ -//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ -//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ - -/* SSL options */ -//#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ -//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ - -/** - * Complete list of ciphersuites to use, in order of preference. - * - * \warning No dependency checking is done on that field! This option can only - * be used to restrict the set of available ciphersuites. It is your - * responsibility to make sure the needed modules are active. - * - * Use this to save a few hundred bytes of ROM (default ordering of all - * available ciphersuites) and a few to a few hundred bytes of RAM. - * - * The value below is only an example, not the default. - */ -//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - -/* Debug options */ -//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ - -/* \} name SECTION: Module configuration options */ - -#include "check_config.h" - -#endif /* POLARSSL_CONFIG_H */ diff --git a/Sources/OpenVPN3/deps/polarssl/config.h.orig b/Sources/OpenVPN3/deps/polarssl/config.h.orig deleted file mode 100644 index 50b4e33..0000000 --- a/Sources/OpenVPN3/deps/polarssl/config.h.orig +++ /dev/null @@ -1,2180 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def POLARSSL_HAVE_INT8 - * - * The system uses 8-bit wide native integers. - * - * Uncomment if native integers are 8-bit wide. - */ -//#define POLARSSL_HAVE_INT8 - -/** - * \def POLARSSL_HAVE_INT16 - * - * The system uses 16-bit wide native integers. - * - * Uncomment if native integers are 16-bit wide. - */ -//#define POLARSSL_HAVE_INT16 - -/** - * \def POLARSSL_HAVE_LONGLONG - * - * The compiler supports the 'long long' type. - * (Only used on 32-bit platforms) - */ -#define POLARSSL_HAVE_LONGLONG - -/** - * \def POLARSSL_HAVE_ASM - * - * The compiler has support for asm(). - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - * Comment to disable the use of assembly code. - */ -#define POLARSSL_HAVE_ASM - -/** - * \def POLARSSL_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - */ -//#define POLARSSL_HAVE_SSE2 - -/** - * \def POLARSSL_HAVE_TIME - * - * System has time.h and time() / localtime() / gettimeofday(). - * - * Comment if your system does not support time functions - */ -#define POLARSSL_HAVE_TIME - -/** - * \def POLARSSL_HAVE_IPV6 - * - * System supports the basic socket interface for IPv6 (RFC 3493), - * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. - * - * Note: on Windows/MingW, XP or higher is required. - * - * Comment if your system does not support the IPv6 socket interface - */ -#define POLARSSL_HAVE_IPV6 - -/** - * \def POLARSSL_PLATFORM_MEMORY - * - * Enable the memory allocation layer. - * - * By default PolarSSL uses the system-provided malloc() and free(). - * This allows different allocators (self-implemented or provided) to be - * provided to the platform abstraction layer. - * - * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()" - * to allow you to set an alternative malloc() and free() function pointer. - * - * Requires: POLARSSL_PLATFORM_C - * - * Enable this layer to allow use of alternative memory allocators. - */ -//#define POLARSSL_PLATFORM_MEMORY - -/** - * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS - * - * Do not assign standard functions in the platform layer (e.g. malloc() to - * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) - * - * This makes sure there are no linking errors on platforms that do not support - * these functions. You will HAVE to provide alternatives, either at runtime - * via the platform_set_xxx() functions or at compile time by setting - * the POLARSSL_PLATFORM_STD_XXX defines. - * - * Requires: POLARSSL_PLATFORM_C - * - * Uncomment to prevent default assignment of standard functions in the - * platform layer. - */ -//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS - -/** - * \def POLARSSL_PLATFORM_XXX_ALT - * - * Uncomment a macro to let PolarSSL support the function in the platform - * abstraction layer. - * - * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will - * provide a function "platform_set_printf()" that allows you to set an - * alternative printf function pointer. - * - * All these define require POLARSSL_PLATFORM_C to be defined! - * - * Uncomment a macro to enable alternate implementation of specific base - * platform function - */ -//#define POLARSSL_PLATFORM_PRINTF_ALT -//#define POLARSSL_PLATFORM_FPRINTF_ALT -/* \} name SECTION: System support */ - -/** - * \name SECTION: PolarSSL feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def POLARSSL_TIMING_ALT - * - * Uncomment to provide your own alternate implementation for hardclock(), - * get_timer(), set_alarm() and m_sleep(). - * - * Only works if you have POLARSSL_TIMING_C enabled. - * - * You will need to provide a header "timing_alt.h" and an implementation at - * compile time. - */ -//#define POLARSSL_TIMING_ALT - -/** - * \def POLARSSL_XXX_ALT - * - * Uncomment a macro to let PolarSSL use your alternate core implementation of - * a symmetric or hash algorithm (e.g. platform specific assembly optimized - * implementations). Keep in mind that the function prototypes should remain - * the same. - * - * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer - * provide the "struct aes_context" definition and omit the base function - * declarations and implementations. "aes_alt.h" will be included from - * "aes.h" to include the new function definitions. - * - * Uncomment a macro to enable alternate implementation for core algorithm - * functions - */ -//#define POLARSSL_AES_ALT -//#define POLARSSL_ARC4_ALT -//#define POLARSSL_BLOWFISH_ALT -//#define POLARSSL_CAMELLIA_ALT -//#define POLARSSL_DES_ALT -//#define POLARSSL_XTEA_ALT -//#define POLARSSL_MD2_ALT -//#define POLARSSL_MD4_ALT -//#define POLARSSL_MD5_ALT -//#define POLARSSL_RIPEMD160_ALT -//#define POLARSSL_SHA1_ALT -//#define POLARSSL_SHA256_ALT -//#define POLARSSL_SHA512_ALT - -/** - * \def POLARSSL_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - * - */ -//#define POLARSSL_AES_ROM_TABLES - -/** - * \def POLARSSL_CIPHER_MODE_CBC - * - * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CBC - -/** - * \def POLARSSL_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CFB - -/** - * \def POLARSSL_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CTR - -/** - * \def POLARSSL_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * TLS_ECDH_ECDSA_WITH_NULL_SHA - * TLS_ECDH_RSA_WITH_NULL_SHA - * TLS_ECDHE_ECDSA_WITH_NULL_SHA - * TLS_ECDHE_RSA_WITH_NULL_SHA - * TLS_ECDHE_PSK_WITH_NULL_SHA384 - * TLS_ECDHE_PSK_WITH_NULL_SHA256 - * TLS_ECDHE_PSK_WITH_NULL_SHA - * TLS_DHE_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_NULL_SHA256 - * TLS_DHE_PSK_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_SHA256 - * TLS_RSA_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_MD5 - * TLS_RSA_PSK_WITH_NULL_SHA384 - * TLS_RSA_PSK_WITH_NULL_SHA256 - * TLS_RSA_PSK_WITH_NULL_SHA - * TLS_PSK_WITH_NULL_SHA384 - * TLS_PSK_WITH_NULL_SHA256 - * TLS_PSK_WITH_NULL_SHA - * - * Uncomment this macro to enable the NULL cipher and ciphersuites - */ -//#define POLARSSL_CIPHER_NULL_CIPHER - -/** - * \def POLARSSL_CIPHER_PADDING_XXX - * - * Uncomment or comment macros to add support for specific padding modes - * in the cipher layer with cipher modes that support padding (e.g. CBC) - * - * If you disable all padding modes, only full blocks can be used with CBC. - * - * Enable padding modes in the cipher layer. - */ -#define POLARSSL_CIPHER_PADDING_PKCS7 -#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS -#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN -#define POLARSSL_CIPHER_PADDING_ZEROS - -/** - * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS. - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * TLS_RSA_WITH_DES_CBC_SHA - * TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites - */ -//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES - -/** - * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES - * - * Remove RC4 ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on RC4 from the default list as - * returned by ssl_list_ciphersuites(). However, it is still possible to - * enable (some of) them with ssl_set_ciphersuites() by including them - * explicitly. - * - * Uncomment this macro to remove RC4 ciphersuites by default. - */ -//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES - -/** - * \def POLARSSL_ECP_XXXX_ENABLED - * - * Enables specific curves within the Elliptic Curve module. - * By default all supported curves are enabled. - * - * Comment macros to disable the curve and functions for it - */ -#define POLARSSL_ECP_DP_SECP192R1_ENABLED -#define POLARSSL_ECP_DP_SECP224R1_ENABLED -#define POLARSSL_ECP_DP_SECP256R1_ENABLED -#define POLARSSL_ECP_DP_SECP384R1_ENABLED -#define POLARSSL_ECP_DP_SECP521R1_ENABLED -#define POLARSSL_ECP_DP_SECP192K1_ENABLED -#define POLARSSL_ECP_DP_SECP224K1_ENABLED -#define POLARSSL_ECP_DP_SECP256K1_ENABLED -#define POLARSSL_ECP_DP_BP256R1_ENABLED -#define POLARSSL_ECP_DP_BP384R1_ENABLED -#define POLARSSL_ECP_DP_BP512R1_ENABLED -//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! -#define POLARSSL_ECP_DP_M255_ENABLED -//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! -//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! - -/** - * \def POLARSSL_ECP_NIST_OPTIM - * - * Enable specific 'modulo p' routines for each NIST prime. - * Depending on the prime and architecture, makes operations 4 to 8 times - * faster on the corresponding curve. - * - * Comment this macro to disable NIST curves optimisation. - */ -#define POLARSSL_ECP_NIST_OPTIM - -/** - * \def POLARSSL_ECDSA_DETERMINISTIC - * - * Enable deterministic ECDSA (RFC 6979). - * Standard ECDSA is "fragile" in the sense that lack of entropy when signing - * may result in a compromise of the long-term signing key. This is avoided by - * the deterministic variant. - * - * Requires: POLARSSL_HMAC_DRBG_C - * - * Comment this macro to disable deterministic ECDSA. - */ -#define POLARSSL_ECDSA_DETERMINISTIC - -/** - * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED - * - * Enable the PSK based ciphersuite modes in SSL / TLS. - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - * - * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - * - * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - * - * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED - * - * Enable the RSA-only based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - */ -#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - * - * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - */ -#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - * - * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - * - * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - * - * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - * - * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - -/** - * \def POLARSSL_PK_PARSE_EC_EXTENDED - * - * Enhance support for reading EC keys using variants of SEC1 not allowed by - * RFC 5915 and RFC 5480. - * - * Currently this means parsing the SpecifiedECDomain choice of EC - * parameters (only known groups are supported, not arbitrary domains, to - * avoid validation issues). - * - * Disable if you only need to support RFC 5915 + 5480 key formats. - */ -#define POLARSSL_PK_PARSE_EC_EXTENDED - -/** - * \def POLARSSL_ERROR_STRERROR_BC - * - * Make available the backward compatible error_strerror() next to the - * current polarssl_strerror(). - * - * For new code, it is recommended to use polarssl_strerror() instead and - * disable this. - * - * Disable if you run into name conflicts and want to really remove the - * error_strerror() - */ -#define POLARSSL_ERROR_STRERROR_BC - -/** - * \def POLARSSL_ERROR_STRERROR_DUMMY - * - * Enable a dummy error function to make use of polarssl_strerror() in - * third party libraries easier when POLARSSL_ERROR_C is disabled - * (no effect when POLARSSL_ERROR_C is enabled). - * - * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're - * not using polarssl_strerror() or error_strerror() in your application. - * - * Disable if you run into name conflicts and want to really remove the - * polarssl_strerror() - */ -#define POLARSSL_ERROR_STRERROR_DUMMY - -/** - * \def POLARSSL_GENPRIME - * - * Enable the prime-number generation code. - * - * Requires: POLARSSL_BIGNUM_C - */ -#define POLARSSL_GENPRIME - -/** - * \def POLARSSL_FS_IO - * - * Enable functions that use the filesystem. - */ -#define POLARSSL_FS_IO - -/** - * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. - */ -//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - -/** - * \def POLARSSL_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. - */ -//#define POLARSSL_NO_PLATFORM_ENTROPY - -/** - * \def POLARSSL_ENTROPY_FORCE_SHA256 - * - * Force the entropy accumulator to use a SHA-256 accumulator instead of the - * default SHA-512 based one (if both are available). - * - * Requires: POLARSSL_SHA256_C - * - * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option - * if you have performance concerns. - * - * This option is only useful if both POLARSSL_SHA256_C and - * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. - */ -//#define POLARSSL_ENTROPY_FORCE_SHA256 - -/** - * \def POLARSSL_MEMORY_DEBUG - * - * Enable debugging of buffer allocator memory issues. Automatically prints - * (to stderr) all (fatal) messages on memory allocation issues. Enables - * function for 'debug output' of allocated memory. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Uncomment this macro to let the buffer allocator print out error messages. - */ -//#define POLARSSL_MEMORY_DEBUG - -/** - * \def POLARSSL_MEMORY_BACKTRACE - * - * Include backtrace information with each allocated block. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * GLIBC-compatible backtrace() an backtrace_symbols() support - * - * Uncomment this macro to include backtrace information - */ -//#define POLARSSL_MEMORY_BACKTRACE - -/** - * \def POLARSSL_PKCS1_V15 - * - * Enable support for PKCS#1 v1.5 encoding. - * - * Requires: POLARSSL_RSA_C - * - * This enables support for PKCS#1 v1.5 operations. - */ -#define POLARSSL_PKCS1_V15 - -/** - * \def POLARSSL_PKCS1_V21 - * - * Enable support for PKCS#1 v2.1 encoding. - * - * Requires: POLARSSL_MD_C, POLARSSL_RSA_C - * - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -#define POLARSSL_PKCS1_V21 - -/** - * \def POLARSSL_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * - */ -//#define POLARSSL_RSA_NO_CRT - -/** - * \def POLARSSL_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -#define POLARSSL_SELF_TEST - -/** - * \def POLARSSL_SSL_ALL_ALERT_MESSAGES - * - * Enable sending of alert messages in case of encountered errors as per RFC. - * If you choose not to send the alert messages, PolarSSL can still communicate - * with other servers, only debugging of failures is harder. - * - * The advantage of not sending alert messages, is that no information is given - * about reasons for failures thus preventing adversaries of gaining intel. - * - * Enable sending of all alert messages - */ -#define POLARSSL_SSL_ALERT_MESSAGES - -/** - * \def POLARSSL_SSL_DEBUG_ALL - * - * Enable the debug messages in SSL module for all issues. - * Debug messages have been disabled in some places to prevent timing - * attacks due to (unbalanced) debugging function calls. - * - * If you need all error reporting you should enable this during debugging, - * but remove this for production servers that should log as well. - * - * Uncomment this macro to report all debug messages on errors introducing - * a timing side-channel. - * - */ -//#define POLARSSL_SSL_DEBUG_ALL - -/** - * \def POLARSSL_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * Uncomment this macro to enable hooking functions. - */ -//#define POLARSSL_SSL_HW_RECORD_ACCEL - -/** - * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (POLARSSL_SSL_SRV_C). - * - * Comment this macro to disable support for SSLv2 Client Hello messages. - */ -#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - -/** - * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - * - * Pick the ciphersuite according to the client's preferences rather than ours - * in the SSL Server module (POLARSSL_SSL_SRV_C). - * - * Uncomment this macro to respect client's ciphersuite order - */ -//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - -/** - * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH - * - * Enable support for RFC 6066 max_fragment_length extension in SSL. - * - * Comment this macro to disable support for the max_fragment_length extension - */ -#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH - -/** - * \def POLARSSL_SSL_PROTO_SSL3 - * - * Enable support for SSL 3.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for SSL 3.0 - */ -#define POLARSSL_SSL_PROTO_SSL3 - -/** - * \def POLARSSL_SSL_PROTO_TLS1 - * - * Enable support for TLS 1.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.0 - */ -#define POLARSSL_SSL_PROTO_TLS1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_1 - * - * Enable support for TLS 1.1. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.1 - */ -#define POLARSSL_SSL_PROTO_TLS1_1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_2 - * - * Enable support for TLS 1.2. - * - * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C - * (Depends on ciphersuites) - * - * Comment this macro to disable support for TLS 1.2 - */ -#define POLARSSL_SSL_PROTO_TLS1_2 - -/** - * \def POLARSSL_SSL_ALPN - * - * Enable support for Application Layer Protocol Negotiation. - * draft-ietf-tls-applayerprotoneg-05 - * - * Comment this macro to disable support for ALPN. - */ -#define POLARSSL_SSL_ALPN - -/** - * \def POLARSSL_SSL_SESSION_TICKETS - * - * Enable support for RFC 5077 session tickets in SSL. - * - * Requires: POLARSSL_AES_C - * POLARSSL_SHA256_C - * POLARSSL_CIPHER_MODE_CBC - * - * Comment this macro to disable support for SSL session tickets - */ -#define POLARSSL_SSL_SESSION_TICKETS - -/** - * \def POLARSSL_SSL_SERVER_NAME_INDICATION - * - * Enable support for RFC 6066 server name indication (SNI) in SSL. - * - * Comment this macro to disable support for server name indication in SSL - */ -#define POLARSSL_SSL_SERVER_NAME_INDICATION - -/** - * \def POLARSSL_SSL_TRUNCATED_HMAC - * - * Enable support for RFC 6066 truncated HMAC in SSL. - * - * Comment this macro to disable support for truncated HMAC in SSL - */ -#define POLARSSL_SSL_TRUNCATED_HMAC - -/** - * \def POLARSSL_SSL_SET_CURVES - * - * Enable ssl_set_curves(). - * - * This is disabled by default since it breaks binary compatibility with the - * 1.3.x line. If you choose to enable it, you will need to rebuild your - * application against the new header files, relinking will not be enough. - * It will be enabled by default, or no longer an option, in the 1.4 branch. - * - * Uncomment to make ssl_set_curves() available. - */ -//#define POLARSSL_SSL_SET_CURVES - -/** - * \def POLARSSL_THREADING_ALT - * - * Provide your own alternate threading implementation. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to allow your own alternate threading implementation. - */ -//#define POLARSSL_THREADING_ALT - -/** - * \def POLARSSL_THREADING_PTHREAD - * - * Enable the pthread wrapper layer for the threading layer. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to enable pthread mutexes. - */ -//#define POLARSSL_THREADING_PTHREAD - -/** - * \def POLARSSL_VERSION_FEATURES - * - * Allow run-time checking of compile-time enabled features. Thus allowing users - * to check at run-time if the library is for instance compiled with threading - * support via version_check_feature(). - * - * Requires: POLARSSL_VERSION_C - * - * Comment this to disable run-time checking and save ROM space - */ -#define POLARSSL_VERSION_FEATURES - -/** - * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an extension in a v1 or v2 certificate. - * - * Uncomment to prevent an error. - */ -//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - -/** - * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * Uncomment to prevent an error. - */ -//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - -/** - * \def POLARSSL_X509_CHECK_KEY_USAGE - * - * Enable verification of the keyUsage extension (CA and leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused - * (intermediate) CA and leaf certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip keyUsage checking for both CA and leaf certificates. - */ -#define POLARSSL_X509_CHECK_KEY_USAGE - -/** - * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - * - * Enable verification of the extendedKeyUsage extension (leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip extendedKeyUsage checking for certificates. - */ -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - -/** - * \def POLARSSL_X509_RSASSA_PSS_SUPPORT - * - * Enable parsing and verification of X.509 certificates, CRLs and CSRS - * signed with RSASSA-PSS (aka PKCS#1 v2.1). - * - * Comment this macro to disallow using RSASSA-PSS in certificates. - */ -#define POLARSSL_X509_RSASSA_PSS_SUPPORT - -/** - * \def POLARSSL_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * \warning TLS-level compression MAY REDUCE SECURITY! See for example the - * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be a applicable to your use case. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB - */ -//#define POLARSSL_ZLIB_SUPPORT -/* \} name SECTION: PolarSSL feature support */ - -/** - * \name SECTION: PolarSSL modules - * - * This section enables or disables entire modules in PolarSSL - * \{ - */ - -/** - * \def POLARSSL_AESNI_C - * - * Enable AES-NI support on x86-64. - * - * Module: library/aesni.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the AES-NI instructions on x86-64 - */ -#define POLARSSL_AESNI_C - -/** - * \def POLARSSL_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * - * PEM_PARSE uses AES for decrypting encrypted keys. - */ -#define POLARSSL_AES_C - -/** - * \def POLARSSL_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - * TLS_RSA_PSK_WITH_RC4_128_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_ARC4_C - -/** - * \def POLARSSL_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509.c - * library/dhm.c - * library/pkcs12.c - * library/pkcs5.c - * library/pkparse.c - */ -#define POLARSSL_ASN1_PARSE_C - -/** - * \def POLARSSL_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - * Caller: library/ecdsa.c - * library/pkwrite.c - * library/x509_create.c - * library/x509write_crt.c - * library/x509write_csr.c - */ -#define POLARSSL_ASN1_WRITE_C - -/** - * \def POLARSSL_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -#define POLARSSL_BASE64_C - -/** - * \def POLARSSL_BIGNUM_C - * - * Enable the multi-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/ecp.c - * library/ecdsa.c - * library/rsa.c - * library/ssl_tls.c - * - * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. - */ -#define POLARSSL_BIGNUM_C - -/** - * \def POLARSSL_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define POLARSSL_BLOWFISH_C - -/** - * \def POLARSSL_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - */ -#define POLARSSL_CAMELLIA_C - -/** - * \def POLARSSL_CCM_C - * - * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. - * - * Module: library/ccm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-CCM ciphersuites, if other requisites are - * enabled as well. - */ -#define POLARSSL_CCM_C - -/** - * \def POLARSSL_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * Requires: POLARSSL_PEM_PARSE_C - * - * This module is used for testing (ssl_client/server). - */ -#define POLARSSL_CERTS_C - -/** - * \def POLARSSL_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: library/ssl_tls.c - * - * Uncomment to enable generic cipher wrappers. - */ -#define POLARSSL_CIPHER_C - -/** - * \def POLARSSL_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator. - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: POLARSSL_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -#define POLARSSL_CTR_DRBG_C - -/** - * \def POLARSSL_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define POLARSSL_DEBUG_C - -/** - * \def POLARSSL_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/pem.c - * library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * - * PEM_PARSE uses DES/3DES for decrypting encrypted keys. - */ -#define POLARSSL_DES_C - -/** - * \def POLARSSL_DHM_C - * - * Enable the Diffie-Hellman-Merkle module. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * DHE-RSA, DHE-PSK - */ -#define POLARSSL_DHM_C - -/** - * \def POLARSSL_ECDH_C - * - * Enable the elliptic curve Diffie-Hellman library. - * - * Module: library/ecdh.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK - * - * Requires: POLARSSL_ECP_C - */ -#define POLARSSL_ECDH_C - -/** - * \def POLARSSL_ECDSA_C - * - * Enable the elliptic curve DSA library. - * - * Module: library/ecdsa.c - * Caller: - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA - * - * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C - */ -#define POLARSSL_ECDSA_C - -/** - * \def POLARSSL_ECP_C - * - * Enable the elliptic curve over GF(p) library. - * - * Module: library/ecp.c - * Caller: library/ecdh.c - * library/ecdsa.c - * - * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED - */ -#define POLARSSL_ECP_C - -/** - * \def POLARSSL_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C - * - * This module provides a generic entropy pool - */ -#define POLARSSL_ENTROPY_C - -/** - * \def POLARSSL_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables polarssl_strerror(). - */ -#define POLARSSL_ERROR_C - -/** - * \def POLARSSL_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES. - * - * Module: library/gcm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other - * requisites are enabled as well. - */ -#define POLARSSL_GCM_C - -/** - * \def POLARSSL_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments - * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. - * - * Module: library/havege.c - * Caller: - * - * Requires: POLARSSL_TIMING_C - * - * Uncomment to enable the HAVEGE random generator. - */ -//#define POLARSSL_HAVEGE_C - -/** - * \def POLARSSL_HMAC_DRBG_C - * - * Enable the HMAC_DRBG random generator. - * - * Module: library/hmac_drbg.c - * Caller: - * - * Requires: POLARSSL_MD_C - * - * Uncomment to enable the HMAC_DRBG random number geerator. - */ -#define POLARSSL_HMAC_DRBG_C - -/** - * \def POLARSSL_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define POLARSSL_MD_C - -/** - * \def POLARSSL_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - */ -//#define POLARSSL_MD2_C - -/** - * \def POLARSSL_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - */ -//#define POLARSSL_MD4_C - -/** - * \def POLARSSL_MD5_C - * - * Enable the MD5 hash algorithm. - * - * Module: library/md5.c - * Caller: library/md.c - * library/pem.c - * library/ssl_tls.c - * - * This module is required for SSL/TLS and X.509. - * PEM_PARSE uses MD5 for decrypting encrypted keys. - */ -#define POLARSSL_MD5_C - -/** - * \def POLARSSL_MEMORY_C - * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. - */ -//#define POLARSSL_MEMORY_C - -/** - * \def POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Enable the buffer allocator implementation that makes use of a (stack) - * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() - * calls) - * - * Module: library/memory_buffer_alloc.c - * - * Requires: POLARSSL_PLATFORM_C - * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) - * - * Enable this module to enable the buffer memory allocator. - */ -//#define POLARSSL_MEMORY_BUFFER_ALLOC_C - -/** - * \def POLARSSL_NET_C - * - * Enable the TCP/IP networking routines. - * - * Module: library/net.c - * - * This module provides TCP/IP networking routines. - */ -#define POLARSSL_NET_C - -/** - * \def POLARSSL_OID_C - * - * Enable the OID database. - * - * Module: library/oid.c - * Caller: library/asn1write.c - * library/pkcs5.c - * library/pkparse.c - * library/pkwrite.c - * library/rsa.c - * library/x509.c - * library/x509_create.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * This modules translates between OIDs and internal values. - */ -#define POLARSSL_OID_C - -/** - * \def POLARSSL_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the VIA PadLock on x86. - */ -#define POLARSSL_PADLOCK_C - -/** - * \def POLARSSL_PBKDF2_C - * - * Enable PKCS#5 PBKDF2 key derivation function. - * DEPRECATED: Use POLARSSL_PKCS5_C instead - * - * Module: library/pbkdf2.c - * - * Requires: POLARSSL_PKCS5_C - * - * This module adds support for the PKCS#5 PBKDF2 key derivation function. - */ -#define POLARSSL_PBKDF2_C - -/** - * \def POLARSSL_PEM_PARSE_C - * - * Enable PEM decoding / parsing. - * - * Module: library/pem.c - * Caller: library/dhm.c - * library/pkparse.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for decoding / parsing PEM files. - */ -#define POLARSSL_PEM_PARSE_C - -/** - * \def POLARSSL_PEM_WRITE_C - * - * Enable PEM encoding / writing. - * - * Module: library/pem.c - * Caller: library/pkwrite.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for encoding / writing PEM files. - */ -#define POLARSSL_PEM_WRITE_C - -/** - * \def POLARSSL_PK_C - * - * Enable the generic public (asymetric) key layer. - * - * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C - * - * Uncomment to enable generic public key wrappers. - */ -#define POLARSSL_PK_C - -/** - * \def POLARSSL_PK_PARSE_C - * - * Enable the generic public (asymetric) key parser. - * - * Module: library/pkparse.c - * Caller: library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key parse functions. - */ -#define POLARSSL_PK_PARSE_C - -/** - * \def POLARSSL_PK_WRITE_C - * - * Enable the generic public (asymetric) key writer. - * - * Module: library/pkwrite.c - * Caller: library/x509write.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key write functions. - */ -#define POLARSSL_PK_WRITE_C - -/** - * \def POLARSSL_PKCS5_C - * - * Enable PKCS#5 functions. - * - * Module: library/pkcs5.c - * - * Requires: POLARSSL_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define POLARSSL_PKCS5_C - -/** - * \def POLARSSL_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support. - * - * Module: library/pkcs11.c - * Caller: library/pk.c - * - * Requires: POLARSSL_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) - */ -//#define POLARSSL_PKCS11_C - -/** - * \def POLARSSL_PKCS12_C - * - * Enable PKCS#12 PBE functions. - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/pkparse.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C - * Can use: POLARSSL_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define POLARSSL_PKCS12_C - -/** - * \def POLARSSL_PLATFORM_C - * - * Enable the platform abstraction layer that allows you to re-assign - * functions like malloc(), free(), printf(), fprintf() - * - * Module: library/platform.c - * Caller: Most other .c files - * - * This module enables abstraction of common (libc) functions. - */ -#define POLARSSL_PLATFORM_C - -/** - * \def POLARSSL_RIPEMD160_C - * - * Enable the RIPEMD-160 hash algorithm. - * - * Module: library/ripemd160.c - * Caller: library/md.c - * - */ -#define POLARSSL_RIPEMD160_C - -/** - * \def POLARSSL_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is used by the following key exchanges: - * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C - */ -#define POLARSSL_RSA_C - -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/** - * \def POLARSSL_SHA256_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA2_C) - * - * Module: library/sha256.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define POLARSSL_SHA256_C - -/** - * \def POLARSSL_SHA512_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA4_C) - * - * Module: library/sha512.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA512_C - -/** - * \def POLARSSL_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: POLARSSL_SSL_CACHE_C - */ -#define POLARSSL_SSL_CACHE_C - -/** - * \def POLARSSL_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/** - * \def POLARSSL_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -#define POLARSSL_SSL_SRV_C - -/** - * \def POLARSSL_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C - * and at least one of the POLARSSL_SSL_PROTO_* defines - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/** - * \def POLARSSL_THREADING_C - * - * Enable the threading abstraction layer. - * By default PolarSSL assumes it is used in a non-threaded environment or that - * contexts are not shared between threads. If you do intend to use contexts - * between threads, you will need to enable this layer to prevent race - * conditions. - * - * Module: library/threading.c - * - * This allows different threading implementations (self-implemented or - * provided). - * - * You will have to enable either POLARSSL_THREADING_ALT or - * POLARSSL_THREADING_PTHREAD. - * - * Enable this layer to allow use of mutexes within PolarSSL - */ -//#define POLARSSL_THREADING_C - -/** - * \def POLARSSL_TIMING_C - * - * Enable the portable timing interface. - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -#define POLARSSL_TIMING_C - -/** - * \def POLARSSL_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define POLARSSL_VERSION_C - -/** - * \def POLARSSL_X509_USE_C - * - * Enable X.509 core for using certificates. - * - * Module: library/x509.c - * Caller: library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, - * POLARSSL_PK_PARSE_C - * - * This module is required for the X.509 parsing modules. - */ -#define POLARSSL_X509_USE_C - -/** - * \def POLARSSL_X509_CRT_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_CRT_PARSE_C - -/** - * \def POLARSSL_X509_CRL_PARSE_C - * - * Enable X.509 CRL parsing. - * - * Module: library/x509_crl.c - * Caller: library/x509_crt.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 CRL parsing. - */ -#define POLARSSL_X509_CRL_PARSE_C - -/** - * \def POLARSSL_X509_CSR_PARSE_C - * - * Enable X.509 Certificate Signing Request (CSR) parsing. - * - * Module: library/x509_csr.c - * Caller: library/x509_crt_write.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is used for reading X.509 certificate request. - */ -#define POLARSSL_X509_CSR_PARSE_C - -/** - * \def POLARSSL_X509_CREATE_C - * - * Enable X.509 core for creating certificates. - * - * Module: library/x509_create.c - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C - * - * This module is the basis for creating X.509 certificates and CSRs. - */ -#define POLARSSL_X509_CREATE_C - -/** - * \def POLARSSL_X509_CRT_WRITE_C - * - * Enable creating X.509 certificates. - * - * Module: library/x509_crt_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate creation. - */ -#define POLARSSL_X509_CRT_WRITE_C - -/** - * \def POLARSSL_X509_CSR_WRITE_C - * - * Enable creating X.509 Certificate Signing Requests (CSR). - * - * Module: library/x509_csr_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate request writing. - */ -#define POLARSSL_X509_CSR_WRITE_C - -/** - * \def POLARSSL_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#define POLARSSL_XTEA_C - -/* \} name SECTION: PolarSSL modules */ - -/** - * \name SECTION: Module configuration options - * - * This section allows for the setting of module specific sizes and - * configuration options. The default values are already present in the - * relevant header files and should suffice for the regular use cases. - * - * Our advice is to enable options and change their values here - * only if you have a good reason and know the consequences. - * - * Please check the respective header file for documentation on these - * parameters (to prevent duplicate documentation). - * \{ - */ - -/* MPI / BIGNUM options */ -//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -//#define POLARSSL_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ - -/* CTR_DRBG options */ -//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* HMAC_DRBG options */ -//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* ECP options */ -//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ - -/* Entropy options */ -//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ - -/* Memory buffer allocator options */ -//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ - -/* Platform options */ -//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ - -/* SSL Cache options */ -//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ -//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ - -/* SSL options */ -//#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ -//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ - -/** - * Complete list of ciphersuites to use, in order of preference. - * - * \warning No dependency checking is done on that field! This option can only - * be used to restrict the set of available ciphersuites. It is your - * responsibility to make sure the needed modules are active. - * - * Use this to save a few hundred bytes of ROM (default ordering of all - * available ciphersuites) and a few to a few hundred bytes of RAM. - * - * The value below is only an example, not the default. - */ -//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - -/* Debug options */ -//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ - -/* \} name SECTION: Module configuration options */ - -#include "check_config.h" - -#endif /* POLARSSL_CONFIG_H */ diff --git a/Sources/OpenVPN3/deps/polarssl/config12.h b/Sources/OpenVPN3/deps/polarssl/config12.h deleted file mode 100644 index 26fdf8b..0000000 --- a/Sources/OpenVPN3/deps/polarssl/config12.h +++ /dev/null @@ -1,959 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * Copyright (C) 2006-2012, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#include - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def POLARSSL_HAVE_INT8 - * - * The system uses 8-bit wide native integers. - * - * Uncomment if native integers are 8-bit wide. -#define POLARSSL_HAVE_INT8 - */ - -/** - * \def POLARSSL_HAVE_INT16 - * - * The system uses 16-bit wide native integers. - * - * Uncomment if native integers are 16-bit wide. -#define POLARSSL_HAVE_INT16 - */ - -/** - * \def POLARSSL_HAVE_LONGLONG - * - * The compiler supports the 'long long' type. - * (Only used on 32-bit platforms) - */ -#define POLARSSL_HAVE_LONGLONG - -/** - * \def POLARSSL_HAVE_ASM - * - * The compiler has support for asm() - * - * Uncomment to enable the use of assembly code. - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - */ -#define POLARSSL_HAVE_ASM - -/** - * \def POLARSSL_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - * -#define POLARSSL_HAVE_SSE2 - */ -/* \} name */ - -/** - * \name SECTION: PolarSSL feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def POLARSSL_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - * -#define POLARSSL_AES_ROM_TABLES - */ - -/** - * \def POLARSSL_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -// JY removed -//#define POLARSSL_CIPHER_MODE_CFB - -/** - * \def POLARSSL_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -// JY removed -//#define POLARSSL_CIPHER_MODE_CTR - -/** - * \def POLARSSL_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * TLS_RSA_WITH_NULL_MD5 - * TLS_RSA_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_SHA256 - * - * Uncomment this macro to enable the NULL cipher and ciphersuites -#define POLARSSL_CIPHER_NULL_CIPHER - */ - -/** - * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * TLS_RSA_WITH_DES_CBC_SHA - * TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites -#define POLARSSL_ENABLE_WEAK_CIPHERSUITES - */ - -/** - * \def POLARSSL_ERROR_STRERROR_DUMMY - * - * Enable a dummy error function to make use of error_strerror() in - * third party libraries easier. - * - * Disable if you run into name conflicts and want to really remove the - * error_strerror() - */ -#define POLARSSL_ERROR_STRERROR_DUMMY - -/** - * \def POLARSSL_GENPRIME - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * Enable the RSA prime-number generation code. - */ -#define POLARSSL_GENPRIME - -/** - * \def POLARSSL_FS_IO - * - * Enable functions that use the filesystem. - */ -// JY removed -//#define POLARSSL_FS_IO - -/** - * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - */ - -/** - * \def POLARSSL_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. -#define POLARSSL_NO_PLATFORM_ENTROPY - */ - -// JY added -#ifdef EXTERNAL_RNG -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES -#define POLARSSL_NO_PLATFORM_ENTROPY -#endif - -/** - * \def POLARSSL_PKCS1_V21 - * - * Requires: POLARSSL_MD_C, POLARSSL_RSA_C - * - * Enable support for PKCS#1 v2.1 encoding. - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -#define POLARSSL_PKCS1_V21 - -/** - * \def POLARSSL_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * -#define POLARSSL_RSA_NO_CRT - */ - -/** - * \def POLARSSL_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -// JY changed -#if defined(ENABLE_TESTING) && !defined(POLARSSL_SELF_TEST) -#define POLARSSL_SELF_TEST -#endif - -/** - * \def POLARSSL_SSL_ALL_ALERT_MESSAGES - * - * Enable sending of alert messages in case of encountered errors as per RFC. - * If you choose not to send the alert messages, PolarSSL can still communicate - * with other servers, only debugging of failures is harder. - * - * The advantage of not sending alert messages, is that no information is given - * about reasons for failures thus preventing adversaries of gaining intel. - * - * Enable sending of all alert messages - */ -#define POLARSSL_SSL_ALERT_MESSAGES - -/** - * \def POLARSSL_SSL_DEBUG_ALL - * - * Enable the debug messages in SSL module for all issues. - * Debug messages have been disabled in some places to prevent timing - * attacks due to (unbalanced) debugging function calls. - * - * If you need all error reporting you should enable this during debugging, - * but remove this for production servers that should log as well. - * - * Uncomment this macro to report all debug messages on errors introducing - * a timing side-channel. - * -#define POLARSSL_SSL_DEBUG_ALL - */ - -/** - * \def POLARSSL_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * Uncomment this macro to enable hooking functions. -#define POLARSSL_SSL_HW_RECORD_ACCEL - */ - -/** - * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (POLARSSL_SSL_SRV_C) - * - * Comment this macro to disable support for SSLv2 Client Hello messages. - */ -// JY removed -//#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - -/** - * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * Uncomment to prevent an error. - * -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - */ - -/** - * \def POLARSSL_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB -#define POLARSSL_ZLIB_SUPPORT - */ -/* \} name */ - -/** - * \name SECTION: PolarSSL modules - * - * This section enables or disables entire modules in PolarSSL - * \{ - */ - -/** - * \def POLARSSL_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * - * PEM uses AES for decrypting encrypted keys. - */ -#define POLARSSL_AES_C - -/** - * \def POLARSSL_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites: - * TLS_RSA_WITH_RC4_128_MD5 - * TLS_RSA_WITH_RC4_128_SHA - */ -// JY removed -//#define POLARSSL_ARC4_C - -/** - * \def POLARSSL_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509parse.c - */ -#define POLARSSL_ASN1_PARSE_C - -/** - * \def POLARSSL_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - */ -// JY removed -//#define POLARSSL_ASN1_WRITE_C - -/** - * \def POLARSSL_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -#define POLARSSL_BASE64_C - -/** - * \def POLARSSL_BIGNUM_C - * - * Enable the multi-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/rsa.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for RSA and DHM support. - */ -#define POLARSSL_BIGNUM_C - -/** - * \def POLARSSL_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define POLARSSL_BLOWFISH_C - -/** - * \def POLARSSL_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - */ -// JY removed -//#define POLARSSL_CAMELLIA_C - -/** - * \def POLARSSL_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * This module is used for testing (ssl_client/server). - */ -// JY changed -#ifdef ENABLE_TESTING -#define POLARSSL_CERTS_C -#endif - -/** - * \def POLARSSL_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: - * - * Uncomment to enable generic cipher wrappers. - */ -#define POLARSSL_CIPHER_C - -/** - * \def POLARSSL_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: POLARSSL_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -// JY added -#ifndef EXTERNAL_RNG -#define POLARSSL_CTR_DRBG_C -#endif - -/** - * \def POLARSSL_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define POLARSSL_DEBUG_C - -/** - * \def POLARSSL_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/pem.c - * library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * - * PEM uses DES/3DES for decrypting encrypted keys. - */ -#define POLARSSL_DES_C - -/** - * \def POLARSSL_DHM_C - * - * Enable the Diffie-Hellman-Merkle key exchange. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_RSA_WITH_DES_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - */ -#define POLARSSL_DHM_C - -/** - * \def POLARSSL_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: POLARSSL_SHA4_C - * - * This module provides a generic entropy pool - */ -#define POLARSSL_ENTROPY_C - -/** - * \def POLARSSL_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables err_strerror(). - */ -#define POLARSSL_ERROR_C - -/** - * \def POLARSSL_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES - * - * Module: library/gcm.c - * - * Requires: POLARSSL_AES_C - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_256_GCM_SHA384 - */ -#define POLARSSL_GCM_C - -/** - * \def POLARSSL_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Module: library/havege.c - * Caller: - * - * Requires: POLARSSL_TIMING_C - * - * This module enables the HAVEGE random number generator. - */ -// JY removed -//#define POLARSSL_HAVEGE_C - -/** - * \def POLARSSL_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define POLARSSL_MD_C - -/** - * \def POLARSSL_MD2_C - * - * Enable the MD2 hash algorithm - * - * Module: library/md2.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - * -#define POLARSSL_MD2_C - */ - -/** - * \def POLARSSL_MD4_C - * - * Enable the MD4 hash algorithm - * - * Module: library/md4.c - * Caller: library/x509parse.c - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - * - */ -// JY Added for NTLM proxy auth -#define POLARSSL_MD4_C - -/** - * \def POLARSSL_MD5_C - * - * Enable the MD5 hash algorithm - * - * Module: library/md5.c - * Caller: library/pem.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and X.509. - * PEM uses MD5 for decrypting encrypted keys. - */ -#define POLARSSL_MD5_C - -/** - * \def POLARSSL_NET_C - * - * Enable the TCP/IP networking routines. - * - * Module: library/net.c - * Caller: - * - * This module provides TCP/IP networking routines. - */ -// JY removed -//#define POLARSSL_NET_C - -/** - * \def POLARSSL_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * This modules adds support for the VIA PadLock on x86. - */ -// JY removed -//#define POLARSSL_PADLOCK_C - -/** - * \def POLARSSL_PBKDF2_C - * - * Enable PKCS#5 PBKDF2 key derivation function - * DEPRECATED: Use POLARSSL_PKCS5_C instead - * - * Module: library/pbkdf2.c - * - * Requires: POLARSSL_PKCS5_C - * - * This module adds support for the PKCS#5 PBKDF2 key derivation function. -#define POLARSSL_PBKDF2_C - */ - -/** - * \def POLARSSL_PEM_C - * - * Enable PEM decoding - * - * Module: library/pem.c - * Caller: library/x509parse.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for decoding PEM files. - */ -#define POLARSSL_PEM_C - -/** - * \def POLARSSL_PKCS5_C - * - * Enable PKCS#5 functions - * - * Module: library/pkcs5.c - * - * Requires: POLARSSL_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define POLARSSL_PKCS5_C - -/** - * \def POLARSSL_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support. - * - * Module: library/ssl_srv.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) -#define POLARSSL_PKCS11_C - */ - -/** - * \def POLARSSL_PKCS12_C - * - * Enable PKCS#12 PBE functions - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/x509parse.c - * - * Requires: POLARSSL_ASN1_PARSE_C - * Can use: POLARSSL_SHA1_C, POLARSSL_DES_C, POLARSSL_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define POLARSSL_PKCS12_C - -/** - * \def POLARSSL_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * Requires: POLARSSL_BIGNUM_C - * - * This module is required for SSL/TLS and MD5-signed certificates. - */ -#define POLARSSL_RSA_C - -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509parse.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/** - * \def POLARSSL_SHA2_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * - * Module: library/sha2.c - * Caller: library/md_wrap.c - * library/x509parse.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define POLARSSL_SHA2_C - -/** - * \def POLARSSL_SHA4_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * - * Module: library/sha4.c - * Caller: library/md_wrap.c - * library/x509parse.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA4_C - -/** - * \def POLARSSL_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: POLARSSL_SSL_CACHE_C - */ -// JY removed -//#define POLARSSL_SSL_CACHE_C - -/** - * \def POLARSSL_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/** - * \def POLARSSL_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -// JY removed -//#define POLARSSL_SSL_SRV_C - -/** - * \def POLARSSL_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_MD5_C, POLARSSL_SHA1_C, POLARSSL_X509_PARSE_C - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/** - * \def POLARSSL_TIMING_C - * - * Enable the portable timing interface. - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -// JY removed -//#define POLARSSL_TIMING_C - -/** - * \def POLARSSL_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define POLARSSL_VERSION_C - -/** - * \def POLARSSL_X509_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509parse.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_PARSE_C - -/** - * \def POLARSSL_X509_WRITE_C - * - * Enable X.509 buffer writing. - * - * Module: library/x509write.c - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_RSA_C - * - * This module is required for X.509 certificate request writing. - */ -// JY removed -//#define POLARSSL_X509_WRITE_C - -/** - * \def POLARSSL_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -// JY removed -//#define POLARSSL_XTEA_C -/* \} name */ - -// JY added -#define POLARSSL_BLOWFISH_NAME "BF" -#define POLARSSL_BLOWFISH_DEFAULT_KEY_LEN 128 - -#endif /* config.h */ diff --git a/Sources/OpenVPN3/deps/polarssl/crypto-alt.txt b/Sources/OpenVPN3/deps/polarssl/crypto-alt.txt deleted file mode 100644 index 32fb2e6..0000000 --- a/Sources/OpenVPN3/deps/polarssl/crypto-alt.txt +++ /dev/null @@ -1,16 +0,0 @@ -This patch (against PolarSSL 1.2.7) allows alternative crypto -implementations to be compiled, without actually defining -such implementations. - -* define POLARSSL_AES_ALT to include alternative AES implementation - from polarssl/aes_alt.h - -* define POLARSSL_SHA1_ALT to include alternative SHA1 implementation - from polarssl/sha1_alt.h - -* define POLARSSL_SHA2_ALT to include alternative SHA2 implementation - from polarssl/sha2_alt.h - -* define POLARSSL_SHA4_ALT to include alternative SHA4 implementation - from polarssl/sha4_alt.h - diff --git a/Sources/OpenVPN3/deps/polarssl/dhm.patch b/Sources/OpenVPN3/deps/polarssl/dhm.patch deleted file mode 100644 index 43732f2..0000000 --- a/Sources/OpenVPN3/deps/polarssl/dhm.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur polarssl-1.3.4/library/dhm.c polarssl.new/library/dhm.c ---- polarssl-1.3.4/library/dhm.c 2014-01-27 05:36:23.000000000 -0700 -+++ polarssl.new/library/dhm.c 2014-03-02 14:47:02.000000000 -0700 -@@ -32,6 +32,8 @@ - - #if defined(POLARSSL_DHM_C) - -+#include "polarssl/x509.h" // for POLARSSL_ERR_X509_FEATURE_UNAVAILABLE -+ - #include "polarssl/dhm.h" - - #if defined(POLARSSL_PEM_PARSE_C) diff --git a/Sources/OpenVPN3/deps/polarssl/entropy-printf.patch b/Sources/OpenVPN3/deps/polarssl/entropy-printf.patch deleted file mode 100644 index 9a5b288..0000000 --- a/Sources/OpenVPN3/deps/polarssl/entropy-printf.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -ur polarssl-1.3.8.orig/library/entropy.c polarssl-1.3.8/library/entropy.c ---- polarssl-1.3.8.orig/library/entropy.c 2014-07-09 03:34:48.000000000 -0600 -+++ polarssl-1.3.8/library/entropy.c 2014-07-09 16:27:06.000000000 -0600 -@@ -34,7 +34,7 @@ - #include "polarssl/entropy.h" - #include "polarssl/entropy_poll.h" - --#if defined(POLARSSL_FS_IO) -+#if defined(POLARSSL_FS_IO) || defined(POLARSSL_SELF_TEST) - #include - #endif - diff --git a/Sources/OpenVPN3/deps/polarssl/gitar b/Sources/OpenVPN3/deps/polarssl/gitar deleted file mode 100755 index d340407..0000000 --- a/Sources/OpenVPN3/deps/polarssl/gitar +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -. $O3/core/deps/lib-versions -rm -rf gitar.tmp -mkdir gitar.tmp -cd gitar.tmp -git clone https://github.com/polarssl/polarssl.git -b $POLARSSL_VERSION $POLARSSL_VERSION -tar cfz $DL/$POLARSSL_VERSION-gpl.tgz $POLARSSL_VERSION -cd .. -rm -rf gitar.tmp diff --git a/Sources/OpenVPN3/deps/polarssl/intel_cpu.c b/Sources/OpenVPN3/deps/polarssl/intel_cpu.c deleted file mode 100644 index fea1eda..0000000 --- a/Sources/OpenVPN3/deps/polarssl/intel_cpu.c +++ /dev/null @@ -1,22 +0,0 @@ -#if defined(_WIN32) -typedef unsigned __int64 IA32CAP; -#else -typedef unsigned long long IA32CAP; -#endif - -IA32CAP OPENSSL_ia32_cpuid(void); - -unsigned int OPENSSL_ia32cap_P[2]; // GLOBAL - -void OPENSSL_cpuid_setup(void) -{ - const IA32CAP vec = OPENSSL_ia32_cpuid(); - - /* - * |(1<<10) sets a reserved bit to signal that variable - * was initialized already... This is to avoid interference - * with cpuid snippets in ELF .init segment. - */ - OPENSSL_ia32cap_P[0] = (unsigned int)vec|(1<<10); - OPENSSL_ia32cap_P[1] = (unsigned int)(vec>>32); -} diff --git a/Sources/OpenVPN3/deps/polarssl/linux-arm.cmake b/Sources/OpenVPN3/deps/polarssl/linux-arm.cmake deleted file mode 100644 index a356912..0000000 --- a/Sources/OpenVPN3/deps/polarssl/linux-arm.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# this one is important -SET(CMAKE_SYSTEM_NAME Linux) -#this one not so much -SET(CMAKE_SYSTEM_VERSION 1) - -# specify the cross compiler -SET(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-4.6) -SET(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-4.6) - -# where is the target environment -#SET(CMAKE_FIND_ROOT_PATH /opt/eldk-2007-01-19/ppc_74xx /home/alex/eldk-ppc74xx-inst) - -# search for programs in the build host directories -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -# for libraries and headers in the target directories -SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/Sources/OpenVPN3/deps/polarssl/polar-openssl.patch b/Sources/OpenVPN3/deps/polarssl/polar-openssl.patch deleted file mode 100644 index 9601b14..0000000 --- a/Sources/OpenVPN3/deps/polarssl/polar-openssl.patch +++ /dev/null @@ -1,782 +0,0 @@ -diff -uNr polarssl-1.2.7/include/polarssl/aes.h polarssl.new/include/polarssl/aes.h ---- polarssl-1.2.7/include/polarssl/aes.h 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/include/polarssl/aes.h 2013-06-07 17:43:56.000000000 -0600 -@@ -29,6 +29,8 @@ - - #include - -+#include "config.h" -+ - #ifdef _MSC_VER - #include - typedef UINT32 uint32_t; -@@ -42,6 +44,12 @@ - #define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ - #define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ - -+#ifdef POLARSSL_AES_ALT -+ -+#include "polarssl/aes_alt.h" -+ -+#else -+ - /** - * \brief AES context structure - */ -@@ -169,6 +177,17 @@ - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* POLARSSL_AES_ALT */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** - * \brief Checkup routine - * -diff -uNr polarssl-1.2.7/include/polarssl/aes_alt.h polarssl.new/include/polarssl/aes_alt.h ---- polarssl-1.2.7/include/polarssl/aes_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/aes_alt.h 2013-06-07 18:18:37.000000000 -0600 -@@ -0,0 +1,183 @@ -+/* -+ * Use OpenSSL implementation of AES methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by aes.h when -+ * POLARSSL_AES_ALT is defined. -+ */ -+ -+#ifdef _MSC_VER -+#include -+typedef UINT32 uint32_t; -+#else -+#include -+#endif -+ -+#define OPENSSL_AES_BLOCK_SIZE 16 -+#define OPENSSL_AES_MAXNR 14 -+ -+/** -+ * \brief AES context structure -+ */ -+typedef struct -+{ -+ uint32_t rd_key[4 * (OPENSSL_AES_MAXNR + 1)]; -+ int rounds; -+} -+aes_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(POLARSSL_USE_OPENSSL_AES_NI) -+ -+int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+int aesni_set_decrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+void aesni_ecb_encrypt(const unsigned char *in, unsigned char *out, -+ size_t length, const aes_context *key, const int enc); -+void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out, -+ size_t length, const aes_context *key, -+ unsigned char *ivec, const int enc); -+ -+#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) aesni_set_encrypt_key(k,b,c) -+#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) aesni_set_decrypt_key(k,b,c) -+#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_ENCRYPT) -+#define OPENSSL_AES_ECB_DECRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_DECRYPT) -+#define OPENSSL_AES_CBC_ENCRYPT(i,o,l,k,iv,e) aesni_cbc_encrypt(i,o,l,k,iv,e) -+ -+#else -+ -+int AES_set_encrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+int AES_set_decrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+ -+void AES_encrypt(const unsigned char *in, unsigned char *out, const aes_context *key); -+void AES_decrypt(const unsigned char *in, unsigned char *out, const aes_context *key); -+ -+ -+#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) AES_set_encrypt_key(k,b,c) -+#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) AES_set_decrypt_key(k,b,c) -+#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) AES_encrypt(i,o,k) -+#define OPENSSL_AES_ECB_DECRYPT(i,o,k) AES_decrypt(i,o,k) -+ -+#endif -+ -+/** -+ * \brief AES key schedule (encryption) -+ * -+ * \param ctx AES context to be initialized -+ * \param key encryption key -+ * \param keysize must be 128, 192 or 256 -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH -+ */ -+static inline int aes_setkey_enc( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) -+{ -+ const int status = OPENSSL_AES_SET_ENCRYPT_KEY(key, keysize, ctx); -+ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; -+} -+ -+/** -+ * \brief AES key schedule (decryption) -+ * -+ * \param ctx AES context to be initialized -+ * \param key decryption key -+ * \param keysize must be 128, 192 or 256 -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH -+ */ -+static inline int aes_setkey_dec( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) -+{ -+ const int status = OPENSSL_AES_SET_DECRYPT_KEY(key, keysize, ctx); -+ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; -+} -+ -+/** -+ * \brief AES-ECB block encryption/decryption -+ * -+ * \param ctx AES context -+ * \param mode AES_ENCRYPT or AES_DECRYPT -+ * \param input 16-byte input block -+ * \param output 16-byte output block -+ * -+ * \return 0 if successful -+ */ -+static inline int aes_crypt_ecb( aes_context *ctx, -+ const int mode, -+ const unsigned char input[16], -+ unsigned char output[16] ) -+{ -+ if (mode == AES_DECRYPT) -+ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); -+ else -+ OPENSSL_AES_ECB_ENCRYPT(input, output, ctx); -+ return 0; -+} -+ -+/** -+ * \brief AES-CBC buffer encryption/decryption -+ * Length should be a multiple of the block -+ * size (16 bytes) -+ * -+ * \param ctx AES context -+ * \param mode AES_ENCRYPT or AES_DECRYPT -+ * \param length length of the input data -+ * \param iv initialization vector (updated after use) -+ * \param input buffer holding the input data -+ * \param output buffer holding the output data -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -+ */ -+static inline int aes_crypt_cbc( aes_context *ctx, -+ const int mode, -+ size_t length, -+ unsigned char iv[16], -+ const unsigned char *input, -+ unsigned char *output ) -+{ -+#ifdef OPENSSL_AES_CBC_ENCRYPT -+ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) -+ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; -+ OPENSSL_AES_CBC_ENCRYPT(input, output, length, ctx, iv, mode); -+ return 0; -+#else -+ int i; -+ unsigned char temp[16]; -+ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) -+ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; -+ if( mode == AES_DECRYPT ) -+ { -+ while( length > 0 ) -+ { -+ memcpy( temp, input, 16 ); -+ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); -+ for( i = 0; i < 16; i++ ) -+ output[i] = (unsigned char)( output[i] ^ iv[i] ); -+ memcpy( iv, temp, 16 ); -+ input += 16; -+ output += 16; -+ length -= 16; -+ } -+ } -+ else -+ { -+ while( length > 0 ) -+ { -+ for( i = 0; i < 16; i++ ) -+ output[i] = (unsigned char)( input[i] ^ iv[i] ); -+ OPENSSL_AES_ECB_ENCRYPT(output, output, ctx); -+ memcpy( iv, output, 16 ); -+ input += 16; -+ output += 16; -+ length -= 16; -+ } -+ } -+ return( 0 ); -+#endif -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha1.h polarssl.new/include/polarssl/sha1.h ---- polarssl-1.2.7/include/polarssl/sha1.h 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/include/polarssl/sha1.h 2013-06-07 17:43:56.000000000 -0600 -@@ -29,6 +29,8 @@ - - #include - -+#include "config.h" -+ - #ifdef _MSC_VER - #include - typedef UINT32 uint32_t; -@@ -38,6 +40,12 @@ - - #define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ - -+#ifdef POLARSSL_SHA1_ALT -+ -+#include "polarssl/sha1_alt.h" -+ -+#else -+ - /** - * \brief SHA-1 context structure - */ -@@ -80,6 +88,19 @@ - */ - void sha1_finish( sha1_context *ctx, unsigned char output[20] ); - -+/* Internal use */ -+void sha1_process( sha1_context *ctx, const unsigned char data[64] ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* POLARSSL_SHA1_ALT */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** - * \brief Output = SHA-1( input buffer ) - * -@@ -152,9 +173,6 @@ - */ - int sha1_self_test( int verbose ); - --/* Internal use */ --void sha1_process( sha1_context *ctx, const unsigned char data[64] ); -- - #ifdef __cplusplus - } - #endif -diff -uNr polarssl-1.2.7/include/polarssl/sha1_alt.h polarssl.new/include/polarssl/sha1_alt.h ---- polarssl-1.2.7/include/polarssl/sha1_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha1_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,56 @@ -+/* -+ * Use OpenSSL implementation of SHA1 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha1.h when -+ * POLARSSL_SHA1_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha_context { -+ SHA_LONG h0,h1,h2,h3,h4; -+ SHA_LONG Nl,Nh; -+ SHA_LONG data[SHA_LBLOCK]; -+ unsigned int num; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha_context octx; -+ -+ unsigned char ipad[64]; /*!< HMAC: inner padding */ -+ unsigned char opad[64]; /*!< HMAC: outer padding */ -+} -+sha1_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA1_Init(struct openssl_sha_context *c); -+int SHA1_Update(struct openssl_sha_context *c, const void *data, size_t len); -+int SHA1_Final(unsigned char *md, struct openssl_sha_context *c); -+void sha1_block_data_order(struct openssl_sha_context *c, const void *p, size_t num); -+ -+static inline void sha1_starts( sha1_context *ctx ) -+{ -+ SHA1_Init(&ctx->octx); -+} -+ -+static inline void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ SHA1_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha1_finish( sha1_context *ctx, unsigned char output[20] ) -+{ -+ SHA1_Final(output, &ctx->octx); -+} -+ -+static inline void sha1_process( sha1_context *ctx, const unsigned char data[64] ) -+{ -+ sha1_block_data_order(&ctx->octx, data, 1); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha2.h polarssl.new/include/polarssl/sha2.h ---- polarssl-1.2.7/include/polarssl/sha2.h 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/include/polarssl/sha2.h 2013-06-07 17:43:56.000000000 -0600 -@@ -29,6 +29,8 @@ - - #include - -+#include "config.h" -+ - #ifdef _MSC_VER - #include - typedef UINT32 uint32_t; -@@ -38,6 +40,12 @@ - - #define POLARSSL_ERR_SHA2_FILE_IO_ERROR -0x0078 /**< Read/write error in file. */ - -+#ifdef POLARSSL_SHA2_ALT -+ -+#include "polarssl/sha2_alt.h" -+ -+#else -+ - /** - * \brief SHA-256 context structure - */ -@@ -82,6 +90,19 @@ - */ - void sha2_finish( sha2_context *ctx, unsigned char output[32] ); - -+/* Internal use */ -+void sha2_process( sha2_context *ctx, const unsigned char data[64] ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* POLARSSL_SHA2_ALT */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** - * \brief Output = SHA-256( input buffer ) - * -@@ -160,9 +181,6 @@ - */ - int sha2_self_test( int verbose ); - --/* Internal use */ --void sha2_process( sha2_context *ctx, const unsigned char data[64] ); -- - #ifdef __cplusplus - } - #endif -diff -uNr polarssl-1.2.7/include/polarssl/sha2_alt.h polarssl.new/include/polarssl/sha2_alt.h ---- polarssl-1.2.7/include/polarssl/sha2_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha2_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,71 @@ -+/* -+ * Use OpenSSL implementation of SHA2 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha2.h when -+ * POLARSSL_SHA2_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha2_context { -+ SHA_LONG h[8]; -+ SHA_LONG Nl,Nh; -+ SHA_LONG data[SHA_LBLOCK]; -+ unsigned int num,md_len; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha2_context octx; -+ -+ unsigned char ipad[64]; /*!< HMAC: inner padding */ -+ unsigned char opad[64]; /*!< HMAC: outer padding */ -+ int is224; /*!< 0 => SHA-256, else SHA-224 */ -+} -+sha2_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA224_Init(struct openssl_sha2_context *c); -+int SHA224_Update(struct openssl_sha2_context *c, const void *data, size_t len); -+int SHA224_Final(unsigned char *md, struct openssl_sha2_context *c); -+ -+int SHA256_Init(struct openssl_sha2_context *c); -+int SHA256_Update(struct openssl_sha2_context *c, const void *data, size_t len); -+int SHA256_Final(unsigned char *md, struct openssl_sha2_context *c); -+ -+void sha256_block_data_order(struct openssl_sha2_context *c, const void *p, size_t num); -+ -+static inline void sha2_starts( sha2_context *ctx, int is224 ) -+{ -+ if ((ctx->is224 = is224)) -+ SHA224_Init(&ctx->octx); -+ else -+ SHA256_Init(&ctx->octx); -+} -+ -+static inline void sha2_update( sha2_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ if (ctx->is224) -+ SHA224_Update(&ctx->octx, input, ilen); -+ else -+ SHA256_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha2_finish( sha2_context *ctx, unsigned char output[32] ) -+{ -+ if (ctx->is224) -+ SHA224_Final(output, &ctx->octx); -+ else -+ SHA256_Final(output, &ctx->octx); -+} -+ -+static inline void sha2_process( sha2_context *ctx, const unsigned char data[64] ) -+{ -+ sha256_block_data_order(&ctx->octx, data, 1); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha4.h polarssl.new/include/polarssl/sha4.h ---- polarssl-1.2.7/include/polarssl/sha4.h 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/include/polarssl/sha4.h 2013-06-07 17:43:56.000000000 -0600 -@@ -29,6 +29,8 @@ - - #include - -+#include "config.h" -+ - #if defined(_MSC_VER) || defined(__WATCOMC__) - #define UL64(x) x##ui64 - typedef unsigned __int64 uint64_t; -@@ -39,6 +41,12 @@ - - #define POLARSSL_ERR_SHA4_FILE_IO_ERROR -0x007A /**< Read/write error in file. */ - -+#ifdef POLARSSL_SHA4_ALT -+ -+#include "polarssl/sha4_alt.h" -+ -+#else -+ - /** - * \brief SHA-512 context structure - */ -@@ -83,6 +91,16 @@ - */ - void sha4_finish( sha4_context *ctx, unsigned char output[64] ); - -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* POLARSSL_SHA4_ALT */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** - * \brief Output = SHA-512( input buffer ) - * -diff -uNr polarssl-1.2.7/include/polarssl/sha4_alt.h polarssl.new/include/polarssl/sha4_alt.h ---- polarssl-1.2.7/include/polarssl/sha4_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha4_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,67 @@ -+/* -+ * Use OpenSSL implementation of SHA4 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha4.h when -+ * POLARSSL_SHA4_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha4_context { -+ SHA_LONG64 h[8]; -+ SHA_LONG64 Nl,Nh; -+ union { -+ SHA_LONG64 d[SHA_LBLOCK]; -+ unsigned char p[SHA512_CBLOCK]; -+ } u; -+ unsigned int num,md_len; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha4_context octx; -+ -+ unsigned char ipad[128]; /*!< HMAC: inner padding */ -+ unsigned char opad[128]; /*!< HMAC: outer padding */ -+ int is384; /*!< 0 => SHA-512, else SHA-384 */ -+} -+sha4_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA384_Init(struct openssl_sha4_context *c); -+int SHA384_Update(struct openssl_sha4_context *c, const void *data, size_t len); -+int SHA384_Final(unsigned char *md, struct openssl_sha4_context *c); -+ -+int SHA512_Init(struct openssl_sha4_context *c); -+int SHA512_Update(struct openssl_sha4_context *c, const void *data, size_t len); -+int SHA512_Final(unsigned char *md, struct openssl_sha4_context *c); -+ -+static inline void sha4_starts( sha4_context *ctx, int is384 ) -+{ -+ if ((ctx->is384 = is384)) -+ SHA384_Init(&ctx->octx); -+ else -+ SHA512_Init(&ctx->octx); -+} -+ -+static inline void sha4_update( sha4_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ if (ctx->is384) -+ SHA384_Update(&ctx->octx, input, ilen); -+ else -+ SHA512_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha4_finish( sha4_context *ctx, unsigned char output[64] ) -+{ -+ if (ctx->is384) -+ SHA384_Final(output, &ctx->octx); -+ else -+ SHA512_Final(output, &ctx->octx); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha_openssl.h polarssl.new/include/polarssl/sha_openssl.h ---- polarssl-1.2.7/include/polarssl/sha_openssl.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha_openssl.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,42 @@ -+/* -+ * Common header file for all OpenSSL-imported SHA methods -+ */ -+ -+#ifndef POLARSSL_SHA_OPENSSL_H -+#define POLARSSL_SHA_OPENSSL_H -+ -+/* -+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! -+ * ! SHA_LONG_LOG2 has to be defined along. ! -+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -+ */ -+ -+#if defined(__LP32__) -+#define SHA_LONG unsigned long -+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) -+#define SHA_LONG unsigned long -+#define SHA_LONG_LOG2 3 -+#else -+#define SHA_LONG unsigned int -+#endif -+ -+#define SHA_LBLOCK 16 -+ -+/* -+ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 -+ * being exactly 64-bit wide. See Implementation Notes in sha512.c -+ * for further details. -+ */ -+#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a -+ * contiguous array of 64 bit -+ * wide big-endian values. */ -+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) -+#define SHA_LONG64 unsigned __int64 -+#elif defined(__arch64__) -+#define SHA_LONG64 unsigned long -+#else -+#define SHA_LONG64 unsigned long long -+#endif -+ -+#endif -diff -uNr polarssl-1.2.7/library/aes.c polarssl.new/library/aes.c ---- polarssl-1.2.7/library/aes.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/library/aes.c 2013-06-07 17:43:56.000000000 -0600 -@@ -38,6 +38,8 @@ - #include "polarssl/padlock.h" - #endif - -+#ifndef POLARSSL_AES_ALT -+ - /* - * 32-bit integer manipulation macros (little endian) - */ -@@ -914,6 +916,7 @@ - return( 0 ); - } - #endif /* POLARSSL_CIPHER_MODE_CTR */ -+#endif /* !POLARSSL_AES_ALT */ - - #if defined(POLARSSL_SELF_TEST) - -diff -uNr polarssl-1.2.7/library/sha1.c polarssl.new/library/sha1.c ---- polarssl-1.2.7/library/sha1.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/library/sha1.c 2013-06-07 17:43:56.000000000 -0600 -@@ -38,6 +38,8 @@ - #include - #endif - -+#ifndef POLARSSL_SHA1_ALT -+ - /* - * 32-bit integer manipulation macros (big endian) - */ -@@ -313,6 +315,8 @@ - PUT_UINT32_BE( ctx->state[4], output, 16 ); - } - -+#endif /* !POLARSSL_SHA1_ALT */ -+ - /* - * output = SHA-1( input buffer ) - */ -diff -uNr polarssl-1.2.7/library/sha2.c polarssl.new/library/sha2.c ---- polarssl-1.2.7/library/sha2.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/library/sha2.c 2013-06-07 17:43:56.000000000 -0600 -@@ -38,6 +38,8 @@ - #include - #endif - -+#ifndef POLARSSL_SHA2_ALT -+ - /* - * 32-bit integer manipulation macros (big endian) - */ -@@ -314,6 +316,8 @@ - PUT_UINT32_BE( ctx->state[7], output, 28 ); - } - -+#endif /* !POLARSSL_SHA2_ALT */ -+ - /* - * output = SHA-256( input buffer ) - */ -diff -uNr polarssl-1.2.7/library/sha4.c polarssl.new/library/sha4.c ---- polarssl-1.2.7/library/sha4.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/library/sha4.c 2013-06-07 17:43:56.000000000 -0600 -@@ -38,6 +38,8 @@ - #include - #endif - -+#ifndef POLARSSL_SHA4_ALT -+ - /* - * 64-bit integer manipulation macros (big endian) - */ -@@ -312,6 +314,8 @@ - } - } - -+#endif /* !POLARSSL_SHA4_ALT */ -+ - /* - * output = SHA-512( input buffer ) - */ -diff -uNr polarssl-1.2.7/library/ssl_tls.c polarssl.new/library/ssl_tls.c ---- polarssl-1.2.7/library/ssl_tls.c 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/library/ssl_tls.c 2013-06-07 17:43:56.000000000 -0600 -@@ -2550,8 +2550,10 @@ - SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); - -+#ifndef POLARSSL_SHA1_ALT - SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -+#endif - - sender = ( from == SSL_IS_CLIENT ) ? (char *) "CLNT" - : (char *) "SRVR"; -@@ -2621,8 +2623,10 @@ - SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); - -+#ifndef POLARSSL_SHA1_ALT - SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -+#endif - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" -@@ -2666,8 +2670,10 @@ - * Hash( handshake ) )[0.11] - */ - -+#ifndef POLARSSL_SHA2_ALT - SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) - sha2.state, sizeof( sha2.state ) ); -+#endif - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" -@@ -2710,8 +2716,10 @@ - * Hash( handshake ) )[0.11] - */ - -+#ifndef POLARSSL_SHA4_ALT - SSL_DEBUG_BUF( 4, "finished sha4 state", (unsigned char *) - sha4.state, sizeof( sha4.state ) ); -+#endif - - sender = ( from == SSL_IS_CLIENT ) - ? (char *) "client finished" -diff -uNr polarssl-1.2.7/tests/suites/test_suite_aes.function polarssl.new/tests/suites/test_suite_aes.function ---- polarssl-1.2.7/tests/suites/test_suite_aes.function 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/tests/suites/test_suite_aes.function 2013-06-07 17:43:56.000000000 -0600 -@@ -1,4 +1,5 @@ - BEGIN_HEADER -+#include - #include - END_HEADER - -diff -uNr polarssl-1.2.7/tests/suites/test_suite_ctr_drbg.function polarssl.new/tests/suites/test_suite_ctr_drbg.function ---- polarssl-1.2.7/tests/suites/test_suite_ctr_drbg.function 2013-04-13 03:56:17.000000000 -0600 -+++ polarssl.new/tests/suites/test_suite_ctr_drbg.function 2013-06-07 17:43:56.000000000 -0600 -@@ -1,4 +1,5 @@ - BEGIN_HEADER -+#include - #include - - int test_offset; diff --git a/Sources/OpenVPN3/deps/polarssl/polarssl-minicrypto.patch b/Sources/OpenVPN3/deps/polarssl/polarssl-minicrypto.patch deleted file mode 100644 index 0331ae1..0000000 --- a/Sources/OpenVPN3/deps/polarssl/polarssl-minicrypto.patch +++ /dev/null @@ -1,446 +0,0 @@ -diff -uNr polarssl-1.2.7/include/polarssl/aes_alt.h polarssl.new/include/polarssl/aes_alt.h ---- polarssl-1.2.7/include/polarssl/aes_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/aes_alt.h 2013-06-07 18:18:37.000000000 -0600 -@@ -0,0 +1,183 @@ -+/* -+ * Use OpenSSL implementation of AES methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by aes.h when -+ * POLARSSL_AES_ALT is defined. -+ */ -+ -+#ifdef _MSC_VER -+#include -+typedef UINT32 uint32_t; -+#else -+#include -+#endif -+ -+#define OPENSSL_AES_BLOCK_SIZE 16 -+#define OPENSSL_AES_MAXNR 14 -+ -+/** -+ * \brief AES context structure -+ */ -+typedef struct -+{ -+ uint32_t rd_key[4 * (OPENSSL_AES_MAXNR + 1)]; -+ int rounds; -+} -+aes_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#if defined(POLARSSL_USE_OPENSSL_AES_NI) -+ -+int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+int aesni_set_decrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+void aesni_ecb_encrypt(const unsigned char *in, unsigned char *out, -+ size_t length, const aes_context *key, const int enc); -+void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out, -+ size_t length, const aes_context *key, -+ unsigned char *ivec, const int enc); -+ -+#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) aesni_set_encrypt_key(k,b,c) -+#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) aesni_set_decrypt_key(k,b,c) -+#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_ENCRYPT) -+#define OPENSSL_AES_ECB_DECRYPT(i,o,k) aesni_ecb_encrypt(i,o,16,k,AES_DECRYPT) -+#define OPENSSL_AES_CBC_ENCRYPT(i,o,l,k,iv,e) aesni_cbc_encrypt(i,o,l,k,iv,e) -+ -+#else -+ -+int AES_set_encrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+int AES_set_decrypt_key(const unsigned char *userKey, const int bits, -+ aes_context *key); -+ -+void AES_encrypt(const unsigned char *in, unsigned char *out, const aes_context *key); -+void AES_decrypt(const unsigned char *in, unsigned char *out, const aes_context *key); -+ -+ -+#define OPENSSL_AES_SET_ENCRYPT_KEY(k,b,c) AES_set_encrypt_key(k,b,c) -+#define OPENSSL_AES_SET_DECRYPT_KEY(k,b,c) AES_set_decrypt_key(k,b,c) -+#define OPENSSL_AES_ECB_ENCRYPT(i,o,k) AES_encrypt(i,o,k) -+#define OPENSSL_AES_ECB_DECRYPT(i,o,k) AES_decrypt(i,o,k) -+ -+#endif -+ -+/** -+ * \brief AES key schedule (encryption) -+ * -+ * \param ctx AES context to be initialized -+ * \param key encryption key -+ * \param keysize must be 128, 192 or 256 -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH -+ */ -+static inline int aes_setkey_enc( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) -+{ -+ const int status = OPENSSL_AES_SET_ENCRYPT_KEY(key, keysize, ctx); -+ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; -+} -+ -+/** -+ * \brief AES key schedule (decryption) -+ * -+ * \param ctx AES context to be initialized -+ * \param key decryption key -+ * \param keysize must be 128, 192 or 256 -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH -+ */ -+static inline int aes_setkey_dec( aes_context *ctx, const unsigned char *key, const unsigned int keysize ) -+{ -+ const int status = OPENSSL_AES_SET_DECRYPT_KEY(key, keysize, ctx); -+ return status ? POLARSSL_ERR_AES_INVALID_KEY_LENGTH : 0; -+} -+ -+/** -+ * \brief AES-ECB block encryption/decryption -+ * -+ * \param ctx AES context -+ * \param mode AES_ENCRYPT or AES_DECRYPT -+ * \param input 16-byte input block -+ * \param output 16-byte output block -+ * -+ * \return 0 if successful -+ */ -+static inline int aes_crypt_ecb( aes_context *ctx, -+ const int mode, -+ const unsigned char input[16], -+ unsigned char output[16] ) -+{ -+ if (mode == AES_DECRYPT) -+ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); -+ else -+ OPENSSL_AES_ECB_ENCRYPT(input, output, ctx); -+ return 0; -+} -+ -+/** -+ * \brief AES-CBC buffer encryption/decryption -+ * Length should be a multiple of the block -+ * size (16 bytes) -+ * -+ * \param ctx AES context -+ * \param mode AES_ENCRYPT or AES_DECRYPT -+ * \param length length of the input data -+ * \param iv initialization vector (updated after use) -+ * \param input buffer holding the input data -+ * \param output buffer holding the output data -+ * -+ * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -+ */ -+static inline int aes_crypt_cbc( aes_context *ctx, -+ const int mode, -+ size_t length, -+ unsigned char iv[16], -+ const unsigned char *input, -+ unsigned char *output ) -+{ -+#ifdef OPENSSL_AES_CBC_ENCRYPT -+ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) -+ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; -+ OPENSSL_AES_CBC_ENCRYPT(input, output, length, ctx, iv, mode); -+ return 0; -+#else -+ int i; -+ unsigned char temp[16]; -+ if (length & (OPENSSL_AES_BLOCK_SIZE-1)) -+ return POLARSSL_ERR_AES_INVALID_INPUT_LENGTH; -+ if( mode == AES_DECRYPT ) -+ { -+ while( length > 0 ) -+ { -+ memcpy( temp, input, 16 ); -+ OPENSSL_AES_ECB_DECRYPT(input, output, ctx); -+ for( i = 0; i < 16; i++ ) -+ output[i] = (unsigned char)( output[i] ^ iv[i] ); -+ memcpy( iv, temp, 16 ); -+ input += 16; -+ output += 16; -+ length -= 16; -+ } -+ } -+ else -+ { -+ while( length > 0 ) -+ { -+ for( i = 0; i < 16; i++ ) -+ output[i] = (unsigned char)( input[i] ^ iv[i] ); -+ OPENSSL_AES_ECB_ENCRYPT(output, output, ctx); -+ memcpy( iv, output, 16 ); -+ input += 16; -+ output += 16; -+ length -= 16; -+ } -+ } -+ return( 0 ); -+#endif -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha1_alt.h polarssl.new/include/polarssl/sha1_alt.h ---- polarssl-1.2.7/include/polarssl/sha1_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha1_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,56 @@ -+/* -+ * Use OpenSSL implementation of SHA1 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha1.h when -+ * POLARSSL_SHA1_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha_context { -+ SHA_LONG h0,h1,h2,h3,h4; -+ SHA_LONG Nl,Nh; -+ SHA_LONG data[SHA_LBLOCK]; -+ unsigned int num; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha_context octx; -+ -+ unsigned char ipad[64]; /*!< HMAC: inner padding */ -+ unsigned char opad[64]; /*!< HMAC: outer padding */ -+} -+sha1_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA1_Init(struct openssl_sha_context *c); -+int SHA1_Update(struct openssl_sha_context *c, const void *data, size_t len); -+int SHA1_Final(unsigned char *md, struct openssl_sha_context *c); -+void sha1_block_data_order(struct openssl_sha_context *c, const void *p, size_t num); -+ -+static inline void sha1_starts( sha1_context *ctx ) -+{ -+ SHA1_Init(&ctx->octx); -+} -+ -+static inline void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ SHA1_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha1_finish( sha1_context *ctx, unsigned char output[20] ) -+{ -+ SHA1_Final(output, &ctx->octx); -+} -+ -+static inline void sha1_process( sha1_context *ctx, const unsigned char data[64] ) -+{ -+ sha1_block_data_order(&ctx->octx, data, 1); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha256_alt.h polarssl.new/include/polarssl/sha256_alt.h ---- polarssl-1.2.7/include/polarssl/sha256_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha256_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,71 @@ -+/* -+ * Use OpenSSL implementation of SHA256 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha256.h when -+ * POLARSSL_SHA256_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha256_context { -+ SHA_LONG h[8]; -+ SHA_LONG Nl,Nh; -+ SHA_LONG data[SHA_LBLOCK]; -+ unsigned int num,md_len; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha256_context octx; -+ -+ unsigned char ipad[64]; /*!< HMAC: inner padding */ -+ unsigned char opad[64]; /*!< HMAC: outer padding */ -+ int is224; /*!< 0 => SHA-256, else SHA-224 */ -+} -+sha256_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA224_Init(struct openssl_sha256_context *c); -+int SHA224_Update(struct openssl_sha256_context *c, const void *data, size_t len); -+int SHA224_Final(unsigned char *md, struct openssl_sha256_context *c); -+ -+int SHA256_Init(struct openssl_sha256_context *c); -+int SHA256_Update(struct openssl_sha256_context *c, const void *data, size_t len); -+int SHA256_Final(unsigned char *md, struct openssl_sha256_context *c); -+ -+void sha256_block_data_order(struct openssl_sha256_context *c, const void *p, size_t num); -+ -+static inline void sha256_starts( sha256_context *ctx, int is224 ) -+{ -+ if ((ctx->is224 = is224)) -+ SHA224_Init(&ctx->octx); -+ else -+ SHA256_Init(&ctx->octx); -+} -+ -+static inline void sha256_update( sha256_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ if (ctx->is224) -+ SHA224_Update(&ctx->octx, input, ilen); -+ else -+ SHA256_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha256_finish( sha256_context *ctx, unsigned char output[32] ) -+{ -+ if (ctx->is224) -+ SHA224_Final(output, &ctx->octx); -+ else -+ SHA256_Final(output, &ctx->octx); -+} -+ -+static inline void sha256_process( sha256_context *ctx, const unsigned char data[64] ) -+{ -+ sha256_block_data_order(&ctx->octx, data, 1); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha512_alt.h polarssl.new/include/polarssl/sha512_alt.h ---- polarssl-1.2.7/include/polarssl/sha512_alt.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha512_alt.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,74 @@ -+/* -+ * Use OpenSSL implementation of SHA512 methods to get asm and hardware acceleration. -+ * Don't include this file directly, it is included by sha512.h when -+ * POLARSSL_SHA512_ALT is defined. -+ */ -+ -+#include "polarssl/sha_openssl.h" -+ -+struct openssl_sha512_context { -+ SHA_LONG64 h[8]; -+ SHA_LONG64 Nl,Nh; -+ union { -+ SHA_LONG64 d[SHA_LBLOCK]; -+ unsigned char p[SHA512_CBLOCK]; -+ } u; -+ unsigned int num,md_len; -+}; -+ -+typedef struct -+{ -+ struct openssl_sha512_context octx; -+ -+ unsigned char ipad[128]; /*!< HMAC: inner padding */ -+ unsigned char opad[128]; /*!< HMAC: outer padding */ -+ int is384; /*!< 0 => SHA-512, else SHA-384 */ -+} -+sha512_context; -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+int SHA384_Init(struct openssl_sha512_context *c); -+int SHA384_Update(struct openssl_sha512_context *c, const void *data, size_t len); -+int SHA384_Final(unsigned char *md, struct openssl_sha512_context *c); -+ -+int SHA512_Init(struct openssl_sha512_context *c); -+int SHA512_Update(struct openssl_sha512_context *c, const void *data, size_t len); -+int SHA512_Final(unsigned char *md, struct openssl_sha512_context *c); -+ -+void sha512_block_data_order(struct openssl_sha512_context *c, const void *p, size_t num); -+ -+static inline void sha512_starts( sha512_context *ctx, int is384 ) -+{ -+ if ((ctx->is384 = is384)) -+ SHA384_Init(&ctx->octx); -+ else -+ SHA512_Init(&ctx->octx); -+} -+ -+static inline void sha512_update( sha512_context *ctx, const unsigned char *input, size_t ilen ) -+{ -+ if (ctx->is384) -+ SHA384_Update(&ctx->octx, input, ilen); -+ else -+ SHA512_Update(&ctx->octx, input, ilen); -+} -+ -+static inline void sha512_finish( sha512_context *ctx, unsigned char output[64] ) -+{ -+ if (ctx->is384) -+ SHA384_Final(output, &ctx->octx); -+ else -+ SHA512_Final(output, &ctx->octx); -+} -+ -+static inline void sha512_process( sha512_context *ctx, const unsigned char data[128] ) -+{ -+ sha512_block_data_order(&ctx->octx, data, 1); -+} -+ -+#ifdef __cplusplus -+} -+#endif -diff -uNr polarssl-1.2.7/include/polarssl/sha_openssl.h polarssl.new/include/polarssl/sha_openssl.h ---- polarssl-1.2.7/include/polarssl/sha_openssl.h 1969-12-31 17:00:00.000000000 -0700 -+++ polarssl.new/include/polarssl/sha_openssl.h 2013-06-07 17:43:56.000000000 -0600 -@@ -0,0 +1,42 @@ -+/* -+ * Common header file for all OpenSSL-imported SHA methods -+ */ -+ -+#ifndef POLARSSL_SHA_OPENSSL_H -+#define POLARSSL_SHA_OPENSSL_H -+ -+/* -+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! -+ * ! SHA_LONG_LOG2 has to be defined along. ! -+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -+ */ -+ -+#if defined(__LP32__) -+#define SHA_LONG unsigned long -+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) -+#define SHA_LONG unsigned long -+#define SHA_LONG_LOG2 3 -+#else -+#define SHA_LONG unsigned int -+#endif -+ -+#define SHA_LBLOCK 16 -+ -+/* -+ * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 -+ * being exactly 64-bit wide. See Implementation Notes in sha512.c -+ * for further details. -+ */ -+#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a -+ * contiguous array of 64 bit -+ * wide big-endian values. */ -+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) -+#define SHA_LONG64 unsigned __int64 -+#elif defined(__arch64__) -+#define SHA_LONG64 unsigned long -+#else -+#define SHA_LONG64 unsigned long long -+#endif -+ -+#endif diff --git a/Sources/OpenVPN3/deps/polarssl/ref b/Sources/OpenVPN3/deps/polarssl/ref deleted file mode 100644 index 6e16cdd..0000000 --- a/Sources/OpenVPN3/deps/polarssl/ref +++ /dev/null @@ -1,24 +0,0 @@ -AES_set_encrypt_key -AES_set_decrypt_key -AES_ecb_encrypt -AES_cbc_encrypt -BF_set_key -BF_ecb_encrypt -BF_cbc_encrypt -SHA1_Init -SHA1_Update -SHA1_Final -SHA224_Init -SHA224_Update -SHA224_Final -SHA256_Init -SHA256_Update -SHA256_Final -SHA384_Init -SHA384_Update -SHA384_Final -SHA512_Init -SHA512_Update -SHA512_Final -OPENSSL_ia32_cpuid --OPENSSL_cpuid_setup diff --git a/Sources/OpenVPN3/deps/polarssl/ref-aesni b/Sources/OpenVPN3/deps/polarssl/ref-aesni deleted file mode 100644 index 0574500..0000000 --- a/Sources/OpenVPN3/deps/polarssl/ref-aesni +++ /dev/null @@ -1,24 +0,0 @@ -aesni_set_encrypt_key -aesni_set_decrypt_key -aesni_ecb_encrypt -aesni_cbc_encrypt -BF_set_key -BF_ecb_encrypt -BF_cbc_encrypt -SHA1_Init -SHA1_Update -SHA1_Final -SHA224_Init -SHA224_Update -SHA224_Final -SHA256_Init -SHA256_Update -SHA256_Final -SHA384_Init -SHA384_Update -SHA384_Final -SHA512_Init -SHA512_Update -SHA512_Final -OPENSSL_ia32_cpuid --OPENSSL_cpuid_setup diff --git a/Sources/OpenVPN3/deps/polarssl/relaxed-x509-date.patch b/Sources/OpenVPN3/deps/polarssl/relaxed-x509-date.patch deleted file mode 100644 index eb021f2..0000000 --- a/Sources/OpenVPN3/deps/polarssl/relaxed-x509-date.patch +++ /dev/null @@ -1,118 +0,0 @@ -diff -ur mbedtls-1.3.17/library/x509.c polarssl.new/library/x509.c ---- mbedtls-1.3.17/library/x509.c 2016-06-27 13:00:26.000000000 -0600 -+++ polarssl.new/library/x509.c 2016-08-04 17:21:52.000000000 -0600 -@@ -490,6 +490,73 @@ - } - - /* -+ * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) field. -+ */ -+static int x509_parse_time(unsigned char **p, size_t len, unsigned int yearlen, x509_time *time) -+{ -+ int ret; -+ -+ /* minimum length is 10 or 12 depending on yearlen */ -+ if (len < yearlen + 8) -+ return POLARSSL_ERR_X509_INVALID_DATE; -+ len -= yearlen + 8; -+ -+ /* parse year, month, day, hour, minute */ -+ CHECK( x509_parse_int( p, yearlen, &time->year ) ); -+ if (yearlen == 2) -+ { -+ if (time->year < 50) -+ time->year += 100; -+ time->year += 1900; -+ } -+ CHECK( x509_parse_int( p, 2, &time->mon ) ); -+ CHECK( x509_parse_int( p, 2, &time->day ) ); -+ CHECK( x509_parse_int( p, 2, &time->hour ) ); -+ CHECK( x509_parse_int( p, 2, &time->min ) ); -+ -+ /* parse seconds if present */ -+ if (len >= 2 && **p >= '0' && **p <= '9') -+ { -+ CHECK( x509_parse_int( p, 2, &time->sec ) ); -+ len -= 2; -+ } -+ else -+ { -+#if defined(POLARSSL_RELAXED_X509_DATE) -+ /* if relaxed mode, allow seconds to be absent */ -+ time->sec = 0; -+#else -+ return POLARSSL_ERR_X509_INVALID_DATE; -+#endif -+ } -+ -+ /* parse trailing 'Z' if present */ -+ if (len == 1 && **p == 'Z') -+ { -+ (*p)++; -+ return 0; -+ } -+ -+#if defined(POLARSSL_RELAXED_X509_DATE) -+ /* if relaxed mode, allow timezone to be present */ -+ else if (len == 5 && **p == '+') -+ { -+ int tz; /* throwaway timezone */ -+ (*p)++; -+ CHECK( x509_parse_int( p, 4, &tz ) ); -+ return 0; -+ } -+#endif -+ -+ /* okay if no trailing 'Z' or timezone specified */ -+ else if (len == 0) -+ return 0; -+ -+ else -+ return POLARSSL_ERR_X509_INVALID_DATE; -+} -+ -+/* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime } -@@ -515,20 +582,7 @@ - if( ret != 0 ) - return( POLARSSL_ERR_X509_INVALID_DATE + ret ); - -- CHECK( x509_parse_int( p, 2, &time->year ) ); -- CHECK( x509_parse_int( p, 2, &time->mon ) ); -- CHECK( x509_parse_int( p, 2, &time->day ) ); -- CHECK( x509_parse_int( p, 2, &time->hour ) ); -- CHECK( x509_parse_int( p, 2, &time->min ) ); -- if( len > 10 ) -- CHECK( x509_parse_int( p, 2, &time->sec ) ); -- if( len > 12 && *(*p)++ != 'Z' ) -- return( POLARSSL_ERR_X509_INVALID_DATE ); -- -- time->year += 100 * ( time->year < 50 ); -- time->year += 1900; -- -- return( 0 ); -+ return x509_parse_time(p, len, 2, time); - } - else if( tag == ASN1_GENERALIZED_TIME ) - { -@@ -538,17 +592,7 @@ - if( ret != 0 ) - return( POLARSSL_ERR_X509_INVALID_DATE + ret ); - -- CHECK( x509_parse_int( p, 4, &time->year ) ); -- CHECK( x509_parse_int( p, 2, &time->mon ) ); -- CHECK( x509_parse_int( p, 2, &time->day ) ); -- CHECK( x509_parse_int( p, 2, &time->hour ) ); -- CHECK( x509_parse_int( p, 2, &time->min ) ); -- if( len > 12 ) -- CHECK( x509_parse_int( p, 2, &time->sec ) ); -- if( len > 14 && *(*p)++ != 'Z' ) -- return( POLARSSL_ERR_X509_INVALID_DATE ); -- -- return( 0 ); -+ return x509_parse_time(p, len, 4, time); - } - else - return( POLARSSL_ERR_X509_INVALID_DATE + diff --git a/Sources/OpenVPN3/deps/polarssl/testpatch b/Sources/OpenVPN3/deps/polarssl/testpatch deleted file mode 100755 index 0330a9e..0000000 --- a/Sources/OpenVPN3/deps/polarssl/testpatch +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -ver=1.2.7 -src=~/src/mac/polarssl-$ver -rm -rf polarssl-$ver polarssl-$ver.new -tar xfz $DL/polarssl-$ver-gpl.tgz -cp -a polarssl-$ver polarssl-$ver.new -cd polarssl-$ver.new -cp $src/include/polarssl/bn_mul.h include/polarssl/ -cp $src/library/bignum.c library/ -#cp $src/library/mpi_mul_hlp.c library/ -#cp $src/library/CMakeLists.txt library/ -cd .. -diff -uNr polarssl-$ver polarssl-$ver.new diff --git a/Sources/OpenVPN3/deps/snappy/build-snappy b/Sources/OpenVPN3/deps/snappy/build-snappy deleted file mode 100755 index e05ff5f..0000000 --- a/Sources/OpenVPN3/deps/snappy/build-snappy +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi -if [ -z "$TARGET" ]; then - echo TARGET var must be defined - exit 1 -fi - -[ -z "$DL" ] && DL=~/Downloads - -# source vars -. $O3/core/vars/vars-${TARGET} -. $O3/core/deps/lib-versions - -[ "$GCC_CMD" ] && export CC=$GCC_CMD -[ "$GPP_CMD" ] && export CXX=$GPP_CMD -[ "$LD_CMD" ] && export LD=$LD_CMD -[ "$AR_CMD" ] && export AR=$AR_CMD -[ "$RANLIB_CMD" ] && export RANLIB=$RANLIB_CMD - -case $PLATFORM in -android*) - echo PLATFORM android - host=arm - target=arm - ;; -ios*) - echo PLATFORM ios - host="x86_64-apple-darwin" - target=arm - ;; -*) - host="" - target="" - ;; -esac - -if [ "$target" ]; then - targ_opt="--target=$target" -fi - -if [ "$host" ]; then - host_opt="--host=$host" -fi - -if [ "$NO_WIPE" != "1" ]; then - rm -rf $SNAPPY_VERSION - tar xfz $DL/$SNAPPY_VERSION.tar.gz -fi - -DIST=$(pwd)/snappy/snappy-$PLATFORM -rm -rf $DIST -mkdir -p $DIST -cd $SNAPPY_VERSION -echo 'OPTIONS' CC=$CC LD=$LD AR=$AR RANLIB=$RANLIB host_opt=$host_opt targ_opt=$targ_opt -export CFLAGS="$PLATFORM_FLAGS $OTHER_COMPILER_FLAGS $LIB_OPT_LEVEL $LIB_FPIC" -echo 'CFLAGS' $CFLAGS -export CXXFLAGS="$CFLAGS $CXX_COMPILER_FLAGS" -./configure --prefix=$DIST $host_opt $targ_opt --enable-static --disable-shared -make -make install -exit 0 diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/asio/CMakeLists.txt b/Sources/OpenVPN3/deps/vcpkg-ports/asio/CMakeLists.txt deleted file mode 100644 index 6bdb490..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/asio/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.8) -project(asio) - -add_library(asio INTERFACE) - -# Export target -install(TARGETS asio - EXPORT asio - INCLUDES DESTINATION include/ -) - -install(EXPORT asio - DESTINATION "share/asio" - FILE asio-targets.cmake -) - -install(DIRECTORY - asio/include/asio - DESTINATION include/ - FILES_MATCHING - PATTERN "*.hpp" - PATTERN "*.ipp" -) - -install(FILES - asio/include/asio.hpp - DESTINATION include/ -) diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/asio/CONTROL b/Sources/OpenVPN3/deps/vcpkg-ports/asio/CONTROL deleted file mode 100644 index d7f3988..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/asio/CONTROL +++ /dev/null @@ -1,4 +0,0 @@ -Source: asio -Version: 1.14.0-1 -Homepage: https://github.com/chriskohlhoff/asio -Description: Asio is a cross-platform C++ library for network and low-level I/O programming that provides developers with a consistent asynchronous model using a modern C++ approach. diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/asio/asio-config.cmake b/Sources/OpenVPN3/deps/vcpkg-ports/asio/asio-config.cmake deleted file mode 100644 index 6e53250..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/asio/asio-config.cmake +++ /dev/null @@ -1,6 +0,0 @@ -include ("${CMAKE_CURRENT_LIST_DIR}/asio-targets.cmake") -add_library(asio::asio INTERFACE IMPORTED) -target_link_libraries(asio::asio INTERFACE asio) - -get_target_property(_ASIO_INCLUDE_DIR asio INTERFACE_INCLUDE_DIRECTORIES) -set(ASIO_INCLUDE_DIR "${_ASIO_INCLUDE_DIR}") diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/asio/portfile.cmake b/Sources/OpenVPN3/deps/vcpkg-ports/asio/portfile.cmake deleted file mode 100644 index f19357c..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/asio/portfile.cmake +++ /dev/null @@ -1,39 +0,0 @@ -#header-only library -include(vcpkg_common_functions) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO chriskohlhoff/asio - REF asio-1-14-0 - SHA512 056ef5b0fe7def4fb5c8b176a1469658150b38110cc40825f2b07a7dd4c7b1800445e438c06a753d6a006aef6045789134b0ab32b1b74643fb287ee5a8f85fb9 - HEAD_REF master - PATCHES - ..\\..\\asio\\patches\\0001-Added-Apple-NAT64-support-when-both-ASIO_HAS_GETADDR.patch - ..\\..\\asio\\patches\\0002-Added-randomize-method-to-asio-ip-tcp-resolver-resul.patch - ..\\..\\asio\\patches\\0003-Added-user-code-hook-async_connect_post_open-to-be-c.patch - ..\\..\\asio\\patches\\0004-error_code.ipp-Use-English-for-Windows-error-message.patch -) - -# Always use "ASIO_STANDALONE" to avoid boost dependency -file(READ "${SOURCE_PATH}/asio/include/asio/detail/config.hpp" _contents) -string(REPLACE "defined(ASIO_STANDALONE)" "!defined(VCPKG_DISABLE_ASIO_STANDALONE)" _contents "${_contents}") -file(WRITE "${SOURCE_PATH}/asio/include/asio/detail/config.hpp" "${_contents}") - -# CMake install -file(COPY ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt DESTINATION ${SOURCE_PATH}) -vcpkg_configure_cmake( - SOURCE_PATH ${SOURCE_PATH} - PREFER_NINJA -) -vcpkg_install_cmake() - -vcpkg_fixup_cmake_targets(CONFIG_PATH "share/asio") -file(INSTALL - ${CMAKE_CURRENT_LIST_DIR}/asio-config.cmake - DESTINATION ${CURRENT_PACKAGES_DIR}/share/asio/ -) -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug) - -# Handle copyright -file(INSTALL ${SOURCE_PATH}/asio/LICENSE_1_0.txt DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) - diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/CONTROL b/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/CONTROL deleted file mode 100644 index 31e56c9..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/CONTROL +++ /dev/null @@ -1,4 +0,0 @@ -Source: mbedtls -Version: 2.7.12-1 -Homepage: https://github.com/ARMmbed/mbedtls -Description: An open source, portable, easy to use, readable and flexible SSL library diff --git a/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/portfile.cmake b/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/portfile.cmake deleted file mode 100644 index c4bf2e5..0000000 --- a/Sources/OpenVPN3/deps/vcpkg-ports/mbedtls/portfile.cmake +++ /dev/null @@ -1,31 +0,0 @@ -include(vcpkg_common_functions) - -set(VCPKG_LIBRARY_LINKAGE static) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO ARMmbed/mbedtls - REF mbedtls-2.7.12 - SHA512 bfad5588804e52827ecba81ca030fe570c9772f633fbf470d71a781db4366541da69b85ee10941bf500a987c4da825caa049afc2c0e6ec0ecc55d50efd74e5a6 - HEAD_REF master - PATCHES - ..\\..\\mbedtls\\patches\\0001-relax-x509-date-format-check.patch - ..\\..\\mbedtls\\patches\\0002-Enable-allowing-unsupported-critical-extensions-in-r.patch - ..\\..\\mbedtls\\patches\\0003-fix-gcc-android-build.patch -) - -vcpkg_configure_cmake( - SOURCE_PATH ${SOURCE_PATH} - PREFER_NINJA - OPTIONS - -DENABLE_TESTING=OFF - -DENABLE_PROGRAMS=OFF -) - -vcpkg_install_cmake() - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/mbedtls RENAME copyright) - -vcpkg_copy_pdbs() diff --git a/Sources/OpenVPN3/doc/openvpn-protocol-extensions.txt b/Sources/OpenVPN3/doc/openvpn-protocol-extensions.txt deleted file mode 100644 index 593fd04..0000000 --- a/Sources/OpenVPN3/doc/openvpn-protocol-extensions.txt +++ /dev/null @@ -1,198 +0,0 @@ -OpenVPN Protocol extensions -2015-01-06 - -1. DATA_V2 opcode with 24-bit peer ID - - * The DATA_V2 opcode is 9. - * The DATA_V2 opcode/key_id byte is followed by 3 additional - (network endian) bytes indicating the peer ID. - * If a 4-byte DATA_V2 header is passed through ntohl, - the resulting high 8 bits will be the DATA_V2 opcode/key_id, - and the lower 24 bits will be the peer ID. - * A disabled peer ID is denoted by 0xFFFFFF. - * Server tells the client to use DATA_V2/peer_id by pushing - the directive "peer-id ID" where ID is a decimal integer - in the range [-1, 16777215]. Setting the peer ID to -1 - transmits DATA_V2 packets with the peer ID field set to - 0xFFFFFF. Setting the peer_id to -1 is the same as - setting it to 16777215 (i.e. 0xFFFFFF). - * Client never transmits DATA_V2 packets unless the server - has pushed a "peer-id" directive. - * Server never pushes a "peer-id" directive unless the - client has indicated its support for DATA_V2 by - including "IV_PROTO=2" in the peer info data. - * When DATA_V2 is used for "float" functionality, the server - must perform the following checks before allowing - a client to float, i.e. to assume a new source address. - (a) verify integrity (HMAC or GCM auth tag, replay - protection, etc.) of the DATA_V2 packet, and - (b) ensure that the float doesn't clobber a pre-existing - client (i.e. if the address floated to is already - owned by another client) unless it can be verified - that the pre-existing client is a previous instance - of the floating client. - -2. AEAD mode - - To support AEAD crypto modes such as AES-GCM, some protocol - changes are in order. AES-GCM, for example, requires a 12 - byte unique nonce for every packet. I would propose that 4 - bytes be taken from the Packet ID which increments for every - packet and therefore provides uniqueness. The remaining 8 - bytes would be derived from the random key material that would - normally be used to key the HMAC key. This is possible since - AEAD modes use a combined key for encryption and integrity - checking, therefore the random key material for HMAC is - unused and can be repurposed as an AEAD nonce source. The 8 - byte nonce component derived from the HMAC keying material - would remain constant for a given Key State. Only the 4 byte - Packet ID would increment for each packet. Because AEAD - encryption can be compromised if the nonce ever repeats for - a given key, the implementation MUST disable encryption - for a key if the 32-bit packet ID wraps. In practical usage, - renegotiation usually preempts wrapping, so the - disable-encryption-on-wrap feature is a failsafe. - - AEAD Nonce: - - [ Packet ID ] [ HMAC keying material ] - [ 4 bytes ] [ 8 bytes ] - [ AEAD nonce total: 12 bytes ] - - TLS wire protocol: - - [ DATA_V2 opcode ] [ Packet ID ] [ AEAD Auth tag ] [ ciphertext ] - [ 4 bytes ] [ 4 bytes ] [ 16 bytes ] - [ AEAD additional data (AD) ] - - Static Key wire protocol: - - [ DATA_V2 opcode ] [ Packet ID ] [ Nonce tail (random) ] [ AEAD Auth tag ] [ ciphertext ] - [ AEAD nonce ] - [ 4 bytes ] [ 8 bytes ] [ 4 bytes ] [ 16 bytes ] - [ AEAD additional data (AD) ] - - Note that the AEAD additional data (AD) includes all data - preceding the AEAD Auth tag including the DATA_V2/peer_id - opcode and packet ID. - - Also, note that because the HMAC keying material used to derive - the last 8 bytes of the AEAD nonce is negotiated once per key - as part of the control channel handshake, we can omit it from the - data channel packets, thereby saving 8 bytes per packet. So - only the 4-byte Packet ID component of the nonce must be - transmitted with every packet. - - When negotiating AEAD mode, the client indicates its support - of AES-128-GCM, AES-192-GCM, and AES-192-GCM by including: - - IV_NCP=2 - - in the peer info string (NCP stands for Negotiable Crypto - Parameters). - - When the IV_NCP value is 2 or higher, it indicates that - the server may push an AEAD "cipher" directive, e.g.: - - push "cipher AES-128-GCM" - - In the future, the IV_NCP value (2 in the current - implementation) may be increased to indicate the - availability of additional negotiable ciphers. - -3. Compression V2 - - I have observed that compression in many cases, even when - enabled, often does not produce packet size reduction - because much of the packet data typically generated by web - sessions is already compressed. Further, the single byte that - precedes the packet and indicates whether or not compression - occurred has the unfortunate side effect of misaligning the IP - packet in cases where compression did not occur. To remedy this, - I propose a Compression V2 header that is optimized for the - case where compression does not occur. - - a. No compression occurred and first byte of IP/Ethernet packet - is NOT 0x50 (0 bytes of overhead and maintains alignment): - - [ uncompressed IP/Ethernet packet ] - - b. No compression occurred and first byte of IP/Ethernet packet - is 0x50 (2 bytes of overhead but unlikely since no known - IP packet can begin with 0x50): - - [ 0x50 ] [ 0x00 ] [ uncompressed IP/Ethernet packet ] - - c. Compression occurred (2 bytes of overhead): - - [ 0x50 ] [ compression Alg ID byte ] [ compressed IP/Ethernet packet ] - - Compression Alg ID is one-byte algorithm identifier - for LZ4 (0x1), LZO (0x2), or Snappy (0x3). - - This approach has several beneficial effects: - - 1. In the common case where compression does not occur, no - compression op is required, therefore there is zero overhead. - - 2. When compression does not occur, the IP/Ethernet packet - alignment is retained. - - 3. This technique does not require any byte swapping with - the tail of the packet which can potentially incur an - expensive cache miss. - - When negotiating Compression V2 mode, the client indicates its - support by including the following in the peer info string: - - IV_LZ4v2=1 -> LZ4 compression available in V2 format - IV_COMP_STUBv2=1 -> stub compression available in V2 format - (i.e. disable compression but still - retain compression framing) - - In response, the server can push to the client: - - push "compress lz4-v2" -> enable LZ4 compression in V2 format - - or - - push "compress stub-v2" -> disable compression but retain - compression framing in V2 format - -4. TCP nonlinear mode - - The OpenVPN 2.x packet ID and replay protection code, when running - in TCP mode, requires that the packet ID follows a linearly - incrementing sequence, i.e. 1, 2, 2, 3, ... This was a reasonable - requirement, since the reliable nature of TCP guaranteed that a - linear sequence of packet IDs transmitted by the sender would be - received in the same order by the receiver. - - However, recent work has shown that multithreaded OpenVPN servers - may not be able to guarantee TCP packet ID linearity (on the - transmit side) without incurring a performance penalty. This - is because the packet ID for transmitted packets must be allocated - before the packet is encrypted, while a multithreaded OpenVPN server - might be concurrently encrypting and transmitting multiple packets - using different threads, where the order that the threads complete - encryption and transmit the packet is non-deterministic. This - non-deterministic ordering of packets over the TCP session means - that the client might see out-of-order packets and a non-linear - packet ID progression, just as clients now see with UDP. - - My proposed solution to the issue is to relax the Packet ID - validation on the receiver side to allow non-linear packet ID - sequences, even in TCP mode. This essentially means that the - packet ID validation logic is now the same for both UDP and TCP. - - The client indicates its ability to process non-linear packet - ID sequences in TCP mode by including the following in the - peer info string: - - IV_TCPNL=1 -> TCP non-linear receiver supported - - When the server receives a IV_TCPNL setting of 1 from the - client, it may transmit out-of-order packets in TCP mode. - Otherwise, servers must use other means (such as using thread - synchronization primitives) to ensure strictly linear packet - ID ordering in TCP mode. diff --git a/Sources/OpenVPN3/doc/webauth.md b/Sources/OpenVPN3/doc/webauth.md deleted file mode 100644 index 1e44533..0000000 --- a/Sources/OpenVPN3/doc/webauth.md +++ /dev/null @@ -1,363 +0,0 @@ -Contents of this documents -========================== -This document describes various web based protocols that are used together with OpenVPN. -They are not part of core protocol of OpenVPN but are extremely closely related. -Interoperability between products building on OpenVPN is expected, so products -are expect to implement web based mechanisms according to this specification. - -This document has a three parts: The first focuses web based authentication during -connection (AUTH_PENDING). The second describes standardised -endpoints for client applications to retrieve a client profile. And final third section -describes a simpler REST based interface that OpenVPN Connect Client and Access Server use to -download profiles to the client with minimal user interaction. - -OpenVPN web auth protocol during Connect -======================================== - -This document describes the assumption and what client and server should implement -to facilitate a web based second factor login for OpenVPN. - -Triggering web based authentication ------------------------------------ - -To trigger web based authentication the client needs to signal its ability with `IV_SSO` and -the server needs to send the url to the client. The details are documented in -https://github.com/OpenVPN/openvpn/blob/master/doc/management-notes.txt -and are outside the scope of this document. - -Receiving a OPEN_URL request ----------------------------- - -When the client receives an `OPEN_URL` request to continue the authentication via web based -authentication the client should directly open the web page or prompt the user to open -the web page. This can be either can in an internal browser windows/webview or open the -web page in an external browser. A web based login should be able to handle both cases. - -There is a special "initially hidden" mode that is explained in the internal webview section. - -Auth-token usage ----------------- - -The server side should try to minimize the number of web based authentication requests -to the client. This helps avoid issues when the client cannot reach the authentication -portal during reconnect in addition to avoid disturbing the user with authentication -requests in the web views. This disturbance will be even more annoying when an external -browser window is opened by a client app not having the user's focus. - -To avoid this, the server should send an authentication token to the client -(see `--auth-token` and `--auth-gen-token` in the OpenVPN man page as well as -`doc/management-notes.txt`). When the server sends an authentication token to the client, -the client will use that token instead of normal user credentials for the succeeding -authentication requests, for as long as the token is considered valid by the server. - -Internal webview integration API --------------------------------- - -When the application uses an internal browser for web login process the API -allows tighter integration of the login. The application should append a -`embedded=true` parameter to the URL provided by the server to indicate the request -is made from an internal webview. The server may choose to serve a web page that -integrates better into the flow of an app or ignore the parameter. - -Initial hiding of a webview ---------------------------- - -There are situations where initially hiding the webview is desirable. Mainly when relying -on persistent storage/cookies on the client webview to determine if user input is required -or not. Starting all web auth hidden would break web login pages that are not specifically -designed to work with OpenVPN. Therefore this feature must be implemented strictly as opt-in. -To enable this mode the url should have the parameter `OVPN_WEBVIEW_HIDDEN=1` as parameter in -the url. When a client implements this mode it must also implement the State API to allow -the web page to show the webview. A web login must not depend on the feature being present. - -State API ---------- -This API is optional on both server and client side. Neither should the client side assume -that this API will be used during login process (unless `OVPN_WEBVIEW_HIDDEN=1` is used) -nor should the server side assume that this API is present. - -The reason to make this API optional on the client side is that client are allowed to open -the URL in the default browser of the user that has no specific OpenVPN support. On the server -side any identity provider should be able to be used. Unless the IdP is tightly integrated/designed -for OpenVPN web auth, it will not support the State API. - -To communicate the current state of the web based login with an application that -implements an internal webview, the web page should use a JavaScript mechanism based on -[postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). - -The wep page should send events with either appEvent.postMessage if appEvent exists and -window.parent.postMessage otherwise. The data is a JSON dictionary with `type` and an optional -`data` key if needed. - - appEvent.postMessage({"type": , "data": }) - -The approach of first trying to use `appEvent` and otherwise `window.parent` is to maximise -compatibility with various webview implementations. - -The events that are defined are: - -For events where `data` is not defined, the `data` field is reserved and a client should ignore -it when present. - -- `ACTION_REQUIRED`: This signal to the client that a user input is required. - - If the webview is currently hidden, the webview needs to be shown to the user. - - This event can be ignored if the client does not implement the hidden initial webview. - -- `CONNECT_SUCCESS` and `CONNECT_FAILED`: The web login process was successful/failed. For the logic of the - application this state is just informal and can be shown in the VPN connection progress. The real - success/failure condition is determined by the VPN connection succeeding/failing. - - The application should close the webview on receiving this event. - -- `LOCATION_CHANGE`: This notifies the internal webview to change the title to the provided title as - string in `data`, for example - - {"type": "LOCATION_CHANGE", "data": "Flower power VPN login step 2/3"} - - Web pages also need to implement the traditional changing of the web page to change the title when - the page is opening in an external browser. - - -Certificate checks ------------------- -A client must implement certificate checks. It is recommended to implement a a user dialog -step where the user is presented the subject information of an unknown certificate, which -the user can choose to accept or reject. - -The client profile may also contain an embedded custom CA certificate. These CA certificates -should be considered trustworthy without interaction from the user. The embedded custom -certificate are included in the client profile like this: - - # OVPN_ACCESS_SERVER_WEB_CA_BUNDLE_START - # -----BEGIN CERTIFICATE----- - # [...] - # -----END CERTIFICATE----- - # OVPN_ACCESS_SERVER_WEB_CA_BUNDLE_STOP - -Profile download -================ - -There are two possible ways users may be provided client profiles: Browser based download -interface and a generic direct download interface. The browser based interface is best suited -for implementations providing an embedded browser experience, where the app can pick up the -downloaded file and parse it further. The browser based interface is also useful when the server -can provide different client profiles for various server regions. The generic direct download API -will not require any user interaction and the received client profile can be parsed instantly. - - -Web based profile download -========================== - - -This API is intended to provide a uniform way for client to initiate the download of a profile -and have the login/download process performed through a webview. For an internal webview -the state API provides event to automatically trigger the import of a profile. If an external -browser the OpenVPN profile should be offered as download with be content-type -`application/x-openvpn-profile`. - -Detection of web based profile download support ------------------------------------------------ - -The classic way of a downloading profiles is outlined in the next section. To determine -what method has to be used to download a profile from a server, the client should do -a `HEAD` or `GET` request to `https://servername/openvpn-api/profile`. If the response -contains a header `Ovpn-WebAuth` with any value, the web based method should be used. - -The header `Ovpn-WebAuth` has the following format: - - Ovpn-WebAuth: providername,flags - -The flags are also comma separated values. Currently the only flag that is defined is - - * hidden-webview Starts the webview in hidden mode. See the web auth section for more details - -In general websites should also report ovpn-webauth without `embedded=true` parameter to allow -clients without internal browser support to craft a url to open in an external browser that -contains the additional parameters like `deviceID` and indicates `tls-cryptv2` support. - -To start the web based method the client should load the url - - https://servername/openvpn-api/profile - -with the following optional parameters: - -- `deviceID` unique device ID, must be identical with the ID provided with `IV_HWADDR` if provided -- `deviceModel` model of connected device -- `deviceOS` OS version of connected device -- `appVersion` Version of OpenVPN client -- `embedded` Request is made from an internal webview. The server may choose to serve a - web page that integrates better into the flow of an app or ignore the parameter. -- `tls-cryptv2` Should be set to 1 if the client supports tls-crypt-v2 -- `auth=method` The app supports the auth specified AUTH_PENDING authentication method. The parameter - can be specified multiple times. The values for the method parameter - are the same as in the `IV_SSO` parameter. For example an app supporting text based - challenge response and the web based authentication would add - `auth=crtext&auth=openurl` to the request. - -State API ---------- - -The state API is identical to the API used during connection. The web page can -also use the `LOCATION_CHANGED` event and additionally should provide the following -events. - - - `PROFILE_DOWNLOAD_FAILED`: The process in the web page to download the profile was unsuccessful. - The client should close the webview. - - `PROFILE_DOWNLOAD_SUCCESS`: Download a of profile worked. The client should import the profile - in the next step. `data` will contain the profile as json object with `profile` and `title` as - keys. `profile` will contain the ovpn profile and title will have a suggested title - for the new profile: - - {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile>", "title": ""}} - - To allow a client to connect directly after downloading a profile without requiring a - web authentication on the first the connect, the two optional keys `vpn-session-user` - and `vpn-session-token` can be present that act as `the auth-token` to be used on - the first connect. These keys are not base64 encoded (unlike in the REST based download) - since JSON has proper escaping: - - {"type": "PROFILE_DOWNLOAD_SUCCESS", "data": {"profile": "<.ovpn profile content>", "vpn-session-user": "foo\'bar", "vpn-session-token": "AT-123456789"}} - - The implementation of `vpn-session-token` and `vpn-session-user` is optional but strongly - recommended to improve user experience. - -REST profile download API -========================= -REST is a simple and more lightweight interface to download profiles. -This is currently mainly implemented by OpenVPN Access Server API and -Connect clients but can also be implemented by other server and clients. -The endpoint is https://servername/rest/methodname - -Basic API ------------ -Access server calls profile that require username and password Userlogin -profile and profile without Autologin. This is also replicated in the -method name (`rest/GetAutologin` or `rest/GetUserlogin`) in the request URL. -The configuration file is returned as a `text/plain` HTTP document (Note: this -in contrast to the right type `application/x-openvpn-profile`). Credentials -are specified using HTTP Basic Authentication. The REST API is implemented -through an SSL web server. The client must do the normal SSL certificate check -but should also allow a user to pin a self-signed certificate. - -The client should also indicate support supported features that influence -profile generation and cannot be negotiated by the VPN protocol. -Currently only TLS Crypt V2 support indicated by adding a tls-cryptv2=1 -to the request - -Typically a client app will present a username and password input field and -checkbox to enable/disable autologin. - -To get the Autologin configuration using curl (from a client without tls-cryptv2 support): - - $ curl -u USERNAME:PASSWORD https://asdemo.openvpn.net/rest/GetAutologin - -To get the Userlogin (requiring authentication) configuration using curl, indicating -that the client supports tls crypt v2 - - $ curl -u USERNAME:PASSWORD https://asdemo.openvpn.net/rest/GetUserlogin?tls-cryptv2=1&action=import - -Additional for User login profiles headers to initiate a direct VPN are provided to avoid -double 2FA login in a short amount of time: - - VPN-Session-User: base64_encoded_user - VPN-Session-Token: base64_encoded_pw - -These parameters are optional but should be used as VPN session user and token when -initiating a connection directly after downloading a profile. - -Error reporting with Rest API ------------------------------ - -Internally OpenVPN Access server used XMLRPC when this and the current -implementation did not properly account for this, so error reporting is -done with xml replies. This is an unfortunate design/implementation detail. -So the rest error replies look more like XMLRPC errors than rest error. -They carry a HTTP error status. - -Authentication failed (bad USERNAME or PASSWORD): - - <?xml version="1.0" encoding="UTF-8"?> - <Error> - <Type>Authorization Required</Type> - <Synopsis>REST method failed</Synopsis> - <Message>AUTH_FAILED: Server Agent XML method requires authentication (9007)</Message> - </Error> - -User does not have permission to use an Autologin profile: - - <?xml version="1.0" encoding="UTF-8"?> - <Error> - <Type>Internal Server Error</Type> - <Synopsis>REST method failed</Synopsis> - <Message>NEED_AUTOLOGIN: User 'USERNAME' lacks autologin privilege (9000)</Message> - </Error> - -User is not enrolled through the WEB client yet: - - <?xml version="1.0" encoding="UTF-8"?> - <Error> - <Type>Access denied</Type> - <Synopsis>REST method failed</Synopsis> - <Message>You must enroll this user in Authenticator first before you are allowed to retrieve a connection profile. (9008)</Message> - </Error> - -Challenge/response authentication ---------------------------------- -The challenge/response protocol for the Rest web api mirrors the approach -taken by the old (non using AUTH-PENDING,cr-response) challenge/response -of the OpenVPN protocol. - -When the server issues a challenge to the authentication -request. For example suppose we have a user called 'test' and a password -of 'mypass". Get the OpenVPN config file: - - curl -u test:mypass https://ACCESS_SERVER/rest/GetUserlogin - -But instead of immediately receiving the config file, -we might get a challenge instead: - - <Error> - <Type>Authorization Required</Type> - <Synopsis>REST method failed</Synopsis> - <Message>CRV1:R,E:miwN39AlF4k40Fd8X8r9j74FuOoaJKJM:dGVzdA==:Turing test: what is 1 x 3? (9007)</Message> - </Error> - - -a challenge is indicated by the "CRV1:" prefix in the <Message> (meaning -Challenge Response protocol Version 1). The CRV1 message is formatted -as follows: - - CRV1:<flags>:<state_id>:<username_base64>:<challenge_text> - -`flags` : a series of optional, comma-separated flags: - - `E` : echo the response when the user types it - - `R` : a response is required - -`state_id`: an opaque string that should be returned to the server -along with the response. - -`username_base64` : the username formatted as base64 - -`challenge_text` : the challenge text to be shown to the user - -After showing the challenge_text and getting a response from the user -(if `R` flag is specified), the client should resubmit the REST -request with the `USERNAME:PASSWORD` field in the HTTP header set -as follows: - - <username decoded from username_base64>:CRV1::<state_id>::<response_text> - -Where state_id is taken from the challenge request and `response_text` -is what the user entered in response to the `challenge_text`. -If the `R` flag is not present, `response_text` may be the empty -string. - -Using curl to respond to the turing test given in the example above: - - curl -u "test:CRV1::miwN39AlF4k40Fd8X8r9j74FuOoaJKJM::3" https://ACCESS_SERVER/rest/GetUserlogin - -If the challenge response (In this case '3' in response to the turing -test) is verified by the server, it will then return the configuration -file per the GetUserlogin method. diff --git a/Sources/OpenVPN3/docker-build.sh b/Sources/OpenVPN3/docker-build.sh deleted file mode 100755 index 97bbe21..0000000 --- a/Sources/OpenVPN3/docker-build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -# build ovpn3-core with system-provided mbedtls and lz4 on various linux distros - -docker build -f dockerfiles/Dockerfile.debian -t deb . -docker run -it deb - -docker build -f dockerfiles/Dockerfile.ubu -t ubu . -docker run -it ubu - -docker build -f dockerfiles/Dockerfile.centos -t cnt . -docker run -it cnt diff --git a/Sources/OpenVPN3/dockerfiles/Dockerfile.centos b/Sources/OpenVPN3/dockerfiles/Dockerfile.centos deleted file mode 100644 index 32d1088..0000000 --- a/Sources/OpenVPN3/dockerfiles/Dockerfile.centos +++ /dev/null @@ -1,19 +0,0 @@ -FROM centos/devtoolset-7-toolchain-centos7 - -USER 0 -RUN yum -y update && yum -y install epel-release && \ - yum -y install -y mbedtls-devel lz4-devel git wget perl-Digest-SHA make - -ADD . /ovpn3/core - -ENV O3 /ovpn3/ -ENV DEP_DIR /ovpn3/deps -ENV DL /ovpn3/dl - -CMD mkdir $DEP_DIR && mkdir $DL && \ - /ovpn3/core/scripts/linux/build-all && \ - cd $O3/core/test/ovpncli && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ - cd $O3/core/test/ssl && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ - ./proto diff --git a/Sources/OpenVPN3/dockerfiles/Dockerfile.debian b/Sources/OpenVPN3/dockerfiles/Dockerfile.debian deleted file mode 100644 index 3aaceaa..0000000 --- a/Sources/OpenVPN3/dockerfiles/Dockerfile.debian +++ /dev/null @@ -1,17 +0,0 @@ -FROM debian:9 - -RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev - -ADD . /ovpn3/core - -ENV O3 /ovpn3/ -ENV DEP_DIR /ovpn3/deps -ENV DL /ovpn3/dl - -CMD mkdir $DEP_DIR && mkdir $DL && \ - /ovpn3/core/scripts/linux/build-all && \ - cd $O3/core/test/ovpncli && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ - cd $O3/core/test/ssl && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ - ./proto diff --git a/Sources/OpenVPN3/dockerfiles/Dockerfile.ubu b/Sources/OpenVPN3/dockerfiles/Dockerfile.ubu deleted file mode 100644 index 1502a28..0000000 --- a/Sources/OpenVPN3/dockerfiles/Dockerfile.ubu +++ /dev/null @@ -1,17 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y autoconf build-essential wget git liblz4-dev libmbedtls-dev - -ADD . /ovpn3/core - -ENV O3 /ovpn3/ -ENV DEP_DIR /ovpn3/deps -ENV DL /ovpn3/dl - -CMD mkdir $DEP_DIR && mkdir $DL && \ - /ovpn3/core/scripts/linux/build-all && \ - cd $O3/core/test/ovpncli && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build cli && \ - cd $O3/core/test/ssl && \ - ECHO=1 PROF=linux ASIO=1 MTLS_SYS=1 LZ4_SYS=1 NOSSL=1 $O3/core/scripts/build proto && \ - ./proto diff --git a/Sources/OpenVPN3/javacli/.gitignore b/Sources/OpenVPN3/javacli/.gitignore deleted file mode 100644 index 2ae5f45..0000000 --- a/Sources/OpenVPN3/javacli/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -build -ovpncli_wrap.cxx -ovpncli_wrap.h -ovpncli.java -ovpncliJNI.java -ClientAPI_*.java -SWIGTYPE_*.java diff --git a/Sources/OpenVPN3/javacli/Client.java b/Sources/OpenVPN3/javacli/Client.java deleted file mode 100644 index 9328ea9..0000000 --- a/Sources/OpenVPN3/javacli/Client.java +++ /dev/null @@ -1,143 +0,0 @@ -// 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-2020 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/>. - -// TESTING_ONLY - -public class Client implements OpenVPNClientThread.EventReceiver { - private OpenVPNClientThread client_thread; - - public static class ConfigError extends Exception { - public ConfigError(String msg) { super(msg); } - } - - public static class CredsUnspecifiedError extends Exception { - public CredsUnspecifiedError(String msg) { super(msg); } - } - - // Load OpenVPN core (implements ClientAPI_OpenVPNClient) from shared library - static { - System.loadLibrary("ovpncli"); - String test = ClientAPI_OpenVPNClient.crypto_self_test(); - System.out.format("CRYPTO SELF TEST: %s", test); - } - - public Client(String config_text, String username, String password) throws ConfigError, CredsUnspecifiedError { - // init client implementation object - client_thread = new OpenVPNClientThread(); - - // load/eval config - ClientAPI_Config config = new ClientAPI_Config(); - config.setContent(config_text); - config.setCompressionMode("yes"); - ClientAPI_EvalConfig ec = client_thread.eval_config(config); - if (ec.getError()) - throw new ConfigError("OpenVPN config file parse error: " + ec.getMessage()); - - // handle creds - ClientAPI_ProvideCreds creds = new ClientAPI_ProvideCreds(); - if (!ec.getAutologin()) - { - if (username.length() > 0) - { - creds.setUsername(username); - creds.setPassword(password); - creds.setReplacePasswordWithSessionID(true); - } - else - throw new CredsUnspecifiedError("OpenVPN config file requires username/password but none provided"); - } - client_thread.provide_creds(creds); - } - - public void connect() { - // connect - client_thread.connect(this); - - // wait for worker thread to exit - client_thread.wait_thread_long(); - } - - public void stop() { - client_thread.stop(); - } - - public void show_stats() { - int n = client_thread.stats_n(); - for (int i = 0; i < n; ++i) - { - String name = client_thread.stats_name(i); - long value = client_thread.stats_value(i); - if (value > 0) - System.out.format("STAT %s=%s%n", name, value); - } - } - - @Override - public void event(ClientAPI_Event event) { - boolean error = event.getError(); - String name = event.getName(); - String info = event.getInfo(); - System.out.format("EVENT: err=%b name=%s info='%s'%n", error, name, info); - } - - // Callback to get a certificate - @Override - public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { - req.setError(true); - req.setErrorText("cert request failed: external PKI not implemented"); - } - - // Callback to sign data - @Override - public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { - req.setError(true); - req.setErrorText("sign request failed: external PKI not implemented"); - } - - @Override - public void log(ClientAPI_LogInfo loginfo) { - String text = loginfo.getText(); - System.out.format("LOG: %s", text); - } - - @Override - public void done(ClientAPI_Status status) { - System.out.format("DONE ClientAPI_Status: err=%b msg='%s'%n", status.getError(), status.getMessage()); - } - - @Override - public boolean socket_protect(int socket) - { - return false; - } - - @Override - public boolean pause_on_connection_timeout() - { - return false; - } - - @Override - public OpenVPNClientThread.TunBuilder tun_builder_new() - { - return null; - } - } diff --git a/Sources/OpenVPN3/javacli/Main.java b/Sources/OpenVPN3/javacli/Main.java deleted file mode 100644 index 5ac3d9c..0000000 --- a/Sources/OpenVPN3/javacli/Main.java +++ /dev/null @@ -1,97 +0,0 @@ -// 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-2020 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/>. - -// TESTING_ONLY - -import java.io.*; -import java.nio.charset.Charset; - -public class Main { - // utility method to read a file and return as a String - public static String readFile(String filename) throws IOException { - return readStream(new FileInputStream(filename)); - } - - private static String readStream(InputStream stream) throws IOException { - // No real need to close the BufferedReader/InputStreamReader - // as they're only wrapping the stream - try { - Reader reader = new BufferedReader(new InputStreamReader(stream)); - StringBuilder builder = new StringBuilder(); - char[] buffer = new char[4096]; - int read; - while ((read = reader.read(buffer, 0, buffer.length)) > 0) { - builder.append(buffer, 0, read); - } - return builder.toString(); - } finally { - // Potential issue here: if this throws an IOException, - // it will mask any others. Normally I'd use a utility - // method which would log exceptions and swallow them - stream.close(); - } - } - - public static void main(String[] args) throws IOException, Client.ConfigError, Client.CredsUnspecifiedError { - if (args.length >= 1) - { - // load config file - String config = readFile(args[0]); - - // get creds - String username = ""; - String password = ""; - if (args.length >= 3) - { - username = args[1]; - password = args[2]; - } - - // instantiate client object - final Client client = new Client(config, username, password); - - // catch signals - final Thread mainThread = Thread.currentThread(); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - client.stop(); - try { - mainThread.join(); - } - catch (InterruptedException e) { - } - } - }); - - // execute client session - client.connect(); - - // show stats before exit - client.show_stats(); - } - else - { - System.err.println("OpenVPN Java client"); - System.err.println("Usage: java Client <client.ovpn> [username] [password]"); - System.exit(2); - } - } -} diff --git a/Sources/OpenVPN3/javacli/OpenVPNClientThread.java b/Sources/OpenVPN3/javacli/OpenVPNClientThread.java deleted file mode 100644 index 042b931..0000000 --- a/Sources/OpenVPN3/javacli/OpenVPNClientThread.java +++ /dev/null @@ -1,359 +0,0 @@ -// 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-2020 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/>. - -// package OPENVPN_PACKAGE - -import java.util.HashSet; - -public class OpenVPNClientThread extends ClientAPI_OpenVPNClient implements Runnable { - private EventReceiver parent; - private TunBuilder tun_builder; - private Thread thread; - private ClientAPI_Status m_connect_status; - private boolean connect_called = false; - - private int bytes_in_index = -1; - private int bytes_out_index = -1; - - // thrown if instantiator attempts to call connect more than once - public static class ConnectCalledTwice extends RuntimeException { - } - - public interface EventReceiver { - // Called with events from core - void event(ClientAPI_Event event); - - // Called with log text from core - void log(ClientAPI_LogInfo loginfo); - - // Called when connect() thread exits - void done(ClientAPI_Status status); - - // Called to "protect" a socket from being routed through the tunnel - boolean socket_protect(int socket); - - // When a connection is close to timeout, the core will call this - // method. If it returns false, the core will disconnect with a - // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE - // state. - boolean pause_on_connection_timeout(); - - // Callback to construct a new tun builder - TunBuilder tun_builder_new(); - - // Callback to get a certificate - void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req); - - // Callback to sign data - void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req); - } - - public interface TunBuilder { - // Tun builder methods. - // Methods documented in openvpn/tun/builder/base.hpp - - boolean tun_builder_set_remote_address(String address, boolean ipv6); - boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30); - boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags); - boolean tun_builder_add_route(String address, int prefix_length, boolean ipv6); - boolean tun_builder_exclude_route(String address, int prefix_length, boolean ipv6); - boolean tun_builder_add_dns_server(String address, boolean ipv6); - boolean tun_builder_add_search_domain(String domain); - boolean tun_builder_set_mtu(int mtu); - boolean tun_builder_set_session_name(String name); - int tun_builder_establish(); - void tun_builder_teardown(boolean disconnect); - } - - public OpenVPNClientThread() { - final int n = stats_n(); - for (int i = 0; i < n; ++i) - { - String name = stats_name(i); - if (name.equals("BYTES_IN")) - bytes_in_index = i; - if (name.equals("BYTES_OUT")) - bytes_out_index = i; - } - } - - // start connect session in worker thread - public void connect(EventReceiver parent_arg) { - if (connect_called) - throw new ConnectCalledTwice(); - connect_called = true; - - // direct client callbacks to parent - parent = parent_arg; - - // clear status - m_connect_status = null; - - // execute client in a worker thread - thread = new Thread(this, "OpenVPNClientThread"); - thread.start(); - } - - // Wait for worker thread to complete; to stop thread, - // first call super stop() method then wait_thread(). - // This method will give the thread one second to - // exit and will abandon it after this time. - public void wait_thread_short() { - final int wait_millisecs = 5000; // max time that we will wait for thread to exit - Thread th = thread; - if (th != null) { - try { - th.join(wait_millisecs); - } - catch (InterruptedException e) { - } - - // thread failed to stop? - if (th.isAlive()) { - // abandon thread and deliver our own status object to instantiator. - ClientAPI_Status status = new ClientAPI_Status(); - status.setError(true); - status.setMessage("CORE_THREAD_ABANDONED"); - call_done(status); - } - } - } - - // Wait for worker thread to complete; to stop thread, - // first call super stop() method then wait_thread(). - // This method will wait forever for the thread to exit. - public void wait_thread_long() { - if (thread != null) { - boolean interrupted; - do { - interrupted = false; - try { - thread.join(); - } - catch (InterruptedException e) { - interrupted = true; - super.stop(); // send thread a stop message - } - } while (interrupted); - } - } - - public long bytes_in() - { - return super.stats_value(bytes_in_index); - } - - public long bytes_out() - { - return super.stats_value(bytes_out_index); - } - - private void call_done(ClientAPI_Status status) - { - EventReceiver p = finalize_thread(status); - if (p != null) - p.done(m_connect_status); - } - - private synchronized EventReceiver finalize_thread(ClientAPI_Status connect_status) - { - EventReceiver p = parent; - if (p != null) { - // save thread connection status - m_connect_status = connect_status; - - // disassociate client callbacks from parent - parent = null; - tun_builder = null; - thread = null; - } - return p; - } - - // Runnable overrides - - @Override - public void run() { - // Call out to core to start connection. - // Doesn't return until connection has terminated. - ClientAPI_Status status = super.connect(); - call_done(status); - } - - // ClientAPI_OpenVPNClient (C++ class) overrides - - @Override - public boolean socket_protect(int socket) { - EventReceiver p = parent; - if (p != null) - return p.socket_protect(socket); - else - return false; - } - - @Override - public boolean pause_on_connection_timeout() { - EventReceiver p = parent; - if (p != null) - return p.pause_on_connection_timeout(); - else - return false; - } - - @Override - public void event(ClientAPI_Event event) { - EventReceiver p = parent; - if (p != null) - p.event(event); - } - - @Override - public void log(ClientAPI_LogInfo loginfo) { - EventReceiver p = parent; - if (p != null) - p.log(loginfo); - } - - @Override - public void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req) { - EventReceiver p = parent; - if (p != null) - p.external_pki_cert_request(req); - } - - @Override - public void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req) { - EventReceiver p = parent; - if (p != null) - p.external_pki_sign_request(req); - } - - // TunBuilderBase (C++ class) overrides - - @Override - public boolean tun_builder_new() { - EventReceiver p = parent; - if (p != null) { - tun_builder = p.tun_builder_new(); - return tun_builder != null; - } else - return false; - } - - @Override - public boolean tun_builder_set_remote_address(String address, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_remote_address(address, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_address(String address, int prefix_length, String gateway, boolean ipv6, boolean net30) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_address(address, prefix_length, gateway, ipv6, net30); - else - return false; - } - - @Override - public boolean tun_builder_reroute_gw(boolean ipv4, boolean ipv6, long flags) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_reroute_gw(ipv4, ipv6, flags); - else - return false; - } - - @Override - public boolean tun_builder_add_route(String address, int prefix_length, int metric, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_route(address, prefix_length, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_exclude_route(String address, int prefix_length, int metric, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_exclude_route(address, prefix_length, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_dns_server(String address, boolean ipv6) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_dns_server(address, ipv6); - else - return false; - } - - @Override - public boolean tun_builder_add_search_domain(String domain) - { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_add_search_domain(domain); - else - return false; - } - - @Override - public boolean tun_builder_set_mtu(int mtu) { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_mtu(mtu); - else - return false; - } - - @Override - public boolean tun_builder_set_session_name(String name) - { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_set_session_name(name); - else - return false; - } - - @Override - public int tun_builder_establish() { - TunBuilder tb = tun_builder; - if (tb != null) - return tb.tun_builder_establish(); - else - return -1; - } - - @Override - public void tun_builder_teardown(boolean disconnect) { - TunBuilder tb = tun_builder; - if (tb != null) - tb.tun_builder_teardown(disconnect); - } -} diff --git a/Sources/OpenVPN3/javacli/android/cpu.cpp b/Sources/OpenVPN3/javacli/android/cpu.cpp deleted file mode 100644 index 3d557ce..0000000 --- a/Sources/OpenVPN3/javacli/android/cpu.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// 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-2020 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/>. - -#include <stdio.h> -#include <unistd.h> -#include <jni.h> - -#ifdef SWIGEXPORT -#define EXPORT SWIGEXPORT -#else -#define EXPORT -#endif - -#ifndef OPENVPN_PACKAGE_ID -#error OPENVPN_PACKAGE_ID must be defined -#endif - -#define MAKE_SYM2(pkg_id, suffix) Java_ ## pkg_id ## _CPUUsage_ ## suffix -#define MAKE_SYM(pkg_id, suffix) MAKE_SYM2(pkg_id, suffix) - -#define CPU_USAGE MAKE_SYM(OPENVPN_PACKAGE_ID, cpu_1usage) - -extern "C" { - jdouble CPU_USAGE(JNIEnv* env, jclass); -}; - -EXPORT jdouble CPU_USAGE(JNIEnv* env, jclass) -{ - char fnbuf[64]; - const pid_t pid = getpid(); - double ret = 0.0; - - snprintf(fnbuf, sizeof(fnbuf), "/proc/%u/stat", (unsigned int)pid); - FILE *fp = fopen(fnbuf, "r"); - if (fp) - { - double user = 0.0; - double system = 0.0; - if (fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lf %lf", &user, &system) == 2) - ret = (user + system) / sysconf(_SC_CLK_TCK); - fclose(fp); - } - return ret; -} diff --git a/Sources/OpenVPN3/javacli/android/jellybean_hack.cpp b/Sources/OpenVPN3/javacli/android/jellybean_hack.cpp deleted file mode 100644 index 10b70e8..0000000 --- a/Sources/OpenVPN3/javacli/android/jellybean_hack.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// 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-2020 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/>. - -// Native companion code for JellyBeanHack.java - -#include <stdio.h> -#include <dlfcn.h> -#include <jni.h> - -#include <android/log.h> - -#ifdef SWIGEXPORT -#define EXPORT SWIGEXPORT -#else -#define EXPORT -#endif - -#ifndef OPENVPN_PACKAGE_ID -#error OPENVPN_PACKAGE_ID must be defined -#endif - -#define MAKE_SYM2(pkg_id, suffix) Java_ ## pkg_id ## _JellyBeanHack_ ## suffix -#define MAKE_SYM(pkg_id, suffix) MAKE_SYM2(pkg_id, suffix) - -#define RSA_SIGN_INIT MAKE_SYM(OPENVPN_PACKAGE_ID, rsa_1sign_1init) -#define RSA_SIGN MAKE_SYM(OPENVPN_PACKAGE_ID, rsa_1sign) -#define PKEY_RETAIN MAKE_SYM(OPENVPN_PACKAGE_ID, pkey_1retain) - -extern "C" { - jint RSA_SIGN_INIT(JNIEnv* env, jclass); - jbyteArray RSA_SIGN(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef); - void PKEY_RETAIN(JNIEnv* env, jclass, jint pkeyRef); -}; - -typedef void *RSA; - -enum { - NID_md5_sha1=114, - CRYPTO_LOCK_EVP_PKEY=10, -}; - -struct EVP_PKEY -{ - int type; - int save_type; - int references; - void *ameth; - void *engine; - union { - RSA *rsa; - } pkey; -}; - -typedef int (*RSA_size_func_t)(const RSA *); - -typedef int (*RSA_sign_func_t)(int type, const unsigned char *m, unsigned int m_length, - unsigned char *sigret, unsigned int *siglen, RSA *rsa); - -typedef void (*ERR_print_errors_fp_func_t)(FILE *fp); - -typedef int (*CRYPTO_add_lock_func_t)(int *pointer, int amount, int type, const char *file, int line); - -static bool initialized; -static RSA_size_func_t RSA_size; -static RSA_sign_func_t RSA_sign; -static ERR_print_errors_fp_func_t ERR_print_errors_fp; -static CRYPTO_add_lock_func_t CRYPTO_add_lock; - -inline bool callbacks_defined() -{ - return RSA_size != NULL - && RSA_sign != NULL - && ERR_print_errors_fp != NULL - && CRYPTO_add_lock != NULL; -} - -EXPORT jint RSA_SIGN_INIT(JNIEnv* env, jclass) -{ - if (!initialized) - { - void *handle = dlopen("libcrypto.so", RTLD_NOW); - if (handle) - { - RSA_size = (RSA_size_func_t) dlsym(handle, "RSA_size"); - RSA_sign = (RSA_sign_func_t) dlsym(handle, "RSA_sign"); - ERR_print_errors_fp = (ERR_print_errors_fp_func_t) dlsym(handle, "ERR_print_errors_fp"); - CRYPTO_add_lock = (CRYPTO_add_lock_func_t) dlsym(handle, "CRYPTO_add_lock"); - } - initialized = true; - } - return callbacks_defined(); -} - -static int jni_throw(JNIEnv* env, const char* className, const char* msg) -{ - jclass exceptionClass = env->FindClass(className); - - if (exceptionClass == NULL) { - // ClassNotFoundException now pending - return -1; - } - - if (env->ThrowNew( exceptionClass, msg) != JNI_OK) { - // an exception, most likely OOM, will now be pending - return -1; - } - - env->DeleteLocalRef(exceptionClass); - return 0; -} - -EXPORT jbyteArray RSA_SIGN(JNIEnv* env, jclass, jbyteArray from, jint pkeyRef) -{ - if (!callbacks_defined()) - { - jni_throw(env, "java/lang/NullPointerException", "rsa_sign: OpenSSL callbacks undefined"); - return NULL; - } - - EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); - if (pkey == NULL || from == NULL) - { - jni_throw(env, "java/lang/NullPointerException", "rsa_sign: from/pkey is NULL"); - return NULL; - } - - jbyte* data = env->GetByteArrayElements(from, NULL); - if (data == NULL) - { - jni_throw(env, "java/lang/NullPointerException", "rsa_sign: data is NULL"); - return NULL; - } - int datalen = env->GetArrayLength(from); - - unsigned int siglen; - unsigned char* sigret = new unsigned char[(*RSA_size)(pkey->pkey.rsa)]; - - if ((*RSA_sign)(NID_md5_sha1, (unsigned char*) data, datalen, - sigret, &siglen, pkey->pkey.rsa) <= 0) - { - jni_throw(env, "java/security/InvalidKeyException", "OpenSSL RSA_sign failed"); - (*ERR_print_errors_fp)(stderr); - return NULL; - } - - jbyteArray jb = env->NewByteArray(siglen); - env->SetByteArrayRegion(jb, 0, siglen, (jbyte *)sigret); - delete [] sigret; - return jb; -} - -EXPORT void PKEY_RETAIN(JNIEnv* env, jclass, jint pkeyRef) -{ - EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef); - if (pkey && CRYPTO_add_lock) - { - const int newref = (*CRYPTO_add_lock)(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY, __FILE__, __LINE__); - __android_log_print(ANDROID_LOG_DEBUG, "openvpn", "pkey_retain ref=%d", newref); - } -} diff --git a/Sources/OpenVPN3/javacli/build-android b/Sources/OpenVPN3/javacli/build-android deleted file mode 100755 index 2fcfa40..0000000 --- a/Sources/OpenVPN3/javacli/build-android +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env bash -# generate expire time in python: time.mktime((2012, 5, 1, 0, 0, 0, 0, 0, -1)) -# -DAPP_EXPIRE_TIME=1364796000 \ -set -e - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -cd $O3/core -. vars/android-sdk-path -cd javacli -git clean -q -fXd . - -if [ "$PKG" ]; then - pkg=$PKG - pkg_id_def="-DOPENVPN_PACKAGE_ID=${PKG//./_}" -else - pkg=net.openvpn.openvpn - pkg_id_def="-DOPENVPN_PACKAGE_ID=net_openvpn_openvpn" -fi -echo PACKAGE $PKG - -if [ "$PT_PROXY" = "1" ] && [ -d "$O3/common" ]; then - common="-I$O3/common -DPRIVATE_TUNNEL_PROXY" -else - common="" -fi - -echo SWIG -swig -c++ -java -package $pkg -I$O3/core/client -I$O3/core ovpncli.i - -TARGETS=${TARGETS:-android-a7a android-a8a android-x86} - -for TARGET in $TARGETS; do - -if [ "$DEBUG_BUILD" = "1" ]; then - . ../vars/vars-${TARGET}-dbg - vis1="" - vis2="" - opt2="$pkg_id_def $LIB_OPT_LEVEL" -else - . ../vars/vars-${TARGET} - vis1="-fvisibility=hidden" - vis2='-DSWIGEXPORT=__attribute__((visibility("default")))' - opt2="$pkg_id_def -Os" -fi - -if [ "$OPENSSL" = "1" ]; then - ssl_def="-DUSE_OPENSSL" - ssl_inc="-I$DEP_DIR/openssl/openssl-$PLATFORM/include" - ssl_lib="-lssl -lcrypto" - ssl_libdir="-L$DEP_DIR/openssl/openssl-$PLATFORM/lib" -else - ssl_def="-DUSE_MBEDTLS" - ssl_inc="-I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" - ssl_lib="-lmbedtls" - ssl_libdir="-L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" -fi - -[ -z "$GPP_CMD" ] && GPP_CMD=g++ - -echo CORE $ABI -$GPP_CMD \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $OTHER_COMPILER_FLAGS \ - $LIB_OPT_LEVEL $LIB_FPIC \ - -Wall -Wno-sign-compare -Wno-unused-parameter \ - -Wno-unused-local-typedefs \ - $vis1 \ - $ssl_def \ - -DUSE_ASIO \ - -DASIO_STANDALONE \ - -DASIO_NO_DEPRECATED \ - -DHAVE_LZ4 \ - -DOPENVPN_USE_TLS_MD5 \ - -DASIO_HAS_STD_STRING_VIEW \ - -I$O3/core/client \ - -I$O3/core \ - $common \ - -I$DEP_DIR/asio/asio/include \ - $ssl_inc \ - -I$DEP_DIR/lz4/lz4-$PLATFORM/include \ - -c $O3/core/client/ovpncli.cpp - -echo WRAP $ABI -$GPP_CMD \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $OTHER_COMPILER_FLAGS \ - $opt2 $LIB_FPIC \ - -fno-strict-aliasing \ - -Wall \ - $vis1 $vis2 \ - -I$O3/core/client \ - -I$O3/core \ - $common \ - $ssl_libdir \ - -L$DEP_DIR/lz4/lz4-$PLATFORM/lib \ - ovpncli_wrap.cxx \ - android/jellybean_hack.cpp \ - android/cpu.cpp \ - ovpncli.o \ - -o libovpncli.so \ - -shared -Wl,-soname,libovpncli.so \ - $ssl_lib \ - -llz4 \ - -llog - -if [ "$DEBUG_BUILD" != "1" ]; then - echo STRIP $ABI - strip libovpncli.so -fi - -mkdir -p build/libs/$ABI -mv libovpncli.so build/libs/$ABI/ -rm ovpncli.o -done - -mv ovpncli_wrap.cxx ovpncli_wrap.h ovpncli.java ovpncliJNI.java SWIGTYPE_*.java ClientAPI_*.java build/ -git clean -q -fX . - -tar -czf android-core-build.tgz build -mv android-core-build.tgz $O3/ diff --git a/Sources/OpenVPN3/javacli/build-linux b/Sources/OpenVPN3/javacli/build-linux deleted file mode 100755 index d0e37a1..0000000 --- a/Sources/OpenVPN3/javacli/build-linux +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash - -# Build OpenVPN 3 core on Linux as a callable module from Java: -# -# ./build-linux -# java -Djava.library.path=. Main profile.ovpn - -set -e - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -TARGET=linux -JINC="-I/usr/local/java/jdk1.7.0_55/include -I/usr/local/java/jdk1.7.0_55/include/linux" - -cd $O3/core/javacli -git clean -q -fXd . -git clean -q -fd . - -if [ "$DEBUG_BUILD" = "1" ]; then - . $O3/core/vars/vars-${TARGET}-dbg - vis1="" - vis2="" - opt2="$pkg_id_def $LIB_OPT_LEVEL" -else - . $O3/core/vars/vars-${TARGET} - vis1="-fvisibility=hidden" - vis2='-DSWIGEXPORT=__attribute__((visibility("default")))' - opt2="$pkg_id_def -Os" -fi - -if [ "$OPENSSL" = "1" ]; then - ssl_def="-DUSE_OPENSSL" - ssl_inc="-I$DEP_DIR/openssl/openssl-$PLATFORM/include" - ssl_lib="-lssl -lcrypto" - ssl_libdir="-L$DEP_DIR/openssl/openssl-$PLATFORM/lib" -else - ssl_def="-DUSE_MBEDTLS" - ssl_inc="-I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" - ssl_lib="-lmbedtls" - ssl_libdir="-L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" -fi - -echo SWIG -swig -c++ -java -I$O3/core/client -I$O3/core ovpncli.i - -echo JAVA -javac *.java - -echo CORE -g++ \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $LIB_OPT_LEVEL $LIB_FPIC \ - -Wall -Werror -Wno-sign-compare -Wno-unused-parameter \ - -Wno-unused-local-typedefs \ - $vis1 \ - $ssl_def \ - -DUSE_ASIO \ - -DASIO_STANDALONE \ - -DASIO_NO_DEPRECATED \ - -DHAVE_LZ4 \ - -I$O3/core/client \ - -I$O3/core \ - -I$DEP_DIR/asio/asio/include \ - $ssl_inc \ - -I$DEP_DIR/lz4/lz4-$PLATFORM/include \ - -c $O3/core/client/ovpncli.cpp - -echo WRAP -g++ \ - $CXX_COMPILER_FLAGS \ - $PLATFORM_FLAGS \ - $opt2 $LIB_FPIC \ - -fno-strict-aliasing \ - -Wall -Werror \ - $vis1 $vis2 \ - -I$O3/core/client \ - -I$O3/core \ - $JINC \ - $ssl_libdir \ - -L$DEP_DIR/lz4/lz4-$PLATFORM/lib \ - ovpncli_wrap.cxx \ - ovpncli.o \ - -o libovpncli.so \ - -shared -Wl,-soname,libovpncli.so \ - $ssl_lib \ - -llz4 - -if [ "$DEBUG_BUILD" != "1" ]; then - echo STRIP $ABI - strip libovpncli.so -fi diff --git a/Sources/OpenVPN3/javacli/ovpncli.i b/Sources/OpenVPN3/javacli/ovpncli.i deleted file mode 100644 index 0671a6d..0000000 --- a/Sources/OpenVPN3/javacli/ovpncli.i +++ /dev/null @@ -1,55 +0,0 @@ -// SWIG interface file for OpenVPN client - -// enable director feature for OpenVPNClientBase virtual method callbacks -%module(directors="1") ovpncli -%feature("director") OpenVPNClient; - -%include "std_string.i" // for std::string typemaps -%include "std_vector.i" - -// top-level C++ implementation file -%{ -#include "ovpncli.hpp" -%} - -// ignore these ClientAPI::OpenVPNClient bases -%ignore openvpn::ClientAPI::LogReceiver; -%ignore openvpn::ExternalTun::Factory; -%ignore openvpn::ExternalTransport::Factory; - -// modify exported C++ class names to incorporate their enclosing namespace -%rename(ClientAPI_OpenVPNClient) OpenVPNClient; -%rename(ClientAPI_TunBuilderBase) TunBuilderBase; -%rename(ClientAPI_ExternalPKIBase) ExternalPKIBase; -%rename(ClientAPI_ServerEntry) ServerEntry; -%rename(ClientAPI_EvalConfig) EvalConfig; -%rename(ClientAPI_ProvideCreds) ProvideCreds; -%rename(ClientAPI_SessionToken) SessionToken; -%rename(ClientAPI_DynamicChallenge) DynamicChallenge; -%rename(ClientAPI_KeyValue) KeyValue; -%rename(ClientAPI_Config) Config; -%rename(ClientAPI_Event) Event; -%rename(ClientAPI_ConnectionInfo) ConnectionInfo; -%rename(ClientAPI_Status) Status; -%rename(ClientAPI_LogInfo) LogInfo; -%rename(ClientAPI_InterfaceStats) InterfaceStats; -%rename(ClientAPI_TransportStats) TransportStats; -%rename(ClientAPI_MergeConfig) MergeConfig; -%rename(ClientAPI_ExternalPKIRequestBase) ExternalPKIRequestBase; -%rename(ClientAPI_ExternalPKICertRequest) ExternalPKICertRequest; -%rename(ClientAPI_ExternalPKISignRequest) ExternalPKISignRequest; -%rename(ClientAPI_RemoteOverride) RemoteOverride; - -// declare vectors -namespace std { - %template(ClientAPI_ServerEntryVector) vector<openvpn::ClientAPI::ServerEntry>; - %template(ClientAPI_LLVector) vector<long long>; - %template(ClientAPI_StringVec) vector<string>; -}; - -// interface to be bridged between C++ and target language -%include "openvpn/pki/epkibase.hpp" -%include "openvpn/tun/builder/base.hpp" -%import "openvpn/tun/extern/fw.hpp" // ignored -%import "openvpn/transport/client/extern/fw.hpp" // ignored -%include "ovpncli.hpp" diff --git a/Sources/OpenVPN3/mac/.gitignore b/Sources/OpenVPN3/mac/.gitignore deleted file mode 100644 index 14ce7f3..0000000 --- a/Sources/OpenVPN3/mac/.gitignore +++ /dev/null @@ -1 +0,0 @@ -**/xcuserdata/ diff --git a/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj b/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj deleted file mode 100644 index cdd8e99..0000000 --- a/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.pbxproj +++ /dev/null @@ -1,573 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - DF28F0D422E6071900E5B24C /* ovpnagent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF28F0D322E6071900E5B24C /* ovpnagent.cpp */; }; - DF28F0D522E60BBF00E5B24C /* libjsoncpp_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF28F0C522E5E40D00E5B24C /* libjsoncpp_static.a */; }; - DF28F0D622E60BEF00E5B24C /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEA201F0DDC0003272D /* CoreServices.framework */; }; - DF28F0D722E60BF500E5B24C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE8201F0DB80003272D /* IOKit.framework */; }; - DF28F0D822E60BFD00E5B24C /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE6201F0D910003272D /* SystemConfiguration.framework */; }; - DF28F0D922E60C0700E5B24C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE4201F0D4F0003272D /* CoreFoundation.framework */; }; - DF380AE2201F0A2F0003272D /* cli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF380AE1201F0A2F0003272D /* cli.cpp */; }; - DF380AE5201F0D4F0003272D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE4201F0D4F0003272D /* CoreFoundation.framework */; }; - DF380AE7201F0D910003272D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE6201F0D910003272D /* SystemConfiguration.framework */; }; - DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AE8201F0DB80003272D /* IOKit.framework */; }; - DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEA201F0DDC0003272D /* CoreServices.framework */; }; - DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF380AEC201F0E0E0003272D /* libmbedtls.a */; }; - DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF838B402090AC2F00B68F90 /* liblz4.a */; }; - DFA442402361E2F3007ACEF6 /* libjsoncpp_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF28F0C522E5E40D00E5B24C /* libjsoncpp_static.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - DF28F0C922E5E6C600E5B24C /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - DF380AD4201F07AE0003272D /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - DF28F0C522E5E40D00E5B24C /* libjsoncpp_static.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjsoncpp_static.a; path = ../../../../../../../usr/local/lib/libjsoncpp_static.a; sourceTree = "<group>"; }; - DF28F0CB22E5E6C600E5B24C /* agent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = agent; sourceTree = BUILT_PRODUCTS_DIR; }; - DF28F0D322E6071900E5B24C /* ovpnagent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ovpnagent.cpp; path = ../../../../common/ovpnagent/mac/ovpnagent.cpp; sourceTree = "<group>"; }; - DF380AD6201F07AE0003272D /* ovpn3-core */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "ovpn3-core"; sourceTree = BUILT_PRODUCTS_DIR; }; - DF380AE0201F09B70003272D /* openvpn */ = {isa = PBXFileReference; lastKnownFileType = folder; name = openvpn; path = ../../../openvpn; sourceTree = "<group>"; }; - DF380AE1201F0A2F0003272D /* cli.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cli.cpp; path = ../../../test/ovpncli/cli.cpp; sourceTree = "<group>"; }; - DF380AE4201F0D4F0003272D /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - DF380AE6201F0D910003272D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - DF380AE8201F0DB80003272D /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; - DF380AEA201F0DDC0003272D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; - DF380AEC201F0E0E0003272D /* libmbedtls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmbedtls.a; path = "../../../deps/mbedtls/mbedtls-osx/library/libmbedtls.a"; sourceTree = "<group>"; }; - DF838B402090AC2F00B68F90 /* liblz4.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblz4.a; path = "../../../deps/lz4/lz4-osx/lib/liblz4.a"; sourceTree = "<group>"; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - DF28F0C822E5E6C600E5B24C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DF28F0D922E60C0700E5B24C /* CoreFoundation.framework in Frameworks */, - DF28F0D822E60BFD00E5B24C /* SystemConfiguration.framework in Frameworks */, - DF28F0D722E60BF500E5B24C /* IOKit.framework in Frameworks */, - DF28F0D622E60BEF00E5B24C /* CoreServices.framework in Frameworks */, - DF28F0D522E60BBF00E5B24C /* libjsoncpp_static.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DF380AD3201F07AE0003272D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DF838B412090AC2F00B68F90 /* liblz4.a in Frameworks */, - DF380AED201F0E0E0003272D /* libmbedtls.a in Frameworks */, - DFA442402361E2F3007ACEF6 /* libjsoncpp_static.a in Frameworks */, - DF380AEB201F0DDC0003272D /* CoreServices.framework in Frameworks */, - DF380AE9201F0DB80003272D /* IOKit.framework in Frameworks */, - DF380AE7201F0D910003272D /* SystemConfiguration.framework in Frameworks */, - DF380AE5201F0D4F0003272D /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - DF28F0CC22E5E6C700E5B24C /* agent */ = { - isa = PBXGroup; - children = ( - DF28F0D322E6071900E5B24C /* ovpnagent.cpp */, - ); - path = agent; - sourceTree = "<group>"; - }; - DF380ACD201F07AE0003272D = { - isa = PBXGroup; - children = ( - DF380AD8201F07AE0003272D /* ovpn3-core */, - DF28F0CC22E5E6C700E5B24C /* agent */, - DF380AD7201F07AE0003272D /* Products */, - DF380AE3201F0D4F0003272D /* Frameworks */, - ); - sourceTree = "<group>"; - }; - DF380AD7201F07AE0003272D /* Products */ = { - isa = PBXGroup; - children = ( - DF380AD6201F07AE0003272D /* ovpn3-core */, - DF28F0CB22E5E6C600E5B24C /* agent */, - ); - name = Products; - sourceTree = "<group>"; - }; - DF380AD8201F07AE0003272D /* ovpn3-core */ = { - isa = PBXGroup; - children = ( - DF380AE1201F0A2F0003272D /* cli.cpp */, - DF380AE0201F09B70003272D /* openvpn */, - ); - path = "ovpn3-core"; - sourceTree = "<group>"; - }; - DF380AE3201F0D4F0003272D /* Frameworks */ = { - isa = PBXGroup; - children = ( - DF28F0C522E5E40D00E5B24C /* libjsoncpp_static.a */, - DF838B402090AC2F00B68F90 /* liblz4.a */, - DF380AEC201F0E0E0003272D /* libmbedtls.a */, - DF380AEA201F0DDC0003272D /* CoreServices.framework */, - DF380AE8201F0DB80003272D /* IOKit.framework */, - DF380AE6201F0D910003272D /* SystemConfiguration.framework */, - DF380AE4201F0D4F0003272D /* CoreFoundation.framework */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - DF28F0CA22E5E6C600E5B24C /* agent */ = { - isa = PBXNativeTarget; - buildConfigurationList = DF28F0CF22E5E6C700E5B24C /* Build configuration list for PBXNativeTarget "agent" */; - buildPhases = ( - DF28F0C722E5E6C600E5B24C /* Sources */, - DF28F0C822E5E6C600E5B24C /* Frameworks */, - DF28F0C922E5E6C600E5B24C /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = agent; - productName = agent; - productReference = DF28F0CB22E5E6C600E5B24C /* agent */; - productType = "com.apple.product-type.tool"; - }; - DF380AD5201F07AE0003272D /* ovpn3-core */ = { - isa = PBXNativeTarget; - buildConfigurationList = DF380ADD201F07AE0003272D /* Build configuration list for PBXNativeTarget "ovpn3-core" */; - buildPhases = ( - DF380AD2201F07AE0003272D /* Sources */, - DF380AD3201F07AE0003272D /* Frameworks */, - DF380AD4201F07AE0003272D /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "ovpn3-core"; - productName = "ovpn3-core"; - productReference = DF380AD6201F07AE0003272D /* ovpn3-core */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - DF380ACE201F07AE0003272D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1030; - ORGANIZATIONNAME = "Lev Stipakov"; - TargetAttributes = { - DF28F0CA22E5E6C600E5B24C = { - CreatedOnToolsVersion = 10.1; - ProvisioningStyle = Automatic; - }; - DF380AD5201F07AE0003272D = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = DF380AD1201F07AE0003272D /* Build configuration list for PBXProject "ovpn3-core" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = DF380ACD201F07AE0003272D; - productRefGroup = DF380AD7201F07AE0003272D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - DF380AD5201F07AE0003272D /* ovpn3-core */, - DF28F0CA22E5E6C600E5B24C /* agent */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - DF28F0C722E5E6C600E5B24C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DF28F0D422E6071900E5B24C /* ovpnagent.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - DF380AD2201F07AE0003272D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DF380AE2201F0A2F0003272D /* cli.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - DF28F0C322E5DAD200E5B24C /* DebugAgent */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = DebugAgent; - }; - DF28F0C422E5DAD200E5B24C /* DebugAgent */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - GCC_PREPROCESSOR_DEFINITIONS = ( - USE_ASIO, - ASIO_STANDALONE, - USE_MBEDTLS, - HAVE_LZ4, - LZ4_DISABLE_DEPRECATE_WARNINGS, - OPENVPN_COMMAND_AGENT, - HAVE_JSONCPP, - ); - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../..\"", - "\"$(SRCROOT)/../../../deps/asio/asio/include\"", - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", - "\"$(SRCROOT)/../../../common\"", - /usr/local/include, - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", - /usr/local/lib, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - }; - name = DebugAgent; - }; - DF28F0D022E5E6C700E5B24C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_STYLE = Automatic; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - DF28F0D122E5E6C700E5B24C /* DebugAgent */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_STYLE = Automatic; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ASIO_STANDALONE, - USE_ASIO, - USE_MBEDTLS, - HAVE_JSONCPP, - ); - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../..\"", - "\"$(SRCROOT)/../../../deps/asio/asio/include\"", - "\"$(SRCROOT)/../../../common\"", - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", - /usr/local/include, - ); - LIBRARY_SEARCH_PATHS = /usr/local/lib; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = DebugAgent; - }; - DF28F0D222E5E6C700E5B24C /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CODE_SIGN_STYLE = Automatic; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - DF380ADB201F07AE0003272D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - DF380ADC201F07AE0003272D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - }; - name = Release; - }; - DF380ADE201F07AE0003272D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - GCC_PREPROCESSOR_DEFINITIONS = ( - USE_ASIO, - ASIO_STANDALONE, - USE_MBEDTLS, - HAVE_LZ4, - LZ4_DISABLE_DEPRECATE_WARNINGS, - ); - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../..\"", - "\"$(SRCROOT)/../../../deps/asio/asio/include\"", - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - }; - name = Debug; - }; - DF380ADF201F07AE0003272D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - GCC_PREPROCESSOR_DEFINITIONS = ( - USE_ASIO, - ASIO_STANDALONE, - USE_MBEDTLS, - HAVE_LZ4, - LZ4_DISABLE_DEPRECATE_WARNINGS, - ); - HEADER_SEARCH_PATHS = ( - "\"$(SRCROOT)/../..\"", - "\"$(SRCROOT)/../../../deps/asio/asio/include\"", - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/include\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/include\"", - ); - LIBRARY_SEARCH_PATHS = ( - "\"$(SRCROOT)/../../../deps/mbedtls/mbedtls-osx/library\"", - "\"$(SRCROOT)/../../../deps/lz4/lz4-osx/lib\"", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - DF28F0CF22E5E6C700E5B24C /* Build configuration list for PBXNativeTarget "agent" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DF28F0D022E5E6C700E5B24C /* Debug */, - DF28F0D122E5E6C700E5B24C /* DebugAgent */, - DF28F0D222E5E6C700E5B24C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = DebugAgent; - }; - DF380AD1201F07AE0003272D /* Build configuration list for PBXProject "ovpn3-core" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DF380ADB201F07AE0003272D /* Debug */, - DF28F0C322E5DAD200E5B24C /* DebugAgent */, - DF380ADC201F07AE0003272D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = DebugAgent; - }; - DF380ADD201F07AE0003272D /* Build configuration list for PBXNativeTarget "ovpn3-core" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DF380ADE201F07AE0003272D /* Debug */, - DF28F0C422E5DAD200E5B24C /* DebugAgent */, - DF380ADF201F07AE0003272D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = DebugAgent; - }; -/* End XCConfigurationList section */ - }; - rootObject = DF380ACE201F07AE0003272D /* Project object */; -} diff --git a/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1595398..0000000 --- a/Sources/OpenVPN3/mac/ovpn3-core/ovpn3-core.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<Workspace - version = "1.0"> - <FileRef - location = "self:ovpn3-core.xcodeproj"> - </FileRef> -</Workspace> diff --git a/Sources/OpenVPN3/openvpn/acceptor/base.hpp b/Sources/OpenVPN3/openvpn/acceptor/base.hpp deleted file mode 100644 index 06f6e01..0000000 --- a/Sources/OpenVPN3/openvpn/acceptor/base.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// 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-2020 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/>. - -// multi-protocol acceptor classes that handle the protocol-specific -// details of accepting client connections. - -#pragma once - -#include <vector> -#include <utility> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/asio/asiopolysock.hpp> - -#ifndef OPENVPN_ACCEPTOR_LISTENER_BASE_RC -#define OPENVPN_ACCEPTOR_LISTENER_BASE_RC RC<thread_unsafe_refcount> -#endif - -namespace openvpn { - namespace Acceptor { - - struct ListenerBase : public OPENVPN_ACCEPTOR_LISTENER_BASE_RC - { - typedef RCPtr<ListenerBase> Ptr; - - virtual void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code& error) = 0; - }; - - struct Base : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Base> Ptr; - - virtual void async_accept(ListenerBase* listener, - const size_t acceptor_index, - openvpn_io::io_context& io_context) = 0; - virtual void close() = 0; - }; - - struct Item - { - enum SSLMode { - SSLOff, - SSLOn, -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - AltRouting, -#endif - }; - - Item(Base::Ptr acceptor_arg, - const SSLMode ssl_mode_arg) - : acceptor(std::move(acceptor_arg)), - ssl_mode(ssl_mode_arg) - { - } - - Base::Ptr acceptor; - SSLMode ssl_mode; - }; - - struct Set : public std::vector<Item> - { - void close() - { - for (auto &i : *this) - i.acceptor->close(); - } - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/acceptor/namedpipe.hpp b/Sources/OpenVPN3/openvpn/acceptor/namedpipe.hpp deleted file mode 100644 index 38199f0..0000000 --- a/Sources/OpenVPN3/openvpn/acceptor/namedpipe.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// 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-2020 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/acceptor/base.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/secattr.hpp> - -namespace openvpn { - namespace Acceptor { - - class NamedPipe : public Base - { - public: - OPENVPN_EXCEPTION(named_pipe_acceptor_error); - - typedef RCPtr<NamedPipe> Ptr; - - NamedPipe(openvpn_io::io_context& io_context, - const std::string& name_arg, - const std::string& sddl_string) - : name(name_arg), - handle(io_context), - sa(sddl_string, false, "named pipe") - { - } - - virtual void async_accept(ListenerBase* listener, - const size_t acceptor_index, - openvpn_io::io_context& io_context) override - { - // create the named pipe - const HANDLE h = ::CreateNamedPipeA( - name.c_str(), - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, -#if _WIN32_WINNT >= 0x0600 // Vista and higher - PIPE_REJECT_REMOTE_CLIENTS | -#endif - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, - PIPE_UNLIMITED_INSTANCES, - 2048, // output buffer size - 2048, // input buffer size - 0, - &sa.sa); - if (!Win::Handle::defined(h)) - { - const openvpn_io::error_code err(::GetLastError(), openvpn_io::error::get_system_category()); - OPENVPN_THROW(named_pipe_acceptor_error, "failed to create named pipe: " << name << " : " << err.message()); - } - - // wait for connection (asynchronously) - { - handle.assign(h); - openvpn_io::windows::overlapped_ptr over( - io_context, - [self=Ptr(this), listener=ListenerBase::Ptr(listener), acceptor_index] - (const openvpn_io::error_code& ec, size_t bytes_transferred) { - // accept client connection - listener->handle_accept(new AsioPolySock::NamedPipe(std::move(self->handle), acceptor_index), - ec.value() == ERROR_PIPE_CONNECTED // not an error - ? openvpn_io::error_code() - : ec); - }); - - const BOOL ok = ::ConnectNamedPipe(handle.native_handle(), over.get()); - const DWORD err = ::GetLastError(); - if (!ok && err != ERROR_IO_PENDING) - { - // The operation completed immediately, - // so a completion notification needs - // to be posted. When complete() is called, - // ownership of the OVERLAPPED-derived - // object passes to the io_service. - const openvpn_io::error_code ec(err, openvpn_io::error::get_system_category()); - over.complete(ec, 0); - } - else // ok || err == ERROR_IO_PENDING - { - // The operation was successfully initiated, - // so ownership of the OVERLAPPED-derived object - // has passed to the io_service. - over.release(); - } - } - } - - virtual void close() override - { - handle.close(); - } - - private: - std::string name; - openvpn_io::windows::stream_handle handle; - Win::SecurityAttributes sa; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/acceptor/tcp.hpp b/Sources/OpenVPN3/openvpn/acceptor/tcp.hpp deleted file mode 100644 index 695c9b7..0000000 --- a/Sources/OpenVPN3/openvpn/acceptor/tcp.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// 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-2020 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/acceptor/base.hpp> -#include <openvpn/ssl/sslconsts.hpp> - -namespace openvpn { - namespace Acceptor { - - struct TCP : public Base - { - typedef RCPtr<TCP> Ptr; - - TCP(openvpn_io::io_context& io_context) - : acceptor(io_context) - { - } - - virtual void async_accept(ListenerBase* listener, - const size_t acceptor_index, - openvpn_io::io_context& io_context) override - { - AsioPolySock::TCP::Ptr sock(new AsioPolySock::TCP(io_context, acceptor_index)); - acceptor.async_accept(sock->socket, [listener=ListenerBase::Ptr(listener), sock](const openvpn_io::error_code& error) mutable - { - listener->handle_accept(std::move(sock), error); - }); - } - - virtual void close() override - { -#ifdef OPENVPN_DEBUG_ACCEPT - OPENVPN_LOG("ACCEPTOR CLOSE " << local_endpoint); -#endif - acceptor.close(); - } - - enum { - // start at (1<<24) to avoid conflicting with SSLConst flags - DISABLE_REUSE_ADDR = (1<<24), - REUSE_PORT = (1<<25), - - FIRST=DISABLE_REUSE_ADDR - }; - void set_socket_options(unsigned int flags) - { - static_assert(int(FIRST) > int(SSLConst::LAST), "TCP flags in conflict with SSL flags"); - -#if defined(OPENVPN_PLATFORM_WIN) - // set Windows socket flags - if (!(flags & DISABLE_REUSE_ADDR)) - acceptor.set_option(openvpn_io::ip::tcp::acceptor::reuse_address(true)); -#else - // set Unix socket flags - { - const int fd = acceptor.native_handle(); - if (flags & REUSE_PORT) - SockOpt::reuseport(fd); - if (!(flags & DISABLE_REUSE_ADDR)) - SockOpt::reuseaddr(fd); - SockOpt::set_cloexec(fd); - } -#endif - } - - // filter all but socket option flags - static unsigned int sockopt_flags(const unsigned int flags) - { - return flags & (DISABLE_REUSE_ADDR|REUSE_PORT); - } - - openvpn_io::ip::tcp::endpoint local_endpoint; - openvpn_io::ip::tcp::acceptor acceptor; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/acceptor/unix.hpp b/Sources/OpenVPN3/openvpn/acceptor/unix.hpp deleted file mode 100644 index 51ecb5a..0000000 --- a/Sources/OpenVPN3/openvpn/acceptor/unix.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// 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-2020 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 <unistd.h> // for unlink() -#include <sys/stat.h> // for chmod() - -#include <openvpn/acceptor/base.hpp> - -namespace openvpn { - namespace Acceptor { - - struct Unix : public Base - { - OPENVPN_EXCEPTION(unix_acceptor_error); - - typedef RCPtr<Unix> Ptr; - - Unix(openvpn_io::io_context& io_context) - : acceptor(io_context) - { - } - - virtual void async_accept(ListenerBase* listener, - const size_t acceptor_index, - openvpn_io::io_context& io_context) override - { - AsioPolySock::Unix::Ptr sock(new AsioPolySock::Unix(io_context, acceptor_index)); - acceptor.async_accept(sock->socket, [listener=ListenerBase::Ptr(listener), sock](const openvpn_io::error_code& error) mutable - { - listener->handle_accept(std::move(sock), error); - }); - } - - virtual void close() override - { - acceptor.close(); - } - - static void pre_listen(const std::string& socket_path) - { - // remove previous socket instance - ::unlink(socket_path.c_str()); - } - - // set socket permissions in filesystem - static void set_socket_permissions(const std::string& socket_path, - const mode_t unix_mode) - { - if (unix_mode) - { - if (::chmod(socket_path.c_str(), unix_mode) < 0) - throw unix_acceptor_error("chmod failed on unix socket"); - } - } - - openvpn_io::local::stream_protocol::endpoint local_endpoint; - openvpn_io::basic_socket_acceptor<openvpn_io::local::stream_protocol> acceptor; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/addr/addrlist.hpp b/Sources/OpenVPN3/openvpn/addr/addrlist.hpp deleted file mode 100644 index c011d4b..0000000 --- a/Sources/OpenVPN3/openvpn/addr/addrlist.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// 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-2020 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_ADDR_ADDRLIST_H -#define OPENVPN_ADDR_ADDRLIST_H - -#include <openvpn/common/rc.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - namespace IP { - - // A list of unique IP addresses - class AddrList : public std::vector<IP::Addr>, public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<AddrList> Ptr; - - void add(const IP::Addr& a) - { - if (!exists(a)) - push_back(a); - } - - bool exists(const IP::Addr& a) const - { - for (const_iterator i = begin(); i != end(); ++i) - { - if (a == *i) - return true; - } - return false; - } - -#if 0 - void dump() const - { - OPENVPN_LOG("******* AddrList::dump"); - for (const_iterator i = begin(); i != end(); ++i) - OPENVPN_LOG(i->to_string()); - } -#endif - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/addrpair.hpp b/Sources/OpenVPN3/openvpn/addr/addrpair.hpp deleted file mode 100644 index 4c196ec..0000000 --- a/Sources/OpenVPN3/openvpn/addr/addrpair.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// 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-2020 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_ADDR_ADDRPAIR_H -#define OPENVPN_ADDR_ADDRPAIR_H - -#include <sstream> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - namespace IP { - - // AddrMaskPair is basically an object that combines an IP address (v4 or v6) - // with a netmask or prefix length. - struct AddrMaskPair - { - public: - OPENVPN_EXCEPTION(addr_pair_mask_parse_error); - - class StringPair { - public: - OPENVPN_SIMPLE_EXCEPTION(addr_pair_string_error); - - StringPair() - : size_(0) - { - } - - explicit StringPair(const std::string& s1) - : size_(1) - { - data[0] = s1; - } - - explicit StringPair(const std::string& s1, const std::string& s2) - : size_(2) - { - data[0] = s1; - data[1] = s2; - } - - void push_back(const std::string& s) - { - if (size_ < 2) - data[size_++] = s; - else - throw addr_pair_string_error(); - } - - const std::string& operator[](const size_t i) const - { - if (i >= 2) - throw addr_pair_string_error(); - return data[i]; - } - - std::string& operator[](const size_t i) - { - if (i >= 2) - throw addr_pair_string_error(); - return data[i]; - } - - size_t size() const { return size_; } - - std::string render() const - { - switch (size_) - { - case 1: - return data[0]; - case 2: - return data[0] + "/" + data[1]; - default: - return ""; - } - } - - private: - std::string data[2]; - unsigned int size_; - }; - - static AddrMaskPair from_string(const std::string& s1, const std::string& s2, const char *title = nullptr) - { - try { - if (s2.empty()) - { - const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s1, '/'); - return from_string_impl(pair, title); - } - else - { - const StringPair pair(s1, s2); - return from_string_impl(pair, title); - } - } - catch (const std::exception& e) - { - const StringPair pair(s1, s2); - error(e, pair.render(), title); - } - return AddrMaskPair(); // NOTREACHED - } - - static AddrMaskPair from_string(const std::string& s, const char *title = nullptr) - { - try { - const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s, '/'); - return from_string_impl(pair, title); - } - catch (const std::exception& e) - { - error(e, s, title); - } - return AddrMaskPair(); // NOTREACHED - } - - static AddrMaskPair from_string(const StringPair& pair, const char *title = nullptr) - { - try { - return from_string_impl(pair, title); - } - catch (const std::exception& e) - { - error(e, pair.render(), title); - } - return AddrMaskPair(); // NOTREACHED - } - - std::string to_string(const bool netmask_form=false) const - { - std::ostringstream os; - if (netmask_form) - os << addr.to_string() << '/' << netmask.to_string(); - else - os << addr.to_string() << '/' << netmask.prefix_len(); - return os.str(); - } - - bool is_canonical() const - { - return (addr & netmask) == addr; - } - - Addr::Version version() const - { - const Addr::Version v1 = addr.version(); - const Addr::Version v2 = netmask.version(); - if (v1 == v2) - return v1; - else - return Addr::UNSPEC; - } - - Addr addr; - Addr netmask; - - private: - static void error(const std::exception& e, const std::string& s, const char *title) - { - if (!title) - title = ""; - OPENVPN_THROW(addr_pair_mask_parse_error, "AddrMaskPair parse error '" << title << "': " << s << " : " << e.what()); - } - - static AddrMaskPair from_string_impl(const StringPair& pair, const char *title = nullptr) - { - AddrMaskPair ret; - if (pair.size() == 1 || pair.size() == 2) - { - ret.addr = Addr::from_string(pair[0], title); - if (pair.size() == 2 && !pair[1].empty()) - { - if (is_number(pair[1].c_str())) - ret.netmask = Addr::netmask_from_prefix_len(ret.addr.version(), - parse_number_throw<unsigned int>(pair[1], "prefix length")); - else - ret.netmask = Addr::from_string(pair[1]); - ret.netmask.prefix_len(); // verify that netmask is ok - } - else - ret.netmask = Addr::from_zero_complement(ret.addr.version()); - ret.addr.verify_version_consistency(ret.netmask); - } - else - throw addr_pair_mask_parse_error("only one or two address terms allowed"); - return ret; - } - - }; - OPENVPN_OSTREAM(AddrMaskPair, to_string) - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/addrspacesplit.hpp b/Sources/OpenVPN3/openvpn/addr/addrspacesplit.hpp deleted file mode 100644 index f0be8ae..0000000 --- a/Sources/OpenVPN3/openvpn/addr/addrspacesplit.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// 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-2020 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/>. - -// Invert a route list. Used to support excluded routes on platforms that -// don't support them natively. - -#pragma once - -#include <openvpn/common/exception.hpp> -#include <openvpn/addr/route.hpp> - -namespace openvpn { - namespace IP { - class AddressSpaceSplitter : public RouteList - { - public: - OPENVPN_EXCEPTION(address_space_splitter); - - AddressSpaceSplitter() {} - - // NOTE: when passing AddressSpaceSplitter to this constructor, make sure - // to static_cast it to RouteList& so as to avoid matching the - // default copy constructor. - explicit AddressSpaceSplitter(const RouteList& in) - : AddressSpaceSplitter(in, in.version_mask()) - { - } - - AddressSpaceSplitter(const RouteList& in, const Addr::VersionMask vermask) - { - in.verify_canonical(); - if (vermask & Addr::V4_MASK) - descend(in, Route(Addr::from_zero(Addr::V4), 0)); - if (vermask & Addr::V6_MASK) - descend(in, Route(Addr::from_zero(Addr::V6), 0)); - } - - private: - enum Type { - EQUAL, - SUBROUTE, - LEAF, - }; - /** - * This method construct a non-overlapping list of routes spanning the address - * space in @param route. The routes are constructed in a way that each - * route in the returned list is smaller or equalto each route in - * parameter @param in - * - * @param route The route we currently are looking at and split if it does - * not meet the requirements - */ - void descend(const RouteList& in, const Route& route) - { - switch (find(in, route)) - { - case SUBROUTE: - { - Route r1, r2; - if (route.split(r1, r2)) - { - descend(in, r1); - descend(in, r2); - } - else - push_back(route); - break; - } - case EQUAL: - case LEAF: - push_back(route); - break; - } - } - - static Type find(const RouteList& in, const Route& route) - { - Type type = LEAF; - for (RouteList::const_iterator i = in.begin(); i != in.end(); ++i) - { - const Route& r = *i; - if (route == r) - type = EQUAL; - else if (route.contains(r)) - return SUBROUTE; - } - return type; - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/addr/ip.hpp b/Sources/OpenVPN3/openvpn/addr/ip.hpp deleted file mode 100644 index f34c8f0..0000000 --- a/Sources/OpenVPN3/openvpn/addr/ip.hpp +++ /dev/null @@ -1,1031 +0,0 @@ -// 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-2020 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_ADDR_IP_H -#define OPENVPN_ADDR_IP_H - -#include <string> -#include <cstring> // for std::memset - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/ostream.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/addr/ipv4.hpp> -#include <openvpn/addr/ipv6.hpp> -#include <openvpn/addr/iperr.hpp> - -namespace openvpn { - // This is our fundamental IP address class that handles IPv4 or IPv6 - // IP addresses. It is implemented as a discriminated union of IPv4::Addr - // and IPv6::Addr. - namespace IP { - - OPENVPN_EXCEPTION(ip_exception); - - class Addr - { - public: - enum Version { UNSPEC, V4, V6 }; - - enum { V4_MASK=(1<<0), V6_MASK=(1<<1) }; - typedef unsigned int VersionMask; - - enum VersionSize { - V4_SIZE = IPv4::Addr::SIZE, - V6_SIZE = IPv6::Addr::SIZE, - }; - - template <typename TITLE> - Addr(const Addr& other, const TITLE& title, const Version required_version) - : ver(other.ver) - { - other.validate_version(title, required_version); - switch (ver) - { - case V4: - u.v4 = other.u.v4; - break; - case V6: - u.v6 = other.u.v6; - break; - default: - break; - } - } - - template <typename TITLE> - Addr(const Addr& other, const TITLE& title) - : Addr(other, title, UNSPEC) - { - } - - Addr(const Addr& other) - : Addr(other, nullptr, UNSPEC) - { - } - - template <typename TITLE> - Addr(const std::string& ipstr, const TITLE& title, const Version required_version) - : Addr(from_string(ipstr, title, required_version)) - { - } - - template <typename TITLE> - Addr(const std::string& ipstr, const TITLE& title) - : Addr(from_string(ipstr, title, UNSPEC)) - { - } - - Addr(const std::string& ipstr) - : Addr(from_string(ipstr, nullptr, UNSPEC)) - { - } - - template <typename TITLE> - static Addr from_string(const std::string& ipstr, - const TITLE& title, - const Version required_version) - { - openvpn_io::error_code ec; - openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec); - if (ec) - throw ip_exception(internal::format_error(ipstr, title, "", ec)); - const Addr ret = from_asio(a); - if (required_version != UNSPEC && required_version != ret.ver) - throw ip_exception(internal::format_error(ipstr, title, version_string_static(required_version), "wrong IP version")); - return ret; - } - - template <typename TITLE> - static Addr from_string(const std::string& ipstr, const TITLE& title) - { - return from_string(ipstr, title, UNSPEC); - } - - static Addr from_string(const std::string& ipstr) - { - return from_string(ipstr, nullptr, UNSPEC); - } - - template <typename TITLE> - static std::string validate(const std::string& ipstr, - const TITLE& title, - const Version required_version) - { - Addr a = from_string(ipstr, title, required_version); - return a.to_string(); - } - - template <typename TITLE> - static std::string validate(const std::string& ipstr, const TITLE& title) - { - return validate(ipstr, title, UNSPEC); - } - - static std::string validate(const std::string& ipstr) - { - return validate(ipstr, nullptr, UNSPEC); - } - - template <typename TITLE> - void validate_version(const TITLE& title, const Version required_version) const - { - if (required_version != UNSPEC && required_version != ver) - throw ip_exception(internal::format_error(to_string(), title, version_string_static(required_version), "wrong IP version")); - } - - static bool is_valid(const std::string& ipstr) - { - // fast path -- rule out validity if invalid chars - for (size_t i = 0; i < ipstr.length(); ++i) - { - const char c = ipstr[i]; - if (!((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F') - || (c == '.' || c == ':' || c == '%'))) - return false; - } - - // slow path - { - openvpn_io::error_code ec; - openvpn_io::ip::make_address(ipstr, ec); - return !ec; - } - } - - static Addr from_hex(Version v, const std::string& s) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_hex(s)); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_hex(s)); - else - throw ip_exception("address unspecified"); - } - - static Addr from_ipv4(IPv4::Addr addr) - { - Addr a; - a.ver = V4; - a.u.v4 = std::move(addr); - return a; - } - - static Addr from_ipv6(IPv6::Addr addr) - { - Addr a; - a.ver = V6; - a.u.v6 = std::move(addr); - return a; - } - - const IPv4::Addr& to_ipv4() const - { - if (ver == V4) - return u.v4; - else - throw ip_exception("address is not IPv4"); - } - - IPv4::Addr to_ipv4_zero() const - { - if (ver == V4) - return u.v4; - else if (ver == UNSPEC) - return IPv4::Addr::from_zero(); - else - throw ip_exception("address is not IPv4 (zero)"); - } - - const IPv6::Addr& to_ipv6() const - { - if (ver == V6) - return u.v6; - else - throw ip_exception("address is not IPv6"); - } - - IPv6::Addr to_ipv6_zero() const - { - if (ver == V6) - return u.v6; - else if (ver == UNSPEC) - return IPv6::Addr::from_zero(); - else - throw ip_exception("address is not IPv6 (zero)"); - } - - const IPv4::Addr& to_ipv4_nocheck() const - { - return u.v4; - } - - const IPv6::Addr& to_ipv6_nocheck() const - { - return u.v6; - } - - static Addr from_sockaddr(const struct sockaddr *sa) - { - if (sa->sa_family == AF_INET) - return from_ipv4(IPv4::Addr::from_sockaddr((struct sockaddr_in *)sa)); - else if (sa->sa_family == AF_INET6) - return from_ipv6(IPv6::Addr::from_sockaddr((struct sockaddr_in6 *)sa)); - else - return Addr(); - } - - static bool sockaddr_defined(const struct sockaddr *sa) - { - return sa && (sa->sa_family == AF_INET || sa->sa_family == AF_INET6); - } - - static Addr from_ulong(Version v, unsigned long ul) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_ulong(ul)); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_ulong(ul)); - else - throw ip_exception("address unspecified"); - } - - // return *this as a ulong, will raise exception on overflow - unsigned long to_ulong() const - { - if (ver == V4) - return u.v4.to_ulong(); - else if (ver == V6) - return u.v6.to_ulong(); - else - throw ip_exception("address unspecified"); - } - - static Addr from_long(Version v, long ul) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_long(ul)); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_long(ul)); - else - throw ip_exception("address unspecified"); - } - - // return *this as a long, will raise exception on overflow - long to_long() const - { - if (ver == V4) - return u.v4.to_long(); - else if (ver == V6) - return u.v6.to_long(); - else - throw ip_exception("address unspecified"); - } - - // return Addr from 16 byte binary string - static Addr from_byte_string(const unsigned char *bytestr) - { - Addr a; - if (IPv6::Addr::byte_string_is_v4(bytestr)) - { - a.ver = V4; - a.u.v4 = IPv4::Addr::from_uint32_net(IPv6::Addr::v4_from_byte_string(bytestr)); - } - else - { - a.ver = V6; - a.u.v6 = IPv6::Addr::from_byte_string(bytestr); - } - return a; - } - - // convert Addr to 16 byte binary string - void to_byte_string(unsigned char *bytestr) const - { - if (ver == V4) - IPv6::Addr::v4_to_byte_string(bytestr, u.v4.to_uint32_net()); - else if (ver == V6) - u.v6.to_byte_string(bytestr); - else - std::memset(bytestr, 0, 16); - } - - // convert Addr to variable length byte string - void to_byte_string_variable(unsigned char *bytestr) const - { - if (ver == V4) - u.v4.to_byte_string(bytestr); - else if (ver == V6) - u.v6.to_byte_string(bytestr); - else - throw ip_exception("address unspecified"); - } - - std::uint32_t to_uint32_net() const // return value in net byte order - { - if (ver == V4) - return u.v4.to_uint32_net(); - else - return 0; - } - - // construct an address where all bits are zero - static Addr from_zero(Version v) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_zero()); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_zero()); - else - throw ip_exception("address unspecified"); - } - - // construct an address where all bits are zero - static Addr from_one(Version v) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_one()); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_one()); - else - throw ip_exception("address unspecified"); - } - - // construct an address where all bits are one - static Addr from_zero_complement(Version v) - { - if (v == V4) - return from_ipv4(IPv4::Addr::from_zero_complement()); - else if (v == V6) - return from_ipv6(IPv6::Addr::from_zero_complement()); - else - throw ip_exception("address unspecified"); - } - - // validate the prefix length for the IP version - static bool validate_prefix_len(Version v, const unsigned int prefix_len) - { - if (v == V4) - { - if (prefix_len <= V4_SIZE) - return true; - } - else if (v == V6) - { - if (prefix_len <= V6_SIZE) - return true; - } - return false; - } - - // build a netmask using given prefix_len - static Addr netmask_from_prefix_len(Version v, const unsigned int prefix_len) - { - if (v == V4) - return from_ipv4(IPv4::Addr::netmask_from_prefix_len(prefix_len)); - else if (v == V6) - return from_ipv6(IPv6::Addr::netmask_from_prefix_len(prefix_len)); - else - throw ip_exception("address unspecified"); - } - - // build a netmask using *this as extent - Addr netmask_from_extent() const - { - if (ver == V4) - return from_ipv4(u.v4.netmask_from_extent()); - else if (ver == V6) - return from_ipv6(u.v6.netmask_from_extent()); - else - throw ip_exception("address unspecified"); - } - - std::string to_string() const - { - if (ver != UNSPEC) - { - const openvpn_io::ip::address a = to_asio(); - std::string ret = a.to_string(); - return ret; - } - else - return "UNSPEC"; - } - - std::string to_string_bracket_ipv6() const - { - std::string ret; - if (ver == V6) - ret += '['; - ret += to_string(); - if (ver == V6) - ret += ']'; - return ret; - } - - std::string to_hex() const - { - if (ver == V4) - return u.v4.to_hex(); - else if (ver == V6) - return u.v6.to_hex(); - else - throw ip_exception("address unspecified"); - } - - std::string arpa() const - { - if (ver == V4) - return u.v4.arpa(); - else if (ver == V6) - return u.v6.arpa(); - else - throw ip_exception("address unspecified"); - } - - static Addr from_asio(const openvpn_io::ip::address& addr) - { - if (addr.is_v4()) - { - Addr a; - a.ver = V4; - a.u.v4 = IPv4::Addr::from_asio(addr.to_v4()); - return a; - } - else if (addr.is_v6()) - { - Addr a; - a.ver = V6; - a.u.v6 = IPv6::Addr::from_asio(addr.to_v6()); - return a; - } - else - throw ip_exception("address unspecified"); - } - - openvpn_io::ip::address to_asio() const - { - switch (ver) - { - case V4: - return openvpn_io::ip::address_v4(u.v4.to_asio()); - case V6: - return openvpn_io::ip::address_v6(u.v6.to_asio()); - default: - throw ip_exception("address unspecified"); - } - } - - Addr operator+(const long delta) const { - switch (ver) - { - case V4: - { - Addr ret; - ret.ver = V4; - ret.u.v4 = u.v4 + delta; - return ret; - } - case V6: - { - Addr ret; - ret.ver = V6; - ret.u.v6 = u.v6 + delta; - return ret; - } - default: - throw ip_exception("address unspecified"); - } - } - - Addr operator-(const long delta) const { - return operator+(-delta); - } - -#define OPENVPN_IP_OPERATOR_BINOP(OP) \ - Addr operator OP (const Addr& other) const { \ - if (ver != other.ver) \ - throw ip_exception("version inconsistency"); \ - switch (ver) \ - { \ - case V4: \ - { \ - Addr ret; \ - ret.ver = V4; \ - ret.u.v4 = u.v4 OP other.u.v4; \ - return ret; \ - } \ - case V6: \ - { \ - Addr ret; \ - ret.ver = V6; \ - ret.u.v6 = u.v6 OP other.u.v6; \ - return ret; \ - } \ - default: \ - throw ip_exception("address unspecified"); \ - } \ - } - - OPENVPN_IP_OPERATOR_BINOP(+) - OPENVPN_IP_OPERATOR_BINOP(-) - OPENVPN_IP_OPERATOR_BINOP(*) - OPENVPN_IP_OPERATOR_BINOP(/) - OPENVPN_IP_OPERATOR_BINOP(%) - OPENVPN_IP_OPERATOR_BINOP(&) - OPENVPN_IP_OPERATOR_BINOP(|) - -#undef OPENVPN_IP_OPERATOR_BINOP - - Addr operator<<(const unsigned int shift) const { - switch (ver) - { - case V4: - { - Addr ret; - ret.ver = V4; - ret.u.v4 = u.v4 << shift; - return ret; - } - case V6: - { - Addr ret; - ret.ver = V6; - ret.u.v6 = u.v6 << shift; - return ret; - } - default: - throw ip_exception("address unspecified"); - } - } - - Addr operator>>(const unsigned int shift) const { - switch (ver) - { - case V4: - { - Addr ret; - ret.ver = V4; - ret.u.v4 = u.v4 >> shift; - return ret; - } - case V6: - { - Addr ret; - ret.ver = V6; - ret.u.v6 = u.v6 >> shift; - return ret; - } - default: - throw ip_exception("address unspecified"); - } - } - - Addr operator~() const { - switch (ver) - { - case V4: - { - Addr ret; - ret.ver = V4; - ret.u.v4 = ~u.v4; - return ret; - } - case V6: - { - Addr ret; - ret.ver = V6; - ret.u.v6 = ~u.v6; - return ret; - } - default: - throw ip_exception("address unspecified"); - } - } - - Addr network_addr(const unsigned int prefix_len) const { - switch (ver) - { - case V4: - { - Addr ret; - ret.ver = V4; - ret.u.v4 = u.v4.network_addr(prefix_len); - return ret; - } - case V6: - { - Addr ret; - ret.ver = V6; - ret.u.v6 = u.v6.network_addr(prefix_len); - return ret; - } - default: - throw ip_exception("address unspecified"); - } - } - - bool operator==(const Addr& other) const - { - switch (ver) - { - case UNSPEC: - return other.ver == UNSPEC; - case V4: - if (ver == other.ver) - return u.v4 == other.u.v4; - break; - case V6: - if (ver == other.ver) - return u.v6 == other.u.v6; - break; - } - return false; - } - - bool operator!=(const Addr& other) const - { - return !operator==(other); - } - -#define OPENVPN_IP_OPERATOR_REL(OP) \ - bool operator OP(const Addr& other) const \ - { \ - if (ver == other.ver) \ - { \ - switch (ver) \ - { \ - case V4: \ - return u.v4 OP other.u.v4; \ - case V6: \ - return u.v6 OP other.u.v6; \ - default: \ - return false; \ - } \ - } \ - else if (ver OP other.ver) \ - return true; \ - else \ - return false; \ - } - - OPENVPN_IP_OPERATOR_REL(<) - OPENVPN_IP_OPERATOR_REL(>) - OPENVPN_IP_OPERATOR_REL(<=) - OPENVPN_IP_OPERATOR_REL(>=) - -#undef OPENVPN_IP_OPERATOR_REL - - bool unspecified() const - { - return all_zeros(); - } - - bool specified() const - { - return !unspecified(); - } - - bool all_zeros() const - { - switch (ver) - { - case V4: - return u.v4.all_zeros(); - case V6: - return u.v6.all_zeros(); - default: - return true; - } - } - - bool all_ones() const - { - switch (ver) - { - case V4: - return u.v4.all_ones(); - case V6: - return u.v6.all_ones(); - default: - return false; - } - } - - bool is_loopback() const - { - switch (ver) - { - case V4: - return u.v4.is_loopback(); - case V6: - return u.v6.is_loopback(); - default: - return false; - } - } - - bool defined() const - { - return ver != UNSPEC; - } - - const char *version_string() const - { - return version_string_static(ver); - } - - static const char *version_string_static(Version ver) - { - switch (ver) - { - case V4: - return "v4"; - case V6: - return "v6"; - default: - return "v?"; - } - } - - Version version() const { return ver; } - - static VersionMask version_mask(const Version ver) - { - switch (ver) - { - case V4: - return V4_MASK; - case V6: - return V6_MASK; - default: - return 0; - } - } - - VersionMask version_mask() const - { - return version_mask(ver); - } - - int version_index() const - { - switch (ver) - { - case V4: - return 0; - case V6: - return 1; - default: - throw ip_exception("version index undefined"); - } - } - - int family() const - { - switch (ver) - { - case V4: - return AF_INET; - case V6: - return AF_INET6; - default: - return -1; - } - } - - bool is_compatible(const Addr& other) const - { - return ver == other.ver; - } - - bool is_ipv6() const - { - return ver == V6; - } - - void verify_version_consistency(const Addr& other) const - { - if (!is_compatible(other)) - throw ip_exception("version inconsistency"); - } - - // throw exception if address is not a valid netmask - void validate_netmask() - { - prefix_len(); - } - - // number of network bits in netmask, - // throws exception if addr is not a netmask - unsigned int prefix_len() const - { - switch (ver) - { - case V4: - return u.v4.prefix_len(); - case V6: - return u.v6.prefix_len(); - default: - throw ip_exception("address unspecified"); - } - } - - // IPv6 scope ID or -1 if not IPv6 - int scope_id() const - { - return ver == V6 ? u.v6.scope_id() : -1; - } - - // number of host bits in netmask - unsigned int host_len() const - { - switch (ver) - { - case V4: - return u.v4.host_len(); - case V6: - return u.v6.host_len(); - default: - throw ip_exception("address unspecified"); - } - } - - // return the number of host addresses contained within netmask - Addr extent_from_netmask() const - { - switch (ver) - { - case V4: - return from_ipv4(u.v4.extent_from_netmask()); - case V6: - return from_ipv6(u.v6.extent_from_netmask()); - default: - throw ip_exception("address unspecified"); - } - } - - // address size in bits - unsigned int size() const - { - return version_size(ver); - } - - // address size in bytes - unsigned int size_bytes() const - { - return size() / 8; - } - - // address size in bits of particular IP version - static unsigned int version_size(Version v) - { - if (v == V4) - return IPv4::Addr::SIZE; - else if (v == V6) - return IPv6::Addr::SIZE; - else - return 0; - } - - template <typename HASH> - void hash(HASH& h) const - { - switch (ver) - { - case Addr::V4: - u.v4.hash(h); - break; - case Addr::V6: - u.v6.hash(h); - break; - default: - break; - } - } - -#ifdef HAVE_CITYHASH - std::size_t hashval() const - { - HashSizeT h; - hash(h); - return h.value(); - } -#endif - -#ifdef OPENVPN_IP_IMMUTABLE - private: -#endif - - Addr() - : ver(UNSPEC) - { - } - - void reset() - { - ver = UNSPEC; - } - - Addr& operator=(const Addr& other) - { - ver = other.ver; - u = other.u; - return *this; - } - - Addr& operator++() - { - switch (ver) - { - case V4: - ++u.v4; - break; - case V6: - ++u.v6; - break; - default: - break; - } - return *this; - } - - Addr& operator+=(const long delta) - { - switch (ver) - { - case V4: - u.v4 += delta; - break; - case V6: - u.v6 += delta; - break; - default: - break; - } - return *this; - } - - Addr& operator-=(const long delta) - { - switch (ver) - { - case V4: - u.v4 -= delta; - break; - case V6: - u.v6 -= delta; - break; - default: - break; - } - return *this; - } - - void reset_ipv4_from_uint32(const IPv4::Addr::base_type addr) - { - ver = V4; - u.v4 = IPv4::Addr::from_uint32(addr); - } - - private: - union { - IPv4::Addr v4; - IPv6::Addr v6; - } u {}; - - Version ver; - }; - - OPENVPN_OSTREAM(Addr, to_string) - } -} - -#ifdef HAVE_CITYHASH -OPENVPN_HASH_METHOD(openvpn::IP::Addr, hashval); -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/iperr.hpp b/Sources/OpenVPN3/openvpn/addr/iperr.hpp deleted file mode 100644 index 5cc98a7..0000000 --- a/Sources/OpenVPN3/openvpn/addr/iperr.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// 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-2020 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/>. - -// Called internally by IP, IPv4, and IPv6 classes - -#pragma once - -#include <string> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/stringtempl2.hpp> - -namespace openvpn { - namespace IP { - namespace internal { - - template <typename TITLE> - inline std::string format_error(const std::string& ipstr, - const TITLE& title, - const char *ipver, - const std::string& message) - { - std::string err = "error parsing"; - if (!StringTempl::empty(title)) - { - err += ' '; - err += StringTempl::to_string(title); - } - err += " IP"; - err += ipver; - err += " address '"; - err += ipstr; - err += '\''; - if (!message.empty()) - { - err += " : "; - err += message; - } - return err; - } - - template <typename TITLE> - inline std::string format_error(const std::string& ipstr, - const TITLE& title, - const char *ipver, - const openvpn_io::error_code& ec) - { - return format_error(ipstr, title, ipver, ec.message()); - } - - } - } -} diff --git a/Sources/OpenVPN3/openvpn/addr/ipv4.hpp b/Sources/OpenVPN3/openvpn/addr/ipv4.hpp deleted file mode 100644 index 6adbc12..0000000 --- a/Sources/OpenVPN3/openvpn/addr/ipv4.hpp +++ /dev/null @@ -1,594 +0,0 @@ -// 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-2020 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_ADDR_IPV4_H -#define OPENVPN_ADDR_IPV4_H - -#include <cstring> // for std::memcpy, std::memset -#include <sstream> -#include <cstdint> // for std::uint32_t - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/endian.hpp> -#include <openvpn/common/ostream.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/ffs.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/addr/iperr.hpp> - -namespace openvpn { - namespace IP { - class Addr; - } - - // Fundamental classes for representing an IPv4 IP address. - - namespace IPv4 { - - OPENVPN_EXCEPTION(ipv4_exception); - - class Addr // NOTE: must be union-legal, so default constructor does not initialize - { - friend class IP::Addr; - - public: - enum { SIZE=32 }; - - typedef std::uint32_t base_type; - typedef std::int32_t signed_base_type; - - bool defined() const - { - return true; - } - - static Addr from_addr(const Addr& addr) - { - return addr; - } - - static Addr from_in_addr(const struct in_addr *in4) - { - Addr ret; - ret.u.addr = ntohl(in4->s_addr); - return ret; - } - - struct in_addr to_in_addr() const - { - struct in_addr ret; - ret.s_addr = htonl(u.addr); - return ret; - } - - static Addr from_sockaddr(const struct sockaddr_in *sa) - { - Addr ret; - ret.u.addr = ntohl(sa->sin_addr.s_addr); - return ret; - } - - struct sockaddr_in to_sockaddr(const unsigned short port=0) const - { - struct sockaddr_in ret; - std::memset(&ret, 0, sizeof(ret)); - ret.sin_family = AF_INET; - ret.sin_port = htons(port); - ret.sin_addr.s_addr = htonl(u.addr); - return ret; - } - - static Addr from_uint32(const base_type addr) // host byte order - { - Addr ret; - ret.u.addr = addr; - return ret; - } - - std::uint32_t to_uint32() const // host byte order - { - return u.addr; - } - - static Addr from_uint32_net(const base_type addr) // addr in net byte order - { - Addr ret; - ret.u.addr = ntohl(addr); - return ret; - } - - void to_byte_string(unsigned char *bytestr) const - { - *(base_type*)bytestr = ntohl(u.addr); - } - - std::uint32_t to_uint32_net() const // return value in net byte order - { - return htonl(u.addr); - } - - static Addr from_ulong(unsigned long ul) - { - Addr ret; - ret.u.addr = (base_type)ul; - return ret; - } - - // return *this as a unsigned long - unsigned long to_ulong() const - { - return (unsigned long)u.addr; - } - - static Addr from_long(long ul) - { - Addr ret; - ret.u.addr = (base_type)(signed_base_type)ul; - return ret; - } - - // return *this as a long - long to_long() const - { - return (long)(signed_base_type)u.addr; - } - - static Addr from_bytes(const unsigned char *bytes) // host byte order - { - Addr ret; - std::memcpy(ret.u.bytes, bytes, 4); - return ret; - } - - static Addr from_bytes_net(const unsigned char *bytes) // network byte order - { - Addr ret; - std::memcpy(ret.u.bytes, bytes, 4); - ret.u.addr = ntohl(ret.u.addr); - return ret; - } - - static Addr from_zero() - { - Addr ret; - ret.zero(); - return ret; - } - - static Addr from_one() - { - Addr ret; - ret.one(); - return ret; - } - - static Addr from_zero_complement() - { - Addr ret; - ret.zero_complement(); - return ret; - } - - // build a netmask using given prefix_len - static Addr netmask_from_prefix_len(const unsigned int prefix_len) - { - Addr ret; - ret.u.addr = prefix_len_to_netmask(prefix_len); - return ret; - } - - // build a netmask using given extent - Addr netmask_from_extent() const - { - const int lb = find_last_set(u.addr - 1); - return netmask_from_prefix_len(SIZE - lb); - } - - template <typename TITLE> - static Addr from_string(const std::string& ipstr, const TITLE& title) - { - openvpn_io::error_code ec; - openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec); - if (ec) - throw ipv4_exception(IP::internal::format_error(ipstr, title, "v4", ec)); - return from_asio(a); - } - - static Addr from_string(const std::string& ipstr) - { - return from_string(ipstr, nullptr); - } - - std::string to_string() const - { - const openvpn_io::ip::address_v4 a = to_asio(); - std::string ret = a.to_string(); - return ret; - } - - static Addr from_hex(const std::string& s) - { - Addr ret; - ret.u.addr = 0; - size_t len = s.length(); - size_t base = 0; - if (len > 0 && s[len-1] == 'L') - len -= 1; - if (len >= 2 && s[0] == '0' && s[1] == 'x') - { - base = 2; - len -= 2; - } - if (len < 1 || len > 8) - throw ipv4_exception("parse hex error"); - size_t di = (len-1)>>1; - for (int i = (len & 1) ? -1 : 0; i < int(len); i += 2) - { - const size_t idx = base + i; - const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0; - const int bl = parse_hex_char(s[idx+1]); - if (bh == -1 || bl == -1) - throw ipv4_exception("parse hex error"); - ret.u.bytes[Endian::e4(di--)] = (bh<<4) + bl; - } - return ret; - } - - std::string to_hex() const - { - std::string ret; - ret.reserve(8); - bool firstnonzero = false; - for (size_t i = 0; i < 4; ++i) - { - const unsigned char b = u.bytes[Endian::e4rev(i)]; - if (b || firstnonzero || i == 3) - { - const char bh = b >> 4; - if (bh || firstnonzero) - ret += render_hex_char(bh); - ret += render_hex_char(b & 0x0F); - firstnonzero = true; - } - } - return ret; - } - - std::string arpa() const - { - std::ostringstream os; - os << int(u.bytes[Endian::e4(0)]) << '.' - << int(u.bytes[Endian::e4(1)]) << '.' - << int(u.bytes[Endian::e4(2)]) << '.' - << int(u.bytes[Endian::e4(3)]) << ".in-addr.arpa"; - return os.str(); - } - - static Addr from_asio(const openvpn_io::ip::address_v4& asio_addr) - { - Addr ret; - ret.u.addr = (std::uint32_t)asio_addr.to_uint(); - return ret; - } - - openvpn_io::ip::address_v4 to_asio() const - { - return openvpn_io::ip::address_v4(u.addr); - } - - Addr operator&(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr & other.u.addr; - return ret; - } - - Addr operator|(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr | other.u.addr; - return ret; - } - - Addr operator+(const long delta) const { - Addr ret; - ret.u.addr = u.addr + (std::uint32_t)delta; - return ret; - } - - Addr operator+(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr + other.u.addr; - return ret; - } - - Addr operator-(const long delta) const { - return operator+(-delta); - } - - Addr operator-(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr - other.u.addr; - return ret; - } - - Addr operator*(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr * other.u.addr; - return ret; - } - - Addr operator/(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr / other.u.addr; - return ret; - } - - Addr operator%(const Addr& other) const { - Addr ret; - ret.u.addr = u.addr % other.u.addr; - return ret; - } - - Addr operator<<(const unsigned int shift) const { - Addr ret; - ret.u.addr = u.addr << shift; - return ret; - } - - Addr operator>>(const unsigned int shift) const { - Addr ret; - ret.u.addr = u.addr >> shift; - return ret; - } - - Addr operator~() const { - Addr ret; - ret.u.addr = ~u.addr; - return ret; - } - - // return the network that contains the current address - Addr network_addr(const unsigned int prefix_len) const - { - Addr ret; - ret.u.addr = u.addr & prefix_len_to_netmask(prefix_len); - return ret; - } - - bool operator==(const Addr& other) const - { - return u.addr == other.u.addr; - } - - bool operator!=(const Addr& other) const - { - return u.addr != other.u.addr; - } - - bool operator<(const Addr& other) const - { - return u.addr < other.u.addr; - } - - bool operator>(const Addr& other) const - { - return u.addr > other.u.addr; - } - - bool operator<=(const Addr& other) const - { - return u.addr <= other.u.addr; - } - - bool operator>=(const Addr& other) const - { - return u.addr >= other.u.addr; - } - - bool unspecified() const - { - return all_zeros(); - } - - bool specified() const - { - return !unspecified(); - } - - bool all_zeros() const - { - return u.addr == 0; - } - - bool all_ones() const - { - return ~u.addr == 0; - } - - bool is_loopback() const - { - return (u.addr & 0x7F000000) == 0x7F000000; - } - - // number of network bits in netmask, - // throws exception if addr is not a netmask - unsigned int prefix_len() const - { - const int ret = prefix_len_32(u.addr); - if (ret >= 0) - return ret; - else - throw ipv4_exception("malformed netmask"); - } - - int prefix_len_nothrow() const - { - return prefix_len_32(u.addr); - } - - // number of host bits in netmask - unsigned int host_len() const - { - return SIZE - prefix_len(); - } - - // return the number of host addresses contained within netmask - Addr extent_from_netmask() const - { - Addr ret; - ret.u.addr = extent_from_netmask_uint32(); - return ret; - } - - std::uint32_t extent_from_netmask_uint32() const - { - const unsigned int hl = host_len(); - if (hl < SIZE) - return 1 << hl; - else if (hl == SIZE) - return 0; - else - throw ipv4_exception("extent overflow"); - } - - // convert netmask in addr to prefix_len, will return -1 on error - static int prefix_len_32(const std::uint32_t addr) - { - if (addr == ~std::uint32_t(0)) - return 32; - else if (addr == 0) - return 0; - else - { - unsigned int high = 32; - unsigned int low = 1; - for (unsigned int i = 0; i < 5; ++i) - { - const unsigned int mid = (high + low) / 2; - const IPv4::Addr::base_type test = prefix_len_to_netmask_unchecked(mid); - if (addr == test) - return mid; - else if (addr > test) - low = mid; - else - high = mid; - } - return -1; - } - } - - // address size in bits - static unsigned int size() - { - return SIZE; - } - - template <typename HASH> - void hash(HASH& h) const - { - h(u.addr); - } - -#ifdef HAVE_CITYHASH - std::size_t hashval() const - { - HashSizeT h; - hash(h); - return h.value(); - } -#endif - -#ifdef OPENVPN_IP_IMMUTABLE - private: -#endif - - void negate() - { - u.addr = ~u.addr; - } - - void zero() - { - u.addr = 0; - } - - void zero_complement() - { - u.addr = ~0; - } - - void one() - { - u.addr = 1; - } - - Addr& operator++() - { - ++u.addr; - return *this; - } - - Addr& operator+=(const long delta) - { - u.addr += (std::uint32_t)delta; - return *this; - } - - Addr& operator-=(const long delta) - { - return operator+=(-delta); - } - - private: - static base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) - { - if (prefix_len) - return ~((1 << (SIZE - prefix_len)) - 1); - else - return 0; - } - - static base_type prefix_len_to_netmask(const unsigned int prefix_len) - { - if (prefix_len <= SIZE) - return prefix_len_to_netmask_unchecked(prefix_len); - else - throw ipv4_exception("bad prefix len"); - } - - union { - base_type addr; // host byte order - unsigned char bytes[4]; - } u; - }; - - OPENVPN_OSTREAM(Addr, to_string) - } -} - -#ifdef HAVE_CITYHASH -OPENVPN_HASH_METHOD(openvpn::IPv4::Addr, hashval); -#endif - -#endif // OPENVPN_ADDR_IPV4_H diff --git a/Sources/OpenVPN3/openvpn/addr/ipv6.hpp b/Sources/OpenVPN3/openvpn/addr/ipv6.hpp deleted file mode 100644 index af0ba8a..0000000 --- a/Sources/OpenVPN3/openvpn/addr/ipv6.hpp +++ /dev/null @@ -1,857 +0,0 @@ -// 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-2020 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_ADDR_IPV6_H -#define OPENVPN_ADDR_IPV6_H - -#include <cstring> // for std::memcpy, std::memset -#include <algorithm> // for std::min -#include <cstdint> // for std::uint32_t - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/ostream.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/ffs.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/addr/ipv4.hpp> -#include <openvpn/addr/iperr.hpp> - -namespace openvpn { - namespace IP { - class Addr; - } - - // Fundamental classes for representing an IPv6 IP address. - - namespace IPv6 { - - OPENVPN_EXCEPTION(ipv6_exception); - - class Addr // NOTE: must be union-legal, so default constructor does not initialize - { - friend class IP::Addr; - - public: - enum { SIZE=128 }; - - bool defined() const - { - return true; - } - - static Addr from_addr(const Addr& addr) - { - return addr; - } - - static Addr from_in6_addr(const struct in6_addr *in6) - { - Addr ret; - network_to_host_order(&ret.u, (const union ipv6addr *)in6->s6_addr); - ret.scope_id_ = 0; - return ret; - } - - struct in6_addr to_in6_addr() const - { - struct in6_addr ret; - host_to_network_order((union ipv6addr *)&ret, &u); - return ret; - } - - static Addr from_sockaddr(const struct sockaddr_in6 *sa) - { - Addr ret; - network_to_host_order(&ret.u, (const union ipv6addr *)sa->sin6_addr.s6_addr); - ret.scope_id_ = sa->sin6_scope_id; - return ret; - } - - struct sockaddr_in6 to_sockaddr(const unsigned short port=0) const - { - struct sockaddr_in6 ret; - std::memset(&ret, 0, sizeof(ret)); - ret.sin6_family = AF_INET6; - ret.sin6_port = htons(port); - host_to_network_order((union ipv6addr *)&ret.sin6_addr.s6_addr, &u); - ret.sin6_scope_id = scope_id_; - return ret; - } - - template <typename TITLE> - static Addr from_string(const std::string& ipstr, const TITLE& title) - { - openvpn_io::error_code ec; - openvpn_io::ip::address_v6 a = openvpn_io::ip::make_address_v6(ipstr, ec); - if (ec) - throw ipv6_exception(IP::internal::format_error(ipstr, title, "v6", ec)); - return from_asio(a); - } - - static Addr from_string(const std::string& ipstr) - { - return from_string(ipstr, nullptr); - } - - std::string to_string() const - { - const openvpn_io::ip::address_v6 a = to_asio(); - std::string ret = a.to_string(); -#ifdef UNIT_TEST - return string::to_lower_copy(ret); -#else - return ret; -#endif - } - - static Addr from_hex(const std::string& s) - { - Addr ret; - ret.scope_id_ = 0; - ret.zero(); - size_t len = s.length(); - size_t base = 0; - if (len > 0 && s[len-1] == 'L') - len -= 1; - if (len >= 2 && s[0] == '0' && s[1] == 'x') - { - base = 2; - len -= 2; - } - if (len < 1 || len > 32) - throw ipv6_exception("parse hex error"); - size_t di = (len-1)>>1; - for (int i = (len & 1) ? -1 : 0; i < int(len); i += 2) - { - const size_t idx = base + i; - const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0; - const int bl = parse_hex_char(s[idx+1]); - if (bh == -1 || bl == -1) - throw ipv6_exception("parse hex error"); - ret.u.bytes[Endian::e16(di--)] = (bh<<4) + bl; - } - return ret; - } - - std::string to_hex() const - { - std::string ret; - ret.reserve(32); - bool firstnonzero = false; - for (size_t i = 0; i < 16; ++i) - { - const unsigned char b = u.bytes[Endian::e16rev(i)]; - if (b || firstnonzero || i == 15) - { - const char bh = b >> 4; - if (bh || firstnonzero) - ret += render_hex_char(bh); - ret += render_hex_char(b & 0x0F); - firstnonzero = true; - } - } - return ret; - } - - static Addr from_ulong(unsigned long ul) - { - Addr ret; - ret.scope_id_ = 0; - ret.u.u64[Endian::e2(0)] = std::uint64_t(ul); - ret.u.u64[Endian::e2(1)] = 0; - return ret; - } - - // return *this as a unsigned long - unsigned long to_ulong() const - { - const unsigned long ret = (unsigned long)u.u64[Endian::e2(0)]; - const std::uint64_t cmp = std::uint64_t(ret); - if (u.u64[Endian::e2(1)] || cmp != u.u64[Endian::e2(0)]) - throw ipv6_exception("overflow in conversion from IPv6.Addr to unsigned long"); - return ret; - } - - static Addr from_long(long ul) - { - bool neg = false; - Addr ret; - ret.scope_id_ = 0; - if (ul < 0) - { - ul = -(ul + 1); - neg = true; - } - ret.u.u64[Endian::e2(0)] = std::uint64_t(ul); - ret.u.u64[Endian::e2(1)] = 0; - if (neg) - ret.negate(); - return ret; - } - - // return *this as a long - long to_long() const - { - bool neg = false; - Addr a = *this; - if (a.u.u64[Endian::e2(1)]) - { - a.negate(); - neg = true; - } - const long ret = (long)a.u.u64[Endian::e2(0)]; - const std::uint64_t cmp = std::uint64_t(ret); - if (a.u.u64[Endian::e2(1)] || cmp != a.u.u64[Endian::e2(0)]) - throw ipv6_exception("overflow in conversion from IPv6.Addr to long"); - return neg ? -(ret + 1) : ret; - } - - std::string arpa() const - { - throw ipv6_exception("arpa() not implemented"); - } - - static Addr from_asio(const openvpn_io::ip::address_v6& asio_addr) - { - Addr ret; - union ipv6addr addr; - addr.asio_bytes = asio_addr.to_bytes(); - network_to_host_order(&ret.u, &addr); - ret.scope_id_ = (unsigned int)asio_addr.scope_id(); - return ret; - } - - static Addr from_byte_string(const unsigned char *bytestr) - { - Addr ret; - network_to_host_order(&ret.u, (const union ipv6addr *)bytestr); - ret.scope_id_ = 0; - return ret; - } - - void to_byte_string(unsigned char *bytestr) const - { - host_to_network_order((union ipv6addr *)bytestr, &u); - } - - static void v4_to_byte_string(unsigned char *bytestr, - const std::uint32_t v4addr) - { - union ipv6addr *a = (union ipv6addr *)bytestr; - a->u32[0] = a->u32[1] = a->u32[2] = 0; - a->u32[3] = v4addr; - } - - static bool byte_string_is_v4(const unsigned char *bytestr) - { - const union ipv6addr *a = (const union ipv6addr *)bytestr; - return a->u32[0] == 0 && a->u32[1] == 0 && a->u32[2] == 0; - } - - static std::uint32_t v4_from_byte_string(const unsigned char *bytestr) - { - const union ipv6addr *a = (const union ipv6addr *)bytestr; - return a->u32[3]; - } - - openvpn_io::ip::address_v6 to_asio() const - { - union ipv6addr addr; - host_to_network_order(&addr, &u); - return openvpn_io::ip::address_v6(addr.asio_bytes, scope_id_); - } - - static Addr from_zero() - { - Addr ret; - ret.scope_id_ = 0; - ret.zero(); - return ret; - } - - static Addr from_one() - { - Addr ret; - ret.scope_id_ = 0; - ret.one(); - return ret; - } - - static Addr from_zero_complement() - { - Addr ret; - ret.scope_id_ = 0; - ret.zero_complement(); - return ret; - } - - // build a netmask using given prefix_len - static Addr netmask_from_prefix_len(const unsigned int prefix_len) - { - Addr ret; - ret.scope_id_ = 0; - ret.prefix_len_to_netmask(prefix_len); - return ret; - } - - // build a netmask using given extent - Addr netmask_from_extent() const - { - const Addr lb = *this - 1; - for (size_t i = 4; i --> 0 ;) - { - const std::uint32_t v = lb.u.u32[Endian::e4(i)]; - if (v) - return netmask_from_prefix_len(SIZE - (((unsigned int)i<<5) + find_last_set(v))); - } - return from_zero_complement(); - } - - Addr operator&(const Addr& other) const { - Addr ret; - ret.scope_id_ = scope_id_; - ret.u.u64[0] = u.u64[0] & other.u.u64[0]; - ret.u.u64[1] = u.u64[1] & other.u.u64[1]; - return ret; - } - - Addr operator|(const Addr& other) const { - Addr ret; - ret.scope_id_ = scope_id_; - ret.u.u64[0] = u.u64[0] | other.u.u64[0]; - ret.u.u64[1] = u.u64[1] | other.u.u64[1]; - return ret; - } - - Addr operator+(const long delta) const { - Addr ret = *this; - ret.u.u64[Endian::e2(0)] += delta; - ret.u.u64[Endian::e2(1)] += (delta >= 0) - ? (ret.u.u64[Endian::e2(0)] < u.u64[Endian::e2(0)]) - : -(ret.u.u64[Endian::e2(0)] > u.u64[Endian::e2(0)]); - return ret; - } - - Addr operator+(const Addr& other) const { - Addr ret = *this; - add(ret.u, other.u); - return ret; - } - - Addr operator-(const long delta) const { - return operator+(-delta); - } - - Addr operator-(const Addr& other) const { - Addr ret = *this; - sub(ret.u, other.u); - return ret; - } - - Addr operator*(const Addr& d) const { - Addr m = d; - Addr ret = from_zero(); - for (unsigned int i = 0; i < SIZE; ++i) - { - if (bit(i)) - ret += m; - m <<= 1; - } - return ret; - } - - Addr operator/(const Addr& d) const { - Addr q, r; - div(*this, d, q, r); - return q; - } - - Addr operator%(const Addr& d) const { - Addr q, r; - div(*this, d, q, r); - return r; - } - - Addr operator<<(const unsigned int shift) const { - Addr ret = *this; - shiftl128(ret.u.u64[Endian::e2(0)], - ret.u.u64[Endian::e2(1)], - shift); - return ret; - } - - Addr operator>>(const unsigned int shift) const { - Addr ret = *this; - shiftr128(ret.u.u64[Endian::e2(0)], - ret.u.u64[Endian::e2(1)], - shift); - return ret; - } - - Addr operator~() const { - Addr ret; - ret.scope_id_ = scope_id_; - ret.u.u64[0] = ~u.u64[0]; - ret.u.u64[1] = ~u.u64[1]; - return ret; - } - - // return the network that contains the current address - Addr network_addr(const unsigned int prefix_len) const - { - return *this & netmask_from_prefix_len(prefix_len); - } - - bool operator==(const Addr& other) const - { - return u.u64[0] == other.u.u64[0] && u.u64[1] == other.u.u64[1] && scope_id_ == other.scope_id_; - } - - bool operator!=(const Addr& other) const - { - return !operator==(other); - } - -#define OPENVPN_IPV6_OPERATOR_REL(OP) \ - bool operator OP(const Addr& other) const \ - { \ - if (u.u64[Endian::e2(1)] == other.u.u64[Endian::e2(1)]) \ - { \ - if (u.u64[Endian::e2(0)] != other.u.u64[Endian::e2(0)]) \ - return u.u64[Endian::e2(0)] OP other.u.u64[Endian::e2(0)]; \ - else \ - return scope_id_ OP other.scope_id_; \ - } \ - else \ - return u.u64[Endian::e2(1)] OP other.u.u64[Endian::e2(1)]; \ - } - - OPENVPN_IPV6_OPERATOR_REL(<) - OPENVPN_IPV6_OPERATOR_REL(>) - OPENVPN_IPV6_OPERATOR_REL(<=) - OPENVPN_IPV6_OPERATOR_REL(>=) - -#undef OPENVPN_IPV6_OPERATOR_REL - - bool unspecified() const - { - return all_zeros(); - } - - bool specified() const - { - return !unspecified(); - } - - bool all_zeros() const - { - return u.u64[0] == 0 && u.u64[1] == 0; - } - - bool all_ones() const - { - return u.u64[0] == ~std::uint64_t(0) && u.u64[1] == ~std::uint64_t(0); - } - - bool is_loopback() const // ::1 - { - return u.u64[Endian::e2(1)] == 0 && u.u64[Endian::e2(0)] == 1; - } - - bool bit(unsigned int pos) const - { - if (pos < 64) - return (u.u64[Endian::e2(0)] & (std::uint64_t(1)<<pos)) != 0; - else - return (u.u64[Endian::e2(1)] & (std::uint64_t(1)<<(pos-64))) != 0; - } - - // number of network bits in netmask, - // throws exception if addr is not a netmask - unsigned int prefix_len() const - { - int idx = -1; - - if (u.u32[Endian::e4(3)] != ~std::uint32_t(0)) - { - if (!u.u32[Endian::e4(0)] && !u.u32[Endian::e4(1)] && !u.u32[Endian::e4(2)]) - idx = 0; - } - else if (u.u32[Endian::e4(2)] != ~std::uint32_t(0)) - { - if (!u.u32[Endian::e4(0)] && !u.u32[Endian::e4(1)]) - idx = 1; - } - else if (u.u32[Endian::e4(1)] != ~std::uint32_t(0)) - { - if (!u.u32[Endian::e4(0)]) - idx = 2; - } - else - idx = 3; - - if (idx >= 0) - { - const int ret = IPv4::Addr::prefix_len_32(u.u32[Endian::e4rev(idx)]); - if (ret >= 0) - return ret + (idx<<5); - } - throw ipv6_exception("malformed netmask"); - } - - // number of host bits in netmask - unsigned int host_len() const - { - return SIZE - prefix_len(); - } - - // return the number of host addresses contained within netmask - Addr extent_from_netmask() const - { - const unsigned int hl = host_len(); - if (hl < SIZE) - { - Addr a; - a.scope_id_ = 0; - a.one(); - return a << hl; - } - else if (hl == SIZE) - return from_zero(); - else - throw ipv6_exception("extent overflow"); - } - - // address size in bits - static unsigned int size() - { - return SIZE; - } - - template <typename HASH> - void hash(HASH& h) const - { - h(u.bytes, sizeof(u.bytes)); - } - -#ifdef HAVE_CITYHASH - std::size_t hashval() const - { - HashSizeT h; - hash(h); - return h.value(); - } -#endif - -#ifdef OPENVPN_IP_IMMUTABLE - private: -#endif - - void negate() - { - u.u64[0] = ~u.u64[0]; - u.u64[1] = ~u.u64[1]; - } - - void zero() - { - u.u64[0] = 0; - u.u64[1] = 0; - } - - void zero_complement() - { - u.u64[0] = ~std::uint64_t(0); - u.u64[1] = ~std::uint64_t(0); - } - - void one() - { - u.u64[0] = 1; - u.u64[1] = 0; - } - - Addr& operator++() - { - if (++u.u64[Endian::e2(0)] == 0) - ++u.u64[Endian::e2(1)]; - return *this; - } - - Addr& operator+=(const long delta) - { - *this = *this + delta; - return *this; - } - - Addr& operator-=(const long delta) - { - return operator+=(-delta); - } - - Addr& operator+=(const Addr& other) { - add(u, other.u); - return *this; - } - - Addr& operator-=(const Addr& other) { - sub(u, other.u); - return *this; - } - - Addr& operator<<=(const unsigned int shift) { - shiftl128(u.u64[Endian::e2(0)], - u.u64[Endian::e2(1)], - shift); - return *this; - } - - Addr& operator>>=(const unsigned int shift) { - shiftr128(u.u64[Endian::e2(0)], - u.u64[Endian::e2(1)], - shift); - return *this; - } - - void set_clear_bit(unsigned int pos, bool value) - { - if (pos < 64) - { - if (value) - u.u64[Endian::e2(0)] |= (std::uint64_t(1)<<pos); - else - u.u64[Endian::e2(0)] &= ~(std::uint64_t(1)<<pos); - } - else - { - if (value) - u.u64[Endian::e2(1)] |= (std::uint64_t(1)<<(pos-64)); - else - u.u64[Endian::e2(1)] &= ~(std::uint64_t(1)<<(pos-64)); - } - } - - void set_bit(unsigned int pos, bool value) - { - if (value) - { - if (pos < 64) - u.u64[Endian::e2(0)] |= (std::uint64_t(1)<<pos); - else - u.u64[Endian::e2(1)] |= (std::uint64_t(1)<<(pos-64)); - } - } - - static void div(const Addr& n, const Addr& d, Addr& q, Addr& r) - { - if (d.all_zeros()) - throw ipv6_exception("division by 0"); - q = from_zero(); // quotient - r = n; // remainder (init to numerator) - Addr ml = from_zero(); // mask low - Addr mh = d; // mask high (init to denominator) - for (unsigned int i = 0; i < SIZE; ++i) - { - ml >>= 1; - ml.set_bit(SIZE-1, mh.bit(0)); - mh >>= 1; - if (mh.all_zeros() && r >= ml) - { - r -= ml; - q.set_bit((SIZE-1)-i, true); - } - } - } - - int scope_id() const - { - return scope_id_; - } - - private: - union ipv6addr { - std::uint64_t u64[2]; - std::uint32_t u32[4]; // generally stored in host byte order - unsigned char bytes[16]; - openvpn_io::ip::address_v6::bytes_type asio_bytes; - }; - - void prefix_len_to_netmask_unchecked(const unsigned int prefix_len) - { - if (prefix_len > 0) - { - const unsigned int pl = prefix_len - 1; - const std::uint32_t mask = ~((1 << (31 - (pl & 31))) - 1); - switch (pl >> 5) - { - case 0: - u.u32[Endian::e4(0)] = 0; - u.u32[Endian::e4(1)] = 0; - u.u32[Endian::e4(2)] = 0; - u.u32[Endian::e4(3)] = mask; - break; - case 1: - u.u32[Endian::e4(0)] = 0; - u.u32[Endian::e4(1)] = 0; - u.u32[Endian::e4(2)] = mask; - u.u32[Endian::e4(3)] = ~0; - break; - case 2: - u.u32[Endian::e4(0)] = 0; - u.u32[Endian::e4(1)] = mask; - u.u32[Endian::e4(2)] = ~0; - u.u32[Endian::e4(3)] = ~0; - break; - case 3: - u.u32[Endian::e4(0)] = mask; - u.u32[Endian::e4(1)] = ~0; - u.u32[Endian::e4(2)] = ~0; - u.u32[Endian::e4(3)] = ~0; - break; - } - } - else - zero(); - } - - void prefix_len_to_netmask(const unsigned int prefix_len) - { - if (prefix_len <= SIZE) - return prefix_len_to_netmask_unchecked(prefix_len); - else - throw ipv6_exception("bad prefix len"); - } - - static void host_to_network_order(union ipv6addr *dest, const union ipv6addr *src) - { - dest->u32[0] = htonl(src->u32[Endian::e4rev(0)]); - dest->u32[1] = htonl(src->u32[Endian::e4rev(1)]); - dest->u32[2] = htonl(src->u32[Endian::e4rev(2)]); - dest->u32[3] = htonl(src->u32[Endian::e4rev(3)]); - } - - static void network_to_host_order(union ipv6addr *dest, const union ipv6addr *src) - { - dest->u32[0] = ntohl(src->u32[Endian::e4rev(0)]); - dest->u32[1] = ntohl(src->u32[Endian::e4rev(1)]); - dest->u32[2] = ntohl(src->u32[Endian::e4rev(2)]); - dest->u32[3] = ntohl(src->u32[Endian::e4rev(3)]); - } - - static void shiftl128(std::uint64_t& low, - std::uint64_t& high, - unsigned int shift) - { - if (shift == 1) - { - high <<= 1; - if (low & (std::uint64_t(1) << 63)) - high |= 1; - low <<= 1; - } - else if (shift == 0) - ; - else if (shift <= 128) - { - if (shift >= 64) - { - high = low; - low = 0; - shift -= 64; - } - if (shift < 64) - { - high = (high << shift) | (low >> (64-shift)); - low <<= shift; - } - else // shift == 64 - high = 0; - } - else - throw ipv6_exception("l-shift too large"); - } - - static void shiftr128(std::uint64_t& low, - std::uint64_t& high, - unsigned int shift) - { - if (shift == 1) - { - low >>= 1; - if (high & 1) - low |= (std::uint64_t(1) << 63); - high >>= 1; - } - else if (shift == 0) - ; - else if (shift <= 128) - { - if (shift >= 64) - { - low = high; - high = 0; - shift -= 64; - } - if (shift < 64) - { - low = (low >> shift) | (high << (64-shift)); - high >>= shift; - } - else // shift == 64 - low = 0; - } - else - throw ipv6_exception("r-shift too large"); - } - - static void add(ipv6addr& dest, const ipv6addr& src) { - const std::uint64_t dorigl = dest.u64[Endian::e2(0)]; - dest.u64[Endian::e2(0)] += src.u64[Endian::e2(0)]; - dest.u64[Endian::e2(1)] += src.u64[Endian::e2(1)]; - // check for overflow of low 64 bits, add carry to high - if (dest.u64[Endian::e2(0)] < dorigl) - ++dest.u64[Endian::e2(1)]; - } - - static void sub(ipv6addr& dest, const ipv6addr& src) { - const std::uint64_t dorigl = dest.u64[Endian::e2(0)]; - dest.u64[Endian::e2(0)] -= src.u64[Endian::e2(0)]; - dest.u64[Endian::e2(1)] -= src.u64[Endian::e2(1)] - + (dorigl < dest.u64[Endian::e2(0)]); - } - - union ipv6addr u; - unsigned int scope_id_; - }; - - OPENVPN_OSTREAM(Addr, to_string) - } -} - -#ifdef HAVE_CITYHASH -OPENVPN_HASH_METHOD(openvpn::IPv6::Addr, hashval); -#endif - -#endif // OPENVPN_ADDR_IPV6_H diff --git a/Sources/OpenVPN3/openvpn/addr/macaddr.hpp b/Sources/OpenVPN3/openvpn/addr/macaddr.hpp deleted file mode 100644 index e9227e5..0000000 --- a/Sources/OpenVPN3/openvpn/addr/macaddr.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// 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-2020 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_ADDR_MACADDR_H -#define OPENVPN_ADDR_MACADDR_H - -#include <ostream> -#include <cstring> -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/ostream.hpp> -#include <openvpn/common/hexstr.hpp> - -namespace openvpn { - - // Fundamental class for representing an ethernet MAC address. - - class MACAddr { - public: - MACAddr() - { - std::memset(addr_, 0, sizeof(addr_)); - } - - MACAddr(const unsigned char *addr) - { - reset(addr); - } - - void reset(const unsigned char *addr) - { - std::memcpy(addr_, addr, sizeof(addr_)); - } - - std::string to_string() const - { - return render_hex_sep(addr_, sizeof(addr_), ':'); - } - - private: - unsigned char addr_[6]; - }; - - OPENVPN_OSTREAM(MACAddr, to_string) - -} // namespace openvpn - -#endif // OPENVPN_ADDR_MACADDR_H diff --git a/Sources/OpenVPN3/openvpn/addr/pool.hpp b/Sources/OpenVPN3/openvpn/addr/pool.hpp deleted file mode 100644 index c6fe92b..0000000 --- a/Sources/OpenVPN3/openvpn/addr/pool.hpp +++ /dev/null @@ -1,166 +0,0 @@ -// 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-2020 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_ADDR_POOL_H -#define OPENVPN_ADDR_POOL_H - -#include <string> -#include <sstream> -#include <deque> -#include <unordered_map> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -#include <openvpn/addr/ip.hpp> -#include <openvpn/addr/range.hpp> - -namespace openvpn { - namespace IP { - - // Maintain a pool of IP addresses. - // A should be IP::Addr, IPv4::Addr, or IPv6::Addr. - template <typename ADDR> - class PoolType - { - public: - PoolType() = default; - - // Add range of addresses to pool (pool will own the addresses). - void add_range(const RangeType<ADDR>& range) - { - auto iter = range.iterator(); - while (iter.more()) - { - const ADDR& a = iter.addr(); - add_addr(a); - iter.next(); - } - } - - // Add single address to pool (pool will own the address). - void add_addr(const ADDR& addr) - { - auto e = map.find(addr); - if (e == map.end()) - { - freelist.push_back(addr); - map[addr] = false; - } - } - - // Return number of pool addresses currently in use. - size_t n_in_use() const - { - return map.size() - freelist.size(); - } - - // Return number of pool addresses currently in use. - size_t n_free() const - { - return freelist.size(); - } - - // Acquire an address from pool. Returns true if successful, - // with address placed in dest, or false if pool depleted. - bool acquire_addr(ADDR& dest) - { - while (true) - { - freelist_fill(); - if (freelist.empty()) - return false; - const ADDR& a = freelist.front(); - auto e = map.find(a); - if (e == map.end()) // any address in freelist must exist in map - throw Exception("PoolType: address in freelist doesn't exist in map"); - if (!e->second) - { - e->second = true; - dest = a; - freelist.pop_front(); - return true; - } - freelist.pop_front(); - } - } - - // Acquire a specific address from pool, returning true if - // successful, or false if the address is not available. - bool acquire_specific_addr(const ADDR& addr) - { - auto e = map.find(addr); - if (e != map.end() && !e->second) - { - e->second = true; - return true; - } - else - return false; - } - - // Return a previously acquired address to the pool. Does nothing if - // (a) the address is owned by the pool and marked as free, or - // (b) the address is not owned by the pool. - void release_addr(const ADDR& addr) - { - auto e = map.find(addr); - if (e != map.end() && e->second) - { - freelist.push_back(addr); - e->second = false; - } - } - - // DEBUGGING -- get the map load factor - float load_factor() const { return map.load_factor(); } - - // Override to refill freelist on demand - virtual void freelist_fill() - { - } - - std::string to_string() const - { - std::string ret; - for (const auto& e : map) - { - if (e.second) - { - ret += e.first.to_string(); - ret += '\n'; - } - } - return ret; - } - - virtual ~PoolType<ADDR>() = default; - - private: - std::deque<ADDR> freelist; - std::unordered_map<ADDR, bool> map; - }; - - typedef PoolType<IP::Addr> Pool; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/quoteip.hpp b/Sources/OpenVPN3/openvpn/addr/quoteip.hpp deleted file mode 100644 index 7f883b8..0000000 --- a/Sources/OpenVPN3/openvpn/addr/quoteip.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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-2020 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> - -namespace openvpn { - - // return ip_addr in brackets if it is IPv6 - std::string quote_ip(const std::string& ip_addr) - { - if (ip_addr.find(':') != std::string::npos) - return '[' + ip_addr + ']'; - else - return ip_addr; - } -} diff --git a/Sources/OpenVPN3/openvpn/addr/randaddr.hpp b/Sources/OpenVPN3/openvpn/addr/randaddr.hpp deleted file mode 100644 index d136223..0000000 --- a/Sources/OpenVPN3/openvpn/addr/randaddr.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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-2020 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/addr/route.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - namespace IP { - - inline IPv4::Addr random_addr_v4(RandomAPI& prng) - { - return IPv4::Addr::from_uint32(prng.rand_get<std::uint32_t>()); - } - - inline IPv6::Addr random_addr_v6(RandomAPI& prng) - { - unsigned char bytes[16]; - prng.rand_fill(bytes); - return IPv6::Addr::from_byte_string(bytes); - } - - inline Addr random_addr(const Addr::Version v, RandomAPI& prng) - { - switch (v) - { - case Addr::V4: - return Addr::from_ipv4(random_addr_v4(prng)); - case Addr::V6: - return Addr::from_ipv6(random_addr_v6(prng)); - default: - throw ip_exception("address unspecified"); - } - } - - // bit positions between templ.prefix_len and prefix_len are randomized - inline Route random_subnet(const Route& templ, - const unsigned int prefix_len, - RandomAPI& prng) - { - if (!templ.is_canonical()) - throw Exception("IP::random_subnet: template route not canonical: " + templ.to_string()); - return Route(((random_addr(templ.addr.version(), prng) & ~templ.netmask()) | templ.addr) - & Addr::netmask_from_prefix_len(templ.addr.version(), prefix_len), - prefix_len); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/addr/range.hpp b/Sources/OpenVPN3/openvpn/addr/range.hpp deleted file mode 100644 index dea4bc7..0000000 --- a/Sources/OpenVPN3/openvpn/addr/range.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// 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-2020 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_ADDR_RANGE_H -#define OPENVPN_ADDR_RANGE_H - -#include <string> -#include <sstream> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - namespace IP { - - // Denote a range of IP addresses with a start and extent, - // where A represents an address class. - // A should be a network address class such as IP::Addr, IPv4::Addr, or IPv6::Addr. - - template <typename ADDR> - class RangeType - { - public: - class Iterator - { - friend class RangeType; - public: - bool more() const { return remaining_ > 0; } - - const ADDR& addr() const { return addr_; } - - void next() - { - if (more()) - { - ++addr_; - --remaining_; - } - } - - private: - Iterator(const RangeType& range) - : addr_(range.start_), remaining_(range.extent_) {} - - ADDR addr_; - size_t remaining_; - }; - - RangeType() : extent_(0) {} - - RangeType(const ADDR& start, const size_t extent) - : start_(start), extent_(extent) {} - - Iterator iterator() const { return Iterator(*this); } - - const bool defined() const { return extent_ > 0; } - const ADDR& start() const { return start_; } - size_t extent() const { return extent_; } - - RangeType pull_front(size_t extent) - { - if (extent > extent_) - extent = extent_; - RangeType ret(start_, extent); - start_ += extent; - extent_ -= extent; - return ret; - } - - std::string to_string() const - { - std::ostringstream os; - os << start_.to_string() << '[' << extent_ << ']'; - return os.str(); - } - - private: - ADDR start_; - size_t extent_; - }; - - template <typename ADDR> - class RangePartitionType - { - public: - RangePartitionType(const RangeType<ADDR>& src_range, const size_t n_partitions) - : range(src_range), - remaining(n_partitions) - { - } - - bool next(RangeType<ADDR>& r) - { - if (remaining) - { - if (remaining > 1) - r = range.pull_front(range.extent() / remaining); - else - r = range; - --remaining; - return r.defined(); - } - else - return false; - } - - private: - RangeType<ADDR> range; - size_t remaining; - }; - - typedef RangeType<IP::Addr> Range; - typedef RangePartitionType<IP::Addr> RangePartition; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/regex.hpp b/Sources/OpenVPN3/openvpn/addr/regex.hpp deleted file mode 100644 index 5ba7019..0000000 --- a/Sources/OpenVPN3/openvpn/addr/regex.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// 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-2020 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/>. - -// Regular expressions for IPv4/v6 -// Source: http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses - -#ifndef OPENVPN_ADDR_REGEX_H -#define OPENVPN_ADDR_REGEX_H - -#include <string> - -namespace openvpn { - namespace IP { - inline std::string v4_regex() - { - const std::string ipv4seg = "(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])"; - return "(?:" + ipv4seg + "\\.){3,3}" + ipv4seg; - } - - inline std::string v6_regex() - { - const std::string ipv6seg = "[0-9a-fA-F]{1,4}"; - return "(?:" - "(?:" + ipv6seg + ":){7,7}" + ipv6seg + "|" // 1:2:3:4:5:6:7:8 - "(?:" + ipv6seg + ":){1,7}:|" // 1:: 1:2:3:4:5:6:7:: - "(?:" + ipv6seg + ":){1,6}:" + ipv6seg + "|" // 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 - "(?:" + ipv6seg + ":){1,5}(?::" + ipv6seg + "){1,2}|" // 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 - "(?:" + ipv6seg + ":){1,4}(?::" + ipv6seg + "){1,3}|" // 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 - "(?:" + ipv6seg + ":){1,3}(?::" + ipv6seg + "){1,4}|" // 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 - "(?:" + ipv6seg + ":){1,2}(?::" + ipv6seg + "){1,5}|" + // 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 - ipv6seg + ":(?:(?::" + ipv6seg + "){1,6})|" // 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 - ":(?:(?::" + ipv6seg + "){1,7}|:)|" // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: - "fe80:(?::" + ipv6seg + "){0,4}%[0-9a-zA-Z]{1,}|" // fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) - "::(?:ffff(?::0{1,4}){0,1}:){0,1}" + v4_regex() + "|" // ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses) - "(?:" + ipv6seg + ":){1,4}:" + v4_regex() + // 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address) - ")"; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/addr/route.hpp b/Sources/OpenVPN3/openvpn/addr/route.hpp deleted file mode 100644 index ce6e586..0000000 --- a/Sources/OpenVPN3/openvpn/addr/route.hpp +++ /dev/null @@ -1,362 +0,0 @@ -// 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-2020 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_ADDR_ROUTE_H -#define OPENVPN_ADDR_ROUTE_H - -#include <string> -#include <sstream> -#include <vector> -#include <cstdint> // for std::uint32_t -#include <tuple> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - namespace IP { - // Basic route object - template <typename ADDR> - class RouteType - { - public: - typedef ADDR Addr; - - ADDR addr; - unsigned int prefix_len; - - OPENVPN_EXCEPTION(route_error); - - RouteType() - : prefix_len(0) - { - } - - RouteType(const ADDR& addr_arg, - const unsigned int prefix_len_arg) - : addr(addr_arg), - prefix_len(prefix_len_arg) - { - } - - template <typename TITLE> - RouteType(const std::string& rtstr, const TITLE& title) - : RouteType(RouteType::from_string(rtstr, title)) - { - } - - RouteType(const std::string& rtstr) - : RouteType(RouteType::from_string(rtstr, nullptr)) - { - } - - template <typename TITLE> - static RouteType from_string(const std::string& rtstr, const TITLE& title) - { - RouteType r; - std::vector<std::string> pair; - pair.reserve(2); - Split::by_char_void<std::vector<std::string>, NullLex, Split::NullLimit>(pair, rtstr, '/', 0, 1); - r.addr = ADDR::from_string(pair[0], title); - if (pair.size() >= 2) - { - r.prefix_len = parse_number_throw<unsigned int>(pair[1], "prefix length"); - if (r.prefix_len > r.addr.size()) - OPENVPN_THROW(route_error, (!StringTempl::empty(title) ? title : "route") << " : bad prefix length : " << rtstr); - } - else - r.prefix_len = r.addr.size(); - return r; - } - - static RouteType from_string(const std::string& rtstr) - { - return from_string(rtstr, nullptr); - } - - bool defined() const - { - return addr.defined(); - } - - IP::Addr::Version version() const - { - return addr.version(); - } - - IP::Addr::VersionMask version_mask() const - { - return addr.version_mask(); - } - - RouteType<IPv4::Addr> to_ipv4() const - { - return RouteType<IPv4::Addr>(addr.to_ipv4(), prefix_len); - } - - RouteType<IPv6::Addr> to_ipv6() const - { - return RouteType<IPv6::Addr>(addr.to_ipv6(), prefix_len); - } - - ADDR netmask() const - { - return netmask_(addr, prefix_len); - } - - size_t extent() const - { - return netmask().extent_from_netmask().to_ulong(); - } - - bool is_canonical() const - { - return (addr & netmask()) == addr; - } - - void force_canonical() - { - addr = addr & netmask(); - } - - void verify_canonical() const - { - if (!is_canonical()) - throw route_error("route not canonical: " + to_string()); - } - - bool is_host() const - { - return addr.defined() && prefix_len == addr.size(); - } - - unsigned int host_bits() const - { - if (prefix_len < addr.size()) - return addr.size() - prefix_len; - else - return 0; - } - - bool contains(const ADDR& a) const // assumes canonical address/routes - { - if (addr.defined() && version_eq(addr, a)) - return (a & netmask()) == addr; - else - return false; - } - - bool contains(const RouteType& r) const // assumes canonical routes - { - return contains(r.addr) && r.prefix_len >= prefix_len; - } - - bool split(RouteType& r1, RouteType& r2) const // assumes we are canonical - { - if (!is_host()) - { - const unsigned int newpl = prefix_len + 1; - r1.addr = addr; - r1.prefix_len = newpl; - - r2.addr = addr + netmask_(addr, newpl).extent_from_netmask(); - r2.prefix_len = newpl; - - return true; - } - return false; - } - - std::string to_string() const - { - return addr.to_string() + '/' + openvpn::to_string(prefix_len); - } - - std::string to_string_by_netmask() const - { - return addr.to_string() + ' ' + netmask().to_string(); - } - - std::string to_string_optional_prefix_len() const - { - if (prefix_len == addr.size()) - return addr.to_string(); - else - return addr.to_string() + '/' + openvpn::to_string(prefix_len); - } - - bool operator==(const RouteType& other) const - { - return std::tie(prefix_len, addr) == std::tie(other.prefix_len, other.addr); - } - - bool operator!=(const RouteType& other) const - { - return std::tie(prefix_len, addr) != std::tie(other.prefix_len, other.addr); - } - - bool operator<(const RouteType& other) const - { - return std::tie(prefix_len, addr) < std::tie(other.prefix_len, other.addr); - } - - template <typename HASH> - void hash(HASH& h) const - { - addr.hash(h); - h(prefix_len); - } - -#ifdef HAVE_CITYHASH - std::size_t hash_value() const - { - HashSizeT h; - hash(h); - return h.value(); - } -#endif - - private: - static IPv4::Addr netmask_(const IPv4::Addr&, unsigned int prefix_len) - { - return IPv4::Addr::netmask_from_prefix_len(prefix_len); - } - - static IPv6::Addr netmask_(const IPv6::Addr&, unsigned int prefix_len) - { - return IPv6::Addr::netmask_from_prefix_len(prefix_len); - } - - static IP::Addr netmask_(const IP::Addr& addr, unsigned int prefix_len) - { - return IP::Addr::netmask_from_prefix_len(addr.version(), prefix_len); - } - - static bool version_eq(const IPv4::Addr&, const IPv4::Addr&) - { - return true; - } - - static bool version_eq(const IPv6::Addr&, const IPv6::Addr&) - { - return true; - } - - static bool version_eq(const IP::Addr& a1, const IP::Addr& a2) - { - return a1.version() == a2.version(); - } - }; - - template <typename ADDR> - struct RouteTypeList : public std::vector<RouteType<ADDR>> - { - typedef std::vector< RouteType<ADDR> > Base; - - OPENVPN_EXCEPTION(route_list_error); - - std::string to_string() const - { - std::ostringstream os; - for (auto &r : *this) - os << r.to_string() << std::endl; - return os.str(); - } - - IP::Addr::VersionMask version_mask() const - { - IP::Addr::VersionMask mask = 0; - for (auto &r : *this) - mask |= r.version_mask(); - return mask; - } - - void verify_canonical() const - { - for (auto &r : *this) - r.verify_canonical(); - } - - template <typename R> - bool contains(const R& c) const - { - for (auto &r : *this) - if (r.contains(c)) - return true; - return false; - } - }; - - typedef RouteType<IP::Addr> Route; - typedef RouteType<IPv4::Addr> Route4; - typedef RouteType<IPv6::Addr> Route6; - - typedef RouteTypeList<IP::Addr> RouteList; - typedef RouteTypeList<IPv4::Addr> Route4List; - typedef RouteTypeList<IPv6::Addr> Route6List; - - OPENVPN_OSTREAM(Route, to_string); - OPENVPN_OSTREAM(Route4, to_string); - OPENVPN_OSTREAM(Route6, to_string); - - OPENVPN_OSTREAM(RouteList, to_string); - OPENVPN_OSTREAM(Route4List, to_string); - OPENVPN_OSTREAM(Route6List, to_string); - - template <typename TITLE> - inline Route route_from_string_prefix(const std::string& addrstr, - const unsigned int prefix_len, - const TITLE& title, - const IP::Addr::Version required_version = IP::Addr::UNSPEC) - { - Route r; - r.addr = IP::Addr(addrstr, title, required_version); - r.prefix_len = prefix_len; - if (r.prefix_len > r.addr.size()) - OPENVPN_THROW(Route::route_error, title << " : bad prefix length : " << addrstr); - return r; - } - - template <typename TITLE> - inline Route route_from_string(const std::string& rtstr, - const TITLE& title, - const IP::Addr::Version required_version = IP::Addr::UNSPEC) - { - Route r(rtstr, title); - r.addr.validate_version(title, required_version); - return r; - } - - } -} - -#ifdef HAVE_CITYHASH -OPENVPN_HASH_METHOD(openvpn::IP::Route, hash_value); -OPENVPN_HASH_METHOD(openvpn::IP::Route4, hash_value); -OPENVPN_HASH_METHOD(openvpn::IP::Route6, hash_value); -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cf.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cf.hpp deleted file mode 100644 index 15e7e1f..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cf.hpp +++ /dev/null @@ -1,459 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CF_H -#define OPENVPN_APPLECRYPTO_CF_CF_H - -#include <string> -#include <iostream> -#include <sstream> -#include <algorithm> -#include <utility> -#include <exception> - -#include <CoreFoundation/CoreFoundation.h> - -// Wrapper classes for Apple Core Foundation objects. - -#define OPENVPN_CF_WRAP(cls, castmeth, cftype, idmeth) \ - template <> \ - struct Type<cftype> \ - { \ - static CFTypeRef cast(CFTypeRef obj) \ - { \ - if (obj && CFGetTypeID(obj) == idmeth()) \ - return obj; \ - else \ - return nullptr; \ - } \ - }; \ - typedef Wrap<cftype> cls; \ - inline cls castmeth(CFTypeRef obj) \ - { \ - CFTypeRef o = Type<cftype>::cast(obj); \ - if (o) \ - return cls(cftype(o), GET); \ - else \ - return cls(); \ - } - -namespace openvpn { - namespace CF - { - enum Rule { - CREATE, // create rule - GET // get rule - }; - - template <typename T> struct Type {}; - - template <typename T> - class Wrap - { - public: - Wrap() : obj_(nullptr) {} - - explicit Wrap(T obj, const Rule rule=CREATE) - { - if (rule == GET && obj) - CFRetain(obj); - obj_ = obj; - } - - Wrap(const Wrap& other) - { - obj_ = other.obj_; - if (obj_) - CFRetain(obj_); - } - - Wrap& operator=(const Wrap& other) - { - if (other.obj_) - CFRetain(other.obj_); - if (obj_) - CFRelease(obj_); - obj_ = other.obj_; - return *this; - } - - Wrap(Wrap&& other) noexcept - { - obj_ = other.obj_; - other.obj_ = nullptr; - } - - Wrap& operator=(Wrap&& other) noexcept - { - if (obj_) - CFRelease(obj_); - obj_ = other.obj_; - other.obj_ = nullptr; - return *this; - } - - void swap(Wrap& other) - { - std::swap(obj_, other.obj_); - } - - void reset(T obj=nullptr, const Rule rule=CREATE) - { - if (rule == GET && obj) - CFRetain(obj); - if (obj_) - CFRelease(obj_); - obj_ = obj; - } - - bool defined() const { return obj_ != nullptr; } - - explicit operator bool() const noexcept - { - return defined(); - } - - T operator()() const { return obj_; } - - CFTypeRef generic() const { return (CFTypeRef)obj_; } - - static T cast(CFTypeRef obj) { return T(Type<T>::cast(obj)); } - - static Wrap from_generic(CFTypeRef obj, const Rule rule=CREATE) - { - return Wrap(cast(obj), rule); - } - - T release() - { - T ret = obj_; - obj_ = nullptr; - return ret; - } - - CFTypeRef generic_release() - { - T ret = obj_; - obj_ = nullptr; - return (CFTypeRef)ret; - } - - // Intended for use with Core Foundation methods that require - // a T* for saving a create-rule return value - T* mod_ref() - { - if (obj_) - { - CFRelease(obj_); - obj_ = nullptr; - } - return &obj_; - } - - void show() const - { - if (obj_) - CFShow(obj_); - else - std::cerr << "CF_UNDEFINED" << std::endl; - } - - virtual ~Wrap() - { - if (obj_) - CFRelease(obj_); - } - - private: - Wrap& operator=(T obj) = delete; // prevent use because no way to pass rule parameter - - T obj_; - }; - - // common CF types - - OPENVPN_CF_WRAP(String, string_cast, CFStringRef, CFStringGetTypeID) - OPENVPN_CF_WRAP(Number, number_cast, CFNumberRef, CFNumberGetTypeID) - OPENVPN_CF_WRAP(Bool, bool_cast, CFBooleanRef, CFBooleanGetTypeID) - OPENVPN_CF_WRAP(Data, data_cast, CFDataRef, CFDataGetTypeID) - OPENVPN_CF_WRAP(Array, array_cast, CFArrayRef, CFArrayGetTypeID) - OPENVPN_CF_WRAP(MutableArray, mutable_array_cast, CFMutableArrayRef, CFArrayGetTypeID) - OPENVPN_CF_WRAP(Dict, dict_cast, CFDictionaryRef, CFDictionaryGetTypeID) - OPENVPN_CF_WRAP(MutableDict, mutable_dict_cast, CFMutableDictionaryRef, CFDictionaryGetTypeID) - OPENVPN_CF_WRAP(Error, error_cast, CFErrorRef, CFErrorGetTypeID); - - // generic CFTypeRef wrapper - - typedef Wrap<CFTypeRef> Generic; - - inline Generic generic_cast(CFTypeRef obj) - { - return Generic(obj, GET); - } - - // constructors - - inline String string(const char *str) - { - return String(CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8)); - } - - inline String string(CFStringRef str) - { - return String(str, GET); - } - - inline String string(const String& str) - { - return String(str); - } - - inline String string(const std::string& str) - { - return String(CFStringCreateWithCString(kCFAllocatorDefault, str.c_str(), kCFStringEncodingUTF8)); - } - - inline String string(const std::string* str) - { - return String(CFStringCreateWithCString(kCFAllocatorDefault, str->c_str(), kCFStringEncodingUTF8)); - } - - inline Number number_from_int(const int n) - { - return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &n)); - } - - inline Number number_from_int32(const SInt32 n) - { - return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &n)); - } - - inline Number number_from_long_long(const long long n) - { - return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &n)); - } - - inline Number number_from_index(const CFIndex n) - { - return Number(CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &n)); - } - - inline Data data(const void *bytes, CFIndex length) - { - return Data(CFDataCreate(kCFAllocatorDefault, (const UInt8 *)bytes, length)); - } - - inline Array array(const void **values, CFIndex numValues) - { - return Array(CFArrayCreate(kCFAllocatorDefault, values, numValues, &kCFTypeArrayCallBacks)); - } - - inline Dict dict(const void **keys, const void **values, CFIndex numValues) - { - return Dict(CFDictionaryCreate(kCFAllocatorDefault, - keys, - values, - numValues, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - } - - inline Dict const_dict(MutableDict& mdict) - { - return Dict(mdict(), CF::GET); - } - - inline Array const_array(MutableArray& marray) - { - return Array(marray(), CF::GET); - } - - inline Dict empty_dict() - { - return Dict(CFDictionaryCreate(kCFAllocatorDefault, - nullptr, - nullptr, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - } - - inline MutableArray mutable_array(const CFIndex capacity=0) - { - return MutableArray(CFArrayCreateMutable(kCFAllocatorDefault, capacity, &kCFTypeArrayCallBacks)); - } - - inline MutableDict mutable_dict(const CFIndex capacity=0) - { - return MutableDict(CFDictionaryCreateMutable(kCFAllocatorDefault, capacity, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - } - - template <typename DICT> - inline MutableDict mutable_dict_copy(const DICT& dict, const CFIndex capacity=0) - { - if (dict.defined()) - return MutableDict(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, capacity, dict())); - else - return mutable_dict(capacity); - } - - inline Error error(CFStringRef domain, CFIndex code, CFDictionaryRef userInfo) - { - return Error(CFErrorCreate(kCFAllocatorDefault, domain, code, userInfo)); - } - - // accessors - - template <typename ARRAY> - inline CFIndex array_len(const ARRAY& array) - { - if (array.defined()) - return CFArrayGetCount(array()); - else - return 0; - } - - template <typename DICT> - inline CFIndex dict_len(const DICT& dict) - { - if (dict.defined()) - return CFDictionaryGetCount(dict()); - else - return 0; - } - - template <typename ARRAY> - inline CFTypeRef array_index(const ARRAY& array, const CFIndex idx) - { - if (array.defined() && CFArrayGetCount(array()) > idx) - return CFArrayGetValueAtIndex(array(), idx); - else - return nullptr; - } - - template <typename DICT, typename KEY> - inline CFTypeRef dict_index(const DICT& dict, const KEY& key) - { - if (dict.defined()) - { - String keystr = string(key); - if (keystr.defined()) - return CFDictionaryGetValue(dict(), keystr()); - } - return nullptr; - } - - // string methods - - struct cppstring_error : public std::exception - { - virtual const char* what() const throw() - { - return "cppstring_error"; - } - }; - - inline std::string cppstring(CFStringRef str) - { - const CFStringEncoding encoding = kCFStringEncodingUTF8; - if (str) - { - const CFIndex len = CFStringGetLength(str); - if (len > 0) - { - const CFIndex maxsize = CFStringGetMaximumSizeForEncoding(len, encoding); - char *buf = new char[maxsize]; - const Boolean status = CFStringGetCString(str, buf, maxsize, encoding); - if (status) - { - std::string ret(buf); - delete [] buf; - return ret; - } - else - { - delete [] buf; - throw cppstring_error(); - } - } - } - return ""; - } - - inline std::string cppstring(const String& str) - { - return cppstring(str()); - } - - inline std::string description(CFTypeRef obj) - { - if (obj) - { - String s(CFCopyDescription(obj)); - return cppstring(s); - } - else - return "UNDEF"; - } - - // format an array of strings (non-string elements in array are ignored) - template <typename ARRAY> - inline std::string array_to_string(const ARRAY& array, const char delim=',') - { - std::ostringstream os; - const CFIndex len = array_len(array); - if (len) - { - bool sep = false; - for (CFIndex i = 0; i < len; ++i) - { - const String v(string_cast(array_index(array, i))); - if (v.defined()) - { - if (sep) - os << delim; - os << cppstring(v); - sep = true; - } - } - } - return os.str(); - } - - inline bool string_equal(const String& s1, const String& s2, const CFStringCompareFlags compareOptions = 0) - { - return s1.defined() && s2.defined() && CFStringCompare(s1(), s2(), compareOptions) == kCFCompareEqualTo; - } - - // property lists - inline Data plist(CFTypeRef obj) - { - return Data(CFPropertyListCreateData(kCFAllocatorDefault, - obj, - kCFPropertyListBinaryFormat_v1_0, - 0, - nullptr)); - } - - } // namespace CF -} // namespace openvpn - -#endif // OPENVPN_APPLECRYPTO_CF_CF_H diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfhelper.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfhelper.hpp deleted file mode 100644 index 90630dc..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfhelper.hpp +++ /dev/null @@ -1,261 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFHELPER_H -#define OPENVPN_APPLECRYPTO_CF_CFHELPER_H - -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/apple/cf/cf.hpp> - -// These methods build on the Wrapper classes for Apple Core Foundation objects -// defined in cf.hpp. They add additional convenience methods, such as dictionary -// lookup. - -namespace openvpn { - namespace CF { - - // essentially a vector of void *, used as source for array and dictionary constructors - typedef BufferAllocatedType<CFTypeRef, thread_unsafe_refcount> SrcList; - - inline Array array(const SrcList& values) - { - return array((const void **)values.c_data(), values.size()); - } - - inline Dict dict(const SrcList& keys, const SrcList& values) - { - return dict((const void **)keys.c_data(), (const void **)values.c_data(), std::min(keys.size(), values.size())); - } - - inline CFTypeRef mutable_dict_new() - { - return CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - - inline CFTypeRef mutable_array_new() - { - return CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - } - - // Lookup or create (if absent) an item in a mutable dictionary. - // Return the item, which will be owned by base. - template <typename KEY> - inline CFTypeRef dict_get_create(CFMutableDictionaryRef base, - const KEY& key, - CFTypeRef (*create_method)()) - { - if (base) - { - String keystr = string(key); - CFTypeRef ret = CFDictionaryGetValue(base, keystr()); // try lookup first - if (!ret) - { - // doesn't exist, must create - ret = (*create_method)(); - CFDictionaryAddValue(base, keystr(), ret); - CFRelease(ret); // because ret is now owned by base - } - return ret; - } - return nullptr; - } - - // lookup a dict in another dict (base) and return or create if absent - template <typename KEY> - inline MutableDict dict_get_create_dict(MutableDict& base, const KEY& key) - { - String keystr = string(key); - return mutable_dict_cast(dict_get_create(base(), keystr(), mutable_dict_new)); - } - - // lookup an array in a dict (base) and return or create if absent - template <typename KEY> - inline MutableArray dict_get_create_array(MutableDict& base, const KEY& key) - { - String keystr = string(key); - return mutable_array_cast(dict_get_create(base(), keystr(), mutable_array_new)); - } - - // lookup an object in a dictionary (DICT should be a Dict or a MutableDict) - template <typename DICT, typename KEY> - inline CFTypeRef dict_get_obj(const DICT& dict, const KEY& key) - { - return dict_index(dict, key); - } - - // lookup a string in a dictionary (DICT should be a Dict or a MutableDict) - template <typename DICT, typename KEY> - inline std::string dict_get_str(const DICT& dict, const KEY& key) - { - return cppstring(string_cast(dict_index(dict, key))); - } - - // lookup a string in a dictionary (DICT should be a Dict or a MutableDict) - template <typename DICT, typename KEY> - inline std::string dict_get_str(const DICT& dict, const KEY& key, const std::string& default_value) - { - String str(string_cast(dict_index(dict, key))); - if (str.defined()) - return cppstring(str()); - else - return default_value; - } - - // lookup an integer in a dictionary (DICT should be a Dict or a MutableDict) - template <typename DICT, typename KEY> - inline int dict_get_int(const DICT& dict, const KEY& key, const int default_value) - { - int ret; - Number num = number_cast(dict_index(dict, key)); - if (num.defined() && CFNumberGetValue(num(), kCFNumberIntType, &ret)) - return ret; - else - return default_value; - } - - // lookup a boolean in a dictionary (DICT should be a Dict or a MutableDict) - template <typename DICT, typename KEY> - inline bool dict_get_bool(const DICT& dict, const KEY& key, const bool default_value) - { - Bool b = bool_cast(dict_index(dict, key)); - if (b.defined()) - { - if (b() == kCFBooleanTrue) - return true; - else if (b() == kCFBooleanFalse) - return false; - } - return default_value; - } - - // like CFDictionarySetValue, but no-op if any args are NULL - inline void dictionarySetValue(CFMutableDictionaryRef theDict, const void *key, const void *value) - { - if (theDict && key && value) - CFDictionarySetValue(theDict, key, value); - } - - // like CFArrayAppendValue, but no-op if any args are NULL - inline void arrayAppendValue(CFMutableArrayRef theArray, const void *value) - { - if (theArray && value) - CFArrayAppendValue(theArray, value); - } - - // set a CFTypeRef in a mutable dictionary - template <typename KEY> - inline void dict_set_obj(MutableDict& dict, const KEY& key, CFTypeRef value) - { - String keystr = string(key); - dictionarySetValue(dict(), keystr(), value); - } - - // set a string in a mutable dictionary - - template <typename KEY, typename VALUE> - inline void dict_set_str(MutableDict& dict, const KEY& key, const VALUE& value) - { - String keystr = string(key); - String valstr = string(value); - dictionarySetValue(dict(), keystr(), valstr()); - } - - // set a number in a mutable dictionary - - template <typename KEY> - inline void dict_set_int(MutableDict& dict, const KEY& key, int value) - { - String keystr = string(key); - Number num = number_from_int(value); - dictionarySetValue(dict(), keystr(), num()); - } - - template <typename KEY> - inline void dict_set_int32(MutableDict& dict, const KEY& key, SInt32 value) - { - String keystr = string(key); - Number num = number_from_int32(value); - dictionarySetValue(dict(), keystr(), num()); - } - - template <typename KEY> - inline void dict_set_long_long(MutableDict& dict, const KEY& key, long long value) - { - String keystr = string(key); - Number num = number_from_long_long(value); - dictionarySetValue(dict(), keystr(), num()); - } - - template <typename KEY> - inline void dict_set_index(MutableDict& dict, const KEY& key, CFIndex value) - { - String keystr = string(key); - Number num = number_from_index(value); - dictionarySetValue((CFMutableDictionaryRef)dict(), keystr(), num()); - } - - // set a boolean in a mutable dictionary - - template <typename KEY> - inline void dict_set_bool(MutableDict& dict, const KEY& key, bool value) - { - String keystr = string(key); - CFBooleanRef boolref = value ? kCFBooleanTrue : kCFBooleanFalse; - dictionarySetValue(dict(), keystr(), boolref); - } - - // append string to a mutable array - - template <typename VALUE> - inline void array_append_str(MutableArray& array, const VALUE& value) - { - String valstr = string(value); - arrayAppendValue(array(), valstr()); - } - - // append a number to a mutable array - - inline void array_append_int(MutableArray& array, int value) - { - Number num = number_from_int(value); - arrayAppendValue(array(), num()); - } - - inline void array_append_int32(MutableArray& array, SInt32 value) - { - Number num = number_from_int32(value); - arrayAppendValue(array(), num()); - } - - inline void array_append_long_long(MutableArray& array, long long value) - { - Number num = number_from_long_long(value); - arrayAppendValue(array(), num()); - } - - inline void array_append_index(MutableArray& array, CFIndex value) - { - Number num = number_from_index(value); - arrayAppendValue(array(), num()); - } - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfhost.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfhost.hpp deleted file mode 100644 index c1ba633..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfhost.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFHOST_H -#define OPENVPN_APPLECRYPTO_CF_CFHOST_H - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(Host, host_cast, CFHostRef, CFHostGetTypeID) - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfrunloop.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfrunloop.hpp deleted file mode 100644 index 102881f..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfrunloop.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFRUNLOOP_H -#define OPENVPN_APPLECRYPTO_CF_CFRUNLOOP_H - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(RunLoop, runloop_cast, CFRunLoopRef, CFRunLoopGetTypeID) - OPENVPN_CF_WRAP(RunLoopSource, runloop_source_cast, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfsec.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfsec.hpp deleted file mode 100644 index e0fdb2f..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfsec.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFSEC_H -#define OPENVPN_APPLECRYPTO_CF_CFSEC_H - -#include <openvpn/common/platform.hpp> - -#include <Security/SecCertificate.h> -#include <Security/SecIdentity.h> -#include <Security/SecPolicy.h> -#include <Security/SecTrust.h> - -#ifndef OPENVPN_PLATFORM_IPHONE -#include <Security/SecKeychain.h> -#include <Security/SecAccess.h> -#endif - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/apple/cf/cf.hpp> - -// Define C++ wrappings for Apple security-related objects. - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(Cert, cert_cast, SecCertificateRef, SecCertificateGetTypeID) - OPENVPN_CF_WRAP(Key, key_cast, SecKeyRef, SecKeyGetTypeID) - OPENVPN_CF_WRAP(Identity, identity_cast, SecIdentityRef, SecIdentityGetTypeID) - OPENVPN_CF_WRAP(Policy, policy_cast, SecPolicyRef, SecPolicyGetTypeID) - OPENVPN_CF_WRAP(Trust, trust_cast, SecTrustRef, SecTrustGetTypeID) -#ifndef OPENVPN_PLATFORM_IPHONE - OPENVPN_CF_WRAP(Keychain, keychain_cast, SecKeychainRef, SecKeychainGetTypeID) - OPENVPN_CF_WRAP(Access, access_cast, SecAccessRef, SecAccessGetTypeID) -#endif - } // namespace CF - -} // namespace openvpn - -#endif // OPENVPN_APPLECRYPTO_CF_CFSEC_H diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfsocket.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfsocket.hpp deleted file mode 100644 index ea61196..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfsocket.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFSTREAM_H -#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(Socket, socket_cast, CFSocketRef, CFSocketGetTypeID) - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cfstream.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cfstream.hpp deleted file mode 100644 index 357acc1..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cfstream.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFSTREAM_H -#define OPENVPN_APPLECRYPTO_CF_CFSTREAM_H - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(ReadStream, read_stream_cast, CFReadStreamRef, CFReadStreamGetTypeID) - OPENVPN_CF_WRAP(WriteStream, write_stream_cast, CFWriteStreamRef, CFWriteStreamGetTypeID) - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/cftimer.hpp b/Sources/OpenVPN3/openvpn/apple/cf/cftimer.hpp deleted file mode 100644 index 31aff23..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/cftimer.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_CFTIMER_H -#define OPENVPN_APPLECRYPTO_CF_CFTIMER_H - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(Timer, timer_cast, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID) - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/cf/error.hpp b/Sources/OpenVPN3/openvpn/apple/cf/error.hpp deleted file mode 100644 index e609205..0000000 --- a/Sources/OpenVPN3/openvpn/apple/cf/error.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CF_ERROR_H -#define OPENVPN_APPLECRYPTO_CF_ERROR_H - -#include <string> - -#include <CoreFoundation/CFBase.h> - -#include <openvpn/common/exception.hpp> - -// An exception object that encapsulates Apple Core Foundation errors. - -namespace openvpn { - - // string exception class - class CFException : public std::exception - { - public: - CFException(const std::string& text) - { - errtxt = text; - } - - CFException(const std::string& text, const OSStatus status) - { - set_errtxt(text, status); - } - - virtual const char* what() const throw() { return errtxt.c_str(); } - std::string what_str() const { return errtxt; } - - virtual ~CFException() throw() {} - - private: - void set_errtxt(const std::string& text, const OSStatus status) - { - std::ostringstream s; - s << text << ": OSX Error code=" << status; - errtxt = s.str(); - } - - std::string errtxt; - }; - -} // namespace openvpn - -#endif // OPENVPN_APPLECRYPTO_CF_ERROR_H diff --git a/Sources/OpenVPN3/openvpn/apple/iosactiveiface.hpp b/Sources/OpenVPN3/openvpn/apple/iosactiveiface.hpp deleted file mode 100644 index 3227a81..0000000 --- a/Sources/OpenVPN3/openvpn/apple/iosactiveiface.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// 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-2020 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/>. - -#include <string> - -#include <openvpn/apple/reach.hpp> -#include <openvpn/netconf/enumiface.hpp> - -#ifndef OPENVPN_APPLECRYPTO_UTIL_IOSACTIVEIFACE_H -#define OPENVPN_APPLECRYPTO_UTIL_IOSACTIVEIFACE_H - -namespace openvpn { - - class iOSActiveInterface : public ReachabilityInterface - { - public: - virtual Status reachable() const - { - if (ei.iface_up("en0")) - return ReachableViaWiFi; - else if (ei.iface_up("pdp_ip0")) - return ReachableViaWWAN; - else - return NotReachable; - } - - virtual bool reachableVia(const std::string& net_type) const - { - const Status r = reachable(); - if (net_type == "cellular") - return r == ReachableViaWWAN; - else if (net_type == "wifi") - return r == ReachableViaWiFi; - else - return r != NotReachable; - } - - virtual std::string to_string() const - { - switch (reachable()) - { - case ReachableViaWiFi: - return "ReachableViaWiFi"; - case ReachableViaWWAN: - return "ReachableViaWWAN"; - case NotReachable: - return "NotReachable"; - } - } - - private: - EnumIface ei; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/maclife.hpp b/Sources/OpenVPN3/openvpn/apple/maclife.hpp deleted file mode 100644 index a1920a8..0000000 --- a/Sources/OpenVPN3/openvpn/apple/maclife.hpp +++ /dev/null @@ -1,325 +0,0 @@ -// 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-2020 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_APPLE_MACLIFE_H -#define OPENVPN_APPLE_MACLIFE_H - -#include <string> -#include <sstream> - -#include <thread> - -#include <openvpn/log/logthread.hpp> -#include <openvpn/apple/cf/cftimer.hpp> -#include <openvpn/apple/cf/cfhelper.hpp> -#include <openvpn/apple/cf/cfrunloop.hpp> -#include <openvpn/apple/reachable.hpp> -#include <openvpn/client/clilife.hpp> -#include <openvpn/apple/macsleep.hpp> -#include <openvpn/apple/scdynstore.hpp> - -namespace openvpn { - class MacLifeCycle : public ClientLifeCycle, MacSleep, ReachabilityTracker - { - public: - OPENVPN_EXCEPTION(mac_lifecycle_error); - - MacLifeCycle() - : ReachabilityTracker(true, false), - nc(nullptr), - thread(nullptr), - paused(false) - { - } - - virtual ~MacLifeCycle() - { - stop_thread(); - } - - virtual bool network_available() - { - return net_up(); - } - - virtual void start(NotifyCallback* nc_arg) - { - if (!thread && nc_arg) - { - nc = nc_arg; - thread = new std::thread(&MacLifeCycle::thread_func, this); - } - } - - virtual void stop() - { - stop_thread(); - } - - private: - struct State - { - State() - : net_up(false), - sleep(false) - { - } - - State(bool net_up_arg, const std::string& iface_arg, bool sleep_arg) - : net_up(net_up_arg), - iface(iface_arg), - sleep(sleep_arg) - { - } - - bool operator==(const State& other) const - { - return net_up == other.net_up && iface == other.iface && sleep == other.sleep; - } - - bool operator!=(const State& other) const - { - return !operator==(other); - } - - std::string to_string() const - { - std::ostringstream os; - os << "[net_up=" << net_up << " iface=" << iface << " sleep=" << sleep << ']'; - return os.str(); - } - - bool net_up; - std::string iface; - bool sleep; - }; - - void stop_thread() - { - if (thread) - { - if (runloop.defined()) - CFRunLoopStop(runloop()); - thread->join(); - delete thread; - thread = nullptr; - } - } - - void thread_func() - { - runloop.reset(CFRunLoopGetCurrent(), CF::GET); - Log::Context logctx(logwrap); - try { - // set up dynamic store query object - dstore.reset(SCDynamicStoreCreate(kCFAllocatorDefault, - CFSTR("OpenVPN_MacLifeCycle"), - nullptr, - nullptr)); - - // init state - state = State(net_up(), primary_interface(), false); - prev_state = state; - paused = false; - - // enable sleep/wakeup notifications - mac_sleep_start(); - - // enable network reachability notifications - reachability_tracker_schedule(); - - // enable interface change notifications - iface_watch(); - - // process event loop until CFRunLoopStop is called from parent thread - CFRunLoopRun(); - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacLifeCycle exception: " << e.what()); - } - - // cleanup - cancel_action_timer(); - mac_sleep_stop(); - reachability_tracker_cancel(); - dstore.reset(); - } - - std::string primary_interface() - { - CF::Dict dict(CF::DynamicStoreCopyDict(dstore, "State:/Network/Global/IPv4")); - return CF::dict_get_str(dict, "PrimaryInterface"); - } - - bool net_up() - { - ReachabilityViaInternet r; - return ReachabilityViaInternet::status_from_flags(r.flags()) != ReachabilityInterface::NotReachable; - } - - void iface_watch() - { - SCDynamicStoreContext context = {0, this, nullptr, nullptr, nullptr}; - CF::DynamicStore ds(SCDynamicStoreCreate(kCFAllocatorDefault, - CFSTR("OpenVPN_MacLifeCycle_iface_watch"), - iface_watch_callback_static, - &context)); - if (!ds.defined()) - throw mac_lifecycle_error("SCDynamicStoreCreate"); - CF::MutableArray watched_keys(CF::mutable_array()); - CF::array_append_str(watched_keys, "State:/Network/Global/IPv4"); - //CF::array_append_str(watched_keys, "State:/Network/Global/IPv6"); - if (!watched_keys.defined()) - throw mac_lifecycle_error("watched_keys is undefined"); - if (!SCDynamicStoreSetNotificationKeys(ds(), - watched_keys(), - nullptr)) - throw mac_lifecycle_error("SCDynamicStoreSetNotificationKeys failed"); - CF::RunLoopSource rls(SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, ds(), 0)); - if (!rls.defined()) - throw mac_lifecycle_error("SCDynamicStoreCreateRunLoopSource failed"); - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls(), kCFRunLoopDefaultMode); - } - - static void iface_watch_callback_static(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg) - { - MacLifeCycle *self = (MacLifeCycle *)arg; - self->iface_watch_callback(store, changedKeys); - } - - void iface_watch_callback(SCDynamicStoreRef store, CFArrayRef changedKeys) - { - state.iface = primary_interface(); - OPENVPN_LOG("MacLifeCycle NET_IFACE " << state.iface); - schedule_action_timer(1); - } - - virtual void notify_sleep() - { - OPENVPN_LOG("MacLifeCycle SLEEP"); - state.sleep = true; - schedule_action_timer(0); - } - - virtual void notify_wakeup() - { - OPENVPN_LOG("MacLifeCycle WAKEUP"); - state.sleep = false; - schedule_action_timer(1); - } - - virtual void reachability_tracker_event(const ReachabilityBase& rb, SCNetworkReachabilityFlags flags) - { - if (rb.vtype() == ReachabilityBase::Internet) - { - const ReachabilityBase::Status status = rb.vstatus(flags); - state.net_up = (status != ReachabilityInterface::NotReachable); - OPENVPN_LOG("MacLifeCycle NET_STATE " << state.net_up << " status=" << ReachabilityBase::render_status(status) << " flags=" << ReachabilityBase::render_flags(flags)); - schedule_action_timer(1); - } - } - - void schedule_action_timer(const int seconds) - { - cancel_action_timer(); - if (seconds) - { - CFRunLoopTimerContext context = { 0, this, nullptr, nullptr, nullptr }; - action_timer.reset(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + seconds, 0, 0, 0, action_timer_callback_static, &context)); - if (action_timer.defined()) - CFRunLoopAddTimer(CFRunLoopGetCurrent(), action_timer(), kCFRunLoopCommonModes); - else - OPENVPN_LOG("MacLifeCycle::schedule_action_timer: failed to create timer"); - } - else - action_timer_callback(nullptr); - } - - void cancel_action_timer() - { - if (action_timer.defined()) - { - CFRunLoopTimerInvalidate(action_timer()); - action_timer.reset(nullptr); - } - } - - static void action_timer_callback_static(CFRunLoopTimerRef timer, void *info) - { - MacLifeCycle* self = (MacLifeCycle*)info; - self->action_timer_callback(timer); - } - - void action_timer_callback(CFRunLoopTimerRef timer) - { - try { - if (state != prev_state) - { - OPENVPN_LOG("MacLifeCycle ACTION pause=" << paused << " state=" << state.to_string() << " prev=" << prev_state.to_string()); - if (paused) - { - if (!state.sleep && state.net_up) - { - nc->cln_resume(); - paused = false; - } - } - else - { - if (state.sleep) - { - nc->cln_pause("sleep"); - paused = true; - } - else if (!state.net_up) - { - nc->cln_pause("network-unavailable"); - paused = true; - } - else - { - if (state.iface != prev_state.iface) - nc->cln_reconnect(0); - } - } - prev_state = state; - } - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacLifeCycle::action_timer_callback exception: " << e.what()); - } - } - - NotifyCallback* nc; - std::thread* thread; - CF::RunLoop runloop; // run loop in thread - CF::DynamicStore dstore; - State state; - State prev_state; - bool paused; - CF::Timer action_timer; - Log::Context::Wrapper logwrap; // used to carry forward the log context from parent thread - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/macsleep.hpp b/Sources/OpenVPN3/openvpn/apple/macsleep.hpp deleted file mode 100644 index 8584fe8..0000000 --- a/Sources/OpenVPN3/openvpn/apple/macsleep.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// 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-2020 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_APPLE_MACSLEEP_H -#define OPENVPN_APPLE_MACSLEEP_H - -#include <mach/mach_port.h> -#include <mach/mach_interface.h> -#include <mach/mach_init.h> - -#include <IOKit/pwr_mgt/IOPMLib.h> -#include <IOKit/IOMessage.h> - -#include <openvpn/common/size.hpp> - -namespace openvpn { - class MacSleep - { - MacSleep(const MacSleep&) = delete; - MacSleep& operator=(const MacSleep&) = delete; - - public: - MacSleep() - : root_port(0), - notifyPortRef(nullptr), - notifierObject(0) - { - } - - virtual ~MacSleep() - { - mac_sleep_stop(); - } - - bool mac_sleep_start() - { - if (!root_port) - { - root_port = IORegisterForSystemPower(this, ¬ifyPortRef, callback_static, ¬ifierObject); - if (!root_port) - return false; - CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); - } - return true; - } - - void mac_sleep_stop() - { - if (root_port) - { - // remove the sleep notification port from the application runloop - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(notifyPortRef), - kCFRunLoopCommonModes); - - // deregister for system sleep notifications - IODeregisterForSystemPower(¬ifierObject); - - // IORegisterForSystemPower implicitly opens the Root Power Domain IOService - // so we close it here - IOServiceClose(root_port); - - // destroy the notification port allocated by IORegisterForSystemPower - IONotificationPortDestroy(notifyPortRef); - - // reset object members - root_port = 0; - notifyPortRef = nullptr; - notifierObject = 0; - } - } - - virtual void notify_sleep() = 0; - virtual void notify_wakeup() = 0; - - private: - static void callback_static(void* arg, io_service_t service, natural_t messageType, void *messageArgument) - { - MacSleep* self = (MacSleep*)arg; - self->callback(service, messageType, messageArgument); - } - - void callback(io_service_t service, natural_t messageType, void *messageArgument) - { - switch (messageType) - { - case kIOMessageCanSystemSleep: - IOAllowPowerChange(root_port, (long)messageArgument); - break; - case kIOMessageSystemWillSleep: - notify_sleep(); - IOAllowPowerChange(root_port, (long)messageArgument); - break; - case kIOMessageSystemHasPoweredOn: - notify_wakeup(); - break; - } - } - - // a reference to the Root Power Domain IOService - io_connect_t root_port; - - // notification port allocated by IORegisterForSystemPower - IONotificationPortRef notifyPortRef; - - // notifier object, used to deregister later - io_object_t notifierObject; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/macver.hpp b/Sources/OpenVPN3/openvpn/apple/macver.hpp deleted file mode 100644 index bca35c3..0000000 --- a/Sources/OpenVPN3/openvpn/apple/macver.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// 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-2020 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_APPLE_MACVER_H -#define OPENVPN_APPLE_MACVER_H - -#include <errno.h> -#include <sys/sysctl.h> - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/split.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/apple/ver.hpp> - -namespace openvpn { - namespace Mac { - class Version : public AppleVersion - { - public: - // Mac OS X versions - // 15.x.x OS X 10.11.x El Capitan - // 14.x.x OS X 10.10.x Yosemite - // 13.x.x OS X 10.9.x Mavericks - // 12.x.x OS X 10.8.x Mountain Lion - // 11.x.x OS X 10.7.x Lion - // 10.x.x OS X 10.6.x Snow Leopard - // 9.x.x OS X 10.5.x Leopard - // 8.x.x OS X 10.4.x Tiger - // 7.x.x OS X 10.3.x Panther - // 6.x.x OS X 10.2.x Jaguar - // 5.x OS X 10.1.x Puma - - enum { - OSX_10_11=15, - OSX_10_10=14, - OSX_10_9=13, - OSX_10_8=12, - OSX_10_7=11, - OSX_10_6=10, - }; - - Version() - { - char str[256]; - size_t size = sizeof(str); - int ret = sysctlbyname("kern.osrelease", str, &size, nullptr, 0); - if (!ret) - init(std::string(str, size)); - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/reach.hpp b/Sources/OpenVPN3/openvpn/apple/reach.hpp deleted file mode 100644 index cb59f79..0000000 --- a/Sources/OpenVPN3/openvpn/apple/reach.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// 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-2020 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_APPLECRYPTO_UTIL_REACH_H -#define OPENVPN_APPLECRYPTO_UTIL_REACH_H - -// An interface to various network reachability implementations, -// primarily for iOS. - -namespace openvpn { - struct ReachabilityInterface - { - enum Status { - NotReachable, - ReachableViaWiFi, - ReachableViaWWAN - }; - - virtual Status reachable() const = 0; - virtual bool reachableVia(const std::string& net_type) const = 0; - virtual std::string to_string() const = 0; - virtual ~ReachabilityInterface() {} - }; -} -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/reachable.hpp b/Sources/OpenVPN3/openvpn/apple/reachable.hpp deleted file mode 100644 index 9df6e97..0000000 --- a/Sources/OpenVPN3/openvpn/apple/reachable.hpp +++ /dev/null @@ -1,468 +0,0 @@ -// 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-2020 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/>. -// -// This code is derived from the Apple sample Reachability.m under -// the following license. -// -// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple -// Inc. ("Apple") in consideration of your agreement to the following -// terms, and your use, installation, modification or redistribution of -// this Apple software constitutes acceptance of these terms. If you do -// not agree with these terms, please do not use, install, modify or -// redistribute this Apple software. -// -// In consideration of your agreement to abide by the following terms, and -// subject to these terms, Apple grants you a personal, non-exclusive -// license, under Apple's copyrights in this original Apple software (the -// "Apple Software"), to use, reproduce, modify and redistribute the Apple -// Software, with or without modifications, in source and/or binary forms; -// provided that if you redistribute the Apple Software in its entirety and -// without modifications, you must retain this notice and the following -// text and disclaimers in all such redistributions of the Apple Software. -// Neither the name, trademarks, service marks or logos of Apple Inc. may -// be used to endorse or promote products derived from the Apple Software -// without specific prior written permission from Apple. Except as -// expressly stated in this notice, no other rights or licenses, express or -// implied, are granted by Apple herein, including but not limited to any -// patent rights that may be infringed by your derivative works or by other -// works in which the Apple Software may be incorporated. -// -// The Apple Software is provided by Apple on an "AS IS" basis. APPLE -// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION -// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND -// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. -// -// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL -// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, -// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED -// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), -// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Copyright (C) 2013 Apple Inc. All Rights Reserved. - -// Wrapper for Apple SCNetworkReachability methods. - -#ifndef OPENVPN_APPLECRYPTO_UTIL_REACHABLE_H -#define OPENVPN_APPLECRYPTO_UTIL_REACHABLE_H - -#import "TargetConditionals.h" - -#include <netinet/in.h> -#include <SystemConfiguration/SCNetworkReachability.h> - -#include <string> -#include <sstream> -#include <memory> - -#include <openvpn/common/socktypes.hpp> -#include <openvpn/apple/cf/cf.hpp> -#include <openvpn/apple/reach.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(NetworkReachability, network_reachability_cast, SCNetworkReachabilityRef, SCNetworkReachabilityGetTypeID); - } - - class ReachabilityBase - { - public: - typedef ReachabilityInterface::Status Status; - - enum Type { - Internet, - WiFi, - }; - - std::string to_string() const - { - return to_string(flags()); - } - - std::string to_string(const SCNetworkReachabilityFlags f) const - { - const Status s = vstatus(f); - const Type t = vtype(); - - std::string ret; - ret += render_type(t); - ret += ':'; - ret += render_status(s); - ret += '/'; - ret += render_flags(f); - return ret; - } - - Status status() const - { - return vstatus(flags()); - } - - SCNetworkReachabilityFlags flags() const - { - SCNetworkReachabilityFlags f = 0; - if (SCNetworkReachabilityGetFlags(reach(), &f) == TRUE) - return f; - else - return 0; - } - - static std::string render_type(Type type) - { - switch (type) { - case Internet: - return "Internet"; - case WiFi: - return "WiFi"; - default: - return "Type???"; - } - } - - static std::string render_status(const Status status) - { - switch (status) { - case ReachabilityInterface::NotReachable: - return "NotReachable"; - case ReachabilityInterface::ReachableViaWiFi: - return "ReachableViaWiFi"; - case ReachabilityInterface::ReachableViaWWAN: - return "ReachableViaWWAN"; - default: - return "ReachableVia???"; - } - } - - static std::string render_flags(const SCNetworkReachabilityFlags flags) - { - std::string ret; -#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR // Mac OS X doesn't define WWAN flags - if (flags & kSCNetworkReachabilityFlagsIsWWAN) - ret += 'W'; - else -#endif - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsReachable) - ret += 'R'; - else - ret += '-'; - ret += ' '; - if (flags & kSCNetworkReachabilityFlagsTransientConnection) - ret += 't'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsConnectionRequired) - ret += 'c'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) - ret += 'C'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsInterventionRequired) - ret += 'i'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) - ret += 'D'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsIsLocalAddress) - ret += 'l'; - else - ret += '-'; - if (flags & kSCNetworkReachabilityFlagsIsDirect) - ret += 'd'; - else - ret += '-'; - return ret; - } - - virtual Type vtype() const = 0; - virtual Status vstatus(const SCNetworkReachabilityFlags flags) const = 0; - - virtual ~ReachabilityBase() {} - - CF::NetworkReachability reach; - }; - - class ReachabilityViaInternet : public ReachabilityBase - { - public: - ReachabilityViaInternet() - { - struct sockaddr_in addr; - bzero(&addr, sizeof(addr)); - addr.sin_len = sizeof(addr); - addr.sin_family = AF_INET; - reach.reset(SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr*)&addr)); - } - - virtual Type vtype() const - { - return Internet; - } - - virtual Status vstatus(const SCNetworkReachabilityFlags flags) const - { - return status_from_flags(flags); - } - - static Status status_from_flags(const SCNetworkReachabilityFlags flags) - { - if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) - { - // The target host is not reachable. - return ReachabilityInterface::NotReachable; - } - - Status ret = ReachabilityInterface::NotReachable; - - if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) - { - // If the target host is reachable and no connection is required then - // we'll assume (for now) that you're on Wi-Fi... - ret = ReachabilityInterface::ReachableViaWiFi; - } - -#if 0 // don't contaminate result by considering on-demand viability - if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) - { - // ... and the connection is on-demand (or on-traffic) if the - // calling application is using the CFSocketStream or higher APIs... - - if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) - { - // ... and no [user] intervention is needed... - ret = ReachabilityInterface::ReachableViaWiFi; - } - } -#endif - -#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR // Mac OS X doesn't define WWAN flags - if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) - { - // ... but WWAN connections are OK if the calling application - // is using the CFNetwork APIs. - ret = ReachabilityInterface::ReachableViaWWAN; - } -#endif - - return ret; - } - }; - - class ReachabilityViaWiFi : public ReachabilityBase - { - public: - ReachabilityViaWiFi() - { - struct sockaddr_in addr; - bzero(&addr, sizeof(addr)); - addr.sin_len = sizeof(addr); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); // 169.254.0.0. - reach.reset(SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr*)&addr)); - } - - virtual Type vtype() const - { - return WiFi; - } - - virtual Status vstatus(const SCNetworkReachabilityFlags flags) const - { - return status_from_flags(flags); - } - - static Status status_from_flags(const SCNetworkReachabilityFlags flags) - { - Status ret = ReachabilityInterface::NotReachable; - if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) - ret = ReachabilityInterface::ReachableViaWiFi; - return ret; - } - }; - - class Reachability : public ReachabilityInterface - { - public: - Reachability(const bool enable_internet, const bool enable_wifi) - { - if (enable_internet) - internet.reset(new ReachabilityViaInternet); - if (enable_wifi) - wifi.reset(new ReachabilityViaWiFi); - } - - bool reachableViaWiFi() const { - if (internet) - { - if (wifi) - return internet->status() == ReachableViaWiFi && wifi->status() == ReachableViaWiFi; - else - return internet->status() == ReachableViaWiFi; - } - else - { - if (wifi) - return wifi->status() == ReachableViaWiFi; - else - return false; - } - } - - bool reachableViaCellular() const - { - if (internet) - return internet->status() == ReachableViaWWAN; - else - return false; - } - - virtual Status reachable() const - { - if (reachableViaWiFi()) - return ReachableViaWiFi; - else if (reachableViaCellular()) - return ReachableViaWWAN; - else - return NotReachable; - } - - virtual bool reachableVia(const std::string& net_type) const - { - if (net_type == "cellular") - return reachableViaCellular(); - else if (net_type == "wifi") - return reachableViaWiFi(); - else - return reachableViaWiFi() || reachableViaCellular(); - } - - virtual std::string to_string() const - { - std::string ret; - if (internet) - ret += internet->to_string(); - if (internet && wifi) - ret += ' '; - if (wifi) - ret += wifi->to_string(); - return ret; - } - - std::unique_ptr<ReachabilityViaInternet> internet; - std::unique_ptr<ReachabilityViaWiFi> wifi; - }; - - class ReachabilityTracker - { - public: - ReachabilityTracker(const bool enable_internet, const bool enable_wifi) - : reachability(enable_internet, enable_wifi), - scheduled(false) - { - } - - void reachability_tracker_schedule() - { - if (!scheduled) - { - if (reachability.internet) - schedule(*reachability.internet, internet_callback_static); - if (reachability.wifi) - schedule(*reachability.wifi, wifi_callback_static); - scheduled = true; - } - } - - void reachability_tracker_cancel() - { - if (scheduled) - { - if (reachability.internet) - cancel(*reachability.internet); - if (reachability.wifi) - cancel(*reachability.wifi); - scheduled = false; - } - } - - virtual void reachability_tracker_event(const ReachabilityBase& rb, SCNetworkReachabilityFlags flags) = 0; - - virtual ~ReachabilityTracker() - { - reachability_tracker_cancel(); - } - - private: - bool schedule(ReachabilityBase& rb, SCNetworkReachabilityCallBack cb) - { - SCNetworkReachabilityContext context = { 0, this, nullptr, nullptr, nullptr }; - if (rb.reach.defined()) - { - if (SCNetworkReachabilitySetCallback(rb.reach(), - cb, - &context) == FALSE) - return false; - if (SCNetworkReachabilityScheduleWithRunLoop(rb.reach(), - CFRunLoopGetCurrent(), - kCFRunLoopCommonModes) == FALSE) - return false; - return true; - } - else - return false; - } - - void cancel(ReachabilityBase& rb) - { - if (rb.reach.defined()) - SCNetworkReachabilityUnscheduleFromRunLoop(rb.reach(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes); - } - - static void internet_callback_static(SCNetworkReachabilityRef target, - SCNetworkReachabilityFlags flags, - void *info) - { - ReachabilityTracker* self = (ReachabilityTracker*)info; - self->reachability_tracker_event(*self->reachability.internet, flags); - } - - static void wifi_callback_static(SCNetworkReachabilityRef target, - SCNetworkReachabilityFlags flags, - void *info) - { - ReachabilityTracker* self = (ReachabilityTracker*)info; - self->reachability_tracker_event(*self->reachability.wifi, flags); - } - - Reachability reachability; - bool scheduled; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/scdynstore.hpp b/Sources/OpenVPN3/openvpn/apple/scdynstore.hpp deleted file mode 100644 index 943c3c2..0000000 --- a/Sources/OpenVPN3/openvpn/apple/scdynstore.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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_APPLE_SCDYNSTORE_H -#define OPENVPN_APPLE_SCDYNSTORE_H - -#include <SystemConfiguration/SCDynamicStore.h> - -#include <openvpn/apple/cf/cf.hpp> - -namespace openvpn { - namespace CF { - OPENVPN_CF_WRAP(DynamicStore, dynamic_store_cast, SCDynamicStoreRef, SCDynamicStoreGetTypeID) - - template <typename RET, typename KEY> - inline RET DynamicStoreCopy(const DynamicStore& ds, const KEY& key) - { - String keystr = string(key); - return RET(RET::cast(SCDynamicStoreCopyValue(ds(), keystr()))); - } - - template <typename KEY> - inline Dict DynamicStoreCopyDict(const DynamicStore& ds, const KEY& key) - { - Dict dict = DynamicStoreCopy<Dict>(ds, key); - if (dict.defined()) - return dict; - else - return CF::empty_dict(); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/apple/ver.hpp b/Sources/OpenVPN3/openvpn/apple/ver.hpp deleted file mode 100644 index 1dff47b..0000000 --- a/Sources/OpenVPN3/openvpn/apple/ver.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// 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-2020 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_APPLE_VER_H -#define OPENVPN_APPLE_VER_H - -#include <errno.h> -#include <sys/sysctl.h> - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/split.hpp> -#include <openvpn/common/number.hpp> - -namespace openvpn { - class AppleVersion - { - public: - int major() const { return ver[0]; } - int minor() const { return ver[1]; } - int build() const { return ver[2]; } - - std::string to_string() const - { - std::ostringstream os; - os << major() << '.' << minor() << '.' << build(); - return os.str(); - } - - protected: - AppleVersion() - { - reset(); - } - - // verstr should be in the form major.minor.build - void init(const std::string& verstr) - { - typedef std::vector<std::string> StringList; - reset(); - StringList sl; - sl.reserve(3); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, verstr, '.'); - for (size_t i = 0; i < 3; ++i) - { - if (i < sl.size()) - parse_number(sl[i], ver[i]); - } - } - - private: - void reset() - { - ver[0] = ver[1] = ver[2] = -1; - } - - int ver[3]; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/applecrypto/crypto/api.hpp b/Sources/OpenVPN3/openvpn/applecrypto/crypto/api.hpp deleted file mode 100644 index 45e2002..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/crypto/api.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CRYPTO_API_H -#define OPENVPN_APPLECRYPTO_CRYPTO_API_H - -#include <openvpn/applecrypto/crypto/cipher.hpp> -#include <openvpn/applecrypto/crypto/ciphergcm.hpp> -#include <openvpn/applecrypto/crypto/digest.hpp> -#include <openvpn/applecrypto/crypto/hmac.hpp> - -namespace openvpn { - - // type container for Apple Crypto-level API - struct AppleCryptoAPI { - // cipher - typedef AppleCrypto::CipherContext CipherContext; - typedef AppleCrypto::CipherContextAEAD CipherContextAEAD; - - // digest - typedef AppleCrypto::DigestContext DigestContext; - - // HMAC - typedef AppleCrypto::HMACContext HMACContext; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/applecrypto/crypto/cipher.hpp b/Sources/OpenVPN3/openvpn/applecrypto/crypto/cipher.hpp deleted file mode 100644 index 3731702..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/crypto/cipher.hpp +++ /dev/null @@ -1,201 +0,0 @@ -// 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-2020 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/>. - -// Wrap the Apple cipher API defined in <CommonCrypto/CommonCryptor.h> so -// that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_APPLECRYPTO_CRYPTO_CIPHER_H -#define OPENVPN_APPLECRYPTO_CRYPTO_CIPHER_H - -#include <string> -#include <cstring> - -#include <CommonCrypto/CommonCryptor.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/apple/cf/error.hpp> - -namespace openvpn { - namespace AppleCrypto { - class CipherContext - { - CipherContext(const CipherContext&) = delete; - CipherContext& operator=(const CipherContext&) = delete; - - public: - OPENVPN_SIMPLE_EXCEPTION(apple_cipher_mode_error); - OPENVPN_SIMPLE_EXCEPTION(apple_cipher_uninitialized); - OPENVPN_EXCEPTION(apple_cipher_error); - - // mode parameter for constructor - enum { - MODE_UNDEF = -1, - ENCRYPT = kCCEncrypt, - DECRYPT = kCCDecrypt - }; - - enum { - MAX_IV_LENGTH = 16, - CIPH_CBC_MODE = 0 - }; - - CipherContext() - : cinfo(nullptr), cref(nullptr) - { - } - - ~CipherContext() { erase() ; } - - void init(const CryptoAlgs::Type alg, const unsigned char *key, const int mode) - { - erase(); - - // check that mode is valid - if (!(mode == ENCRYPT || mode == DECRYPT)) - throw apple_cipher_mode_error(); - - // initialize cipher context with cipher type - const CCCryptorStatus status = CCCryptorCreate(mode, - cipher_type(alg), - kCCOptionPKCS7Padding, - key, - CryptoAlgs::key_length(alg), - nullptr, - &cref); - if (status != kCCSuccess) - throw CFException("CipherContext: CCCryptorCreate", status); - - cinfo = CryptoAlgs::get_ptr(alg); - } - - void reset(const unsigned char *iv) - { - check_initialized(); - const CCCryptorStatus status = CCCryptorReset(cref, iv); - if (status != kCCSuccess) - throw CFException("CipherContext: CCCryptorReset", status); - } - - bool update(unsigned char *out, const size_t max_out_size, - const unsigned char *in, const size_t in_size, - size_t& out_acc) - { - check_initialized(); - size_t dataOutMoved; - const CCCryptorStatus status = CCCryptorUpdate(cref, in, in_size, out, max_out_size, &dataOutMoved); - if (status == kCCSuccess) - { - out_acc += dataOutMoved; - return true; - } - else - return false; - } - - bool final(unsigned char *out, const size_t max_out_size, size_t& out_acc) - { - check_initialized(); - size_t dataOutMoved; - const CCCryptorStatus status = CCCryptorFinal(cref, out, max_out_size, &dataOutMoved); - if (status == kCCSuccess) - { - out_acc += dataOutMoved; - return true; - } - else - return false; - } - - bool is_initialized() const { return cinfo != nullptr; } - - size_t iv_length() const - { - check_initialized(); - return cinfo->iv_length(); - } - - size_t block_size() const - { - check_initialized(); - return cinfo->block_size(); - } - - // return cipher mode (such as CIPH_CBC_MODE, etc.) - int cipher_mode() const - { - check_initialized(); - return CIPH_CBC_MODE; - } - - private: - static CCAlgorithm cipher_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::AES_128_CBC: - case CryptoAlgs::AES_192_CBC: - case CryptoAlgs::AES_256_CBC: - case CryptoAlgs::AES_256_CTR: - return kCCAlgorithmAES128; - case CryptoAlgs::DES_CBC: - return kCCAlgorithmDES; - case CryptoAlgs::DES_EDE3_CBC: - return kCCAlgorithm3DES; -#ifdef OPENVPN_PLATFORM_IPHONE - case CryptoAlgs::BF_CBC: - return kCCAlgorithmBlowfish; -#endif - default: - OPENVPN_THROW(apple_cipher_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - - void erase() - { - if (cinfo) - { - if (cref) - CCCryptorRelease(cref); - cref = nullptr; - cinfo = nullptr; - } - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!cinfo) - throw apple_cipher_uninitialized(); -#endif - } - - const CryptoAlgs::Alg* cinfo; - CCCryptorRef cref; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/applecrypto/crypto/digest.hpp b/Sources/OpenVPN3/openvpn/applecrypto/crypto/digest.hpp deleted file mode 100644 index 5fe2812..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/crypto/digest.hpp +++ /dev/null @@ -1,255 +0,0 @@ -// 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-2020 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/>. - -// Wrap the Apple digest API defined in <CommonCrypto/CommonDigest.h> -// so that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H -#define OPENVPN_APPLECRYPTO_CRYPTO_DIGEST_H - -#include <string> - -#include <CommonCrypto/CommonDigest.h> -#include <CommonCrypto/CommonHMAC.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/apple/cf/error.hpp> - -#define OPENVPN_DIGEST_CONTEXT(TYPE) CC_##TYPE##_CTX TYPE##_ctx - -#define OPENVPN_DIGEST_ALG_CLASS(TYPE) \ - class DigestAlgorithm##TYPE : public DigestAlgorithm \ - { \ - public: \ - DigestAlgorithm##TYPE() {} \ - virtual int init(DigestCTX& ctx) const \ - { \ - return CC_##TYPE##_Init(&ctx.u.TYPE##_ctx); \ - } \ - virtual int update(DigestCTX& ctx, const unsigned char *data, size_t size) const \ - { \ - return CC_##TYPE##_Update(&ctx.u.TYPE##_ctx, data, size); \ - } \ - virtual int final(DigestCTX& ctx, unsigned char *md) const \ - { \ - return CC_##TYPE##_Final(md, &ctx.u.TYPE##_ctx); \ - } \ - } - -#define OPENVPN_DIGEST_ALG_DECLARE(TYPE) const DigestAlgorithm##TYPE alg_##TYPE; - -#define OPENVPN_DIGEST_INFO_DECLARE(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, kCCHmacAlg##TYPE) - -#define OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(TYPE) const DigestInfo info_##TYPE(CryptoAlgs::TYPE, &alg_##TYPE, DigestInfo::NO_HMAC_ALG) - -namespace openvpn { - namespace AppleCrypto { - typedef CC_SHA256_CTX CC_SHA224_CTX; - typedef CC_SHA512_CTX CC_SHA384_CTX; - - struct DigestCTX { - union { - OPENVPN_DIGEST_CONTEXT(MD4); - OPENVPN_DIGEST_CONTEXT(MD5); - OPENVPN_DIGEST_CONTEXT(SHA1); - OPENVPN_DIGEST_CONTEXT(SHA224); - OPENVPN_DIGEST_CONTEXT(SHA256); - OPENVPN_DIGEST_CONTEXT(SHA384); - OPENVPN_DIGEST_CONTEXT(SHA512); - } u; - }; - - struct DigestAlgorithm { - virtual int init(DigestCTX& ctx) const = 0; - virtual int update(DigestCTX& ctx, const unsigned char *data, size_t size) const = 0; - virtual int final(DigestCTX& ctx, unsigned char *md) const = 0; - }; - - // individual digest algorithm classes (each inherits from DigestAlgorithm) - OPENVPN_DIGEST_ALG_CLASS(MD4); - OPENVPN_DIGEST_ALG_CLASS(MD5); - OPENVPN_DIGEST_ALG_CLASS(SHA1); - OPENVPN_DIGEST_ALG_CLASS(SHA224); - OPENVPN_DIGEST_ALG_CLASS(SHA256); - OPENVPN_DIGEST_ALG_CLASS(SHA384); - OPENVPN_DIGEST_ALG_CLASS(SHA512); - - class DigestInfo - { - public: - enum { - NO_HMAC_ALG = -1 - }; - - DigestInfo(CryptoAlgs::Type type, - const DigestAlgorithm* digest_alg, - const CCHmacAlgorithm hmac_alg) - : type_(type), - digest_alg_(digest_alg), - hmac_alg_(hmac_alg) {} - - CryptoAlgs::Type type() const { return type_; } - const char *name() const { return CryptoAlgs::name(type_); } - size_t size() const { return CryptoAlgs::size(type_); } - const DigestAlgorithm* digest_alg() const { return digest_alg_; } - CCHmacAlgorithm hmac_alg() const { return hmac_alg_; } - - private: - CryptoAlgs::Type type_; - const DigestAlgorithm* digest_alg_; - CCHmacAlgorithm hmac_alg_; - }; - - // instantiate individual digest algorithm class instances (each inherits from DigestAlgorithm), - // naming convention is alg_TYPE - OPENVPN_DIGEST_ALG_DECLARE(MD4); - OPENVPN_DIGEST_ALG_DECLARE(MD5); - OPENVPN_DIGEST_ALG_DECLARE(SHA1); - OPENVPN_DIGEST_ALG_DECLARE(SHA224); - OPENVPN_DIGEST_ALG_DECLARE(SHA256); - OPENVPN_DIGEST_ALG_DECLARE(SHA384); - OPENVPN_DIGEST_ALG_DECLARE(SHA512); - - // instantiate individual digest info class instances (each is a DigestInfo), - // naming convention is info_TYPE - OPENVPN_DIGEST_INFO_DECLARE_NO_HMAC(MD4); - OPENVPN_DIGEST_INFO_DECLARE(MD5); - OPENVPN_DIGEST_INFO_DECLARE(SHA1); - OPENVPN_DIGEST_INFO_DECLARE(SHA224); - OPENVPN_DIGEST_INFO_DECLARE(SHA256); - OPENVPN_DIGEST_INFO_DECLARE(SHA384); - OPENVPN_DIGEST_INFO_DECLARE(SHA512); - - class HMACContext; - - class DigestContext - { - DigestContext(const DigestContext&) = delete; - DigestContext& operator=(const DigestContext&) = delete; - - public: - friend class HMACContext; - - OPENVPN_SIMPLE_EXCEPTION(apple_digest_uninitialized); - OPENVPN_SIMPLE_EXCEPTION(apple_digest_final_overflow); - OPENVPN_EXCEPTION(apple_digest_error); - - enum { - MAX_DIGEST_SIZE = CC_SHA512_DIGEST_LENGTH // largest known is SHA512 - }; - - DigestContext() - { - clear(); - } - - DigestContext(const CryptoAlgs::Type alg) - { - init(alg); - } - - void init(const CryptoAlgs::Type alg) - { - clear(); - info = digest_type(alg); - meth = info->digest_alg(); - if (meth->init(ctx) != 1) - throw apple_digest_error("init"); - initialized = true; - } - - void update(const unsigned char *in, const size_t size) - { - check_initialized(); - if (meth->update(ctx, in, size) != 1) - throw apple_digest_error("update"); - } - - size_t final(unsigned char *out) - { - check_initialized(); - if (meth->final(ctx, out) != 1) - throw apple_digest_error("final"); - return info->size(); - } - - size_t size() const - { - check_initialized(); - return info->size(); - } - - bool is_initialized() const { return initialized; } - - private: - static const DigestInfo *digest_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::MD4: - return &info_MD4; - case CryptoAlgs::MD5: - return &info_MD5; - case CryptoAlgs::SHA1: - return &info_SHA1; - case CryptoAlgs::SHA224: - return &info_SHA224; - case CryptoAlgs::SHA256: - return &info_SHA256; - case CryptoAlgs::SHA384: - return &info_SHA384; - case CryptoAlgs::SHA512: - return &info_SHA512; - default: - OPENVPN_THROW(apple_digest_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - - void clear() - { - initialized = false; - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!initialized) - throw apple_digest_uninitialized(); -#endif - } - - bool initialized; - const DigestInfo *info; - const DigestAlgorithm *meth; - DigestCTX ctx; - }; - } -} - -#undef OPENVPN_DIGEST_CONTEXT -#undef OPENVPN_DIGEST_ALG_CLASS -#undef OPENVPN_DIGEST_ALG_DECLARE -#undef OPENVPN_DIGEST_INFO_DECLARE - -#endif diff --git a/Sources/OpenVPN3/openvpn/applecrypto/crypto/hmac.hpp b/Sources/OpenVPN3/openvpn/applecrypto/crypto/hmac.hpp deleted file mode 100644 index 256f40f..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/crypto/hmac.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// 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-2020 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_APPLECRYPTO_CRYPTO_HMAC_H -#define OPENVPN_APPLECRYPTO_CRYPTO_HMAC_H - -// Wrap the Apple HMAC API defined in <CommonCrypto/CommonHMAC.h> so that -// it can be used as part of the crypto layer of the OpenVPN core. - -#include <string> -#include <cstring> - -#include <CommonCrypto/CommonHMAC.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/applecrypto/crypto/digest.hpp> - -namespace openvpn { - namespace AppleCrypto { - class HMACContext - { - HMACContext(const HMACContext&) = delete; - HMACContext& operator=(const HMACContext&) = delete; - - public: - OPENVPN_EXCEPTION(digest_cannot_be_used_with_hmac); - OPENVPN_SIMPLE_EXCEPTION(hmac_uninitialized); - OPENVPN_SIMPLE_EXCEPTION(hmac_keysize_error); - - enum { - MAX_HMAC_SIZE = DigestContext::MAX_DIGEST_SIZE, - MAX_HMAC_KEY_SIZE = 128, - }; - - HMACContext() - { - state = PRE; - } - - HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - { - init(digest, key, key_size); - } - - ~HMACContext() - { - } - - void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - { - state = PRE; - info = DigestContext::digest_type(digest); - digest_size_ = CryptoAlgs::size(digest); - hmac_alg = info->hmac_alg(); - if (hmac_alg == DigestInfo::NO_HMAC_ALG) - throw digest_cannot_be_used_with_hmac(info->name()); - if (key_size > MAX_HMAC_KEY_SIZE) - throw hmac_keysize_error(); - std::memcpy(key_, key, key_size_ = key_size); - state = PARTIAL; - } - - void reset() // Apple HMAC API is missing reset method, so we have to reinit - { - cond_reset(true); - } - - void update(const unsigned char *in, const size_t size) - { - cond_reset(false); - CCHmacUpdate(&ctx, in, size); - } - - size_t final(unsigned char *out) - { - cond_reset(false); - CCHmacFinal(&ctx, out); - return digest_size_; - } - - size_t size() const - { - if (!is_initialized()) - throw hmac_uninitialized(); - return digest_size_; - } - - bool is_initialized() const - { - return state >= PARTIAL; - } - - private: - void cond_reset(const bool force_init) - { - switch (state) - { - case PRE: - throw hmac_uninitialized(); - case READY: - if (!force_init) - return; - case PARTIAL: - CCHmacInit(&ctx, hmac_alg, key_, key_size_); - state = READY; - } - } - - enum State { - PRE=0, - PARTIAL, - READY - }; - int state; - - const DigestInfo *info; - CCHmacAlgorithm hmac_alg; - size_t key_size_; - size_t digest_size_; - unsigned char key_[MAX_HMAC_KEY_SIZE]; - CCHmacContext ctx; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/applecrypto/ssl/sslctx.hpp b/Sources/OpenVPN3/openvpn/applecrypto/ssl/sslctx.hpp deleted file mode 100644 index 45a91c2..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/ssl/sslctx.hpp +++ /dev/null @@ -1,488 +0,0 @@ -// 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-2020 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/>. - -// Wrap the Apple SSL API as defined in <Security/SecureTransport.h> -// so that it can be used as the SSL layer by the OpenVPN core. -// NOTE: not used in production code. - -// Note that the Apple SSL API is missing some functionality (as of -// Mac OS X 10.8) that makes it difficult to use as a drop in replacement -// for OpenSSL or MbedTLS. The biggest issue is that the API doesn't -// allow an SSL context to be built out of PEM-based certificates and -// keys. It requires an "Identity" in the Keychain that was imported -// by the user as a PKCS#12 file. - -#ifndef OPENVPN_APPLECRYPTO_SSL_SSLCTX_H -#define OPENVPN_APPLECRYPTO_SSL_SSLCTX_H - -#include <string> - -#include <Security/SecImportExport.h> -#include <Security/SecItem.h> -#include <Security/SecureTransport.h> -#include <Security/SecKey.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/mode.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/frame/memq_stream.hpp> -#include <openvpn/pki/epkibase.hpp> -#include <openvpn/apple/cf/cfsec.hpp> -#include <openvpn/apple/cf/error.hpp> -#include <openvpn/ssl/tlsver.hpp> -#include <openvpn/ssl/sslconsts.hpp> -#include <openvpn/ssl/sslapi.hpp> - -// An SSL Context is essentially a configuration that can be used -// to generate an arbitrary number of actual SSL connections objects. - -// AppleSSLContext is an SSL Context implementation that uses the -// Mac/iOS SSL library as a backend. - -namespace openvpn { - - // Represents an SSL configuration that can be used - // to instantiate actual SSL sessions. - class AppleSSLContext : public SSLFactoryAPI - { - public: - typedef RCPtr<AppleSSLContext> Ptr; - - enum { - MAX_CIPHERTEXT_IN = 64 - }; - - // The data needed to construct an AppleSSLContext. - class Config : public SSLConfigAPI - { - friend class AppleSSLContext; - - public: - typedef RCPtr<Config> Ptr; - - Config() {} - - void load_identity(const std::string& subject_match) - { - identity = load_identity_(subject_match); - if (!identity()) - OPENVPN_THROW(ssl_context_error, "AppleSSLContext: identity '" << subject_match << "' undefined"); - } - - virtual SSLFactoryAPI::Ptr new_factory() - { - return SSLFactoryAPI::Ptr(new AppleSSLContext(this)); - } - - virtual void set_mode(const Mode& mode_arg) - { - mode = mode_arg; - } - - virtual const Mode& get_mode() const - { - return mode; - } - - virtual void set_frame(const Frame::Ptr& frame_arg) - { - frame = frame_arg; - } - - virtual void load(const OptionList& opt, const unsigned int lflags) - { - // client/server - if (lflags & LF_PARSE_MODE) - mode = opt.exists("client") ? Mode(Mode::CLIENT) : Mode(Mode::SERVER); - - // identity - { - const std::string& subject_match = opt.get("identity", 1, 256); - load_identity(subject_match); - } - } - - virtual void set_external_pki_callback(ExternalPKIBase* external_pki_arg) - { - not_implemented("set_external_pki_callback"); - } - - virtual void set_private_key_password(const std::string& pwd) - { - return not_implemented("set_private_key_password"); - } - - virtual void load_ca(const std::string& ca_txt, bool strict) - { - return not_implemented("load_ca"); - } - - virtual void load_crl(const std::string& crl_txt) - { - return not_implemented("load_crl"); - } - - virtual void load_cert(const std::string& cert_txt) - { - return not_implemented("load_cert"); - } - - virtual void load_cert(const std::string& cert_txt, const std::string& extra_certs_txt) - { - return not_implemented("load_cert"); - } - - virtual void load_private_key(const std::string& key_txt) - { - return not_implemented("load_private_key"); - } - - virtual void load_dh(const std::string& dh_txt) - { - return not_implemented("load_dh"); - } - - virtual void set_debug_level(const int debug_level) - { - return not_implemented("set_debug_level"); - } - - virtual void set_flags(const unsigned int flags_arg) - { - return not_implemented("set_flags"); - } - - virtual void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) - { - return not_implemented("set_ns_cert_type"); - } - - virtual void set_remote_cert_tls(const KUParse::TLSWebType wt) - { - return not_implemented("set_remote_cert_tls"); - } - - virtual void set_tls_remote(const std::string& tls_remote_arg) - { - return not_implemented("set_tls_remote"); - } - - virtual void set_tls_version_min(const TLSVersion::Type tvm) - { - return not_implemented("set_tls_version_min"); - } - - virtual void set_local_cert_enabled(const bool v) - { - return not_implemented("set_local_cert_enabled"); - } - - virtual void set_enable_renegotiation(const bool v) - { - return not_implemented("set_enable_renegotiation"); - } - - virtual void set_rng(const RandomAPI::Ptr& rng_arg) - { - return not_implemented("set_rng"); - } - - private: - void not_implemented(const char *funcname) - { - OPENVPN_LOG("AppleSSL: " << funcname << " not implemented"); - } - - Mode mode; - CF::Array identity; // as returned by load_identity - Frame::Ptr frame; - }; - - // Represents an actual SSL session. - // Normally instantiated by AppleSSLContext::ssl(). - class SSL : public SSLAPI - { - friend class AppleSSLContext; - - public: - typedef RCPtr<SSL> Ptr; - - virtual void start_handshake() - { - SSLHandshake(ssl); - } - - virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) - { - size_t actual = 0; - const OSStatus status = SSLWrite(ssl, data, size, &actual); - if (status < 0) - { - if (status == errSSLWouldBlock) - return SSLConst::SHOULD_RETRY; - else - throw CFException("AppleSSLContext::SSL::write_cleartext failed", status); - } - else - return actual; - } - - virtual ssize_t read_cleartext(void *data, const size_t capacity) - { - if (!overflow) - { - size_t actual = 0; - const OSStatus status = SSLRead(ssl, data, capacity, &actual); - if (status < 0) - { - if (status == errSSLWouldBlock) - return SSLConst::SHOULD_RETRY; - else - throw CFException("AppleSSLContext::SSL::read_cleartext failed", status); - } - else - return actual; - } - else - throw ssl_ciphertext_in_overflow(); - } - - virtual bool read_cleartext_ready() const - { - // fixme: need to detect data buffered at SSL layer - return !ct_in.empty(); - } - - virtual void write_ciphertext(const BufferPtr& buf) - { - if (ct_in.size() < MAX_CIPHERTEXT_IN) - ct_in.write_buf(buf); - else - overflow = true; - } - - virtual bool read_ciphertext_ready() const - { - return !ct_out.empty(); - } - - virtual BufferPtr read_ciphertext() - { - return ct_out.read_buf(); - } - - virtual std::string ssl_handshake_details() const // fixme -- code me - { - return "[AppleSSL not implemented]"; - } - - virtual const AuthCert::Ptr& auth_cert() const - { - OPENVPN_THROW(ssl_context_error, "AppleSSL::SSL: auth_cert() not implemented"); - } - - ~SSL() - { - ssl_erase(); - } - - private: - SSL(const AppleSSLContext& ctx) - { - ssl_clear(); - try { - OSStatus s; - -#ifdef OPENVPN_PLATFORM_IPHONE - // init SSL object, select client or server mode - if (ctx.mode().is_server()) - ssl = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); - else if (ctx.mode().is_client()) - ssl = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); - else - OPENVPN_THROW(ssl_context_error, "AppleSSLContext::SSL: unknown client/server mode"); - if (ssl == nullptr) - throw CFException("SSLCreateContext failed"); - - // use TLS v1 - s = SSLSetProtocolVersionMin(ssl, kTLSProtocol1); - if (s) - throw CFException("SSLSetProtocolVersionMin failed", s); -#else - // init SSL object, select client or server mode - if (ctx.mode().is_server()) - s = SSLNewContext(true, &ssl); - else if (ctx.mode().is_client()) - s = SSLNewContext(false, &ssl); - else - OPENVPN_THROW(ssl_context_error, "AppleSSLContext::SSL: unknown client/server mode"); - if (s) - throw CFException("SSLNewContext failed", s); - - // use TLS v1 - s = SSLSetProtocolVersionEnabled(ssl, kSSLProtocol2, false); - if (s) - throw CFException("SSLSetProtocolVersionEnabled !S2 failed", s); - s = SSLSetProtocolVersionEnabled(ssl, kSSLProtocol3, false); - if (s) - throw CFException("SSLSetProtocolVersionEnabled !S3 failed", s); - s = SSLSetProtocolVersionEnabled(ssl, kTLSProtocol1, true); - if (s) - throw CFException("SSLSetProtocolVersionEnabled T1 failed", s); -#endif - // configure cert, private key, and supporting CAs via identity wrapper - s = SSLSetCertificate(ssl, ctx.identity()()); - if (s) - throw CFException("SSLSetCertificate failed", s); - - // configure ciphertext buffers - ct_in.set_frame(ctx.frame()); - ct_out.set_frame(ctx.frame()); - - // configure the "connection" object to be self - s = SSLSetConnection(ssl, this); - if (s) - throw CFException("SSLSetConnection", s); - - // configure ciphertext read/write callbacks - s = SSLSetIOFuncs(ssl, ct_read_func, ct_write_func); - if (s) - throw CFException("SSLSetIOFuncs failed", s); - } - catch (...) - { - ssl_erase(); - throw; - } - } - - static OSStatus ct_read_func(SSLConnectionRef cref, void *data, size_t *length) - { - try { - SSL *self = (SSL *)cref; - const size_t actual = self->ct_in.read((unsigned char *)data, *length); - const OSStatus ret = (*length == actual) ? 0 : errSSLWouldBlock; - *length = actual; - return ret; - } - catch (...) - { - return errSSLInternal; - } - } - - static OSStatus ct_write_func(SSLConnectionRef cref, const void *data, size_t *length) - { - try { - SSL *self = (SSL *)cref; - self->ct_out.write((const unsigned char *)data, *length); - return 0; - } - catch (...) - { - return errSSLInternal; - } - } - - void ssl_clear() - { - ssl = nullptr; - overflow = false; - } - - void ssl_erase() - { - if (ssl) - { -#ifdef OPENVPN_PLATFORM_IPHONE - CFRelease(ssl); -#else - SSLDisposeContext(ssl); -#endif - } - ssl_clear(); - } - - SSLContextRef ssl; // underlying SSL connection object - MemQStream ct_in; // write ciphertext to here - MemQStream ct_out; // read ciphertext from here - bool overflow; - }; - - /////// start of main class implementation - - // create a new SSL instance - virtual SSLAPI::Ptr ssl() - { - return SSL::Ptr(new SSL(*this)); - } - - // like ssl() above but verify hostname against cert CommonName and/or SubjectAltName - virtual SSLAPI::Ptr ssl(const std::string& hostname) - { - OPENVPN_THROW(ssl_context_error, "AppleSSLContext: ssl session with CommonName and/or SubjectAltName verification not implemented"); - } - - virtual const Mode& mode() const - { - return config_->mode; - } - - private: - AppleSSLContext(Config* config) - : config_(config) - { - if (!config_->identity()) - OPENVPN_THROW(ssl_context_error, "AppleSSLContext: identity undefined"); - } - - const Frame::Ptr& frame() const { return config_->frame; } - const CF::Array& identity() const { return config_->identity; } - - // load an identity from keychain, return as an array that can - // be passed to SSLSetCertificate - static CF::Array load_identity_(const std::string& subj_match) - { - const CF::String label = CF::string(subj_match); - const void *keys[] = { kSecClass, kSecMatchSubjectContains, kSecMatchTrustedOnly, kSecReturnRef }; - const void *values[] = { kSecClassIdentity, label(), kCFBooleanTrue, kCFBooleanTrue }; - const CF::Dict query = CF::dict(keys, values, sizeof(keys)/sizeof(keys[0])); - CF::Generic result; - const OSStatus s = SecItemCopyMatching(query(), result.mod_ref()); - if (!s && result.defined()) - { - const void *asrc[] = { result() }; - return CF::array(asrc, 1); - } - else - return CF::Array(); // not found - } - - Config::Ptr config_; - }; - - typedef AppleSSLContext::Ptr AppleSSLContextPtr; - -} // namespace openvpn - -#endif // OPENVPN_APPLECRYPTO_SSL_SSLCTX_H diff --git a/Sources/OpenVPN3/openvpn/applecrypto/util/rand.hpp b/Sources/OpenVPN3/openvpn/applecrypto/util/rand.hpp deleted file mode 100644 index 7338e0e..0000000 --- a/Sources/OpenVPN3/openvpn/applecrypto/util/rand.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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-2020 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/>. - -// Wrap the Apple Cryptographic Random API defined in <Security/SecRandom.h> -// so that it can be used as the primary source of cryptographic entropy by -// the OpenVPN core. - -#ifndef OPENVPN_APPLECRYPTO_UTIL_RAND_H -#define OPENVPN_APPLECRYPTO_UTIL_RAND_H - -#include <Security/SecRandom.h> - -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - class AppleRandom : public RandomAPI - { - public: - OPENVPN_EXCEPTION(rand_error_apple); - - typedef RCPtr<AppleRandom> Ptr; - - AppleRandom(const bool prng) - { - } - - virtual std::string name() const - { - return "AppleRandom"; - } - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const - { - return true; - } - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) - { - if (!rndbytes(buf, size)) - throw rand_error_apple("rand_bytes"); - } - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) - { - return rndbytes(buf, size); - } - - private: - bool rndbytes(unsigned char *buf, size_t size) - { - return SecRandomCopyBytes(kSecRandomDefault, size, buf) ? false : true; - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asioboundsock.hpp b/Sources/OpenVPN3/openvpn/asio/asioboundsock.hpp deleted file mode 100644 index bc07527..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asioboundsock.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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-2020 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/>. - -// Asio TCP socket that can be configured so that open() method -// always prebinds the socket to a given local address. Useful -// for TCP clients. - -#ifndef OPENVPN_ASIO_ASIOBOUNDSOCK_H -#define OPENVPN_ASIO_ASIOBOUNDSOCK_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/addr/ip.hpp> -#include <openvpn/common/extern.hpp> -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - namespace AsioBoundSocket { - - typedef openvpn_io::basic_stream_socket<openvpn_io::ip::tcp> SocketBase; - - class Socket : public SocketBase - { - public: - explicit Socket(openvpn_io::io_context& io_context) - : SocketBase(io_context) - { - } - - // if port 0, kernel will dynamically allocate free port - void bind_local(const IP::Addr& addr, const unsigned short port=0) - { - bind_local_addr = addr; - bind_local_port = port; - } - - std::string to_string() const - { - std::string ret; - ret.reserve(64); - if (bind_local_addr.defined()) - { - ret += "local=["; - ret += bind_local_addr.to_string(); - ret += "]:"; - ret += openvpn::to_string(bind_local_port); - } - try { - const std::string re = openvpn::to_string(remote_endpoint()); - if (!ret.empty()) - ret += ' '; - ret += "remote="; - ret += re; - } - catch (const std::exception& e) - { - } - return ret; - } - - protected: - virtual void async_connect_post_open(const protocol_type& protocol, openvpn_io::error_code& ec) override - { - if (bind_local_addr.defined()) - { - set_option(openvpn_io::socket_base::reuse_address(true), ec); - if (ec) - return; - bind(openvpn_io::ip::tcp::endpoint(bind_local_addr.to_asio(), bind_local_port), ec); - } - } - - private: - IP::Addr bind_local_addr; - unsigned short bind_local_port = 0; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asiocontext.hpp b/Sources/OpenVPN3/openvpn/asio/asiocontext.hpp deleted file mode 100644 index 779829e..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asiocontext.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// 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-2020 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_ASIO_ASIOCONTEXT_H -#define OPENVPN_ASIO_ASIOCONTEXT_H - -#include <vector> -#include <memory> -#include <mutex> - -#include <openvpn/io/io.hpp> - -namespace openvpn { - class AsioContextStore - { - public: - openvpn_io::io_context& new_context(int concurrency_hint) - { - openvpn_io::io_context* ioc = new openvpn_io::io_context(concurrency_hint); - { - std::lock_guard<std::mutex> lock(mutex); - contexts.emplace_back(ioc); - } - return *ioc; - } - - private: - std::mutex mutex; - std::vector<std::unique_ptr<openvpn_io::io_context>> contexts; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asioerr.hpp b/Sources/OpenVPN3/openvpn/asio/asioerr.hpp deleted file mode 100644 index 2179e09..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asioerr.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// 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-2020 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_ASIO_ASIOERR_H -#define OPENVPN_ASIO_ASIOERR_H - -#include <string> - -#include <openvpn/io/io.hpp> // was: #include <asio/error_code.hpp> - -namespace openvpn { - - // returns a string describing an i/o error code - template <typename ErrorCode> - inline std::string errinfo(ErrorCode err) - { - openvpn_io::error_code e(err, openvpn_io::system_category()); - return e.message(); - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asiopolysock.hpp b/Sources/OpenVPN3/openvpn/asio/asiopolysock.hpp deleted file mode 100644 index 9c7784e..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asiopolysock.hpp +++ /dev/null @@ -1,377 +0,0 @@ -// 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-2020 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/>. - -// Asio polymorphic socket for handling TCP -// and unix domain sockets. - -#ifndef OPENVPN_ASIO_ASIOPOLYSOCK_H -#define OPENVPN_ASIO_ASIOPOLYSOCK_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/function.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/sockopt.hpp> -#include <openvpn/addr/ip.hpp> - -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) -#include <openvpn/asio/alt_routing.hpp> -#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND) -#include <openvpn/asio/asioboundsock.hpp> -#endif - -#ifdef ASIO_HAS_LOCAL_SOCKETS -#include <openvpn/common/peercred.hpp> -#endif - -namespace openvpn { - namespace AsioPolySock { - // for shutdown() - enum ShutdownFlags { - SHUTDOWN_SEND = (1<<0), - SHUTDOWN_RECV = (1<<1), - }; - - class Base : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Base> Ptr; - - virtual void async_send(const openvpn_io::const_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) = 0; - - virtual void async_receive(const openvpn_io::mutable_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) = 0; - - virtual std::string remote_endpoint_str() const = 0; - virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const = 0; - - virtual void non_blocking(const bool state) = 0; - - virtual void close() = 0; - - virtual void shutdown(const unsigned int flags) {} - - virtual void tcp_nodelay() {} - virtual void set_cloexec() {} - - virtual int native_handle() - { - return -1; - } - -#ifdef ASIO_HAS_LOCAL_SOCKETS - virtual bool peercreds(SockOpt::Creds& cr) - { - return false; - } -#endif - -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - virtual bool alt_routing_enabled() - { - return false; - } -#endif - - virtual bool is_open() const = 0; - virtual bool is_local() const = 0; - - size_t index() const { return index_; } - - protected: - Base(const size_t index) - : index_(index) - { - } - - private: - size_t index_; - }; - - struct TCP : public Base - { - typedef RCPtr<TCP> Ptr; - - TCP(openvpn_io::io_context& io_context, - const size_t index) - : Base(index), - socket(io_context) - { - } - - virtual void async_send(const openvpn_io::const_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - socket.async_send(buf, std::move(callback)); - } - - virtual void async_receive(const openvpn_io::mutable_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - socket.async_receive(buf, std::move(callback)); - } - -#if !defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - virtual std::string remote_endpoint_str() const override - { - try { - return "TCP " + openvpn::to_string(socket.remote_endpoint()); - } - catch (const std::exception&) - { - return "TCP"; - } - } -#endif - - virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const override - { - try { - addr = IP::Addr::from_asio(socket.remote_endpoint().address()); - port = socket.remote_endpoint().port(); - return true; - } - catch (const std::exception&) - { - return false; - } - } - - virtual void non_blocking(const bool state) override - { - socket.non_blocking(state); - } - - virtual void tcp_nodelay() override - { - socket.set_option(openvpn_io::ip::tcp::no_delay(true)); - } - -#if !defined(OPENVPN_PLATFORM_WIN) - virtual void set_cloexec() override - { - const int fd = socket.native_handle(); - if (fd >= 0) - SockOpt::set_cloexec(fd); - } -#endif - - virtual void shutdown(const unsigned int flags) override - { - if (flags & SHUTDOWN_SEND) - socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); - else if (flags & SHUTDOWN_RECV) - socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); - } - - virtual void close() override - { - socket.close(); - } - - virtual bool is_open() const override - { - return socket.is_open(); - } - - virtual bool is_local() const override - { - return false; - } - - virtual int native_handle() override - { - return socket.native_handle(); - } - -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - virtual std::string remote_endpoint_str() const override - { - const char *proto = (socket.alt_routing_enabled() ? "TCP ALT " : "TCP "); - return proto + socket.to_string(); - } - - virtual bool alt_routing_enabled() override - { - return socket.alt_routing_enabled(); - } - - AltRouting::Socket socket; -#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND) - AsioBoundSocket::Socket socket; -#else - openvpn_io::ip::tcp::socket socket; -#endif - }; - -#ifdef ASIO_HAS_LOCAL_SOCKETS - struct Unix : public Base - { - typedef RCPtr<Unix> Ptr; - - Unix(openvpn_io::io_context& io_context, - const size_t index) - : Base(index), - socket(io_context) - { - } - - virtual void async_send(const openvpn_io::const_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - socket.async_send(buf, std::move(callback)); - } - - virtual void async_receive(const openvpn_io::mutable_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - socket.async_receive(buf, std::move(callback)); - } - - virtual std::string remote_endpoint_str() const override - { - return "LOCAL"; - } - - virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override - { - return false; - } - - virtual void non_blocking(const bool state) override - { - socket.non_blocking(state); - } - - virtual bool peercreds(SockOpt::Creds& cr) override - { - return SockOpt::peercreds(socket.native_handle(), cr); - } - - virtual void set_cloexec() override - { - const int fd = socket.native_handle(); - if (fd >= 0) - SockOpt::set_cloexec(fd); - } - -#if !defined(OPENVPN_PLATFORM_MAC) - // shutdown() throws "socket is not connected" exception - // on macos if another side has called close() - this behavior - // breaks communication with agent, and hence disabled - virtual void shutdown(const unsigned int flags) override - { - if (flags & SHUTDOWN_SEND) - socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send); - else if (flags & SHUTDOWN_RECV) - socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive); - } -#endif - - virtual void close() override - { - socket.close(); - } - - virtual bool is_open() const override - { - return socket.is_open(); - } - - virtual bool is_local() const override - { - return true; - } - - virtual int native_handle() override - { - return socket.native_handle(); - } - - openvpn_io::local::stream_protocol::socket socket; - }; -#endif - -#if defined(OPENVPN_PLATFORM_WIN) - struct NamedPipe : public Base - { - typedef RCPtr<NamedPipe> Ptr; - - NamedPipe(openvpn_io::windows::stream_handle&& handle_arg, - const size_t index) - : Base(index), - handle(std::move(handle_arg)) - { - } - - virtual void async_send(const openvpn_io::const_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - handle.async_write_some(buf, std::move(callback)); - } - - virtual void async_receive(const openvpn_io::mutable_buffer& buf, - Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override - { - handle.async_read_some(buf, std::move(callback)); - } - - virtual std::string remote_endpoint_str() const override - { - return "NAMED_PIPE"; - } - - virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override - { - return false; - } - - virtual void non_blocking(const bool state) override - { - } - - virtual void close() override - { - handle.close(); - } - - virtual bool is_open() const override - { - return handle.is_open(); - } - - virtual bool is_local() const override - { - return true; - } - - openvpn_io::windows::stream_handle handle; - }; -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asioresolverres.hpp b/Sources/OpenVPN3/openvpn/asio/asioresolverres.hpp deleted file mode 100644 index 627f1cf..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asioresolverres.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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 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/>. - -#pragma once - -#include <string> - -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - - template <class EPRANGE> - inline std::string asio_resolver_results_to_string(const EPRANGE& endpoint_range) - { - std::string ret; - ret.reserve(64); - bool first = true; - for (const auto &i : endpoint_range) - { - if (!first) - ret += ' '; - ret += '['; - ret += openvpn::to_string(i.endpoint().address()); - ret += "]:"; - ret += openvpn::to_string(i.endpoint().port()); - first = false; - } - return ret; - } - -} diff --git a/Sources/OpenVPN3/openvpn/asio/asiosignal.hpp b/Sources/OpenVPN3/openvpn/asio/asiosignal.hpp deleted file mode 100644 index a190266..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asiosignal.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// 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-2020 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/>. - -// A simple class that allows an arbitrary set of posix signals to be -// associated with an Asio handler. - -#ifndef OPENVPN_ASIO_ASIOSIGNAL_H -#define OPENVPN_ASIO_ASIOSIGNAL_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/rc.hpp> - -namespace openvpn { - - class ASIOSignals : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<ASIOSignals> Ptr; - - ASIOSignals(openvpn_io::io_context& io_context) - : halt(false), signals_(io_context) {} - - enum { - S_SIGINT = (1<<0), - S_SIGTERM = (1<<1), -#ifndef OPENVPN_PLATFORM_WIN - S_SIGQUIT = (1<<2), - S_SIGHUP = (1<<3), - S_SIGUSR1 = (1<<4), - S_SIGUSR2 = (1<<5), -#endif - }; - - template <typename SignalHandler> - void register_signals(SignalHandler stop_handler, unsigned int sigmask = (S_SIGINT|S_SIGTERM)) - { - if (sigmask & S_SIGINT) - signals_.add(SIGINT); - if (sigmask & S_SIGTERM) - signals_.add(SIGTERM); -#ifndef OPENVPN_PLATFORM_WIN - if (sigmask & S_SIGQUIT) - signals_.add(SIGQUIT); - if (sigmask & S_SIGHUP) - signals_.add(SIGHUP); - if (sigmask & S_SIGUSR1) - signals_.add(SIGUSR1); - if (sigmask & S_SIGUSR2) - signals_.add(SIGUSR2); -#endif - signals_.async_wait(stop_handler); - } - - template <typename SignalHandler> - void register_signals_all(SignalHandler stop_handler) - { - register_signals(stop_handler, - S_SIGINT - | S_SIGTERM -#ifndef OPENVPN_PLATFORM_WIN - | S_SIGHUP - | S_SIGUSR1 - | S_SIGUSR2 -#endif - ); - } - - void cancel() - { - if (!halt) - { - halt = true; - signals_.cancel(); - } - } - - private: - bool halt; - openvpn_io::signal_set signals_; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asiostop.hpp b/Sources/OpenVPN3/openvpn/asio/asiostop.hpp deleted file mode 100644 index dd860eb..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asiostop.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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_ASIO_ASIOSTOP_H -#define OPENVPN_ASIO_ASIOSTOP_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/stop.hpp> - -namespace openvpn { - class AsioStopScope : public Stop::Scope - { - public: - AsioStopScope(openvpn_io::io_context& io_context, - Stop* stop, - std::function<void()>&& method) - : Stop::Scope(stop, post_method(io_context, std::move(method))) - { - } - - private: - static std::function<void()> post_method(openvpn_io::io_context& io_context, std::function<void()>&& method) - { - return [&io_context, method=std::move(method)]() - { - openvpn_io::post(io_context, std::move(method)); - }; - } - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/asiowork.hpp b/Sources/OpenVPN3/openvpn/asio/asiowork.hpp deleted file mode 100644 index 19aa57b..0000000 --- a/Sources/OpenVPN3/openvpn/asio/asiowork.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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-2020 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/>. - -// A null Asio unit of work, that prevents the Asio event loop from -// exiting. - -#ifndef OPENVPN_ASIO_ASIOWORK_H -#define OPENVPN_ASIO_ASIOWORK_H - -#include <openvpn/io/io.hpp> - -namespace openvpn { - class AsioWork - { - public: - AsioWork(openvpn_io::io_context& io_context) - : work(openvpn_io::make_work_guard(io_context)) - { - } - - private: - openvpn_io::executor_work_guard<openvpn_io::io_context::executor_type> work; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/asio/scoped_asio_stream.hpp b/Sources/OpenVPN3/openvpn/asio/scoped_asio_stream.hpp deleted file mode 100644 index 30ec28b..0000000 --- a/Sources/OpenVPN3/openvpn/asio/scoped_asio_stream.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// 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-2020 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/>. - -// A scoped Asio stream that is automatically closed by its destructor. - -#ifndef OPENVPN_ASIO_SCOPED_ASIO_STREAM_H -#define OPENVPN_ASIO_SCOPED_ASIO_STREAM_H - -#include <openvpn/common/size.hpp> - -namespace openvpn { - - template <typename STREAM> - class ScopedAsioStream - { - ScopedAsioStream(const ScopedAsioStream&) = delete; - ScopedAsioStream& operator=(const ScopedAsioStream&) = delete; - - public: - typedef STREAM* base_type; - - ScopedAsioStream() : obj_(undefined()) {} - - explicit ScopedAsioStream(STREAM *obj) - : obj_(obj) {} - - static STREAM* undefined() { return nullptr; } - - STREAM* release() - { - STREAM* ret = obj_; - obj_ = nullptr; - //OPENVPN_LOG("**** SAS RELEASE=" << ret); - return ret; - } - - static bool defined_static(STREAM* obj) - { - return obj != nullptr; - } - - bool defined() const - { - return defined_static(obj_); - } - - STREAM* operator()() const - { - return obj_; - } - - void reset(STREAM* obj) - { - close(); - obj_ = obj; - //OPENVPN_LOG("**** SAS RESET=" << obj_); - } - - // unusual semantics: replace obj without closing it first - void replace(STREAM* obj) - { - //OPENVPN_LOG("**** SAS REPLACE " << obj_ << " -> " << obj); - obj_ = obj; - } - - // return false if close error - bool close() - { - if (defined()) - { - //OPENVPN_LOG("**** SAS CLOSE obj=" << obj_); - delete obj_; - obj_ = nullptr; - } - return true; - } - - ~ScopedAsioStream() - { - //OPENVPN_LOG("**** SAS DESTRUCTOR"); - close(); - } - - private: - STREAM* obj_; - }; - -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/auth/authcert.hpp b/Sources/OpenVPN3/openvpn/auth/authcert.hpp deleted file mode 100644 index 1b298c5..0000000 --- a/Sources/OpenVPN3/openvpn/auth/authcert.hpp +++ /dev/null @@ -1,287 +0,0 @@ -// 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-2020 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_AUTH_AUTHCERT_H -#define OPENVPN_AUTH_AUTHCERT_H - -#include <string> -#include <vector> -#include <sstream> -#include <cstring> -#include <cstdint> -#include <memory> -#include <utility> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/binprefix.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/pki/x509track.hpp> -#include <openvpn/ssl/sni_metadata.hpp> - -namespace openvpn { - - class OpenSSLContext; - class MbedTLSContext; - - class AuthCert : public RC<thread_unsafe_refcount> - { - public: - // AuthCert needs to friend SSL implementation classes - friend class OpenSSLContext; - friend class MbedTLSContext; - - typedef RCPtr<AuthCert> Ptr; - - class Fail - { - public: - // Ordered by severity. If many errors are present, the - // most severe error will be returned by get_code(). - enum Type { - OK=0, // OK MUST be 0 - EXPIRED, // less severe... - BAD_CERT_TYPE, - CERT_FAIL, - SNI_ERROR, // more severe... - N - }; - - void add_fail(const size_t depth, const Type new_code, std::string reason) - { - if (new_code > code) - code = new_code; - while (errors.size() <= depth) - errors.emplace_back(); - std::string& err = errors[depth]; - if (err.empty()) - err = std::move(reason); - else if (err.find(reason) == std::string::npos) - { - err += ", "; - err += reason; - } - } - - bool is_fail() const - { - return code != OK; - } - - Type get_code() const - { - return code; - } - - std::string to_string(const bool use_prefix) const - { - std::string ret; - if (use_prefix) - { - ret += render_code(code); - ret += ": "; - } - bool notfirst = false; - for (size_t i = 0; i < errors.size(); ++i) - { - if (errors[i].empty()) - continue; - if (notfirst) - ret += ", "; - notfirst = true; - ret += errors[i]; - ret += " ["; - ret += openvpn::to_string(i); - ret += ']'; - } - return ret; - } - - static std::string render_code(const Type code) - { - switch (code) - { - case OK: - return "OK"; - case CERT_FAIL: - default: - return "CERT_FAIL"; - case BAD_CERT_TYPE: - return "BAD_CERT_TYPE"; - case EXPIRED: - return "EXPIRED"; - case SNI_ERROR: - return "SNI_ERROR"; - } - } - - private: - Type code{OK}; // highest-valued cert fail code - std::vector<std::string> errors; // human-readable cert errors by depth - }; - - AuthCert() - { - std::memset(issuer_fp, 0, sizeof(issuer_fp)); - sn = -1; - } - - bool defined() const - { - return sn >= 0; - } - - bool sni_defined() const - { - return !sni.empty(); - } - - bool cn_defined() const - { - return !cn.empty(); - } - - bool is_uninitialized() const - { - return cn.empty() && sn < 0 && !fail; - } - - template <typename T> - T issuer_fp_prefix() const - { - return bin_prefix<T>(issuer_fp); - } - - bool operator==(const AuthCert& other) const - { - return sni == other.sni && cn == other.cn && sn == other.sn && !std::memcmp(issuer_fp, other.issuer_fp, sizeof(issuer_fp)); - } - - bool operator!=(const AuthCert& other) const - { - return !operator==(other); - } - - std::string to_string() const - { - std::ostringstream os; - if (!sni.empty()) - os << "SNI=" << sni << ' '; - if (sni_metadata) - os << "SNI_CN=" << sni_metadata->sni_client_name(*this) << ' '; - os << "CN=" << cn - << " SN=" << sn - << " ISSUER_FP=" << issuer_fp_str(false); - return os.str(); - } - - std::string issuer_fp_str(const bool openssl_fmt) const - { - if (openssl_fmt) - return render_hex_sep(issuer_fp, sizeof(issuer_fp), ':', true); - else - return render_hex(issuer_fp, sizeof(issuer_fp), false); - } - - std::string normalize_cn() const // remove trailing "_AUTOLOGIN" from AS certs - { - if (string::ends_with(cn, "_AUTOLOGIN")) - return cn.substr(0, cn.length() - 10); - else - return cn; - } - - // Allow sni_metadata object, if it exists, to generate the client name. - // Otherwise fall back to normalize_cn(). - std::string sni_client_name() const - { - if (sni_metadata) - return sni_metadata->sni_client_name(*this); - else - return normalize_cn(); - } - - const std::string& get_sni() const - { - return sni; - } - - const std::string& get_cn() const - { - return cn; - } - - std::int64_t get_sn() const - { - return sn; - } - - const X509Track::Set* x509_track_get() const - { - return x509_track.get(); - } - - std::unique_ptr<X509Track::Set> x509_track_take_ownership() - { - return std::move(x509_track); - } - - void add_fail(const size_t depth, const Fail::Type new_code, std::string reason) - { - if (!fail) - fail.reset(new Fail()); - fail->add_fail(depth, new_code, std::move(reason)); - } - - bool is_fail() const - { - return fail && fail->is_fail(); - } - - const Fail* get_fail() const - { - return fail.get(); - } - - std::string fail_str() const - { - if (fail) - return fail->to_string(true); - else - return "OK"; - } - -#ifndef UNIT_TEST - private: -#endif - std::string sni; // SNI (server name indication) - std::string cn; // common name - std::int64_t sn; // serial number - unsigned char issuer_fp[20]; // issuer cert fingerprint - - std::unique_ptr<Fail> fail; - std::unique_ptr<X509Track::Set> x509_track; - SNI::Metadata::UPtr sni_metadata; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/auth/authcreds.hpp b/Sources/OpenVPN3/openvpn/auth/authcreds.hpp deleted file mode 100644 index e3c2026..0000000 --- a/Sources/OpenVPN3/openvpn/auth/authcreds.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// 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-2020 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_AUTH_AUTHCREDS -#define OPENVPN_AUTH_AUTHCREDS - -#include <utility> // for std::move -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/buffer/safestr.hpp> -#include <openvpn/auth/validatecreds.hpp> - -namespace openvpn { - - class AuthCreds : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<AuthCreds> Ptr; - - AuthCreds(std::string&& username_arg, - SafeString&& password_arg, - const std::string& peer_info_str) - : username(std::move(username_arg)), - password(std::move(password_arg)) - { - peer_info.parse_from_peer_info(peer_info_str, nullptr); - peer_info.update_map(); - } - - // for unit test - AuthCreds(std::string username_arg, - SafeString password_arg, - OptionList peer_info_arg) - : username(std::move(username_arg)), - password(std::move(password_arg)), - peer_info(std::move(peer_info_arg)) - { - } - - bool defined() const - { - return !username.empty(); - } - - bool is_valid_user_pass(const bool strict) const - { - return ValidateCreds::is_valid(ValidateCreds::USERNAME, username, strict) - && ValidateCreds::is_valid(ValidateCreds::PASSWORD, password, strict); - } - - bool is_valid(const bool strict) const - { - return defined() && is_valid_user_pass(strict); - } - - void wipe_password() - { - password.wipe(); - } - - std::string to_string() const - { - std::ostringstream os; - os << "*** AuthCreds ***" << std::endl; - os << "user: '" << username << "'" << std::endl; - os << "pass: (" << password.length() << " chars)" << std::endl; - os << "peer info:" << std::endl; - os << peer_info.render(Option::RENDER_BRACKET|Option::RENDER_NUMBER); - return os.str(); - } - - std::string username; - SafeString password; - OptionList peer_info; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/auth/cr.hpp b/Sources/OpenVPN3/openvpn/auth/cr.hpp deleted file mode 100644 index 18c75eb..0000000 --- a/Sources/OpenVPN3/openvpn/auth/cr.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// 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-2020 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/>. - -// Encapsulate the state of a static or dynamic authentication challenge. - -#ifndef OPENVPN_AUTH_CR_H -#define OPENVPN_AUTH_CR_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> - -// Static Challenge response: -// SCRV1:<BASE64_PASSWORD>:<BASE64_RESPONSE> -// -// Dynamic Challenge: -// CRV1:<FLAGS>:<STATE_ID>:<BASE64_USERNAME>:<CHALLENGE_TEXT> -// FLAGS is a comma-separated list of options: -// E -- echo -// R -- response required -// -// Dynamic Challenge response: -// Username: [username decoded from username_base64] -// Password: CRV1::<STATE_ID>::<RESPONSE_TEXT> - -namespace openvpn { - class ChallengeResponse : public RC<thread_unsafe_refcount> { - public: - typedef RCPtr<ChallengeResponse> Ptr; - - OPENVPN_SIMPLE_EXCEPTION(dynamic_challenge_parse_error); - OPENVPN_SIMPLE_EXCEPTION(static_challenge_parse_error); - - ChallengeResponse() - : echo(false), response_required(false) - { - } - - explicit ChallengeResponse(const std::string& cookie) - : echo(false), response_required(false) - { - init(cookie); - } - - ChallengeResponse(const std::string& cookie, const std::string& user) - : echo(false), response_required(false) - { - if (!is_dynamic(cookie) && cookie.find_first_of(':') == std::string::npos) - { - state_id = cookie; - username = user; - } - else - init(cookie); - } - - void init(const std::string& cookie) - { - typedef std::vector<std::string> StringList; - StringList sl; - sl.reserve(5); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, cookie, ':', 0, 4); - if (sl.size() != 5) - throw dynamic_challenge_parse_error(); - if (sl[0] != "CRV1") - throw dynamic_challenge_parse_error(); - - // parse options - { - StringList opt; - opt.reserve(2); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(opt, sl[1], ','); - for (StringList::const_iterator i = opt.begin(); i != opt.end(); ++i) - { - if (*i == "E") - echo = true; - else if (*i == "R") - response_required = true; - } - } - - // save state ID - state_id = sl[2]; - - // save username - try { - username = base64->decode(sl[3]); - } - catch (const Base64::base64_decode_error&) - { - throw dynamic_challenge_parse_error(); - } - - // save challenge - challenge_text = sl[4]; - } - - static bool is_dynamic(const std::string& s) - { - return string::starts_with(s, "CRV1:"); - } - - static bool is_static(const std::string& s) - { - return string::starts_with(s, "SCRV1:"); - } - - static void validate_dynamic(const std::string& cookie) - { - ChallengeResponse cr(cookie); - } - - std::string construct_dynamic_password(const std::string& response) const - { - std::ostringstream os; - os << "CRV1::" << state_id << "::" << response; - return os.str(); - } - - static std::string construct_static_password(const std::string& password, - const std::string& response) - { - std::ostringstream os; - os << "SCRV1:" << base64->encode(password) << ':' << base64->encode(response); - return os.str(); - } - - static void parse_static_cookie(const std::string& cookie, - std::string& password, - std::string& response) - { - typedef std::vector<std::string> StringList; - StringList sl; - sl.reserve(3); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, cookie, ':'); - if (sl.size() != 3) - throw static_challenge_parse_error(); - if (sl[0] != "SCRV1") - throw static_challenge_parse_error(); - - // get password - try { - password = base64->decode(sl[1]); - } - catch (const Base64::base64_decode_error&) - { - throw static_challenge_parse_error(); - } - - // get response - try { - response = base64->decode(sl[2]); - } - catch (const Base64::base64_decode_error&) - { - throw static_challenge_parse_error(); - } - } - - static std::string generate_dynamic_challenge(const std::string& session_token, - const std::string& username, - const std::string& challenge, - const bool echo, - const bool response_required) - { - std::ostringstream os; - bool comma = false; - os << "CRV1:"; - if (echo) - { - if (comma) - os << ","; - os << "E"; - comma = true; - } - if (response_required) - { - if (comma) - os << ","; - os << "R"; - comma = true; - } - os << ':' << session_token; - os << ':' << base64->encode(username); - os << ':' << challenge; - return os.str(); - } - - const std::string& get_state_id() const { return state_id; } - const std::string& get_username() const { return username; } - bool get_echo() const { return echo; } - bool get_response_required() const { return response_required; } - const std::string& get_challenge_text() const { return challenge_text; } - - private: - bool echo; - bool response_required; - std::string state_id; - std::string username; - std::string challenge_text; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/auth/validatecreds.hpp b/Sources/OpenVPN3/openvpn/auth/validatecreds.hpp deleted file mode 100644 index aeeff24..0000000 --- a/Sources/OpenVPN3/openvpn/auth/validatecreds.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// 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-2020 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_AUTH_VALIDATE_CREDS_H -#define OPENVPN_AUTH_VALIDATE_CREDS_H - -#include <openvpn/common/unicode.hpp> - -namespace openvpn { - // Validate authentication credential. - // Must be UTF-8. - // Other checks on size and content below. - // We don't check that the credential is non-empty. - namespace ValidateCreds { - - enum Type { - USERNAME, - PASSWORD, - RESPONSE - }; - - template <typename STRING> - static bool is_valid(const Type type, const STRING& cred, const bool strict) - { - size_t max_len_flags; - if (strict) - { - // length <= 512 unicode chars, no control chars allowed - max_len_flags = 512 | Unicode::UTF8_NO_CTRL; - } - else - { - switch (type) - { - case USERNAME: - // length <= 512 unicode chars, no control chars allowed - max_len_flags = 512 | Unicode::UTF8_NO_CTRL; - break; - case PASSWORD: - case RESPONSE: - // length <= 16384 unicode chars - max_len_flags = 16384; - break; - default: - return false; - } - } - return Unicode::is_valid_utf8(cred, max_len_flags); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/aws/awsca.hpp b/Sources/OpenVPN3/openvpn/aws/awsca.hpp deleted file mode 100644 index 1181d1c..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awsca.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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-2020 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/>. - -// AWS API CA - -#pragma once - -#include <openvpn/common/fileunix.hpp> - -namespace openvpn { - namespace AWS { - inline std::string api_ca() - { - // paths are copied from https://golang.org/src/crypto/x509/root_linux.go - std::list<std::string> certs = { - "/etc/ssl/certs/ca-certificates.crt", // debian/ubuntu - "/etc/pki/tls/certs/ca-bundle.crt", // fedora/rhel6 - "/etc/ssl/ca-bundle.pem", // opensuse, - "/etc/pki/tls/cacert.pem" // openelec - "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" // centos/rhel7 - "/etc/ssl/cert.pem" // alpine - }; - for (const auto& cert : certs) - { - if (std::ifstream{cert}) - return read_text_unix(cert); - } - throw file_unix_error("No CA certificate files found in system paths"); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/aws/awscreds.hpp b/Sources/OpenVPN3/openvpn/aws/awscreds.hpp deleted file mode 100644 index a0311ad..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awscreds.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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/>. - -// AWS credentials - -#pragma once - -#include <string> - -namespace openvpn { - namespace AWS { - struct Creds - { - Creds() {} - - Creds(std::string access_key_arg, - std::string secret_key_arg, - std::string token_arg = "") - : access_key(std::move(access_key_arg)), - secret_key(std::move(secret_key_arg)), - token(std::move(token_arg)) - { - } - - bool defined() const - { - return !access_key.empty() && !secret_key.empty(); - } - - std::string to_string() const - { - return "AWS::Creds[access_key=" + access_key + " len(secret_key)=" + std::to_string(secret_key.length()) + ']'; - } - - std::string access_key; - std::string secret_key; - std::string token; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/aws/awshttp.hpp b/Sources/OpenVPN3/openvpn/aws/awshttp.hpp deleted file mode 100644 index 2300eda..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awshttp.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// 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-2020 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/>. - -// Build HTTPS context for AWS queries - -#ifndef OPENVPN_AWS_AWSHTTP_H -#define OPENVPN_AWS_AWSHTTP_H - -#include <string> -#include <utility> - -#include <openvpn/frame/frame_init.hpp> -#include <openvpn/crypto/digestapi.hpp> -#include <openvpn/ws/httpcliset.hpp> -#include <openvpn/aws/awsca.hpp> -#include <openvpn/ssl/sslchoose.hpp> - -namespace openvpn { - namespace AWS { - class HTTPContext - { - public: - HTTPContext(RandomAPI::Ptr rng, - const int debug_level) - : frame_(frame_init_simple(2048)), - digest_factory_(new CryptoDigestFactory<SSLLib::CryptoAPI>()), - rng_(std::move(rng)), - debug_level_(debug_level) - { - http_config_ = http_config(); - } - - WS::ClientSet::TransactionSet::Ptr transaction_set(std::string host) const - { - WS::ClientSet::TransactionSet::Ptr ts = new WS::ClientSet::TransactionSet; - ts->host.host = std::move(host); - ts->host.port = "443"; - ts->http_config = http_config_; - ts->max_retries = 10; - ts->retry_duration = Time::Duration::seconds(1); - ts->debug_level = debug_level_; - return ts; - } - - int debug_level() const - { - return debug_level_; - } - - DigestFactory& digest_factory() const - { - return *digest_factory_; - } - - RandomAPI* rng() const - { - return rng_.get(); - } - - private: - WS::Client::Config::Ptr http_config() const - { - // SSL flags - unsigned int ssl_flags = 0; - if (debug_level_ >= 2) - ssl_flags |= SSLConst::LOG_VERIFY_STATUS; - - // make SSL context using awspc_web_cert() as our CA bundle - SSLLib::SSLAPI::Config::Ptr ssl(new SSLLib::SSLAPI::Config); - ssl->set_mode(Mode(Mode::CLIENT)); - ssl->load_ca(api_ca(), false); - ssl->set_local_cert_enabled(false); - ssl->set_tls_version_min(TLSVersion::V1_2); - ssl->set_remote_cert_tls(KUParse::TLS_WEB_SERVER); - ssl->set_flags(ssl_flags); - ssl->set_frame(frame_); - ssl->set_rng(rng_); - - // make HTTP context - WS::Client::Config::Ptr hc(new WS::Client::Config()); - hc->frame = frame_; - hc->ssl_factory = ssl->new_factory(); - hc->user_agent = "OpenVPN-PG"; - hc->connect_timeout = 30; - hc->general_timeout = 60; - return hc; - } - - Frame::Ptr frame_; - DigestFactory::Ptr digest_factory_; - RandomAPI::Ptr rng_; - WS::Client::Config::Ptr http_config_; - int debug_level_; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/aws/awspc.hpp b/Sources/OpenVPN3/openvpn/aws/awspc.hpp deleted file mode 100644 index 22850ef..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awspc.hpp +++ /dev/null @@ -1,556 +0,0 @@ -// 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-2020 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/>. - -// Get AWS info such as instanceId, region, and privateIp. -// Also optionally call AWSPC API with product code to get -// number of licensed concurrent connections. - -#pragma once - -#include <string> -#include <utility> - -#include <openvpn/aws/awscreds.hpp> -#include <openvpn/ws/httpcliset.hpp> -#include <openvpn/common/jsonhelper.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/enumdir.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/random/devurand.hpp> -#include <openvpn/frame/frame_init.hpp> -#include <openvpn/openssl/sign/verify.hpp> -#include <openvpn/openssl/sign/pkcs7verify.hpp> -#include <openvpn/ssl/sslchoose.hpp> - -namespace openvpn { - namespace AWS { - - class PCQuery : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<PCQuery> Ptr; - - OPENVPN_EXCEPTION(awspc_query_error); - - struct Info - { - std::string instanceId; - std::string region; - std::string privateIp; - - Creds creds; - - int concurrentConnections = -1; - std::string error; - - bool is_error() const - { - return !error.empty(); - } - - bool instance_data_defined() const - { - return !instanceId.empty() && !region.empty() && !privateIp.empty(); - } - - // example: [instanceId=i-ae91d23e region=us-east-1 privateIp=10.0.0.218 concurrentConnections=10] - std::string to_string() const - { - std::string ret = "[instanceId=" + instanceId + " region=" + region; - if (!privateIp.empty()) - ret += " privateIp=" + privateIp; - if (concurrentConnections >= 0) - ret += " concurrentConnections=" + std::to_string(concurrentConnections); - if (!error.empty()) - ret += " error='" + error + '\''; - ret += ']'; - return ret; - } - }; - - PCQuery(WS::ClientSet::Ptr cs_arg, - const bool lookup_product_code_arg, - const int debug_level_arg) - : cs(std::move(cs_arg)), - rng(new DevURand()), - frame(frame_init_simple(1024)), - lookup_product_code(lookup_product_code_arg), - debug_level(debug_level_arg) - { - } - - PCQuery(WS::ClientSet::Ptr cs_arg, - const std::string& role_for_credentials_arg, - const std::string& certs_dir_arg) - : cs(std::move(cs_arg)), - rng(new DevURand()), - frame(frame_init_simple(1024)), - lookup_product_code(false), - debug_level(0), - role_for_credentials(role_for_credentials_arg), - certs_dir(certs_dir_arg) - { - } - - void start(std::function<void(Info info)> completion_arg) - { - // make sure we are not in a pending state - if (pending) - throw awspc_query_error("request pending"); - pending = true; - - // save completion method - completion = std::move(completion_arg); - - // init return object - info = Info(); - - try { - // make HTTP context - WS::Client::Config::Ptr http_config(new WS::Client::Config()); - http_config->frame = frame; - http_config->connect_timeout = 15; - http_config->general_timeout = 30; - - // make transaction set for initial local query - WS::ClientSet::TransactionSet::Ptr ts = new WS::ClientSet::TransactionSet; - ts->host.host = "169.254.169.254"; - ts->host.port = "80"; - ts->http_config = http_config; - ts->max_retries = 3; - ts->debug_level = debug_level; - - // transaction #1 - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.method = "GET"; - t->req.uri = "/latest/dynamic/instance-identity/document"; - ts->transactions.push_back(std::move(t)); - } - - // transaction #2 - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.method = "GET"; - t->req.uri = "/latest/dynamic/instance-identity/pkcs7"; - ts->transactions.push_back(std::move(t)); - } - - // transaction #3 - if (lookup_product_code) - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.method = "GET"; - t->req.uri = "/latest/meta-data/product-codes"; - ts->transactions.push_back(std::move(t)); - } - - // transaction #4 - if (!role_for_credentials.empty()) - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.method = "GET"; - t->req.uri = "/latest/meta-data/iam/security-credentials/" + role_for_credentials; - ts->transactions.push_back(std::move(t)); - } - - // completion handler - ts->completion = [self=Ptr(this)](WS::ClientSet::TransactionSet& ts) { - self->local_query_complete(ts); - }; - - // do the request - cs->new_request(ts); - } - catch (const std::exception& e) - { - done(e.what()); - } - } - - void stop() - { - if (cs) - cs->stop(); - } - - private: - void done(std::string error) - { - pending = false; - info.error = std::move(error); - if (completion) - completion(std::move(info)); - } - - void local_query_complete(WS::ClientSet::TransactionSet& lts) - { - try { - // get transactions and check that they succeeded - WS::ClientSet::Transaction& ident_trans = *lts.transactions.at(0); - if (!ident_trans.request_status_success()) - { - done("could not fetch AWS identity document: " + ident_trans.format_status(lts)); - return; - } - - WS::ClientSet::Transaction& sig_trans = *lts.transactions.at(1); - if (!sig_trans.request_status_success()) - { - done("could not fetch AWS identity document signature: " + sig_trans.format_status(lts)); - return; - } - - // get identity document and signature - const std::string ident = ident_trans.content_in.to_string(); - const std::string sig = "-----BEGIN PKCS7-----\n" - + sig_trans.content_in.to_string() - + "\n-----END PKCS7-----\n"; - - if (debug_level >= 3) - { - OPENVPN_LOG("IDENT\n" << ident); - OPENVPN_LOG("SIG\n" << sig); - } - - // verify signature on identity document - { - std::list<OpenSSLPKI::X509> certs; - if (certs_dir.empty()) - certs.emplace_back(awscert(), "AWS Cert"); - else - { - enum_dir(certs_dir, [&certs, certs_dir=certs_dir](const std::string& file) { - certs.emplace_back(read_text(certs_dir + "/" + file), "AWS Cert"); - }); - } - OpenSSLSign::verify_pkcs7(certs, sig, ident); - } - - // parse the identity document (JSON) - { - const std::string title = "identity-document"; - const Json::Value root = json::parse(ident, title); - info.region = json::get_string(root, "region", title); - info.instanceId = json::get_string(root, "instanceId", title); - info.privateIp = json::get_string(root, "privateIp", title); - } - - if (lookup_product_code) - { - WS::ClientSet::Transaction& pc_trans = *lts.transactions.at(2); - if (pc_trans.request_status_success()) - { - const std::string pc = pc_trans.content_in.to_string(); - queue_pc_validation(pc); - } - else - done("could not fetch AWS product code: " + pc_trans.format_status(lts)); - } - - if (!role_for_credentials.empty()) - { - WS::ClientSet::Transaction& cred_trans = *lts.transactions.at(lookup_product_code ? 3 : 2); - if (cred_trans.request_status_success()) - { - const std::string creds = cred_trans.content_in.to_string(); - const Json::Value root = json::parse(creds); - info.creds.access_key = json::get_string(root, "AccessKeyId"); - info.creds.secret_key = json::get_string(root, "SecretAccessKey"); - info.creds.token = json::get_string(root, "Token"); - done(""); - } - else - done("could not fetch role credentials: " + cred_trans.format_status(lts)); - } - else - done(""); - } - catch (const std::exception& e) - { - done(e.what()); - } - } - - void queue_pc_validation(const std::string& pc) - { - if (debug_level >= 3) - OPENVPN_LOG("PRODUCT CODE: " << pc); - - // SSL flags - unsigned int ssl_flags = SSLConst::ENABLE_CLIENT_SNI; - if (debug_level >= 1) - ssl_flags |= SSLConst::LOG_VERIFY_STATUS; - - // make SSL context using awspc_web_cert() as our CA bundle - SSLLib::SSLAPI::Config::Ptr ssl(new SSLLib::SSLAPI::Config); - ssl->set_mode(Mode(Mode::CLIENT)); - ssl->load_ca(awspc_web_cert(), false); - ssl->set_local_cert_enabled(false); - ssl->set_tls_version_min(TLSVersion::V1_2); - ssl->set_remote_cert_tls(KUParse::TLS_WEB_SERVER); - ssl->set_flags(ssl_flags); - ssl->set_frame(frame); - ssl->set_rng(rng); - - // make HTTP context - WS::Client::Config::Ptr hc(new WS::Client::Config()); - hc->frame = frame; - hc->ssl_factory = ssl->new_factory(); - hc->user_agent = "PG"; - hc->connect_timeout = 30; - hc->general_timeout = 60; - - // make host list - WS::ClientSet::HostRetry::Ptr hr(new WS::ClientSet::HostRetry( - "awspc1.openvpn.net", - "awspc2.openvpn.net" - )); - - // make transaction set - WS::ClientSet::TransactionSet::Ptr ts = new WS::ClientSet::TransactionSet; - ts->host.host = hr->next_host(); - ts->host.port = "443"; - ts->http_config = hc; - ts->error_recovery = hr; - ts->max_retries = 5; - ts->retry_duration = Time::Duration::seconds(5); - ts->debug_level = debug_level; - - // transaction #1 - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.uri = "/prod/AwsPC"; - t->req.method = "POST"; - t->ci.type = "application/json"; - t->randomize_resolver_results = true; - - Json::Value root(Json::objectValue); - root["region"] = Json::Value(info.region); - root["identityIp"] = Json::Value(info.privateIp); - root["host"] = Json::Value(openvpn_io::ip::host_name()); - root["instanceId"] = Json::Value(info.instanceId); - root["productCode"] = Json::Value(pc); - root["nonce"] = Json::Value(nonce()); - const std::string jreq = root.toStyledString(); - t->content_out.push_back(buf_from_string(jreq)); - awspc_req = std::move(root); - - ts->transactions.push_back(std::move(t)); - - if (debug_level >= 3) - OPENVPN_LOG("AWSPC REQ\n" << jreq); - } - - // completion handler - ts->completion = [self=Ptr(this)](WS::ClientSet::TransactionSet& ts) { - self->awspc_query_complete(ts); - }; - - // do the request - cs->new_request(ts); - } - - void awspc_query_complete(WS::ClientSet::TransactionSet& ats) - { - try { - const std::string title = "awspc-reply"; - - // get transactions and check that they succeeded - WS::ClientSet::Transaction& trans = *ats.transactions.at(0); - if (!trans.request_status_success()) - { - done("awspc server error: " + trans.format_status(ats)); - return; - } - - // check content-type - if (trans.reply.headers.get_value_trim("content-type") != "application/json") - { - done("expected application/json reply from awspc server"); - return; - } - - // parse JSON reply - const std::string jtxt = trans.content_in.to_string(); - const Json::Value root = json::parse(jtxt, title); - if (debug_level >= 3) - OPENVPN_LOG("AWSPC REPLY\n" << root.toStyledString()); - - // check for errors - if (json::exists(root, "errorMessage")) - { - const std::string em = json::get_string(root, "errorMessage", title); - const std::string et = json::get_string_optional(root, "errorType", "unspecified-error", title); - done(et + " : " + em); - return; - } - - // verify consistency of region, instanceId, productCode, and nonce - if (!awspc_req_verify_consistency(root)) - { - done("awspc request/reply consistency"); - return; - } - - // verify reply signature - { - const std::string line_to_sign = to_string_sig(root); - if (debug_level >= 3) - OPENVPN_LOG("LINE TO SIGN: " << line_to_sign); - const std::string sig = json::get_string(root, "signature", title); - const OpenSSLPKI::X509 cert(awspc_signing_cert(), "awspc-cert"); - OpenSSLSign::verify(cert, sig, line_to_sign, "sha256"); - } - - // get concurrent connections - info.concurrentConnections = json::get_int(root, "concurrentConnections", title); - done(""); - } - catch (const std::exception& e) - { - done(e.what()); - } - } - - bool awspc_req_verify_consistency(const Json::Value& reply, - const std::string& key) const - { - return json::get_string(reply, key, "awspc-verify-reply") == json::get_string(awspc_req, key, "awspc-verify-request"); - } - - bool awspc_req_verify_consistency(const Json::Value& reply) const - { - return awspc_req_verify_consistency(reply, "region") - && awspc_req_verify_consistency(reply, "instanceId") - && awspc_req_verify_consistency(reply, "productCode") - && awspc_req_verify_consistency(reply, "nonce"); - } - - static std::string to_string_sig(const Json::Value& reply) - { - const std::string title = "to-string-sig"; - return json::get_string(reply, "region", title) - + '/' + json::get_string(reply, "instanceId", title) - + '/' + json::get_string(reply, "productCode", title) - + '/' + json::get_string(reply, "nonce", title) - + '/' + std::to_string(json::get_int(reply, "concurrentConnections", title)); - } - - std::string nonce() const - { - unsigned char data[16]; - rng->assert_crypto(); - rng->rand_fill(data); - return render_hex(data, sizeof(data)); - } - - // The AWS cert for PKCS#7 validation of AWS identity document - static std::string awscert() - { - return std::string( - "-----BEGIN CERTIFICATE-----\n" - "MIIC7TCCAq0CCQCWukjZ5V4aZzAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw\n" - "FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD\n" - "VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xMjAxMDUxMjU2MTJaFw0z\n" - "ODAxMDUxMjU2MTJaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u\n" - "IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl\n" - "cnZpY2VzIExMQzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCjkvcS2bb1VQ4yt/5e\n" - "ih5OO6kK/n1Lzllr7D8ZwtQP8fOEpp5E2ng+D6Ud1Z1gYipr58Kj3nssSNpI6bX3\n" - "VyIQzK7wLclnd/YozqNNmgIyZecN7EglK9ITHJLP+x8FtUpt3QbyYXJdmVMegN6P\n" - "hviYt5JH/nYl4hh3Pa1HJdskgQIVALVJ3ER11+Ko4tP6nwvHwh6+ERYRAoGBAI1j\n" - "k+tkqMVHuAFcvAGKocTgsjJem6/5qomzJuKDmbJNu9Qxw3rAotXau8Qe+MBcJl/U\n" - "hhy1KHVpCGl9fueQ2s6IL0CaO/buycU1CiYQk40KNHCcHfNiZbdlx1E9rpUp7bnF\n" - "lRa2v1ntMX3caRVDdbtPEWmdxSCYsYFDk4mZrOLBA4GEAAKBgEbmeve5f8LIE/Gf\n" - "MNmP9CM5eovQOGx5ho8WqD+aTebs+k2tn92BBPqeZqpWRa5P/+jrdKml1qx4llHW\n" - "MXrs3IgIb6+hUIB+S8dz8/mmO0bpr76RoZVCXYab2CZedFut7qc3WUH9+EUAH5mw\n" - "vSeDCOUMYQR7R9LINYwouHIziqQYMAkGByqGSM44BAMDLwAwLAIUWXBlk40xTwSw\n" - "7HX32MxXYruse9ACFBNGmdX2ZBrVNGrN9N2f6ROk0k9K\n" - "-----END CERTIFICATE-----\n"); - } - - // The OpenVPN Tech. lambda web cert - static std::string awspc_web_cert() - { - // Go Daddy Root Certificate Authority - G2 - return std::string( - "-----BEGIN CERTIFICATE-----\n" - "MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT\n" - "B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu\n" - "MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5\n" - "MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n" - "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G\n" - "A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI\n" - "hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq\n" - "9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD\n" - "+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd\n" - "fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl\n" - "NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC\n" - "MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9\n" - "BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac\n" - "vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r\n" - "5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV\n" - "N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO\n" - "LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1\n" - "-----END CERTIFICATE-----\n"); - } - - // The OpenVPN Tech. lambda response signing cert - static std::string awspc_signing_cert() - { - return std::string( - "-----BEGIN CERTIFICATE-----\n" - "MIIDSDCCAjCgAwIBAgIQYadxADonNbu3mPeXR0yYVTANBgkqhkiG9w0BAQsFADAW\n" - "MRQwEgYDVQQDEwtBV1MgUEMgUm9vdDAeFw0xNjAzMDExOTU2NTZaFw0yNjAyMjcx\n" - "OTU2NTZaMBAxDjAMBgNVBAMTBWF3c3BjMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" - "MIIBCgKCAQEA0ggZoYroOMwDHKCngVOdUKiF6y65LDWmbAwZVqwVI7WYpvOELV34\n" - "04ZYtSqPq6IoGFuH6zl0P5rCi674T0oBPSUTmlLwLks+1zrGznboApkr67Mf2dCd\n" - "snlyaNPuwrjWHJBa6Pi9dv/YMoJgDxOxk9mslAlcl5xOFgXbfSj1pAA0KVzwwbzz\n" - "dnznJL67wCnuiAeqBxbkyarfOL414tepsI24kHoAddAVDdhWQ2WkhrT/vK2IRdGZ\n" - "kU5hAAz/qPKkJxebw5uc+cL2TBii2r0Hvg7tEXI9eIEWeoghftsE5YEuaQHP4EVL\n" - "JU+21OQzz0lT9L2rrvffTR7cF89Nbn2KMQIDAQABo4GXMIGUMAkGA1UdEwQCMAAw\n" - "HQYDVR0OBBYEFAMy6uiElCGZVP/wwJeqvXL7QHTSMEYGA1UdIwQ/MD2AFLDKS6Dk\n" - "NtTpQoOPxJi+DRS+GD2CoRqkGDAWMRQwEgYDVQQDEwtBV1MgUEMgUm9vdIIJAOu5\n" - "NqrIe040MBMGA1UdJQQMMAoGCCsGAQUFBwMCMAsGA1UdDwQEAwIHgDANBgkqhkiG\n" - "9w0BAQsFAAOCAQEAsFhhC9wwybTS2yTYiStATbxHWqnHJRrbMBpqX8FJweS1MM/j\n" - "pwr1suTllwTHpqXpqgN6SDzdeG2ZKx8pvJr/dlmD9e+cHguIMTo6TcqPv1MPl3MZ\n" - "ugOmDPlgmFYwAWBwzujiGR9bgdGfzw+94KK06iO8MrFLtkz9EbeoJol68mi98CEz\n" - "kmOb2BM6tVzkvB9fIYyNkW66ZJs2gXwb6RZTyE9HMMGR67nWKYo9SxpB6f+6hlyU\n" - "q7ptxP2Rwmz0u1pRaZdfHmJFOJnPniB7UmMx/t3ftqYWYDXuobr3LVvg7+33WUk0\n" - "HfSdbAEkzzC82UTHj0xVH/uZZt8ORChRxuIWZQ==\n" - "-----END CERTIFICATE-----\n"); - } - - WS::ClientSet::Ptr cs; - RandomAPI::Ptr rng; - Frame::Ptr frame; - const bool lookup_product_code; - const int debug_level; - std::string role_for_credentials; - std::string certs_dir; - - std::function<void(Info info)> completion; - Info info; - Json::Value awspc_req; - bool pending = false; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/aws/awsrest.hpp b/Sources/OpenVPN3/openvpn/aws/awsrest.hpp deleted file mode 100644 index 2cf3a4e..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awsrest.hpp +++ /dev/null @@ -1,254 +0,0 @@ -// 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-2020 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/>. - -// AWS REST API query utilities such as query signing - -#pragma once - -#include <string> -#include <vector> -#include <cstdint> // for std::uint8_t -#include <algorithm> -#include <utility> -#include <time.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/http/urlencode.hpp> -#include <openvpn/crypto/digestapi.hpp> -#include <openvpn/aws/awscreds.hpp> - -namespace openvpn { - namespace AWS { - class REST - { - public: - OPENVPN_EXCEPTION(aws_rest_error); - - // 20130524T000000Z - static std::string amz_date() - { - struct tm lt; - char buf[64]; - const time_t t = ::time(nullptr); - if (!::gmtime_r(&t, <)) - throw aws_rest_error("gmtime_r failed"); - if (!::strftime(buf, sizeof(buf), - "%Y%m%dT%H%M%SZ", - <)) - throw aws_rest_error("strftime failed"); - return std::string(buf); - } - - struct SHA256 - { - std::string to_hex() const - { - return render_hex(hash, sizeof(hash)); - } - - std::uint8_t hash[32]; - }; - - static SHA256 hmac_sha256(DigestFactory& digest_factory, const std::string& data, const std::string& key) - { - SHA256 ret; - HMACInstance::Ptr hi(digest_factory.new_hmac(CryptoAlgs::SHA256, (const std::uint8_t *)key.c_str(), key.length())); - hi->update((const std::uint8_t *)data.c_str(), data.length()); - hi->final(ret.hash); - return ret; - } - - static SHA256 hmac_sha256(DigestFactory& digest_factory, const std::string& data, const SHA256& key) - { - SHA256 ret; - HMACInstance::Ptr hi(digest_factory.new_hmac(CryptoAlgs::SHA256, key.hash, sizeof(key.hash))); - hi->update((const std::uint8_t *)data.c_str(), data.length()); - hi->final(ret.hash); - return ret; - } - - static SHA256 sha256(DigestFactory& digest_factory, const std::string& data) - { - SHA256 ret; - DigestInstance::Ptr di(digest_factory.new_digest(CryptoAlgs::SHA256)); - di->update((const std::uint8_t *)data.c_str(), data.length()); - di->final(ret.hash); - return ret; - } - - static SHA256 signing_key(DigestFactory& df, - const std::string& key, - const std::string& date_stamp, - const std::string& region_name, - const std::string& service_name) - { - const SHA256 h1 = hmac_sha256(df, date_stamp, "AWS4" + key); - const SHA256 h2 = hmac_sha256(df, region_name, h1); - const SHA256 h3 = hmac_sha256(df, service_name, h2); - const SHA256 h4 = hmac_sha256(df, "aws4_request", h3); - return h4; - } - - struct KeyValue - { - KeyValue(std::string key_arg, std::string value_arg) - : key(std::move(key_arg)), - value(std::move(value_arg)) - { - } - - bool operator<(const KeyValue& rhs) const - { - return key < rhs.key; - } - - std::string uri_encode() const - { - return URL::encode(key) + '=' + URL::encode(value); - } - - std::string key; - std::string value; - }; - - struct Query : public std::vector<KeyValue> - { - std::string canonical_query_string() const - { - bool first = true; - std::string ret; - for (auto &p : *this) - { - if (!first) - ret += '&'; - ret += p.uri_encode(); - first = false; - } - return ret; - } - - void sort() - { - std::sort(begin(), end()); - } - }; - - struct QueryBuilder - { - std::string date; // such as "20130524T000000Z" - unsigned int expires = 300; // request expiration in seconds - std::string region; // such as "us-east-1" - std::string service; // such as "s3" - std::string method; // such as "GET" - std::string host; // such as "ec2.us-west-2.amazonaws.com" - std::string uri; // such as "/" - Query parms; - - std::string uri_query() const - { - return uri + '?' + parms.canonical_query_string(); - } - - std::string url_query() const - { - return "https://" + host + uri_query(); - } - - void add_amz_parms(const Creds& creds) - { - parms.emplace_back("X-Amz-Algorithm", "AWS4-HMAC-SHA256"); - parms.emplace_back("X-Amz-Credential", creds.access_key + '/' + amz_credential()); - parms.emplace_back("X-Amz-Date", date); - parms.emplace_back("X-Amz-Expires", std::to_string(expires)); - parms.emplace_back("X-Amz-SignedHeaders", amz_signed_headers()); - - if (!creds.token.empty()) - parms.emplace_back("X-Amz-Security-Token", creds.token); - } - - void sort_parms() - { - parms.sort(); - } - - void add_amz_signature(DigestFactory& digest_factory, const Creds& creds) - { - parms.emplace_back("X-Amz-Signature", signature(digest_factory, creds)); - } - - std::string signature(DigestFactory& digest_factory, const Creds& creds) const - { - const SHA256 sk = signing_key(digest_factory, - creds.secret_key, - date.substr(0, 8), - region, - service); - return hmac_sha256(digest_factory, string_to_sign(digest_factory), sk).to_hex(); - } - - virtual std::string content_hash() const - { - // SHA256 of empty string - return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - } - - std::string canonical_request() const - { - std::string ret = - method + '\n' - + uri + '\n' - + parms.canonical_query_string() + '\n' - + "host:" + host + '\n' - + '\n' - + amz_signed_headers() + '\n'; - if (service == "s3") - ret += "UNSIGNED-PAYLOAD"; - else - ret += content_hash(); - return ret; - } - - std::string amz_signed_headers() const - { - std::string signed_headers = "host"; - return signed_headers; - } - - std::string string_to_sign(DigestFactory& digest_factory) const - { - return - "AWS4-HMAC-SHA256\n" - + date + '\n' - + amz_credential() + "\n" - + sha256(digest_factory, canonical_request()).to_hex(); - } - - std::string amz_credential() const - { - return date.substr(0, 8) + '/' + region + '/' + service + "/aws4_request"; - } - - virtual ~QueryBuilder() {} - }; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/aws/awsroute.hpp b/Sources/OpenVPN3/openvpn/aws/awsroute.hpp deleted file mode 100644 index c2b028a..0000000 --- a/Sources/OpenVPN3/openvpn/aws/awsroute.hpp +++ /dev/null @@ -1,481 +0,0 @@ -// 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-2020 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/>. - -// Query/Set VPC routes, requires this policy: -// -// { -// "Version": "2012-10-17", -// "Statement": [ -// { -// "Sid": "Stmt1478633458000", -// "Effect": "Allow", -// "Action": [ -// "ec2:CreateRoute", -// "ec2:DescribeNetworkInterfaceAttribute", -// "ec2:DescribeNetworkInterfaces", -// "ec2:DescribeRouteTables", -// "ec2:ModifyNetworkInterfaceAttribute", -// "ec2:ReplaceRoute", -// "ec2:DeleteRoute" -// ], -// "Resource": [ -// "*" -// ] -// } -// ] -// } - -#pragma once - -#include <openvpn/common/xmlhelper.hpp> -#include <openvpn/aws/awshttp.hpp> -#include <openvpn/aws/awspc.hpp> -#include <openvpn/aws/awsrest.hpp> - -namespace openvpn { - namespace AWS { - class Route - { - public: - OPENVPN_EXCEPTION(aws_route_error); - - enum class RouteTargetType - { - INTERFACE_ID, - INSTANCE_ID - }; - - class Context - { - public: - Context(PCQuery::Info instance_info_arg, - Creds creds_arg, - RandomAPI::Ptr rng, - Stop* async_stop_arg, - const int debug_level) - : instance_info(std::move(instance_info_arg)), - http_context(std::move(rng), debug_level), - ts(http_context.transaction_set(ec2_host(instance_info))), - creds(std::move(creds_arg)), - async_stop(async_stop_arg) - { - } - - void reset() - { - if (ts) - ts->hsc.reset(); - } - - std::string instance_id() const - { - return instance_info.instanceId; - } - - private: - friend class Route; - PCQuery::Info instance_info; - HTTPContext http_context; - WS::ClientSet::TransactionSet::Ptr ts; - Creds creds; - Stop* async_stop; - }; - - // Query network_interface_id and route_table_id - // from EC2 API. - class Info - { - public: - Info(std::string network_interface_id_arg, - std::string route_table_id_arg) - : network_interface_id(std::move(network_interface_id_arg)), - route_table_id(std::move(route_table_id_arg)) - { - } - - Info(Context& ctx) - { - // AWS IDs local to this constructor - std::string vpc_id; - std::string subnet_id; - - // first request -- get the AWS network interface - { - // create API query - { - REST::Query q; - q.emplace_back("Action", "DescribeNetworkInterfaces"); - q.emplace_back("Filter.1.Name", "attachment.instance-id"); - q.emplace_back("Filter.1.Value.1", ctx.instance_info.instanceId); - q.emplace_back("Filter.2.Name", "addresses.private-ip-address"); - q.emplace_back("Filter.2.Value.1", ctx.instance_info.privateIp); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "DescribeNetworkInterfaces: " << t.format_status(*ctx.ts)); - - // parse XML reply - const Xml::Document doc(reply, "DescribeNetworkInterfaces"); - const tinyxml2::XMLElement* item = Xml::find(&doc, - "DescribeNetworkInterfacesResponse", - "networkInterfaceSet", - "item"); - if (!item) - OPENVPN_THROW(aws_route_error, "DescribeNetworkInterfaces: cannot locate <item> tag in returned XML:\n" << reply); - network_interface_id = Xml::find_text(item, "networkInterfaceId"); - vpc_id = Xml::find_text(item, "vpcId"); - subnet_id = Xml::find_text(item, "subnetId"); - if (network_interface_id.empty() || vpc_id.empty() || subnet_id.empty()) - OPENVPN_THROW(aws_route_error, "DescribeNetworkInterfaces: cannot locate one of networkInterfaceId, vpcId, or subnetId in returned XML:\n" << reply); - } - } - - // second request -- get the VPC routing table - { - // create API query - { - REST::Query q; - q.emplace_back("Action", "DescribeRouteTables"); - q.emplace_back("Filter.1.Name", "vpc-id"); - q.emplace_back("Filter.1.Value.1", vpc_id); - q.emplace_back("Filter.2.Name", "association.subnet-id"); - q.emplace_back("Filter.2.Value.1", subnet_id); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "DescribeRouteTables: " << t.format_status(*ctx.ts) << '\n' << reply); - - // parse XML reply - const Xml::Document doc(reply, "DescribeRouteTables"); - route_table_id = Xml::find_text(&doc, - "DescribeRouteTablesResponse", - "routeTableSet", - "item", - "routeTableId"); - if (route_table_id.empty()) - OPENVPN_THROW(aws_route_error, "DescribeRouteTables: cannot locate routeTableId in returned XML:\n" << reply); - } - } - } - - std::string to_string() const - { - return '[' + network_interface_id + '/' + route_table_id + ']'; - } - - std::string network_interface_id; - std::string route_table_id; - }; - - // Set sourceDestCheck flag on AWS network interface. - static void set_source_dest_check(Context& ctx, - const std::string& network_interface_id, - const bool source_dest_check) - { - const std::string sdc = source_dest_check ? "true" : "false"; - - // first get the attribute and see if it is already set - // the way we want it - { - REST::Query q; - q.emplace_back("Action", "DescribeNetworkInterfaceAttribute"); - q.emplace_back("NetworkInterfaceId", network_interface_id); - q.emplace_back("Attribute", "sourceDestCheck"); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "DescribeNetworkInterfaceAttribute: " << t.format_status(*ctx.ts) << '\n' << reply); - - // parse XML reply - const Xml::Document doc(reply, "DescribeNetworkInterfaceAttribute"); - const std::string retval = Xml::find_text(&doc, - "DescribeNetworkInterfaceAttributeResponse", - "sourceDestCheck", - "value"); - // already set to desired value? - if (retval == sdc) - return; - } - - // create API query - { - REST::Query q; - q.emplace_back("Action", "ModifyNetworkInterfaceAttribute"); - q.emplace_back("NetworkInterfaceId", network_interface_id); - q.emplace_back("SourceDestCheck.Value", sdc); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "ModifyNetworkInterfaceAttribute: " << t.format_status(*ctx.ts) << '\n' << reply); - - // parse XML reply - const Xml::Document doc(reply, "ModifyNetworkInterfaceAttribute"); - const std::string retval = Xml::find_text(&doc, - "ModifyNetworkInterfaceAttributeResponse", - "return"); - if (retval != "true") - OPENVPN_THROW(aws_route_error, "ModifyNetworkInterfaceAttribute: returned failure status: " << '\n' << reply); - - OPENVPN_LOG("AWS EC2 ModifyNetworkInterfaceAttribute " << network_interface_id << " SourceDestCheck.Value=" << sdc); - } - } - - static void delete_route(Context& ctx, - const std::string& route_table_id, - const std::string& cidr, - bool ipv6) - { - { - REST::Query q; - q.emplace_back("Action", "DeleteRoute"); - q.emplace_back(ipv6 ? "DestinationIpv6CidrBlock" : "DestinationCidrBlock", cidr); - q.emplace_back("RouteTableId", route_table_id); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "DeleteRoute: " << t.format_status(*ctx.ts) << '\n' << reply); - - // parse XML reply - const Xml::Document doc(reply, "DeleteRoute"); - const std::string retval = Xml::find_text(&doc, - "DeleteRouteResponse", - "return"); - if (retval != "true") - OPENVPN_THROW(aws_route_error, "DeleteRoute: returned failure status: " << '\n' << reply); - - OPENVPN_LOG("AWS EC2 DeleteRoute " << cidr << " -> table " << route_table_id); - } - } - - // Create/replace a VPC route - static void replace_create_route(Context& ctx, - const std::string& route_table_id, - const std::string& route, - RouteTargetType target_type, - const std::string& target_value, - bool ipv6) - { - std::string target_type_str; - - switch (target_type) - { - case RouteTargetType::INSTANCE_ID: - target_type_str = "InstanceId"; - break; - - case RouteTargetType::INTERFACE_ID: - target_type_str = "NetworkInterfaceId"; - break; - - default: - OPENVPN_THROW(aws_route_error, - "replace_create_route: unknown RouteTargetType " << (int)target_type); - } - - const std::string dest_cidr_block_name = ipv6 ? - "DestinationCidrIpv6Block" : "DestinationCidrBlock"; - - // create API query - { - REST::Query q; - q.emplace_back("Action", "ReplaceRoute"); - q.emplace_back(dest_cidr_block_name, route); - q.emplace_back(target_type_str, target_value); - q.emplace_back("RouteTableId", route_table_id); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // Check the reply status. We only throw on communication failure, - // since ReplaceRoute will legitimately fail if the route doesn't - // exist yet. - if (!t.comm_status_success()) - OPENVPN_THROW(aws_route_error, "ReplaceRoute: " << t.format_status(*ctx.ts) << '\n' << reply); - - // ReplaceRoute succeeded? - if (t.request_status_success()) - { - // parse XML reply - const Xml::Document doc(reply, "ReplaceRoute"); - const std::string retval = Xml::find_text(&doc, - "ReplaceRouteResponse", - "return"); - if (retval == "true") - { - OPENVPN_LOG("AWS EC2 ReplaceRoute " << route << " -> table " << route_table_id); - return; - } - } - } - - // Now try CreateRoute - { - REST::Query q; - q.emplace_back("Action", "CreateRoute"); - q.emplace_back(dest_cidr_block_name, route); - q.emplace_back(target_type_str, target_value); - q.emplace_back("RouteTableId", route_table_id); - add_transaction(ctx, std::move(q)); - } - - // do transaction - execute_transaction(ctx); - - // process reply - { - // get the transaction - WS::ClientSet::Transaction& t = ctx.ts->first_transaction(); - - // get reply - const std::string reply = t.content_in_string(); - - // check the reply status - if (!t.http_status_success()) - OPENVPN_THROW(aws_route_error, "CreateRoute: " << t.format_status(*ctx.ts) << '\n' << reply); - - // parse XML reply - const Xml::Document doc(reply, "CreateRoute"); - const std::string retval = Xml::find_text(&doc, - "CreateRouteResponse", - "return"); - if (retval != "true") - OPENVPN_THROW(aws_route_error, "CreateRoute: returned failure status: " << '\n' << reply); - - OPENVPN_LOG("AWS EC2 CreateRoute " << route << " -> table " << route_table_id); - } - } - - private: - static void execute_transaction(Context& ctx) - { - WS::ClientSet::new_request_synchronous(ctx.ts, ctx.async_stop, ctx.http_context.rng(), true); - } - - static void add_transaction(const Context& ctx, REST::Query&& q) - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.uri = ec2_uri(ctx, std::move(q)); - t->req.method = "GET"; - t->ci.keepalive = true; - ctx.ts->transactions.clear(); - ctx.ts->transactions.push_back(std::move(t)); - } - - static std::string ec2_uri(const Context& ctx, REST::Query&& q) - { - REST::QueryBuilder qb; - qb.date = REST::amz_date(); - qb.expires = 300; - qb.region = ctx.instance_info.region; - qb.service = "ec2"; - qb.method = "GET"; - qb.host = ec2_host(ctx.instance_info); - qb.uri = "/"; - qb.parms = std::move(q); - qb.parms.emplace_back("Version", "2015-10-01"); - qb.add_amz_parms(ctx.creds); - qb.sort_parms(); - qb.add_amz_signature(ctx.http_context.digest_factory(), ctx.creds); - return qb.uri_query(); - } - - static std::string ec2_host(const PCQuery::Info& instance_info) - { - return "ec2." + instance_info.region + ".amazonaws.com"; - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/buffer/asiobuf.hpp b/Sources/OpenVPN3/openvpn/buffer/asiobuf.hpp deleted file mode 100644 index 8a64282..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/asiobuf.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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-2020 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_BUFFER_ASIOBUF_H -#define OPENVPN_BUFFER_ASIOBUF_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - class AsioConstBufferSeq2 - { - public: - AsioConstBufferSeq2(const Buffer& b1, const Buffer& b2) - : buf{openvpn_io::const_buffer{b1.c_data(), b1.size()}, - openvpn_io::const_buffer{b2.c_data(), b2.size()}} - { - } - - // Implement the ConstBufferSequence requirements. - typedef openvpn_io::const_buffer value_type; - typedef const openvpn_io::const_buffer* const_iterator; - const openvpn_io::const_buffer* begin() const { return buf; } - const openvpn_io::const_buffer* end() const { return buf + 2; } - - const size_t size() const - { - return openvpn_io::buffer_size(buf[0]) - + openvpn_io::buffer_size(buf[1]); - } - - private: - const openvpn_io::const_buffer buf[2]; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufclamp.hpp b/Sources/OpenVPN3/openvpn/buffer/bufclamp.hpp deleted file mode 100644 index 573be4d..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufclamp.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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/>. - -// For debugging, reduce effective buffer size for I/O. -// Enable by defining OPENVPN_BUF_CLAMP_READ and/or OPENVPN_BUF_CLAMP_WRITE - -#ifndef OPENVPN_BUFFER_BUFCLAMP_H -#define OPENVPN_BUFFER_BUFCLAMP_H - -#include <algorithm> - -#include <openvpn/common/size.hpp> - -namespace openvpn { - inline size_t buf_clamp_read(const size_t size) - { -#ifdef OPENVPN_BUF_CLAMP_READ - return std::min(size, size_t(OPENVPN_BUF_CLAMP_READ)); -#else - return size; -#endif - } - - inline size_t buf_clamp_write(const size_t size) - { -#ifdef OPENVPN_BUF_CLAMP_WRITE - return std::min(size, size_t(OPENVPN_BUF_CLAMP_WRITE)); -#else - return size; -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufcomplete.hpp b/Sources/OpenVPN3/openvpn/buffer/bufcomplete.hpp deleted file mode 100644 index 6418ad1..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufcomplete.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// 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-2020 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_BUFFER_BUFCOMPLETE_H -#define OPENVPN_BUFFER_BUFCOMPLETE_H - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t -#include <algorithm> // for std::min - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - class BufferComplete - { - public: - /* each advance/get method returns false if message is incomplete */ - - bool advance(size_t size) - { - while (size) - { - if (!fetch_buffer()) - return false; - const size_t s = std::min(size, buf.size()); - buf.advance(s); - size -= s; - } - return true; - } - - // assumes embedded big-endian uint16_t length in the stream - bool advance_string() - { - std::uint8_t h, l; - if (!get(h)) - return false; - if (!get(l)) - return false; - return advance(size_t(h) << 8 | size_t(l)); - } - - bool advance_to_null() - { - std::uint8_t c; - while (get(c)) - { - if (!c) - return true; - } - return false; - } - - bool get(std::uint8_t& c) - { - if (!fetch_buffer()) - return false; - c = buf.pop_front(); - return true; - } - - bool defined() const - { - return buf.defined(); - } - - protected: - void reset_buf(const Buffer& buf_arg) - { - buf = buf_arg; - } - - void reset_buf() - { - buf.reset_content(); - } - - private: - virtual void next_buffer() = 0; - - bool fetch_buffer() - { - if (buf.defined()) - return true; - next_buffer(); - return buf.defined(); - } - - Buffer buf; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufcomposed.hpp b/Sources/OpenVPN3/openvpn/buffer/bufcomposed.hpp deleted file mode 100644 index 3eb0812..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufcomposed.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// 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-2020 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_BUFFER_BUFCOMPOSED_H -#define OPENVPN_BUFFER_BUFCOMPOSED_H - -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/bufcomplete.hpp> -#include <openvpn/buffer/buflist.hpp> - -namespace openvpn { - class BufferComposed - { - public: - class Complete : public BufferComplete - { - public: - BufferPtr get() - { -#if 0 // don't include for production - if (iter_defined()) - throw Exception("BufferComposed::Complete: residual data"); -#endif - BufferPtr ret = bc.bv.join(); - bc.bv.clear(); - return ret; - } - - private: - friend class BufferComposed; - - Complete(BufferComposed& bc_arg) - : bc(bc_arg), - iter(bc.bv.cbegin()) - { - next_buffer(); - } - - bool iter_defined() - { - return iter != bc.bv.end(); - } - - virtual void next_buffer() override - { - if (iter_defined()) - reset_buf(**iter++); - else - reset_buf(); - } - - BufferComposed& bc; - BufferVector::const_iterator iter; - }; - - size_t size() const - { - return bv.join_size(); - } - - void put(BufferPtr bp) - { - bv.push_back(std::move(bp)); - } - - Complete complete() - { - return Complete(*this); - } - - private: - BufferVector bv; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/buffer.hpp b/Sources/OpenVPN3/openvpn/buffer/buffer.hpp deleted file mode 100644 index 6a5892c..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/buffer.hpp +++ /dev/null @@ -1,937 +0,0 @@ -// 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-2020 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/>. - -// These templates define the fundamental data buffer classes used by the -// OpenVPN core. Normally OpenVPN uses buffers of unsigned chars, but the -// templatization of the classes would allow buffers of other types to -// be defined. -// -// Fundamentally a buffer is an object with 4 fields: -// -// 1. a pointer to underlying data array -// 2. the capacity of the underlying data array -// 3. an offset into the data array -// 4. the size of the referenced data within the array -// -// The BufferType template is the lowest-level buffer class template. It refers -// to a buffer but without any notion of ownership of the underlying data. -// -// The BufferAllocatedType template is a higher-level template that inherits -// from BufferType but which asserts ownership over the resources of the buffer -- -// for example, it will free the underlying buffer in its destructor. -// -// Since most of the time, we want our buffers to be made out of unsigned chars, -// some typedefs at the end of the file define common instantations for the -// BufferType and BufferAllocatedType templates. -// -// Buffer : a simple buffer of unsigned char without ownership semantics -// ConstBuffer : like buffer but where the data pointed to by the buffer is const -// BufferAllocated : an allocated Buffer with ownership semantics -// BufferPtr : a smart, reference-counted pointer to a BufferAllocated - -#ifndef OPENVPN_BUFFER_BUFFER_H -#define OPENVPN_BUFFER_BUFFER_H - -#include <string> -#include <cstring> -#include <algorithm> -#include <type_traits> // for std::is_nothrow_move_constructible, std::remove_const - -#ifndef OPENVPN_NO_IO -#include <openvpn/io/io.hpp> -#endif - -#include <openvpn/common/size.hpp> -#include <openvpn/common/abort.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/bufclamp.hpp> - -#ifdef OPENVPN_BUFFER_ABORT -#define OPENVPN_BUFFER_THROW(exc) { std::abort(); } -#else -#define OPENVPN_BUFFER_THROW(exc) { throw BufferException(BufferException::exc); } -#endif - -namespace openvpn { - - // special-purpose exception class for Buffer classes - class BufferException : public std::exception - { - public: - enum Status { - buffer_full, - buffer_headroom, - buffer_underflow, - buffer_overflow, - buffer_offset, - buffer_index, - buffer_const_index, - buffer_push_front_headroom, - buffer_no_reset_impl, - buffer_pop_back, - buffer_set_size, - buffer_range, - }; - - BufferException(Status status) - : status_(status) - { - } - - BufferException(Status status, const std::string& msg) - : status_(status), - msg_(std::string(status_string(status)) + " : " + msg) - { - } - - virtual const char* what() const throw() - { - if (!msg_.empty()) - return msg_.c_str(); - else - return status_string(status_); - } - - Status status() const { return status_; } - virtual ~BufferException() throw() {} - - private: - static const char *status_string(const Status status) - { - switch (status) - { - case buffer_full: - return "buffer_full"; - case buffer_headroom: - return "buffer_headroom"; - case buffer_underflow: - return "buffer_underflow"; - case buffer_overflow: - return "buffer_overflow"; - case buffer_offset: - return "buffer_offset"; - case buffer_index: - return "buffer_index"; - case buffer_const_index: - return "buffer_const_index"; - case buffer_push_front_headroom: - return "buffer_push_front_headroom"; - case buffer_no_reset_impl: - return "buffer_no_reset_impl"; - case buffer_pop_back: - return "buffer_pop_back"; - case buffer_set_size: - return "buffer_set_size"; - case buffer_range: - return "buffer_range"; - default: - return "buffer_???"; - } - } - - Status status_; - std::string msg_; - }; - - template <typename T, typename R> - class BufferAllocatedType; - - template <typename T> - class BufferType { - template <typename, typename> friend class BufferAllocatedType; - - public: - typedef T value_type; - typedef T* type; - typedef const T* const_type; - typedef typename std::remove_const<T>::type NCT; // non-const type - - BufferType() - { - static_assert(std::is_nothrow_move_constructible<BufferType>::value, "class BufferType not noexcept move constructable"); - data_ = nullptr; - offset_ = size_ = capacity_ = 0; - } - - BufferType(void* data, const size_t size, const bool filled) - : BufferType((T*)data, size, filled) - { - } - - BufferType(T* data, const size_t size, const bool filled) - { - data_ = data; - offset_ = 0; - capacity_ = size; - size_ = filled ? size : 0; - } - - void reserve(const size_t n) - { - if (n > capacity_) - resize(n); - } - - void init_headroom(const size_t headroom) - { - if (headroom > capacity_) - OPENVPN_BUFFER_THROW(buffer_headroom); - offset_ = headroom; - size_ = 0; - } - - void reset_offset(const size_t offset) - { - const size_t size = size_ + offset_ - offset; - if (offset > capacity_ || size > capacity_ || offset + size > capacity_) - OPENVPN_BUFFER_THROW(buffer_offset); - offset_ = offset; - size_ = size; - } - - void reset_size() - { - size_ = 0; - } - - void reset_content() - { - offset_ = size_ = 0; - } - - // std::string compatible methods - const T* c_str() const { return c_data(); } - size_t length() const { return size(); } - - // return a const pointer to start of array - const T* c_data() const { return data_ + offset_; } - - // return a mutable pointer to start of array - T* data() { return data_ + offset_; } - - // return a const pointer to end of array - const T* c_data_end() const { return data_ + offset_ + size_; } - - // return a mutable pointer to end of array - T* data_end() { return data_ + offset_ + size_; } - - // return a const pointer to start of raw data - const T* c_data_raw() const { return data_; } - - // return a mutable pointer to start of raw data - T* data_raw() { return data_; } - - // return size of array in T objects - size_t size() const { return size_; } - - // return raw size of allocated buffer in T objects - size_t capacity() const { return capacity_; } - - // return current offset (headroom) into buffer - size_t offset() const { return offset_; } - - // return true if array is not empty - bool defined() const { return size_ > 0; } - - // return true if data memory is defined - bool allocated() const { return data_ != nullptr; } - - // return true if array is empty - bool empty() const { return !size_; } - - // return the number of additional T objects that can be added before capacity is reached (without considering resize) - size_t remaining(const size_t tailroom = 0) const { - const size_t r = capacity_ - (offset_ + size_ + tailroom); - return r <= capacity_ ? r : 0; - } - - // return the maximum allowable size value in T objects given the current offset (without considering resize) - size_t max_size() const { - const size_t r = capacity_ - offset_; - return r <= capacity_ ? r : 0; - } - - // like max_size, but take tailroom into account - size_t max_size_tailroom(const size_t tailroom) const { - const size_t r = capacity_ - (offset_ + tailroom); - return r <= capacity_ ? r : 0; - } - - // After an external method, operating on the array as - // a mutable unsigned char buffer, has written data to the - // array, use this method to set the array length in terms - // of T objects. - void set_size(const size_t size) - { - if (size > max_size()) - OPENVPN_BUFFER_THROW(buffer_set_size); - size_ = size; - } - - // Increment size (usually used in a similar context - // to set_size such as after mutable_buffer_append). - void inc_size(const size_t delta) - { - set_size(size_ + delta); - } - - // append a T object to array, with possible resize - void push_back(const T& value) - { - if (!remaining()) - resize(offset_ + size_ + 1); - *(data()+size_++) = value; - } - - // append a T object to array, with possible resize - void push_front(const T& value) - { - if (!offset_) - OPENVPN_BUFFER_THROW(buffer_push_front_headroom); - --offset_; - ++size_; - *data() = value; - } - - T pop_back() - { - if (!size_) - OPENVPN_BUFFER_THROW(buffer_pop_back); - return *(data()+(--size_)); - } - - T pop_front() - { - T ret = (*this)[0]; - ++offset_; - --size_; - return ret; - } - - T front() const - { - return (*this)[0]; - } - - T back() const - { - return (*this)[size_-1]; - } - - // Place a T object after the last object in the - // array, with possible resize to contain it, - // however don't actually change the size of the - // array to reflect the added object. Useful - // for maintaining null-terminated strings. - void set_trailer(const T& value) - { - if (!remaining()) - resize(offset_ + size_ + 1); - *(data()+size_) = value; - } - - void null_terminate() - { - if (empty() || back()) - push_back(0); - } - - void advance(const size_t delta) - { - if (delta > size_) - OPENVPN_BUFFER_THROW(buffer_overflow); - offset_ += delta; - size_ -= delta; - } - - bool contains_null() const - { - const T* end = c_data_end(); - for (const T* p = c_data(); p < end; ++p) - { - if (!*p) - return true; - } - return false; - } - - bool is_zeroed() const - { - const T* end = c_data_end(); - for (const T* p = c_data(); p < end; ++p) - { - if (*p) - return false; - } - return true; - } - - // mutable index into array - T& operator[](const size_t index) - { - if (index >= size_) - OPENVPN_BUFFER_THROW(buffer_index); - return data()[index]; - } - - // const index into array - const T& operator[](const size_t index) const - { - if (index >= size_) - OPENVPN_BUFFER_THROW(buffer_const_index); - return c_data()[index]; - } - - // mutable index into array - T* index(const size_t index) - { - if (index >= size_) - OPENVPN_BUFFER_THROW(buffer_index); - return &data()[index]; - } - - // const index into array - const T* c_index(const size_t index) const - { - if (index >= size_) - OPENVPN_BUFFER_THROW(buffer_const_index); - return &c_data()[index]; - } - - bool operator==(const BufferType& other) const - { - if (size_ != other.size_) - return false; - return std::memcmp(c_data(), other.c_data(), size_) == 0; - } - - bool operator!=(const BufferType& other) const - { - return !(*this == other); - } - -#ifndef OPENVPN_NO_IO - // return a openvpn_io::mutable_buffer object used by - // asio read methods, starting from data() - openvpn_io::mutable_buffer mutable_buffer(const size_t tailroom = 0) - { - return openvpn_io::mutable_buffer(data(), max_size_tailroom(tailroom)); - } - - // return a openvpn_io::mutable_buffer object used by - // asio read methods, starting from data_end() - openvpn_io::mutable_buffer mutable_buffer_append(const size_t tailroom = 0) - { - return openvpn_io::mutable_buffer(data_end(), remaining(tailroom)); - } - - // return a openvpn_io::const_buffer object used by - // asio write methods. - openvpn_io::const_buffer const_buffer() const - { - return openvpn_io::const_buffer(c_data(), size()); - } - - // clamped versions of mutable_buffer(), mutable_buffer_append(), - // and const_buffer() - - openvpn_io::mutable_buffer mutable_buffer_clamp(const size_t tailroom = 0) - { - return openvpn_io::mutable_buffer(data(), buf_clamp_read(max_size_tailroom(tailroom))); - } - - openvpn_io::mutable_buffer mutable_buffer_append_clamp(const size_t tailroom = 0) - { - return openvpn_io::mutable_buffer(data_end(), buf_clamp_read(remaining(tailroom))); - } - - openvpn_io::const_buffer const_buffer_clamp() const - { - return openvpn_io::const_buffer(c_data(), buf_clamp_write(size())); - } - - openvpn_io::const_buffer const_buffer_limit(const size_t limit) const - { - return openvpn_io::const_buffer(c_data(), std::min(buf_clamp_write(size()), limit)); - } -#endif - - void realign(size_t headroom) - { - if (headroom != offset_) - { - if (headroom + size_ > capacity_) - OPENVPN_BUFFER_THROW(buffer_headroom); - std::memmove(data_ + headroom, data_ + offset_, size_); - offset_ = headroom; - } - } - - void write(const T* data, const size_t size) - { - std::memcpy(write_alloc(size), data, size * sizeof(T)); - } - - void write(const void* data, const size_t size) - { - write((const T*)data, size); - } - - void prepend(const T* data, const size_t size) - { - std::memcpy(prepend_alloc(size), data, size * sizeof(T)); - } - - void prepend(const void* data, const size_t size) - { - prepend((const T*)data, size); - } - - void read(NCT* data, const size_t size) - { - std::memcpy(data, read_alloc(size), size * sizeof(T)); - } - - void read(void* data, const size_t size) - { - read((NCT*)data, size); - } - - T* write_alloc(const size_t size) - { - if (size > remaining()) - resize(offset_ + size_ + size); - T* ret = data() + size_; - size_ += size; - return ret; - } - - T* prepend_alloc(const size_t size) - { - if (size <= offset_) - { - offset_ -= size; - size_ += size; - return data(); - } - else - OPENVPN_BUFFER_THROW(buffer_headroom); - } - - T* read_alloc(const size_t size) - { - if (size <= size_) - { - T* ret = data(); - offset_ += size; - size_ -= size; - return ret; - } - else - OPENVPN_BUFFER_THROW(buffer_underflow); - } - - BufferType read_alloc_buf(const size_t size) - { - if (size <= size_) - { - BufferType ret(data_, offset_, size, capacity_); - offset_ += size; - size_ -= size; - return ret; - } - else - OPENVPN_BUFFER_THROW(buffer_underflow); - } - - void reset(const size_t min_capacity, const unsigned int flags) - { - if (min_capacity > capacity_) - reset_impl(min_capacity, flags); - } - - void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) - { - reset(min_capacity, flags); - init_headroom(headroom); - } - - template <typename B> - void append(const B& other) - { - write(other.c_data(), other.size()); - } - - BufferType range(size_t offset, size_t len) const - { - if (offset + len > size()) - { - if (offset < size()) - len = size() - offset; - else - len = 0; - } - return BufferType(datac(), offset, len, len); - } - - protected: - BufferType(T* data, const size_t offset, const size_t size, const size_t capacity) - : data_(data), offset_(offset), size_(size), capacity_(capacity) - { - } - - // return a mutable pointer to start of array but - // remain const with respect to *this. - T* datac() const { return data_ + offset_; } - - // Called when reset method needs to expand the buffer size - virtual void reset_impl(const size_t min_capacity, const unsigned int flags) - { - OPENVPN_BUFFER_THROW(buffer_no_reset_impl); - } - - // Derived classes can implement buffer growing semantics - // by overloading this method. In the default implementation, - // buffers are non-growable, so we throw an exception. - virtual void resize(const size_t new_capacity) - { - if (new_capacity > capacity_) - buffer_full_error(new_capacity, false); - } - - void buffer_full_error(const size_t newcap, const bool allocated) const - { -#ifdef OPENVPN_BUFFER_ABORT - std::abort(); -#else - throw BufferException(BufferException::buffer_full, "allocated=" + std::to_string(allocated) + " size=" + std::to_string(size_) + " offset=" + std::to_string(offset_) + " capacity=" + std::to_string(capacity_) + " newcap=" + std::to_string(newcap)); -#endif - } - - T* data_; // pointer to data - size_t offset_; // offset from data_ of beginning of T array (to allow for headroom) - size_t size_; // number of T objects in array starting at data_ + offset_ - size_t capacity_; // maximum number of array objects of type T for which memory is allocated, starting at data_ - }; - - template <typename T, typename R> - class BufferAllocatedType : public BufferType<T>, public RC<R> - { - using BufferType<T>::data_; - using BufferType<T>::offset_; - using BufferType<T>::size_; - using BufferType<T>::capacity_; - using BufferType<T>::buffer_full_error; - - template <typename, typename> friend class BufferAllocatedType; - - public: - enum { - CONSTRUCT_ZERO = (1<<0), // if enabled, constructors/init will zero allocated space - DESTRUCT_ZERO = (1<<1), // if enabled, destructor will zero data before deletion - GROW = (1<<2), // if enabled, buffer will grow (otherwise buffer_full exception will be thrown) - ARRAY = (1<<3), // if enabled, use as array - }; - - BufferAllocatedType() - { - static_assert(std::is_nothrow_move_constructible<BufferAllocatedType>::value, "class BufferAllocatedType not noexcept move constructable"); - flags_ = 0; - } - - BufferAllocatedType(const size_t capacity, const unsigned int flags) - { - flags_ = flags; - capacity_ = capacity; - if (capacity) - { - data_ = new T[capacity]; - if (flags & CONSTRUCT_ZERO) - std::memset(data_, 0, capacity * sizeof(T)); - if (flags & ARRAY) - size_ = capacity; - } - } - - BufferAllocatedType(const T* data, const size_t size, const unsigned int flags) - { - flags_ = flags; - size_ = capacity_ = size; - if (size) - { - data_ = new T[size]; - std::memcpy(data_, data, size * sizeof(T)); - } - } - - BufferAllocatedType(const BufferAllocatedType& other) - { - offset_ = other.offset_; - size_ = other.size_; - capacity_ = other.capacity_; - flags_ = other.flags_; - if (capacity_) - { - data_ = new T[capacity_]; - if (size_) - std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); - } - } - - template <typename T_> - BufferAllocatedType(const BufferType<T_>& other, const unsigned int flags) - { - static_assert(sizeof(T) == sizeof(T_), "size inconsistency"); - offset_ = other.offset_; - size_ = other.size_; - capacity_ = other.capacity_; - flags_ = flags; - if (capacity_) - { - data_ = new T[capacity_]; - if (size_) - std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); - } - } - - void operator=(const BufferAllocatedType& other) - { - if (this != &other) - { - offset_ = size_ = 0; - if (capacity_ != other.capacity_) - { - erase_(); - if (other.capacity_) - data_ = new T[other.capacity_]; - capacity_ = other.capacity_; - } - offset_ = other.offset_; - size_ = other.size_; - flags_ = other.flags_; - if (size_) - std::memcpy(data_ + offset_, other.data_ + offset_, size_ * sizeof(T)); - } - } - - void init(const size_t capacity, const unsigned int flags) - { - offset_ = size_ = 0; - flags_ = flags; - if (capacity_ != capacity) - { - erase_(); - if (capacity) - { - data_ = new T[capacity]; - } - capacity_ = capacity; - } - if ((flags & CONSTRUCT_ZERO) && capacity) - std::memset(data_, 0, capacity * sizeof(T)); - if (flags & ARRAY) - size_ = capacity; - } - - void init(const T* data, const size_t size, const unsigned int flags) - { - offset_ = size_ = 0; - flags_ = flags; - if (size != capacity_) - { - erase_(); - if (size) - data_ = new T[size]; - capacity_ = size; - } - size_ = size; - std::memcpy(data_, data, size * sizeof(T)); - } - - void realloc(const size_t newcap) - { - if (newcap > capacity_) - realloc_(newcap); - } - - void reset(const size_t min_capacity, const unsigned int flags) - { - if (min_capacity > capacity_) - init (min_capacity, flags); - } - - void reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) - { - reset(min_capacity, flags); - BufferType<T>::init_headroom(headroom); - } - - template <typename T_, typename R_> - void move(BufferAllocatedType<T_, R_>& other) - { - if (data_) - delete_(data_, capacity_, flags_); - move_(other); - } - - RCPtr<BufferAllocatedType<T, R>> move_to_ptr() - { - RCPtr<BufferAllocatedType<T, R>> bp = new BufferAllocatedType<T, R>(); - bp->move(*this); - return bp; - } - - void swap(BufferAllocatedType& other) - { - std::swap(data_, other.data_); - std::swap(offset_, other.offset_); - std::swap(size_, other.size_); - std::swap(capacity_, other.capacity_); - std::swap(flags_, other.flags_); - } - - template <typename T_, typename R_> - BufferAllocatedType(BufferAllocatedType<T_, R_>&& other) noexcept - { - move_(other); - } - - BufferAllocatedType& operator=(BufferAllocatedType&& other) noexcept - { - move(other); - return *this; - } - - void clear() - { - erase_(); - flags_ = 0; - size_ = offset_ = 0; - } - - void or_flags(const unsigned int flags) - { - flags_ |= flags; - } - - void and_flags(const unsigned int flags) - { - flags_ &= flags; - } - - ~BufferAllocatedType() - { - if (data_) - delete_(data_, capacity_, flags_); - } - - protected: - // Called when reset method needs to expand the buffer size - virtual void reset_impl(const size_t min_capacity, const unsigned int flags) - { - init(min_capacity, flags); - } - - // Set current capacity to at least new_capacity. - virtual void resize(const size_t new_capacity) - { - const size_t newcap = std::max(new_capacity, capacity_ * 2); - if (newcap > capacity_) - { - if (flags_ & GROW) - realloc_(newcap); - else - buffer_full_error(newcap, true); - } - } - - void realloc_(const size_t newcap) - { - T* data = new T[newcap]; - if (size_) - std::memcpy(data + offset_, data_ + offset_, size_ * sizeof(T)); - delete_(data_, capacity_, flags_); - data_ = data; - //std::cout << "*** RESIZE " << capacity_ << " -> " << newcap << std::endl; // fixme - capacity_ = newcap; - } - - template <typename T_, typename R_> - void move_(BufferAllocatedType<T_, R_>& other) - { - data_ = other.data_; - offset_ = other.offset_; - size_ = other.size_; - capacity_ = other.capacity_; - flags_ = other.flags_; - - other.data_ = nullptr; - other.offset_ = other.size_ = other.capacity_ = 0; - } - - void erase_() - { - if (data_) - { - delete_(data_, capacity_, flags_); - data_ = nullptr; - } - capacity_ = 0; - } - - static void delete_(T* data, const size_t size, const unsigned int flags) - { - if (size && (flags & DESTRUCT_ZERO)) - std::memset(data, 0, size * sizeof(T)); - delete [] data; - } - - unsigned int flags_; - }; - - // specializations of BufferType for unsigned char - typedef BufferType<unsigned char> Buffer; - typedef BufferType<const unsigned char> ConstBuffer; - typedef BufferAllocatedType<unsigned char, thread_unsafe_refcount> BufferAllocated; - typedef RCPtr<BufferAllocated> BufferPtr; - - // BufferAllocated with thread-safe refcount - typedef BufferAllocatedType<unsigned char, thread_safe_refcount> BufferAllocatedTS; - typedef RCPtr<BufferAllocatedTS> BufferPtrTS; - - // cast BufferType<T> to BufferType<const T> - - template <typename T> - inline BufferType<const T>& const_buffer_ref(BufferType<T>& src) - { - return (BufferType<const T>&)src; - } - - template <typename T> - inline const BufferType<const T>& const_buffer_ref(const BufferType<T>& src) - { - return (const BufferType<const T>&)src; - } - -} // namespace openvpn - -#endif // OPENVPN_BUFFER_BUFFER_H diff --git a/Sources/OpenVPN3/openvpn/buffer/bufhex.hpp b/Sources/OpenVPN3/openvpn/buffer/bufhex.hpp deleted file mode 100644 index 17f0cb3..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufhex.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// 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-2020 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_BUFFER_BUFHEX_H -#define OPENVPN_BUFFER_BUFHEX_H - -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - namespace BufHex { - - OPENVPN_EXCEPTION(buf_hex); - - template <typename T> - inline std::string render(const T obj) - { - const ConstBuffer buf((const unsigned char *)&obj, sizeof(obj), true); - return render_hex_generic(buf); - } - - template <typename T> - inline T parse(const std::string& hex, const std::string& title) - { - T obj; - Buffer buf((unsigned char *)&obj, sizeof(obj), false); - try { - parse_hex(buf, hex); - } - catch (const BufferException& e) - { - OPENVPN_THROW(buf_hex, title << ": buffer issue: " << e.what()); - } - if (buf.size() != sizeof(obj)) - OPENVPN_THROW(buf_hex, title << ": unexpected size"); - return obj; - } - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/buflimit.hpp b/Sources/OpenVPN3/openvpn/buffer/buflimit.hpp deleted file mode 100644 index 75130c0..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/buflimit.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// 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-2020 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_BUFFER_BUFLIMIT_H -#define OPENVPN_BUFFER_BUFLIMIT_H - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - template <typename T> - class BufferLimit - { - public: - BufferLimit() - { - set_max(0, 0); - reset(); - } - - BufferLimit(const T max_lines_arg, - const T max_bytes_arg) - { - set_max(max_lines_arg, max_bytes_arg); - reset(); - } - - void set_max(const T max_lines_arg, - const T max_bytes_arg) - { - max_lines = max_lines_arg; - max_bytes = max_bytes_arg; - } - - void reset() - { - n_bytes = n_lines = 0; - } - - void add(const Buffer& buf) - { - T size = (T)buf.size(); - n_bytes += size; - if (max_bytes && n_bytes > max_bytes) - bytes_exceeded(); - if (max_lines) - { - const unsigned char *p = buf.c_data(); - while (size--) - { - const unsigned char c = *p++; - if (c == '\n') - { - ++n_lines; - if (n_lines > max_lines) - lines_exceeded(); - } - } - } - } - - virtual void bytes_exceeded() = 0; - virtual void lines_exceeded() = 0; - - protected: - T max_lines; - T max_bytes; - T n_bytes; - T n_lines; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/buflineiter.hpp b/Sources/OpenVPN3/openvpn/buffer/buflineiter.hpp deleted file mode 100644 index cf15dd9..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/buflineiter.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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> - -namespace openvpn { - - // Iterate over the lines in a buffer by returning - // a sub-buffer for each line. Zero-copy. - class BufferLineIterator - { - public: - BufferLineIterator(const ConstBuffer& buf) - : src(buf) - { - } - - // Returns a zero-length buffer at end of iteration - ConstBuffer next() - { - return src.read_alloc_buf(line_len()); - } - - private: - size_t line_len() const - { - const unsigned char *const data = src.c_data(); - size_t i = 0; - while (i < src.size()) - if (data[i++] == '\n') - break; - return i; - } - - ConstBuffer src; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/buffer/buflist.hpp b/Sources/OpenVPN3/openvpn/buffer/buflist.hpp deleted file mode 100644 index 68a9190..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/buflist.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// 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-2020 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_BUFFER_BUFLIST_H -#define OPENVPN_BUFFER_BUFLIST_H - -#include <list> -#include <utility> - -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/bufstr.hpp> - -namespace openvpn { - - template <template <typename...> class COLLECTION> - struct BufferCollection : public COLLECTION<BufferPtr> - { - using COLLECTION<BufferPtr>::size; - using COLLECTION<BufferPtr>::front; - using COLLECTION<BufferPtr>::empty; - using COLLECTION<BufferPtr>::back; - using COLLECTION<BufferPtr>::emplace_back; - - BufferPtr join(const size_t headroom, - const size_t tailroom, - const bool size_1_optim) const - { - // special optimization if list contains - // a single element that satisfies our - // headroom/tailroom constraints. - if (size_1_optim - && size() == 1 - && front()->offset() >= headroom - && front()->remaining() >= tailroom) - return front(); - - // first pass -- measure total size - const size_t size = join_size(); - - // allocate buffer - BufferPtr big = new BufferAllocated(size + headroom + tailroom, 0); - big->init_headroom(headroom); - - // second pass -- copy data - for (auto &b : *this) - big->write(b->c_data(), b->size()); - - return big; - } - - BufferPtr join() const - { - return join(0, 0, true); - } - - size_t join_size() const - { - size_t size = 0; - for (auto &b : *this) - size += b->size(); - return size; - } - - std::string to_string() const - { - BufferPtr bp = join(); - return buf_to_string(*bp); - } - - BufferCollection copy() const - { - BufferCollection ret; - for (auto &b : *this) - ret.emplace_back(new BufferAllocated(*b)); - return ret; - } - - void put_consume(BufferAllocated& buf, const size_t tailroom = 0) - { - const size_t s = buf.size(); - if (!s) - return; - if (!empty()) - { - // special optimization if buf data fits in - // back() unused tail capacity -- if so, append - // buf to existing back(). - BufferPtr& b = back(); - const size_t r = b->remaining(tailroom); - if (s < r) - { - b->write(buf.read_alloc(s), s); - return; - } - } - emplace_back(new BufferAllocated(std::move(buf))); - } - }; - - typedef BufferCollection<std::list> BufferList; - typedef BufferCollection<std::vector> BufferVector; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufread.hpp b/Sources/OpenVPN3/openvpn/buffer/bufread.hpp deleted file mode 100644 index d7121c2..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufread.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// 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-2020 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_BUFFER_BUFREAD_H -#define OPENVPN_BUFFER_BUFREAD_H - -#include <unistd.h> -#include <errno.h> - -#include <string> -#include <cstring> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/buffer/buflist.hpp> - -namespace openvpn { - OPENVPN_EXCEPTION(buf_read_error); - - inline bool buf_read(const int fd, Buffer& buf, const std::string& title) - { - const ssize_t status = ::read(fd, buf.data_end(), buf.remaining(0)); - if (status < 0) - { - const int eno = errno; - OPENVPN_THROW(buf_read_error, "on " << title << " : " << strerror_str(eno)); - } - else if (!status) - return false; - buf.inc_size(status); - return true; - } - - inline BufferList buf_read(const int fd, const std::string& title) - { - BufferList buflist; - while (true) - { - BufferAllocated buf(1024, 0); - if (!buf_read(fd, buf, title)) - break; - buflist.put_consume(buf); - } - return buflist; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufstatic.hpp b/Sources/OpenVPN3/openvpn/buffer/bufstatic.hpp deleted file mode 100644 index 1703fdc..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufstatic.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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> - -namespace openvpn { - - // constant-length Buffer for writing that cannot be extended - template <std::size_t N> - class StaticBuffer : public Buffer - { - public: - StaticBuffer() - : Buffer(data, N, false) - { - } - - StaticBuffer(const StaticBuffer&) = delete; - StaticBuffer& operator=(const StaticBuffer&) = delete; - - private: - unsigned char data[N]; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/buffer/bufstr.hpp b/Sources/OpenVPN3/openvpn/buffer/bufstr.hpp deleted file mode 100644 index eda86c6..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufstr.hpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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-2020 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/>. - -// String methods on Buffer objects - -#ifndef OPENVPN_BUFFER_BUFSTR_H -#define OPENVPN_BUFFER_BUFSTR_H - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - // return contents of Buffer as a std::string - inline std::string buf_to_string(const Buffer& buf) - { - return std::string((const char *)buf.c_data(), buf.size()); - } - - // return contents of ConstBuffer as a std::string - inline std::string buf_to_string(const ConstBuffer& buf) - { - return std::string((const char *)buf.c_data(), buf.size()); - } - - // write std::string to Buffer - inline void buf_write_string(Buffer& buf, const std::string& str) - { - buf.write((unsigned char *)str.c_str(), str.length()); - } - - // write C string to buffer - inline void buf_write_string(Buffer& buf, const char *str) - { - buf.write((unsigned char *)str, std::strlen(str)); - } - - // return BufferPtr from std::string - inline BufferPtr buf_from_string(const std::string& str) - { - const size_t len = str.length(); - BufferPtr buf(new BufferAllocated(len, 0)); - buf->write((unsigned char *)str.c_str(), len); - return buf; - } - - // return BufferPtr from C string - inline BufferPtr buf_from_string(const char *str) - { - const size_t len = std::strlen(str); - BufferPtr buf(new BufferAllocated(len, 0)); - buf->write((unsigned char *)str, len); - return buf; - } - - // return BufferAllocated from std::string - inline BufferAllocated buf_alloc_from_string(const std::string& str) - { - const size_t len = str.length(); - BufferAllocated buf(len, 0); - buf.write((unsigned char *)str.c_str(), len); - return buf; - } - - // return BufferAllocated from C string - inline BufferAllocated buf_alloc_from_string(const char *str) - { - const size_t len = std::strlen(str); - BufferAllocated buf(len, 0); - buf.write((unsigned char *)str, len); - return buf; - } - - // append str to buf - inline void buf_append_string(Buffer& buf, const std::string& str) - { - buf.write((unsigned char *)str.c_str(), str.length()); - } - - // append str to buf - inline void buf_append_string(Buffer& buf, const char *str) - { - buf.write((unsigned char *)str, std::strlen(str)); - } - - // Note: ConstBuffer deep links to str, so returned ConstBuffer - // is only defined while str is in scope. - inline ConstBuffer const_buf_from_string(const std::string& str) - { - return ConstBuffer((const unsigned char *)str.c_str(), str.size(), true); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/bufstream.hpp b/Sources/OpenVPN3/openvpn/buffer/bufstream.hpp deleted file mode 100644 index c99c934..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/bufstream.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// 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-2020 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_BUFFER_BUFSTREAM_H -#define OPENVPN_BUFFER_BUFSTREAM_H - -#include <streambuf> - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - class BufferStream : public std::streambuf - { - public: - BufferStream(Buffer& buffer) : buf(buffer) {} - - protected: -#if 0 // not implemented yet - // input - virtual std::streamsize showmanyc(); - virtual std::streamsize xsgetn(char* s, std::streamsize n); - virtual int underflow(); - virtual int uflow(); - virtual int pbackfail(int c = EOF); -#endif - - // output - virtual std::streamsize xsputn(const char* s, std::streamsize n) - { - buf.write((unsigned char *)s, (size_t)n); - return n; - } - - virtual int overflow(int c = EOF) - { - if (c != EOF) - { - unsigned char uc = (unsigned char)c; - buf.push_back(uc); - } - return c; - } - - private: - Buffer& buf; - }; - - class BufferStreamOut : public std::ostream - { - public: - BufferStreamOut(Buffer& buffer) - : std::ostream(new BufferStream(buffer)) - { - } - - ~BufferStreamOut() - { - delete rdbuf(); - } - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/lz4.hpp b/Sources/OpenVPN3/openvpn/buffer/lz4.hpp deleted file mode 100644 index 88b84b1..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/lz4.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// 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-2020 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 <cstdint> // for std::uint32_t, uint64_t, etc. - -#include <lz4.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/socktypes.hpp> // for ntohl/htonl -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - namespace LZ4 { - OPENVPN_EXCEPTION(lz4_error); - - inline BufferPtr compress(const ConstBuffer& src, - const size_t headroom, - const size_t tailroom) - { - // sanity check - if (src.size() > LZ4_MAX_INPUT_SIZE) - OPENVPN_THROW(lz4_error, "compress buffer size=" << src.size() << " exceeds LZ4_MAX_INPUT_SIZE=" << LZ4_MAX_INPUT_SIZE); - - // allocate dest buffer - BufferPtr dest = new BufferAllocated(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size()), 0); - dest->init_headroom(headroom); - - // as a hint to receiver, write the decompressed size - { - const std::uint32_t size = htonl(src.size()); - dest->write(&size, sizeof(size)); - } - - // compress - const int comp_size = ::LZ4_compress_default((const char *)src.c_data(), (char *)dest->data_end(), - (int)src.size(), (int)dest->remaining(tailroom)); - if (comp_size <= 0) - OPENVPN_THROW(lz4_error, "LZ4_compress_default returned error status=" << comp_size); - dest->inc_size(comp_size); - return dest; - } - - inline BufferPtr decompress(const ConstBuffer& source, - const size_t headroom, - const size_t tailroom, - size_t max_decompressed_size=LZ4_MAX_INPUT_SIZE) - { - // get the decompressed size - ConstBuffer src(source); - if (src.size() < sizeof(std::uint32_t)) - OPENVPN_THROW(lz4_error, "decompress buffer size=" << src.size() << " is too small"); - std::uint32_t size; - src.read(&size, sizeof(size)); - size = ntohl(size); - if (max_decompressed_size > LZ4_MAX_INPUT_SIZE) - max_decompressed_size = LZ4_MAX_INPUT_SIZE; - if (max_decompressed_size && size > max_decompressed_size) - OPENVPN_THROW(lz4_error, "decompress expansion size=" << size << " is too large (must be <= " << max_decompressed_size << ')'); - - // allocate dest buffer - BufferPtr dest = new BufferAllocated(headroom + tailroom + size, 0); - dest->init_headroom(headroom); - - // decompress - const int decomp_size = LZ4_decompress_safe((const char *)src.c_data(), (char *)dest->data(), - (int)src.size(), size); - if (decomp_size <= 0) - OPENVPN_THROW(lz4_error, "LZ4_decompress_safe returned error status=" << decomp_size); - if (static_cast<unsigned int>(decomp_size) != size) - OPENVPN_THROW(lz4_error, "decompress size inconsistency expected_size=" << size << " actual_size=" << decomp_size); - dest->inc_size(decomp_size); - return dest; - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/buffer/memq.hpp b/Sources/OpenVPN3/openvpn/buffer/memq.hpp deleted file mode 100644 index f2c8952..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/memq.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// 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-2020 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/>. - -// A queue of buffers, implemented as std::deque<BufferPtr>. - -#ifndef OPENVPN_BUFFER_MEMQ_H -#define OPENVPN_BUFFER_MEMQ_H - -#include <deque> - -#include <openvpn/common/size.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - class MemQBase - { - public: - MemQBase() : length(0) {} - - size_t size() const - { - return q.size(); - } - - bool empty() const - { - return q.empty(); - } - - size_t total_length() const { return length; } - - void clear() - { - while (!q.empty()) - q.pop_back(); - length = 0; - } - - void write_buf(const BufferPtr& bp) - { - q.push_back(bp); - length += bp->size(); - } - - BufferPtr read_buf() - { - BufferPtr ret = q.front(); - q.pop_front(); - length -= ret->size(); - return ret; - } - - BufferPtr& peek() - { - return q.front(); - } - - void pop() - { - length -= q.front()->size(); - q.pop_front(); - } - - void resize(const size_t cap) - { - q.resize(cap); - } - - protected: - typedef std::deque<BufferPtr> q_type; - size_t length; - q_type q; - }; - -} // namespace openvpn - -#endif // OPENVPN_BUFFER_MEMQ_H diff --git a/Sources/OpenVPN3/openvpn/buffer/safestr.hpp b/Sources/OpenVPN3/openvpn/buffer/safestr.hpp deleted file mode 100644 index f780818..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/safestr.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// 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-2020 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_BUFFER_SAFESTR_H -#define OPENVPN_BUFFER_SAFESTR_H - -#include <cstring> // for std::strlen, and std::memset -#include <ostream> - -#include <openvpn/common/memneq.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/bufstr.hpp> - -namespace openvpn { - class SafeString - { - static constexpr size_t INITIAL_CAPACITY = 32; - static constexpr unsigned int BUF_FLAGS = BufferAllocated::DESTRUCT_ZERO|BufferAllocated::GROW; - - public: - SafeString() - { - } - - SafeString(const char *str, const size_t size) - : data(size+1, BUF_FLAGS) - { - data.write((unsigned char *)str, size); - trail(); - } - - SafeString(const char *str) - : SafeString(str, std::strlen(str)) - { - } - - SafeString(const std::string& str) - : SafeString(str.c_str(), str.length()) - { - } - - const char *c_str() const - { - if (data.defined()) - return (const char *)data.c_data(); - else - return ""; - } - - // Note: unsafe because of conversion to std::string - std::string to_string() const - { - return buf_to_string(data); - } - - size_t length() const - { - return data.size(); - } - - bool empty() const - { - return !length(); - } - - char& operator[](size_t pos) - { - return *reinterpret_cast<char *>(data.index(pos)); - } - - const char& operator[](size_t pos) const - { - return *reinterpret_cast<const char *>(data.c_index(pos)); - } - - bool operator==(const char *str) const - { - const size_t len = std::strlen(str); - if (len != length()) - return false; - return !crypto::memneq(str, c_str(), len); - } - - bool operator!=(const char *str) const - { - return !operator==(str); - } - - SafeString& operator+=(char c) - { - alloc(); - data.push_back((unsigned char)c); - trail(); - return *this; - } - - SafeString& operator+=(const char* s) - { - return append(s); - } - - SafeString& operator+=(const SafeString& str) - { - return append(str); - } - - SafeString& append(const char* s) - { - alloc(); - data.write((unsigned char *)s, std::strlen(s)); - trail(); - return *this; - } - - SafeString& append(const SafeString& str) - { - alloc(); - data.append(str.data); - trail(); - return *this; - } - - SafeString& append(const SafeString& str, size_t subpos, size_t sublen) - { - alloc(); - data.append(str.data.range(subpos, sublen)); - trail(); - return *this; - } - - void reserve(const size_t n) - { - if (data.allocated()) - data.reserve(n+1); - else - data.init(n+1, BUF_FLAGS); - } - - void wipe() - { - data.clear(); - } - - private: - void alloc() - { - if (!data.allocated()) - data.init(INITIAL_CAPACITY, BUF_FLAGS); - } - - void trail() - { - data.set_trailer(0); - } - - BufferAllocated data; - }; - - template <typename Elem, typename Traits> - std::basic_ostream<Elem, Traits>& operator<<( - std::basic_ostream<Elem, Traits>& os, const SafeString& ss) - { - os << ss.c_str(); - return os; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/buffer/zlib.hpp b/Sources/OpenVPN3/openvpn/buffer/zlib.hpp deleted file mode 100644 index 3235eae..0000000 --- a/Sources/OpenVPN3/openvpn/buffer/zlib.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// 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-2020 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_BUFFER_ZLIB_H -#define OPENVPN_BUFFER_ZLIB_H - -#ifdef HAVE_ZLIB - -#include <cstring> // for std::memset - -#include <zlib.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/buflist.hpp> - -namespace openvpn { - namespace ZLib { - OPENVPN_EXCEPTION(zlib_error); - - class ZStreamBase // used internally by compress_gzip/decompress_gzip - { - public: - z_stream s; - protected: - ZStreamBase() { std::memset(&s, 0, sizeof(s)); } - private: - ZStreamBase(const ZStreamBase&) = delete; - ZStreamBase& operator=(const ZStreamBase&) = delete; - }; - - inline BufferPtr compress_gzip(BufferPtr src, - const size_t headroom, - const size_t tailroom, - const int level, - const int window_bits=15, - const int mem_level=8) - { - constexpr int GZIP_ENCODING = 16; - - struct ZStream : public ZStreamBase { - ~ZStream() { ::deflateEnd(&s); } - }; - - if (src) - { - int status; - ZStream zs; - zs.s.next_in = src->data(); - zs.s.avail_in = src->size(); - status = ::deflateInit2(&zs.s, - level, - Z_DEFLATED, - GZIP_ENCODING + window_bits, - mem_level, - Z_DEFAULT_STRATEGY); - if (status != Z_OK) - OPENVPN_THROW(zlib_error, "zlib deflateinit2 failed, error=" << status); - const uLong outcap = ::deflateBound(&zs.s, src->size()); - BufferPtr b = new BufferAllocated(outcap + headroom + tailroom, 0); - b->init_headroom(headroom); - zs.s.next_out = b->data(); - zs.s.avail_out = outcap; - status = ::deflate(&zs.s, Z_FINISH); - if (status != Z_STREAM_END) - OPENVPN_THROW(zlib_error, "zlib deflate failed, error=" << status); - b->set_size(zs.s.total_out); - return b; - } - else - return BufferPtr(); - } - - inline BufferPtr decompress_gzip(BufferPtr src, - const size_t headroom, - const size_t tailroom, - const size_t max_size, - const size_t block_size=4096, - const int window_bits=15) - { - constexpr int GZIP_ENCODING = 16; - - struct ZStream : public ZStreamBase { - ~ZStream() { ::inflateEnd(&s); } - }; - - if (src) - { - int status; - ZStream zs; - zs.s.next_in = src->data(); - zs.s.avail_in = src->size(); - status = ::inflateInit2(&zs.s, GZIP_ENCODING + window_bits); - if (status != Z_OK) - OPENVPN_THROW(zlib_error, "zlib inflateinit2 failed, error=" << status); - - BufferList blist; - size_t hr = headroom; - size_t tr = tailroom; - do { - // use headroom/tailroom on first block to take advantage - // of BufferList::join() optimization for one-block lists - BufferPtr b = new BufferAllocated(block_size + hr + tr, 0); - b->init_headroom(hr); - const size_t avail = b->remaining(tr); - zs.s.next_out = b->data(); - zs.s.avail_out = avail; - status = ::inflate(&zs.s, Z_SYNC_FLUSH); - if (status != Z_OK && status != Z_STREAM_END) - OPENVPN_THROW(zlib_error, "zlib inflate failed, error=" << status); - b->set_size(avail - zs.s.avail_out); - blist.push_back(std::move(b)); - if (max_size && zs.s.total_out > max_size) - OPENVPN_THROW(zlib_error, "zlib inflate max_size " << max_size << " exceeded"); - hr = tr = 0; - } while (status == Z_OK); - return blist.join(headroom, tailroom, true); - } - else - return BufferPtr(); - } - - } -} - -#endif -#endif diff --git a/Sources/OpenVPN3/openvpn/client/async_resolve.hpp b/Sources/OpenVPN3/openvpn/client/async_resolve.hpp deleted file mode 100644 index a20c6df..0000000 --- a/Sources/OpenVPN3/openvpn/client/async_resolve.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// 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-2020 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 */ diff --git a/Sources/OpenVPN3/openvpn/client/async_resolve/asio.hpp b/Sources/OpenVPN3/openvpn/client/async_resolve/asio.hpp deleted file mode 100644 index 85e6b5d..0000000 --- a/Sources/OpenVPN3/openvpn/client/async_resolve/asio.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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-2020 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 - { - private: - typedef RCPtr<AsyncResolvable> Ptr; - - class ResolveThread : public RC<thread_safe_refcount> - { - friend class AsyncResolvable<RESOLVER_TYPE>; - - private: - typedef RCPtr<ResolveThread> Ptr; - - openvpn_io::io_context& io_context; - AsyncResolvable<RESOLVER_TYPE> *parent; - std::atomic<bool> detached{false}; - - ResolveThread(openvpn_io::io_context &io_context_arg, - AsyncResolvable<RESOLVER_TYPE> *parent_arg, - const std::string& host, const std::string& port) - : io_context(io_context_arg), - parent(parent_arg) - { - std::thread t([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); - if (!self->is_detached()) - { - self->post_callback(results, error); - } - }); - // detach the thread so that the client won't need to wait for - // it to join. - t.detach(); - } - - void detach() - { - detached.store(true, std::memory_order_relaxed); - parent = nullptr; - } - - bool is_detached() const - { - return detached.load(std::memory_order_relaxed); - } - - void post_callback(typename RESOLVER_TYPE::results_type results, - openvpn_io::error_code error) - { - openvpn_io::post(io_context, [self=Ptr(this), results, error]() - { - auto parent = self->parent; - if (!self->is_detached() && parent) - { - self->detach(); - OPENVPN_ASYNC_HANDLER; - parent->resolve_callback(error, results); - } - }); - } - }; - - openvpn_io::io_context& io_context; - std::unique_ptr<AsioWork> asio_work; - typename ResolveThread::Ptr resolve_thread; - - public: - AsyncResolvable(openvpn_io::io_context& io_context_arg) - : io_context(io_context_arg) - { - } - - virtual ~AsyncResolvable() - { - async_resolve_cancel(); - } - - 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) - { - resolve_thread.reset(new ResolveThread(io_context, this, host, 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. - void async_resolve_lock() - { - asio_work.reset(new AsioWork(io_context)); - } - - // to be called by the child class when the core wants to stop - // and we don't need to wait for the detached thread any longer. - // It simulates a resolve abort - void async_resolve_cancel() - { - if (resolve_thread) - { - resolve_thread->detach(); - resolve_thread.reset(); - } - - asio_work.reset(); - } - }; -} - -#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_ASIO_H */ diff --git a/Sources/OpenVPN3/openvpn/client/async_resolve/generic.hpp b/Sources/OpenVPN3/openvpn/client/async_resolve/generic.hpp deleted file mode 100644 index e2d23f7..0000000 --- a/Sources/OpenVPN3/openvpn/client/async_resolve/generic.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// 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-2020 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); - }); - } - - // no-op: needed to provide the same class signature of the ASIO version - void async_resolve_lock() - { - } - - void async_resolve_cancel() - { - resolver.cancel(); - } - }; -} - -#endif /* OPENVPN_CLIENT_ASYNC_RESOLVE_GENERIC_H */ diff --git a/Sources/OpenVPN3/openvpn/client/cliconnect.hpp b/Sources/OpenVPN3/openvpn/client/cliconnect.hpp deleted file mode 100644 index 7000042..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliconnect.hpp +++ /dev/null @@ -1,699 +0,0 @@ -// 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-2020 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/>. - -// This file implements the top-level connection logic for an OpenVPN client -// connection. It is concerned with starting, stopping, pausing, and resuming -// OpenVPN client connections. It deals with retrying a connection and handles -// the connection timeout. It also deals with connection exceptions and understands -// the difference between an exception that should halt any further reconnection -// attempts (such as AUTH_FAILED), and other exceptions such as network errors -// that would justify a retry. -// -// Some of the methods in the class (such as stop, pause, and reconnect) are often -// called by another thread that is controlling the connection, therefore -// thread-safe methods are provided where the thread-safe function posts a message -// to the actual connection thread. -// -// In an OpenVPN client connection, the following object stack would be used: -// -// 1. class ClientConnect -- -// The top level object in an OpenVPN client connection. -// 2. class ClientProto::Session -- -// The OpenVPN client protocol object. -// 3. class ProtoContext -- -// The core OpenVPN protocol implementation that is common to both -// client and server. -// 4. ProtoStackBase<Packet> -- -// The lowest-level class that implements the basic functionality of -// tunneling a protocol over a reliable or unreliable transport -// layer, but isn't specific to OpenVPN per-se. - -#ifndef OPENVPN_CLIENT_CLICONNECT_H -#define OPENVPN_CLIENT_CLICONNECT_H - -#include <memory> -#include <utility> - -#include <openvpn/common/bigmutex.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/asio/asiowork.hpp> -#include <openvpn/error/excode.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/client/cliopt.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/client/clilife.hpp> - -namespace openvpn { - - // ClientConnect implements an "always-try-to-reconnect" approach, with remote - // list rotation. Only gives up on auth failure or other fatal errors that - // cannot be remedied by retrying. - class ClientConnect : ClientProto::NotifyCallback, - RemoteList::PreResolve::NotifyCallback, - ClientLifeCycle::NotifyCallback, - public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<ClientConnect> Ptr; - typedef ClientOptions::Client Client; - - OPENVPN_SIMPLE_EXCEPTION(client_connect_unhandled_exception); - - ClientConnect(openvpn_io::io_context& io_context_arg, - const ClientOptions::Ptr& client_options_arg) - : generation(0), - halt(false), - paused(false), - client_finalized(false), - dont_restart_(false), - lifecycle_started(false), - conn_timeout(client_options_arg->conn_timeout()), - io_context(io_context_arg), - client_options(client_options_arg), - server_poll_timer(io_context_arg), - restart_wait_timer(io_context_arg), - conn_timer(io_context_arg), - conn_timer_pending(false) - { - } - - void start() - { - if (!client && !halt) - { - if (!test_network()) - throw ErrorCode(Error::NETWORK_UNAVAILABLE, true, "Network Unavailable"); - - RemoteList::Ptr remote_list = client_options->remote_list_precache(); - RemoteList::PreResolve::Ptr preres(new RemoteList::PreResolve(io_context, - remote_list, - client_options->stats_ptr())); - if (preres->work_available()) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Resolve(); - client_options->events().add_event(std::move(ev)); - pre_resolve = preres; - pre_resolve->start(this); // asynchronous -- will call back to pre_resolve_done - } - else - new_client(); - } - } - - void send_explicit_exit_notify() - { - if (!halt && client) - client->send_explicit_exit_notify(); - } - - void graceful_stop() - { - send_explicit_exit_notify(); - //sleep(5); // simulate slow stop (comment out for production) - stop(); - } - - void stop() - { - if (!halt) - { - halt = true; - if (pre_resolve) - pre_resolve->cancel(); - if (client) - { - client->tun_set_disconnect(); - client->stop(false); - } - cancel_timers(); - asio_work.reset(); - - client_options->finalize(true); - - if (lifecycle_started) - { - ClientLifeCycle* lc = client_options->lifecycle(); - if (lc) - lc->stop(); - } - - ClientEvent::Base::Ptr ev = new ClientEvent::Disconnected(); - client_options->events().add_event(std::move(ev)); -#ifdef OPENVPN_IO_REQUIRES_STOP - io_context.stop(); -#endif - } - } - - void stop_on_signal(const openvpn_io::error_code& error, int signal_number) - { - stop(); - } - - // like stop() but may be safely called by another thread - void thread_safe_stop() - { - if (!halt) - openvpn_io::post(io_context, [self=Ptr(this)]() - { - OPENVPN_ASYNC_HANDLER; - self->graceful_stop(); - }); - } - - void pause(const std::string& reason) - { - if (!halt && !paused) - { - paused = true; - if (client) - { - client->send_explicit_exit_notify(); - client->stop(false); - interim_finalize(); - } - cancel_timers(); - asio_work.reset(new AsioWork(io_context)); - ClientEvent::Base::Ptr ev = new ClientEvent::Pause(reason); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::N_PAUSE); - } - } - - void resume() - { - if (!halt && paused) - { - paused = false; - ClientEvent::Base::Ptr ev = new ClientEvent::Resume(); - client_options->events().add_event(std::move(ev)); - client_options->remote_reset_cache_item(); - new_client(); - } - } - - void reconnect(int seconds) - { - if (!halt) - { - if (seconds < 0) - seconds = 0; - OPENVPN_LOG("Client terminated, reconnecting in " << seconds << "..."); - server_poll_timer.cancel(); - client_options->remote_reset_cache_item(); - restart_wait_timer.expires_after(Time::Duration::seconds(seconds)); - restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->restart_wait_callback(gen, error); - }); - } - } - - void thread_safe_pause(const std::string& reason) - { - if (!halt) - openvpn_io::post(io_context, [self=Ptr(this), reason]() - { - OPENVPN_ASYNC_HANDLER; - self->pause(reason); - }); - } - - void thread_safe_resume() - { - if (!halt) - openvpn_io::post(io_context, [self=Ptr(this)]() - { - OPENVPN_ASYNC_HANDLER; - self->resume(); - }); - } - - void thread_safe_reconnect(int seconds) - { - if (!halt) - openvpn_io::post(io_context, [self=Ptr(this), seconds]() - { - OPENVPN_ASYNC_HANDLER; - self->reconnect(seconds); - }); - } - - void dont_restart() - { - dont_restart_ = true; - } - - void post_cc_msg(const std::string& msg) - { - if (!halt && client) - client->post_cc_msg(msg); - } - - void thread_safe_post_cc_msg(std::string msg) - { - if (!halt) - openvpn_io::post(io_context, [self=Ptr(this), msg=std::move(msg)]() - { - OPENVPN_ASYNC_HANDLER; - self->post_cc_msg(msg); - }); - } - - ~ClientConnect() - { - stop(); - } - - private: - void interim_finalize() - { - if (!client_finalized) - { - client_options->finalize(false); - client_finalized = true; - } - } - - virtual void pre_resolve_done() override - { - if (!halt) - new_client(); - } - - void cancel_timers() - { - restart_wait_timer.cancel(); - server_poll_timer.cancel(); - conn_timer.cancel(); - conn_timer_pending = false; - } - - void restart_wait_callback(unsigned int gen, const openvpn_io::error_code& e) - { - if (!e && gen == generation && !halt) - { - if (paused) - resume(); - else - { - if (client) - client->send_explicit_exit_notify(); - new_client(); - } - } - } - - void server_poll_callback(unsigned int gen, const openvpn_io::error_code& e) - { - if (!e && gen == generation && !halt && !client->first_packet_received()) - { - OPENVPN_LOG("Server poll timeout, trying next remote entry..."); - new_client(); - } - } - - void conn_timer_callback(unsigned int gen, const openvpn_io::error_code& e) - { - if (!e && !halt) - { - client_options->stats().error(Error::CONNECTION_TIMEOUT); - if (!paused && client_options->pause_on_connection_timeout()) - { - // go into pause state instead of disconnect - pause(""); - } - else - { - ClientEvent::Base::Ptr ev = new ClientEvent::ConnectionTimeout(); - client_options->events().add_event(std::move(ev)); - stop(); - } - } - } - - void conn_timer_start(int timeout) - { - if (!conn_timer_pending && timeout > 0) - { - conn_timer.expires_after(Time::Duration::seconds(timeout)); - conn_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->conn_timer_callback(gen, error); - }); - conn_timer_pending = true; - } - } - - bool test_network() const - { - ClientLifeCycle* lc = client_options->lifecycle(); - if (lc) - { - if (!lc->network_available()) - return false; - } - return true; - } - - virtual void client_proto_connected() override - { - conn_timer.cancel(); - conn_timer_pending = false; - - // Monitor connection lifecycle notifications, such as sleep, - // wakeup, network-unavailable, and network-available. - // Not all platforms define a lifecycle object. Some platforms - // such as Android and iOS manage lifecycle notifications - // in the UI, and they call pause(), resume(), reconnect(), etc. - // as needed using the main ovpncli API. - if (!lifecycle_started) - { - ClientLifeCycle* lc = client_options->lifecycle(); // lifecycle is defined by platform, and may be NULL - if (lc) - { - lc->start(this); - lifecycle_started = true; - } - } - } - - void queue_restart(const unsigned int delay_ms = 2000) - { - OPENVPN_LOG("Client terminated, restarting in " << delay_ms << " ms..."); - server_poll_timer.cancel(); - interim_finalize(); - client_options->remote_reset_cache_item(); - restart_wait_timer.expires_after(Time::Duration::milliseconds(delay_ms)); - restart_wait_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->restart_wait_callback(gen, error); - }); - } - - virtual void client_proto_auth_pending_timeout(int timeout) override - { - if (conn_timer_pending) - { - auto timer_left = std::chrono::duration_cast<std::chrono::seconds>(conn_timer.expiry() - AsioTimer::clock_type::now()).count(); - if(timer_left < timeout) - { - OPENVPN_LOG("Extending connection timeout from " << timer_left << " to " << timeout << " for pending authentification"); - conn_timer.cancel(); - conn_timer_pending = false; - conn_timer_start(timeout); - } - } - } - - virtual void client_proto_terminate() override - { - if (!halt) - { - if (dont_restart_) - { - stop(); - } - else - { - switch (client->fatal()) - { - case Error::UNDEF: // means that there wasn't a fatal error - queue_restart(); - break; - - // Errors below will cause the client to NOT retry the connection, - // or otherwise give the error special handling. - - case Error::AUTH_FAILED: - { - const std::string& reason = client->fatal_reason(); - if (ChallengeResponse::is_dynamic(reason)) // dynamic challenge/response? - { - ClientEvent::Base::Ptr ev = new ClientEvent::DynamicChallenge(reason); - client_options->events().add_event(std::move(ev)); - stop(); - } - else - { - ClientEvent::Base::Ptr ev = new ClientEvent::AuthFailed(reason); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::AUTH_FAILED); - if (client_options->retry_on_auth_failed()) - queue_restart(5000); - else - stop(); - } - } - break; - case Error::TUN_SETUP_FAILED: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunSetupFailed(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_SETUP_FAILED); - stop(); - } - break; - case Error::TUN_REGISTER_RINGS_ERROR: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunSetupFailed(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_REGISTER_RINGS_ERROR); - stop(); - } - break; - case Error::TUN_IFACE_CREATE: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunIfaceCreate(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_IFACE_CREATE); - stop(); - } - break; - case Error::TUN_IFACE_DISABLED: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunIfaceDisabled(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_IFACE_DISABLED); - queue_restart(5000); - } - break; - case Error::PROXY_ERROR: - { - ClientEvent::Base::Ptr ev = new ClientEvent::ProxyError(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::PROXY_ERROR); - stop(); - } - break; - case Error::PROXY_NEED_CREDS: - { - ClientEvent::Base::Ptr ev = new ClientEvent::ProxyNeedCreds(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::PROXY_NEED_CREDS); - stop(); - } - break; - case Error::CERT_VERIFY_FAIL: - { - ClientEvent::Base::Ptr ev = new ClientEvent::CertVerifyFail(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::CERT_VERIFY_FAIL); - stop(); - } - break; - case Error::TLS_VERSION_MIN: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TLSVersionMinFail(); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TLS_VERSION_MIN); - stop(); - } - break; - case Error::CLIENT_HALT: - { - ClientEvent::Base::Ptr ev = new ClientEvent::ClientHalt(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::CLIENT_HALT); - stop(); - } - break; - case Error::CLIENT_RESTART: - { - ClientEvent::Base::Ptr ev = new ClientEvent::ClientRestart(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::CLIENT_RESTART); - queue_restart(); - } - break; - case Error::INACTIVE_TIMEOUT: - { - ClientEvent::Base::Ptr ev = new ClientEvent::InactiveTimeout(); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::INACTIVE_TIMEOUT); - - // explicit exit notify is sent earlier by - // ClientProto::Session::inactive_callback() - stop(); - } - break; - case Error::TRANSPORT_ERROR: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TransportError(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TRANSPORT_ERROR); - queue_restart(5000); // use a larger timeout to allow preemption from higher levels - } - break; - case Error::TUN_ERROR: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunError(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_ERROR); - queue_restart(5000); - } - break; - case Error::TUN_HALT: - { - ClientEvent::Base::Ptr ev = new ClientEvent::TunHalt(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::TUN_HALT); - stop(); - } - break; - case Error::RELAY: - { - ClientEvent::Base::Ptr ev = new ClientEvent::Relay(); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::RELAY); - transport_factory_relay = client->transport_factory_relay(); - queue_restart(0); - } - break; - case Error::RELAY_ERROR: - { - ClientEvent::Base::Ptr ev = new ClientEvent::RelayError(client->fatal_reason()); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::RELAY_ERROR); - stop(); - } - break; - default: - throw client_connect_unhandled_exception(); - } - } - } - } - - void new_client() - { - ++generation; - if (client_options->asio_work_always_on()) - asio_work.reset(new AsioWork(io_context)); - else - asio_work.reset(); - if (client) - { - client->stop(false); - interim_finalize(); - } - if (generation > 1 && !transport_factory_relay) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Reconnecting(); - client_options->events().add_event(std::move(ev)); - client_options->stats().error(Error::N_RECONNECT); - if (!(client && client->reached_connected_state())) - client_options->next(); - } - - // client_config in cliopt.hpp - Client::Config::Ptr cli_config = client_options->client_config(!transport_factory_relay); - client.reset(new Client(io_context, *cli_config, this)); // build ClientProto::Session from cliproto.hpp - client_finalized = false; - - // relay? - if (transport_factory_relay) - { - client->transport_factory_override(std::move(transport_factory_relay)); - transport_factory_relay.reset(); - } - - restart_wait_timer.cancel(); - if (client_options->server_poll_timeout_enabled()) - { - server_poll_timer.expires_after(client_options->server_poll_timeout()); - server_poll_timer.async_wait([self=Ptr(this), gen=generation](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->server_poll_callback(gen, error); - }); - } - conn_timer_start(conn_timeout); - client->start(); - } - - // ClientLifeCycle::NotifyCallback callbacks - - virtual void cln_stop() override - { - thread_safe_stop(); - } - - virtual void cln_pause(const std::string& reason) override - { - thread_safe_pause(reason); - } - - virtual void cln_resume() override - { - thread_safe_resume(); - } - - virtual void cln_reconnect(int seconds) override - { - thread_safe_reconnect(seconds); - } - - unsigned int generation; - bool halt; - bool paused; - bool client_finalized; - bool dont_restart_; - bool lifecycle_started; - int conn_timeout; - openvpn_io::io_context& io_context; - ClientOptions::Ptr client_options; - Client::Ptr client; - TransportClientFactory::Ptr transport_factory_relay; - AsioTimer server_poll_timer; - AsioTimer restart_wait_timer; - AsioTimer conn_timer; - bool conn_timer_pending; - std::unique_ptr<AsioWork> asio_work; - RemoteList::PreResolve::Ptr pre_resolve; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/cliconstants.hpp b/Sources/OpenVPN3/openvpn/client/cliconstants.hpp deleted file mode 100644 index 6d71081..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliconstants.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// 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-2020 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_CLICONSTANTS_H -#define OPENVPN_CLIENT_CLICONSTANTS_H - -// Various sanity checks for different limits on OpenVPN clients - -namespace openvpn { - namespace ProfileParseLimits { - enum { - MAX_PROFILE_SIZE=262144, // maximum size of an OpenVPN configuration file - MAX_PUSH_SIZE=262144, // maximum size of aggregate data that can be pushed to a client - MAX_LINE_SIZE=512, // maximum size of an OpenVPN configuration file line - MAX_DIRECTIVE_SIZE=64, // maximum number of chars in an OpenVPN directive - OPT_OVERHEAD=64, // bytes overhead of one option/directive, for accounting purposes - TERM_OVERHEAD=16, // bytes overhead of one argument in an option, for accounting purposes - MAX_SERVER_LIST_SIZE=4096, // maximum server list size, i.e. "setenv SERVER ..." - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/clicreds.hpp b/Sources/OpenVPN3/openvpn/client/clicreds.hpp deleted file mode 100644 index 1ddce72..0000000 --- a/Sources/OpenVPN3/openvpn/client/clicreds.hpp +++ /dev/null @@ -1,227 +0,0 @@ -// 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-2020 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/>. - -// This class encapsulates the state of authentication credentials -// maintained by an OpenVPN client. It understands dynamic -// challenge/response cookies, and Session Token IDs (where the -// password in the object is wiped and replaced by a token used -// for further authentications). - -#ifndef OPENVPN_CLIENT_CLICREDS_H -#define OPENVPN_CLIENT_CLICREDS_H - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/transport/protocol.hpp> -#include <openvpn/auth/cr.hpp> - -namespace openvpn { - - class ClientCreds : public RC<thread_unsafe_refcount> { - public: - typedef RCPtr<ClientCreds> Ptr; - - ClientCreds() : allow_cache_password(false), - password_save_defined(false), - replace_password_with_session_id(false), - did_replace_password_with_session_id(false) {} - - void set_username(const std::string& username_arg) - { - username = username_arg; - } - - void set_password(const std::string& password_arg) - { - password = password_arg; - did_replace_password_with_session_id = false; - } - - void set_response(const std::string& response_arg) - { - response = response_arg; - } - - void set_dynamic_challenge_cookie(const std::string& cookie, const std::string& username) - { - if (!cookie.empty()) - dynamic_challenge.reset(new ChallengeResponse(cookie, username)); - } - - void set_replace_password_with_session_id(const bool value) - { - replace_password_with_session_id = value; - } - - void enable_password_cache(const bool value) - { - allow_cache_password = value; - } - - bool get_replace_password_with_session_id() const - { - return replace_password_with_session_id; - } - - void set_session_id(const std::string& user, const std::string& sess_id) - { - // force Session ID use if dynamic challenge is enabled - if (dynamic_challenge && !replace_password_with_session_id) - replace_password_with_session_id = true; - - if (replace_password_with_session_id) - { - if (allow_cache_password && !password_save_defined) - { - password_save = password; - password_save_defined = true; - } - password = sess_id; - response = ""; - if (dynamic_challenge) - { - username = dynamic_challenge->get_username(); - dynamic_challenge.reset(); - } - else if (!user.empty()) - username = user; - did_replace_password_with_session_id = true; - } - } - - std::string get_username() const - { - if (dynamic_challenge) - return dynamic_challenge->get_username(); - else - return username; - } - - std::string get_password() const - { - if (dynamic_challenge) - return dynamic_challenge->construct_dynamic_password(response); - else if (response.empty()) - return password; - else - return ChallengeResponse::construct_static_password(password, response); - } - - bool username_defined() const - { - return !username.empty(); - } - - bool password_defined() const - { - return !password.empty(); - } - - bool session_id_defined() const - { - return did_replace_password_with_session_id; - } - - // If we have a saved password that is not a session ID, - // restore it and wipe any existing session ID. - bool can_retry_auth_with_cached_password() - { - if (password_save_defined) - { - password = password_save; - password_save.clear(); - password_save_defined = false; - did_replace_password_with_session_id = false; - return true; - } - else - return false; - } - - void purge_session_id() - { - if (!can_retry_auth_with_cached_password()) - { - password.clear(); - did_replace_password_with_session_id = false; - } - } - - std::string auth_info() const - { - std::string ret; - if (dynamic_challenge) - { - ret = "DynamicChallenge"; - } - else if (response.empty()) - { - if (!username.empty()) - ret += "Username"; - else - ret += "UsernameEmpty"; - ret += '/'; - if (!password.empty()) - { - if (did_replace_password_with_session_id) - ret += "SessionID"; - else - ret += "Password"; - } - else - ret += "PasswordEmpty"; - } - else - { - ret = "StaticChallenge"; - } - return ret; - } - - private: - // Standard credentials - std::string username; - std::string password; - - // Password caching - bool allow_cache_password; - bool password_save_defined; - std::string password_save; - - // Response to challenge - std::string response; - - // Info describing a dynamic challenge - ChallengeResponse::Ptr dynamic_challenge; - - // If true, on successful connect, we will replace the password - // with the session ID we receive from the server. - bool replace_password_with_session_id; - - // true if password has been replaced with Session ID - bool did_replace_password_with_session_id; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/cliemuexr.hpp b/Sources/OpenVPN3/openvpn/client/cliemuexr.hpp deleted file mode 100644 index 4fe9d17..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliemuexr.hpp +++ /dev/null @@ -1,177 +0,0 @@ -// 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-2020 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/>. - -// Emulate Excluded Routes implementation (needed by Android) - -#ifndef OPENVPN_CLIENT_CLIEMUEXR_H -#define OPENVPN_CLIENT_CLIEMUEXR_H - -#include <openvpn/common/exception.hpp> -#include <openvpn/tun/client/emuexr.hpp> -#include <openvpn/addr/addrspacesplit.hpp> - -namespace openvpn { - class EmulateExcludeRouteImpl : public EmulateExcludeRoute - { - public: - OPENVPN_EXCEPTION(emulate_exclude_route_error); - - typedef RCPtr<EmulateExcludeRouteImpl> Ptr; - - explicit EmulateExcludeRouteImpl(const bool exclude_server_address) - : exclude_server_address_(exclude_server_address) - { - } - - private: - void add_route(const bool add, const IP::Addr& addr, const int prefix_len) override - { - (add ? include : exclude).emplace_back(addr, prefix_len); - } - - void add_default_routes(bool ipv4, bool ipv6) override - { - if (ipv4) - add_route(true, IP::Addr::from_zero(IP::Addr::V4), 0); - if (ipv6) - add_route(true, IP::Addr::from_zero(IP::Addr::V6), 0); - } - - bool enabled(const IPVerFlags& ipv) const override - { - return exclude.size() && (ipv.rgv4() || ipv.rgv6()); - } - - void emulate(TunBuilderBase* tb, IPVerFlags& ipv, const IP::Addr& server_addr) const override - { - const unsigned int ip_ver_flags = ipv.ip_ver_flags(); - IP::RouteList rl, tempExcludeList; - rl.reserve(include.size() + exclude.size()); - rl.insert(rl.end(), include.begin(), include.end()); - rl.insert(rl.end(), exclude.begin(), exclude.end()); - - // Check if we have to exclude the server, if yes we temporarily add it to the list - // of excluded networks as small individual /32 or /128 network - const IP::RouteList* excludedRoutes = &exclude; - - if (exclude_server_address_ && (server_addr.version_mask() & ip_ver_flags) && - !exclude.contains(IP::Route(server_addr, server_addr.size()))) - { - rl.emplace_back(server_addr, server_addr.size()); - // Create a temporary list that includes all the routes + the server - tempExcludeList = exclude; - tempExcludeList.emplace_back(server_addr, server_addr.size()); - excludedRoutes = &tempExcludeList; - } - - - if (excludedRoutes->empty()) - { - // Samsung's Android VPN API does different things if you have - // 0.0.0.0/0 in the list of installed routes - // (even if 0.0.0.0/1 and 128.0.0.0/1 and are present it behaves different) - - // We normally always split the address space, breaking a 0.0.0.0/0 into - // smaller routes. If no routes are excluded, we install the original - // routes without modifying them - - for (const auto& rt: include) - { - if (rt.version() & ip_ver_flags) - { - if (!tb->tun_builder_add_route(rt.addr.to_string(), rt.prefix_len, -1, rt.addr.version() == IP::Addr::V6)) - throw emulate_exclude_route_error("tun_builder_add_route failed"); - } - } - return; - } - - // Complete address space (0.0.0.0/0 or ::/0) split into smaller networks - // Figure out which parts of this non overlapping address we want to install - for (const auto& r: IP::AddressSpaceSplitter(rl, ip_ver_flags)) - { - if (check_route_should_be_installed(r, *excludedRoutes)) - if (!tb->tun_builder_add_route(r.addr.to_string(), r.prefix_len, -1, r.addr.version() == IP::Addr::V6)) - throw emulate_exclude_route_error("tun_builder_add_route failed"); - } - - ipv.set_emulate_exclude_routes(); - } - - bool check_route_should_be_installed(const IP::Route& r, const IP::RouteList & excludedRoutes) const - { - // The whole address space was partioned into NON-overlapping routes that - // we get one by one with the parameter r. - // Therefore we already know that the whole route r either is included or - // excluded IPs. - // Figure out if this particular route should be installed or not - - IP::Route const* bestroute = nullptr; - // Get the best (longest-prefix/smallest) route from included routes that completely - // matches this route - for (const auto& incRoute: include) - { - if (incRoute.contains(r)) - { - if (!bestroute || bestroute->prefix_len < incRoute.prefix_len) - bestroute = &incRoute; - } - } - - // No positive route matches the route at all, do not install it - if (!bestroute) - return false; - - // Check if there is a more specific exclude route - for (const auto& exclRoute: excludedRoutes) - { - if (exclRoute.contains(r) && exclRoute.prefix_len > bestroute->prefix_len) - return false; - } - return true; - } - - const bool exclude_server_address_; - IP::RouteList include; - IP::RouteList exclude; - }; - - class EmulateExcludeRouteFactoryImpl : public EmulateExcludeRouteFactory - { - public: - typedef RCPtr<EmulateExcludeRouteFactoryImpl> Ptr; - - EmulateExcludeRouteFactoryImpl(const bool exclude_server_address) - : exclude_server_address_(exclude_server_address) - { - } - - private: - virtual EmulateExcludeRoute::Ptr new_obj() const - { - return EmulateExcludeRoute::Ptr(new EmulateExcludeRouteImpl(exclude_server_address_)); - } - - const bool exclude_server_address_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/clievent.hpp b/Sources/OpenVPN3/openvpn/client/clievent.hpp deleted file mode 100644 index 3209e83..0000000 --- a/Sources/OpenVPN3/openvpn/client/clievent.hpp +++ /dev/null @@ -1,487 +0,0 @@ -// 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-2020 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/>. - -// This file describes the basic set of OpenVPN client events, including the -// normal events leading up to a connection as well as error events. - -#ifndef OPENVPN_CLIENT_CLIEVENT_H -#define OPENVPN_CLIENT_CLIEVENT_H - -#include <sstream> -#include <deque> -#include <utility> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/transport/protocol.hpp> - -namespace openvpn { - namespace ClientEvent { - enum Type { - // normal events including disconnected, connected, and other transitional events - DISCONNECTED=0, - CONNECTED, - RECONNECTING, - AUTH_PENDING, - RESOLVE, - WAIT, - WAIT_PROXY, - CONNECTING, - GET_CONFIG, - ASSIGN_IP, - ADD_ROUTES, - ECHO_OPT, - INFO, - WARN, - PAUSE, - RESUME, - RELAY, - COMPRESSION_ENABLED, - UNSUPPORTED_FEATURE, - - // start of nonfatal errors, must be marked by NONFATAL_ERROR_START below - TRANSPORT_ERROR, - TUN_ERROR, - CLIENT_RESTART, - - // start of errors, must be marked by FATAL_ERROR_START below - AUTH_FAILED, - CERT_VERIFY_FAIL, - TLS_VERSION_MIN, - CLIENT_HALT, - CLIENT_SETUP, - TUN_HALT, - CONNECTION_TIMEOUT, - INACTIVE_TIMEOUT, - DYNAMIC_CHALLENGE, - PROXY_NEED_CREDS, - PROXY_ERROR, - TUN_SETUP_FAILED, - TUN_IFACE_CREATE, - TUN_IFACE_DISABLED, - EPKI_ERROR, // EPKI refers to External PKI errors, i.e. errors in accessing external - EPKI_INVALID_ALIAS, // certificates or keys. - RELAY_ERROR, - - N_TYPES - }; - - enum { - NONFATAL_ERROR_START = TRANSPORT_ERROR, // start of nonfatal errors that automatically reconnect - FATAL_ERROR_START = AUTH_FAILED, // start of fatal errors - }; - - inline const char *event_name(const Type type) - { - static const char *names[] = { - "DISCONNECTED", - "CONNECTED", - "RECONNECTING", - "AUTH_PENDING", - "RESOLVE", - "WAIT", - "WAIT_PROXY", - "CONNECTING", - "GET_CONFIG", - "ASSIGN_IP", - "ADD_ROUTES", - "ECHO", - "INFO", - "WARN", - "PAUSE", - "RESUME", - "RELAY", - "COMPRESSION_ENABLED", - "UNSUPPORTED_FEATURE", - - // nonfatal errors - "TRANSPORT_ERROR", - "TUN_ERROR", - "CLIENT_RESTART", - - // fatal errors - "AUTH_FAILED", - "CERT_VERIFY_FAIL", - "TLS_VERSION_MIN", - "CLIENT_HALT", - "CLIENT_SETUP", - "TUN_HALT", - "CONNECTION_TIMEOUT", - "INACTIVE_TIMEOUT", - "DYNAMIC_CHALLENGE", - "PROXY_NEED_CREDS", - "PROXY_ERROR", - "TUN_SETUP_FAILED", - "TUN_IFACE_CREATE", - "TUN_IFACE_DISABLED", - "EPKI_ERROR", - "EPKI_INVALID_ALIAS", - "RELAY_ERROR", - }; - - static_assert(N_TYPES == array_size(names), "event names array inconsistency"); - if (type < N_TYPES) - return names[type]; - else - return "UNKNOWN_EVENT_TYPE"; - } - - struct Connected; - - // The base class for all events. - class Base : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<Base> Ptr; - Base(Type id) : id_(id) {} - - Type id() const { return id_; } - - const char *name() const - { - return event_name(id_); - } - - bool is_error() const - { - return int(id_) >= NONFATAL_ERROR_START; - } - - bool is_fatal() const - { - return int(id_) >= FATAL_ERROR_START; - } - - virtual std::string render() const - { - return ""; - } - - const Connected* connected_cast() const - { - if (id_ == CONNECTED) - return (const Connected*)this; - else - return nullptr; - } - - private: - Type id_; - }; - - // Specific client events. Some events have no additional data attached to them, - // while other events (such as Connected) have many additional data fields. - - struct Resolve : public Base - { - Resolve() : Base(RESOLVE) {} - }; - - struct Wait : public Base - { - Wait() : Base(WAIT) {} - }; - - struct WaitProxy : public Base - { - WaitProxy() : Base(WAIT_PROXY) {} - }; - - struct Connecting : public Base - { - Connecting() : Base(CONNECTING) {} - }; - - struct Reconnecting : public Base - { - Reconnecting() : Base(RECONNECTING) {} - }; - - struct GetConfig : public Base - { - GetConfig() : Base(GET_CONFIG) {} - }; - - struct AssignIP : public Base - { - AssignIP() : Base(ASSIGN_IP) {} - }; - - struct AddRoutes : public Base - { - AddRoutes() : Base(ADD_ROUTES) {} - }; - - struct Resume : public Base - { - Resume() : Base(RESUME) {} - }; - - struct Relay : public Base - { - Relay() : Base(RELAY) {} - }; - - struct Disconnected : public Base - { - Disconnected() : Base(DISCONNECTED) {} - }; - - struct ConnectionTimeout : public Base - { - ConnectionTimeout() : Base(CONNECTION_TIMEOUT) {} - }; - - struct InactiveTimeout : public Base - { - InactiveTimeout() : Base(INACTIVE_TIMEOUT) {} - }; - - struct TLSVersionMinFail : public Base - { - TLSVersionMinFail() : Base(TLS_VERSION_MIN) {} - }; - - struct UnsupportedFeature : public Base - { - typedef RCPtr<UnsupportedFeature> Ptr; - - UnsupportedFeature(const std::string& name_arg, const std::string& reason_arg, bool critical_arg) - : Base(UNSUPPORTED_FEATURE), - name(name_arg), - reason(reason_arg), - critical(critical_arg) {} - - std::string name; - std::string reason; - bool critical; - - virtual std::string render() const - { - std::ostringstream out; - out << "name: " << name << ", reason: " << reason << ", critical: " << critical; - return out.str(); - } - }; - - struct Connected : public Base - { - typedef RCPtr<Connected> Ptr; - - Connected() : Base(CONNECTED) {} - - std::string user; - std::string server_host; - std::string server_port; - std::string server_proto; - std::string server_ip; - std::string vpn_ip4; - std::string vpn_ip6; - std::string vpn_gw4; - std::string vpn_gw6; - std::string client_ip; - std::string tun_name; - - virtual std::string render() const - { - std::ostringstream out; - // eg. "godot@foo.bar.gov:443 (1.2.3.4) via TCPv4 on tun0/5.5.1.1" - if (!user.empty()) - out << user << '@'; - if (server_host.find_first_of(':') == std::string::npos) - out << server_host; - else - out << '[' << server_host << ']'; - out << ':' << server_port - << " (" << server_ip << ") via " << client_ip << '/' << server_proto - << " on " << tun_name << '/' << vpn_ip4 << '/' << vpn_ip6 - << " gw=[" << vpn_gw4 << '/' << vpn_gw6 << ']'; - return out.str(); - } - }; - - struct ReasonBase : public Base { - ReasonBase(const Type id, const std::string& reason_arg) - : Base(id), - reason(reason_arg) - { - } - - ReasonBase(const Type id, std::string&& reason_arg) - : Base(id), - reason(std::move(reason_arg)) - { - } - - virtual std::string render() const - { - return reason; - } - - std::string reason; - }; - - struct AuthFailed : public ReasonBase - { - AuthFailed(std::string reason) : ReasonBase(AUTH_FAILED, std::move(reason)) {} - }; - - struct CertVerifyFail : public ReasonBase - { - CertVerifyFail(std::string reason) : ReasonBase(CERT_VERIFY_FAIL, std::move(reason)) {} - }; - - struct ClientHalt : public ReasonBase - { - ClientHalt(std::string reason) : ReasonBase(CLIENT_HALT, std::move(reason)) {} - }; - - struct ClientRestart : public ReasonBase - { - ClientRestart(std::string reason) : ReasonBase(CLIENT_RESTART, std::move(reason)) {} - }; - - struct TunHalt : public ReasonBase - { - TunHalt(std::string reason) : ReasonBase(TUN_HALT, std::move(reason)) {} - }; - - struct RelayError : public ReasonBase - { - RelayError(std::string reason) : ReasonBase(RELAY_ERROR, std::move(reason)) {} - }; - - struct DynamicChallenge : public ReasonBase - { - DynamicChallenge(std::string reason) : ReasonBase(DYNAMIC_CHALLENGE, std::move(reason)) {} - }; - - struct Pause : public ReasonBase - { - Pause(std::string reason) : ReasonBase(PAUSE, std::move(reason)) {} - }; - - struct ProxyError : public ReasonBase - { - ProxyError(std::string reason) : ReasonBase(PROXY_ERROR, std::move(reason)) {} - }; - - struct ProxyNeedCreds : public ReasonBase - { - ProxyNeedCreds(std::string reason) : ReasonBase(PROXY_NEED_CREDS, std::move(reason)) {} - }; - - struct TransportError : public ReasonBase - { - TransportError(std::string reason) : ReasonBase(TRANSPORT_ERROR, std::move(reason)) {} - }; - - struct TunSetupFailed : public ReasonBase - { - TunSetupFailed(std::string reason) : ReasonBase(TUN_SETUP_FAILED, std::move(reason)) {} - }; - - struct TunIfaceCreate : public ReasonBase - { - TunIfaceCreate(std::string reason) : ReasonBase(TUN_IFACE_CREATE, std::move(reason)) {} - }; - - struct TunIfaceDisabled : public ReasonBase - { - TunIfaceDisabled(std::string reason) : ReasonBase(TUN_IFACE_DISABLED, std::move(reason)) {} - }; - - struct TunError : public ReasonBase - { - TunError(std::string reason) : ReasonBase(TUN_ERROR, std::move(reason)) {} - }; - - struct EpkiError : public ReasonBase - { - EpkiError(std::string reason) : ReasonBase(EPKI_ERROR, std::move(reason)) {} - }; - - struct EpkiInvalidAlias : public ReasonBase - { - EpkiInvalidAlias(std::string reason) : ReasonBase(EPKI_INVALID_ALIAS, std::move(reason)) {} - }; - - struct Echo : public ReasonBase - { - Echo(std::string value) : ReasonBase(ECHO_OPT, std::move(value)) {} - }; - - struct Info : public ReasonBase - { - Info(std::string value) : ReasonBase(INFO, std::move(value)) {} - }; - - struct AuthPending : public ReasonBase - { - int timeout; - AuthPending(int timeout, std::string value): ReasonBase(AUTH_PENDING, std::move(value)), timeout(timeout) {} - }; - - struct Warn : public ReasonBase - { - Warn(std::string value) : ReasonBase(WARN, std::move(value)) {} - }; - - class ClientSetup : public ReasonBase - { - public: - ClientSetup(const std::string& status, const std::string& message) - : ReasonBase(CLIENT_SETUP, make(status, message)) - { - } - - private: - static std::string make(const std::string& status, const std::string& message) - { - std::string ret; - ret += status; - if (!status.empty() && !message.empty()) - ret += ": "; - ret += message; - return ret; - } - }; - - struct CompressionEnabled : public ReasonBase - { - CompressionEnabled(std::string msg) - : ReasonBase(COMPRESSION_ENABLED, std::move(msg)) - { - } - }; - - class Queue : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Queue> Ptr; - - virtual void add_event(Base::Ptr event) = 0; - }; - } -} - -#endif // OPENVPN_CLIENT_CLIEVENT_H diff --git a/Sources/OpenVPN3/openvpn/client/clihalt.hpp b/Sources/OpenVPN3/openvpn/client/clihalt.hpp deleted file mode 100644 index 69c467a..0000000 --- a/Sources/OpenVPN3/openvpn/client/clihalt.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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_CLIHALT_H -#define OPENVPN_CLIENT_CLIHALT_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/string.hpp> - -// Process halt/restart messages from server: -// HALT,<client_reason> -> disconnect -// RESTART,<client_reason> -> restart with reason, don't preserve session ID -// RESTART,[P]:<client_reason> -> restart with reason, do preserve session ID - -namespace openvpn { - class ClientHalt - { - typedef std::vector<std::string> StringList; - - public: - OPENVPN_SIMPLE_EXCEPTION(client_halt_error); - - ClientHalt(const std::string& msg, const bool unicode_filter) - { - // get operator (halt or restart) - StringList sl; - parse_msg(sl, msg); - if (is_halt(sl)) - ; - else if (is_restart(sl)) - restart_ = true; - else - throw client_halt_error(); - - // get flags and reason - if (sl.size() >= 2) - { - size_t reason_pos = 0; - if (restart_ && string::starts_with(sl[1], "[P]:")) - { - psid_ = true; - reason_pos = 4; - } - reason_ = sl[1].substr(reason_pos); - if (unicode_filter) - reason_ = Unicode::utf8_printable(reason_, 256); - } - } - - static bool match(const std::string& msg) - { - StringList sl; - parse_msg(sl, msg); - return is_halt(sl) || is_restart(sl); - } - - // returns true for restart, false for halt - bool restart() const { return restart_; } - - // returns true if session ID should be preserved - bool psid() const { return psid_; } - - // returns user-visible reason string - const std::string& reason() const { return reason_; } - - std::string render() const { - std::ostringstream os; - os << (restart_ ? "RESTART" : "HALT") << " psid=" << psid_ << " reason='" << reason_ << '\''; - return os.str(); - } - - private: - static void parse_msg(StringList& sl, const std::string& msg) - { - sl.reserve(2); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, msg, ',', 0, 1); - } - - static bool is_halt(const StringList& sl) - { - return sl.size() >= 1 && sl[0] == "HALT"; - } - - static bool is_restart(const StringList& sl) - { - return sl.size() >= 1 && sl[0] == "RESTART"; - } - - bool restart_ = false; - bool psid_ = false; - std::string reason_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/clilife.hpp b/Sources/OpenVPN3/openvpn/client/clilife.hpp deleted file mode 100644 index cbc7b9c..0000000 --- a/Sources/OpenVPN3/openvpn/client/clilife.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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_CLILIFE_H -#define OPENVPN_CLIENT_CLILIFE_H - -#include <string> - -#include <openvpn/common/rc.hpp> - -namespace openvpn { - // Base class for managing connection lifecycle notifications, - // such as sleep, wakeup, network-unavailable, network-available. - class ClientLifeCycle : public RC<thread_unsafe_refcount> { - public: - struct NotifyCallback { - virtual void cln_stop() = 0; - virtual void cln_pause(const std::string& reason) = 0; - virtual void cln_resume() = 0; - virtual void cln_reconnect(int seconds) = 0; - }; - - typedef RCPtr<ClientLifeCycle> Ptr; - - virtual bool network_available() = 0; - - virtual void start(NotifyCallback*) = 0; - virtual void stop() = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/cliopt.hpp b/Sources/OpenVPN3/openvpn/client/cliopt.hpp deleted file mode 100644 index 8137213..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliopt.hpp +++ /dev/null @@ -1,920 +0,0 @@ -// 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-2020 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/>. - -// These classes encapsulate the basic setup of the various objects needed to -// create an OpenVPN client session. The basic idea here is to look at both -// compile time settings (i.e. crypto/SSL/random libraries), and run-time -// (such as transport layer using UDP, TCP, or HTTP-proxy), and -// build the actual objects that will be used to construct a client session. - -#ifndef OPENVPN_CLIENT_CLIOPT_H -#define OPENVPN_CLIENT_CLIOPT_H - -#include <string> - -#include <openvpn/error/excode.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/frame/frame_init.hpp> -#include <openvpn/pki/epkibase.hpp> -#include <openvpn/crypto/cryptodcsel.hpp> -#include <openvpn/ssl/mssparms.hpp> -#include <openvpn/tun/tunmtu.hpp> -#include <openvpn/tun/ipv6_setting.hpp> -#include <openvpn/netconf/hwaddr.hpp> - -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/transport/reconnect_notify.hpp> -#include <openvpn/transport/client/udpcli.hpp> -#include <openvpn/transport/client/tcpcli.hpp> -#include <openvpn/transport/client/httpcli.hpp> -#include <openvpn/transport/altproxy.hpp> -#include <openvpn/transport/dco.hpp> -#include <openvpn/client/cliproto.hpp> -#include <openvpn/client/cliopthelper.hpp> -#include <openvpn/client/optfilt.hpp> -#include <openvpn/client/clilife.hpp> - -#include <openvpn/ssl/sslchoose.hpp> - -#ifdef OPENVPN_GREMLIN -#include <openvpn/transport/gremlin.hpp> -#endif - -#if defined(OPENVPN_PLATFORM_ANDROID) -#include <openvpn/client/cliemuexr.hpp> -#endif - -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) -#include <openvpn/transport/client/extern/config.hpp> -#include <openvpn/transport/client/extern/fw.hpp> -#endif - -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) -// requires that client implements ExternalTun::Factory::new_tun_factory -#include <openvpn/tun/extern/config.hpp> -#elif defined(USE_TUN_BUILDER) -#include <openvpn/tun/builder/client.hpp> -#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL) -#include <openvpn/tun/linux/client/tuncli.hpp> -#ifdef OPENVPN_COMMAND_AGENT -#include <openvpn/client/unix/cmdagent.hpp> -#endif -#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL) -#include <openvpn/tun/mac/client/tuncli.hpp> -#include <openvpn/apple/maclife.hpp> -#ifdef OPENVPN_COMMAND_AGENT -#include <openvpn/client/unix/cmdagent.hpp> -#endif -#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL) -#include <openvpn/tun/win/client/tuncli.hpp> -#ifdef OPENVPN_COMMAND_AGENT -#include <openvpn/client/win/cmdagent.hpp> -#endif -#else -#include <openvpn/tun/client/tunnull.hpp> -#endif - -#ifdef PRIVATE_TUNNEL_PROXY -#include <openvpn/pt/ptproxy.hpp> -#endif - -#if defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO) -#include <openvpn/dco/dcocli.hpp> -#endif - -#ifndef OPENVPN_UNUSED_OPTIONS -#define OPENVPN_UNUSED_OPTIONS "UNUSED OPTIONS" -#endif - -namespace openvpn { - - class ClientOptions : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<ClientOptions> Ptr; - - typedef ClientProto::Session Client; - - struct Config - { - std::string gui_version; - std::string sso_methods; - std::string server_override; - std::string port_override; - std::string hw_addr_override; - std::string platform_version; - Protocol proto_override; - IPv6Setting ipv6; - int conn_timeout = 0; - SessionStats::Ptr cli_stats; - ClientEvent::Queue::Ptr cli_events; - ProtoContextOptions::Ptr proto_context_options; - HTTPProxyTransport::Options::Ptr http_proxy_options; - bool alt_proxy = false; - bool dco = false; - bool echo = false; - bool info = false; - bool tun_persist = false; - bool wintun = false; - bool google_dns_fallback = false; - bool synchronous_dns_lookup = false; - std::string private_key_password; - bool disable_client_cert = false; - int ssl_debug_level = 0; - int default_key_direction = -1; - bool autologin_sessions = false; - bool retry_on_auth_failed = false; - bool allow_local_lan_access = false; - std::string tls_version_min_override; - std::string tls_cert_profile_override; - std::string tls_cipher_list; - std::string tls_ciphersuite_list; - PeerInfo::Set::Ptr extra_peer_info; -#ifdef OPENVPN_GREMLIN - Gremlin::Config::Ptr gremlin_config; -#endif - Stop* stop = nullptr; - - // callbacks -- must remain in scope for lifetime of ClientOptions object - ExternalPKIBase* external_pki = nullptr; - SocketProtect* socket_protect = nullptr; - ReconnectNotify* reconnect_notify = nullptr; - RemoteList::RemoteOverride* remote_override = nullptr; - -#if defined(USE_TUN_BUILDER) - TunBuilderBase* builder = nullptr; -#endif - -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) - ExternalTun::Factory* extern_tun_factory = nullptr; -#endif - -#if defined(OPENVPN_EXTERNAL_TRANSPORT_FACTORY) - ExternalTransport::Factory* extern_transport_factory = nullptr; -#endif - }; - - ClientOptions(const OptionList& opt, // only needs to remain in scope for duration of constructor call - const Config& config) - : server_addr_float(false), - socket_protect(config.socket_protect), - reconnect_notify(config.reconnect_notify), - cli_stats(config.cli_stats), - cli_events(config.cli_events), - server_poll_timeout_(10), - server_override(config.server_override), - port_override(config.port_override), - proto_override(config.proto_override), - conn_timeout_(config.conn_timeout), - tcp_queue_limit(64), - proto_context_options(config.proto_context_options), - http_proxy_options(config.http_proxy_options), -#ifdef OPENVPN_GREMLIN - gremlin_config(config.gremlin_config), -#endif - echo(config.echo), - info(config.info), - autologin(false), - autologin_sessions(false), - creds_locked(false), - asio_work_always_on_(false), - synchronous_dns_lookup(false), - retry_on_auth_failed_(config.retry_on_auth_failed) -#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY - ,extern_transport_factory(config.extern_transport_factory) -#endif - { - // parse general client options - const ParseClientConfig pcc(opt); - - // creds - userlocked_username = pcc.userlockedUsername(); - autologin = pcc.autologin(); - autologin_sessions = (autologin && config.autologin_sessions); - - // digest factory - DigestFactory::Ptr digest_factory(new CryptoDigestFactory<SSLLib::CryptoAPI>()); - - // initialize RNG/PRNG - rng.reset(new SSLLib::RandomAPI(false)); - prng.reset(new SSLLib::RandomAPI(true)); - -#if (defined(ENABLE_KOVPN) || defined(ENABLE_OVPNDCO)) && !defined(OPENVPN_FORCE_TUN_NULL) && !defined(OPENVPN_EXTERNAL_TUN_FACTORY) - if (config.dco) - dco = DCOTransport::new_controller(); -#else - if (config.dco) - throw option_error("DCO not enabled in this build"); -#endif - - // frame - const unsigned int tun_mtu = parse_tun_mtu(opt, 0); // get tun-mtu parameter from config - const MSSCtrlParms mc(opt); - frame = frame_init(true, tun_mtu, mc.mssfix_ctrl, true); - - // TCP queue limit - tcp_queue_limit = opt.get_num<decltype(tcp_queue_limit)>("tcp-queue-limit", 1, tcp_queue_limit, 1, 65536); - - // route-nopull - pushed_options_filter.reset(new PushedOptionsFilter(opt.exists("route-nopull"))); - - // OpenVPN Protocol context (including SSL) - cp_main = proto_config(opt, config, pcc, false); - cp_relay = proto_config(opt, config, pcc, true); // may be null - layer = cp_main->layer; - -#ifdef PRIVATE_TUNNEL_PROXY - if (config.alt_proxy && !dco) - alt_proxy = PTProxy::new_proxy(opt, rng); -#endif - - // If HTTP proxy parameters are not supplied by API, try to get them from config - if (!http_proxy_options) - http_proxy_options = HTTPProxyTransport::Options::parse(opt); - - // load remote list - if (config.remote_override) - remote_list.reset(new RemoteList(config.remote_override)); - else - remote_list.reset(new RemoteList(opt, "", RemoteList::WARN_UNSUPPORTED, nullptr)); - if (!remote_list->defined()) - throw option_error("no remote option specified"); - - // Set remote list prng - remote_list->set_random(prng); - - // If running in tun_persist mode, we need to do basic DNS caching so that - // we can avoid emitting DNS requests while the tunnel is blocked during - // reconnections. - remote_list->set_enable_cache(config.tun_persist); - - // process server/port overrides - remote_list->set_server_override(config.server_override); - remote_list->set_port_override(config.port_override); - - // process protocol override, should be called after set_enable_cache - remote_list->handle_proto_override(config.proto_override, - http_proxy_options || (alt_proxy && alt_proxy->requires_tcp())); - - // process remote-random - if (opt.exists("remote-random")) - remote_list->randomize(); - - // get "float" option - server_addr_float = opt.exists("float"); - - // special remote cache handling for proxies - if (alt_proxy) - { - remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy - alt_proxy->set_enable_cache(config.tun_persist); - } - else if (http_proxy_options) - { - remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy - http_proxy_options->proxy_server_set_enable_cache(config.tun_persist); - } - - // secret option not supported - if (opt.exists("secret")) - throw option_error("sorry, static key encryption mode (non-SSL/TLS) is not supported"); - - // fragment option not supported - if (opt.exists("fragment")) - throw option_error("sorry, 'fragment' directive is not supported, nor is connecting to a server that uses 'fragment' directive"); - -#ifdef OPENVPN_PLATFORM_UWP - // workaround for OVPN3-62 Busy loop in win_event.hpp - asio_work_always_on_ = true; -#endif - - synchronous_dns_lookup = config.synchronous_dns_lookup; - -#ifdef OPENVPN_TLS_LINK - if (opt.exists("tls-ca")) - { - tls_ca = opt.cat("tls-ca"); - } -#endif - - // init transport config - const std::string session_name = load_transport_config(); - - // initialize tun/tap - if (dco) - { - DCO::TunConfig tunconf; -#if defined(USE_TUN_BUILDER) - dco->builder = config.builder; -#endif - tunconf.tun_prop.layer = layer; - tunconf.tun_prop.session_name = session_name; - if (tun_mtu) - tunconf.tun_prop.mtu = tun_mtu; - tunconf.tun_prop.google_dns_fallback = config.google_dns_fallback; - tunconf.tun_prop.remote_list = remote_list; - tunconf.stop = config.stop; - tun_factory = dco->new_tun_factory(tunconf, opt); - } - else - { -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) - { - ExternalTun::Config tunconf; - tunconf.tun_prop.layer = layer; - tunconf.tun_prop.session_name = session_name; - tunconf.tun_prop.google_dns_fallback = config.google_dns_fallback; - if (tun_mtu) - tunconf.tun_prop.mtu = tun_mtu; - tunconf.frame = frame; - tunconf.stats = cli_stats; - tunconf.tun_prop.remote_list = remote_list; - tunconf.tun_persist = config.tun_persist; - tunconf.stop = config.stop; - tun_factory.reset(config.extern_tun_factory->new_tun_factory(tunconf, opt)); - if (!tun_factory) - throw option_error("OPENVPN_EXTERNAL_TUN_FACTORY: no tun factory"); - } -#elif defined(USE_TUN_BUILDER) - { - TunBuilderClient::ClientConfig::Ptr tunconf = TunBuilderClient::ClientConfig::new_obj(); - tunconf->builder = config.builder; - tunconf->tun_prop.session_name = session_name; - tunconf->tun_prop.google_dns_fallback = config.google_dns_fallback; - tunconf->tun_prop.allow_local_lan_access = config.allow_local_lan_access; - if (tun_mtu) - tunconf->tun_prop.mtu = tun_mtu; - tunconf->frame = frame; - tunconf->stats = cli_stats; - tunconf->tun_prop.remote_list = remote_list; - tun_factory = tunconf; -#if defined(OPENVPN_PLATFORM_IPHONE) - tunconf->retain_sd = true; - tunconf->tun_prefix = true; - if (config.tun_persist) - tunconf->tun_prop.remote_bypass = true; -#endif -#if defined(OPENVPN_PLATFORM_ANDROID) - // Android VPN API doesn't support excluded routes, so we must emulate them - tunconf->eer_factory.reset(new EmulateExcludeRouteFactoryImpl(false)); -#endif -#if defined(OPENVPN_PLATFORM_MAC) - tunconf->tun_prefix = true; -#endif - if (config.tun_persist) - tunconf->tun_persist.reset(new TunBuilderClient::TunPersist(true, tunconf->retain_sd, config.builder)); - tun_factory = tunconf; - } -#elif defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_FORCE_TUN_NULL) - { - TunLinux::ClientConfig::Ptr tunconf = TunLinux::ClientConfig::new_obj(); - tunconf->tun_prop.layer = layer; - tunconf->tun_prop.session_name = session_name; - if (tun_mtu) - tunconf->tun_prop.mtu = tun_mtu; - tunconf->tun_prop.google_dns_fallback = config.google_dns_fallback; - tunconf->tun_prop.remote_list = remote_list; - tunconf->frame = frame; - tunconf->stats = cli_stats; - if (config.tun_persist) - tunconf->tun_persist.reset(new TunLinux::TunPersist(true, false, nullptr)); - tunconf->load(opt); - tun_factory = tunconf; - } -#elif defined(OPENVPN_PLATFORM_MAC) && !defined(OPENVPN_FORCE_TUN_NULL) - { - TunMac::ClientConfig::Ptr tunconf = TunMac::ClientConfig::new_obj(); - tunconf->tun_prop.layer = layer; - tunconf->tun_prop.session_name = session_name; - tunconf->tun_prop.google_dns_fallback = config.google_dns_fallback; - if (tun_mtu) - tunconf->tun_prop.mtu = tun_mtu; - tunconf->frame = frame; - tunconf->stats = cli_stats; - tunconf->stop = config.stop; - if (config.tun_persist) - { - tunconf->tun_persist.reset(new TunMac::TunPersist(true, false, nullptr)); -#ifndef OPENVPN_COMMAND_AGENT - /* remote_list is required by remote_bypass to work */ - tunconf->tun_prop.remote_bypass = true; - tunconf->tun_prop.remote_list = remote_list; -#endif - } - client_lifecycle.reset(new MacLifeCycle); -#ifdef OPENVPN_COMMAND_AGENT - tunconf->tun_setup_factory = UnixCommandAgent::new_agent(opt); -#endif - tun_factory = tunconf; - } -#elif defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_FORCE_TUN_NULL) - { - TunWin::ClientConfig::Ptr tunconf = TunWin::ClientConfig::new_obj(); - tunconf->tun_prop.layer = layer; - tunconf->tun_prop.session_name = session_name; - tunconf->tun_prop.google_dns_fallback = config.google_dns_fallback; - if (tun_mtu) - tunconf->tun_prop.mtu = tun_mtu; - tunconf->frame = frame; - tunconf->stats = cli_stats; - tunconf->stop = config.stop; - tunconf->wintun = config.wintun; - if (config.tun_persist) - { - tunconf->tun_persist.reset(new TunWin::TunPersist(true, false, nullptr)); -#ifndef OPENVPN_COMMAND_AGENT - /* remote_list is required by remote_bypass to work */ - tunconf->tun_prop.remote_bypass = true; - tunconf->tun_prop.remote_list = remote_list; -#endif - } -#ifdef OPENVPN_COMMAND_AGENT - tunconf->tun_setup_factory = WinCommandAgent::new_agent(opt); -#endif - tun_factory = tunconf; - } -#else - { - TunNull::ClientConfig::Ptr tunconf = TunNull::ClientConfig::new_obj(); - tunconf->frame = frame; - tunconf->stats = cli_stats; - tun_factory = tunconf; - } -#endif - } - - // The Core Library itself does not handle TAP/OSI_LAYER_2 currently, - // so we bail out early whenever someone tries to use TAP configurations - if (layer == Layer(Layer::OSI_LAYER_2)) - throw ErrorCode(Error::TAP_NOT_SUPPORTED, true, "OSI layer 2 tunnels are not currently supported"); - - // server-poll-timeout - { - const Option *o = opt.get_ptr("server-poll-timeout"); - if (o) - server_poll_timeout_ = parse_number_throw<unsigned int>(o->get(1, 16), "server-poll-timeout"); - } - - // create default creds object in case submit_creds is not called, - // and populate it with embedded creds, if available - { - ClientCreds::Ptr cc = new ClientCreds(); - if (pcc.hasEmbeddedPassword()) - { - cc->set_username(userlocked_username); - cc->set_password(pcc.embeddedPassword()); - cc->enable_password_cache(true); - cc->set_replace_password_with_session_id(true); - submit_creds(cc); - creds_locked = true; - } - else if (autologin_sessions) - { - // autologin sessions require replace_password_with_session_id - cc->set_replace_password_with_session_id(true); - submit_creds(cc); - creds_locked = true; - } - else - { - submit_creds(cc); - } - } - - // configure push_base, a set of base options that will be combined with - // options pushed by server. - { - push_base.reset(new PushOptionsBase()); - - // base options where multiple options of the same type can aggregate - push_base->multi.extend(opt, "route"); - push_base->multi.extend(opt, "route-ipv6"); - push_base->multi.extend(opt, "redirect-gateway"); - push_base->multi.extend(opt, "redirect-private"); - push_base->multi.extend(opt, "dhcp-option"); - - // base options where only a single instance of each option makes sense - push_base->singleton.extend(opt, "redirect-dns"); - push_base->singleton.extend(opt, "inactive"); - push_base->singleton.extend(opt, "route-metric"); - - // IPv6 - { - const unsigned int n = push_base->singleton.extend(opt, "block-ipv6"); - if (!n && config.ipv6() == IPv6Setting::No) - push_base->singleton.emplace_back("block-ipv6"); - } - } - - // show unused options - opt.show_unused_options(OPENVPN_UNUSED_OPTIONS); - } - - static PeerInfo::Set::Ptr build_peer_info(const Config& config, const ParseClientConfig& pcc, const bool autologin_sessions) - { - PeerInfo::Set::Ptr pi(new PeerInfo::Set); - - // IPv6 - if (config.ipv6() == IPv6Setting::No) - pi->emplace_back("IV_IPv6", "0"); - else if (config.ipv6() == IPv6Setting::Yes) - pi->emplace_back("IV_IPv6", "1"); - - // autologin sessions - if (autologin_sessions) - pi->emplace_back("IV_AUTO_SESS", "1"); - - // Config::peerInfo - pi->append_foreign_set_ptr(config.extra_peer_info.get()); - - // setenv UV_ options - pi->append_foreign_set_ptr(pcc.peerInfoUV()); - - // UI version - if (!config.gui_version.empty()) - pi->emplace_back("IV_GUI_VER", config.gui_version); - - // Supported SSO methods - if (!config.sso_methods.empty()) - pi->emplace_back("IV_SSO", config.sso_methods); - - // MAC address - if (pcc.pushPeerInfo()) - { - std::string hwaddr = get_hwaddr(); - if (!config.hw_addr_override.empty()) - pi->emplace_back("IV_HWADDR", config.hw_addr_override); - else if (!hwaddr.empty()) - pi->emplace_back("IV_HWADDR", hwaddr); - pi->emplace_back ("IV_SSL", get_ssl_library_version()); - - if (!config.platform_version.empty()) - pi->emplace_back("IV_PLAT_VER", config.platform_version); - } - return pi; - } - - void next() - { - bool omit_next = false; - - if (alt_proxy) - omit_next = alt_proxy->next(); - if (!omit_next) - remote_list->next(); - load_transport_config(); - } - - void remote_reset_cache_item() - { - remote_list->reset_cache_item(); - } - - bool pause_on_connection_timeout() - { - if (reconnect_notify) - return reconnect_notify->pause_on_connection_timeout(); - else - return false; - } - - bool retry_on_auth_failed() const - { - return retry_on_auth_failed_; - } - - Client::Config::Ptr client_config(const bool relay_mode) - { - Client::Config::Ptr cli_config = new Client::Config; - - // Copy ProtoConfig so that modifications due to server push will - // not persist across client instantiations. - cli_config->proto_context_config.reset(new Client::ProtoConfig(proto_config_cached(relay_mode))); - - cli_config->proto_context_options = proto_context_options; - cli_config->push_base = push_base; - cli_config->transport_factory = transport_factory; - cli_config->tun_factory = tun_factory; - cli_config->cli_stats = cli_stats; - cli_config->cli_events = cli_events; - cli_config->creds = creds; - cli_config->pushed_options_filter = pushed_options_filter; - cli_config->tcp_queue_limit = tcp_queue_limit; - cli_config->echo = echo; - cli_config->info = info; - cli_config->autologin_sessions = autologin_sessions; - return cli_config; - } - - bool need_creds() const - { - return !autologin; - } - - void submit_creds(const ClientCreds::Ptr& creds_arg) - { - if (creds_arg && !creds_locked) - { - // if no username is defined in creds and userlocked_username is defined - // in profile, set the creds username to be the userlocked_username - if (!creds_arg->username_defined() && !userlocked_username.empty()) - creds_arg->set_username(userlocked_username); - creds = creds_arg; - } - } - - bool server_poll_timeout_enabled() const - { - return !http_proxy_options; - } - - Time::Duration server_poll_timeout() const - { - return Time::Duration::seconds(server_poll_timeout_); - } - - SessionStats& stats() { return *cli_stats; } - const SessionStats::Ptr& stats_ptr() const { return cli_stats; } - ClientEvent::Queue& events() { return *cli_events; } - ClientLifeCycle* lifecycle() { return client_lifecycle.get(); } - - int conn_timeout() const { return conn_timeout_; } - - bool asio_work_always_on() const { return asio_work_always_on_; } - - RemoteList::Ptr remote_list_precache() const - { - RemoteList::Ptr r; - if (alt_proxy) - { - alt_proxy->precache(r); - if (r) - return r; - } - if (http_proxy_options) - { - http_proxy_options->proxy_server_precache(r); - if (r) - return r; - } - return remote_list; - } - - void update_now() - { - now_.update(); - } - - void finalize(const bool disconnected) - { - if (tun_factory) - tun_factory->finalize(disconnected); - } - - private: - Client::ProtoConfig& proto_config_cached(const bool relay_mode) - { - if (relay_mode && cp_relay) - return *cp_relay; - else - return *cp_main; - } - - Client::ProtoConfig::Ptr proto_config(const OptionList& opt, - const Config& config, - const ParseClientConfig& pcc, - const bool relay_mode) - { - // relay mode is null unless one of the below directives is defined - if (relay_mode && !opt.exists("relay-mode")) - return Client::ProtoConfig::Ptr(); - - // load flags - unsigned int lflags = SSLConfigAPI::LF_PARSE_MODE; - if (relay_mode) - lflags |= SSLConfigAPI::LF_RELAY_MODE; - - // client SSL config - SSLLib::SSLAPI::Config::Ptr cc(new SSLLib::SSLAPI::Config()); - cc->set_external_pki_callback(config.external_pki); - cc->set_frame(frame); - cc->set_flags(SSLConst::LOG_VERIFY_STATUS); - cc->set_debug_level(config.ssl_debug_level); - cc->set_rng(rng); - cc->set_local_cert_enabled(pcc.clientCertEnabled() && !config.disable_client_cert); - cc->set_private_key_password(config.private_key_password); - cc->load(opt, lflags); - cc->set_tls_version_min_override(config.tls_version_min_override); - cc->set_tls_cert_profile_override(config.tls_cert_profile_override); - cc->set_tls_cipher_list(config.tls_cipher_list); - cc->set_tls_ciphersuite_list(config.tls_ciphersuite_list); - if (!cc->get_mode().is_client()) - throw option_error("only client configuration supported"); - - // client ProtoContext config - Client::ProtoConfig::Ptr cp(new Client::ProtoConfig()); - cp->relay_mode = relay_mode; - cp->dc.set_factory(new CryptoDCSelect<SSLLib::CryptoAPI>(frame, cli_stats, prng)); - cp->dc_deferred = true; // defer data channel setup until after options pull - cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>()); - cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>()); - cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory()); - cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>()); - cp->ssl_factory = cc->new_factory(); - cp->load(opt, *proto_context_options, config.default_key_direction, false); - cp->set_xmit_creds(!autologin || pcc.hasEmbeddedPassword() || autologin_sessions); - cp->extra_peer_info = build_peer_info(config, pcc, autologin_sessions); - cp->frame = frame; - cp->now = &now_; - cp->rng = rng; - cp->prng = prng; - - return cp; - } - - std::string load_transport_config() - { - // get current transport protocol - const Protocol& transport_protocol = remote_list->current_transport_protocol(); - - // If we are connecting over a proxy, and TCP protocol is required, but current - // transport protocol is NOT TCP, we will throw an internal error because this - // should have been caught earlier in RemoteList::handle_proto_override. - - // construct transport object -#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY - ExternalTransport::Config transconf; - transconf.remote_list = remote_list; - transconf.frame = frame; - transconf.stats = cli_stats; - transconf.socket_protect = socket_protect; - transconf.server_addr_float = server_addr_float; - transconf.synchronous_dns_lookup = synchronous_dns_lookup; - transconf.protocol = transport_protocol; - transport_factory = extern_transport_factory->new_transport_factory(transconf); -#ifdef OPENVPN_GREMLIN - udpconf->gremlin_config = gremlin_config; -#endif - -#else - if (dco) - { - DCO::TransportConfig transconf; - transconf.protocol = transport_protocol; - transconf.remote_list = remote_list; - transconf.frame = frame; - transconf.stats = cli_stats; - transconf.server_addr_float = server_addr_float; - transconf.socket_protect = socket_protect; - transport_factory = dco->new_transport_factory(transconf); - } - else if (alt_proxy) - { - if (alt_proxy->requires_tcp() && !transport_protocol.is_tcp()) - throw option_error("internal error: no TCP server entries for " + alt_proxy->name() + " transport"); - AltProxy::Config conf; - conf.remote_list = remote_list; - conf.frame = frame; - conf.stats = cli_stats; - conf.digest_factory.reset(new CryptoDigestFactory<SSLLib::CryptoAPI>()); - conf.socket_protect = socket_protect; - conf.rng = rng; - transport_factory = alt_proxy->new_transport_client_factory(conf); - } - else if (http_proxy_options) - { - if (!transport_protocol.is_tcp()) - throw option_error("internal error: no TCP server entries for HTTP proxy transport"); - - // HTTP Proxy transport - HTTPProxyTransport::ClientConfig::Ptr httpconf = HTTPProxyTransport::ClientConfig::new_obj(); - httpconf->remote_list = remote_list; - httpconf->frame = frame; - httpconf->stats = cli_stats; - httpconf->digest_factory.reset(new CryptoDigestFactory<SSLLib::CryptoAPI>()); - httpconf->socket_protect = socket_protect; - httpconf->http_proxy_options = http_proxy_options; - httpconf->rng = rng; -#ifdef PRIVATE_TUNNEL_PROXY - httpconf->skip_html = true; -#endif - transport_factory = httpconf; - } - else - { - if (transport_protocol.is_udp()) - { - // UDP transport - UDPTransport::ClientConfig::Ptr udpconf = UDPTransport::ClientConfig::new_obj(); - udpconf->remote_list = remote_list; - udpconf->frame = frame; - udpconf->stats = cli_stats; - udpconf->socket_protect = socket_protect; - udpconf->server_addr_float = server_addr_float; -#ifdef OPENVPN_GREMLIN - udpconf->gremlin_config = gremlin_config; -#endif - transport_factory = udpconf; - } - else if (transport_protocol.is_tcp() -#ifdef OPENVPN_TLS_LINK - || transport_protocol.is_tls() -#endif - ) - { - // TCP transport - TCPTransport::ClientConfig::Ptr tcpconf = TCPTransport::ClientConfig::new_obj(); - tcpconf->remote_list = remote_list; - tcpconf->frame = frame; - tcpconf->stats = cli_stats; - tcpconf->socket_protect = socket_protect; -#ifdef OPENVPN_TLS_LINK - if (transport_protocol.is_tls()) - tcpconf->use_tls = true; - tcpconf->tls_ca = tls_ca; -#endif -#ifdef OPENVPN_GREMLIN - tcpconf->gremlin_config = gremlin_config; -#endif - transport_factory = tcpconf; - } - else - throw option_error("internal error: unknown transport protocol"); - } -#endif // OPENVPN_EXTERNAL_TRANSPORT_FACTORY - return remote_list->current_server_host(); - } - - Time now_; // current time - RandomAPI::Ptr rng; - RandomAPI::Ptr prng; - Frame::Ptr frame; - Layer layer; - Client::ProtoConfig::Ptr cp_main; - Client::ProtoConfig::Ptr cp_relay; - RemoteList::Ptr remote_list; - bool server_addr_float; - TransportClientFactory::Ptr transport_factory; - TunClientFactory::Ptr tun_factory; - SocketProtect* socket_protect; - ReconnectNotify* reconnect_notify; - SessionStats::Ptr cli_stats; - ClientEvent::Queue::Ptr cli_events; - ClientCreds::Ptr creds; - unsigned int server_poll_timeout_; - std::string server_override; - std::string port_override; - Protocol proto_override; - int conn_timeout_; - unsigned int tcp_queue_limit; - ProtoContextOptions::Ptr proto_context_options; - HTTPProxyTransport::Options::Ptr http_proxy_options; -#ifdef OPENVPN_GREMLIN - Gremlin::Config::Ptr gremlin_config; -#endif - std::string userlocked_username; - bool echo; - bool info; - bool autologin; - bool autologin_sessions; - bool creds_locked; - bool asio_work_always_on_; - bool synchronous_dns_lookup; - bool retry_on_auth_failed_; - PushOptionsBase::Ptr push_base; - OptionList::FilterBase::Ptr pushed_options_filter; - ClientLifeCycle::Ptr client_lifecycle; - AltProxy::Ptr alt_proxy; - DCO::Ptr dco; -#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY - ExternalTransport::Factory* extern_transport_factory; -#endif -#ifdef OPENVPN_TLS_LINK - std::string tls_ca; -#endif - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/cliopthelper.hpp b/Sources/OpenVPN3/openvpn/client/cliopthelper.hpp deleted file mode 100644 index 64220a7..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliopthelper.hpp +++ /dev/null @@ -1,732 +0,0 @@ -// 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-2020 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/>. - -// A preliminary parser for OpenVPN client configuration files. - -#ifndef OPENVPN_CLIENT_CLIOPTHELPER_H -#define OPENVPN_CLIENT_CLIOPTHELPER_H - -#include <vector> -#include <string> -#include <sstream> -#include <utility> - -#ifdef HAVE_CONFIG_JSONCPP -#include "json/json.h" -#endif /* HAVE_CONFIG_JSONCPP */ - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/userpass.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/client/cliconstants.hpp> -#include <openvpn/ssl/peerinfo.hpp> -#include <openvpn/ssl/proto.hpp> -#include <openvpn/ssl/proto_context_options.hpp> -#include <openvpn/ssl/sslchoose.hpp> - -namespace openvpn { - class ParseClientConfig { - public: - struct ServerEntry { - std::string server; - std::string friendlyName; - }; - - struct ServerList : public std::vector<ServerEntry> - { - }; - - struct RemoteItem { - std::string host; - std::string port; - std::string proto; - }; - - ParseClientConfig() - { - reset_pod(); - } - - ParseClientConfig(const OptionList& options) - { - try { - // reset POD types - reset_pod(); - - // limits - const size_t max_server_list_size = ProfileParseLimits::MAX_SERVER_LIST_SIZE; - - // setenv UV_x - PeerInfo::Set::Ptr peer_info_uv(new PeerInfo::Set); - - // process setenv directives - { - const OptionList::IndexList* se = options.get_index_ptr("setenv"); - if (se) - { - for (OptionList::IndexList::const_iterator i = se->begin(); i != se->end(); ++i) - { - const Option& o = options[*i]; - o.touch(); - const std::string arg1 = o.get_optional(1, 256); - - // server-locked profiles not supported - if (arg1 == "GENERIC_CONFIG") - { - error_ = true; - message_ = "ERR_PROFILE_SERVER_LOCKED_UNSUPPORTED: server locked profiles are currently unsupported"; - return; - } - else if (arg1 == "ALLOW_PASSWORD_SAVE") - allowPasswordSave_ = parse_bool(o, "setenv ALLOW_PASSWORD_SAVE", 2); - else if (arg1 == "CLIENT_CERT") - clientCertEnabled_ = parse_bool(o, "setenv CLIENT_CERT", 2); - else if (arg1 == "USERNAME") - userlockedUsername_ = o.get(2, 256); - else if (arg1 == "FRIENDLY_NAME") - friendlyName_ = o.get(2, 256); - else if (arg1 == "SERVER") - { - const std::string& serv = o.get(2, 256); - std::vector<std::string> slist = Split::by_char<std::vector<std::string>, NullLex, Split::NullLimit>(serv, '/', 0, 1); - ServerEntry se; - if (slist.size() == 1) - { - se.server = slist[0]; - se.friendlyName = slist[0]; - } - else if (slist.size() == 2) - { - se.server = slist[0]; - se.friendlyName = slist[1]; - } - if (!se.server.empty() && !se.friendlyName.empty() && serverList_.size() < max_server_list_size) - serverList_.push_back(std::move(se)); - } - else if (arg1 == "PUSH_PEER_INFO") - pushPeerInfo_ = true; - else if (string::starts_with(arg1, "UV_") && arg1.length() >= 4 && string::is_word(arg1)) - { - const std::string value = o.get_optional(2, 256); - if (string::is_printable(value)) - peer_info_uv->emplace_back(arg1, value); - } - } - } - } - - // Alternative to "setenv CLIENT_CERT 0". Note that as of OpenVPN 2.3, this option - // is only supported server-side, so this extends its meaning into the client realm. - if (options.exists("client-cert-not-required")) - clientCertEnabled_ = false; - - // userlocked username - { - const Option* o = options.get_ptr("USERNAME"); - if (o) - userlockedUsername_ = o->get(1, 256); - } - - // userlocked username/password via <auth-user-pass> - std::vector<std::string> user_pass; - const bool auth_user_pass = parse_auth_user_pass(options, &user_pass); - if (auth_user_pass && user_pass.size() >= 1) - { - userlockedUsername_ = user_pass[0]; - if (user_pass.size() >= 2) - { - hasEmbeddedPassword_ = true; - embeddedPassword_ = user_pass[1]; - } - } - - // External PKI - externalPki_ = (clientCertEnabled_ && is_external_pki(options)); - - // allow password save - { - const Option* o = options.get_ptr("allow-password-save"); - if (o) - allowPasswordSave_ = parse_bool(*o, "allow-password-save", 1); - } - - // autologin - { - autologin_ = is_autologin(options, auth_user_pass, user_pass); - if (autologin_) - allowPasswordSave_ = false; // saving passwords is incompatible with autologin - } - - // static challenge - { - const Option* o = options.get_ptr("static-challenge"); - if (o) - { - staticChallenge_ = o->get(1, 256); - if (o->get_optional(2, 16) == "1") - staticChallengeEcho_ = true; - } - } - - // validate remote list - remoteList.reset(new RemoteList(options, "", 0, nullptr)); - { - const RemoteList::Item* ri = remoteList->first_item(); - if (ri) - { - firstRemoteListItem_.host = ri->server_host; - firstRemoteListItem_.port = ri->server_port; - if (ri->transport_protocol.is_udp()) - firstRemoteListItem_.proto = "udp"; - else if (ri->transport_protocol.is_tcp()) - firstRemoteListItem_.proto = "tcp-client"; - } - } - - // determine if private key is encrypted - if (!externalPki_) - { - const Option* o = options.get_ptr("key"); - if (o) - { - const std::string& key_txt = o->get(1, Option::MULTILINE); - privateKeyPasswordRequired_ = ( - key_txt.find("-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\n") != std::string::npos - || key_txt.find("-----BEGIN EC PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\n") != std::string::npos - || key_txt.find("-----BEGIN ENCRYPTED PRIVATE KEY-----") != std::string::npos - ); - } - } - - // profile name - { - const Option* o = options.get_ptr("PROFILE"); - if (o) - { - // take PROFILE substring up to '/' - const std::string& pn = o->get(1, 256); - const size_t slashpos = pn.find('/'); - if (slashpos != std::string::npos) - profileName_ = pn.substr(0, slashpos); - else - profileName_ = pn; - } - else - { - if (remoteList) - profileName_ = remoteList->first_server_host(); - } - - // windows-driver - { - const Option* o = options.get_ptr("windows-driver"); - if (o) - { - windowsDriver_ = o->get(1, 256); - } - } - } - - // friendly name - { - const Option* o = options.get_ptr("FRIENDLY_NAME"); - if (o) - friendlyName_ = o->get(1, 256); - } - - // server list - { - const Option* o = options.get_ptr("HOST_LIST"); - if (o) - { - SplitLines in(o->get(1, 4096 | Option::MULTILINE), 0); - while (in(true)) - { - ServerEntry se; - se.server = in.line_ref(); - se.friendlyName = se.server; - Option::validate_string("HOST_LIST server", se.server, 256); - Option::validate_string("HOST_LIST friendly name", se.friendlyName, 256); - if (!se.server.empty() && !se.friendlyName.empty() && serverList_.size() < max_server_list_size) - serverList_.push_back(std::move(se)); - } - } - } - - // push-peer-info - { - if (options.exists("push-peer-info")) - pushPeerInfo_ = true; - if (pushPeerInfo_) - peerInfoUV_ = peer_info_uv; - } - - // dev name - { - const Option *o = options.get_ptr("dev"); - if (o) - { - dev = o->get(1, 256); - } - } - - // protocol configuration - { - protoConfig.reset(new ProtoContext::Config()); - protoConfig->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>()); - protoConfig->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>()); - protoConfig->load(options, ProtoContextOptions(), -1, false); - } - - unsigned int lflags = SSLConfigAPI::LF_PARSE_MODE; - - // ssl lib configuration - try { - sslConfig.reset(new SSLLib::SSLAPI::Config()); - sslConfig->load(options, lflags); - } catch (...) { - sslConfig.reset(); - } - } - catch (const option_error& e) - { - error_ = true; - message_ = Unicode::utf8_printable<std::string>(std::string("ERR_PROFILE_OPTION: ") + e.what(), 256); - } - catch (const std::exception& e) - { - error_ = true; - message_ = Unicode::utf8_printable<std::string>(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); - } - } - - static ParseClientConfig parse(const std::string& content) - { - return parse(content, nullptr); - } - - static ParseClientConfig parse(const std::string& content, OptionList::KeyValueList* content_list) - { - OptionList options; - return parse(content, content_list, options); - } - - static ParseClientConfig parse(const std::string& content, - OptionList::KeyValueList* content_list, - OptionList& options) - { - try { - OptionList::Limits limits("profile is too large", - ProfileParseLimits::MAX_PROFILE_SIZE, - ProfileParseLimits::OPT_OVERHEAD, - ProfileParseLimits::TERM_OVERHEAD, - ProfileParseLimits::MAX_LINE_SIZE, - ProfileParseLimits::MAX_DIRECTIVE_SIZE); - options.clear(); - options.parse_from_config(content, &limits); - options.parse_meta_from_config(content, "OVPN_ACCESS_SERVER", &limits); - if (content_list) - { - content_list->preprocess(); - options.parse_from_key_value_list(*content_list, &limits); - } - process_setenv_opt(options); - options.update_map(); - - // add in missing options - bool added = false; - - // client - if (!options.exists("client")) - { - Option opt; - opt.push_back("client"); - options.push_back(std::move(opt)); - added = true; - } - - // dev - if (!options.exists("dev")) - { - Option opt; - opt.push_back("dev"); - opt.push_back("tun"); - options.push_back(std::move(opt)); - added = true; - } - if (added) - options.update_map(); - - return ParseClientConfig(options); - } - catch (const std::exception& e) - { - ParseClientConfig ret; - ret.error_ = true; - ret.message_ = Unicode::utf8_printable<std::string>(std::string("ERR_PROFILE_GENERIC: ") + e.what(), 256); - return ret; - } - } - - // true if error - bool error() const { return error_; } - - // if error, message given here - const std::string& message() const { return message_; } - - // this username must be used with profile - const std::string& userlockedUsername() const { return userlockedUsername_; } - - // profile name of config - const std::string& profileName() const { return profileName_; } - - // "friendly" name of config - const std::string& friendlyName() const { return friendlyName_; } - - // true: no creds required, false: username/password required - bool autologin() const { return autologin_; } - - // profile embedded password via <auth-user-pass> - bool hasEmbeddedPassword() const { return hasEmbeddedPassword_; } - const std::string& embeddedPassword() const { return embeddedPassword_; } - - // true: no client cert/key required, false: client cert/key required - bool clientCertEnabled() const { return clientCertEnabled_; } - - // if true, this is an External PKI profile (no cert or key directives) - bool externalPki() const { return externalPki_; } - - // static challenge, may be empty, ignored if autologin - const std::string& staticChallenge() const { return staticChallenge_; } - - // true if static challenge response should be echoed to UI, ignored if autologin - bool staticChallengeEcho() const { return staticChallengeEcho_; } - - // true if this profile requires a private key password - bool privateKeyPasswordRequired() const { return privateKeyPasswordRequired_; } - - // true if user is allowed to save authentication password in UI - bool allowPasswordSave() const { return allowPasswordSave_; } - - // true if "setenv PUSH_PEER_INFO" or "push-peer-info" are defined - bool pushPeerInfo() const { return pushPeerInfo_; } - - // "setenv UV_x" directives if pushPeerInfo() is true - const PeerInfo::Set* peerInfoUV() const { return peerInfoUV_.get(); } - - // optional list of user-selectable VPN servers - const ServerList& serverList() const { return serverList_; } - - // return first remote directive in config - const RemoteItem& firstRemoteListItem() const { return firstRemoteListItem_; } - - const std::string& windowsDriver() const { return windowsDriver_; } - - std::string to_string() const - { - std::ostringstream os; - os << "user=" << userlockedUsername_ - << " pn=" << profileName_ - << " fn=" << friendlyName_ - << " auto=" << autologin_ - << " embed_pw=" << hasEmbeddedPassword_ - << " epki=" << externalPki_ - << " schal=" << staticChallenge_ - << " scecho=" << staticChallengeEcho_; - return os.str(); - } - - std::string to_string_config() const - { - std::ostringstream os; - - os << "client" << std::endl; - os << "dev " << dev << std::endl; - os << "dev-type " << protoConfig->layer.dev_type() << std::endl; - for (size_t i = 0; i < remoteList->size(); i++) - { - const RemoteList::Item& item = remoteList->get_item(i); - - os << "remote " << item.server_host << " " << item.server_port; - const char *proto = item.transport_protocol.protocol_to_string(); - if (proto) - os << " " << proto; - os << std::endl; - } - if (protoConfig->tls_crypt_context) - { - os << "<tls-crypt>" << std::endl << protoConfig->tls_key.render() << "</tls-crypt>" - << std::endl; - } - else if (protoConfig->tls_auth_context) - { - os << "<tls-auth>" << std::endl << protoConfig->tls_key.render() << "</tls-auth>" - << std::endl; - os << "key_direction " << protoConfig->key_direction << std::endl; - } - - // SSL parameters - if (sslConfig) - { - print_pem(os, "ca", sslConfig->extract_ca()); - print_pem(os, "crl", sslConfig->extract_crl()); - print_pem(os, "key", sslConfig->extract_private_key()); - print_pem(os, "cert", sslConfig->extract_cert()); - - std::vector<std::string> extra_certs = sslConfig->extract_extra_certs(); - if (extra_certs.size() > 0) - { - os << "<extra-certs>" << std::endl; - for (auto& cert : extra_certs) - { - os << cert; - } - os << "</extra-certs>" << std::endl; - } - } - - os << "cipher " << CryptoAlgs::name(protoConfig->dc.cipher(), "none") - << std::endl; - os << "auth " << CryptoAlgs::name(protoConfig->dc.digest(), "none") - << std::endl; - const char *comp = protoConfig->comp_ctx.method_to_string(); - if (comp) - os << "compress " << comp << std::endl; - os << "keepalive " << protoConfig->keepalive_ping.to_seconds() << " " - << protoConfig->keepalive_timeout.to_seconds() << std::endl; - os << "tun-mtu " << protoConfig->tun_mtu << std::endl; - os << "reneg-sec " << protoConfig->renegotiate.to_seconds() << std::endl; - - return os.str(); - } - -#ifdef HAVE_CONFIG_JSONCPP - - std::string to_json_config() const - { - std::ostringstream os; - - Json::Value root(Json::objectValue); - - root["mode"] = Json::Value("client"); - root["dev"] = Json::Value(dev); - root["dev-type"] = Json::Value(protoConfig->layer.dev_type()); - root["remotes"] = Json::Value(Json::arrayValue); - for (size_t i = 0; i < remoteList->size(); i++) - { - const RemoteList::Item& item = remoteList->get_item(i); - - Json::Value el = Json::Value(Json::objectValue); - el["address"] = Json::Value(item.server_host); - el["port"] = Json::Value((Json::UInt)std::stoi(item.server_port)); - if (item.transport_protocol() == Protocol::NONE) - el["proto"] = Json::Value("adaptive"); - else - el["proto"] = Json::Value(item.transport_protocol.str()); - - root["remotes"].append(el); - } - if (protoConfig->tls_crypt_context) - { - root["tls_wrap"] = Json::Value(Json::objectValue); - root["tls_wrap"]["mode"] = Json::Value("tls_crypt"); - root["tls_wrap"]["key"] = Json::Value(protoConfig->tls_key.render()); - } - else if (protoConfig->tls_auth_context) - { - root["tls_wrap"] = Json::Value(Json::objectValue); - root["tls_wrap"]["mode"] = Json::Value("tls_auth"); - root["tls_wrap"]["key_direction"] = Json::Value((Json::UInt)protoConfig->key_direction); - root["tls_wrap"]["key"] = Json::Value(protoConfig->tls_key.render()); - } - - // SSL parameters - if (sslConfig) - { - json_pem(root, "ca", sslConfig->extract_ca()); - json_pem(root, "crl", sslConfig->extract_crl()); - json_pem(root, "cert", sslConfig->extract_cert()); - - // JSON config is aimed to users, therefore we do not export the raw private - // key, but only some basic info - PKType::Type priv_key_type = sslConfig->private_key_type(); - if (priv_key_type != PKType::PK_NONE) - { - root["key"] = Json::Value(Json::objectValue); - root["key"]["type"] = Json::Value(sslConfig->private_key_type_string()); - root["key"]["length"] = Json::Value((Json::UInt)sslConfig->private_key_length()); - } - - std::vector<std::string> extra_certs = sslConfig->extract_extra_certs(); - if (extra_certs.size() > 0) - { - root["extra_certs"] = Json::Value(Json::arrayValue); - for (auto cert = extra_certs.begin(); cert != extra_certs.end(); cert++) - { - if (!cert->empty()) - root["extra_certs"].append(Json::Value(*cert)); - } - } - } - - root["cipher"] = Json::Value(CryptoAlgs::name(protoConfig->dc.cipher(), "none")); - root["auth"] = Json::Value(CryptoAlgs::name(protoConfig->dc.digest(), "none")); - if (protoConfig->comp_ctx.type() != CompressContext::NONE) - root["compression"] = Json::Value(protoConfig->comp_ctx.str()); - root["keepalive"] = Json::Value(Json::objectValue); - root["keepalive"]["ping"] = Json::Value((Json::UInt)protoConfig->keepalive_ping.to_seconds()); - root["keepalive"]["timeout"] = Json::Value((Json::UInt)protoConfig->keepalive_timeout.to_seconds()); - root["tun_mtu"] = Json::Value((Json::UInt)protoConfig->tun_mtu); - root["reneg_sec"] = Json::Value((Json::UInt)protoConfig->renegotiate.to_seconds()); - - return root.toStyledString(); - } - -#endif /* HAVE_CONFIG_JSONCPP */ - - private: - static void print_pem(std::ostream& os, std::string label, std::string pem) - { - if (pem.empty()) - return; - os << "<" << label << ">" << std::endl << pem << "</" << label << ">" << std::endl; - } - -#ifdef HAVE_CONFIG_JSONCPP - - static void json_pem(Json::Value& obj, std::string key, std::string pem) - { - if (pem.empty()) - return; - obj[key] = Json::Value(pem); - } - -#endif /* HAVE_CONFIG_JSONCPP */ - - static bool parse_auth_user_pass(const OptionList& options, std::vector<std::string>* user_pass) - { - return UserPass::parse(options, "auth-user-pass", 0, user_pass); - } - - static void process_setenv_opt(OptionList& options) - { - for (OptionList::iterator i = options.begin(); i != options.end(); ++i) - { - Option& o = *i; - if (o.size() >= 3 && o.ref(0) == "setenv" && o.ref(1) == "opt") - o.remove_first(2); - } - } - - static bool is_autologin(const OptionList& options, - const bool auth_user_pass, - const std::vector<std::string>& user_pass) - { - if (auth_user_pass && user_pass.size() >= 2) // embedded password? - return true; - else - { - const Option* autologin = options.get_ptr("AUTOLOGIN"); - if (autologin) - return string::is_true(autologin->get_optional(1, 16)); - else - { - bool ret = !auth_user_pass; - if (ret) - { - // External PKI profiles from AS don't declare auth-user-pass, - // and we have no way of knowing if they are autologin unless - // we examine their cert, which requires accessing the system-level - // cert store on the client. For now, we are going to assume - // that External PKI profiles from the AS are always userlogin, - // unless explicitly overriden by AUTOLOGIN above. - if (options.exists("EXTERNAL_PKI")) - return false; - } - return ret; - } - } - } - - static bool is_external_pki(const OptionList& options) - { - const Option* epki = options.get_ptr("EXTERNAL_PKI"); - if (epki) - return string::is_true(epki->get_optional(1, 16)); - else - { - const Option* cert = options.get_ptr("cert"); - const Option* key = options.get_ptr("key"); - return !cert || !key; - } - } - - void reset_pod() - { - error_ = autologin_ = externalPki_ = staticChallengeEcho_ = false; - privateKeyPasswordRequired_ = hasEmbeddedPassword_ = false; - pushPeerInfo_ = false; - allowPasswordSave_ = clientCertEnabled_ = true; - } - - bool parse_bool(const Option& o, const std::string& title, const size_t index) - { - const std::string parm = o.get(index, 16); - if (parm == "0") - return false; - else if (parm == "1") - return true; - else - throw option_error(title + ": parameter must be 0 or 1"); - } - - bool error_; - std::string message_; - std::string userlockedUsername_; - std::string profileName_; - std::string friendlyName_; - bool autologin_; - bool clientCertEnabled_; - bool externalPki_; - bool pushPeerInfo_; - std::string staticChallenge_; - bool staticChallengeEcho_; - bool privateKeyPasswordRequired_; - bool allowPasswordSave_; - ServerList serverList_; - bool hasEmbeddedPassword_; - std::string embeddedPassword_; - RemoteList::Ptr remoteList; - RemoteItem firstRemoteListItem_; - PeerInfo::Set::Ptr peerInfoUV_; - ProtoContext::Config::Ptr protoConfig; - SSLLib::SSLAPI::Config::Ptr sslConfig; - std::string dev; - std::string windowsDriver_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/cliproto.hpp b/Sources/OpenVPN3/openvpn/client/cliproto.hpp deleted file mode 100644 index 70165b3..0000000 --- a/Sources/OpenVPN3/openvpn/client/cliproto.hpp +++ /dev/null @@ -1,1183 +0,0 @@ -// 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-2020 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_CLIPROTO_H -#define OPENVPN_CLIENT_CLIPROTO_H - -// This is a middle-layer object in the OpenVPN client protocol stack. -// It is above the general OpenVPN protocol implementation in -// class ProtoContext but below the top -// level object in a client connect (ClientConnect). See ClientConnect for -// a fuller description of the full client stack. -// -// This layer deals with setting up an OpenVPN client connection: -// -// 1. handles creation of transport-layer handler via TransportClientFactory -// 2. handles creation of tun-layer handler via TunClientFactory -// 3. handles sending PUSH_REQUEST to server and processing reply of server-pushed options -// 4. manages the underlying OpenVPN protocol object (class ProtoContext) -// 5. handles timers on behalf of the underlying OpenVPN protocol object -// 6. acts as an exception dispatcher for errors occuring in any of the underlying layers - -#include <string> -#include <vector> -#include <memory> -#include <algorithm> // for std::min -#include <cstdint> // for std::uint... - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/count.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/ip/ptb.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/client/relay.hpp> -#include <openvpn/options/continuation.hpp> -#include <openvpn/options/sanitize.hpp> -#include <openvpn/client/clievent.hpp> -#include <openvpn/client/clicreds.hpp> -#include <openvpn/client/cliconstants.hpp> -#include <openvpn/client/clihalt.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/time/coarsetime.hpp> -#include <openvpn/time/durhelper.hpp> -#include <openvpn/error/excode.hpp> - -#include <openvpn/ssl/proto.hpp> - -#ifdef OPENVPN_DEBUG_CLIPROTO -#define OPENVPN_LOG_CLIPROTO(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_CLIPROTO(x) -#endif - -namespace openvpn { - namespace ClientProto { - - struct NotifyCallback { - virtual void client_proto_terminate() = 0; - virtual void client_proto_connected() {} - virtual void client_proto_auth_pending_timeout(int timeout) {} - }; - - class Session : ProtoContext, - TransportClientParent, - TunClientParent, - public RC<thread_unsafe_refcount> - { - typedef ProtoContext Base; - typedef Base::PacketType PacketType; - - using Base::now; - using Base::stat; - - public: - typedef RCPtr<Session> Ptr; - typedef Base::Config ProtoConfig; - - OPENVPN_EXCEPTION(client_exception); - OPENVPN_EXCEPTION(client_halt_restart); - OPENVPN_EXCEPTION(tun_exception); - OPENVPN_EXCEPTION(transport_exception); - OPENVPN_EXCEPTION(max_pushed_options_exceeded); - OPENVPN_SIMPLE_EXCEPTION(session_invalidated); - OPENVPN_SIMPLE_EXCEPTION(authentication_failed); - OPENVPN_SIMPLE_EXCEPTION(inactive_timer_expired); - OPENVPN_SIMPLE_EXCEPTION(relay_event); - - OPENVPN_EXCEPTION(proxy_exception); - - struct Config : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - Config() - : pushed_options_limit("server-pushed options data too large", - ProfileParseLimits::MAX_PUSH_SIZE, - ProfileParseLimits::OPT_OVERHEAD, - ProfileParseLimits::TERM_OVERHEAD, - 0, - ProfileParseLimits::MAX_DIRECTIVE_SIZE) - {} - - ProtoConfig::Ptr proto_context_config; - ProtoContextOptions::Ptr proto_context_options; - PushOptionsBase::Ptr push_base; - TransportClientFactory::Ptr transport_factory; - TunClientFactory::Ptr tun_factory; - SessionStats::Ptr cli_stats; - ClientEvent::Queue::Ptr cli_events; - ClientCreds::Ptr creds; - OptionList::Limits pushed_options_limit; - OptionList::FilterBase::Ptr pushed_options_filter; - unsigned int tcp_queue_limit = 0; - bool echo = false; - bool info = false; - bool autologin_sessions = false; - }; - - Session(openvpn_io::io_context& io_context_arg, - const Config& config, - NotifyCallback* notify_callback_arg) - : Base(config.proto_context_config, config.cli_stats), - io_context(io_context_arg), - transport_factory(config.transport_factory), - tun_factory(config.tun_factory), - tcp_queue_limit(config.tcp_queue_limit), - notify_callback(notify_callback_arg), - housekeeping_timer(io_context_arg), - push_request_timer(io_context_arg), - received_options(config.push_base), - creds(config.creds), - proto_context_options(config.proto_context_options), - cli_stats(config.cli_stats), - cli_events(config.cli_events), - echo(config.echo), - info(config.info), - autologin_sessions(config.autologin_sessions), - pushed_options_limit(config.pushed_options_limit), - pushed_options_filter(config.pushed_options_filter), - inactive_timer(io_context_arg), - info_hold_timer(io_context_arg) - { -#ifdef OPENVPN_PACKET_LOG - packet_log.open(OPENVPN_PACKET_LOG, std::ios::binary); - if (!packet_log) - OPENVPN_THROW(open_file_error, "cannot open packet log for output: " << OPENVPN_PACKET_LOG); -#endif - Base::update_now(); - Base::reset(); - //Base::enable_strict_openvpn_2x(); - - info_hold.reset(new std::vector<ClientEvent::Base::Ptr>()); - } - - bool first_packet_received() const { return first_packet_received_; } - - void start() - { - if (!halt) - { - Base::update_now(); - - // coarse wakeup range - housekeeping_schedule.init(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024)); - - // initialize transport-layer packet handler - transport = transport_factory->new_transport_client_obj(io_context, this); - transport_has_send_queue = transport->transport_has_send_queue(); - if (transport_factory->is_relay()) - transport_connecting(); - else - transport->transport_start(); - } - } - - TransportClientFactory::Ptr transport_factory_relay() - { - TransportClient::Ptr tc(new TransportRelayFactory::TransportClientNull(transport.get())); - tc.swap(transport); - return new TransportRelayFactory(io_context, std::move(tc), this); - } - - void transport_factory_override(TransportClientFactory::Ptr factory) - { - transport_factory = std::move(factory); - } - - void send_explicit_exit_notify() - { - if (!halt) - Base::send_explicit_exit_notify(); - } - - void tun_set_disconnect() - { - if (tun) - tun->set_disconnect(); - } - - void post_cc_msg(const std::string& msg) - { - Base::update_now(); - Base::write_control_string(msg); - Base::flush(true); - set_housekeeping_timer(); - } - - void stop(const bool call_terminate_callback) - { - if (!halt) - { - halt = true; - housekeeping_timer.cancel(); - push_request_timer.cancel(); - inactive_timer.cancel(); - info_hold_timer.cancel(); - if (notify_callback && call_terminate_callback) - notify_callback->client_proto_terminate(); - if (tun) - tun->stop(); // call after client_proto_terminate() so it can call back to tun_set_disconnect - if (transport) - transport->stop(); - } - } - - void stop_on_signal(const openvpn_io::error_code& error, int signal_number) - { - stop(true); - } - - bool reached_connected_state() const { return bool(connected_); } - - // If fatal() returns something other than Error::UNDEF, it - // is intended to flag the higher levels (cliconnect.hpp) - // that special handling is required. This handling might include - // considering the error to be fatal and stopping future connect - // retries, or emitting a special event. See cliconnect.hpp - // for actual implementation. - Error::Type fatal() const { return fatal_; } - const std::string& fatal_reason() const { return fatal_reason_; } - - virtual ~Session() - { - stop(false); - } - - private: - virtual bool transport_is_openvpn_protocol() - { - return true; - } - - // transport obj calls here with incoming packets - virtual void transport_recv(BufferAllocated& buf) - { - try { - OPENVPN_LOG_CLIPROTO("Transport RECV " << server_endpoint_render() << ' ' << Base::dump_packet(buf)); - - // update current time - Base::update_now(); - - // update last packet received - stat().update_last_packet_received(now()); - - // log connecting event (only on first packet received) - if (!first_packet_received_) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Connecting(); - cli_events->add_event(std::move(ev)); - first_packet_received_ = true; - } - - // get packet type - Base::PacketType pt = Base::packet_type(buf); - - // process packet - if (pt.is_data()) - { - // data packet - Base::data_decrypt(pt, buf); - if (buf.size()) - { -#ifdef OPENVPN_PACKET_LOG - log_packet(buf, false); -#endif - // make packet appear as incoming on tun interface - if (tun) - { - OPENVPN_LOG_CLIPROTO("TUN send, size=" << buf.size()); - tun->tun_send(buf); - } - } - - // do a lightweight flush - Base::flush(false); - } - else if (pt.is_control()) - { - // control packet - Base::control_net_recv(pt, std::move(buf)); - - // do a full flush - Base::flush(true); - } - else - cli_stats->error(Error::KEY_STATE_ERROR); - - // schedule housekeeping wakeup - set_housekeeping_timer(); - } - catch (const ExceptionCode& e) - { - if (e.code_defined()) - { - if (e.fatal()) - transport_error((Error::Type)e.code(), e.what()); - else - cli_stats->error((Error::Type)e.code()); - } - else - process_exception(e, "transport_recv_excode"); - } - catch (const std::exception& e) - { - process_exception(e, "transport_recv"); - } - } - - virtual void transport_needs_send() - { - } - - // tun i/o driver calls here with incoming packets - virtual void tun_recv(BufferAllocated& buf) - { - try { - OPENVPN_LOG_CLIPROTO("TUN recv, size=" << buf.size()); - - // update current time - Base::update_now(); - - // log packet -#ifdef OPENVPN_PACKET_LOG - log_packet(buf, true); -#endif - - // if transport layer has an output queue, check if it's full - if (transport_has_send_queue) - { - if (transport->transport_send_queue_size() > tcp_queue_limit) - { - buf.reset_size(); // queue full, drop packet - cli_stats->error(Error::TCP_OVERFLOW); - } - } - - // encrypt packet - if (buf.size()) - { - const ProtoContext::Config& c = Base::conf(); - if (c.mss_inter > 0 && buf.size() > c.mss_inter) - { - Ptb::generate_icmp_ptb(buf, c.mss_inter); - tun->tun_send(buf); - } - else - { - Base::data_encrypt(buf); - if (buf.size()) - { - // send packet via transport to destination - OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << Base::dump_packet(buf)); - if (transport->transport_send(buf)) - Base::update_last_sent(); - else if (halt) - return; - } - } - } - - // do a lightweight flush - Base::flush(false); - - // schedule housekeeping wakeup - set_housekeeping_timer(); - } - catch (const std::exception& e) - { - process_exception(e, "tun_recv"); - } - } - - // Return true if keepalive parameter(s) are enabled. - virtual bool is_keepalive_enabled() const - { - return Base::is_keepalive_enabled(); - } - - // Disable keepalive for rest of session, but fetch - // the keepalive parameters (in seconds). - virtual void disable_keepalive(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) - { - Base::disable_keepalive(keepalive_ping, keepalive_timeout); - } - - virtual void transport_pre_resolve() - { - ClientEvent::Base::Ptr ev = new ClientEvent::Resolve(); - cli_events->add_event(std::move(ev)); - } - - std::string server_endpoint_render() - { - std::string server_host, server_port, server_proto, server_ip; - transport->server_endpoint_info(server_host, server_port, server_proto, server_ip); - std::ostringstream out; - out << '[' << server_host << "]:" << server_port << " (" << server_ip << ") via " << server_proto; - return out.str(); - } - - virtual void transport_wait_proxy() - { - ClientEvent::Base::Ptr ev = new ClientEvent::WaitProxy(); - cli_events->add_event(std::move(ev)); - } - - virtual void transport_wait() - { - ClientEvent::Base::Ptr ev = new ClientEvent::Wait(); - cli_events->add_event(std::move(ev)); - } - - virtual void transport_connecting() - { - try { - OPENVPN_LOG("Connecting to " << server_endpoint_render()); - Base::set_protocol(transport->transport_protocol()); - Base::start(); - Base::flush(true); - set_housekeeping_timer(); - } - catch (const std::exception& e) - { - process_exception(e, "transport_connecting"); - } - } - - virtual void transport_error(const Error::Type fatal_err, const std::string& err_text) - { - if (fatal_err != Error::UNDEF) - { - fatal_ = fatal_err; - fatal_reason_ = err_text; - } - if (notify_callback) - { - OPENVPN_LOG("Transport Error: " << err_text); - stop(true); - } - else - throw transport_exception(err_text); - } - - virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text) - { - if (fatal_err != Error::UNDEF) - { - fatal_ = fatal_err; - fatal_reason_ = err_text; - } - if (notify_callback) - { - OPENVPN_LOG("Proxy Error: " << err_text); - stop(true); - } - else - throw proxy_exception(err_text); - } - - void extract_auth_token(const OptionList& opt) - { - std::string username; - - // auth-token-user - { - const Option* o = opt.get_ptr("auth-token-user"); - if (o) - username = base64->decode(o->get(1, 340)); // 255 chars after base64 decode - } - - // auth-token - { - // if auth-token is present, use it as the password for future renegotiations - const Option* o = opt.get_ptr("auth-token"); - if (o) - { - const std::string& sess_id = o->get(1, 256); - if (creds) - { - if (!username.empty()) - OPENVPN_LOG("Session user: " << username); -#ifdef OPENVPN_SHOW_SESSION_TOKEN - OPENVPN_LOG("Session token: " << sess_id); -#else - OPENVPN_LOG("Session token: [redacted]"); -#endif - creds->set_session_id(username, sess_id); - } - } - } - } - - // proto base class calls here for control channel network sends - virtual void control_net_send(const Buffer& net_buf) - { - OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << Base::dump_packet(net_buf)); - if (transport->transport_send_const(net_buf)) - Base::update_last_sent(); - } - - // proto base class calls here for app-level control-channel messages received - virtual void control_recv(BufferPtr&& app_bp) - { - const std::string msg = Unicode::utf8_printable(Base::template read_control_string<std::string>(*app_bp), - Unicode::UTF8_FILTER|Unicode::UTF8_PASS_FMT); - - //OPENVPN_LOG("SERVER: " << sanitize_control_message(msg)); - - if (!received_options.complete() && string::starts_with(msg, "PUSH_REPLY,")) - { - // parse the received options - received_options.add(OptionList::parse_from_csv_static(msg.substr(11), &pushed_options_limit), - pushed_options_filter.get()); - if (received_options.complete()) - { - // show options - OPENVPN_LOG("OPTIONS:" << std::endl << render_options_sanitized(received_options, Option::RENDER_PASS_FMT|Option::RENDER_NUMBER|Option::RENDER_BRACKET)); - - // relay servers are not allowed to establish a tunnel with us - if (Base::conf().relay_mode) - { - tun_error(Error::RELAY_ERROR, "tunnel not permitted to relay server"); - return; - } - - // process "echo" directives - if (echo) - process_echo(received_options); - - // process auth-token - extract_auth_token(received_options); - - // modify proto config (cipher, auth, key-derivation and compression methods) - Base::process_push(received_options, *proto_context_options); - - // initialize tun/routing - tun = tun_factory->new_tun_client_obj(io_context, *this, transport.get()); - tun->tun_start(received_options, *transport, Base::dc_settings()); - - // we should be connected at this point - if (!connected_) - throw tun_exception("not connected"); - - // initialize data channel after pushed options have been processed - Base::init_data_channel(); - - // Allow ProtoContext to suggest an alignment adjustment - // hint for transport layer. - transport->reset_align_adjust(Base::align_adjust_hint()); - - // process "inactive" directive - process_inactive(received_options); - - // tell parent that we are connected - if (notify_callback) - notify_callback->client_proto_connected(); - - // start info-hold timer - schedule_info_hold_callback(); - - // send the Connected event - cli_events->add_event(connected_); - - // check for proto options - check_proto_warnings(); - } - else - OPENVPN_LOG("Options continuation..."); - } - else if (received_options.complete() && string::starts_with(msg, "PUSH_REPLY,")) - { - // We got a PUSH REPLY in the middle of a session. Ignore it apart from - // updating the auth-token if included in the push reply - auto opts = OptionList::parse_from_csv_static(msg.substr(11), nullptr); - extract_auth_token(opts); - } - else if (string::starts_with(msg, "AUTH_FAILED")) - { - std::string reason; - std::string log_reason; - - // get reason (if it exists) for authentication failure - if (msg.length() >= 13) - reason = string::trim_left_copy(std::string(msg, 12)); - - // If session token problem (such as expiration), and we have a cached - // password, retry with it. Otherwise, fail without retry. - if (string::starts_with(reason, "SESSION:") - && (autologin_sessions - || (creds && creds->can_retry_auth_with_cached_password()))) - { - log_reason = "SESSION_AUTH_FAILED"; - } - else - { - fatal_ = Error::AUTH_FAILED; - fatal_reason_ = reason; - log_reason = "AUTH_FAILED"; - } - if (notify_callback) - { - OPENVPN_LOG(log_reason); - stop(true); - } - else - throw authentication_failed(); - } - else if (ClientHalt::match(msg)) - { - const ClientHalt ch(msg, true); - process_halt_restart(ch); - } - else if (info && string::starts_with(msg, "INFO,")) - { - // Buffer INFO messages received near Connected event to fire - // one second after Connected event, to reduce the chance of - // race conditions in the client app, if the INFO event - // triggers the client app to perform an operation that - // requires the VPN tunnel to be ready. - ClientEvent::Base::Ptr ev = new ClientEvent::Info(msg.substr(5)); - if (info_hold) - info_hold->push_back(std::move(ev)); - else - cli_events->add_event(std::move(ev)); - } - else if (info && string::starts_with(msg, "INFO_PRE,")) - { - // INFO_PRE is like INFO but it is never buffered - ClientEvent::Base::Ptr ev = new ClientEvent::Info(msg.substr(9)); - cli_events->add_event(std::move(ev)); - } - else if (msg == "AUTH_PENDING" || string::starts_with(msg, "AUTH_PENDING,")) - { - // AUTH_PENDING indicates an out-of-band authentication step must - // be performed before the server will send the PUSH_REPLY message. - if (!auth_pending) - { - auth_pending = true; - std::string key_words; - - unsigned int timeout = 0; - - if (string::starts_with(msg, "AUTH_PENDING,")) - { - key_words = msg.substr(::strlen("AUTH_PENDING,")); - auto opts = OptionList::parse_from_csv_static(key_words, nullptr); - std::string timeout_str = opts.get_optional("timeout", 1, 20); - if (timeout_str != "") - { - try - { - timeout = std::stoul(timeout_str); - // Cap the timeout to end well before renegotiation starts - timeout = std::min(timeout, static_cast<decltype(timeout)>(conf().renegotiate.to_seconds() / 2)); - } - catch (const std::logic_error& e) - { - OPENVPN_LOG("could not parse AUTH_PENDING timeout: " << timeout_str); - } - } - } - - - - if (notify_callback && timeout > 0) - { - notify_callback->client_proto_auth_pending_timeout(timeout); - } - - ClientEvent::Base::Ptr ev = new ClientEvent::AuthPending(timeout, key_words); - cli_events->add_event(std::move(ev)); - } - } - else if (msg == "RELAY") - { - if (Base::conf().relay_mode) - { - fatal_ = Error::RELAY; - fatal_reason_ = ""; - } - else - { - fatal_ = Error::RELAY_ERROR; - fatal_reason_ = "not in relay mode"; - } - if (notify_callback) - { - OPENVPN_LOG(Error::name(fatal_) << ' ' << fatal_reason_); - stop(true); - } - else - throw relay_event(); - } - } - - virtual void tun_pre_tun_config() - { - ClientEvent::Base::Ptr ev = new ClientEvent::AssignIP(); - cli_events->add_event(std::move(ev)); - } - - virtual void tun_pre_route_config() - { - ClientEvent::Base::Ptr ev = new ClientEvent::AddRoutes(); - cli_events->add_event(std::move(ev)); - } - - virtual void tun_connected() - { - OPENVPN_LOG("Connected via " + tun->tun_name()); - - ClientEvent::Connected::Ptr ev = new ClientEvent::Connected(); - if (creds) - ev->user = creds->get_username(); - transport->server_endpoint_info(ev->server_host, ev->server_port, ev->server_proto, ev->server_ip); - ev->vpn_ip4 = tun->vpn_ip4(); - ev->vpn_ip6 = tun->vpn_ip6(); - ev->vpn_gw4 = tun->vpn_gw4(); - ev->vpn_gw6 = tun->vpn_gw6(); - try { - std::string client_ip = received_options.get_optional("client-ip", 1, 256); - if (!client_ip.empty()) - ev->client_ip = IP::Addr::validate(client_ip, "client-ip"); - } - catch (const std::exception& e) - { - OPENVPN_LOG("exception parsing client-ip: " << e.what()); - } - ev->tun_name = tun->tun_name(); - connected_ = std::move(ev); - } - - virtual void tun_error(const Error::Type fatal_err, const std::string& err_text) - { - if (fatal_err == Error::TUN_HALT) - send_explicit_exit_notify(); - if (fatal_err != Error::UNDEF) - { - fatal_ = fatal_err; - fatal_reason_ = err_text; - } - if (notify_callback) - { - OPENVPN_LOG("TUN Error: " << err_text); - stop(true); - } - else - throw tun_exception(err_text); - } - - // proto base class calls here to get auth credentials - virtual void client_auth(Buffer& buf) - { - // we never send creds to a relay server - if (creds && !Base::conf().relay_mode) - { - OPENVPN_LOG("Creds: " << creds->auth_info()); - Base::write_auth_string(creds->get_username(), buf); - Base::write_auth_string(creds->get_password(), buf); - } - else - { - OPENVPN_LOG("Creds: None"); - Base::write_empty_string(buf); // username - Base::write_empty_string(buf); // password - } - } - - void send_push_request_callback(const Time::Duration& dur, - const openvpn_io::error_code& e) - { - try { - if (!e && !halt && !received_options.partial()) - { - Base::update_now(); - if (!sent_push_request) - { - ClientEvent::Base::Ptr ev = new ClientEvent::GetConfig(); - cli_events->add_event(std::move(ev)); - sent_push_request = true; - } - OPENVPN_LOG("Sending PUSH_REQUEST to server..."); - Base::write_control_string(std::string("PUSH_REQUEST")); - Base::flush(true); - set_housekeeping_timer(); - - { - if (auth_pending) - { - // With auth_pending, we can dial back the PUSH_REQUEST - // frequency, but we still need back-and-forth network - // activity to avoid an inactivity timeout, since the crypto - // layer (and hence keepalive ping) is not initialized until - // we receive the PUSH_REPLY from the server. - schedule_push_request_callback(Time::Duration::seconds(8)); - } - else - { - // step function with ceiling: 1 sec, 2 secs, 3 secs, 3, 3, ... - const Time::Duration newdur = std::min(dur + Time::Duration::seconds(1), - Time::Duration::seconds(3)); - schedule_push_request_callback(newdur); - } - } - } - } - catch (const std::exception& e) - { - process_exception(e, "send_push_request_callback"); - } - } - - void schedule_push_request_callback(const Time::Duration& dur) - { - if (!received_options.partial()) - { - push_request_timer.expires_after(dur); - push_request_timer.async_wait([self=Ptr(this), dur](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->send_push_request_callback(dur, error); - }); - } - } - - // react to any tls warning triggered during the tls-handshake - virtual void check_tls_warnings() - { - uint32_t tls_warnings = get_tls_warnings(); - - if (tls_warnings & SSLAPI::TLS_WARN_SIG_MD5) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Warn("TLS: received certificate signed with MD5. Please inform your admin to upgrade to a stronger algorithm. Support for MD5 will be dropped at end of Apr 2018"); - cli_events->add_event(std::move(ev)); - } - - if (tls_warnings & SSLAPI::TLS_WARN_SIG_SHA1) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Warn("TLS: received certificate signed with SHA1. Please inform your admin to upgrade to a stronger algorithm. Support for SHA1 signatures will be dropped in the future"); - cli_events->add_event(std::move(ev)); - } - } - - void check_proto_warnings() - { - if (uses_bs64_cipher()) - { - ClientEvent::Base::Ptr ev = new ClientEvent::Warn("Proto: Using a 64-bit block cipher that is vulnerable to the SWEET32 attack. Please inform your admin to upgrade to a stronger algorithm. Support for 64-bit block cipher will be dropped in the future."); - cli_events->add_event(std::move(ev)); - } - - // Issue an event if compression is enabled - CompressContext::Type comp_type = Base::conf().comp_ctx.type(); - if (comp_type != CompressContext::NONE - && !CompressContext::is_any_stub(comp_type)) - { - std::ostringstream msg; - msg << (proto_context_options->is_comp_asym() - ? "Asymmetric compression enabled. Server may send compressed data." - : "Compression enabled."); - msg << " This may be a potential security issue."; - ClientEvent::Base::Ptr ev = new ClientEvent::CompressionEnabled(msg.str()); - cli_events->add_event(std::move(ev)); - } - } - - // base class calls here when primary session transitions to ACTIVE state - virtual void active() - { - OPENVPN_LOG("Session is ACTIVE"); - check_tls_warnings(); - schedule_push_request_callback(Time::Duration::seconds(0)); - } - - void housekeeping_callback(const openvpn_io::error_code& e) - { - try { - if (!e && !halt) - { - // update current time - Base::update_now(); - - housekeeping_schedule.reset(); - Base::housekeeping(); - if (Base::invalidated()) - { - if (notify_callback) - { - OPENVPN_LOG("Session invalidated: " << Error::name(Base::invalidation_reason())); - stop(true); - } - else - throw session_invalidated(); - } - set_housekeeping_timer(); - } - } - catch (const std::exception& e) - { - process_exception(e, "housekeeping_callback"); - } - } - - void set_housekeeping_timer() - { - if (halt) - return; - - Time next = Base::next_housekeeping(); - if (!housekeeping_schedule.similar(next)) - { - if (!next.is_infinite()) - { - next.max(now()); - housekeeping_schedule.reset(next); - housekeeping_timer.expires_at(next); - housekeeping_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->housekeeping_callback(error); - }); - } - else - { - housekeeping_timer.cancel(); - housekeeping_schedule.reset(); - } - } - } - - void process_inactive(const OptionList& opt) - { - try { - const Option *o = load_duration_parm(inactive_duration, "inactive", opt, 1, false, false); - if (o) - { - if (o->size() >= 3) - inactive_bytes = parse_number_throw<unsigned int>(o->get(2, 16), "inactive bytes"); - schedule_inactive_timer(); - } - } - catch (const std::exception& e) - { - OPENVPN_LOG("exception parsing inactive: " << e.what()); - } - } - - void schedule_inactive_timer() - { - inactive_timer.expires_after(inactive_duration); - inactive_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->inactive_callback(error); - }); - } - - void inactive_callback(const openvpn_io::error_code& e) // fixme for DCO - { - try { - if (!e && !halt) - { - // update current time - Base::update_now(); - const count_t sample = cli_stats->get_stat(SessionStats::TUN_BYTES_IN) + cli_stats->get_stat(SessionStats::TUN_BYTES_OUT); - const count_t delta = sample - inactive_last_sample; - //OPENVPN_LOG("*** INACTIVE SAMPLE " << delta << ' ' << inactive_bytes); - if (delta <= count_t(inactive_bytes)) - { - fatal_ = Error::INACTIVE_TIMEOUT; - send_explicit_exit_notify(); - if (notify_callback) - { - OPENVPN_LOG("inactive timer expired"); - stop(true); - } - else - throw inactive_timer_expired(); - } - else - { - inactive_last_sample = sample; - schedule_inactive_timer(); - } - } - } - catch (const std::exception& e) - { - process_exception(e, "inactive_callback"); - } - } - - void process_echo(const OptionList& opt) - { - OptionList::IndexMap::const_iterator echo_opt = opt.map().find("echo"); - if (echo_opt != opt.map().end()) - { - for (OptionList::IndexList::const_iterator i = echo_opt->second.begin(); i != echo_opt->second.end(); ++i) - { - const Option& o = opt[*i]; - o.touch(); - const std::string& value = o.get(1, 512); - ClientEvent::Base::Ptr ev = new ClientEvent::Echo(value); - cli_events->add_event(std::move(ev)); - } - } - } - - void process_exception(const std::exception& e, const char *method_name) - { - if (notify_callback) - { - OPENVPN_LOG("Client exception in " << method_name << ": " << e.what()); - stop(true); - } - else - throw client_exception(e.what()); - } - - void process_halt_restart(const ClientHalt& ch) - { - if (!ch.psid() && creds) - creds->purge_session_id(); - if (ch.restart()) - fatal_ = Error::CLIENT_RESTART; - else - fatal_ = Error::CLIENT_HALT; - fatal_reason_ = ch.reason(); - if (notify_callback) - { - OPENVPN_LOG("Client halt/restart: " << ch.render()); - stop(true); - } - else - throw client_halt_restart(ch.render()); - } - - void schedule_info_hold_callback() - { - Base::update_now(); - info_hold_timer.expires_after(Time::Duration::seconds(1)); - info_hold_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->info_hold_callback(error); - }); - } - - void info_hold_callback(const openvpn_io::error_code& e) - { - try { - if (!e && !halt) - { - Base::update_now(); - if (info_hold) - { - for (auto &ev : *info_hold) - cli_events->add_event(std::move(ev)); - info_hold.reset(); - } - } - } - catch (const std::exception& e) - { - process_exception(e, "info_hold_callback"); - } - } - -#ifdef OPENVPN_PACKET_LOG - void log_packet(const Buffer& buf, const bool out) - { - if (buf.size()) - { - std::uint16_t len = buf.size() & 0x7FFF; - if (out) - len |= 0x8000; - packet_log.write((const char *)&len, sizeof(len)); - packet_log.write((const char *)buf.c_data(), buf.size()); - } - } -#endif - - openvpn_io::io_context& io_context; - - TransportClientFactory::Ptr transport_factory; - TransportClient::Ptr transport; - - TunClientFactory::Ptr tun_factory; - TunClient::Ptr tun; - - unsigned int tcp_queue_limit; - bool transport_has_send_queue = false; - - NotifyCallback* notify_callback; - - CoarseTime housekeeping_schedule; - AsioTimer housekeeping_timer; - AsioTimer push_request_timer; - bool halt = false; - - OptionListContinuation received_options; - - ClientCreds::Ptr creds; - - ProtoContextOptions::Ptr proto_context_options; - - bool first_packet_received_ = false; - bool sent_push_request = false; - bool auth_pending = false; - - SessionStats::Ptr cli_stats; - ClientEvent::Queue::Ptr cli_events; - - ClientEvent::Connected::Ptr connected_; - - bool echo; - bool info; - bool autologin_sessions; - - Error::Type fatal_ = Error::UNDEF; - std::string fatal_reason_; - - OptionList::Limits pushed_options_limit; - OptionList::FilterBase::Ptr pushed_options_filter; - - AsioTimer inactive_timer; - Time::Duration inactive_duration; - unsigned int inactive_bytes = 0; - count_t inactive_last_sample = 0; - - std::unique_ptr<std::vector<ClientEvent::Base::Ptr>> info_hold; - AsioTimer info_hold_timer; - -#ifdef OPENVPN_PACKET_LOG - std::ofstream packet_log; -#endif - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/ipverflags.hpp b/Sources/OpenVPN3/openvpn/client/ipverflags.hpp deleted file mode 100644 index cd9129d..0000000 --- a/Sources/OpenVPN3/openvpn/client/ipverflags.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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-2020 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_IPVERFLAGS_H -#define OPENVPN_CLIENT_IPVERFLAGS_H - -#include <openvpn/addr/ip.hpp> -#include <openvpn/client/rgopt.hpp> -#include <openvpn/tun/builder/rgwflags.hpp> - -namespace openvpn { - class IPVerFlags - { - public: - IPVerFlags(const OptionList& opt, - const IP::Addr::VersionMask ip_ver_flags) - : ip_ver_flags_(ip_ver_flags), - rg_flags_(opt), - api_flags_(0) - { - } - - bool rgv4() const - { - return v4() && rg_flags_.redirect_gateway_ipv4_enabled(); - } - - bool rgv6() const - { - return v6() && rg_flags_.redirect_gateway_ipv6_enabled(); - } - - bool v4() const - { - return (ip_ver_flags_ & IP::Addr::V4_MASK) ? true : false; - } - - bool v6() const - { - return (ip_ver_flags_ & IP::Addr::V6_MASK) ? true : false; - } - - IP::Addr::VersionMask rg_ver_flags() const - { - IP::Addr::VersionMask flags = 0; - if (rgv4()) - flags |= IP::Addr::V4_MASK; - if (rgv6()) - flags |= IP::Addr::V6_MASK; - return flags; - } - - IP::Addr::VersionMask ip_ver_flags() const - { - IP::Addr::VersionMask flags = 0; - if (v4()) - flags |= IP::Addr::V4_MASK; - if (v6()) - flags |= IP::Addr::V6_MASK; - return flags; - } - - // these flags are passed to tun_builder_reroute_gw method - unsigned int api_flags() const - { - return api_flags_ | rg_flags_(); - } - - void set_emulate_exclude_routes() - { - api_flags_ |= RGWFlags::EmulateExcludeRoutes; - } - - private: - const IP::Addr::VersionMask ip_ver_flags_; - const RedirectGatewayFlags rg_flags_; - unsigned int api_flags_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/optfilt.hpp b/Sources/OpenVPN3/openvpn/client/optfilt.hpp deleted file mode 100644 index 43c8d17..0000000 --- a/Sources/OpenVPN3/openvpn/client/optfilt.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// 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-2020 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_OPTFILT_H -#define OPENVPN_CLIENT_OPTFILT_H - -#include <openvpn/common/options.hpp> - -// Options filters - -namespace openvpn { - - class PushedOptionsFilter : public OptionList::FilterBase - { - public: - PushedOptionsFilter(const bool route_nopull) - : route_nopull_(route_nopull) {} - - virtual bool filter(const Option& opt) - { - const bool ret = filt(opt); - if (!ret) - OPENVPN_LOG("Ignored due to route-nopull: " << opt.render(Option::RENDER_TRUNC_64|Option::RENDER_BRACKET)); - return ret; - } - - private: - // return false if pushed option should be ignored due to route-nopull directive. - bool filt(const Option& opt) - { - if (route_nopull_) - { - if (opt.size() >= 1) - { - const std::string& directive = opt.ref(0); - if (directive.length() >= 1) - { - switch (directive[0]) - { - case 'b': - if (directive == "block-ipv6") - return false; - break; - case 'c': - if (directive == "client-nat") - return false; - break; - case 'd': - if (directive == "dhcp-option" || - directive == "dhcp-renew" || - directive == "dhcp-pre-release" || - directive == "dhcp-release") - return false; - break; - case 'i': - if (directive == "ip-win32") - return false; - break; - case 'r': - if (directive == "route" || - directive == "route-ipv6" || - directive == "route-metric" || - directive == "redirect-gateway" || - directive == "redirect-private" || - directive == "register-dns" || - directive == "route-delay" || - directive == "route-method") - return false; - break; - case 't': - if (directive == "tap-sleep") - return false; - break; - } - } - } - } - return true; - } - - bool route_nopull_; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/remotelist.hpp b/Sources/OpenVPN3/openvpn/client/remotelist.hpp deleted file mode 100644 index d10796a..0000000 --- a/Sources/OpenVPN3/openvpn/client/remotelist.hpp +++ /dev/null @@ -1,926 +0,0 @@ -// 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-2020 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/>. - -// These classes handle parsing and representation of OpenVPN "remote" directives, -// and the list of IP addresses that they resolve to. -// <connection> blocks are supported. - -#ifndef OPENVPN_CLIENT_REMOTELIST_H -#define OPENVPN_CLIENT_REMOTELIST_H - -#include <string> -#include <sstream> -#include <vector> -#include <algorithm> -#include <utility> -#include <thread> - -#include <openvpn/io/io.hpp> -#include <openvpn/asio/asiowork.hpp> - -#include <openvpn/common/bigmutex.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/addr/addrlist.hpp> -#include <openvpn/transport/protocol.hpp> -#include <openvpn/client/cliconstants.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/client/async_resolve.hpp> - -#if OPENVPN_DEBUG_REMOTELIST >= 1 -#define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_REMOTELIST(x) -#endif - -namespace openvpn { - class RemoteList : public RC<thread_unsafe_refcount> - { - // A single IP address that is part of a list of IP addresses - // associated with a "remote" item. - struct ResolvedAddr : public RC<thread_unsafe_refcount> - { - typedef RCPtr<ResolvedAddr> Ptr; - IP::Addr addr; - - std::string to_string() const - { - return addr.to_string(); - } - }; - - // The IP address list associated with a single "remote" item. - struct ResolvedAddrList : public std::vector<ResolvedAddr::Ptr>, public RC<thread_unsafe_refcount> - { - typedef RCPtr<ResolvedAddrList> Ptr; - - std::string to_string() const - { - std::string ret; - for (std::vector<ResolvedAddr::Ptr>::const_iterator i = begin(); i != end(); ++i) - { - if (!ret.empty()) - ret += ' '; - ret += (*i)->to_string(); - } - return ret; - } - }; - - public: - struct Item; - - struct ConnBlock : public RC<thread_unsafe_refcount> - { - typedef RCPtr<ConnBlock> Ptr; - - virtual void new_item(const Item& item) = 0; - }; - - struct ConnBlockFactory - { - typedef RCPtr<ConnBlockFactory> Ptr; - - virtual ConnBlock::Ptr new_conn_block(const OptionList::Ptr& opt) = 0; - }; - - // A single "remote" item - struct Item : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Item> Ptr; - - // "remote" item parameters from config file - std::string server_host; - std::string server_port; - Protocol transport_protocol; - - // IP address list defined after server_host is resolved - ResolvedAddrList::Ptr res_addr_list; - - // Other options if this is a <connection> block - ConnBlock::Ptr conn_block; - - bool res_addr_list_defined() const - { - return res_addr_list && res_addr_list->size() > 0; - } - - // cache a single IP address - void set_ip_addr(const IP::Addr& addr) - { - res_addr_list.reset(new ResolvedAddrList()); - ResolvedAddr::Ptr ra(new ResolvedAddr()); - ra->addr = addr; - res_addr_list->push_back(std::move(ra)); - OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint SET " << to_string()); - } - - // cache a list of DNS-resolved IP addresses - template <class EPRANGE> - void set_endpoint_range(const EPRANGE& endpoint_range, RandomAPI* rng) - { - res_addr_list.reset(new ResolvedAddrList()); - for (const auto &i : endpoint_range) - { - ResolvedAddr::Ptr addr(new ResolvedAddr()); - addr->addr = IP::Addr::from_asio(i.endpoint().address()); - res_addr_list->push_back(addr); - } - if (rng && res_addr_list->size() >= 2) - std::shuffle(res_addr_list->begin(), res_addr_list->end(), *rng); - OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint SET " << to_string()); - } - - // get an endpoint for contacting server - template <class EP> - bool get_endpoint(EP& endpoint, const size_t index) const - { - if (res_addr_list && index < res_addr_list->size()) - { - endpoint.address((*res_addr_list)[index]->addr.to_asio()); - endpoint.port(parse_number_throw<unsigned int>(server_port, "remote_port")); - OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint GET[" << index << "] " << endpoint << ' ' << to_string()); - return true; - } - else - return false; - } - - std::string to_string() const - { - std::ostringstream out; - out << "host=" << server_host; - if (res_addr_list) - out << '[' << res_addr_list->to_string() << ']'; - out << " port=" << server_port - << " proto=" << transport_protocol.str(); - return out.str(); - } - }; - - struct RemoteOverride - { - virtual Item::Ptr get() = 0; - }; - - private: - // Directive names that we search for in options - struct Directives - { - void init(const std::string& connection_tag) - { - connection = connection_tag.length() ? connection_tag : "connection"; - remote = "remote"; - proto = "proto"; - port = "port"; - } - - std::string connection; - std::string remote; - std::string proto; - std::string port; - }; - - // Used to index into remote list. - // The primary index is the remote list index. - // The secondary index is the index into the - // Item's IP address list (res_addr_list). - class Index - { - public: - Index() - { - reset(); - } - - void reset() - { - primary_ = secondary_ = 0; - } - - void reset_secondary() - { - secondary_ = 0; - } - - // return true if primary index was incremented - bool increment(const size_t pri_len, const size_t sec_len) - { - if (++secondary_ >= sec_len) - { - secondary_ = 0; - if (++primary_ >= pri_len) - primary_ = 0; - return true; - } - else - return false; - } - - bool equals(const Index& other) const - { - return primary_ == other.primary_ && secondary_ == other.secondary_; - } - - size_t primary() const { return primary_; } - size_t secondary() const { return secondary_; } - - private: - size_t primary_; - size_t secondary_; - }; - - public: - // Used for errors occurring after initial options processing, - // and generally indicate logic errors - // (option_error used during initial options processing). - OPENVPN_EXCEPTION(remote_list_error); - - typedef RCPtr<RemoteList> Ptr; - - // Helper class used to pre-resolve all items in remote list. - // This is useful in tun_persist mode, where it may be necessary - // to pre-resolve all potential remote server items prior - // to initial tunnel establishment. - class PreResolve : public virtual RC<thread_unsafe_refcount>, AsyncResolvableTCP - { - public: - typedef RCPtr<PreResolve> Ptr; - - struct NotifyCallback - { - // client callback when resolve operation is complete - virtual void pre_resolve_done() = 0; - }; - - PreResolve(openvpn_io::io_context& io_context_arg, - const RemoteList::Ptr& remote_list_arg, - const SessionStats::Ptr& stats_arg) - : AsyncResolvableTCP(io_context_arg), - notify_callback(nullptr), - remote_list(remote_list_arg), - stats(stats_arg), - index(0) - { - } - - bool work_available() const - { - return remote_list->defined() && remote_list->enable_cache; - } - - void start(NotifyCallback* notify_callback_arg) - { - if (notify_callback_arg) - { - // This method is a no-op (i.e. pre_resolve_done is called immediately) - // if caching not enabled in underlying remote_list or if start() was - // previously called and is still in progress. - if (!notify_callback && work_available()) - { - notify_callback = notify_callback_arg; - remote_list->index.reset(); - index = 0; - async_resolve_lock(); - next(); - } - else - notify_callback_arg->pre_resolve_done(); - } - } - - void cancel() - { - notify_callback = nullptr; - index = 0; - async_resolve_cancel(); - } - - private: - void next() - { - while (index < remote_list->list.size()) - { - Item& item = *remote_list->list[index]; - - // try to resolve item if no cached data present - if (!item.res_addr_list_defined()) - { - // next item to resolve - const Item* sitem = remote_list->search_server_host(item.server_host); - if (sitem) - { - // item's server_host matches one previously resolved -- use it - OPENVPN_LOG_REMOTELIST("*** PreResolve USED CACHE for " << item.server_host); - item.res_addr_list = sitem->res_addr_list; - } - else - { - OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << item.server_host << " : " << item.server_port); - async_resolve_name(item.server_host, item.server_port); - return; - } - } - ++index; - } - - // Done resolving list. Prune out all entries we were unable to - // resolve unless doing so would result in an empty list. - // Then call client's callback method. - { - async_resolve_cancel(); - NotifyCallback* ncb = notify_callback; - if (remote_list->cached_item_exists()) - remote_list->prune_uncached(); - cancel(); - ncb->pre_resolve_done(); - } - } - - // callback on resolve completion - void resolve_callback(const openvpn_io::error_code& error, - openvpn_io::ip::tcp::resolver::results_type results) override - { - if (notify_callback && index < remote_list->list.size()) - { - Item& item = *remote_list->list[index++]; - if (!error) - { - // resolve succeeded - item.set_endpoint_range(results, remote_list->rng.get()); - } - else - { - // resolve failed - OPENVPN_LOG("DNS pre-resolve error on " << item.server_host << ": " << error.message()); - if (stats) - stats->error(Error::RESOLVE_ERROR); - } - next(); - } - } - - NotifyCallback* notify_callback; - RemoteList::Ptr remote_list; - SessionStats::Ptr stats; - size_t index; - }; - - // create an empty remote list - RemoteList() - { - init(""); - } - - // create a remote list with a RemoteOverride callback - RemoteList(RemoteOverride* remote_override_arg) - : remote_override(remote_override_arg) - { - init(""); - next(); - } - - // create a remote list with exactly one item - RemoteList(const std::string& server_host, - const std::string& server_port, - const Protocol& transport_protocol, - const std::string& title) - { - init(""); - - HostPort::validate_port(server_port, title); - - Item::Ptr item(new Item()); - item->server_host = server_host; - item->server_port = server_port; - item->transport_protocol = transport_protocol; - list.push_back(item); - } - - // RemoteList flags - enum { - WARN_UNSUPPORTED=1<<0, - CONN_BLOCK_ONLY=1<<1, - CONN_BLOCK_OMIT_UNDEF=1<<2, - ALLOW_EMPTY=1<<3, - }; - - // create a remote list from config file option list - RemoteList(const OptionList& opt, - const std::string& connection_tag, - const unsigned int flags, - ConnBlockFactory* conn_block_factory) - { - init(connection_tag); - - // defaults - Protocol default_proto(Protocol::UDPv4); - std::string default_port = "1194"; - - // handle remote, port, and proto at the top-level - if (!(flags & CONN_BLOCK_ONLY)) - add(opt, default_proto, default_port, ConnBlock::Ptr()); - - // cycle through <connection> blocks - { - const size_t max_conn_block_size = 4096; - const OptionList::IndexList* conn = opt.get_index_ptr(directives.connection); - if (conn) - { - for (OptionList::IndexList::const_iterator i = conn->begin(); i != conn->end(); ++i) - { - try { - const Option& o = opt[*i]; - o.touch(); - const std::string& conn_block_text = o.get(1, Option::MULTILINE); - OptionList::Limits limits("<connection> block is too large", - max_conn_block_size, - ProfileParseLimits::OPT_OVERHEAD, - ProfileParseLimits::TERM_OVERHEAD, - ProfileParseLimits::MAX_LINE_SIZE, - ProfileParseLimits::MAX_DIRECTIVE_SIZE); - OptionList::Ptr conn_block = OptionList::parse_from_config_static_ptr(conn_block_text, &limits); - Protocol proto(default_proto); - std::string port(default_port); - - // unsupported options - if (flags & WARN_UNSUPPORTED) - { - unsupported_in_connection_block(*conn_block, "http-proxy"); - unsupported_in_connection_block(*conn_block, "http-proxy-option"); - unsupported_in_connection_block(*conn_block, "http-proxy-user-pass"); - } - - // connection block options encapsulation via user-defined factory - { - ConnBlock::Ptr cb; - if (conn_block_factory) - cb = conn_block_factory->new_conn_block(conn_block); - if (!(flags & CONN_BLOCK_OMIT_UNDEF) || cb) - add(*conn_block, proto, port, cb); - } - } - catch (Exception& e) - { - e.remove_label("option_error"); - e.add_label("connection_block"); - throw; - } - } - } - } - - if (!(flags & ALLOW_EMPTY) && list.empty()) - throw option_error("remote option not specified"); - - //OPENVPN_LOG(to_string()); - } - - // if cache is enabled, all DNS names will be preemptively queried - void set_enable_cache(const bool enable_cache_arg) - { - enable_cache = enable_cache_arg; - } - - bool get_enable_cache() const - { - return enable_cache; - } - - // override all server hosts to server_override - void set_server_override(const std::string& server_override) - { - if (server_override.empty()) - return; - for (auto &item : list) - { - item->server_host = server_override; - item->res_addr_list.reset(); - } - reset_cache(); - } - - // override all server ports to port_override - void set_port_override(const std::string& port_override) - { - if (port_override.empty()) - return; - for (auto &item : list) - { - item->server_port = port_override; - item->res_addr_list.reset(); - } - reset_cache(); - } - - void set_random(const RandomAPI::Ptr& rng_arg) - { - rng = rng_arg; - } - - // randomize item list, used to implement remote-random directive - void randomize() - { - if (rng) - { - std::shuffle(list.begin(), list.end(), *rng); - index.reset(); - } - } - - // return true if at least one remote entry is of type proto - bool contains_protocol(const Protocol& proto) - { - for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i) - { - if (proto.transport_match((*i)->transport_protocol)) - return true; - } - return false; - } - - // Higher-level version of set_proto_override that also supports indication - // on whether or not TCP-based proxies are enabled. Should be called after set_enable_cache - // because it may modify enable_cache flag. - void handle_proto_override(const Protocol& proto_override, const bool tcp_proxy_enabled) - { - if (tcp_proxy_enabled) - { - const Protocol tcp(Protocol::TCP); - if (contains_protocol(tcp)) - set_proto_override(tcp); - else - throw option_error("cannot connect via TCP-based proxy because no TCP server entries exist in profile"); - } - else if (proto_override.defined() && contains_protocol(proto_override)) - set_proto_override(proto_override); - } - - // increment to next IP address - void next() - { - if (remote_override) - { - Item::Ptr item = remote_override->get(); - if (item) - { - list.clear(); - index.reset(); - list.push_back(std::move(item)); - return; - } - } - - index.increment(list.size(), secondary_length(index.primary())); - if (!enable_cache) - reset_item(index.primary()); - } - - // Return details about current connection entry. - // Return value is true if get_endpoint may be called - // without raising an exception. - bool endpoint_available(std::string* server_host, std::string* server_port, Protocol* transport_protocol) const - { - const Item& item = *list[primary_index()]; - if (server_host) - *server_host = item.server_host; - if (server_port) - *server_port = item.server_port; - const bool cached = (item.res_addr_list && index.secondary() < item.res_addr_list->size()); - if (transport_protocol) - { - if (cached) - { - // Since we know whether resolved address is IPv4 or IPv6, add - // that info to the returned Protocol object. - Protocol proto(item.transport_protocol); - proto.mod_addr_version((*item.res_addr_list)[index.secondary()]->addr); - *transport_protocol = proto; - } - else - *transport_protocol = item.transport_protocol; - } - return cached; - } - - // cache a list of DNS-resolved IP addresses - template <class EPRANGE> - void set_endpoint_range(EPRANGE& endpoint_range) - { - Item& item = *list[primary_index()]; - item.set_endpoint_range(endpoint_range, rng.get()); - index.reset_secondary(); - } - - // get an endpoint for contacting server - template <class EP> - void get_endpoint(EP& endpoint) const - { - const Item& item = *list[primary_index()]; - if (!item.get_endpoint(endpoint, index.secondary())) - throw remote_list_error("current remote server endpoint is undefined"); - } - - // return true if object has at least one connection entry - bool defined() const { return list.size() > 0; } - - // return remote list size - size_t size() const { return list.size(); } - - const Item& get_item(const size_t index) const - { - return *list.at(index); - } - - // return hostname (or IP address) of current connection entry - const std::string& current_server_host() const - { - const Item& item = *list[primary_index()]; - return item.server_host; - } - - // return transport protocol of current connection entry - const Protocol& current_transport_protocol() const - { - const Item& item = *list[primary_index()]; - return item.transport_protocol; - } - - template <typename T> - typename T::Ptr current_conn_block() const - { - const Item& item = *list[primary_index()]; - return item.conn_block.template dynamic_pointer_cast<T>(); - } - - template <typename T> - T* current_conn_block_rawptr() const - { - const Item& item = *list[primary_index()]; - return dynamic_cast<T*>(item.conn_block.get()); - } - - // return hostname (or IP address) of first connection entry - std::string first_server_host() const - { - const Item& item = *list.at(0); - return item.server_host; - } - - const Item* first_item() const - { - if (defined()) - return list[0].get(); - else - return nullptr; - } - - std::string to_string() const - { - std::ostringstream out; - for (size_t i = 0; i < list.size(); ++i) - { - const Item& e = *list[i]; - out << '[' << i << "] " << e.to_string() << std::endl; - } - return out.str(); - } - - // return a list of unique, cached IP addresses - void cached_ip_address_list(IP::AddrList& addrlist) const - { - for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i) - { - const Item& item = **i; - if (item.res_addr_list_defined()) - { - const ResolvedAddrList& ral = *item.res_addr_list; - for (ResolvedAddrList::const_iterator j = ral.begin(); j != ral.end(); ++j) - { - const ResolvedAddr& addr = **j; - addrlist.add(addr.addr); - } - } - } - } - - // reset the cache associated with all items - void reset_cache() - { - for (auto &e : list) - e->res_addr_list.reset(nullptr); - index.reset(); - } - - // if caching is disabled, reset the cache for current item - void reset_cache_item() - { - if (!enable_cache) - reset_item(index.primary()); - } - - private: - // initialization, called by constructors - void init(const std::string& connection_tag) - { - enable_cache = false; - directives.init(connection_tag); - } - - // reset the cache associated with a given item - void reset_item(const size_t i) - { - if (i <= list.size()) - list[i]->res_addr_list.reset(nullptr); - } - - // return the current primary index (into list) and raise an exception - // if it is undefined - size_t primary_index() const - { - const size_t pri = index.primary(); - if (pri < list.size()) - return pri; - else - throw remote_list_error("current remote server item is undefined"); - } - - // return the number of cached IP addresses associated with a given item - size_t secondary_length(const size_t i) const - { - if (i < list.size()) - { - const Item& item = *list[i]; - if (item.res_addr_list) - return item.res_addr_list->size(); - } - return 0; - } - - // Search for cached Item by server_host - Item* search_server_host(const std::string& server_host) - { - for (std::vector<Item::Ptr>::iterator i = list.begin(); i != list.end(); ++i) - { - Item* item = i->get(); - if (server_host == item->server_host && item->res_addr_list_defined()) - return item; - } - return nullptr; - } - - // prune remote entries so that only those of Protocol proto_override remain - void set_proto_override(const Protocol& proto_override) - { - if (proto_override.defined()) - { - size_t di = 0; - for (size_t si = 0; si < list.size(); ++si) - { - const Item& item = *list[si]; - if (proto_override.transport_match(item.transport_protocol)) - { - if (si != di) - list[di] = list[si]; - ++di; - } - } - if (di != list.size()) - list.resize(di); - reset_cache(); - } - } - - // Return true if at least one cached Item exists - bool cached_item_exists() const - { - for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i) - { - const Item& item = **i; - if (item.res_addr_list_defined()) - return true; - } - return false; - } - - // Prune uncached Items so that only Items containing a res_addr_list with - // size > 0 remain. - void prune_uncached() - { - size_t di = 0; - for (size_t si = 0; si < list.size(); ++si) - { - const Item& item = *list[si]; - if (item.res_addr_list_defined()) - { - if (si != di) - list[di] = list[si]; - ++di; - } - } - if (di != list.size()) - list.resize(di); - index.reset(); - } - - void add(const OptionList& opt, Protocol& default_proto, std::string& default_port, ConnBlock::Ptr conn_block) - { - // parse "proto" option if present - { - const Option* o = opt.get_ptr(directives.proto); - if (o) - default_proto = Protocol::parse(o->get(1, 16), Protocol::CLIENT_SUFFIX); - } - - // parse "port" option if present - { - const Option* o = opt.get_ptr(directives.port); - if (o) - { - default_port = o->get(1, 16); - HostPort::validate_port(default_port, directives.port); - } - } - - // cycle through remote entries - { - const OptionList::IndexList* rem = opt.get_index_ptr(directives.remote); - if (rem) - { - for (OptionList::IndexList::const_iterator i = rem->begin(); i != rem->end(); ++i) - { - Item::Ptr e(new Item()); - const Option& o = opt[*i]; - o.touch(); - e->server_host = o.get(1, 256); - int adj = 0; - if (o.size() >= 3) - { - e->server_port = o.get(2, 16); - if (Protocol::is_local_type(e->server_port)) - { - adj = -1; - e->server_port = ""; - } - else - HostPort::validate_port(e->server_port, directives.port); - } - else - e->server_port = default_port; - if (o.size() >= (size_t)(4+adj)) - e->transport_protocol = Protocol::parse(o.get(3+adj, 16), Protocol::CLIENT_SUFFIX); - else - e->transport_protocol = default_proto; - e->conn_block = conn_block; - if (conn_block) - conn_block->new_item(*e); - list.push_back(e); - } - } - } - } - - void unsupported_in_connection_block(const OptionList& options, const std::string& option) - { - if (options.exists(option)) - OPENVPN_LOG("NOTE: " << option << " directive is not currently supported in <connection> blocks"); - } - - bool enable_cache; - Index index; - - std::vector<Item::Ptr> list; - - Directives directives; - - RemoteOverride* remote_override = nullptr; - - RandomAPI::Ptr rng; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/rgopt.hpp b/Sources/OpenVPN3/openvpn/client/rgopt.hpp deleted file mode 100644 index cdae841..0000000 --- a/Sources/OpenVPN3/openvpn/client/rgopt.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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-2020 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/>. - -// This class handles parsing and representation of redirect-gateway -// and redirect-private directives. - -#ifndef OPENVPN_CLIENT_RGOPT_H -#define OPENVPN_CLIENT_RGOPT_H - -#include <openvpn/common/options.hpp> - -namespace openvpn { - class RedirectGatewayFlags { - public: - enum Flags { - RG_ENABLE = (1<<0), - RG_REROUTE_GW = (1<<1), - RG_LOCAL = (1<<2), - RG_AUTO_LOCAL = (1<<3), - RG_DEF1 = (1<<4), - RG_BYPASS_DHCP = (1<<5), - RG_BYPASS_DNS = (1<<6), - RG_BLOCK_LOCAL = (1<<7), - RG_IPv4 = (1<<8), - RG_IPv6 = (1<<9), - - RG_DEFAULT = (RG_IPv4), - }; - - RedirectGatewayFlags() : flags_(RG_DEFAULT) {} - - RedirectGatewayFlags(unsigned int flags) : flags_(flags) {} - - explicit RedirectGatewayFlags(const OptionList& opt) - { - init(opt); - } - - void init(const OptionList& opt) - { - flags_ = RG_DEFAULT; - doinit(opt, "redirect-gateway", true); // DIRECTIVE - doinit(opt, "redirect-private", false); // DIRECTIVE - } - - unsigned int operator()() const { return flags_; } - - bool redirect_gateway_ipv4_enabled() const - { - return rg_enabled() && (flags_ & RG_IPv4); - } - - bool redirect_gateway_ipv6_enabled() const - { - return rg_enabled() && (flags_ & RG_IPv6); - } - - bool redirect_gateway_local() const - { - return flags_ & RG_LOCAL; - } - - std::string to_string() const - { - std::string ret; - ret += "[ "; - if (flags_ & RG_ENABLE) - ret += "ENABLE "; - if (flags_ & RG_REROUTE_GW) - ret += "REROUTE_GW "; - if (flags_ & RG_LOCAL) - ret += "LOCAL "; - if (flags_ & RG_AUTO_LOCAL) - ret += "AUTO_LOCAL "; - if (flags_ & RG_DEF1) - ret += "DEF1 "; - if (flags_ & RG_BYPASS_DHCP) - ret += "BYPASS_DHCP "; - if (flags_ & RG_BYPASS_DNS) - ret += "BYPASS_DNS "; - if (flags_ & RG_BLOCK_LOCAL) - ret += "BLOCK_LOCAL "; - if (flags_ & RG_IPv4) - ret += "IPv4 "; - if (flags_ & RG_IPv6) - ret += "IPv6 "; - ret += "]"; - return ret; - } - - private: - bool rg_enabled() const - { - return (flags_ & (RG_ENABLE|RG_REROUTE_GW)) == (RG_ENABLE|RG_REROUTE_GW); - } - - void doinit(const OptionList& opt, const std::string& directive, const bool redirect_gateway) - { - OptionList::IndexMap::const_iterator rg = opt.map().find(directive); - if (rg != opt.map().end()) - add_flags(opt, rg->second, redirect_gateway); - } - - void add_flags(const OptionList& opt, const OptionList::IndexList& idx, const bool redirect_gateway) - { - flags_ |= RG_ENABLE; - if (redirect_gateway) - flags_ |= RG_REROUTE_GW; - else - flags_ &= ~RG_REROUTE_GW; - for (OptionList::IndexList::const_iterator i = idx.begin(); i != idx.end(); ++i) - { - const Option& o = opt[*i]; - for (size_t j = 1; j < o.size(); ++j) - { - const std::string& f = o.get(j, 64); - if (f == "local") - flags_ |= RG_LOCAL; - else if (f == "autolocal") - flags_ |= RG_AUTO_LOCAL; - else if (f == "def1") - flags_ |= RG_DEF1; - else if (f == "bypass-dhcp") - flags_ |= RG_BYPASS_DHCP; - else if (f == "bypass-dns") - flags_ |= RG_BYPASS_DNS; - else if (f == "block-local") - flags_ |= RG_BLOCK_LOCAL; - else if (f == "ipv4") - flags_ |= RG_IPv4; - else if (f == "!ipv4") - flags_ &= ~RG_IPv4; - else if (f == "ipv6") - flags_ |= RG_IPv6; - else if (f == "!ipv6") - flags_ &= ~RG_IPv6; - } - } - } - - unsigned int flags_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/client/win/agentconfig.hpp b/Sources/OpenVPN3/openvpn/client/win/agentconfig.hpp deleted file mode 100644 index f84a816..0000000 --- a/Sources/OpenVPN3/openvpn/client/win/agentconfig.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// 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-2020 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 - -// OVPNAGENT_NAME can be passed on build command line. -// Customized agent name is needed with purpose to install -// few app with agents on one OS (e.g OC 3.0 and PT) -#ifdef OVPNAGENT_NAME -#define OVPNAGENT_NAME_STRING OPENVPN_STRINGIZE(OVPNAGENT_NAME) -#else -#define OVPNAGENT_NAME_STRING "ovpnagent" -#endif - -#include <openvpn/common/string.hpp> -#include <openvpn/common/path.hpp> - -namespace openvpn { - class Agent - { - public: - static std::string named_pipe_path() - { - return "\\\\.\\pipe\\" OVPNAGENT_NAME_STRING; - } - - static bool valid_pipe(const std::string& client_exe, - const std::string& server_exe) - { -#ifdef OVPNAGENT_DISABLE_PATH_CHECK - return true; -#else - return normalize_exe_path(client_exe) == normalize_exe_path(server_exe); -#endif - } - - private: - // If path starts with C:\..., lower-case the drive letter. - // Then strip off the basename and only return the dir. - static std::string normalize_exe_path(const std::string& path) - { - std::string p; - if (path.length() >= 3 - && std::isalpha(static_cast<unsigned char>(path[0])) != 0 - && path[1] == ':' - && path[2] == '\\') - p = string::to_lower_copy(path.substr(0, 3)) + path.substr(3); - else - p = path; - p = path::dirname(p); - return p; - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/client/win/cmdagent.hpp b/Sources/OpenVPN3/openvpn/client/win/cmdagent.hpp deleted file mode 100644 index ebe8433..0000000 --- a/Sources/OpenVPN3/openvpn/client/win/cmdagent.hpp +++ /dev/null @@ -1,315 +0,0 @@ -// 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-2020 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 <utility> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/common/jsonhelper.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/buffer/bufhex.hpp> -#include <openvpn/frame/frame_init.hpp> -#include <openvpn/ws/httpcliset.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/client/win/agentconfig.hpp> -#include <openvpn/win/modname.hpp> -#include <openvpn/tun/win/client/setupbase.hpp> -#include <openvpn/win/npinfo.hpp> -#include <openvpn/win/handlecomm.hpp> -#include <openvpn/win/event.hpp> -#include <openvpn/error/error.hpp> - -namespace openvpn { - - class WinCommandAgent : public TunWin::SetupFactory - { - public: - typedef RCPtr<WinCommandAgent> Ptr; - - OPENVPN_EXCEPTION(ovpnagent); - - static TunWin::SetupFactory::Ptr new_agent(const OptionList& opt) - { - return new WinCommandAgent(opt); - } - - static bool add_bypass_route(IP::Addr endpoint) - { - std::ostringstream os; - os << "WinCommandAgent: transmitting bypass route to " << endpoint.to_string() << std::endl; - - // Build JSON request - Json::Value jreq(Json::objectValue); -#if _WIN32_WINNT < 0x0600 // pre-Vista needs us to explicitly communicate our PID - jreq["pid"] = Json::Value((Json::UInt)::GetProcessId(::GetCurrentProcess())); -#endif - - jreq["host"] = endpoint.to_string(); - jreq["ipv6"] = endpoint.is_ipv6(); - const std::string jtxt = jreq.toStyledString(); - os << jtxt; // dump it - - OPENVPN_LOG(os.str()); - - // Create HTTP transaction container - WS::ClientSet::TransactionSet::Ptr ts = SetupClient::new_transaction_set(Agent::named_pipe_path(), 1, Win::module_name_utf8(), [](HANDLE) { }); - - SetupClient::make_transaction("add-bypass-route", jtxt, ts); - - // Execute transaction - WS::ClientSet::new_request_synchronous(ts); - - return ts->http_status_success(); - } - - private: - struct Config : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - Config() - { - npserv = Agent::named_pipe_path(); - client_exe = Win::module_name_utf8(); - debug_level = 1; - wintun = false; - } - - std::string npserv; // server pipe - std::string client_exe; // for validation - int debug_level; - bool wintun; - }; - - class SetupClient : public TunWin::SetupBase - { - public: - SetupClient(openvpn_io::io_context& io_context, - const Config::Ptr& config_arg) - : config(config_arg), - service_process(io_context) - { - } - - template<class T> - static WS::ClientSet::TransactionSet::Ptr new_transaction_set(const std::string& host, - int debug_level, - const std::string& client_exe, - T cb) - { - WS::Client::Config::Ptr hc(new WS::Client::Config()); - hc->frame = frame_init_simple(2048); - hc->connect_timeout = 30; - hc->general_timeout = 60; - - WS::ClientSet::TransactionSet::Ptr ts = new WS::ClientSet::TransactionSet; - ts->host.host = host; - ts->host.port = "np"; - ts->http_config = hc; - ts->debug_level = debug_level; - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - ts->post_connect = [host, client_exe, cb=std::move(cb)](WS::ClientSet::TransactionSet& ts, AsioPolySock::Base& sock) { - AsioPolySock::NamedPipe* np = dynamic_cast<AsioPolySock::NamedPipe*>(&sock); - if (np) - { - Win::NamedPipePeerInfoServer npinfo(np->handle.native_handle()); - const std::string server_exe = wstring::to_utf8(npinfo.exe_path); - if (!Agent::valid_pipe(client_exe, server_exe)) - OPENVPN_THROW(ovpnagent, host << " server running from " << server_exe << " could not be validated"); - cb(npinfo.proc.release()); - } - }; -#endif - return ts; - } - - static void make_transaction(const std::string& method, const std::string& content, WS::ClientSet::TransactionSet::Ptr ts) - { - std::unique_ptr<WS::ClientSet::Transaction> t(new WS::ClientSet::Transaction); - t->req.method = "POST"; - t->req.uri = "/" + method; - t->ci.type = "application/json"; - t->content_out.push_back(buf_from_string(content)); - ts->transactions.push_back(std::move(t)); - } - - private: - virtual HANDLE establish(const TunBuilderCapture& pull, - const std::wstring& openvpn_app_path, - Stop* stop, - std::ostream& os, - TunWin::RingBuffer::Ptr ring_buffer) override // TunWin::SetupBase - { - os << "SetupClient: transmitting tun setup list to " << config->npserv << std::endl; - - // Build JSON request - Json::Value jreq(Json::objectValue); -#if _WIN32_WINNT < 0x0600 // pre-Vista needs us to explicitly communicate our PID - jreq["pid"] = Json::Value((Json::UInt)::GetProcessId(::GetCurrentProcess())); -#endif - - if (ring_buffer) - ring_buffer->serialize(jreq); - - jreq["wintun"] = config->wintun; - jreq["confirm_event"] = confirm_event.duplicate_local(); - jreq["destroy_event"] = destroy_event.duplicate_local(); - jreq["tun"] = pull.to_json(); // convert TunBuilderCapture to JSON - const std::string jtxt = jreq.toStyledString(); - os << jtxt; // dump it - - // Create HTTP transaction container - WS::ClientSet::TransactionSet::Ptr ts = new_transaction_set(config->npserv, config->debug_level, config->client_exe, [this](HANDLE handle) { - service_process.assign(handle); - }); - - make_transaction("tun-setup", jtxt, ts); - - // Execute transaction - WS::ClientSet::new_request_synchronous(ts, stop); - - // Get result - const Json::Value jres = get_json_result(os, *ts); - - // Dump log - const std::string log_txt = json::get_string(jres, "log_txt"); - os << log_txt; - - // Parse TAP handle - const std::string tap_handle_hex = json::get_string(jres, "tap_handle_hex"); - os << "TAP handle: " << tap_handle_hex << std::endl; - const HANDLE tap = BufHex::parse<HANDLE>(tap_handle_hex, "TAP handle"); - return tap; - } - - virtual void l2_finish(const TunBuilderCapture& pull, - Stop* stop, - std::ostream& os) override - { - throw ovpnagent("l2_finish not implemented"); - } - - virtual bool l2_ready(const TunBuilderCapture& pull) override - { - throw ovpnagent("l2_ready not implemented"); - } - - virtual void confirm() override - { - confirm_event.signal_event(); - } - - virtual void set_service_fail_handler(std::function<void()>&& handler) - { - if (service_process.is_open()) - { - service_process.async_wait([handler=std::move(handler)](const openvpn_io::error_code& error) { - if (!error) - handler(); - }); - } - } - - virtual void destroy(std::ostream& os) override // defined by DestructorBase - { - os << "SetupClient: signaling tun destroy event" << std::endl; - service_process.close(); - destroy_event.signal_event(); - } - - Json::Value get_json_result(std::ostream& os, WS::ClientSet::TransactionSet& ts) - { - // Get content - if (ts.transactions.size() != 1) - throw ovpnagent("unexpected transaction set size"); - WS::ClientSet::Transaction& t = *ts.transactions[0]; - const std::string content = t.content_in.to_string(); - os << t.format_status(ts) << std::endl; - - if (t.comm_status_timeout()) - { - // this could be the case when agent service - // hasn't been started yet, so we throw a non-fatal - // exception which makes core retry. - os << "connection timeout"; - throw ExceptionCode(Error::TUN_ERROR); - } - - if (!t.comm_status_success()) - { - os << content; - throw ovpnagent("communication error"); - } - if (!t.request_status_success()) - { - os << content; - throw ovpnagent("request error"); - } - - // Verify content-type - if (t.reply.headers.get_value_trim("content-type") != "application/json") - { - os << content; - throw ovpnagent("unexpected content-type"); - } - - // Parse the returned json dict - Json::CharReaderBuilder builder; - std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); - Json::Value jres; - std::string err; - if (!reader->parse(content.c_str(), content.c_str() + content.size(), &jres, &err)) - { - os << content; - OPENVPN_THROW(ovpnagent, "error parsing returned JSON: " << err); - } - return jres; - } - - Config::Ptr config; - openvpn_io::windows::object_handle service_process; - Win::Event confirm_event; - Win::DestroyEvent destroy_event; - }; - - virtual TunWin::SetupBase::Ptr new_setup_obj(openvpn_io::io_context& io_context, bool wintun) override - { - if (config) - { - config->wintun = wintun; - return new SetupClient(io_context, config); - } - else - return new TunWin::Setup(io_context, wintun); - } - - WinCommandAgent(const OptionList& opt_parent) - { - config.reset(new Config); - } - - Config::Ptr config; - }; -} diff --git a/Sources/OpenVPN3/openvpn/common/abort.hpp b/Sources/OpenVPN3/openvpn/common/abort.hpp deleted file mode 100644 index 49dcd5d..0000000 --- a/Sources/OpenVPN3/openvpn/common/abort.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// 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-2020 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/>. - -// The file should include any platform-specific files necessary -// to declare the std::abort() function. - -#ifndef OPENVPN_COMMON_ABORT_H -#define OPENVPN_COMMON_ABORT_H - -#include <cstdlib> // defines std::abort() - -#endif // OPENVPN_COMMON_ABORT_H diff --git a/Sources/OpenVPN3/openvpn/common/action.hpp b/Sources/OpenVPN3/openvpn/common/action.hpp deleted file mode 100644 index 63e3ba8..0000000 --- a/Sources/OpenVPN3/openvpn/common/action.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// 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-2020 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_COMMON_ACTION_H -#define OPENVPN_COMMON_ACTION_H - -#include <vector> -#include <string> -#include <ostream> -#include <sstream> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/destruct.hpp> -#include <openvpn/common/jsonlib.hpp> - -namespace openvpn { - - struct Action : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Action> Ptr; - - virtual void execute(std::ostream& os) = 0; - virtual std::string to_string() const = 0; -#ifdef HAVE_JSON - virtual Json::Value to_json() const - { - throw Exception("Action::to_json() virtual method not implemented"); - } -#endif - virtual ~Action() {} - }; - - class ActionList : public std::vector<Action::Ptr>, public DestructorBase - { - public: - typedef RCPtr<ActionList> Ptr; - - ActionList() - { - reserve(16); - } - - void add(Action* action) - { - if (action) - emplace_back(action); - } - - void add(const Action::Ptr& action) - { - if (action) - push_back(action); - } - - void add(const ActionList& other) - { - insert(end(), other.begin(), other.end()); - } - - bool exists(const Action::Ptr& action) const - { - if (action) - { - const std::string cmp = action->to_string(); - for (auto &a : *this) - { - if (a->to_string() == cmp) - return true; - } - } - return false; - } - - virtual void execute(std::ostream& os) - { - Iter i(size(), reverse_); - while (i()) - { - if (is_halt()) - return; - try { - (*this)[i.index()]->execute(os); - } - catch (const std::exception& e) - { - os << "action exception: " << e.what() << std::endl; - } - } - } - - void execute_log() - { - std::ostringstream os; - execute(os); - OPENVPN_LOG_STRING(os.str()); - } - - std::string to_string() const - { - std::string ret; - Iter i(size(), reverse_); - while (i()) - { - ret += (*this)[i.index()]->to_string(); - ret += '\n'; - } - return ret; - } - - void enable_destroy(const bool state) - { - enable_destroy_ = state; - } - - void halt() - { - halt_ = true; - } - - virtual void destroy(std::ostream& os) override // defined by DestructorBase - { - if (enable_destroy_) - { - execute(os); - enable_destroy_ = false; - } - } - - bool is_halt() const - { - return halt_; - } - - protected: - class Iter - { - public: - Iter(size_t size, const bool reverse) - { - if (reverse) - { - idx = size; - end = -1; - delta = -1; - } - else - { - idx = -1; - end = size; - delta = 1; - } - } - - bool operator()() - { - return (idx += delta) != end; - } - - size_t index() const - { - return idx; - } - - private: - size_t idx; - size_t end; - size_t delta; - }; - - bool reverse_ = false; - bool enable_destroy_ = false; - volatile bool halt_ = false; - }; - - struct ActionListReversed : public ActionList - { - ActionListReversed() - { - reverse_ = true; - } - }; - - struct ActionListFactory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<ActionListFactory> Ptr; - - virtual ActionList::Ptr new_action_list() = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/actionthread.hpp b/Sources/OpenVPN3/openvpn/common/actionthread.hpp deleted file mode 100644 index cde4d34..0000000 --- a/Sources/OpenVPN3/openvpn/common/actionthread.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// 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-2020 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_COMMON_ACTIONTHREAD_H -#define OPENVPN_COMMON_ACTIONTHREAD_H - -#include <thread> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/log/logthread.hpp> - -namespace openvpn { - - class ActionThread : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<ActionThread> Ptr; - - struct Notify - { - virtual void action_thread_finished(const ActionThread* self, bool status) = 0; - }; - - ActionThread(openvpn_io::io_context& io_context_arg, - const ActionList::Ptr& action_list, - Notify* completion_handler_arg) - : io_context(io_context_arg), - thread(nullptr), - actions(action_list), - completion_handler(completion_handler_arg) - { - if (actions) - thread = new std::thread(&ActionThread::thread_func, this); - } - - void stop(const bool halt) - { - if (thread) - { - if (halt) - actions->halt(); - thread->join(); - delete thread; - thread = nullptr; - // Necessary because no guarantee that completion_handler - // obj will remain in scope during io_context.post delay. - completion_handler = nullptr; - } - } - - virtual ~ActionThread() - { - stop(true); - } - - private: - void completion_post(bool status) - { - Notify* n = completion_handler; - completion_handler = nullptr; - if (n) - n->action_thread_finished(this, status); - } - - void thread_func() - { - Log::Context logctx(logwrap); - bool status = false; - try { - OPENVPN_LOG("START THREAD..."); - status = actions->execute(); - OPENVPN_LOG("END THREAD"); - } - catch (const std::exception& e) - { - OPENVPN_LOG("ActionThread exception: " << e.what()); - } - openvpn_io::post(io_context, [self=Ptr(this), status]() - { - self->completion_post(status); - }); - } - - openvpn_io::io_context& io_context; - std::thread* thread; - ActionList::Ptr actions; // actions to execute in child thread - Notify* completion_handler; // completion handler - Log::Context::Wrapper logwrap; // used to carry forward the log context from parent thread - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/appversion.hpp b/Sources/OpenVPN3/openvpn/common/appversion.hpp deleted file mode 100644 index 71fdf16..0000000 --- a/Sources/OpenVPN3/openvpn/common/appversion.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// 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-2020 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_COMMON_APPVERSION_H -#define OPENVPN_COMMON_APPVERSION_H - -// BUILD_VERSION version can be passed on build command line - -#include <openvpn/common/stringize.hpp> - -#ifdef BUILD_VERSION -#define MY_VERSION OPENVPN_STRINGIZE(BUILD_VERSION) -#else -#define MY_VERSION "0.1.0" -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/arch.hpp b/Sources/OpenVPN3/openvpn/common/arch.hpp deleted file mode 100644 index 6b102cb..0000000 --- a/Sources/OpenVPN3/openvpn/common/arch.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// 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-2020 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/>. - -// define an ARCH_x macro that describes our target architecture - -#ifndef OPENVPN_COMMON_ARCH_H -#define OPENVPN_COMMON_ARCH_H - -#if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) -# define OPENVPN_ARCH_x86_64 -#elif defined(__i386__) || defined(_M_IX86) -# define OPENVPN_ARCH_i386 -#elif defined(__aarch64__) || defined(__arm64__) -# define OPENVPN_ARCH_ARM64 -#elif defined(__arm__) || defined(_M_ARM) -# define OPENVPN_ARCH_ARM -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/argv.hpp b/Sources/OpenVPN3/openvpn/common/argv.hpp deleted file mode 100644 index c8bfcf7..0000000 --- a/Sources/OpenVPN3/openvpn/common/argv.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// 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-2020 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_COMMON_ARGV_H -#define OPENVPN_COMMON_ARGV_H - -#include <cstring> // memcpy - -#include <string> -#include <vector> - -namespace openvpn { - - class Argv : public std::vector<std::string> - { - public: - Argv(const size_t capacity=16) - { - reserve(capacity); - } - - std::string to_string() const - { - std::string ret; - bool first = true; - for (const auto &s : *this) - { - if (!first) - ret += ' '; - ret += s; - first = false; - } - return ret; - } - }; - - class ArgvWrapper - { - public: - explicit ArgvWrapper(const std::vector<std::string>& argv) - { - size_t i; - argc = argv.size(); - cargv = new char *[argc+1]; - for (i = 0; i < argc; ++i) - cargv[i] = string_alloc(argv[i]); - cargv[i] = nullptr; - } - - ArgvWrapper(ArgvWrapper&& rhs) noexcept - { - argc = rhs.argc; - cargv = rhs.cargv; - rhs.argc = 0; - rhs.cargv = nullptr; - } - - ArgvWrapper& operator=(ArgvWrapper&& rhs) noexcept - { - del(); - argc = rhs.argc; - cargv = rhs.cargv; - rhs.argc = 0; - rhs.cargv = nullptr; - return *this; - } - - ~ArgvWrapper() - { - del(); - } - - char *const *c_argv() const noexcept - { - return cargv; - } - - char **c_argv() noexcept - { - return cargv; - } - - size_t c_argc() const noexcept - { - return argc; - } - - private: - ArgvWrapper(const ArgvWrapper&) = delete; - ArgvWrapper& operator=(const ArgvWrapper&) = delete; - - static char *string_alloc(const std::string& s) - { - const char *sdata = s.c_str(); - const size_t slen = s.length(); - char *ret = new char[slen+1]; - std::memcpy(ret, sdata, slen); - ret[slen] = '\0'; - return ret; - } - - void del() - { - for (size_t i = 0; i < argc; ++i) - delete [] cargv[i]; - delete [] cargv; - } - - size_t argc; - char **cargv; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/arraysize.hpp b/Sources/OpenVPN3/openvpn/common/arraysize.hpp deleted file mode 100644 index 63290a0..0000000 --- a/Sources/OpenVPN3/openvpn/common/arraysize.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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-2020 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_COMMON_ARRAYSIZE_H -#define OPENVPN_COMMON_ARRAYSIZE_H - -#include <cstddef> // defines size_t - -namespace openvpn { - template <typename T, std::size_t N> - constexpr std::size_t array_size( T (&)[N] ) { - return N; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/asyncsleep.hpp b/Sources/OpenVPN3/openvpn/common/asyncsleep.hpp deleted file mode 100644 index 72d8c02..0000000 --- a/Sources/OpenVPN3/openvpn/common/asyncsleep.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// 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-2020 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/>. - -// Interruptible sleep - -#ifndef OPENVPN_COMMON_ASYNCSLEEP_H -#define OPENVPN_COMMON_ASYNCSLEEP_H - -#include <algorithm> - -#include <openvpn/common/stop.hpp> -#include <openvpn/common/sleep.hpp> - -namespace openvpn { - - // returns false if Stop signal prevented full wait - inline bool async_sleep_milliseconds(int milliseconds, Stop* async_stop) - { - const int milliseconds_per_retry = 250; - volatile bool stop = false; - - // allow asynchronous stop - Stop::Scope stop_scope(async_stop, [&stop]() { - stop = true; - }); - - while (milliseconds > 0 && !stop) - { - const int ms = std::min(milliseconds, milliseconds_per_retry); - sleep_milliseconds(ms); - milliseconds -= ms; - } - - return !stop; - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/autoreset.hpp b/Sources/OpenVPN3/openvpn/common/autoreset.hpp deleted file mode 100644 index 95e2882..0000000 --- a/Sources/OpenVPN3/openvpn/common/autoreset.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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-2020 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/>. - -// Automatically reset a target object when -// AutoReset goes out of scope. - -#ifndef OPENVPN_COMMON_AUTORESET_H -#define OPENVPN_COMMON_AUTORESET_H - -namespace openvpn { - - template <typename T> - class AutoReset - { - public: - AutoReset(T& obj) - : obj_(&obj) - {} - - ~AutoReset() - { - if (obj_) - obj_->reset(); - } - - void disarm() - { - obj_ = nullptr; - } - - private: - T* obj_; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/base64.hpp b/Sources/OpenVPN3/openvpn/common/base64.hpp deleted file mode 100644 index 3ce6d0a..0000000 --- a/Sources/OpenVPN3/openvpn/common/base64.hpp +++ /dev/null @@ -1,321 +0,0 @@ -// 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-2020 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/>. - -// General-purpose base64 encode and decode. - -#ifndef OPENVPN_COMMON_BASE64_H -#define OPENVPN_COMMON_BASE64_H - -#include <string> -#include <cstring> // for std::memset, std::strlen -#include <algorithm> // for std::min -#include <cstddef> // for ptrdiff_t - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/extern.hpp> - -namespace openvpn { - - class Base64 { - - class ConstUCharWrap - { - public: - ConstUCharWrap(const unsigned char *data, size_t size) - : data_(data), - size_(size) - {} - - size_t size() const { return size_; } - unsigned char operator[](const size_t i) const { return data_[i]; } - - - private: - const unsigned char *data_; - size_t size_; - }; - - public: - OPENVPN_SIMPLE_EXCEPTION(base64_decode_out_of_bound_error); - - private: - // Minimal class to minic the container our decode method expects - class UCharWrap - { - public: - UCharWrap(unsigned char *data, size_t size): - data(data), size(size), index(0) - { - } - - void push_back(unsigned char c) - { - if (index >= size) - throw base64_decode_out_of_bound_error(); - - data[index++]=c; - } - - unsigned char *data; - size_t size; - size_t index; - }; - - public: - OPENVPN_SIMPLE_EXCEPTION(base64_bad_map); - OPENVPN_SIMPLE_EXCEPTION(base64_decode_error); - - // altmap is "+/=" by default - // another possible encoding for URLs: "-_." - Base64(const char *altmap = nullptr) - { - // build encoding map - { - unsigned int i; - unsigned int j = 65; - for (i = 0; i < 62; ++i) - { - enc[i] = j++; - if (j == 91) - j = 97; - else if (j == 123) - j = 48; - } - if (!altmap) - altmap = "+/="; - if (std::strlen(altmap) != 3) - throw base64_bad_map(); - enc[62] = (unsigned char)altmap[0]; - enc[63] = (unsigned char)altmap[1]; - equal = (unsigned char)altmap[2]; - } - - // build decoding map - { - std::memset(dec, 0xFF, 128); - for (unsigned int i = 0; i < 64; ++i) - { - const unsigned char c = enc[i]; - if (c >= 128) - throw base64_bad_map(); - dec[c] = (unsigned char)i; - } - } - } - - static size_t decode_size_max(const size_t encode_size) - { - return encode_size; - } - - static size_t encode_size_max(const size_t decode_size) - { - return decode_size * 4 / 3 + 4; - } - - template <typename V> - std::string encode(const V& data) const - { - char *s, *p; - size_t i; - unsigned int c; - const size_t size = data.size(); - - p = s = new char[encode_size_max(size)]; - for (i = 0; i < size; ) { - c = static_cast<unsigned char>(data[i++]) << 8; - if (i < size) - c += static_cast<unsigned char>(data[i]); - i++; - c <<= 8; - if (i < size) - c += static_cast<unsigned char>(data[i]); - i++; - p[0] = enc[(c & 0x00fc0000) >> 18]; - p[1] = enc[(c & 0x0003f000) >> 12]; - p[2] = enc[(c & 0x00000fc0) >> 6]; - p[3] = enc[c & 0x0000003f]; - if (i > size) - p[3] = equal; - if (i > size + 1) - p[2] = equal; - p += 4; - } - *p = '\0'; - const std::string ret(s); - delete [] s; - return ret; - } - - std::string encode(const void *data, size_t size) const - { - return encode(ConstUCharWrap((const unsigned char *)data, size)); - } - - /** - * Decodes data from the passed string and stores the - * result in data - * @param data Destination of the decoded data - * @param len Length of the region in data - * @param str Base64 string to decode - * @return Number of bytes written to data - */ - size_t decode(void *data, size_t len, const std::string& str) const - { - UCharWrap ret((unsigned char*)data, len); - decode(ret, str); - return ret.index; - } - - std::string decode(const std::string& str) const - { - std::string ret; - ret.reserve(str.length()); - decode(ret, str); - return ret; - } - - template <typename V> - void decode(V& dest, const std::string& str) const - { - const char *endp = str.c_str() + str.length(); - for (const char *p = str.c_str(); p < endp; p += 4) - { - unsigned int marker; - const unsigned int val = token_decode(p, std::min(endp - p, ptrdiff_t(4)), marker); - dest.push_back((val >> 16) & 0xff); - if (marker < 2) - dest.push_back((val >> 8) & 0xff); - if (marker < 1) - dest.push_back(val & 0xff); - } - } - - template <typename V> - bool is_base64(const V& data, const size_t expected_decoded_length) const - { - const size_t size = data.size(); - if (size != encoded_len(expected_decoded_length)) - return false; - const size_t eq_begin = size - num_eq(expected_decoded_length); - for (size_t i = 0; i < size; ++i) - { - const char c = data[i]; - if (i < eq_begin) - { - if (!is_base64_char(c)) - return false; - } - else - { - if (c != equal) - return false; - } - } - return true; - } - - private: - bool is_base64_char(const char c) const - { - const size_t idx = c; - return idx < 128 && dec[idx] != 0xFF; - } - - unsigned int decode_base64_char(const char c) const - { - const size_t idx = c; - if (idx >= 128) - throw base64_decode_error(); - const unsigned int v = dec[idx]; - if (v == 0xFF) - throw base64_decode_error(); - return v; - } - - unsigned int token_decode(const char *token, const ptrdiff_t len, unsigned int& marker) const - { - size_t i; - unsigned int val = 0; - marker = 0; // number of equal chars seen - if (len < 4) - throw base64_decode_error(); - for (i = 0; i < 4; i++) - { - val <<= 6; - if (token[i] == equal) - marker++; - else if (marker > 0) - throw base64_decode_error(); - else - val += decode_base64_char(token[i]); - } - if (marker > 2) - throw base64_decode_error(); - return val; - } - - static size_t encoded_len(const size_t decoded_len) - { - return (decoded_len * 4 / 3 + 3) & ~3; - } - - static size_t num_eq(const size_t decoded_len) - { - return (-1 - decoded_len) % 3; - } - - unsigned char enc[64]; - unsigned char dec[128]; - unsigned char equal; - }; - - // provide a static Base64 object - - OPENVPN_EXTERN const Base64* base64; // GLOBAL - OPENVPN_EXTERN const Base64* base64_urlsafe; // GLOBAL - - inline void base64_init_static() - { - if (!base64) - base64 = new Base64(); - if (!base64_urlsafe) - base64_urlsafe = new Base64("-_."); - } - - inline void base64_uninit_static() - { - if (base64) - { - delete base64; - base64 = nullptr; - } - if (base64_urlsafe) - { - delete base64_urlsafe; - base64_urlsafe = nullptr; - } - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/bigmutex.hpp b/Sources/OpenVPN3/openvpn/common/bigmutex.hpp deleted file mode 100644 index 99463d1..0000000 --- a/Sources/OpenVPN3/openvpn/common/bigmutex.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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/>. - -// Macro to maintain thread-safety. - -// Platforms like UWP and iOS may call core methods -// from another threads. Since core is not thread-safe, -// we provide OPENVPN_ASYNC_HANDLER macro which instantiates -// lock guard. It follows RIAA principle and locks global -// mutex in constructor and unlocks in destructor. This -// guarantees that code in block protected with this macro -// won't be called simultaneously from different threads. - -#ifndef OPENVPN_COMMON_BIGMUTEX_H -#define OPENVPN_COMMON_BIGMUTEX_H - -#include <mutex> - -#include <openvpn/common/extern.hpp> - -namespace openvpn { - namespace bigmutex { - OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex; - } - - #ifdef OPENVPN_ENABLE_BIGMUTEX - #define OPENVPN_ASYNC_HANDLER \ - std::lock_guard<std::recursive_mutex> lg(bigmutex::the_recursive_mutex); - #else - #define OPENVPN_ASYNC_HANDLER - #endif -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/binprefix.hpp b/Sources/OpenVPN3/openvpn/common/binprefix.hpp deleted file mode 100644 index 309e2fb..0000000 --- a/Sources/OpenVPN3/openvpn/common/binprefix.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// 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-2020 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_COMMON_BINPREFIX_H -#define OPENVPN_COMMON_BINPREFIX_H - -#include <algorithm> // for std::min, std::max -#include <cstring> // for std::memset, std::memcpy -#include <cstdint> // for std::uint32_t, uint64_t - -#include <openvpn/common/socktypes.hpp> // for ntohl - -namespace openvpn { - - // Return the binary prefix of a big-endian data buffer - // as a 32 bit type. - template<typename T> - inline typename std::enable_if< 4 == sizeof(T), T>::type - bin_prefix(const unsigned char *data) - { - static_assert(sizeof(T) == 4, "size inconsistency"); - return T(ntohl(*(uint32_t *)&data[0])); - } - - // Return the binary prefix of a big-endian data buffer - // as a 64 bit type. - template<typename T> - inline typename std::enable_if< 8 == sizeof(T), T>::type - bin_prefix(const unsigned char *data) - { - static_assert(sizeof(T) == 8, "size inconsistency"); - return (T(ntohl(*(uint32_t *)&data[0])) << 32) | T(ntohl(*(uint32_t *)&data[4])); - } - - template <typename T> - inline T bin_prefix(const unsigned char *data, const size_t len) - { - unsigned char d[sizeof(T)] -#ifndef _MSC_VER - __attribute__((aligned(sizeof(T)))) -#endif - ; - const size_t l = std::min(len, sizeof(d)); - std::memset(d, 0, sizeof(d)); - std::memcpy(d + sizeof(d) - l, data, l); - return bin_prefix<T>(d); - } - - template <typename T> - inline T bin_prefix_floor(const unsigned char *data, const size_t len, const T floor) - { - return std::max(bin_prefix<T>(data, len), floor); - } - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/common/circ_list.hpp b/Sources/OpenVPN3/openvpn/common/circ_list.hpp deleted file mode 100644 index 4da9734..0000000 --- a/Sources/OpenVPN3/openvpn/common/circ_list.hpp +++ /dev/null @@ -1,124 +0,0 @@ -// 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-2020 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/>. - -// A general-purpose circular list collection class. -// Used by the OpenVPN anti-replay logic. - -#ifndef OPENVPN_COMMON_CIRC_LIST_H -#define OPENVPN_COMMON_CIRC_LIST_H - -#include <vector> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -namespace openvpn { - - template <typename T> - class CircList - { - public: - OPENVPN_SIMPLE_EXCEPTION(circ_list_reset); - OPENVPN_SIMPLE_EXCEPTION(circ_list_index); - OPENVPN_SIMPLE_EXCEPTION(circ_list_const_index); - OPENVPN_SIMPLE_EXCEPTION(circ_list_push); - - CircList() { init(0); } - - explicit CircList(const size_t capacity) { init(capacity); } - - void init(const size_t capacity) - { - if (capacity) - { - data_.reserve(capacity); - capacity_ = capacity; - reset(); - } - else - { - head_ = capacity_ = 0; - data_.clear(); - } - } - - void reset() - { - if (capacity_) - { - head_ = capacity_ - 1; - data_.clear(); - } - else - throw circ_list_reset(); - } - - size_t size() const - { - return data_.size(); - } - - bool defined() const - { - return capacity_ > 0; - } - - void push(const T& item) - { - if (++head_ >= capacity_) - head_ = 0; - if (head_ < data_.size()) - data_[head_] = item; - else if (head_ == data_.size() && data_.size() < capacity_) - data_.push_back(item); - else - throw circ_list_push(); // could occur if object isn't properly initialized - } - - T& operator[](const size_t index) - { - if (index >= data_.size()) - throw circ_list_index(); - else if (index <= head_) - return data_[head_-index]; - else - return data_[head_+capacity_-index]; - } - - const T& operator[](const size_t index) const - { - if (index >= data_.size()) - throw circ_list_const_index(); - else if (index <= head_) - return data_[head_-index]; - else - return data_[head_+capacity_-index]; - } - - private: - size_t capacity_; - size_t head_; - std::vector<T> data_; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_CIRC_LIST_H diff --git a/Sources/OpenVPN3/openvpn/common/clamp.hpp b/Sources/OpenVPN3/openvpn/common/clamp.hpp deleted file mode 100644 index 9ab4f51..0000000 --- a/Sources/OpenVPN3/openvpn/common/clamp.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// 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-2020 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 - -// loose emulation of std::clamp for pre-C++17 - -namespace openvpn { - - template <typename T> - T clamp(T value, T low, T high) - { - if (value < low) - return low; - else if (value > high) - return high; - else - return value; - } - -} diff --git a/Sources/OpenVPN3/openvpn/common/cleanup.hpp b/Sources/OpenVPN3/openvpn/common/cleanup.hpp deleted file mode 100644 index 988723c..0000000 --- a/Sources/OpenVPN3/openvpn/common/cleanup.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// 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-2020 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_COMMON_CLEANUP_H -#define OPENVPN_COMMON_CLEANUP_H - -#include <utility> - -namespace openvpn { - - template <typename F> - class CleanupType - { - public: - CleanupType(F method) noexcept - : clean(std::move(method)) - { - } - - CleanupType(CleanupType&&) = default; - - ~CleanupType() - { - clean(); - } - - private: - CleanupType(const CleanupType&) = delete; - CleanupType& operator=(const CleanupType&) = delete; - - F clean; - }; - - template <typename F> - inline CleanupType<F> Cleanup(F method) noexcept - { - return CleanupType<F>(std::move(method)); - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/complog.hpp b/Sources/OpenVPN3/openvpn/common/complog.hpp deleted file mode 100644 index 7382659..0000000 --- a/Sources/OpenVPN3/openvpn/common/complog.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// 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-2020 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 - -namespace openvpn { - inline void log_compress(const std::string prefix, const size_t orig_size, const size_t new_size) - { - OPENVPN_LOG(prefix - << ' ' << orig_size - << " -> " << new_size - << " -- compression ratio: " << double(orig_size) / double(new_size)); - } -} diff --git a/Sources/OpenVPN3/openvpn/common/core.hpp b/Sources/OpenVPN3/openvpn/common/core.hpp deleted file mode 100644 index 69b6b8f..0000000 --- a/Sources/OpenVPN3/openvpn/common/core.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// 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-2020 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/>. - -// Linux methods for enumerating the number of cores on machine, -// and binding a thread to a particular core. - -#pragma once - -#include <thread> - -#include <openvpn/common/platform.hpp> - -#if defined(OPENVPN_PLATFORM_TYPE_APPLE) -#include <sys/types.h> -#include <sys/sysctl.h> -#elif defined(OPENVPN_PLATFORM_LINUX) -#include <unistd.h> -#elif defined(OPENVPN_PLATFORM_WIN) -#include <windows.h> -#endif - -namespace openvpn { - - inline int n_cores() - { - int count = std::thread::hardware_concurrency(); - // C++11 allows thread::hardware_concurrency() to return 0, fall back - // to specific solution if we detect this - if (count > 0) - return count; - -#if defined(OPENVPN_PLATFORM_TYPE_APPLE) - size_t count_len = sizeof(count); - if (::sysctlbyname("hw.logicalcpu", &count, &count_len, NULL, 0) != 0) - count = 1; - return count; -#elif defined(OPENVPN_PLATFORM_LINUX) - long ret = ::sysconf(_SC_NPROCESSORS_ONLN); - if (ret <= 0) - ret = 1; - return ret; -#elif defined(OPENVPN_PLATFORM_WIN) - SYSTEM_INFO si; - ::GetSystemInfo(&si); - return si.dwNumberOfProcessors; -#else -#error no implementation for n_cores() -#endif - } - -} diff --git a/Sources/OpenVPN3/openvpn/common/count.hpp b/Sources/OpenVPN3/openvpn/common/count.hpp deleted file mode 100644 index c214300..0000000 --- a/Sources/OpenVPN3/openvpn/common/count.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// 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-2020 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_COMMON_COUNT_H -#define OPENVPN_COMMON_COUNT_H - -namespace openvpn { - typedef long long count_t; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/daemon.hpp b/Sources/OpenVPN3/openvpn/common/daemon.hpp deleted file mode 100644 index d0857db..0000000 --- a/Sources/OpenVPN3/openvpn/common/daemon.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// 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-2020 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_COMMON_DAEMON_H -#define OPENVPN_COMMON_DAEMON_H - -#include <sys/types.h> -#include <unistd.h> - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/logrotate.hpp> -#include <openvpn/common/redir.hpp> -#include <openvpn/common/usergroup.hpp> -#include <openvpn/common/logsetup.hpp> - -namespace openvpn { - - OPENVPN_EXCEPTION(daemon_err); - - class LogReopen : public LogSetup - { - public: - LogReopen(const std::string& log_fn, - const bool combine_out_err) - : log_fn_(log_fn), - combine_out_err_(combine_out_err) - { - } - - virtual void reopen() override - { - try { - // open redirection log file, but don't redirect yet - RedirectStd redir(std::string(), - log_fn_, - RedirectStd::FLAGS_APPEND, - RedirectStd::MODE_USER_GROUP, - combine_out_err_); - - // now do the redirect - redir.redirect(); - } - catch (const std::exception& e) - { - std::cerr << "LogReopen: " << e.what() << std::endl; - } - } - - private: - const std::string log_fn_; - const bool combine_out_err_; - }; - - inline LogSetup::Ptr log_setup(const std::string& log_fn, - const SetUserGroup* user_group, - const bool log_append, - const int log_versions, - const bool stdin_to_dev_null, - const bool combine_out_err) - { - if (!log_append && log_versions >= 1) - log_rotate(log_fn, log_versions); - RedirectStd redir(stdin_to_dev_null ? "/dev/null" : "", - log_fn, - log_append ? RedirectStd::FLAGS_APPEND : RedirectStd::FLAGS_OVERWRITE, - RedirectStd::MODE_USER_GROUP, - combine_out_err); - // if user_group specified, do chown on log file - try { - if (user_group && redir.out.defined()) - user_group->chown(redir.out(), log_fn); - } - catch (const std::exception&) - { - } - redir.redirect(); - - // possibly return a LogReopen object - if (!log_versions) - return LogSetup::Ptr(new LogReopen(log_fn, combine_out_err)); - else - return LogSetup::Ptr(); - } - - inline void daemonize() - { - if (daemon(1, 1) < 0) - throw daemon_err("daemon() failed"); - } - - inline LogSetup::Ptr daemonize(const std::string& log_fn, - const SetUserGroup* user_group, - const bool log_append, - const int log_versions) - { - LogSetup::Ptr ret = log_setup(log_fn, user_group, log_append, log_versions, true, true); - daemonize(); - return ret; - } - - inline void write_pid(const std::string& fn) - { - write_string(fn, to_string(::getpid()) + '\n'); - } - - class WritePid - { - public: - WritePid(const char *pid_fn_arg) // must remain in scope for lifetime of object - : pid_fn(pid_fn_arg) - { - if (pid_fn) - write_pid(pid_fn); - } - - ~WritePid() - { - if (pid_fn) - ::unlink(pid_fn); - } - - private: - WritePid(const WritePid&) = delete; - WritePid& operator=(const WritePid&) = delete; - - const char *const pid_fn; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/demangle.hpp b/Sources/OpenVPN3/openvpn/common/demangle.hpp deleted file mode 100644 index e1507c2..0000000 --- a/Sources/OpenVPN3/openvpn/common/demangle.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// 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-2020 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/>. - -// Demangle a C++ name (GCC only) - -#ifndef OPENVPN_COMMON_DEMANGLE_H -#define OPENVPN_COMMON_DEMANGLE_H - -#include <cxxabi.h> - -#include <string> -#include <memory> - -namespace openvpn { - - inline std::string cxx_demangle(const char *mangled_name) - { - int status; - std::unique_ptr<char[]> realname; - - realname.reset(abi::__cxa_demangle(mangled_name, 0, 0, &status)); - if (!status) - return std::string(realname.get()); - else - return "DEMANGLE_ERROR"; - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/destruct.hpp b/Sources/OpenVPN3/openvpn/common/destruct.hpp deleted file mode 100644 index bd37703..0000000 --- a/Sources/OpenVPN3/openvpn/common/destruct.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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-2020 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_COMMON_DESTRUCT_H -#define OPENVPN_COMMON_DESTRUCT_H - -#include <openvpn/common/rc.hpp> - -// used for general-purpose cleanup - -namespace openvpn { - - struct DestructorBase : public RC<thread_unsafe_refcount> - { - typedef RCPtr<DestructorBase> Ptr; - virtual void destroy(std::ostream& os) = 0; - virtual ~DestructorBase() {} - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/endian.hpp b/Sources/OpenVPN3/openvpn/common/endian.hpp deleted file mode 100644 index 937d39c..0000000 --- a/Sources/OpenVPN3/openvpn/common/endian.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// 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-2020 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_platform.hpp> - -namespace openvpn { - namespace Endian { -# if defined(OPENVPN_LITTLE_ENDIAN) - inline size_t e16(const size_t v) - { - return v; - } - inline size_t e16rev(const size_t v) - { - return 15-v; - } - inline size_t e4(const size_t v) - { - return v; - } - inline size_t e4rev(const size_t v) - { - return 3-v; - } - inline size_t e2(const size_t v) - { - return v; - } - inline size_t e2rev(const size_t v) - { - return 1-v; - } -# elif defined(OPENVPN_BIG_ENDIAN) - inline size_t e16rev(const size_t v) - { - return v; - } - inline size_t e16(const size_t v) - { - return 15-v; - } - inline size_t e4rev(const size_t v) - { - return v; - } - inline size_t e4(const size_t v) - { - return 3-v; - } - inline size_t e2rev(const size_t v) - { - return v; - } - inline size_t e2(const size_t v) - { - return 1-v; - } -# else -# error One of OPENVPN_LITTLE_ENDIAN or OPENVPN_BIG_ENDIAN must be defined -# endif - } -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/common/endian64.hpp b/Sources/OpenVPN3/openvpn/common/endian64.hpp deleted file mode 100644 index 3441c25..0000000 --- a/Sources/OpenVPN3/openvpn/common/endian64.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// 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-2020 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 <cstdint> - -#include <openvpn/common/endian_platform.hpp> - -namespace openvpn { - namespace Endian { -#ifdef __MINGW32__ - inline std::uint64_t mingw_bswap64(const std::uint64_t val) - { - return (((val & (uint64_t)0x00000000000000ffULL) << 56) | - ((val & (uint64_t)0x000000000000ff00ULL) << 40) | - ((val & (uint64_t)0x0000000000ff0000ULL) << 24) | - ((val & (uint64_t)0x00000000ff000000ULL) << 8) | - ((val & (uint64_t)0x000000ff00000000ULL) >> 8) | - ((val & (uint64_t)0x0000ff0000000000ULL) >> 24) | - ((val & (uint64_t)0x00ff000000000000ULL) >> 40) | - ((val & (uint64_t)0xff00000000000000ULL) >> 56)); - } -#endif - inline std::uint64_t rev64(const std::uint64_t value) - { -#ifdef OPENVPN_LITTLE_ENDIAN -#ifdef __clang__ - return __builtin_bswap64(value); -#elif _MSC_VER - return _byteswap_uint64(value); -#elif __MINGW32__ - return mingw_bswap64(value); -#else - return __bswap_constant_64(value); -#endif /* _MSC_VER */ -#else - return value; -#endif /* OPENVPN_LITTLE_ENDIAN */ - } - } -} diff --git a/Sources/OpenVPN3/openvpn/common/endian_platform.hpp b/Sources/OpenVPN3/openvpn/common/endian_platform.hpp deleted file mode 100644 index 0d6023e..0000000 --- a/Sources/OpenVPN3/openvpn/common/endian_platform.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// 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-2020 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 diff --git a/Sources/OpenVPN3/openvpn/common/enumdir.hpp b/Sources/OpenVPN3/openvpn/common/enumdir.hpp deleted file mode 100644 index 54b58d7..0000000 --- a/Sources/OpenVPN3/openvpn/common/enumdir.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// 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-2020 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_COMMON_ENUMDIR_H -#define OPENVPN_COMMON_ENUMDIR_H - -#include <sys/types.h> -#include <dirent.h> - -#include <string> -#include <vector> -#include <utility> -#include <memory> -#include <algorithm> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/uniqueptr.hpp> - -namespace openvpn { - OPENVPN_EXCEPTION(enum_dir_error); - - template <typename F> - inline bool enum_dir(const std::string& dirname, - F func) - { - unique_ptr_del<DIR> dir(::opendir(dirname.c_str()), [](DIR* d) { ::closedir(d); }); - if (!dir) - return false; - - struct dirent *e; - while ((e = ::readdir(dir.get())) != nullptr) - { - std::string fn(e->d_name); - if (fn != "." && fn != "..") - func(std::move(fn)); - } - return true; - } - - inline std::vector<std::string> enum_dir(const std::string& dirname, - const size_t size_hint=0, - const bool sort=false) - { - std::vector<std::string> ret; - if (size_hint) - ret.reserve(size_hint); - - if (!enum_dir(dirname, [&ret](std::string fn) { - ret.push_back(std::move(fn)); - })) - throw enum_dir_error(dirname + ": cannot open directory"); - - if (sort) - std::sort(ret.begin(), ret.end()); - - return ret; - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/environ.hpp b/Sources/OpenVPN3/openvpn/common/environ.hpp deleted file mode 100644 index 873aa3b..0000000 --- a/Sources/OpenVPN3/openvpn/common/environ.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// 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-2020 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/>. - -// Environmental variables - -#ifndef OPENVPN_COMMON_ENVIRON_H -#define OPENVPN_COMMON_ENVIRON_H - -#include <string> -#include <cstring> -#include <vector> -#include <utility> - -#include <openvpn/common/size.hpp> - -extern char **environ; - -namespace openvpn { - - class Environ : public std::vector<std::string> - { - public: - static std::string find_static(const std::string& name) - { - for (char **e = ::environ; *e != NULL; ++e) - { - const char *eq = ::strchr(*e, '='); - if (eq && eq > *e) - { - const size_t namelen = eq - *e; - if (name.length() == namelen && ::strncmp(name.c_str(), *e, namelen) == 0) - return std::string(eq+1); - } - } - return ""; - } - - void load_from_environ() - { - reserve(64); - for (char **e = ::environ; *e != NULL; ++e) - emplace_back(*e); - } - - std::string to_string() const - { - std::string ret; - ret.reserve(512); - for (const auto &s : *this) - { - ret += s; - ret += '\n'; - } - return ret; - } - - int find_index(const std::string& name) const - { - for (size_type i = 0; i < size(); ++i) - { - const std::string& s = (*this)[i]; - const size_t pos = s.find_first_of('='); - if (pos != std::string::npos) - { - if (name == s.substr(0, pos)) - return i; - } - else - { - if (name == s) - return i; - } - } - return -1; - } - - std::string find(const std::string& name) const - { - const int i = find_index(name); - if (i >= 0) - return value(i); - else - return ""; - } - - std::string value(const size_t idx) const - { - const std::string& s = (*this)[idx]; - const size_t pos = s.find_first_of('='); - if (pos != std::string::npos) - return s.substr(pos+1); - else - return ""; - } - - void assign(const std::string& name, const std::string& value) - { - std::string nv = name + '=' + value; - const int i = find_index(name); - if (i >= 0) - (*this)[i] = std::move(nv); - else - push_back(std::move(nv)); - } - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/common/exception.hpp b/Sources/OpenVPN3/openvpn/common/exception.hpp deleted file mode 100644 index 907a060..0000000 --- a/Sources/OpenVPN3/openvpn/common/exception.hpp +++ /dev/null @@ -1,146 +0,0 @@ -// 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-2020 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/>. - -// Basic exception handling. Allow exception classes for specific errors -// to be easily defined, and allow exceptions to be thrown with a consise -// syntax that allows stringstream concatenation using << - -#ifndef OPENVPN_COMMON_EXCEPTION_H -#define OPENVPN_COMMON_EXCEPTION_H - -#include <string> -#include <sstream> -#include <exception> -#include <utility> - -#include <openvpn/common/stringize.hpp> // for OPENVPN_STRINGIZE -#include <openvpn/common/string.hpp> - -#ifdef OPENVPN_DEBUG_EXCEPTION - // well-known preprocessor hack to get __FILE__:__LINE__ rendered as a string -# define OPENVPN_FILE_LINE "/" __FILE__ ":" OPENVPN_STRINGIZE(__LINE__) -#else -# define OPENVPN_FILE_LINE -#endif - -namespace openvpn { - - // string exception class, where the exception is described by a std::string - class Exception : public std::exception - { - public: - Exception(const std::string& err) noexcept : err_(err) {} - Exception(std::string&& err) noexcept : err_(std::move(err)) {} - virtual const char* what() const throw() { return err_.c_str(); } - const std::string& err() const noexcept { return err_; } - virtual ~Exception() throw() {} - - void add_label(const std::string& label) - { - err_ = label + ": " + err_; - } - - void remove_label(const std::string& label) - { - const std::string head = label + ": "; - if (string::starts_with(err_, head)) - err_ = err_.substr(head.length()); - } - - private: - std::string err_; - }; - - // define a simple custom exception class with no extra info -# define OPENVPN_SIMPLE_EXCEPTION(C) \ - class C : public std::exception { \ - public: \ - virtual const char* what() const throw() { return #C OPENVPN_FILE_LINE; } \ - } - - // define a simple custom exception class with no extra info that inherits from a custom base -# define OPENVPN_SIMPLE_EXCEPTION_INHERIT(B, C) \ - class C : public B { \ - public: \ - C() : B(#C OPENVPN_FILE_LINE) {} \ - virtual const char* what() const throw() { return #C OPENVPN_FILE_LINE; } \ - } - - // define a custom exception class that allows extra info -# define OPENVPN_EXCEPTION(C) \ - class C : public openvpn::Exception { \ - public: \ - C() : openvpn::Exception(#C OPENVPN_FILE_LINE) {} \ - C(const std::string err) : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) {} \ - } - - // define a custom exception class that allows extra info, but does not emit a tag -# define OPENVPN_UNTAGGED_EXCEPTION(C) \ - class C : public openvpn::Exception { \ - public: \ - C(const std::string err) : openvpn::Exception(err) {} \ - } - - // define a custom exception class that allows extra info, and inherits from a custom base -# define OPENVPN_EXCEPTION_INHERIT(B, C) \ - class C : public B { \ - public: \ - C() : B(#C OPENVPN_FILE_LINE) {} \ - C(const std::string err) : B(#C OPENVPN_FILE_LINE ": " + err) {} \ - } - - // define a custom exception class that allows extra info, and inherits from a custom base, - // but does not emit a tag -# define OPENVPN_UNTAGGED_EXCEPTION_INHERIT(B, C) \ - class C : public B { \ - public: \ - C(const std::string err) : B(err) {} \ - } - - // throw an Exception with stringstream concatenation allowed -# define OPENVPN_THROW_EXCEPTION(stuff) \ - do { \ - std::ostringstream _ovpn_exc; \ - _ovpn_exc << stuff; \ - throw openvpn::Exception(_ovpn_exc.str()); \ - } while (0) - - // throw an OPENVPN_EXCEPTION class with stringstream concatenation allowed -# define OPENVPN_THROW(exc, stuff) \ - do { \ - std::ostringstream _ovpn_exc; \ - _ovpn_exc << stuff; \ - throw exc(_ovpn_exc.str()); \ - } while (0) - - // properly rethrow an exception that might be derived from Exception - inline void throw_ref(const std::exception& e) - { - const Exception* ex = dynamic_cast<const Exception*>(&e); - if (ex) - throw *ex; - else - throw e; - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_EXCEPTION_H diff --git a/Sources/OpenVPN3/openvpn/common/extern.hpp b/Sources/OpenVPN3/openvpn/common/extern.hpp deleted file mode 100644 index 5e51d66..0000000 --- a/Sources/OpenVPN3/openvpn/common/extern.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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-2020 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_COMMON_EXTERN_H -#define OPENVPN_COMMON_EXTERN_H - -#ifndef OPENVPN_EXTERN -// Remember that OPENVPN_EXTERN was not defined since something like -// #if OPENVPN_EXTERN == extern or OPENVPN_EXTERN == "" is not allowed -// in C/C++ preprocessor -#define OPENVPN_NO_EXTERN -#define OPENVPN_EXTERN -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/ffs.hpp b/Sources/OpenVPN3/openvpn/common/ffs.hpp deleted file mode 100644 index 86cccb3..0000000 --- a/Sources/OpenVPN3/openvpn/common/ffs.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// 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-2020 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_COMMON_FFS_H -#define OPENVPN_COMMON_FFS_H - -// find_first_set: find the one-based position of the first 1 bit in -// a word (scanning from least significant bit to most significant) - -// find_last_set: find the one-based position of the last 1 bit in -// a word (scanning from most significant bit to least significant) - -namespace openvpn { - -#if defined(__GNUC__) - - template <typename T> - inline constexpr int n_bits_type() - { - return sizeof(T) * 8; - } - - template <typename T> - inline constexpr int n_bits_type(const T& v) - { - return sizeof(v) * 8; - } - - inline int find_first_set(const unsigned int v) - { - if (!v) - return 0; - return __builtin_ffs(v); - } - - inline int find_first_set(const int v) - { - return find_first_set(static_cast<unsigned int>(v)); - } - - inline int find_last_set(const unsigned int v) - { - if (!v) - return 0; - return 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) - -#include <intrin.h> - - inline int find_first_set(unsigned int x) - { - if (!x) - return 0; - unsigned int r = 0; - _BitScanForward((unsigned long *)&r, x); - return r + 1; - } - - inline int find_last_set(unsigned int x) - { - if (!x) - return 0; - unsigned int r = 0; - _BitScanReverse((unsigned long *)&r, x); - return r + 1; - } - -#else -#error no find_first_set / find_last_set implementation for this platform -#endif - - template <typename T> - inline bool is_pow2(const T v) - { - return v && find_first_set(v) == find_last_set(v); - } - - template <typename T> - inline int log2(const T v) - { - return find_last_set(v) - 1; - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_FFS_H diff --git a/Sources/OpenVPN3/openvpn/common/file.hpp b/Sources/OpenVPN3/openvpn/common/file.hpp deleted file mode 100644 index 680449c..0000000 --- a/Sources/OpenVPN3/openvpn/common/file.hpp +++ /dev/null @@ -1,225 +0,0 @@ -// 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-2020 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/>. - -// Basic file-handling methods. - -#ifndef OPENVPN_COMMON_FILE_H -#define OPENVPN_COMMON_FILE_H - -#include <string> -#include <fstream> -#include <iostream> -#include <cstdint> // for std::uint64_t - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/buffer/buflist.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/win/unicode.hpp> -#endif - -#if __cplusplus >= 201703L -#include <filesystem> -#endif - -namespace openvpn { - - OPENVPN_UNTAGGED_EXCEPTION(file_exception); - OPENVPN_UNTAGGED_EXCEPTION_INHERIT(file_exception, open_file_error); - OPENVPN_UNTAGGED_EXCEPTION_INHERIT(file_exception, file_too_large); - OPENVPN_UNTAGGED_EXCEPTION_INHERIT(file_exception, file_is_binary); - OPENVPN_UNTAGGED_EXCEPTION_INHERIT(file_exception, file_not_utf8); - - // Read text from file via stream approach that doesn't require that we - // establish the length of the file in advance. - inline std::string read_text_simple(const std::string& filename) - { - std::ifstream ifs(filename.c_str()); - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot open for read: " << filename); - const std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot read: " << filename); - return str; - } - - // Read a file (may be text or binary). - inline BufferPtr read_binary(const std::string& filename, - const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0) - { -#if defined(OPENVPN_PLATFORM_WIN) - Win::UTF16 filenamew(Win::utf16(filename)); -#if __cplusplus >= 201703L - std::filesystem::path path(filenamew.get()); - std::ifstream ifs(path, std::ios::binary); -#elif _MSC_VER - std::ifstream ifs(filenamew.get(), std::ios::binary); -#else - std::ifstream ifs(filename.c_str(), std::ios::binary); -#endif // __cplusplus -#else - std::ifstream ifs(filename.c_str(), std::ios::binary); -#endif // OPENVPN_PLATFORM_WIN - - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot open for read: " << filename); - - // get length of file - ifs.seekg (0, std::ios::end); - const std::streamsize length = ifs.tellg(); - if (max_size && std::uint64_t(length) > max_size) - OPENVPN_THROW(file_too_large, "file too large [" << length << '/' << max_size << "]: " << filename); - ifs.seekg (0, std::ios::beg); - - // allocate buffer - BufferPtr b = new BufferAllocated(size_t(length), buffer_flags | BufferAllocated::ARRAY); - - // read data - ifs.read((char *)b->data(), length); - - // check for errors - if (ifs.gcount() != length) - OPENVPN_THROW(open_file_error, "read length inconsistency: " << filename); - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot read: " << filename); - - return b; - } - - // Read a file (may be text or binary) without seeking to determine - // its length. - inline BufferPtr read_binary_linear(const std::string& filename, - const std::uint64_t max_size = 0, - const size_t block_size = 1024) - { - std::ifstream ifs(filename.c_str(), std::ios::binary); - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot open for read: " << filename); - - BufferList buflist; - std::streamsize total_size = 0; - while (true) - { - BufferPtr b = new BufferAllocated(block_size, 0); - ifs.read((char *)b->data(), b->remaining()); - const std::streamsize size = ifs.gcount(); - if (size) - { - b->set_size(size); - total_size += size; - if (max_size && std::uint64_t(total_size) > max_size) - OPENVPN_THROW(file_too_large, "file too large [" << total_size << '/' << max_size << "]: " << filename); - buflist.push_back(std::move(b)); - } - if (ifs.eof()) - break; - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot read: " << filename); - } - return buflist.join(); - } - - // Read a text file as a std::string, throw error if file is binary - inline std::string read_text(const std::string& filename, const std::uint64_t max_size = 0) - { - BufferPtr bp = read_binary(filename, max_size); - if (bp->contains_null()) - OPENVPN_THROW(file_is_binary, "file is binary: " << filename); - return std::string((const char *)bp->c_data(), bp->size()); - } - - // Read a UTF-8 file as a std::string, throw errors if file is binary or malformed UTF-8 - inline std::string read_text_utf8(const std::string& filename, const std::uint64_t max_size = 0) - { - BufferPtr bp = read_binary(filename, max_size); - - // check if binary - if (bp->contains_null()) - OPENVPN_THROW(file_is_binary, "file is binary: " << filename); - - // remove Windows UTF-8 BOM if present - if (bp->size() >= 3) - { - const unsigned char *data = bp->c_data(); - if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) - bp->advance(3); - } - - // verify that file is valid UTF-8 - if (!Unicode::is_valid_utf8_uchar_buf(bp->c_data(), bp->size())) - OPENVPN_THROW(file_not_utf8, "file is not UTF8: " << filename); - - return std::string((const char *)bp->c_data(), bp->size()); - } - - // Read multi-line string from stdin - inline std::string read_stdin() - { - std::string ret; - std::string line; - while (std::getline(std::cin, line)) - { - ret += line; - ret += '\n'; - } - return ret; - } - - // Write binary buffer to file - inline void write_binary(const std::string& filename, const Buffer& buf) - { - std::ofstream ofs(filename.c_str(), std::ios::binary); - if (!ofs) - OPENVPN_THROW(open_file_error, "cannot open for write: " << filename); - ofs.write((const char *)buf.c_data(), buf.size()); - if (!ofs) - OPENVPN_THROW(open_file_error, "cannot write: " << filename); - } - - // Write binary buffer list to file - template <typename BUFLIST> - inline void write_binary_list(const std::string& filename, const BUFLIST& buflist) - { - std::ofstream ofs(filename.c_str(), std::ios::binary); - if (!ofs) - OPENVPN_THROW(open_file_error, "cannot open for write: " << filename); - for (auto &buf : buflist) - { - ofs.write((const char *)buf->c_data(), buf->size()); - if (!ofs) - OPENVPN_THROW(open_file_error, "cannot write: " << filename); - } - } - - // Write std::string to file - inline void write_string(const std::string& filename, const std::string& str) - { - BufferPtr buf = buf_from_string(str); - write_binary(filename, *buf); - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_FILE_H diff --git a/Sources/OpenVPN3/openvpn/common/fileatomic.hpp b/Sources/OpenVPN3/openvpn/common/fileatomic.hpp deleted file mode 100644 index fdc7f73..0000000 --- a/Sources/OpenVPN3/openvpn/common/fileatomic.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// 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-2020 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/>. - -// Atomic file-handling methods. - -#ifndef OPENVPN_COMMON_FILEATOMIC_H -#define OPENVPN_COMMON_FILEATOMIC_H - -#include <openvpn/common/platform.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) -#error atomic file methods not supported on Windows -#endif - -#include <stdio.h> // for rename() -#include <unistd.h> // for unlink() -#include <errno.h> -#include <cstring> - -#include <openvpn/common/file.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/fileunix.hpp> -#include <openvpn/common/path.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - // Atomically write binary buffer to file (relies on - // the atomicity of rename()) - inline void write_binary_atomic(const std::string& fn, - const std::string& tmpdir, - const mode_t mode, - const std::uint64_t mtime_ns, // set explicit modification-time in nanoseconds since epoch, or 0 to defer to system - const ConstBuffer& buf, - RandomAPI& rng) - { - // generate temporary filename - unsigned char data[16]; - rng.rand_fill(data); - const std::string tfn = path::join(tmpdir, '.' + path::basename(fn).substr(0, 64) + '.' + render_hex(data, sizeof(data))); - - // write to temporary file - write_binary_unix(tfn, mode, mtime_ns, buf); - - // then move into position - if (::rename(tfn.c_str(), fn.c_str()) == -1) - { - const int eno = errno; - ::unlink(tfn.c_str()); // move failed, so delete the temporary file - OPENVPN_THROW(file_unix_error, "error moving '" << tfn << "' -> '" << fn << "' : " << strerror_str(eno)); - } - } - - inline void write_binary_atomic(const std::string& fn, - const std::string& tmpdir, - const mode_t mode, - const std::uint64_t mtime_ns, - const Buffer& buf, - RandomAPI& rng) - { - return write_binary_atomic(fn, tmpdir, mode, mtime_ns, const_buffer_ref(buf), rng); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/fileunix.hpp b/Sources/OpenVPN3/openvpn/common/fileunix.hpp deleted file mode 100644 index 870d236..0000000 --- a/Sources/OpenVPN3/openvpn/common/fileunix.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// 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-2020 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/>. - -// Unix file read/write - -#ifndef OPENVPN_COMMON_FILEUNIX_H -#define OPENVPN_COMMON_FILEUNIX_H - -#include <openvpn/common/platform.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) -#error unix file methods not supported on Windows -#endif - -#include <errno.h> -#include <unistd.h> // for lseek -#include <sys/types.h> // for lseek, open -#include <sys/stat.h> // for open -#include <fcntl.h> // for open -#include <cstdint> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/write.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/common/stat.hpp> -#include <openvpn/common/modstat.hpp> -#include <openvpn/buffer/bufread.hpp> - -namespace openvpn { - OPENVPN_EXCEPTION(file_unix_error); - - // write binary buffer to file - inline void write_binary_unix(const std::string& fn, - const mode_t mode, - const std::uint64_t mtime_ns, // set explicit modification-time in nanoseconds since epoch, or 0 to defer to system - const void *buf, - const ssize_t size) - { - // open - ScopedFD fd(::open(fn.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode)); - if (!fd.defined()) - { - const int eno = errno; - throw file_unix_error(fn + " : open for write : " + strerror_str(eno)); - } - - // write - if (size) - { - const ssize_t len = write_retry(fd(), buf, size); - if (len != size) - { - if (len == -1) - { - const int eno = errno; - throw file_unix_error(fn + " : write error : " + strerror_str(eno)); - } - else - throw file_unix_error(fn + " : incomplete write, request_size=" + std::to_string(size) + " actual_size=" + std::to_string(len)); - } - } - - // explicit modification time - if (mtime_ns) - update_file_mod_time_nanoseconds(fd(), mtime_ns); - - // close - { - const int eno = fd.close_with_errno(); - if (eno) - throw file_unix_error(fn + " : close for write : " + strerror_str(eno)); - } - } - - inline void write_binary_unix(const std::string& fn, - const mode_t mode, - const std::uint64_t mtime_ns, - const Buffer& buf) - { - write_binary_unix(fn, mode, mtime_ns, buf.c_data(), buf.size()); - } - - inline void write_binary_unix(const std::string& fn, - const mode_t mode, - const std::uint64_t mtime_ns, - const ConstBuffer& buf) - { - write_binary_unix(fn, mode, mtime_ns, buf.c_data(), buf.size()); - } - - inline void write_text_unix(const std::string& fn, - const mode_t mode, - const std::uint64_t mtime_ns, - const std::string& content) - { - write_binary_unix(fn, mode, mtime_ns, content.c_str(), content.length()); - } - - enum { // MUST be distinct from BufferAllocated flags - NULL_ON_ENOENT = (1<<8), - }; - inline BufferPtr read_binary_unix(const std::string& fn, - const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0, - std::uint64_t* mtime_ns = nullptr) - { - // open - ScopedFD fd(::open(fn.c_str(), O_RDONLY|O_CLOEXEC)); - if (!fd.defined()) - { - const int eno = errno; - if ((buffer_flags & NULL_ON_ENOENT) && eno == ENOENT) - return BufferPtr(); - throw file_unix_error(fn + " : open for read : " + strerror_str(eno)); - } - - // get file timestamp - if (mtime_ns) - *mtime_ns = fd_mod_time_nanoseconds(fd()); - - // get file length - const off_t length = ::lseek(fd(), 0, SEEK_END); - if (length < 0) - { - const int eno = errno; - throw file_unix_error(fn + " : seek end error : " + strerror_str(eno)); - } - if (::lseek(fd(), 0, SEEK_SET) != 0) - { - const int eno = errno; - throw file_unix_error(fn + " : seek begin error : " + strerror_str(eno)); - } - - // maximum size exceeded? - if (max_size && std::uint64_t(length) > max_size) - throw file_unix_error(fn + " : file too large [" + std::to_string(length) + '/' + std::to_string(max_size) + ']'); - - // allocate buffer - BufferPtr bp = new BufferAllocated(size_t(length), buffer_flags); - - // read file content into buffer - while (buf_read(fd(), *bp, fn)) - ; - - // check for close error - { - const int eno = fd.close_with_errno(); - if (eno) - throw file_unix_error(fn + " : close for read : " + strerror_str(eno)); - } - - return bp; - } - - // read file into a fixed buffer, return zero or errno - inline int read_binary_unix_fast(const std::string& fn, - Buffer& out, - std::uint64_t* mtime_ns = nullptr) - { - ScopedFD fd(::open(fn.c_str(), O_RDONLY|O_CLOEXEC)); - if (!fd.defined()) - return errno; - if (mtime_ns) - *mtime_ns = fd_mod_time_nanoseconds(fd()); - while (true) - { - const size_t remaining = out.remaining(0); - if (!remaining) - return EAGAIN; // note that we also return EAGAIN if buffer is exactly the same size as content - const ssize_t status = ::read(fd(), out.data_end(), remaining); - if (status == 0) - return 0; - else if (status < 0) - return errno; - out.inc_size(status); - } - } - - inline std::string read_text_unix(const std::string& filename, - const std::uint64_t max_size = 0, - const unsigned int buffer_flags = 0, - std::uint64_t* mtime_ns = nullptr) - { - BufferPtr bp = read_binary_unix(filename, max_size, buffer_flags, mtime_ns); - if (bp) - return buf_to_string(*bp); - else - return std::string(); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/format.hpp b/Sources/OpenVPN3/openvpn/common/format.hpp deleted file mode 100644 index 107e36e..0000000 --- a/Sources/OpenVPN3/openvpn/common/format.hpp +++ /dev/null @@ -1,337 +0,0 @@ -// 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-2020 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_COMMON_FORMAT_H -#define OPENVPN_COMMON_FORMAT_H - -#include <cstddef> // for std::nullptr_t -#include <string> -#include <sstream> -#include <ostream> -#include <type_traits> -#include <utility> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - - // Concatenate arguments into a string: - // print(args...) -- concatenate - // prints(args...) -- concatenate but delimit args with space - // printd(char delim, args...) -- concatenate but delimit args with delim - - namespace print_detail { - template<typename T> - inline void print(std::ostream& os, char delim, const T& first) - { - os << first; - } - - template<typename T, typename... Args> - inline void print(std::ostream& os, char delim, const T& first, Args... args) - { - os << first; - if (delim) - os << delim; - print(os, delim, args...); - } - } - - template<typename... Args> - inline std::string printd(char delim, Args... args) - { - std::ostringstream os; - print_detail::print(os, delim, args...); - return os.str(); - } - - template<typename... Args> - inline std::string print(Args... args) - { - return printd(0, args...); - } - - template<typename... Args> - inline std::string prints(Args... args) - { - return printd(' ', args...); - } - - // String formatting similar to sprintf. - // %s formats any argument regardless of type. - // %r formats any argument regardless of type and single-quotes it. - // %R formats any argument regardless of type and double-quotes it. - // %% formats '%' - // printfmt(<format_string>, args...) - - namespace print_formatted_detail { - template<typename T> - class Output {}; - - template<> - class Output<std::string> - { - public: - Output(const size_t reserve) - { - if (reserve) - str_.reserve(reserve); - } - - // numeric types - template <typename T, - typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> - void append(T value) - { - str_ += openvpn::to_string(value); - } - - // non-numeric types not specialized below - template <typename T, - typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0> - void append(const T& value) - { - std::ostringstream os; - os << value; - str_ += os.str(); - } - - // specialization for std::string - void append(const std::string& value) - { - str_ += value; - } - - // specialization for const char * - void append(const char *value) - { - if (value) - str_ += value; - } - - // specialization for char * - void append(char *value) - { - if (value) - str_ += value; - } - - // specialization for char - void append(const char c) - { - str_ += c; - } - - // specialization for bool - void append(const bool value) - { - str_ += value ? "true" : "false"; - } - - // specialization for nullptr - void append(std::nullptr_t) - { - str_ += "nullptr"; - } - - std::string str() - { - return std::move(str_); - } - - private: - std::string str_; - }; - - template<> - class Output<std::ostringstream> - { - public: - Output(const size_t reserve) - { - // fixme -- figure out how to reserve space in std::ostringstream - } - - // general types - template <typename T> - void append(const T& value) - { - os_ << value; - } - - // specialization for const char * - void append(const char *value) - { - if (value) - os_ << value; - } - - // specialization for char * - void append(char *value) - { - if (value) - os_ << value; - } - - // specialization for bool - void append(const bool value) - { - if (value) - os_ << "true"; - else - os_ << "false"; - } - - // specialization for nullptr - void append(std::nullptr_t) - { - os_ << "nullptr"; - } - - std::string str() - { - return os_.str(); - } - - private: - std::ostringstream os_; - }; - } - - template <typename OUTPUT> - class PrintFormatted - { - public: - PrintFormatted(const std::string& fmt_arg, const size_t reserve) - : fmt(fmt_arg), - fi(fmt.begin()), - out(reserve), - pct(false) - { - } - - void process() - { - process_finish(); - } - - template<typename T> - void process(const T& last) - { - process_arg(last); - process_finish(); - } - - template<typename T, typename... Args> - void process(const T& first, Args... args) - { - process_arg(first); - process(args...); - } - - std::string str() - { - return out.str(); - } - - private: - PrintFormatted(const PrintFormatted&) = delete; - PrintFormatted& operator=(const PrintFormatted&) = delete; - - template<typename T> - bool process_arg(const T& arg) - { - while (fi != fmt.end()) - { - const char c = *fi++; - if (pct) - { - pct = false; - const int quote = quote_delim(c); - if (quote >= 0) - { - if (quote) - out.append((char)quote); - out.append(arg); - if (quote) - out.append((char)quote); - return true; - } - else - out.append(c); - } - else - { - if (c == '%') - pct = true; - else - out.append(c); - } - } - return false; - } - - void process_finish() - { - // '?' printed for %s operators that don't match an argument - while (process_arg("?")) - ; - } - - static int quote_delim(const char fmt) - { - switch (fmt) - { - case 's': - return 0; - case 'r': - return '\''; - case 'R': - return '\"'; - default: - return -1; - } - } - - const std::string& fmt; - std::string::const_iterator fi; - print_formatted_detail::Output<OUTPUT> out; - bool pct; - }; - - template<typename... Args> - inline std::string printfmt(const std::string& fmt, Args... args) - { -#ifdef OPENVPN_PLATFORM_ANDROID - PrintFormatted<std::ostringstream> pf(fmt, 256); -#else - PrintFormatted<std::string> pf(fmt, 256); -#endif - pf.process(args...); - return pf.str(); - } - -# define OPENVPN_FMT(...) OPENVPN_LOG_STRING(printfmt(__VA_ARGS__)) - -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/function.hpp b/Sources/OpenVPN3/openvpn/common/function.hpp deleted file mode 100644 index 2b15e64..0000000 --- a/Sources/OpenVPN3/openvpn/common/function.hpp +++ /dev/null @@ -1,257 +0,0 @@ -// 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-2020 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/>. - -// High-performance functor with move-only semantics. - -#ifndef OPENVPN_COMMON_FUNCTION_H -#define OPENVPN_COMMON_FUNCTION_H - -#include <cstddef> // for std::size_t -#include <utility> // for std::move -#include <type_traits> -#include <new> - -namespace openvpn { - // F -- function type (usually a lambda expression) - // N (default=3) -- max size of functor in void* machine words before we overflow to dynamic allocation - // INTERN_ONLY (default=false) -- if true, throw a static assertion if functor cannot be stored internally - template <typename F, std::size_t N=3, bool INTERN_ONLY=false> - class Function; - - template <typename R, typename... A, std::size_t N, bool INTERN_ONLY> - class Function<R(A...), N, INTERN_ONLY> - { - public: - Function() noexcept - { - methods = nullptr; - } - - template <typename T> - Function(T&& functor) noexcept - { - construct(std::move(functor)); - } - - Function(Function&& other) noexcept - { - methods = other.methods; - other.methods = nullptr; - if (methods) - methods->move(data, other.data); - } - - Function& operator=(Function&& other) noexcept - { - if (methods) - methods->destruct(data); - methods = other.methods; - other.methods = nullptr; - if (methods) - methods->move(data, other.data); - return *this; - } - - ~Function() - { - if (methods) - methods->destruct(data); - } - - template <typename T> - void reset(T&& functor) noexcept - { - if (methods) - methods->destruct(data); - construct(std::move(functor)); - } - - void reset() noexcept - { - if (methods) - { - methods->destruct(data); - methods = nullptr; - } - } - - R operator()(A... args) const - { - return methods->invoke(data, std::forward<A>(args)...); - } - - explicit operator bool() const noexcept - { - return methods != nullptr; - } - - private: -#ifdef _MSC_VER - template <typename T> - void construct(T&& functor) noexcept - { - constexpr bool is_intern = (sizeof(Intern<T>) <= sizeof(data)); - static_assert(!INTERN_ONLY || is_intern, "Function: Intern<T> doesn't fit in data[] and INTERN_ONLY=true"); - static_assert(sizeof(Extern<T>) <= sizeof(data), "Function: Extern<T> doesn't fit in data[]"); - - if (is_intern) - { - // store functor internally (in data) - setup_methods_intern<T>(); - new (data) Intern<T>(std::move(functor)); - } - else - { - // store functor externally (using new) - setup_methods_extern<T>(); - new (data) Extern<T>(std::move(functor)); - } - } -#else - template <typename T> - static constexpr bool is_intern() - { - return sizeof(Intern<T>) <= sizeof(data); - } - - template <typename T, - typename std::enable_if<is_intern<T>(), int>::type = 0> - void construct(T&& functor) noexcept - { - // store functor internally (in data) - setup_methods_intern<T>(); - new (data) Intern<T>(std::move(functor)); - } - - template <typename T, - typename std::enable_if<!is_intern<T>(), int>::type = 0> - void construct(T&& functor) noexcept - { - static_assert(!INTERN_ONLY, "Function: Intern<T> doesn't fit in data[] and INTERN_ONLY=true"); - static_assert(sizeof(Extern<T>) <= sizeof(data), "Function: Extern<T> doesn't fit in data[]"); - - // store functor externally (using new) - setup_methods_extern<T>(); - new (data) Extern<T>(std::move(functor)); - } -#endif - - struct Methods - { - R (*invoke)(void *, A&&...); - void (*move)(void *, void *); - void (*destruct)(void *); - }; - - template <typename T> - void setup_methods_intern() - { - static const struct Methods m = { - &Intern<T>::invoke, - &Intern<T>::move, - &Intern<T>::destruct, - }; - methods = &m; - } - - template <typename T> - void setup_methods_extern() - { - static const struct Methods m = { - &Extern<T>::invoke, - &Extern<T>::move, - &Extern<T>::destruct, - }; - methods = &m; - } - - // store functor internally (in data) - template <typename T> - class Intern - { - public: - Intern(T&& functor) noexcept - : functor_(std::move(functor)) - { - } - - static R invoke(void* ptr, A&&... args) - { - Intern* self = reinterpret_cast<Intern*>(ptr); - return self->functor_(std::forward<A>(args)...); - } - - static void move(void *dest, void *src) - { - Intern* s = reinterpret_cast<Intern*>(src); - new (dest) Intern(std::move(*s)); - } - - static void destruct(void *ptr) - { - Intern* self = reinterpret_cast<Intern*>(ptr); - self->~Intern(); - } - - private: - T functor_; - }; - - // store functor externally (using new) - template <typename T> - class Extern - { - public: - Extern(T&& functor) noexcept - : functor_(new T(std::move(functor))) - { - } - - static R invoke(void* ptr, A&&... args) - { - Extern* self = reinterpret_cast<Extern *>(ptr); - return (*self->functor_)(std::forward<A>(args)...); - } - - static void move(void *dest, void *src) - { - Extern* d = reinterpret_cast<Extern*>(dest); - Extern* s = reinterpret_cast<Extern*>(src); - d->functor_ = s->functor_; - // no need to set s->functor_=nullptr because parent will not destruct src after move - } - - static void destruct(void *ptr) - { - Extern* self = reinterpret_cast<Extern*>(ptr); - delete self->functor_; - } - - private: - T* functor_; - }; - - const Methods* methods; - mutable void* data[N]; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/getopt.hpp b/Sources/OpenVPN3/openvpn/common/getopt.hpp deleted file mode 100644 index a6f5742..0000000 --- a/Sources/OpenVPN3/openvpn/common/getopt.hpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 1987, 1993, 1994, 1996 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef OPENVPN_COMMON_GETOPT_H -#define OPENVPN_COMMON_GETOPT_H - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) -#include <getopt.h> -#else - -#include <cstring> // for std::strlen, std::strchr, std::strncmp - -#define GETOPT_BADCH (int)'?' -#define GETOPT_BADARG (int)':' -#define GETOPT_EMSG "" - -namespace openvpn { - - OPENVPN_SIMPLE_EXCEPTION(getopt_assert); - OPENVPN_EXCEPTION(getopt_exception); - - int opterr = 1; /* if error message should be printed */ - int optind = 1; /* index into parent argv vector */ - int optopt = 0; /* character checked for validity */ - int optreset = 0; /* reset getopt */ - const char *optarg = nullptr; /* argument associated with option */ - - struct option - { - const char *name; - int has_arg; - int *flag; - int val; - }; - - enum { - no_argument=0, - required_argument=1, - optional_argument=2 - }; - - namespace getopt_private { - inline void error(const char *prefix, int arg) - { - std::string err = prefix; - err += " -- "; - err += (char)arg; - throw getopt_exception(err); - } - - inline void error(const char *prefix, const char *arg) - { - std::string err = prefix; - err += " -- "; - err += arg; - throw getopt_exception(err); - } - - /* - * getopt -- - * Parse argc/argv argument vector. - */ - inline int getopt_internal(int nargc, char * const *nargv, const char *ostr) - { - static const char *place = GETOPT_EMSG; /* option letter processing */ - const char *oli; /* option letter list index */ - - if (!nargv || !ostr) - throw getopt_assert(); - - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc || *(place = nargv[optind]) != '-') { - place = GETOPT_EMSG; - return (-1); - } - if (place[1] && *++place == '-') { /* found "--" */ - /* ++optind; */ - place = GETOPT_EMSG; - return (-2); - } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || - !(oli = std::strchr(ostr, optopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means -1. - */ - if (optopt == (int)'-') - return (-1); - if (!*place) - ++optind; - if (opterr && *ostr != ':') - getopt_private::error("illegal option", optopt); - return (GETOPT_BADCH); - } - if (*++oli != ':') { /* don't need argument */ - optarg = nullptr; - if (!*place) - ++optind; - } else { /* need an argument */ - if (*place) /* no white space */ - optarg = place; - else if (nargc <= ++optind) { /* no arg */ - place = GETOPT_EMSG; - if ((opterr) && (*ostr != ':')) - getopt_private::error("option requires an argument", optopt); - return (GETOPT_BADARG); - } else /* white space */ - optarg = nargv[optind]; - place = GETOPT_EMSG; - ++optind; - } - return (optopt); /* dump back option letter */ - } - } - - /* - * getopt_long -- - * Parse argc/argv argument vector. - */ - inline int getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *index) - { - int retval; - - if (!nargv || !options || !long_options) - throw getopt_assert(); - - if ((retval = getopt_private::getopt_internal(nargc, nargv, options)) == -2) { - char *current_argv = nargv[optind++] + 2; - char *has_equal; - int i; - int current_argv_len; - int match = -1; - - if (*current_argv == '\0') - return(-1); - if ((has_equal = std::strchr(current_argv, '=')) != nullptr) { - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = std::strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - if (std::strncmp(current_argv, long_options[i].name, current_argv_len)) - continue; - - if (std::strlen(long_options[i].name) == (unsigned)current_argv_len) { - match = i; - break; - } - if (match == -1) - match = i; - } - if (match != -1) { - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else - optarg = nargv[optind++]; - } - if ((long_options[match].has_arg == required_argument) - && (optarg == nullptr)) { - /* - * Missing argument, leading : - * indicates no error should be generated - */ - if ((opterr) && (*options != ':')) - getopt_private::error("option requires an argument", current_argv); - return (GETOPT_BADARG); - } - } else { /* No matching argument */ - if ((opterr) && (*options != ':')) - getopt_private::error("illegal option", current_argv); - return (GETOPT_BADCH); - } - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - retval = 0; - } else - retval = long_options[match].val; - if (index) - *index = match; - } - return(retval); - } - -} -#endif -#endif diff --git a/Sources/OpenVPN3/openvpn/common/getpw.hpp b/Sources/OpenVPN3/openvpn/common/getpw.hpp deleted file mode 100644 index 5163022..0000000 --- a/Sources/OpenVPN3/openvpn/common/getpw.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// 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-2020 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_COMMON_GETPW_H -#define OPENVPN_COMMON_GETPW_H - -#include <openvpn/common/platform.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) -#include <pwd.h> -#include <unistd.h> -#endif - -#include <string> - -#include <openvpn/common/exception.hpp> - -namespace openvpn { - inline std::string get_password(const char *prompt) - { -#if !defined(OPENVPN_PLATFORM_WIN) - char *ret = getpass(prompt); - return ret; -#else - throw Exception("get_password not implemented yet for Windows"); -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/glob.hpp b/Sources/OpenVPN3/openvpn/common/glob.hpp deleted file mode 100644 index b679af2..0000000 --- a/Sources/OpenVPN3/openvpn/common/glob.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// 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-2020 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_COMMON_GLOB_H -#define OPENVPN_COMMON_GLOB_H - -#include <glob.h> - -#include <cstring> -#include <string> - -namespace openvpn { - class Glob - { - public: - Glob(const std::string& pattern, const int flags) - { - reset(); - status_ = ::glob(pattern.c_str(), flags, nullptr, &glob_); - } - - int status() const - { - return status_; - } - - size_t size() const - { - return glob_.gl_pathc; - } - - const char* operator[](const size_t i) const - { - return glob_.gl_pathv[i]; - } - - ~Glob() - { - ::globfree(&glob_); - } - - private: - void reset() - { - std::memset(&glob_, 0, sizeof(glob_)); - status_ = 0; - } - - Glob(const Glob&) = delete; - Glob& operator=(const Glob&) = delete; - - ::glob_t glob_; - int status_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/hash.hpp b/Sources/OpenVPN3/openvpn/common/hash.hpp deleted file mode 100644 index e082e84..0000000 --- a/Sources/OpenVPN3/openvpn/common/hash.hpp +++ /dev/null @@ -1,192 +0,0 @@ -// 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-2020 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_COMMON_HASH_H -#define OPENVPN_COMMON_HASH_H - -#include <string> -#include <cstdint> // for std::uint32_t, uint64_t - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/hexstr.hpp> - -#define OPENVPN_HASH_METHOD(T, meth) \ - namespace std { \ - template <> \ - struct hash<T> \ - { \ - inline std::size_t operator()(const T& obj) const \ - { \ - return obj.meth(); \ - } \ - }; \ - } - -#ifdef HAVE_CITYHASH - -#ifdef OPENVPN_HASH128_CRC -#include <citycrc.h> -#define OPENVPN_HASH128 ::CityHashCrc128WithSeed -#else -#include <city.h> -#define OPENVPN_HASH128 ::CityHash128WithSeed -#endif - -#if SIZE_MAX == 0xFFFFFFFF -#define HashSizeT Hash32 -#elif SIZE_MAX == 0xFFFFFFFFFFFFFFFF -#define HashSizeT Hash64 -#else -#error "Unrecognized SIZE_MAX" -#endif - -namespace openvpn { - - class Hash128 - { - public: - Hash128() : hashval(0,0) {} - - void operator()(const void *data, const std::size_t size) - { - hashval = OPENVPN_HASH128((const char *)data, size, hashval); - } - - void operator()(const std::string& str) - { - (*this)(str.c_str(), str.length()); - } - - template <typename T> - inline void operator()(const T& obj) - { - static_assert(std::is_pod<T>::value, "Hash128: POD type required"); - (*this)(&obj, sizeof(obj)); - } - - std::uint64_t high() const - { - return hashval.second; - } - - std::uint64_t low() const - { - return hashval.first; - } - - std::string to_string() const - { - return render_hex_number(high()) + render_hex_number(low()); - } - - private: - uint128 hashval; - }; - - class Hash64 - { - public: - Hash64(const std::uint64_t init_hashval=0) - : hashval(init_hashval) - { - } - - void operator()(const void *data, const std::size_t size) - { - hashval = ::CityHash64WithSeed((const char *)data, size, hashval); - } - - void operator()(const std::string& str) - { - (*this)(str.c_str(), str.length()); - } - - template <typename T> - inline void operator()(const T& obj) - { - static_assert(std::is_pod<T>::value, "Hash64: POD type required"); - (*this)(&obj, sizeof(obj)); - } - - std::uint64_t value() const - { - return hashval; - } - - std::string to_string() const - { - return render_hex_number(hashval); - } - - private: - std::uint64_t hashval; - }; - - class Hash32 - { - public: - Hash32(const std::uint32_t init_hashval=0) - : hashval(init_hashval) - { - } - - void operator()(const void *data, const std::size_t size) - { - hashval = hash_combine(::CityHash32((const char *)data, size), hashval); - } - - void operator()(const std::string& str) - { - (*this)(str.c_str(), str.length()); - } - - template <typename T> - inline void operator()(const T& obj) - { - static_assert(std::is_pod<T>::value, "Hash64: POD type required"); - (*this)(&obj, sizeof(obj)); - } - - std::uint32_t value() const - { - return hashval; - } - - std::string to_string() const - { - return render_hex_number(hashval); - } - - private: - static std::uint32_t hash_combine(const std::uint32_t h1, - const std::uint32_t h2) - { - return h1 ^ (h2 + 0x9e3779b9 + (h1<<6) + (h1>>2)); - } - - std::uint32_t hashval; - }; - -} - -#endif -#endif diff --git a/Sources/OpenVPN3/openvpn/common/hexstr.hpp b/Sources/OpenVPN3/openvpn/common/hexstr.hpp deleted file mode 100644 index 038c11a..0000000 --- a/Sources/OpenVPN3/openvpn/common/hexstr.hpp +++ /dev/null @@ -1,487 +0,0 @@ -// 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-2020 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/>. - -// A collection of functions for rendering and parsing hexadecimal strings - -#ifndef OPENVPN_COMMON_HEXSTR_H -#define OPENVPN_COMMON_HEXSTR_H - -#include <string> -#include <iomanip> -#include <sstream> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> - -namespace openvpn { - - /** - * Renders an integer value within the hexadecimal range (0-15) - * to a hexadecimal character. - * - * @param c Integer to render as a hexadecimal character. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a char with the hexadecimal representation of - * the input value. If the value is out-of-range (outside - * of 0-15), it will be replaced with a questionmark (?). - */ - inline char render_hex_char(const int c, const bool caps=false) - { - if (c < 10) - return '0' + c; - else if (c < 16) - return (caps ? 'A' : 'a') - 10 + c; - else - return '?'; - } - - - /** - * Parses a character in the range {0..9,A-F,a-f} to an - * integer value. Used to convert hexadecimal character to integer. - * Only a single character is parsed by this function. - * - * @param c Character to be be parsed. - * - * @return Returns an integer value of the hexadecimal input. If the - * input character is invalid, outside of {0..9,A-F,a-f}, it will - * return -1. - */ - inline int parse_hex_char(const char c) - { - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - else - return -1; - } - - - /** - * Class which Renders a single byte as hexadecimal - */ - class RenderHexByte - { - public: - /** - * Initializes a new object - * - * @param byte Unsigned char (one byte) to be processed - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - */ - RenderHexByte(const unsigned char byte, const bool caps=false) - { - c[0] = render_hex_char(byte >> 4, caps); - c[1] = render_hex_char(byte & 0x0F, caps); - } - - char char1() const { return c[0]; } - char char2() const { return c[1]; } - - /** - * Retrieve the hexadecimal representation of the value. - * Warning: The result is a non-NULL terminated string. - * - * @return Returns a non-NULL terminated 2 byte string with the hexadecimal - * representation of the initial value. The return value is guaranteed - * to always be 2 bytes. - */ - const char *str2() const { return c; } // Note: length=2, NOT null terminated - - private: - char c[2]; - }; - - - /** - * Render a byte buffer (unsigned char *) as a hexadecimal string. - * - * @param data Unsigned char pointer to buffer to render. - * @param size size_t of the number of bytes to parse from the buffer. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string of the complete hexadecimal representation - */ - inline std::string render_hex(const unsigned char *data, size_t size, const bool caps=false) - { - if (!data) - return "NULL"; - std::string ret; - ret.reserve(size*2+1); - while (size--) - { - const RenderHexByte b(*data++, caps); - ret += b.char1(); - ret += b.char2(); - } - return ret; - } - - - /** - * Render a byte buffer (void *) as a hexadecimal string. - * - * @param data Void pointer to buffer to render. - * @param size size_t of the number of bytes to parse from the buffer. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string of the complete hexadecimal representation. - */ - inline std::string render_hex(const void *data, const size_t size, const bool caps=false) - { - return render_hex((const unsigned char *)data, size, caps); - } - - - /** - * Variant of @render_hex(const unsiged char *,...) which adds a - * separator between each byte - * - * @param data Unsigned char pointer to buffer to render. - * @param size size_t of the number of bytes to parse from the buffer. - * @param sep A single character to use as the separator. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string of the complete hexadecimal representation - * with each byte separated by a given character. - */ - inline std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps=false) - { - if (!data) - return "NULL"; - std::string ret; - ret.reserve(size*3); - bool prsep = false; - while (size--) - { - if (prsep) - ret += sep; - const RenderHexByte b(*data++, caps); - ret += b.char1(); - ret += b.char2(); - prsep = true; - } - return ret; - } - - /** - * Variant of @render_hex(const void *,...) which adds a - * separator between each byte - - * @param data Void pointer to buffer to render. - * @param size size_t of the number of bytes to parse from the buffer. - * @param sep A single character to use as the separator. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string of the complete hexadecimal representation - * with each byte separated by a given character. - */ - inline std::string render_hex_sep(const void *data, const size_t size, const char sep, const bool caps=false) - { - return render_hex_sep((const unsigned char *)data, size, sep, caps); - } - - - /** - * Render a std::vector<T> container as a hexadecimal string. - * T must be a data type compatible with - * RenderHexByte(const unsigned char,...) - * - * @param data std::vector<T> containing the data to render - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string of the complete hexadecimal representation. - */ - template <typename V> - inline std::string render_hex_generic(const V& data, const bool caps=false) - { - std::string ret; - ret.reserve(data.size()*2+1); - for (size_t i = 0; i < data.size(); ++i) - { - const RenderHexByte b(data[i], caps); - ret += b.char1(); - ret += b.char2(); - } - return ret; - } - - - /** - * Renders a combined hexadecimal and character dump of a buffer, - * with the typical 16 bytes split between hexadecimal and character - * separation per line. - * - * @param data Unsigned char pointer to the buffer to dump. - * @param size Size of the buffer to render. - * - * @return Returns a string containing a preformatted output of the - * hexadecimal dump. - */ - inline std::string dump_hex(const unsigned char *data, size_t size) - { - if (!data) - return "NULL\n"; - const unsigned int mask = 0x0F; // N bytes per line - 1 - std::ostringstream os; - os << std::hex; - std::string chars; - size_t i; - for (i = 0; i < size; ++i) - { - if (!(i & mask)) - { - if (i) - { - os << " " << chars << std::endl; - chars.clear(); - } - os << std::setfill(' ') << std::setw(8) << i << ":"; - } - const unsigned char c = data[i]; - os << ' ' << std::setfill('0') << std::setw(2) << (unsigned int)c; - if (string::is_printable(c)) - chars += c; - else - chars += '.'; - } - if (i) - os << string::spaces(2 + (((i-1) & mask) ^ mask) * 3) << chars << std::endl; - return os.str(); - } - - /** - * Renders a combined hexadecimal and character dump of a buffer, - * with the typical 16 bytes split between hexadecimal and character - * separation per line. - * - * @param data Void pointer to the buffer to dump. - * @param size Size of the buffer to render. - * - * @return Returns a string containing a preformatted output of the - * hexadecimal dump. - */ - inline std::string dump_hex(void* data, size_t size) - { - return dump_hex((const unsigned char *)data, size); - } - - /** - * Renders a combined hexadecimal and character dump of a std::string buffer, - * with the typical 16 bytes split between hexadecimal and character - * separation per line. - * - * @param data std::string containing the buffer to render - * - * @return Returns a string containing a preformatted output of the - * hexadecimal dump. - */ - inline std::string dump_hex(const std::string& str) - { - return dump_hex((const unsigned char *)str.c_str(), str.length()); - } - - - /** - * Renders a combined hexadecimal and character dump of a std::vector<T> - * based buffer, with the typical 16 bytes split between hexadecimal and - * character separation per line. - * - * @param data std::vector<T> containing the buffer to render - * - * @return Returns a string containing a preformatted output of the - * hexadecimal dump. - */ - template <typename V> - inline std::string dump_hex(const V& data) - { - return dump_hex(data.c_data(), data.size()); - } - - /** - * Declaration of a hexadecimal parsing error exception class - */ - OPENVPN_SIMPLE_EXCEPTION(parse_hex_error); - - - /** - * Parses a std::string containing a hexadecimal value into - * a std::vector<T>. - * - * @param dest std::vector<T> destination buffer to use. - * @param str std::string& containing the hexadecimal string to parse. - * - * @return Returns nothing on success. Will throw a parse_hex_error - * exception if the input is invalid/not parseable as a hexadecimal - * number. - */ - template <typename V> - inline void parse_hex(V& dest, const std::string& str) - { - const int len = int(str.length()); - int i; - for (i = 0; i <= len - 2; i += 2) - { - const int high = parse_hex_char(str[i]); - const int low = parse_hex_char(str[i+1]); - if (high == -1 || low == -1) - throw parse_hex_error(); - dest.push_back((high<<4) + low); - } - if (i != len) - throw parse_hex_error(); // straggler char - } - - - /** - * Parses a char buffer (C string) containing a hexadecimal - * string into a templated (T) variable. The input buffer - * MUST be NULL terminated. - * - * WARNING: There are _NO_ overflow checks. - * - * @param str Char pointer (char *) to the buffer to be parsed. - * @param retval Return buffer where the parsed value is stored. - * - * @return Returns true on successful parsing, otherwise false. - */ - template <typename T> - inline bool parse_hex_number(const char *str, T& retval) - { - if (!str[0]) - return false; // empty string - size_t i = 0; - T ret = T(0); - while (true) - { - const char c = str[i++]; - const int hd = parse_hex_char(c); - if (hd >= 0) - { - ret *= T(16); - ret += T(hd); - } - else if (!c) - { - retval = ret; - return true; - } - else - return false; // non-hex-digit - } - } - - - /** - * Variant of @parse_hex_number(const char *, ...) which takes a std::string - * as the input. - * - * @param str std::string containing the hexadecimal string to be parsed. - * @param retval Return buffer where the parsed value is stored. - * - * @return Returns true on successful parsing, otherwise false. - */ - template <typename T> - inline bool parse_hex_number(const std::string& str, T& retval) - { - return parse_hex_number(str.c_str(), retval); - } - - - /** - * Parses a std::string containing a hexadecimal - * string into a templated (T) variable. - * - * NOTE: Currently doesn't detect overflow - * - * @param str std::string containing the hexadecimal - * string to be parsed. - * - * @return Returns a template T variable containing the - * parsed value on success. Will throw the parse_hex_error - * exception on parsing errors. - * - */ - template <typename T> - inline T parse_hex_number(const std::string& str) - { - T ret; - if (!parse_hex_number<T>(str.c_str(), ret)) - throw parse_hex_error(); - return ret; - } - - /** - * Renders a templated T variable containing a numeric value - * into a std::string containing a hexadecimal representation. - * - * @param value Numeric (T) value to represent as hexadecimal. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Retuns a std::string containing the hexadecimal - * representation on succes. Will throw a parse_hex_error - * exception on parsing errors. - */ - template <typename T> - std::string render_hex_number(T value, const bool caps=false) - { - unsigned char buf[sizeof(T)]; - for (size_t i = sizeof(T); i --> 0 ;) - { - buf[i] = value & 0xFF; - value >>= 8; - } - return render_hex(buf, sizeof(T), caps); - } - - - /** - * Renders a single byte as a hexadecimal string - * - * @param value Unsigned char (byte) to be represented as hexadecimal. - * @param caps Boolean (default false) which sets the outout to - * be either lower case (false) or upper case (true). - * - * @return Returns a std::string with the hexadecimal representation - * of the input value. The result will always contain only - * two characters. - */ - inline std::string render_hex_number(unsigned char uc, const bool caps=false) - { - RenderHexByte b(uc, caps); - return std::string(b.str2(), 2); - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_HEXSTR_H diff --git a/Sources/OpenVPN3/openvpn/common/hostlist.hpp b/Sources/OpenVPN3/openvpn/common/hostlist.hpp deleted file mode 100644 index a305b7b..0000000 --- a/Sources/OpenVPN3/openvpn/common/hostlist.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// 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-2020 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_COMMON_HOSTLIST_H -#define OPENVPN_COMMON_HOSTLIST_H - -#include <string> -#include <sstream> -#include <vector> -#include <algorithm> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - namespace HostList { - - struct Host - { - Host() {} - - Host(const std::string& host_arg, const std::string& port_arg) - : host(host_arg), - port(port_arg) - { - } - - bool defined() const - { - return !host.empty(); - } - - void swap(Host& rhs) noexcept - { - host.swap(rhs.host); - port.swap(rhs.port); - } - - void reset() - { - host.clear(); - port.clear(); - } - - std::string to_string() const - { - std::ostringstream os; - if (defined()) - os << '[' << host << "]:" << port; - else - os << "UNDEF_HOST"; - return os.str(); - } - - std::string host; - std::string port; - }; - - class List : public std::vector<Host> - { - public: - List() {} - - List(const OptionList& opt, - const std::string& directive, - const std::string& default_port) - { - auto hl = opt.get_index_ptr(directive); - if (hl) - { - for (auto &i : *hl) - { - const Option& o = opt[i]; - o.touch(); - add(o.get(1, 256), o.get_default(2, 16, default_port)); - } - } - } - - void randomize(RandomAPI& rng) - { - std::shuffle(begin(), end(), rng()); - } - - std::string to_string() const - { - std::ostringstream os; - for (auto &h : *this) - os << h.to_string() << '\n'; - return os.str(); - } - - private: - void add(const std::string& host, - const std::string& port) - { - const std::string title = "host list"; - HostPort::validate_host(host, title); - HostPort::validate_port(port, title); - emplace_back(host, port); - } - }; - - class Iterator - { - public: - Iterator() - { - reset(); - } - - void reset() - { - index = -1; - } - - template <typename HOST> - bool next(const List& list, HOST& host) - { - if (list.size() > 0) - { - if (++index >= list.size()) - index = 0; - const Host& h = list[index]; - host.host = h.host; - host.port = h.port; - return true; - } - else - return false; - } - - private: - int index; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/hostname.hpp b/Sources/OpenVPN3/openvpn/common/hostname.hpp deleted file mode 100644 index bfd7d11..0000000 --- a/Sources/OpenVPN3/openvpn/common/hostname.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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-2020 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/>. - -// Get hostname - -#ifndef OPENVPN_COMMON_HOSTNAME_H -#define OPENVPN_COMMON_HOSTNAME_H - -#include <string> - -#ifdef USE_ASIO -#include <asio/ip/host_name.hpp> -#endif - -namespace openvpn { - inline std::string get_hostname() - { -#ifdef USE_ASIO - return asio::ip::host_name(); -#else - return "HOSTNAME_UNDEFINED"; -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/hostport.hpp b/Sources/OpenVPN3/openvpn/common/hostport.hpp deleted file mode 100644 index d1ff0b1..0000000 --- a/Sources/OpenVPN3/openvpn/common/hostport.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// 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-2020 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_COMMON_HOSTPORT_H -#define OPENVPN_COMMON_HOSTPORT_H - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/unicode.hpp> - -namespace openvpn { - namespace HostPort { - OPENVPN_EXCEPTION(host_port_error); - - inline bool is_valid_port(const unsigned int port) - { - return port < 65536; - } - - inline bool is_valid_port(const std::string& port, unsigned int *value = nullptr) - { - return parse_number_validate<unsigned int>(port, 5, 1, 65535, value); - } - - inline void validate_port(const std::string& port, const std::string& title, unsigned int *value = nullptr) - { - if (!is_valid_port(port, value)) - OPENVPN_THROW(host_port_error, "bad " << title << " port number: " << Unicode::utf8_printable(port, 16)); - } - - inline void validate_port(const unsigned int port, const std::string& title) - { - if (!is_valid_port(port)) - OPENVPN_THROW(host_port_error, "bad " << title << " port number: " << port); - } - - inline unsigned short parse_port(const std::string& port, const std::string& title) - { - unsigned int ret = 0; - validate_port(port, title, &ret); - return ret; - } - - // An IP address is also considered to be a valid host - inline bool is_valid_host_char(const char c) - { - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '.' - || c == '-' - || c == ':'; // for IPv6 - } - - inline bool is_valid_host(const std::string& host) - { - if (!host.length() || host.length() > 256) - return false; - for (const auto &c : host) - { - if (!is_valid_host_char(c)) - return false; - } - return true; - } - - inline bool is_valid_unix_sock_char(const unsigned char c) - { - return c >= 0x21 && c <= 0x7E; - } - - inline bool is_valid_unix_sock(const std::string& host) - { - if (!host.length() || host.length() > 256) - return false; - for (const auto &c : host) - { - if (!is_valid_unix_sock_char(c)) - return false; - } - return true; - } - - inline void validate_host(const std::string& host, const std::string& title) - { - if (!is_valid_host(host)) - OPENVPN_THROW(host_port_error, "bad " << title << " host: " << Unicode::utf8_printable(host, 64)); - } - - inline bool split_host_port(const std::string& str, - std::string& host, - std::string& port, - const std::string& default_port, - const bool allow_unix, - unsigned int *port_save = nullptr) - { - if (port_save) - *port_save = 0; - const size_t pos = str.find_last_of(':'); - const size_t cb = str.find_last_of(']'); - if (pos != std::string::npos && (cb == std::string::npos || pos > cb)) - { - // host:port or [host]:port specified - host = str.substr(0, pos); - port = str.substr(pos + 1); - } - else if (!default_port.empty()) - { - // only host specified - host = str; - port = default_port; - } - else - return false; - - // unbracket host - if (host.length() >= 2 && host[0] == '[' && host[host.length()-1] == ']') - host = host.substr(1, host.length()-2); - - if (allow_unix && port == "unix") - return is_valid_unix_sock(host); - else - return is_valid_host(host) && is_valid_port(port, port_save); - } - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/indexed_title.hpp b/Sources/OpenVPN3/openvpn/common/indexed_title.hpp deleted file mode 100644 index 99e69fc..0000000 --- a/Sources/OpenVPN3/openvpn/common/indexed_title.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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-2020 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 <openvpn/common/size.hpp> - -namespace openvpn { - - // TITLE class for representing an object name and index. - // Useful for referring to array indices when generating errors. - class IndexedTitle - { - public: - IndexedTitle(const char *title, const size_t index) - : title_(title), - index_(index) - { - } - - std::string to_string() const - { - return std::string(title_) + '.' + std::to_string(index_); - } - - bool empty() const - { - return false; - } - - private: - const char *title_; - size_t index_; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/common/jsonfile.hpp b/Sources/OpenVPN3/openvpn/common/jsonfile.hpp deleted file mode 100644 index 691ec73..0000000 --- a/Sources/OpenVPN3/openvpn/common/jsonfile.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// 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-2020 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/jsonhelper.hpp> -#include <openvpn/common/fileatomic.hpp> - -namespace openvpn { - namespace json { - - inline Json::Value read_fast(const std::string& fn, - const bool optional=true, - std::uint64_t* mtime_ns=nullptr) - { - BufferPtr bp = read_binary_unix(fn, 0, optional ? NULL_ON_ENOENT : 0, mtime_ns); - if (!bp || bp->empty()) - return Json::Value(); - return parse_from_buffer(*bp, fn); - } - - inline void write_atomic(const std::string& fn, - const std::string& tmpdir, - const mode_t mode, - const std::uint64_t mtime_ns, // set explicit modification-time in nanoseconds since epoch, or 0 to defer to system - const Json::Value& root, - const size_t size_hint, - RandomAPI& rng) - { - BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); - format_compact(root, *bp); - write_binary_atomic(fn, tmpdir, mode, mtime_ns, *bp, rng); - } - - inline void write_fast(const std::string& fn, - const mode_t mode, - const std::uint64_t mtime_ns, // set explicit modification-time in nanoseconds since epoch, or 0 to defer to system - const Json::Value& root, - const size_t size_hint) - { - BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); - format_compact(root, *bp); - write_binary_unix(fn, mode, mtime_ns, *bp); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/common/jsonhelper.hpp b/Sources/OpenVPN3/openvpn/common/jsonhelper.hpp deleted file mode 100644 index b02741a..0000000 --- a/Sources/OpenVPN3/openvpn/common/jsonhelper.hpp +++ /dev/null @@ -1,823 +0,0 @@ -// 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-2020 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 <cstdint> -#include <utility> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/common/jsonhelperfmt.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/buffer/bufstream.hpp> - -#ifndef HAVE_JSON -#error no JSON library available -#endif - -namespace openvpn { - namespace json { - - OPENVPN_EXCEPTION(json_parse); - - template <typename TITLE> - inline Json::Value parse(const std::string& str, const TITLE& title) - { -#ifdef OPENVPN_JSON - return Json::Value::parse(str, StringTempl::to_string(title)); -#else - Json::CharReaderBuilder builder; - builder["collectComments"] = false; - Json::Value root; - std::string errors; - std::istringstream instr(str); - - if (!Json::parseFromStream(builder, instr, &root, &errors)) - throw json_parse(StringTempl::to_string(title) + " : " + errors); - return root; -#endif - } - - inline Json::Value parse(const std::string& str) - { - return parse(str, "json"); - } - - inline Json::Value parse_from_file(const std::string& fn) - { - return parse(read_text_utf8(fn), fn); - } - - template <typename BUFFER, typename TITLE> - inline Json::Value parse_from_buffer(const BUFFER& buf, const TITLE& title) - { -#ifdef OPENVPN_JSON - return Json::Value::parse(buf, StringTempl::to_string(title)); -#else - Json::CharReaderBuilder builder; - builder["collectComments"] = false; - Json::Value root; - std::string errors; - - std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); - if (!reader->parse(reinterpret_cast<const char *>(buf.c_data()), reinterpret_cast<const char *>(buf.c_data()) + buf.size(), &root, &errors)) - throw json_parse(StringTempl::to_string(title) + " : " + errors); - return root; -#endif - } - -#ifdef OPENVPN_JSON_INTERNAL - template <typename NAME, typename TITLE> - inline const Json::Value& cast(const Json::ValueType target_type, - const Json::Value& value, - const NAME& name, - const bool optional, - const TITLE& title) - { - if (value.isNull()) - { - if (optional) - return value; - throw json_parse(Json::Value::type_string(target_type) + " cast " + fmt_name(name, title) + " is null"); - } - if (!value.isConvertibleTo(target_type)) - throw json_parse(Json::Value::type_string(target_type) + " cast " + fmt_name(name, title) + " is of incorrect type (" + value.type_string() + ')'); - return value; - } - - template <typename NAME, typename TITLE> - inline const Json::Value& cast(const Json::ValueType target_type, - const Json::Value& value, - const NAME& name, - const bool optional) - { - return cast(target_type, value, name, optional, nullptr); - } -#endif - - template <typename T, typename NAME> - inline void from_vector(Json::Value& root, const T& vec, const NAME& name) - { - Json::Value array(Json::arrayValue); - for (auto &e : vec) - array.append(e.to_json()); - if (array.size()) - root[name] = array; - } - - template <typename TITLE> - inline void assert_dict(const Json::Value& obj, const TITLE& title) - { - if (!obj.isObject()) - throw json_parse(fmt_name_cast(title) + " is not a JSON dictionary"); - } - - template <typename TITLE> - inline bool is_dict(const Json::Value& obj, const TITLE& title) - { - if (obj.isNull()) - return false; - assert_dict(obj, title); - return true; - } - - template <typename NAME> - inline bool exists(const Json::Value& root, const NAME& name) - { - if (!root.isObject()) - return false; - return !root[name].isNull(); - } - - template <typename NAME> - inline bool string_exists(const Json::Value& root, const NAME& name) - { - if (!root.isObject()) - return false; - return root[name].isString(); - } - - template <typename T, typename NAME, typename TITLE> - inline void to_vector(const Json::Value& root, T& vec, - const NAME& name, - const TITLE& title) - { - const Json::Value& array = root[name]; - if (array.isNull()) - return; - if (!array.isArray()) - throw json_parse("array " + fmt_name(name, title) + " is of incorrect type"); - for (unsigned int i = 0; i < array.size(); ++i) - { - vec.emplace_back(); - vec.back().from_json(array[i], fmt_name(name, title)); - } - } - - template <typename NAME, typename TITLE> - inline std::string get_string(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("string " + fmt_name(name, title) + " is missing"); - if (!value.isString()) - throw json_parse("string " + fmt_name(name, title) + " is of incorrect type"); - return value.asString(); - } - - template <typename NAME> - inline std::string get_string(const Json::Value& root, const NAME& name) - { - return get_string(root, name, nullptr); - } - -#ifdef OPENVPN_JSON_INTERNAL - template <typename NAME, typename TITLE> - inline const std::string& get_string_ref(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("string " + fmt_name(name, title) + " is missing"); - if (!value.isString()) - throw json_parse("string " + fmt_name(name, title) + " is of incorrect type"); - return value.asStringRef(); - } - - template <typename NAME> - inline const std::string& get_string_ref(const Json::Value& root, const NAME& name) - { - return get_string_ref(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline const std::string* get_string_ptr(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return nullptr; - if (!value.isString()) - throw json_parse("string " + fmt_name(name, title) + " is of incorrect type"); - return value.asStringPtr(); - } - - template <typename NAME> - inline const std::string* get_string_ptr(const Json::Value& root, const NAME& name) - { - return get_string_ptr(root, name, nullptr); - } -#endif - - template <typename NAME, typename TITLE> - inline std::string get_string_optional(const Json::Value& root, - const NAME& name, - const std::string& default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isString()) - throw json_parse("string " + fmt_name(name, title) + " is of incorrect type"); - return value.asString(); - } - - template <typename NAME> - inline std::string get_string_optional(const Json::Value& root, - const NAME& name, - const std::string& default_value) - { - return get_string_optional(root, name, default_value, nullptr); - } - - template <typename TITLE> - inline std::string get_string_from_array(const Json::Value& root, - const Json::ArrayIndex index, - const TITLE& title) - { - const Json::Value& value = root[index]; - if (value.isNull()) - throw json_parse("string " + fmt_name(index, title) + " is missing"); - if (!value.isString()) - throw json_parse("string " + fmt_name(index, title) + " is of incorrect type"); - return value.asString(); - } - - inline std::string get_string_from_array(const Json::Value& root, - const Json::ArrayIndex index) - { - return get_string_from_array(root, index, nullptr); - } - - template <typename NAME, typename TITLE> - inline int get_int(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("int " + fmt_name(name, title) + " is missing"); - if (!value.isInt()) - throw json_parse("int " + fmt_name(name, title) + " is of incorrect type"); - return value.asInt(); - } - - template <typename NAME> - inline int get_int(const Json::Value& root, const NAME& name) - { - return get_int(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline int get_int_optional(const Json::Value& root, - const NAME& name, - const int default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isInt()) - throw json_parse("int " + fmt_name(name, title) + " is of incorrect type"); - return value.asInt(); - } - - template <typename NAME> - inline int get_int_optional(const Json::Value& root, - const NAME& name, - const int default_value) - { - return get_int_optional(root, name, default_value, nullptr); - } - - template <typename NAME, typename TITLE> - inline unsigned int get_uint(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("uint " + fmt_name(name, title) + " is missing"); - if (!value.isUInt()) - throw json_parse("uint " + fmt_name(name, title) + " is of incorrect type"); - return value.asUInt(); - } - - template <typename NAME> - inline unsigned int get_uint(const Json::Value& root, const NAME& name) - { - return get_uint(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline unsigned int get_uint_optional(const Json::Value& root, - const NAME& name, - const unsigned int default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isUInt()) - throw json_parse("uint " + fmt_name(name, title) + " is of incorrect type"); - return value.asUInt(); - } - - template <typename NAME> - inline unsigned int get_uint_optional(const Json::Value& root, - const NAME& name, - const unsigned int default_value) - { - return get_uint_optional(root, name, default_value, nullptr); - } - - template <typename NAME, typename TITLE> - inline unsigned int get_uint_via_string(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("uint-via-string " + fmt_name(name, title) + " is missing"); - if (!value.isString()) - throw json_parse("uint-via-string " + fmt_name(name, title) + " is of incorrect type"); - - unsigned int ret; - if (!parse_number(value.asString(), ret)) - throw json_parse("uint-via-string " + fmt_name(name, title) + " failed to parse"); - return ret; - } - - template <typename NAME> - inline unsigned int get_uint_via_string(const Json::Value& root, - const NAME& name) - { - return get_uint_via_string(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline unsigned int get_uint_optional_via_string(const Json::Value& root, - const NAME& name, - const unsigned int default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isString()) - throw json_parse("uint-via-string " + fmt_name(name, title) + " is of incorrect type"); - - unsigned int ret; - if (!parse_number(value.asString(), ret)) - throw json_parse("uint-via-string " + fmt_name(name, title) + " failed to parse"); - return ret; - } - - template <typename NAME> - inline unsigned int get_uint_optional_via_string(const Json::Value& root, - const NAME& name, - const unsigned int default_value) - { - return get_uint_optional_via_string(root, name, default_value, nullptr); - } - - template <typename NAME, typename TITLE> - inline std::uint64_t get_uint64(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("uint64 " + fmt_name(name, title) + " is missing"); - if (!value.isUInt64()) - throw json_parse("uint64 " + fmt_name(name, title) + " is of incorrect type"); - return value.asUInt64(); - } - - template <typename NAME> - inline std::uint64_t get_uint64(const Json::Value& root, const NAME& name) - { - return get_uint64(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline std::uint64_t get_uint64_optional(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isUInt64()) - throw json_parse("uint64 " + fmt_name(name, title) + " is of incorrect type"); - return value.asUInt64(); - } - - template <typename NAME, typename TITLE> - inline std::int64_t get_int64_optional(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isInt64()) - throw json_parse("int64 " + fmt_name(name, title) + " is of incorrect type"); - return value.asInt64(); - } - - template <typename NAME> - inline std::uint64_t get_uint64_optional(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value) - { - return get_uint64_optional(root, name, default_value, nullptr); - } - - /* - * The get_integer_optional function are used to select the right - * method based on the default_value parameter - */ - - template<typename NAME, typename TITLE> - std::uint64_t get_integer_optional(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value, - const TITLE& title) - { - return get_uint64_optional(root, name, default_value, title); - } - - template<typename NAME, typename TITLE> - std::int64_t get_integer_optional(const Json::Value& root, - const NAME& name, - const std::int64_t default_value, - const TITLE& title) - { - return get_int64_optional(root, name, default_value, title); - } - - template<typename NAME, typename TITLE> - inline unsigned int get_integer_optional(const Json::Value& root, - const NAME& name, - const unsigned int default_value, - const TITLE& title) - { - return get_uint_optional(root, name, default_value, title); - } - - template<typename NAME, typename TITLE> - inline int get_integer_optional(const Json::Value& root, - const NAME& name, - const int default_value, - const TITLE& title) - { - return get_int_optional(root, name, default_value, title); - } - - template <typename NAME, typename TITLE> - inline std::uint64_t get_uint64_via_string(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("uint64-via-string " + fmt_name(name, title) + " is missing"); - if (!value.isString()) - throw json_parse("uint64-via-string " + fmt_name(name, title) + " is of incorrect type"); - - std::uint64_t ret; - if (!parse_number(value.asString(), ret)) - throw json_parse("uint64-via-string " + fmt_name(name, title) + " failed to parse"); - return ret; - } - - template <typename NAME> - inline std::uint64_t get_uint64_via_string(const Json::Value& root, - const NAME& name) - { - return get_uint64_via_string(root, name, nullptr); - } - - template <typename NAME, typename TITLE> - inline std::uint64_t get_uint64_optional_via_string(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - return default_value; - if (!value.isString()) - throw json_parse("uint64-via-string " + fmt_name(name, title) + " is of incorrect type"); - - std::uint64_t ret; - if (!parse_number(value.asString(), ret)) - throw json_parse("uint64-via-string " + fmt_name(name, title) + " failed to parse"); - return ret; - } - - template <typename NAME> - inline std::uint64_t get_uint64_optional_via_string(const Json::Value& root, - const NAME& name, - const std::uint64_t default_value) - { - return get_uint64_optional_via_string(root, name, default_value, nullptr); - } - template <typename NAME, typename TITLE> - inline bool get_bool(const Json::Value& root, - const NAME& name, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - throw json_parse("bool " + fmt_name(name, title) + " is missing"); - if (!value.isBool()) - throw json_parse("bool " + fmt_name(name, title) + " is of incorrect type"); - return value.asBool(); - } - - template <typename NAME> - inline bool get_bool(const Json::Value& root, const NAME& name) - { - return get_bool(root, name, nullptr); - } - - template <typename NAME> - inline bool get_bool_optional(const Json::Value& root, - const NAME& name, - const bool default_value=false) - { - const Json::Value& jv = root[name]; - if (jv.isConvertibleTo(Json::booleanValue)) - return jv.asBool(); - else - return default_value; - } - - template <typename NAME> - inline int get_bool_tristate(const Json::Value& root, - const NAME& name) - { - const Json::Value& jv = root[name]; - if (jv.isConvertibleTo(Json::booleanValue)) - return jv.asBool() ? 1 : 0; - else - return -1; - } - - template <typename NAME, typename TITLE> - inline const Json::Value& get_dict(const Json::Value& root, - const NAME& name, - const bool optional, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - { - if (optional) - return value; - throw json_parse("dictionary " + fmt_name(name, title) + " is missing"); - } - if (!value.isObject()) - throw json_parse("dictionary " + fmt_name(name, title) + " is of incorrect type"); - return value; - } - - template <typename NAME> - inline const Json::Value& get_dict(const Json::Value& root, - const NAME& name, - const bool optional) - { - return get_dict(root, name, optional, nullptr); - } - - template <typename TITLE> - inline const Json::Value& cast_dict(const Json::Value& value, - const bool optional, - const TITLE& title) - { - if (value.isNull()) - { - if (optional) - return value; - throw json_parse("dictionary cast " + fmt_name_cast(title) + " is null"); - } - if (!value.isObject()) - throw json_parse("dictionary cast " + fmt_name_cast(title) + " is of incorrect type"); - return value; - } - - inline const Json::Value& cast_dict(const Json::Value& value, - const bool optional) - { - return cast_dict(value, optional, nullptr); - } - - template <typename NAME, typename TITLE> - inline const Json::Value& get_array(const Json::Value& root, - const NAME& name, - const bool optional, - const TITLE& title) - { - const Json::Value& value = root[name]; - if (value.isNull()) - { - if (optional) - return value; - throw json_parse("array " + fmt_name(name, title) + " is missing"); - } - if (!value.isArray()) - throw json_parse("array " + fmt_name(name, title) + " is of incorrect type"); - return value; - } - - template <typename NAME> - inline const Json::Value& get_array(const Json::Value& root, - const NAME& name, - const bool optional) - { - return get_array(root, name, optional, nullptr); - } - - template <typename TITLE> - inline const Json::Value& cast_array(const Json::Value& value, - const bool optional, - const TITLE& title) - { - if (value.isNull()) - { - if (optional) - return value; - throw json_parse("array cast " + fmt_name_cast(title) + " is null"); - } - if (!value.isArray()) - throw json_parse("array cast " + fmt_name_cast(title) + " is of incorrect type"); - return value; - } - - inline const Json::Value& cast_array(const Json::Value& value, - const bool optional) - { - return cast_array(value, optional, nullptr); - } - - template <typename NAME, typename TITLE> - inline void to_string(const Json::Value& root, - std::string& dest, - const NAME& name, - const TITLE& title) - { - dest = get_string(root, name, title); - } - - template <typename NAME, typename TITLE> - inline void to_string_optional(const Json::Value& root, - std::string& dest, - const NAME& name, - const std::string& default_value, - const TITLE& title) - { - dest = get_string_optional(root, name, default_value, title); - } - - template <typename NAME, typename TITLE> - inline void to_int(const Json::Value& root, - int& dest, - const NAME& name, - const TITLE& title) - { - dest = get_int(root, name, title); - } - - template <typename NAME, typename TITLE> - inline void to_uint(const Json::Value& root, - unsigned int& dest, - const NAME& name, - const TITLE& title) - { - dest = get_uint(root, name, title); - } - - template <typename NAME, typename TITLE> - inline void to_uint_optional(const Json::Value& root, - unsigned int& dest, - const NAME& name, - const unsigned int default_value, - const TITLE& title) - { - dest = get_uint_optional(root, name, default_value, title); - } - - template <typename NAME, typename TITLE> - inline void to_uint64(const Json::Value& root, - std::uint64_t& dest, - const NAME& name, - const TITLE& title) - { - dest = get_uint64(root, name, title); - } - - template <typename NAME, typename TITLE> - inline void to_bool(const Json::Value& root, - bool& dest, - const NAME& name, - const TITLE& title) - { - dest = get_bool(root, name, title); - } - - inline void format_compact(const Json::Value& root, Buffer& buf) - { -#ifdef OPENVPN_JSON - root.toCompactString(buf); -#else - Json::StreamWriterBuilder json_builder; - json_builder.settings_["indentation"] = ""; - BufferStreamOut os(buf); - std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter()); - sw->write(root, &os); -#endif - } - - inline std::string format_compact(const Json::Value& root, - const size_t size_hint=256) - { - BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); - format_compact(root, *bp); - return buf_to_string(*bp); - } - - inline void format(const Json::Value& root, Buffer& buf) - { -#ifdef OPENVPN_JSON - root.toStyledString(buf); -#else - Json::StreamWriterBuilder json_builder; - json_builder.settings_["indentation"] = " "; - BufferStreamOut os(buf); - std::unique_ptr<Json::StreamWriter> sw(json_builder.newStreamWriter()); - sw->write(root, &os); -#endif - } - - inline std::string format(const Json::Value& root) - { - return root.toStyledString(); - } - - inline std::string error(const Json::Value& root) - { - const Json::Value& je = root["error"]; - if (je.isString()) - return je.asString(); - else - return std::string(); - } - - // Guarantee that json object jr is a dictionary. - // Do this by encapsulating jr in a dictionary - // { "result": jr } if it is not already one. - inline Json::Value dict_result(Json::Value jr) - { - if (jr.isObject()) - return jr; - else { - Json::Value jret(Json::objectValue); - jret["result"] = std::move(jr); - return jret; - } - } - } -} diff --git a/Sources/OpenVPN3/openvpn/common/jsonhelperfmt.hpp b/Sources/OpenVPN3/openvpn/common/jsonhelperfmt.hpp deleted file mode 100644 index b6edfe6..0000000 --- a/Sources/OpenVPN3/openvpn/common/jsonhelperfmt.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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 <openvpn/common/stringtempl2.hpp> - -namespace openvpn { - namespace json { - - // format name.title but omit .title if title is empty - template <typename NAME, typename TITLE> - inline std::string fmt_name(const NAME& name, const TITLE& title) - { - if (!StringTempl::empty(title)) - return StringTempl::to_string(title) + '.' + StringTempl::to_string(name); - else - return StringTempl::to_string(name); - } - - // if title is not a number, treat as an ordinary string - template <typename TITLE, - typename std::enable_if<!std::is_arithmetic<TITLE>::value, int>::type = 0> - inline std::string fmt_name_cast(const TITLE& title) - { - return StringTempl::to_string(title); - } - - // if title is a number, assume that it is referring to an array element - template <typename TITLE, - typename std::enable_if<std::is_arithmetic<TITLE>::value, int>::type = 0> - inline std::string fmt_name_cast(const TITLE& title) - { - return "element." + StringTempl::to_string(title); - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/common/jsonlib.hpp b/Sources/OpenVPN3/openvpn/common/jsonlib.hpp deleted file mode 100644 index b6a1f26..0000000 --- a/Sources/OpenVPN3/openvpn/common/jsonlib.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// 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-2020 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 - -#if defined(HAVE_JSONCPP) -#define HAVE_JSON -#include "json/json.h" // JsonCpp library -#elif defined(HAVE_OPENVPN_COMMON) -#define HAVE_JSON -#define OPENVPN_JSON_INTERNAL -#include <openvpn/common/json.hpp> // internal OpenVPN JSON implementation -#endif diff --git a/Sources/OpenVPN3/openvpn/common/lex.hpp b/Sources/OpenVPN3/openvpn/common/lex.hpp deleted file mode 100644 index f3da7a9..0000000 --- a/Sources/OpenVPN3/openvpn/common/lex.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// 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-2020 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/>. - -// A set of lexical analyzer classes. These classes can be combined -// with the methods in split.hpp to create parsers. - -#pragma once - -#include <openvpn/common/string.hpp> - -namespace openvpn { - - // This class (or others that define an is_space method) is used as a - // template parameter to methods in split.hpp. - struct SpaceMatch - { - static bool is_space(char c) - { - return string::is_space(c); - } - }; - - // A basic lexical analyzer that understands quoting - class StandardLex - { - public: - void put(char c) - { - in_backslash_ = false; - if (backslash_) - { - ch = c; - backslash_ = false; - in_backslash_ = true; - } - else if (c == '\\') - { - backslash_ = true; - ch = -1; - } - else if (c == '\"') - { - in_quote_ = !in_quote_; - ch = -1; - } - else - ch = c; - } - - bool available() const { return ch != -1; } - int get() const { return ch; } - void reset() { ch = -1; } - - bool in_quote() const { return in_quote_; } - bool in_backslash() const { return in_backslash_; } - - private: - bool in_quote_ = false; - bool backslash_ = false; - bool in_backslash_ = false; - int ch = -1; - }; - - // A null lexical analyzer has no special understanding - // of any particular string character. - class NullLex - { - public: - void put(char c) { ch = c; } - bool available() const { return ch != -1; } - int get() const { return ch; } - void reset() { ch = -1; } - bool in_quote() const { return false; } - bool in_backslash() const { return false; } - - private: - int ch = -1; - }; - -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/common/likely.hpp b/Sources/OpenVPN3/openvpn/common/likely.hpp deleted file mode 100644 index d62ab19..0000000 --- a/Sources/OpenVPN3/openvpn/common/likely.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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-2020 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_COMMON_LIKELY_H -#define OPENVPN_COMMON_LIKELY_H - -// Branch prediction hints (these make a difference on ARM) -#if !defined(likely) && !defined(unlikely) -#if defined(__GNUC__) -# define likely(x) __builtin_expect((x),1) -# define unlikely(x) __builtin_expect((x),0) -#else -# define likely(x) (x) -# define unlikely(x) (x) -#endif -#endif - -#endif // OPENVPN_COMMON_LIKELY_H diff --git a/Sources/OpenVPN3/openvpn/common/link.hpp b/Sources/OpenVPN3/openvpn/common/link.hpp deleted file mode 100644 index 9615f09..0000000 --- a/Sources/OpenVPN3/openvpn/common/link.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// 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-2020 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_COMMON_LINK_H -#define OPENVPN_COMMON_LINK_H - -#include <utility> - -namespace openvpn { - - // Link creates a sender-receiver relationship between two objects. - // SEND is the sender interface, while RECV is the receiver interface. - // The receiver class should publicly inherit from Link and implement - // the receiver interface. - // Multiple inheritance of Link is intended for objects that play a - // receiver role for multiple interfaces (such as the server-side - // client instance object), and for this reason RECV common base - // classes such as RC should be virtually inherited. - // Usage of Link may create a memory reference cycle between - // Link-derived objects and the SEND object. Therefore be sure - // to manually break cycles as part of an explicit stop() method. - template <typename SEND, typename RECV> - class Link : public RECV - { - protected: - Link() {} - Link(typename SEND::Ptr send_arg) : send(std::move(send_arg)) {} - Link(SEND* send_arg) : send(send_arg) {} - - typename SEND::Ptr send; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/logrotate.hpp b/Sources/OpenVPN3/openvpn/common/logrotate.hpp deleted file mode 100644 index 6eabaad..0000000 --- a/Sources/OpenVPN3/openvpn/common/logrotate.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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_COMMON_LOGROTATE_H -#define OPENVPN_COMMON_LOGROTATE_H - -#include <stdio.h> // for rename() - -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - inline void log_rotate(const std::string& fn, const int max_versions) - { - for (int i = max_versions - 1; i >= 0; --i) - { - std::string src; - if (i) - src = fn + '.' + to_string(i); - else - src = fn; - std::string dest = fn + '.' + to_string(i+1); - ::rename(src.c_str(), dest.c_str()); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/logsetup.hpp b/Sources/OpenVPN3/openvpn/common/logsetup.hpp deleted file mode 100644 index 5e95196..0000000 --- a/Sources/OpenVPN3/openvpn/common/logsetup.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// 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-2020 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 <vector> - -#include <openvpn/common/rc.hpp> - -namespace openvpn { - - class LogSetup : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<LogSetup> Ptr; - - virtual void reopen() = 0; - }; - - class MultiLogSetup : public std::vector<LogSetup::Ptr>, - public LogSetup - { - public: - typedef RCPtr<MultiLogSetup> Ptr; - - virtual void reopen() override - { - for (const auto &e : *this) - e->reopen(); - } - }; - -} diff --git a/Sources/OpenVPN3/openvpn/common/memneq.hpp b/Sources/OpenVPN3/openvpn/common/memneq.hpp deleted file mode 100644 index 6514a06..0000000 --- a/Sources/OpenVPN3/openvpn/common/memneq.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// 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-2020 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/arch.hpp> -#include <openvpn/common/size.hpp> -#include <atomic> - -#if defined(USE_OPENSSL) -#include <openssl/crypto.h> -#endif - -// Does this architecture allow efficient unaligned access? - -#if defined(OPENVPN_ARCH_x86_64) || defined(OPENVPN_ARCH_i386) -#define OPENVPN_HAVE_EFFICIENT_UNALIGNED_ACCESS -#endif - -// Define a portable compiler memory access fence (from Boost). - -#if defined(__INTEL_COMPILER) - -#define OPENVPN_COMPILER_FENCE __memory_barrier(); - -#elif defined( _MSC_VER ) && _MSC_VER >= 1310 - -extern "C" void _ReadWriteBarrier(); -#pragma intrinsic( _ReadWriteBarrier ) - -#define OPENVPN_COMPILER_FENCE _ReadWriteBarrier(); - -#elif defined(__GNUC__) - -#define OPENVPN_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" ); - -#else - -#error need memory fence definition for this compiler - -#endif - -// C++ doesn't allow increment of void * - -#define OPENVPN_INCR_VOID_PTR(var, incr) (var) = static_cast<const unsigned char*>(var) + (incr) - -namespace openvpn { - namespace crypto { - // Clang on Android armeabi-v7a seems to have a compiler bug that compiles - // the function in a segfaulting variant, use an alternative variant of - // the function on all 32 bit arm to be safe - - - /** - * memneq - Compare two areas of memory in constant time - * - * @a: first area of memory - * @b: second area of memory - * @size: The length of the memory area to compare - * - * Returns false when data is equal, true otherwise - */ - inline bool memneq(const void *a, const void *b, size_t size); - -#if defined(__arm__) && defined(USE_OPENSSL) && !defined(__aarch64__) - inline bool memneq(const void *a, const void *b, size_t size) - { - // memcmp does return 0 (=false) when the memory is equal. It normally - // returns the position of first mismatch otherwise but the crypto - // variants only promise to return something != 0 (=true) - return (bool)(CRYPTO_memcmp(a, b, size)); - } -#elif defined(__arm__) && !defined(__aarch64__) - inline bool memneq(const void *a, const void *b, size_t size) - { - // This is inspired by mbedtls' internal safer_memcmp function: - const unsigned char *x = (const unsigned char *) a; - const unsigned char *y = (const unsigned char *) b; - unsigned char diff = 0; - - for(size_t i = 0; i < size; i++ ) - { - unsigned char u = x[i], v = y[i]; - diff |= u ^ v; - } - atomic_thread_fence(std::memory_order_release); - return bool(diff); - } -#else -#ifdef OPENVPN_HAVE_EFFICIENT_UNALIGNED_ACCESS - enum { memneq_unaligned_ok = 1 }; - typedef size_t memneq_t; -#else - enum { memneq_unaligned_ok = 0 }; - typedef unsigned int memneq_t; -#endif - - // Is value of type T aligned on A boundary? - // NOTE: requires that sizeof(A) is a power of 2 - template <typename T, typename A> - inline bool is_aligned(const T value) - { - return (size_t(value) & (sizeof(A)-1)) == 0; - } - - // Returns true if we are allowed to dereference a and b that - // point to objects of type memneq_t. - inline bool memneq_deref_ok(const void *a, const void *b) - { - return memneq_unaligned_ok || (is_aligned<const void *, memneq_t>(a)|is_aligned<const void *, memneq_t>(b)); - } - - // Constant-time memory equality method. Can be used in - // security-sensitive contexts to inhibit timing attacks. - inline bool memneq(const void *a, const void *b, size_t size) - { - memneq_t neq = 0; - - if (memneq_deref_ok(a, b)) - { - while (size >= sizeof(memneq_t)) - { - neq |= *(memneq_t *)a ^ *(memneq_t *)b; - OPENVPN_INCR_VOID_PTR(a, sizeof(memneq_t)); - OPENVPN_INCR_VOID_PTR(b, sizeof(memneq_t)); - size -= sizeof(memneq_t); - } - } - while (size > 0) - { - neq |= *(unsigned char *)a ^ *(unsigned char *)b; - OPENVPN_INCR_VOID_PTR(a, 1); - OPENVPN_INCR_VOID_PTR(b, 1); - size -= 1; - } - OPENVPN_COMPILER_FENCE - return bool(neq); - } -#endif - } -} diff --git a/Sources/OpenVPN3/openvpn/common/mode.hpp b/Sources/OpenVPN3/openvpn/common/mode.hpp deleted file mode 100644 index 99fccb6..0000000 --- a/Sources/OpenVPN3/openvpn/common/mode.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// 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-2020 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_COMMON_MODE_H -#define OPENVPN_COMMON_MODE_H - -// A client/server mode class. - -namespace openvpn { - class Mode - { - public: - enum Type { - CLIENT, - SERVER, - }; - - Mode() : type_(CLIENT) {} - explicit Mode(const Type t) : type_(t) {} - - bool is_server() const { return type_ == SERVER; } - bool is_client() const { return type_ == CLIENT; } - - bool operator==(const Mode& other) - { - return type_ == other.type_; - } - - bool operator!=(const Mode& other) - { - return type_ != other.type_; - } - - const char *str() const - { - switch (type_) - { - case CLIENT: - return "CLIENT"; - case SERVER: - return "SERVER"; - default: - return "UNDEF_MODE"; - } - } - - private: - Type type_; - }; -} // namespace openvpn - -#endif // OPENVPN_COMMON_MODE_H diff --git a/Sources/OpenVPN3/openvpn/common/modstat.hpp b/Sources/OpenVPN3/openvpn/common/modstat.hpp deleted file mode 100644 index 006d77a..0000000 --- a/Sources/OpenVPN3/openvpn/common/modstat.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// 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-2020 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 <fcntl.h> // Definition of AT_* constants */ -#include <sys/stat.h> -#include <cstdint> // for std::uint64_t -#include <cerrno> - -#include <string> - -#include <openvpn/common/platform.hpp> - -namespace openvpn { - -#if defined(OPENVPN_PLATFORM_LINUX) - - inline int update_file_mod_time_nanoseconds(const std::string& filename, - const std::uint64_t nanoseconds_since_epooch) - { - struct timespec times[2]; - times[0].tv_sec = nanoseconds_since_epooch / std::uint64_t(1000000000); - times[0].tv_nsec = nanoseconds_since_epooch % std::uint64_t(1000000000); - times[1] = times[0]; - if (::utimensat(AT_FDCWD, filename.c_str(), times, 0) == -1) - return errno; - return 0; - } - - inline int update_file_mod_time_nanoseconds(const int fd, - const std::uint64_t nanoseconds_since_epooch) - { - struct timespec times[2]; - times[0].tv_sec = nanoseconds_since_epooch / std::uint64_t(1000000000); - times[0].tv_nsec = nanoseconds_since_epooch % std::uint64_t(1000000000); - times[1] = times[0]; - if (::futimens(fd, times) == -1) - return errno; - return 0; - } - -#else - - inline int update_file_mod_time_nanoseconds(const std::string& filename, - const std::uint64_t nanoseconds_since_epooch) - { - return 0; - } - - inline int update_file_mod_time_nanoseconds(const int fd, - const std::uint64_t nanoseconds_since_epooch) - { - return 0; - } - -#endif - -} diff --git a/Sources/OpenVPN3/openvpn/common/msfind.hpp b/Sources/OpenVPN3/openvpn/common/msfind.hpp deleted file mode 100644 index 4190bed..0000000 --- a/Sources/OpenVPN3/openvpn/common/msfind.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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-2020 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/>. - - -// map/set find - -#pragma once - -#include <utility> - -namespace openvpn { - namespace MSF { - - template <typename ITERATOR> - class Iter : public ITERATOR - { - public: - template <typename MAP_SET> - Iter(const MAP_SET& ms, ITERATOR&& iter) - : ITERATOR(std::move(iter)), - exists_(*this != ms.end()) - { - } - - Iter(ITERATOR&& iter) - : ITERATOR(std::move(iter)), - exists_(true) - { - } - - explicit operator bool() const - { - return exists_; - } - - private: - bool exists_; - }; - - // Like ordinary map/set find, but returns an iterator - // that defines an operator bool() method for testing if - // the iterator is defined, so instead of: - // - // if (iter != map.end()) - // do_stuff(); - // - // you can say: - // - // if (iter) - // do_stuff(); - // - template <typename MAP_SET, typename KEY> - inline auto find(MAP_SET& ms, const KEY& k) - { - return Iter<decltype(ms.find(k))>(ms, ms.find(k)); - } - - // Does key exist in map/set? - template <typename MAP_SET, typename KEY> - inline bool exists(MAP_SET& ms, const KEY& k) - { - return ms.find(k) != ms.end(); - } - - // Convert an ordinary, dereferenceable iterator to an MSF::Iter - template <typename ITERATOR> - inline auto iter(ITERATOR i) - { - return Iter<ITERATOR>(std::move(i)); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/common/msgwin.hpp b/Sources/OpenVPN3/openvpn/common/msgwin.hpp deleted file mode 100644 index 133ee5b..0000000 --- a/Sources/OpenVPN3/openvpn/common/msgwin.hpp +++ /dev/null @@ -1,165 +0,0 @@ -// 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-2020 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_COMMON_MSGWIN_H -#define OPENVPN_COMMON_MSGWIN_H - -#include <deque> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -// Fundamental, lowest-level object of OpenVPN protocol reliability layer - -namespace openvpn { - - // MessageWindow -- - // On receiving side: used to order packets which may be received out-of-order - // On sending side: used to buffer unacknowledged packets - // M : message class, must define default constructor, defined(), and erase() methods - // id_t : sequence number object, usually unsigned int - template <typename M, typename id_t> - class MessageWindow - { - public: - OPENVPN_SIMPLE_EXCEPTION(message_window_ref_by_id); - OPENVPN_SIMPLE_EXCEPTION(message_window_rm_head); - - MessageWindow() - : head_id_(0), span_(0) {} - - MessageWindow(const id_t starting_head_id, const id_t span) - : head_id_(starting_head_id), span_(span) {} - - void init(const id_t starting_head_id, const id_t span) - { - head_id_ = starting_head_id; - span_ = span; - q_.clear(); - } - - // Return true if id is within current window - bool in_window(const id_t id) const - { - return id >= head_id_ && id < head_id_ + span_; - } - - // Return true if id is before current window - bool pre_window(const id_t id) const - { - return id < head_id_; - } - - // Return a reference to M object at id, throw exception - // if id is not in current window - M& ref_by_id(const id_t id) - { - if (in_window(id)) - { - grow(id); - return q_[id - head_id_]; - } - else - throw message_window_ref_by_id(); - } - - // Remove the M object at id, is a no-op if - // id not in window. Do a purge() as a last - // step to advance the head_id_ if it's now - // pointing at undefined M objects. - void rm_by_id(const id_t id) - { - if (in_window(id)) - { - grow(id); - M& m = q_[id - head_id_]; - m.erase(); - } - purge(); - } - - // Return true if an object at head of queue is defined - bool head_defined() const - { - return (!q_.empty() && q_.front().defined()); - } - - // Return the id that the object at the head of the queue - // would have (even if it isn't defined yet). - id_t head_id() const { return head_id_; } - - // Return the id of one past the end of the window - id_t tail_id() const { return head_id_ + span_; } - - // Return the window size - id_t span() const { return span_; } - - // Return a reference to the object at the front of the queue - M& ref_head() { return q_.front(); } - - // Remove the object at head of queue, throw an exception if undefined - void rm_head() - { - if (head_defined()) - rm_head_nocheck(); - else - throw message_window_rm_head(); - } - - // Remove the object at head of queue without error checking (other than - // that provided by std::deque object). Don't call this method unless - // head_defined() returns true. - void rm_head_nocheck() - { - q_.front().erase(); - q_.pop_front(); - ++head_id_; - } - - private: - // Expand the queue if necessary so that id maps - // to an object in the queue - void grow(const id_t id) - { - const size_t needed_index = id - head_id_; - while (q_.size() <= needed_index) - q_.push_back(M()); - } - - // Purge all undefined objects at the head of - // the queue, advancing the head_id_ - void purge() - { - while (!q_.empty() && q_.front().erased()) - { - q_.pop_front(); - ++head_id_; - } - } - - id_t head_id_; // id of msgs[0] - id_t span_; - std::deque<M> q_; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_MSGWIN_H diff --git a/Sources/OpenVPN3/openvpn/common/number.hpp b/Sources/OpenVPN3/openvpn/common/number.hpp deleted file mode 100644 index ea0ec05..0000000 --- a/Sources/OpenVPN3/openvpn/common/number.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// 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-2020 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/>. - -// General purpose methods for dealing with numbers. - -#ifndef OPENVPN_COMMON_NUMBER_H -#define OPENVPN_COMMON_NUMBER_H - -#include <string> -#include <limits> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -namespace openvpn { - - OPENVPN_EXCEPTION(number_parse_exception); - - // Parse the number of type T in str, returning - // value in retval. Returns true on success. - // Note -- currently doesn't detect overflow. - // If nondigit_term is true, any non-digit char - // can terminate the numerical value. Otherwise, - // only '\0' can terminate the value. - template <typename T> - inline bool parse_number(const char *str, - T& retval, - const bool nondigit_term = false) - { - if (!str[0]) - return false; // empty string - bool neg = false; - size_t i = 0; - if (std::numeric_limits<T>::min() < 0 && str[0] == '-') - { - neg = true; - i = 1; - } - T ret = T(0); - while (true) - { - const char c = str[i++]; - if (c >= '0' && c <= '9') - { - ret *= T(10); - ret += T(c - '0'); - } - else if (!c || nondigit_term) - { - retval = neg ? -ret : ret; - return true; - } - else - return false; // non-digit - } - } - - // like parse_number above, but accepts std::string - template <typename T> - inline bool parse_number(const std::string& str, T& retval) - { - return parse_number<T>(str.c_str(), retval); - } - - template <typename T> - inline T parse_number_throw(const std::string& str, const std::string& error) - { - T ret; - if (parse_number<T>(str.c_str(), ret)) - return ret; - else - throw number_parse_exception(error); - } - - template <typename T> - inline T parse_number_throw(const std::string& str, const char *error) - { - T ret; - if (parse_number<T>(str.c_str(), ret)) - return ret; - else - throw number_parse_exception(std::string(error)); - } - - template <typename T> - inline T parse_number_throw(const char *str, const char *error) - { - T ret; - if (parse_number<T>(str, ret)) - return ret; - else - throw number_parse_exception(std::string(error)); - } - - template <typename T> - inline bool parse_number_validate(const std::string& numstr, - const size_t max_len, - const T minimum, - const T maximum, - T* value_return = nullptr) - { - if (numstr.length() <= max_len) - { - T value; - if (parse_number<T>(numstr.c_str(), value)) - { - if (value >= minimum && value <= maximum) - { - if (value_return) - *value_return = value; - return true; - } - } - } - return false; - } - - inline bool is_number(const char *str) - { - char c; - bool found_digit = false; - while ((c = *str++)) - { - if (c >= '0' && c <= '9') - found_digit = true; - else - return false; - } - return found_digit; - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_NUMBER_H diff --git a/Sources/OpenVPN3/openvpn/common/olong.hpp b/Sources/OpenVPN3/openvpn/common/olong.hpp deleted file mode 100644 index 4b86345..0000000 --- a/Sources/OpenVPN3/openvpn/common/olong.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// 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-2020 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_COMMON_OLONG_H -#define OPENVPN_COMMON_OLONG_H - -// opportunistic long -- 32 bits on 32-bit machines, and 64 bits -// on 64-bit machines. - -namespace openvpn { -#if defined(_MSC_VER) && defined(_M_X64) - typedef long long olong; - typedef unsigned long long oulong; -#else - typedef long olong; - typedef unsigned long oulong; -#endif -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/option_error.hpp b/Sources/OpenVPN3/openvpn/common/option_error.hpp deleted file mode 100644 index ec8eddd..0000000 --- a/Sources/OpenVPN3/openvpn/common/option_error.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// 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-2020 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/exception.hpp> - -namespace openvpn { - - OPENVPN_EXCEPTION(option_error); - -} diff --git a/Sources/OpenVPN3/openvpn/common/options.hpp b/Sources/OpenVPN3/openvpn/common/options.hpp deleted file mode 100644 index db4a94f..0000000 --- a/Sources/OpenVPN3/openvpn/common/options.hpp +++ /dev/null @@ -1,1520 +0,0 @@ -// 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-2020 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/>. - -// General-purpose options parser, used to parse the OpenVPN configuration -// file as well as the server-pushed options list. Note that these classes -// don't get into the interpretation or typing of options -- they only care -// about parsing the options into lists of strings, and then presenting the -// complete configuration file as a list of options. -// -// The parser understands the general grammar of OpenVPN configuration -// files including: -// -// 1. option/argument parsing, quoting, escaping, and comments, -// 2. inline directives such as -// <ca> -// ... -// </ca> -// 3. and meta-directives such as those used by OpenVPN Access Server such as: -// # OVPN_ACCESS_SERVER_USERNAME=test -// -// The basic organization of the parser is as follows: -// -// Option -- a list of strings, where the first string is the -// option/directive name, and subsequent strings are arguments. -// -// OptionList -- a list of Options that also contains a map for -// optimal lookup of specific options - -#ifndef OPENVPN_COMMON_OPTIONS_H -#define OPENVPN_COMMON_OPTIONS_H - -#include <string> -#include <sstream> -#include <vector> -#include <algorithm> // for std::sort, std::min -#include <utility> // for std::move -#include <type_traits> // for std::is_nothrow_move_constructible -#include <unordered_map> -#include <cstdint> // for std::uint64_t - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/option_error.hpp> - -namespace openvpn { - - class Option - { - public: - enum { - MULTILINE = 0x8000000, - }; - - // Validate string by size and multiline status. - // OR max_len with MULTILINE to allow multiline string. - // Return values: - enum validate_status { - STATUS_GOOD, - STATUS_MULTILINE, - STATUS_LENGTH, - }; - - // Options for render methods - enum render_flags { - RENDER_TRUNC_64 = (1<<0), // truncate option after 64 chars - RENDER_PASS_FMT = (1<<1), // pass \r\n\t - RENDER_NUMBER = (1<<2), // number lines - RENDER_BRACKET = (1<<3), // quote options using [] - RENDER_UNUSED = (1<<4), // only show unused options - }; - - Option() - { - static_assert(std::is_nothrow_move_constructible<Option>::value, "class Option not noexcept move constructable"); - } - - template<typename T, typename... Args> - Option(T first, Args... args) - { - reserve(1 + sizeof...(args)); - from_list(std::move(first), std::forward<Args>(args)...); - } - - static validate_status validate(const std::string& str, const size_t max_len) - { - const size_t pos = str.find_first_of("\r\n"); - const size_t len = max_len & ((size_t)MULTILINE-1); // NOTE -- use smallest flag value here - if (pos != std::string::npos && !(max_len & MULTILINE)) - return STATUS_MULTILINE; - else if (len > 0 && Unicode::utf8_length(str) > len) - return STATUS_LENGTH; - else - return STATUS_GOOD; - } - - static const char *validate_status_description(const validate_status status) - { - switch (status) - { - case STATUS_GOOD: - return "good"; - case STATUS_MULTILINE: - return "multiline"; - case STATUS_LENGTH: - return "too long"; - default: - return "unknown"; - } - } - - void min_args(const size_t n) const - { - const size_t s = data.size(); - if (s < n) - OPENVPN_THROW(option_error, err_ref() << " must have at least " << n << " arguments"); - } - - void exact_args(const size_t n) const - { - const size_t s = data.size(); - if (s != n) - OPENVPN_THROW(option_error, err_ref() << " must have exactly " << n << " arguments"); - } - - void validate_arg(const size_t index, const size_t max_len) const - { - if (max_len > 0 && index < data.size()) - { - const validate_status status = validate(data[index], max_len); - if (status != STATUS_GOOD) - OPENVPN_THROW(option_error, err_ref() << " is " << validate_status_description(status)); - } - } - - static void validate_string(const std::string& name, const std::string& str, const size_t max_len) - { - const validate_status status = validate(str, max_len); - if (status != STATUS_GOOD) - OPENVPN_THROW(option_error, name << " is " << validate_status_description(status)); - } - - std::string printable_directive() const - { - try { - if (data.size() > 0) - return Unicode::utf8_printable(data[0], 32); - else - return ""; - } - catch (const std::exception&) - { - return "[DIRECTIVE]"; - } - } - - const std::string& get(const size_t index, const size_t max_len) const - { - min_args(index+1); - validate_arg(index, max_len); - return data[index]; - } - - std::string get_optional(const size_t index, const size_t max_len) const - { - validate_arg(index, max_len); - if (index < data.size()) - return data[index]; - else - return ""; - } - - std::string get_default(const size_t index, const size_t max_len, const std::string& default_value) const - { - validate_arg(index, max_len); - if (index < data.size()) - return data[index]; - else - return default_value; - } - - const std::string* get_ptr(const size_t index, const size_t max_len) const - { - validate_arg(index, max_len); - if (index < data.size()) - return &data[index]; - else - return nullptr; - } - - template <typename T> - T get_num(const size_t idx) const - { - typedef typename std::remove_const<T>::type T_nonconst; - T_nonconst n(0); // we shouldn't need to initialize here, but some compilers complain "may be used uninitialized in this function" - const std::string& numstr = get(idx, 64); - if (numstr.length() >= 2 && numstr[0] == '0' && numstr[1] == 'x') - { - if (!parse_hex_number(numstr.substr(2), n)) - OPENVPN_THROW(option_error, err_ref() << '[' << idx << "] expecting a hex number"); - } - else if (!parse_number<T_nonconst>(numstr, n)) - OPENVPN_THROW(option_error, err_ref() << '[' << idx << "] must be a number"); - return n; - } - - template <typename T> - T get_num(const size_t idx, const T default_value) const - { - if (size() > idx) - return get_num<T>(idx); - else - return default_value; - } - - template <typename T> - T get_num(const size_t idx, const T default_value, const T min_value, const T max_value) const - { - const T ret = get_num<T>(idx, default_value); - if (ret != default_value && (ret < min_value || ret > max_value)) - range_error(idx, min_value, max_value); - return ret; - } - - template <typename T> - T get_num(const size_t idx, const T min_value, const T max_value) const - { - const T ret = get_num<T>(idx); - if (ret < min_value || ret > max_value) - range_error(idx, min_value, max_value); - return ret; - } - - std::string render(const unsigned int flags) const - { - std::ostringstream out; - size_t max_len_flags = (flags & RENDER_TRUNC_64) ? 64 : 0; - if (flags & RENDER_PASS_FMT) - max_len_flags |= Unicode::UTF8_PASS_FMT; - bool first = true; - for (std::vector<std::string>::const_iterator i = data.begin(); i != data.end(); ++i) - { - if (!first) - out << ' '; - if (flags & RENDER_BRACKET) - out << '['; - out << Unicode::utf8_printable(*i, max_len_flags); - if (flags & RENDER_BRACKET) - out << ']'; - first = false; - } - return out.str(); - } - - static void escape_string(std::ostream& out, const std::string& term, const bool must_quote) - { - if (must_quote) - out << '\"'; - for (std::string::const_iterator j = term.begin(); j != term.end(); ++j) - { - const char c = *j; - if (c == '\"' || c == '\\') - out << '\\'; - out << c; - } - if (must_quote) - out << '\"'; - } - - // Render the option args into a string format such that it could be parsed back to - // the equivalent option args. - std::string escape(const bool csv) const - { - std::ostringstream out; - bool more = false; - for (std::vector<std::string>::const_iterator i = data.begin(); i != data.end(); ++i) - { - const std::string& term = *i; - const bool must_quote = must_quote_string(term, csv); - if (more) - out << ' '; - escape_string(out, term, must_quote); - more = true; - } - return out.str(); - } - - // delegate to data - size_t size() const { return data.size(); } - bool empty() const { return data.empty(); } - void push_back(const std::string& item) { data.push_back(item); } - void push_back(std::string&& item) { data.push_back(std::move(item)); } - void clear() { data.clear(); } - void reserve(const size_t n) { data.reserve(n); } - void resize(const size_t n) { data.resize(n); } - - // raw references to data - const std::string& ref(const size_t i) const { return data[i]; } - std::string& ref(const size_t i) { return data[i]; } - - // equality - bool operator==(const Option& other) const { return data == other.data; } - bool operator!=(const Option& other) const { return data != other.data; } - - // remove first n elements - void remove_first(const size_t n_elements) - { - const size_t n = std::min(data.size(), n_elements); - if (n) - data.erase(data.begin(), data.begin() + n); - } - - // indicate that this option was processed - void touch() const - { - // Note that we violate constness here, which is done - // because the touched bit is considered to be option metadata. - touched_ = true; - } - - // was this option processed? - bool touched() const { return touched_; } - - // refer to the option when constructing an error message - std::string err_ref() const - { - std::string ret = "option"; - if (data.size()) - { - ret += " '"; - ret += printable_directive(); - ret += '\''; - } - return ret; - } - - private: - void from_list(std::string arg) - { - push_back(std::move(arg)); - } - - void from_list(const char *arg) - { - push_back(std::string(arg)); - } - - template<typename T, typename... Args> - void from_list(T first, Args... args) - { - from_list(std::move(first)); - from_list(std::forward<Args>(args)...); - } - - template <typename T> - void range_error(const size_t idx, const T min_value, const T max_value) const - { - OPENVPN_THROW(option_error, err_ref() << '[' << idx << "] must be in the range [" << min_value << ',' << max_value << ']'); - } - - bool must_quote_string(const std::string& str, const bool csv) const - { - for (const auto c : str) - { - if (string::is_space(c)) - return true; - if (csv && c == ',') - return true; - } - return false; - } - - volatile mutable bool touched_ = false; - std::vector<std::string> data; - }; - - class OptionList : public std::vector<Option>, public RCCopyable<thread_unsafe_refcount> - { - public: - typedef RCPtr<OptionList> Ptr; - typedef std::vector<unsigned int> IndexList; - typedef std::unordered_map<std::string, IndexList> IndexMap; - typedef std::pair<std::string, IndexList> IndexPair; - - static bool is_comment(const char c) - { - return c == '#' || c == ';'; - } - - // standard lex filter that doesn't understand end-of-line comments - typedef StandardLex Lex; - - // special lex filter that recognizes end-of-line comments - class LexComment - { - public: - LexComment() : in_quote_(false), in_comment(false), backslash(false), ch(-1) {} - - void put(char c) - { - if (in_comment) - { - ch = -1; - } - else if (backslash) - { - ch = c; - backslash = false; - } - else if (c == '\\') - { - backslash = true; - ch = -1; - } - else if (c == '\"') - { - in_quote_ = !in_quote_; - ch = -1; - } - else if (is_comment(c) && !in_quote_) - { - in_comment = true; - ch = -1; - } - else - { - ch = c; - } - } - - bool available() const { return ch != -1; } - int get() const { return ch; } - void reset() { ch = -1; } - - bool in_quote() const { return in_quote_; } - - private: - bool in_quote_; - bool in_comment; - bool backslash; - int ch; - }; - - class Limits - { - public: - Limits(const std::string& error_message, - const std::uint64_t max_bytes_arg, - const size_t extra_bytes_per_opt_arg, - const size_t extra_bytes_per_term_arg, - const size_t max_line_len_arg, - const size_t max_directive_len_arg) - : bytes(0), - max_bytes(max_bytes_arg), - extra_bytes_per_opt(extra_bytes_per_opt_arg), - extra_bytes_per_term(extra_bytes_per_term_arg), - max_line_len(max_line_len_arg), - max_directive_len(max_directive_len_arg), - err(error_message) {} - - void add_bytes(const size_t n) - { - bytes += n; - check_overflow(); - } - - void add_string(const std::string& str) - { - bytes += str.length(); - check_overflow(); - } - - void add_term() - { - bytes += extra_bytes_per_term; - check_overflow(); - } - - void add_opt() - { - bytes += extra_bytes_per_opt; - check_overflow(); - } - - size_t get_max_line_len() const - { - return max_line_len; - } - - std::uint64_t get_bytes() const - { - return bytes; - } - - void validate_directive(const Option& opt) - { - opt.validate_arg(0, max_directive_len); - } - - private: - void check_overflow() - { - if (bytes >= max_bytes) - error(); - } - - void error() - { - throw option_error(err); - } - - std::uint64_t bytes; - const std::uint64_t max_bytes; - const size_t extra_bytes_per_opt; - const size_t extra_bytes_per_term; - const size_t max_line_len; - const size_t max_directive_len; - const std::string err; - }; - - // Used by extend() to optionally control which options are copied. - struct FilterBase : public RC<thread_unsafe_refcount> - { - typedef RCPtr<FilterBase> Ptr; - virtual bool filter(const Option& opt) = 0; - }; - - class KeyValue : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<KeyValue> Ptr; - - KeyValue() : key_priority(0) {} - KeyValue(const std::string& key_arg, const std::string& value_arg, const int key_priority_arg=0) - : key(key_arg), value(value_arg), key_priority(key_priority_arg) {} - - size_t combined_length() const - { - return key.length() + value.length(); - } - - Option convert_to_option(Limits* lim) const - { - bool newline_present = false; - Option opt; - const std::string unesc_value = unescape(value, newline_present); - opt.push_back(key); - if (newline_present || singular_arg(key)) - opt.push_back(unesc_value); - else if (unesc_value != "NOARGS") - Split::by_space_void<Option, Lex, SpaceMatch, Limits>(opt, unesc_value, lim); - return opt; - } - - void split_priority() - { - // look for usage such as: remote.7 - const size_t dp = key.find_last_of("."); - if (dp != std::string::npos) - { - const size_t tp = dp + 1; - if (tp < key.length()) - { - const char *tail = key.c_str() + tp; - try { - key_priority = parse_number_throw<int>(tail, "option priority"); - key = key.substr(0, dp); - } - catch (const number_parse_exception&) - { - ; - } - } - } - } - - static bool compare(const Ptr& a, const Ptr& b) - { - const int cmp = a->key.compare(b->key); - if (cmp < 0) - return true; - else if (cmp > 0) - return false; - else - return a->key_priority < b->key_priority; - } - - std::string key; - std::string value; - int key_priority; - - private: - static std::string unescape(const std::string& value, bool& newline_present) - { - std::string ret; - ret.reserve(value.length()); - - bool bs = false; - for (size_t i = 0; i < value.length(); ++i) - { - const char c = value[i]; - if (bs) - { - if (c == 'n') - { - ret += '\n'; - newline_present = true; - } - else if (c == '\\') - ret += '\\'; - else - { - ret += '\\'; - ret += c; - } - bs = false; - } - else - { - if (c == '\\') - bs = true; - else - ret += c; - } - } - if (bs) - ret += '\\'; - return ret; - } - - static bool singular_arg(const std::string& key) - { - bool upper = false; - bool lower = false; - for (size_t i = 0; i < key.length(); ++i) - { - const char c = key[i]; - if (c >= 'a' && c <= 'z') - lower = true; - else if (c >= 'A' && c <= 'Z') - upper = true; - } - return upper && !lower; - } - }; - - struct KeyValueList : public std::vector<KeyValue::Ptr> - { - void preprocess() - { - split_priority(); - sort(); - } - - void split_priority() - { - for (iterator i = begin(); i != end(); ++i) - { - KeyValue& kv = **i; - kv.split_priority(); - } - } - - void sort() - { - std::sort(begin(), end(), KeyValue::compare); - } - }; - - OptionList() - { - } - - template<typename T, typename... Args> - explicit OptionList(T first, Args... args) - { - reserve(1 + sizeof...(args)); - from_list(std::move(first), std::forward<Args>(args)...); - update_map(); - } - - static OptionList parse_from_csv_static(const std::string& str, Limits* lim) - { - OptionList ret; - ret.parse_from_csv(str, lim); - ret.update_map(); - return ret; - } - - static OptionList parse_from_csv_static_nomap(const std::string& str, Limits* lim) - { - OptionList ret; - ret.parse_from_csv(str, lim); - return ret; - } - - static OptionList parse_from_config_static(const std::string& str, Limits* lim) - { - OptionList ret; - ret.parse_from_config(str, lim); - ret.update_map(); - return ret; - } - - static OptionList::Ptr parse_from_config_static_ptr(const std::string& str, Limits* lim) - { - OptionList::Ptr ret = new OptionList(); - ret->parse_from_config(str, lim); - ret->update_map(); - return ret; - } - - static OptionList parse_from_argv_static(const std::vector<std::string>& argv) - { - OptionList ret; - ret.parse_from_argv(argv); - ret.update_map(); - return ret; - } - - void clear() - { - std::vector<Option>::clear(); - map_.clear(); - } - - // caller should call update_map() after this function - void parse_from_csv(const std::string& str, Limits* lim) - { - if (lim) - lim->add_string(str); - std::vector<std::string> list = Split::by_char<std::vector<std::string>, Lex, Limits>(str, ',', 0, ~0, lim); - for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); ++i) - { - const Option opt = Split::by_space<Option, Lex, SpaceMatch, Limits>(*i, lim); - if (opt.size()) - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(opt); - } - push_back(std::move(opt)); - } - } - } - - // caller should call update_map() after this function - void parse_from_argv(const std::vector<std::string>& argv) - { - Option opt; - for (auto &arg : argv) - { - std::string a = arg; - if (string::starts_with(a, "--")) - { - if (!opt.empty()) - { - push_back(std::move(opt)); - opt.clear(); - } - a = a.substr(2); - } - if (!a.empty()) - opt.push_back(a); - } - if (!opt.empty()) - push_back(std::move(opt)); - } - - // caller should call update_map() after this function - void parse_from_peer_info(const std::string& str, Limits* lim) - { - if (lim) - lim->add_string(str); - SplitLines in(str, 0); - while (in(true)) - { - const std::string& line = in.line_ref(); - Option opt; - opt.reserve(2); - Split::by_char_void<Option, NullLex, Limits>(opt, line, '=', 0, 1, lim); - if (opt.size()) - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(opt); - } - push_back(std::move(opt)); - } - } - } - - // caller may want to call list.preprocess() before this function - // caller should call update_map() after this function - void parse_from_key_value_list(const KeyValueList& list, Limits* lim) - { - for (KeyValueList::const_iterator i = list.begin(); i != list.end(); ++i) - { - const KeyValue& kv = **i; - if (lim) - lim->add_bytes(kv.combined_length()); - const Option opt = kv.convert_to_option(lim); - if (lim) - { - lim->add_opt(); - lim->validate_directive(opt); - } - push_back(std::move(opt)); - } - } - - static Option parse_option_from_line(const std::string& line, Limits* lim) - { - return Split::by_space<Option, LexComment, SpaceMatch, Limits>(line, lim); - } - - // caller should call update_map() after this function - void parse_from_config(const std::string& str, Limits* lim) - { - if (lim) - lim->add_string(str); - - SplitLines in(str, lim ? lim->get_max_line_len() : 0); - int line_num = 0; - bool in_multiline = false; - Option multiline; - while (in(true)) - { - ++line_num; - if (in.line_overflow()) - line_too_long(line_num); - const std::string& line = in.line_ref(); - if (in_multiline) - { - if (is_close_tag(line, multiline.ref(0))) - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(multiline); - } - push_back(std::move(multiline)); - multiline.clear(); - in_multiline = false; - } - else - { - std::string& mref = multiline.ref(1); - mref += line; - mref += '\n'; - } - } - else if (!ignore_line(line)) - { - Option opt = parse_option_from_line(line, lim); - if (opt.size()) - { - if (is_open_tag(opt.ref(0))) - { - if (opt.size() > 1) - extraneous_err(line_num, "option", opt); - untag_open_tag(opt.ref(0)); - opt.push_back(""); - multiline = opt; - in_multiline = true; - } - else - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(opt); - } - push_back(std::move(opt)); - } - } - } - } - if (in_multiline) - not_closed_out_err("option", multiline); - } - - // caller should call update_map() after this function - void parse_meta_from_config(const std::string& str, const std::string& tag, Limits* lim) - { - SplitLines in(str, lim ? lim->get_max_line_len() : 0); - int line_num = 0; - bool in_multiline = false; - Option multiline; - const std::string prefix = tag + "_"; - while (in(true)) - { - ++line_num; - if (in.line_overflow()) - line_too_long(line_num); - std::string& line = in.line_ref(); - if (string::starts_with(line, "# ")) - { - line = std::string(line, 2); - if (in_multiline) - { - if (is_close_meta_tag(line, prefix, multiline.ref(0))) - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(multiline); - } - push_back(std::move(multiline)); - multiline.clear(); - in_multiline = false; - } - else - { - std::string& mref = multiline.ref(1); - mref += line; - mref += '\n'; - } - } - else if (string::starts_with(line, prefix)) - { - Option opt = Split::by_char<Option, NullLex, Limits>(std::string(line, prefix.length()), '=', 0, 1, lim); - if (opt.size()) - { - if (is_open_meta_tag(opt.ref(0))) - { - if (opt.size() > 1) - extraneous_err(line_num, "meta option", opt); - untag_open_meta_tag(opt.ref(0)); - opt.push_back(""); - multiline = opt; - in_multiline = true; - } - else - { - if (lim) - { - lim->add_opt(); - lim->validate_directive(opt); - } - push_back(std::move(opt)); - } - } - } - } - } - if (in_multiline) - not_closed_out_err("meta option", multiline); - } - - // Append elements in other to self, - // caller should call update_map() after this function. - void extend(const OptionList& other, FilterBase* filt) - { - reserve(size() + other.size()); - for (std::vector<Option>::const_iterator i = other.begin(); i != other.end(); ++i) - { - const Option& opt = *i; - if (!filt || filt->filter(opt)) - { - push_back(opt); - opt.touch(); - } - } - } - - // Append elements in other having given name to self, - // caller should call update_map() after this function. - // Return the number of elements processed. - unsigned int extend(const OptionList& other, const std::string& name) - { - IndexMap::const_iterator oi = other.map().find(name); - unsigned int count = 0; - if (oi != other.map().end()) - for (IndexList::const_iterator i = oi->second.begin(); i != oi->second.end(); ++i) - { - const Option& opt = other[*i]; - push_back(opt); - opt.touch(); - ++count; - } - return count; - } - - // Append to self only those elements in other that do not exist - // in self, caller should call update_map() after this function. - // Caller should also consider calling update_map() before this function, - // to ensure that lookups on this->map will see up-to-date data. - void extend_nonexistent(const OptionList& other) - { - for (std::vector<Option>::const_iterator i = other.begin(); i != other.end(); ++i) - { - const Option& opt = *i; - if (!opt.empty() && map().find(opt.ref(0)) == map().end()) - { - push_back(opt); - opt.touch(); - } - } - } - - // Get the last instance of an option, or return nullptr if option - // doesn't exist. - const Option* get_ptr(const std::string& name) const - { - IndexMap::const_iterator e = map_.find(name); - if (e != map_.end()) - { - const size_t size = e->second.size(); - if (size) - { - const Option* ret = &((*this)[e->second[size-1]]); - ret->touch(); - return ret; - } - } - return nullptr; - } - - // Get an option, return nullptr if option doesn't exist, or - // throw an error if more than one instance exists. - const Option* get_unique_ptr(const std::string& name) const - { - IndexMap::const_iterator e = map_.find(name); - if (e != map_.end() && !e->second.empty()) - { - if (e->second.size() == 1) - { - const Option* ret = &((*this)[e->second[0]]); - ret->touch(); - return ret; - } - else - OPENVPN_THROW(option_error, "more than one instance of option '" << name << '\''); - } - else - return nullptr; - } - - // Get an option, throw an error if more than one instance exists and the instances - // are not exact duplicates of one other. - const Option* get_consistent(const std::string& name) const - { - IndexMap::const_iterator e = map_.find(name); - if (e != map_.end() && !e->second.empty()) - { - const Option *first = &((*this)[e->second[0]]); - first->touch(); - if (e->second.size() >= 2) - { - for (size_t i = 1; i < e->second.size(); ++i) - { - const Option *other = &(*this)[e->second[i]]; - other->touch(); - if (*other != *first) - OPENVPN_THROW(option_error, "more than one instance of option '" << name << "' with inconsistent argument(s)"); - } - } - return first; - } - else - return nullptr; - } - - // Get option, throw error if not found - // If multiple options of the same name exist, return - // the last one. - const Option& get(const std::string& name) const - { - const Option* o = get_ptr(name); - if (o) - return *o; - else - OPENVPN_THROW(option_error, "option '" << name << "' not found"); - } - - // Get the list of options having the same name (by index), - // throw an exception if option is not found. - const IndexList& get_index(const std::string& name) const - { - IndexMap::const_iterator e = map_.find(name); - if (e != map_.end() && !e->second.empty()) - return e->second; - else - OPENVPN_THROW(option_error, "option '" << name << "' not found"); - } - - // Get the list of options having the same name (by index), - // return nullptr is option is not found. - const IndexList* get_index_ptr(const std::string& name) const - { - IndexMap::const_iterator e = map_.find(name); - if (e != map_.end() && !e->second.empty()) - return &e->second; - else - return nullptr; - } - - // Concatenate all one-arg directives of a given name, in index order. - std::string cat(const std::string& name) const - { - std::string ret; - const OptionList::IndexList* il = get_index_ptr(name); - if (il) - { - size_t size = 0; - OptionList::IndexList::const_iterator i; - for (i = il->begin(); i != il->end(); ++i) - { - const Option& o = (*this)[*i]; - if (o.size() == 2) - size += o.ref(1).length() + 1; - else - OPENVPN_THROW(option_error, "option '" << name << "' (" << o.size() << ") must have exactly one parameter"); - } - ret.reserve(size); - for (i = il->begin(); i != il->end(); ++i) - { - const Option& o = (*this)[*i]; - if (o.size() >= 2) - { - o.touch(); - ret += o.ref(1); - string::add_trailing(ret, '\n'); - } - } - } - return ret; - } - - // Return true if option exists, but raise an exception if multiple - // instances of the option exist. - bool exists_unique(const std::string& name) const - { - return get_unique_ptr(name) != nullptr; - } - - // Return true if one or more instances of a given option exist. - bool exists(const std::string& name) const - { - return get_ptr(name) != nullptr; - } - - // Convenience method that gets a particular argument index within an option, - // while raising an exception if option doesn't exist or if argument index - // is out-of-bounds. - const std::string& get(const std::string& name, size_t index, const size_t max_len) const - { - const Option& o = get(name); - return o.get(index, max_len); - } - - // Convenience method that gets a particular argument index within an option, - // while returning the empty string if option doesn't exist, and raising an - // exception if argument index is out-of-bounds. - std::string get_optional(const std::string& name, size_t index, const size_t max_len) const - { - const Option* o = get_ptr(name); - if (o) - return o->get(index, max_len); - else - return ""; - } - - // Like get_optional(), but return "" if argument index is out-of-bounds. - std::string get_optional_relaxed(const std::string& name, size_t index, const size_t max_len) const - { - const Option* o = get_ptr(name); - if (o) - return o->get_optional(index, max_len); - else - return ""; - } - - // Like get_optional(), but return "" if exception is thrown. - std::string get_optional_noexcept(const std::string& name, size_t index, const size_t max_len) const - { - try { - return get_optional(name, index, max_len); - } - catch (const std::exception&) - { - return ""; - } - } - - // Return raw C string to option data or nullptr if option doesn't exist. - const char *get_c_str(const std::string& name, size_t index, const size_t max_len) const - { - const Option* o = get_ptr(name); - if (o) - return o->get(index, max_len).c_str(); - else - return nullptr; - } - - // Convenience method that gets a particular argument index within an option, - // while returning a default string if option doesn't exist, and raising an - // exception if argument index is out-of-bounds. - std::string get_default(const std::string& name, - size_t index, - const size_t max_len, - const std::string& default_value) const - { - const Option* o = get_ptr(name); - if (o) - return o->get(index, max_len); - else - return default_value; - } - - // Like get_default(), but return default_value if argument index is out-of-bounds. - std::string get_default_relaxed(const std::string& name, - size_t index, - const size_t max_len, - const std::string& default_value) const - { - const Option* o = get_ptr(name); - if (o) - { - const std::string* s = o->get_ptr(index, max_len); - if (s) - return *s; - } - return default_value; - } - - template <typename T> - T get_num(const std::string& name, const size_t idx, const T default_value) const - { - typedef typename std::remove_const<T>::type T_nonconst; - T_nonconst n = default_value; - const Option* o = get_ptr(name); - if (o) - n = o->get_num<T>(idx, default_value); - return n; - } - - template <typename T> - T get_num(const std::string& name, const size_t idx, const T default_value, - const T min_value, const T max_value) const - { - typedef typename std::remove_const<T>::type T_nonconst; - T_nonconst n = default_value; - const Option* o = get_ptr(name); - if (o) - n = o->get_num<T>(idx, default_value, min_value, max_value); - return n; - } - - template <typename T> - T get_num(const std::string& name, const size_t idx, const T min_value, const T max_value) const - { - const Option& o = get(name); - return o.get_num<T>(idx, min_value, max_value); - } - - template <typename T> - T get_num(const std::string& name, const size_t idx) const - { - const Option& o = get(name); - return o.get_num<T>(idx); - } - - // Touch an option, if it exists. - void touch(const std::string& name) const - { - const Option* o = get_ptr(name); - if (o) - o->touch(); - } - - // Render object as a string. - // flags should be given as Option::render_flags. - std::string render(const unsigned int flags) const - { - std::ostringstream out; - for (size_t i = 0; i < size(); ++i) - { - const Option& o = (*this)[i]; - if (!(flags & Option::RENDER_UNUSED) || !o.touched()) - { - if (flags & Option::RENDER_NUMBER) - out << i << ' '; - out << o.render(flags) << std::endl; - } - } - return out.str(); - } - - std::string render_csv() const - { - std::string ret; - bool first = true; - for (auto &e : *this) - { - if (!first) - ret += ','; - ret += e.escape(true); - first = false; - } - return ret; - } - - // Render contents of hash map used to locate options after underlying option list - // has been modified. - std::string render_map() const - { - std::ostringstream out; - for (IndexMap::const_iterator i = map_.begin(); i != map_.end(); ++i) - { - out << i->first << " ["; - for (IndexList::const_iterator j = i->second.begin(); j != i->second.end(); ++j) - out << ' ' << *j; - out << " ]" << std::endl; - } - return out.str(); - } - - // Return number of unused options based on the notion that - // all used options have been touched. - size_t n_unused() const - { - size_t n = 0; - for (std::vector<Option>::const_iterator i = begin(); i != end(); ++i) - { - const Option& opt = *i; - if (!opt.touched()) - ++n; - } - return n; - } - - void show_unused_options(const char *title=nullptr) const - { - // show unused options - if (n_unused()) - { - if (!title) - title = "NOTE: Unused Options"; - OPENVPN_LOG_NTNL(title << std::endl << render(Option::RENDER_TRUNC_64|Option::RENDER_NUMBER|Option::RENDER_BRACKET|Option::RENDER_UNUSED)); - } - } - - // Add item to underlying option list while updating map as well. - void add_item(const Option& opt) - { - if (!opt.empty()) - { - const size_t i = size(); - push_back(opt); - map_[opt.ref(0)].push_back((unsigned int)i); - } - } - - // Return hash map used to locate options. - const IndexMap& map() const { return map_; } - - // Rebuild hash map used to locate options after underlying option list - // has been modified. - void update_map() - { - map_.clear(); - for (size_t i = 0; i < size(); ++i) - { - const Option& opt = (*this)[i]; - if (!opt.empty()) - map_[opt.ref(0)].push_back((unsigned int)i); - } - } - - // return true if line is blank or a comment - static bool ignore_line(const std::string& line) - { - for (std::string::const_iterator i = line.begin(); i != line.end(); ++i) - { - const char c = *i; - if (!SpaceMatch::is_space(c)) - return is_comment(c); - } - return true; - } - - // multiline tagging - - // return true if string is a tag, e.g. "<ca>" - static bool is_open_tag(const std::string& str) - { - const size_t n = str.length(); - return n >= 3 && str[0] == '<' && str[1] != '/' && str[n-1] == '>'; - } - - // return true if string is a close tag, e.g. "</ca>" - static bool is_close_tag(const std::string& str, const std::string& tag) - { - const size_t n = str.length(); - return n >= 4 && str[0] == '<' && str[1] == '/' && str.substr(2, n-3) == tag && str[n-1] == '>'; - } - - // remove <> chars from open tag - static void untag_open_tag(std::string& str) - { - const size_t n = str.length(); - if (n >= 3) - str = str.substr(1, n-2); - } - - // detect multiline breakout attempt (return true) - static bool detect_multiline_breakout_nothrow(const std::string& opt, const std::string& tag) - { - std::string line; - for (auto &c : opt) - { - if (c == '\n' || c == '\r') - line.clear(); - else - { - line += c; - if (tag.empty()) - { - if (line.length() >= 2 - && line[0] == '<' - && line[1] == '/') - return true; - } - else if (is_close_tag(line, tag)) - return true; - } - } - return false; - } - - // detect multiline breakout attempt - static void detect_multiline_breakout(const std::string& opt, const std::string& tag) - { - if (detect_multiline_breakout_nothrow(opt, tag)) - throw option_error("multiline breakout detected"); - } - - private: - // multiline tagging (meta) - - // return true if string is a meta tag, e.g. WEB_CA_BUNDLE_START - static bool is_open_meta_tag(const std::string& str) - { - return string::ends_with(str, "_START"); - } - - // return true if string is a tag, e.g. WEB_CA_BUNDLE_STOP - static bool is_close_meta_tag(const std::string& str, const std::string& prefix, const std::string& tag) - { - return prefix + tag + "_STOP" == str; - } - - // remove trailing "_START" from open tag - static void untag_open_meta_tag(std::string& str) - { - const size_t n = str.length(); - if (n >= 6) - str = std::string(str, 0, n - 6); - } - - static void extraneous_err(const int line_num, const char *type, const Option& opt) - { - OPENVPN_THROW(option_error, "line " << line_num << ": " << type << " <" << opt.printable_directive() << "> is followed by extraneous text"); - } - - static void not_closed_out_err(const char *type, const Option& opt) - { - OPENVPN_THROW(option_error, type << " <" << opt.printable_directive() << "> was not properly closed out"); - } - - static void line_too_long(const int line_num) - { - OPENVPN_THROW(option_error, "line " << line_num << " is too long"); - } - - void from_list(Option opt) - { - push_back(std::move(opt)); - } - - template<typename T, typename... Args> - void from_list(T first, Args... args) - { - from_list(std::move(first)); - from_list(std::forward<Args>(args)...); - } - - IndexMap map_; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_OPTIONS_H diff --git a/Sources/OpenVPN3/openvpn/common/ostream.hpp b/Sources/OpenVPN3/openvpn/common/ostream.hpp deleted file mode 100644 index 053baa6..0000000 --- a/Sources/OpenVPN3/openvpn/common/ostream.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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-2020 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/>. - -// A helper macro for setting up an arbitrary class -// to support stringstream concatenation using << - -#ifndef OPENVPN_COMMON_OSTREAM_H -#define OPENVPN_COMMON_OSTREAM_H - -#include <ostream> -#include <string> - -#define OPENVPN_OSTREAM(TYPE, METH) \ - template <typename Elem, typename Traits> \ - std::basic_ostream<Elem, Traits>& operator<<( \ - std::basic_ostream<Elem, Traits>& os, const TYPE& addr) \ - { \ - os << addr.METH(); \ - return os; \ - } - -#endif // OPENVPN_COMMON_OSTREAM_H diff --git a/Sources/OpenVPN3/openvpn/common/path.hpp b/Sources/OpenVPN3/openvpn/common/path.hpp deleted file mode 100644 index 1c9d298..0000000 --- a/Sources/OpenVPN3/openvpn/common/path.hpp +++ /dev/null @@ -1,207 +0,0 @@ -// 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-2020 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/>. - -// General-purpose methods for handling filesystem pathnames - -#ifndef OPENVPN_COMMON_PATH_H -#define OPENVPN_COMMON_PATH_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/common/string.hpp> - -namespace openvpn { - namespace path { - - // Directory separators. The first char in dirsep is the primary - // separator for the platform, while subsequent chars are also - // recognized as separators. - namespace { -#if defined(OPENVPN_PLATFORM_WIN) || defined(OPENVPN_PATH_SIMULATE_WINDOWS) - // Windows - const char dirsep[] = "\\/"; // CONST GLOBAL -#else - // Unix - const char dirsep[] = "/\\"; // CONST GLOBAL -#endif - } - - // true if char is a directory separator - inline bool is_dirsep(const char c) - { - for (const char *p = dirsep; *p != '\0'; ++p) - if (c == *p) - return true; - return false; - } - - inline bool win_dev(const std::string& path, const bool fully_qualified) - { -#if defined(OPENVPN_PLATFORM_WIN) || defined(OPENVPN_PATH_SIMULATE_WINDOWS) - // Identify usage such as "c:\\". - return path.length() >= 3 - && ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) - && path[1] == ':' - && (!fully_qualified || is_dirsep(path[2])); -#else - return false; -#endif - } - - // true if path is fully qualified - inline bool is_fully_qualified(const std::string& path) - { - return win_dev(path, true) || (path.length() > 0 && is_dirsep(path[0])); - } - - // does path refer to regular file without directory traversal - inline bool is_flat(const std::string& path) - { - return path.length() > 0 - && path != "." - && path != ".." - && path.find_first_of(dirsep) == std::string::npos - && !win_dev(path, false); - } - - inline std::string basename(const std::string& path) - { - const size_t pos = path.find_last_of(dirsep); - if (pos != std::string::npos) - { - const size_t p = pos + 1; - if (p >= path.length()) - return ""; - else - return path.substr(p); - } - else - return path; - } - - inline std::string dirname(const std::string& path) - { - const size_t pos = path.find_last_of(dirsep); - if (pos != std::string::npos) - { - if (pos == 0) - return "/"; - else - return path.substr(0, pos); - } - else - return ""; - } - - // return true if path is a regular file that doesn't try to traverse via ".." or "/..." - inline bool is_contained(const std::string& path) - { - if (path.empty()) - return false; - if (win_dev(path, false)) - return false; - if (is_dirsep(path[0])) - return false; - - // look for ".." in path - enum State { - SEP, // immediately after separator - MID, // middle of dir - DOT_2, // looking for second '.' - POST_DOT_2, // after ".." - }; - State state = SEP; - for (const auto c : path) - { - switch (state) - { - case SEP: - if (c == '.') - state = DOT_2; - else if (!is_dirsep(c)) - state = MID; - break; - case MID: - if (is_dirsep(c)) - state = SEP; - break; - case DOT_2: - if (c == '.') - state = POST_DOT_2; - else if (is_dirsep(c)) - state = SEP; - else - state = MID; - break; - case POST_DOT_2: - if (is_dirsep(c)) - return false; - state = MID; - break; - } - } - return state != POST_DOT_2; - } - - inline std::string ext(const std::string& basename) - { - const size_t pos = basename.find_last_of('.'); - if (pos != std::string::npos) - { - const size_t p = pos + 1; - if (p >= basename.length()) - return ""; - else - return basename.substr(p); - } - else - return ""; - } - - inline std::string root(const std::string& basename) - { - const size_t pos = basename.find_last_of('.'); - if (pos != std::string::npos) - return basename.substr(0, pos); - else - return basename; - } - - inline std::string join(const std::string& p1, const std::string& p2) - { - if (p1.empty() || is_fully_qualified(p2)) - return p2; - else - return string::add_trailing_copy(p1, dirsep[0]) + p2; - } - - template<typename... Args> - inline std::string join(const std::string& p1, const std::string& p2, Args... args) - { - return join(join(p1, p2), args...); - } - - } // namespace path -} // namespace openvpn - -#endif // OPENVPN_COMMON_STRING_H diff --git a/Sources/OpenVPN3/openvpn/common/peercred.hpp b/Sources/OpenVPN3/openvpn/common/peercred.hpp deleted file mode 100644 index aa5be90..0000000 --- a/Sources/OpenVPN3/openvpn/common/peercred.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// 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-2020 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_COMMON_PEERCRED_H -#define OPENVPN_COMMON_PEERCRED_H - -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> - -#ifdef OPENVPN_PLATFORM_TYPE_APPLE -#include <sys/ucred.h> -#endif - -namespace openvpn { - namespace SockOpt { - - struct Creds - { - Creds(const int uid_arg=-1, const int gid_arg=-1, const int pid_arg=-1) - : uid(uid_arg), - gid(gid_arg), - pid(pid_arg) - { - } - - bool root_or_self_uid() const - { - return !uid || uid == ::getuid(); - } - - bool root_uid() const - { - return !uid; - } - - bool match_uid(const uid_t other_uid) const - { - return uid >= 0 && uid == other_uid; - } - - uid_t uid; - uid_t gid; - uid_t pid; - }; - - // get credentials of process on other side of unix socket - inline bool peercreds(const int fd, Creds& cr) - { -#if defined(OPENVPN_PLATFORM_TYPE_APPLE) - xucred cred; - socklen_t credLen = sizeof(cred); - if (::getsockopt(fd, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) != 0) - return false; - cr = Creds(cred.cr_uid, cred.cr_gid); - return true; -#elif defined(OPENVPN_PLATFORM_LINUX) - struct ucred uc; - socklen_t uc_len = sizeof(uc); - if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &uc_len) != 0) - return false; - cr = Creds(uc.uid, uc.gid, uc.pid); - return true; -#else -#error no implementation for peercreds() -#endif - } - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/persistfile.hpp b/Sources/OpenVPN3/openvpn/common/persistfile.hpp deleted file mode 100644 index 2099b8e..0000000 --- a/Sources/OpenVPN3/openvpn/common/persistfile.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// 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-2020 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_COMMON_PERSISTFILE_H -#define OPENVPN_COMMON_PERSISTFILE_H - -#include <sys/types.h> // for open(), lseek(), ftruncate() -#include <sys/stat.h> // for open() -#include <fcntl.h> // for open() -#include <unistd.h> // for write(), lseek(), ftruncate() -#include <errno.h> - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/write.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - class PersistentFile - { - public: - PersistentFile(const std::string& fn_arg) - : fn(fn_arg) - { - const int f = ::open(fn.c_str(), O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR); - if (f < 0) - syserr("open"); - fd.reset(f); - } - - void write(const void *buf, size_t count) - { - const off_t off = ::lseek(fd(), 0, SEEK_SET); - if (off < 0) - syserr("seek"); - if (off) - err("unexpected seek"); - if (::ftruncate(fd(), 0) < 0) - syserr("truncate"); - const ssize_t len = write_retry(fd(), buf, count); - if (len < 0) - syserr("write"); - if (len != count || len != ::lseek(fd(), 0, SEEK_CUR)) - err("incomplete write"); - if (::ftruncate(fd(), len) < 0) - syserr("truncate"); - } - - struct stat stat() - { - struct stat s; - if (::fstat(fd(), &s) < 0) - syserr("fstat"); - return s; - } - - void write(const Buffer& buf) - { - write(buf.c_data(), buf.size()); - } - - void write(const std::string& str) - { - write(str.c_str(), str.length()); - } - - private: - void syserr(const char *type) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION(fn << " : " << type << " error : " << strerror_str(eno)); - } - - void err(const char *type) - { - OPENVPN_THROW_EXCEPTION(fn << " : " << type << " error"); - } - - std::string fn; - ScopedFD fd; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/pipe.hpp b/Sources/OpenVPN3/openvpn/common/pipe.hpp deleted file mode 100644 index 99e3d66..0000000 --- a/Sources/OpenVPN3/openvpn/common/pipe.hpp +++ /dev/null @@ -1,147 +0,0 @@ -// 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-2020 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_COMMON_PIPE_H -#define OPENVPN_COMMON_PIPE_H - -#include <unistd.h> -#include <errno.h> - -#include <string> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/buffer/buflist.hpp> - -namespace openvpn { - namespace Pipe { - class SD - { - public: - SD(openvpn_io::io_context& io_context, ScopedFD& fd) - { - if (fd.defined()) - sd.reset(new openvpn_io::posix::stream_descriptor(io_context, fd.release())); - } - - bool defined() const - { - return bool(sd); - } - - protected: - std::unique_ptr<openvpn_io::posix::stream_descriptor> sd; - }; - - class SD_OUT : public SD - { - public: - SD_OUT(openvpn_io::io_context& io_context, const std::string& content, ScopedFD& fd) - : SD(io_context, fd) - { - if (defined()) - { - buf = buf_alloc_from_string(content); - queue_write(); - } - } - - private: - void queue_write() - { - sd->async_write_some(buf.const_buffer_limit(2048), - [this](const openvpn_io::error_code& ec, const size_t bytes_sent) { - if (!ec && bytes_sent < buf.size()) - { - buf.advance(bytes_sent); - queue_write(); - } - else - { - sd->close(); - } - }); - } - - BufferAllocated buf; - }; - - class SD_IN : public SD - { - public: - SD_IN(openvpn_io::io_context& io_context, ScopedFD& fd) - : SD(io_context, fd) - { - if (defined()) - queue_read(); - } - - const std::string content() const - { - return data.to_string(); - } - - private: - void queue_read() - { - buf.reset(0, 2048, 0); - sd->async_read_some(buf.mutable_buffer_clamp(), - [this](const openvpn_io::error_code& ec, const size_t bytes_recvd) { - if (!ec) - { - buf.set_size(bytes_recvd); - data.put_consume(buf); - queue_read(); - } - else - { - sd->close(); - } - }); - } - - BufferAllocated buf; - BufferList data; - }; - - inline void make_pipe(int fd[2]) - { - if (::pipe(fd) < 0) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION("error creating pipe : " << strerror_str(eno)); - } - } - - inline void make_pipe(ScopedFD& read, ScopedFD& write) - { - int fd[2]; - make_pipe(fd); - read.reset(fd[0]); - write.reset(fd[1]); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/platform.hpp b/Sources/OpenVPN3/openvpn/common/platform.hpp deleted file mode 100644 index 5e1173f..0000000 --- a/Sources/OpenVPN3/openvpn/common/platform.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// 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-2020 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/>. - -// define a TARGET_x macro that describes our build target - -#ifndef OPENVPN_COMMON_PLATFORM_H -#define OPENVPN_COMMON_PLATFORM_H - -#if defined(_WIN32) -# define OPENVPN_PLATFORM_WIN -# if defined(__cplusplus_winrt) -# include <winapifamily.h> -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# define OPENVPN_PLATFORM_UWP -# endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) -# endif // defined(__cplusplus_winrt) -#elif defined(__APPLE__) -# include "TargetConditionals.h" -# define OPENVPN_PLATFORM_TYPE_APPLE -# if TARGET_OS_IPHONE // includes iPad -# define OPENVPN_PLATFORM_IPHONE -# define OPENVPN_PLATFORM_IPHONE_DEVICE -# elif TARGET_IPHONE_SIMULATOR // includes iPad -# define OPENVPN_PLATFORM_IPHONE -# define OPENVPN_PLATFORM_IPHONE_SIMULATOR -# elif TARGET_OS_MAC -# define OPENVPN_PLATFORM_MAC -# endif -#elif defined(__ANDROID__) -# define OPENVPN_PLATFORM_ANDROID -#elif defined(__linux__) -# define OPENVPN_PLATFORM_LINUX -#endif - -#if !defined(_WIN32) -#define OPENVPN_PLATFORM_TYPE_UNIX -#endif - -#endif // OPENVPN_COMMON_PLATFORM_H diff --git a/Sources/OpenVPN3/openvpn/common/platform_name.hpp b/Sources/OpenVPN3/openvpn/common/platform_name.hpp deleted file mode 100644 index 14e15ec..0000000 --- a/Sources/OpenVPN3/openvpn/common/platform_name.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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-2020 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_COMMON_PLATFORM_NAME_H -#define OPENVPN_COMMON_PLATFORM_NAME_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/platform.hpp> - -namespace openvpn { - - // return a string that describes our platform - inline const char *platform_name() - { -#if defined(OPENVPN_PLATFORM_WIN) -#if defined(OPENVPN_PLATFORM_UWP) - return "uwp"; -#else - return "win"; -#endif // UWP -#elif defined(OPENVPN_PLATFORM_MAC) - return "mac"; -#elif defined(OPENVPN_PLATFORM_IPHONE) - return "ios"; -#elif defined(OPENVPN_PLATFORM_IPHONE_SIMULATOR) - return "iosim"; -#elif defined(OPENVPN_PLATFORM_ANDROID) - return "android"; -#elif defined(OPENVPN_PLATFORM_LINUX) - return "linux"; -#else - return nullptr; -#endif - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_PLATFORM_NAME_H diff --git a/Sources/OpenVPN3/openvpn/common/platform_string.hpp b/Sources/OpenVPN3/openvpn/common/platform_string.hpp deleted file mode 100644 index 5c488bd..0000000 --- a/Sources/OpenVPN3/openvpn/common/platform_string.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// 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-2020 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_COMMON_PLATFORM_STRING_H -#define OPENVPN_COMMON_PLATFORM_STRING_H - -#include <string> -#include <sstream> - -#include <openvpn/common/version.hpp> -#include <openvpn/common/platform_name.hpp> - -namespace openvpn { - inline std::string platform_string(const std::string& title, const std::string& app_version) - { - std::ostringstream os; - - os << title << " "; - if (!app_version.empty()) - os << app_version << '/'; - os << OPENVPN_VERSION; - os << ' ' << platform_name(); -# if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) - os << " x86_64"; -# elif defined(__i386__) || defined(_M_IX86) - os << " i386"; -# elif defined(__aarch64__) || defined(__arm64__) - os << " arm64"; -# elif defined(__arm__) || defined(_M_ARM) -# if defined(__ARM_ARCH_7S__) || defined(_ARM_ARCH_7S) - os << " armv7s"; -# elif defined(__ARM_ARCH_7A__) - os << " armv7a"; -# elif defined(__ARM_V7__) || defined(_ARM_ARCH_7) - os << " armv7"; -# else - os << " arm"; -# endif -# if defined(__thumb2__) - os << " thumb2"; -# elif defined(__thumb__) || defined(_M_ARMT) - os << " thumb"; -# endif -# endif - - os << ' ' << (sizeof(void *) * 8) << "-bit"; - return os.str(); - } - - inline std::string platform_string() - { - return platform_string("OpenVPN core", ""); - } -} // namespace openvpn - -#endif // OPENVPN_COMMON_PLATFORM_STRING_H diff --git a/Sources/OpenVPN3/openvpn/common/process.hpp b/Sources/OpenVPN3/openvpn/common/process.hpp deleted file mode 100644 index 21bcab6..0000000 --- a/Sources/OpenVPN3/openvpn/common/process.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// 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-2020 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/>. - -// General-purpose classes for instantiating a posix process with arguments. - -#ifndef OPENVPN_COMMON_PROCESS_H -#define OPENVPN_COMMON_PROCESS_H - -#include <stdlib.h> // exit -#include <unistd.h> // fork, execve -#include <sys/types.h> // waitpid -#include <sys/wait.h> // waitpid - -#include <string> -#include <memory> -#include <utility> - -#include <openvpn/common/action.hpp> -#include <openvpn/common/redir.hpp> -#include <openvpn/common/signal.hpp> -#include <openvpn/common/argv.hpp> -#include <openvpn/common/environ.hpp> - -namespace openvpn { - - // low-level fork/exec (async) - inline pid_t system_cmd_async(const std::string& cmd, - const Argv& argv, - const Environ* env, - RedirectBase* redir, - const sigset_t* sigmask) - { - ArgvWrapper argv_wrap(argv); - std::unique_ptr<ArgvWrapper> env_wrap; - if (env) - env_wrap.reset(new ArgvWrapper(*env)); - auto fn = cmd.c_str(); - auto av = argv_wrap.c_argv(); - auto ev = env_wrap ? env_wrap->c_argv() : ::environ; - const pid_t pid = (redir || sigmask) ? ::fork() : ::vfork(); - if (pid == pid_t(0)) /* child side */ - { - // Only Async-signal-safe functions as specified by - // SIGNAL(7) can be called between here and _exit(). - if (sigmask) - ::pthread_sigmask(SIG_SETMASK, sigmask, 0); - if (redir) - redir->redirect(); - ::execve(fn, av, ev); - ::_exit(127); - } - else if (pid < pid_t(0)) /* fork failed */ - return -1; - else /* parent side */ - { - if (redir) - redir->close(); - return pid; - } - } - - // completion for system_cmd_async() - inline int system_cmd_post(const pid_t pid) - { - int status = -1; - if (::waitpid(pid, &status, 0) == pid) - { - if (WIFEXITED(status)) - return WEXITSTATUS(status); - } - return -1; - } - - // synchronous version of system_cmd_async - inline int system_cmd(const std::string& cmd, - const Argv& argv, - RedirectBase* redir, - const Environ* env, - const sigset_t* sigmask) - { - const pid_t pid = system_cmd_async(cmd, argv, env, redir, sigmask); - if (pid < pid_t(0)) - return -1; - return system_cmd_post(pid); - } - - // simple command execution - inline int system_cmd(const std::string& cmd, const Argv& argv) - { - return system_cmd(cmd, argv, nullptr, nullptr, nullptr); - } - - // simple command execution - inline int system_cmd(const Argv& argv) - { - int ret = -1; - if (argv.size()) - ret = system_cmd(argv[0], argv); - return ret; - } - - // command execution with std::strings as - // input/output/error (uses pipes under the - // hood) - inline int system_cmd(const std::string& cmd, - const Argv& argv, - const Environ* env, - RedirectPipe::InOut& inout, - unsigned int redirect_pipe_flags, - const sigset_t* sigmask) - { - SignalBlockerPipe sbpipe; - RedirectPipe remote; - if (!inout.in.empty()) - redirect_pipe_flags |= RedirectPipe::ENABLE_IN; - RedirectPipe local(remote, redirect_pipe_flags); - const pid_t pid = system_cmd_async(cmd, argv, env, &remote, sigmask); - if (pid < pid_t(0)) - return -1; - local.transact(inout); - return system_cmd_post(pid); - } - - struct Command : public Action - { - typedef RCPtr<Command> Ptr; - - Command() {} - - Command(Argv argv_arg) - : argv(std::move(argv_arg)) - { - } - - Command* copy() const - { - Command* ret = new Command; - ret->argv = argv; - return ret; - } - - virtual void execute(std::ostream& os) override - { - if (!argv.empty()) - { - os << to_string() << std::endl; -#ifdef OPENVPN_PROCESS_AVOID_PIPES - const int status = system_cmd(argv[0], argv); - if (status < 0) - os << "Error: command failed to execute" << std::endl; -#else - RedirectPipe::InOut inout; - const int status = system_cmd(argv[0], argv, nullptr, inout, RedirectPipe::COMBINE_OUT_ERR, nullptr); - if (status < 0) - os << "Error: command failed to execute" << std::endl; - os << inout.out; -#endif - } - else - os << "Error: command called with empty argv" << std::endl; - } - - virtual std::string to_string() const override - { - return argv.to_string(); - } - - Argv argv; - }; - -} - -#endif // OPENVPN_COMMON_PROCESS_H diff --git a/Sources/OpenVPN3/openvpn/common/pthreadcond.hpp b/Sources/OpenVPN3/openvpn/common/pthreadcond.hpp deleted file mode 100644 index 870799b..0000000 --- a/Sources/OpenVPN3/openvpn/common/pthreadcond.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// 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-2020 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_COMMON_PTHREADCOND_H -#define OPENVPN_COMMON_PTHREADCOND_H - -#include <mutex> -#include <condition_variable> -#include <chrono> - -#include <openvpn/common/stop.hpp> - -namespace openvpn { - - // Barrier class that is useful in cases where all threads - // need to reach a known point before executing some action. - // Note that this barrier implementation is - // constructed using C++11 condition variables. - class PThreadBarrier - { - enum State { - UNSIGNALED=0, // initial state - SIGNALED, // signal() was called - ERROR_THROWN, // error() was called - }; - - public: - // status return from wait() - enum Status { - SUCCESS=0, // successful - CHOSEN_ONE, // successful and chosen (only one thread is chosen) - TIMEOUT, // timeout - ERROR, // at least one thread called error() - }; - - PThreadBarrier(const int initial_limit = -1) - : stop(nullptr), - limit(initial_limit) - { - } - - PThreadBarrier(Stop* stop_arg, const int initial_limit = -1) - : stop(stop_arg), - limit(initial_limit) - { - } - - // All callers will increment count and block until - // count == limit. CHOSEN_ONE will be returned to - // the first caller to reach limit. This caller can - // then release all the other callers by calling - // signal(). - int wait(const unsigned int seconds) - { - // allow asynchronous stop - Stop::Scope stop_scope(stop, [this]() { - error(); - }); - - bool timeout = false; - int ret; - std::unique_lock<std::mutex> lock(mutex); - const unsigned int c = ++count; - while (state == UNSIGNALED - && (limit < 0 || c < static_cast<unsigned int>(limit)) - && !timeout) - timeout = (cv.wait_for(lock, std::chrono::seconds(seconds)) == std::cv_status::timeout); - if (timeout) - ret = TIMEOUT; - else if (state == ERROR_THROWN) - ret = ERROR; - else if (state == UNSIGNALED && !chosen) - { - ret = CHOSEN_ONE; - chosen = true; - } - else - ret = SUCCESS; - return ret; - } - - void set_limit(const int new_limit) - { - std::unique_lock<std::mutex> lock(mutex); - limit = new_limit; - cv.notify_all(); - } - - // Generally, only the CHOSEN_ONE calls signal() after its work - // is complete, to allow the other threads to pass the barrier. - void signal() - { - signal_(SIGNALED); - } - - // Causes all threads waiting on wait() (and those which call wait() - // in the future) to exit with ERROR status. - void error() - { - signal_(ERROR_THROWN); - } - - private: - void signal_(const State newstate) - { - std::unique_lock<std::mutex> lock(mutex); - if (state == UNSIGNALED) - { - state = newstate; - cv.notify_all(); - } - } - - std::mutex mutex; - std::condition_variable cv; - Stop* stop; - State state{UNSIGNALED}; - bool chosen = false; - int count = 0; - int limit; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/rc.hpp b/Sources/OpenVPN3/openvpn/common/rc.hpp deleted file mode 100644 index 89afb7c..0000000 --- a/Sources/OpenVPN3/openvpn/common/rc.hpp +++ /dev/null @@ -1,750 +0,0 @@ -// 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-2020 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/>. - -// A basic reference-counting garbage collection scheme based -// on intrusive pointers, where the reference count is embedded in -// the object via inheritance. Simply inherit from RC to create an -// object that can be tracked with an RCPtr. -// -// We use tend to use RCPtr (or RCWeakPtr) rather than the other -// smart pointer classes (std or boost) for flexibility and -// performance. -// -// Smart pointers have two basic attributes that determine -// their performance. Either of these attributes, when required, -// will degrade the performance of the smart pointer: -// -// 1. whether the smart pointer is thread-safe, i.e. it uses an -// atomic reference counter -// 2. whether the smart pointer can be referrred to via a -// weak reference -// -// In keeping with the oft-stated C++ motto of only paying for -// what you use, both attributes can be independently controlled. -// -// * thread-unsafe/not-weak-referenceable -- class Foo : public RC<thread_unsafe_refcount> -// * thread-safe/not-weak-referenceable -- class Foo : public RC<thread_safe_refcount> -// * thread-unsafe/weak-referenceable -- class Foo : public RCWeak<thread_unsafe_refcount> -// * thread-safe/weak-referenceable -- class Foo : public RCWeak<thread_safe_refcount> -// -// Thread-safe reference counting can be significantly more expensive -// because an atomic object must be used for the reference count. -// Therefore, thread-safe reference counting should only be used for -// objects that have visibility across multiple threads. -// -// In addition, having an object be weak-referenceable also -// imposes a cost, so it should be avoided unless necessary. -// -// For clarity and as a general convention in the OpenVPN code, -// any object that inherits from RC should also declare a Ptr -// typedef that defines the smart pointer type that should be used to -// track the object, e.g.: -// -// class Foo : public RC<thread_unsafe_refcount> { -// public: -// typedef RCPtr<Foo> Ptr; // strong pointer -// typedef RCWeakPtr<Foo> WPtr; // weak pointer -// }; -// -// This allows a smart-pointer to Foo to be referred to -// as Foo::Ptr or Foo::WPtr. -// -// Note that RC/RCWeak fully supports virtual inheritance. For -// example, consider the diamond inheritance pattern below, where -// both A and B objects contain their own reference count, but C -// inherits from both A and B. To prevent C objects from -// having two separate reference counts, it is necessary to -// virtually inherit from RC. -// -// class A : public virtual RC<thread_unsafe_refcount> {} -// class B : public virtual RC<thread_unsafe_refcount> {} -// class C : public A, public B {} - -#ifndef OPENVPN_COMMON_RC_H -#define OPENVPN_COMMON_RC_H - -#include <atomic> -#include <utility> - -#include <openvpn/common/olong.hpp> - -#ifdef OPENVPN_RC_DEBUG -#include <iostream> -#include <openvpn/common/demangle.hpp> -#endif - -namespace openvpn { - - // The smart pointer class - template <typename T> - class RCPtr - { - public: - typedef T element_type; - - RCPtr() noexcept - : px(nullptr) - { - } - - RCPtr(T* p, const bool add_ref=true) noexcept - : px(p) - { - if (px && add_ref) - intrusive_ptr_add_ref(px); - } - - RCPtr(const RCPtr& rhs) noexcept - : px(rhs.px) - { - if (px) - intrusive_ptr_add_ref(px); - } - - RCPtr(RCPtr&& rhs) noexcept - : px(rhs.px) - { - rhs.px = nullptr; - } - - template <typename U> - RCPtr(const RCPtr<U>& rhs) noexcept - : px(rhs.get()) - { - if (px) - intrusive_ptr_add_ref(px); - } - - ~RCPtr() - { - if (px) - intrusive_ptr_release(px); - } - - RCPtr& operator=(const RCPtr& rhs) noexcept - { - RCPtr(rhs).swap(*this); - return *this; - } - - RCPtr& operator=(RCPtr&& rhs) noexcept - { - RCPtr(std::move(rhs)).swap(*this); - return *this; - } - - void reset() noexcept - { - RCPtr().swap(*this); - } - - void reset(T* rhs) noexcept - { - RCPtr(rhs).swap(*this); - } - - void swap(RCPtr& rhs) noexcept - { - std::swap(px, rhs.px); - } - - T* get() const noexcept - { - return px; - } - - T& operator*() const noexcept - { - return *px; - } - - T* operator->() const noexcept - { - return px; - } - - explicit operator bool() const noexcept - { - return px != nullptr; - } - - bool operator==(const RCPtr& rhs) const - { - return px == rhs.px; - } - - bool operator!=(const RCPtr& rhs) const - { - return px != rhs.px; - } - - RCPtr<T> move_strong() noexcept - { - T* p = px; - px = nullptr; - return RCPtr<T>(p, false); - } - - template <typename U> - RCPtr<U> static_pointer_cast() const noexcept - { - return RCPtr<U>(static_cast<U*>(px)); - } - - template <typename U> - RCPtr<U> dynamic_pointer_cast() const noexcept - { - return RCPtr<U>(dynamic_cast<U*>(px)); - } - - private: - T* px; - }; - - template <typename T> - class RCWeakPtr - { - typedef RCPtr<T> Strong; - - public: - typedef T element_type; - - RCWeakPtr() noexcept {} - - RCWeakPtr(const Strong& p) noexcept - { - if (p) - controller = p->refcount_.controller; - } - - RCWeakPtr(T* p) noexcept - { - if (p) - controller = p->refcount_.controller; - } - - void reset(const Strong& p) noexcept - { - if (p) - controller = p->refcount_.controller; - else - controller.reset(); - } - - void reset(T* p) noexcept - { - if (p) - controller = p->refcount_.controller; - else - controller.reset(); - } - - void reset() noexcept - { - controller.reset(); - } - - void swap(RCWeakPtr& other) noexcept - { - controller.swap(other.controller); - } - - olong use_count() const noexcept - { - if (controller) - return controller->use_count(); - else - return 0; - } - - bool expired() const noexcept - { - return use_count() == 0; - } - - Strong lock() const noexcept - { - if (controller) - return controller->template lock<Strong>(); - else - return Strong(); - } - - Strong move_strong() noexcept - { - typename T::Controller::Ptr c; - c.swap(controller); - if (c) - return c->template lock<Strong>(); - else - return Strong(); - } - - private: - typename T::Controller::Ptr controller; - }; - - class thread_unsafe_refcount - { - public: - thread_unsafe_refcount() noexcept - : rc(olong(0)) - { - } - - void operator++() noexcept - { - ++rc; - } - - olong operator--() noexcept - { - return --rc; - } - - bool inc_if_nonzero() noexcept - { - if (rc) - { - ++rc; - return true; - } - else - return false; - } - - olong use_count() const noexcept - { - return rc; - } - - static constexpr bool is_thread_safe() - { - return false; - } - -#ifdef OPENVPN_RC_NOTIFY - void notify_release() noexcept - { - } -#endif - -#ifdef OPENVPN_RC_NOTIFY - template <typename T> - class ListHead - { - public: - ListHead() noexcept : ptr(nullptr) {} - - T* load() noexcept - { - return ptr; - } - - void insert(T* item) noexcept - { - item->next = ptr; - ptr = item; - } - - private: - ListHead(const ListHead&) = delete; - ListHead& operator=(const ListHead&) = delete; - - T* ptr; - }; -#endif - - private: - thread_unsafe_refcount(const thread_unsafe_refcount&) = delete; - thread_unsafe_refcount& operator=(const thread_unsafe_refcount&) = delete; - - olong rc; - }; - - class thread_safe_refcount - { - public: - thread_safe_refcount() noexcept - : rc(olong(0)) - { - } - - void operator++() noexcept - { - rc.fetch_add(1, std::memory_order_relaxed); - } - - olong operator--() noexcept - { - // http://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html - const olong ret = rc.fetch_sub(1, std::memory_order_release) - 1; - if (ret == 0) - std::atomic_thread_fence(std::memory_order_acquire); - return ret; - } - - // If refcount is 0, do nothing and return false. - // If refcount != 0, increment it and return true. - bool inc_if_nonzero() noexcept - { - olong previous = rc.load(std::memory_order_relaxed); - while (true) - { - if (!previous) - break; - if (rc.compare_exchange_weak(previous, previous + 1, std::memory_order_relaxed)) - break; - } - return previous > 0; - } - - olong use_count() const noexcept - { - return rc.load(std::memory_order_relaxed); - } - - static constexpr bool is_thread_safe() - { - return true; - } - -#ifdef OPENVPN_RC_NOTIFY - void notify_release() noexcept - { - } -#endif - -#ifdef OPENVPN_RC_NOTIFY - template <typename T> - class ListHead - { - public: - ListHead() noexcept : ptr(nullptr) {} - - T* load() noexcept - { - return ptr.load(std::memory_order_relaxed); - } - - void insert(T* item) noexcept - { - T* previous = ptr.load(std::memory_order_relaxed); - while (true) - { - item->next = previous; - if (ptr.compare_exchange_weak(previous, item, std::memory_order_relaxed)) - break; - } - } - - private: - ListHead(const ListHead&) = delete; - ListHead& operator=(const ListHead&) = delete; - - std::atomic<T*> ptr; - }; -#endif - - private: - thread_safe_refcount(const thread_safe_refcount&) = delete; - thread_safe_refcount& operator=(const thread_safe_refcount&) = delete; - - std::atomic<olong> rc; - }; - - // Reference count base class for objects tracked by RCPtr. - // Disallows copying and assignment. - template <typename RCImpl> // RCImpl = thread_safe_refcount or thread_unsafe_refcount - class RC - { - public: - typedef RCPtr<RC> Ptr; - - RC() noexcept {} - virtual ~RC() {} - - olong use_count() const noexcept - { - return refcount_.use_count(); - } - - static constexpr bool is_thread_safe() - { - return RCImpl::is_thread_safe(); - } - - private: - RC(const RC&) = delete; - RC& operator=(const RC&) = delete; - - template <typename R> friend void intrusive_ptr_add_ref(R* p) noexcept; - template <typename R> friend void intrusive_ptr_release(R* p) noexcept; - RCImpl refcount_; - }; - - // Like RC, but allows object to be copied and assigned. - template <typename RCImpl> // RCImpl = thread_safe_refcount or thread_unsafe_refcount - class RCCopyable - { - public: - RCCopyable() noexcept {} - RCCopyable(const RCCopyable&) noexcept {} - RCCopyable& operator=(const RCCopyable&) noexcept { return *this; } - virtual ~RCCopyable() {} - - olong use_count() const noexcept - { - return refcount_.use_count(); - } - - private: - template <typename R> friend void intrusive_ptr_add_ref(R* p) noexcept; - template <typename R> friend void intrusive_ptr_release(R* p) noexcept; - RCImpl refcount_; - }; - - // Like RC, but also allows weak pointers and release notification callables - template <typename RCImpl> // RCImpl = thread_safe_refcount or thread_unsafe_refcount - class RCWeak - { - template<typename T> - friend class RCWeakPtr; - -#ifdef OPENVPN_RC_NOTIFY - // Base class of release notification callables - class NotifyBase - { - public: - NotifyBase() noexcept {} - virtual void call() noexcept = 0; - virtual ~NotifyBase() {} - NotifyBase* next; - - private: - NotifyBase(const NotifyBase&) = delete; - NotifyBase& operator=(const NotifyBase&) = delete; - }; - - // A release notification callable - template <typename CALLABLE> - class NotifyItem : public NotifyBase - { - public: - NotifyItem(const CALLABLE& c) noexcept - : callable(c) - { - } - - NotifyItem(CALLABLE&& c) noexcept - : callable(std::move(c)) - { - } - - private: - virtual void call() noexcept override - { - callable(); - } - - CALLABLE callable; - }; - - // Head of a linked-list of release notification callables - class NotifyListHead - { - public: - NotifyListHead() noexcept {} - - template <typename CALLABLE> - void add(const CALLABLE& c) noexcept - { - NotifyBase* item = new NotifyItem<CALLABLE>(c); - head.insert(item); - } - - template <typename CALLABLE> - void add(CALLABLE&& c) noexcept - { - NotifyBase* item = new NotifyItem<CALLABLE>(std::move(c)); - head.insert(item); - } - - void release() noexcept - { - // In thread-safe mode, list traversal is guaranteed to be - // contention-free because we are not called until refcount - // reaches zero and after a std::memory_order_acquire fence. - NotifyBase* nb = head.load(); - while (nb) - { - NotifyBase* next = nb->next; - nb->call(); - delete nb; - nb = next; - } - } - - private: - NotifyListHead(const NotifyListHead&) = delete; - NotifyListHead& operator=(const NotifyListHead&) = delete; - - typename RCImpl::template ListHead<NotifyBase> head; - }; -#endif - - // For weak-referenceable objects, we must detach the - // refcount from the object and place it in Controller. - struct Controller : public RC<RCImpl> - { - typedef RCPtr<Controller> Ptr; - - Controller(RCWeak* parent_arg) noexcept - : parent(parent_arg) - { - } - - olong use_count() const noexcept - { - return rc.use_count(); - } - - template <typename PTR> - PTR lock() noexcept - { - if (rc.inc_if_nonzero()) - return PTR(static_cast<typename PTR::element_type*>(parent), false); - else - return PTR(); - } - - RCWeak *const parent; // dangles (harmlessly) after rc decrements to 0 - RCImpl rc; // refcount - }; - - struct ControllerRef - { - ControllerRef(RCWeak* parent) noexcept - : controller(new Controller(parent)) - { - } - - void operator++() noexcept - { - ++controller->rc; - } - - olong operator--() noexcept - { - return --controller->rc; - } - -#ifdef OPENVPN_RC_NOTIFY - void notify_release() noexcept - { - notify.release(); - } -#endif - - typename Controller::Ptr controller; // object containing actual refcount - -#ifdef OPENVPN_RC_NOTIFY - NotifyListHead notify; // linked list of callables to be notified on object release -#endif - }; - - public: - typedef RCPtr<RCWeak> Ptr; - typedef RCWeakPtr<RCWeak> WPtr; - - RCWeak() noexcept - : refcount_(this) - { - } - - virtual ~RCWeak() - { - } - -#ifdef OPENVPN_RC_NOTIFY - // Add observers to be called just prior to object deletion, - // but after refcount has been decremented to 0. At this - // point, all weak pointers have expired, and no strong - // pointers are outstanding. Callables can access the - // object by raw pointer but must NOT attempt to create a - // strong pointer referencing the object. - - template <typename CALLABLE> - void rc_release_notify(const CALLABLE& c) noexcept - { - refcount_.notify.add(c); - } - - template <typename CALLABLE> - void rc_release_notify(CALLABLE&& c) noexcept - { - refcount_.notify.add(std::move(c)); - } -#endif - - private: - RCWeak(const RCWeak&) = delete; - RCWeak& operator=(const RCWeak&) = delete; - - template <typename R> friend void intrusive_ptr_add_ref(R* p) noexcept; - template <typename R> friend void intrusive_ptr_release(R* p) noexcept; - - ControllerRef refcount_; - }; - - template <typename R> - inline void intrusive_ptr_add_ref(R *p) noexcept - { -#ifdef OPENVPN_RC_DEBUG - std::cout << "ADD REF " << cxx_demangle(typeid(p).name()) << std::endl; -#endif - ++p->refcount_; - } - - template <typename R> - inline void intrusive_ptr_release(R *p) noexcept - { - if (--p->refcount_ == 0) - { -#ifdef OPENVPN_RC_DEBUG - std::cout << "DEL OBJ " << cxx_demangle(typeid(p).name()) << std::endl; -#endif -#ifdef OPENVPN_RC_NOTIFY - p->refcount_.notify_release(); -#endif - delete p; - } - else - { -#ifdef OPENVPN_RC_DEBUG - std::cout << "REL REF " << cxx_demangle(typeid(p).name()) << std::endl; -#endif - } - } - -} // namespace openvpn - -#endif // OPENVPN_COMMON_RC_H diff --git a/Sources/OpenVPN3/openvpn/common/redir.hpp b/Sources/OpenVPN3/openvpn/common/redir.hpp deleted file mode 100644 index e3db858..0000000 --- a/Sources/OpenVPN3/openvpn/common/redir.hpp +++ /dev/null @@ -1,310 +0,0 @@ -// 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-2020 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_COMMON_REDIR_H -#define OPENVPN_COMMON_REDIR_H - -#include <fcntl.h> -#include <unistd.h> -#include <cstring> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -#include <string> -#include <utility> -#include <memory> -#include <algorithm> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/tempfile.hpp> -#include <openvpn/common/pipe.hpp> -#include <openvpn/common/strerror.hpp> - -namespace openvpn { - - struct RedirectBase - { - OPENVPN_EXCEPTION(redirect_std_err); - virtual void redirect() = 0; - virtual void close() = 0; - virtual ~RedirectBase() {} - }; - - struct RedirectStdFD : public RedirectBase - { - virtual void redirect() noexcept override - { - // stdin - if (in.defined()) - { - ::dup2(in(), 0); - if (in() <= 2) - in.release(); - } - - // stdout - if (out.defined()) - { - ::dup2(out(), 1); - if (!err.defined() && combine_out_err) - ::dup2(out(), 2); - if (out() <= 2) - out.release(); - } - - // stderr - if (err.defined()) - { - ::dup2(err(), 2); - if (err() <= 2) - err.release(); - } - - close(); - } - - virtual void close() override - { - in.close(); - out.close(); - err.close(); - } - - ScopedFD in; - ScopedFD out; - ScopedFD err; - bool combine_out_err = false; - }; - - class RedirectNull : public RedirectStdFD - { - public: - RedirectNull() - { - // open /dev/null for stdin - in.reset(::open("/dev/null", O_RDONLY, 0)); - if (!in.defined()) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "RedirectNull: error opening /dev/null for input : " << strerror_str(eno)); - } - - // open /dev/null for stdout - out.reset(::open("/dev/null", O_RDWR, 0)); - if (!out.defined()) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "RedirectNull: error opening /dev/null for output : " << strerror_str(eno)); - } - combine_out_err = true; - } - }; - - class RedirectStd : public RedirectStdFD - { - public: - // flags shortcuts - static constexpr int FLAGS_OVERWRITE = O_CREAT | O_WRONLY | O_TRUNC; - static constexpr int FLAGS_APPEND = O_CREAT | O_WRONLY | O_APPEND; - static constexpr int FLAGS_MUST_NOT_EXIST = O_CREAT | O_WRONLY | O_EXCL; - - // mode shortcuts - static constexpr mode_t MODE_ALL = 0777; - static constexpr mode_t MODE_USER_GROUP = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; - static constexpr mode_t MODE_USER = S_IRUSR | S_IWUSR; - - RedirectStd(const std::string& in_fn, - const std::string& out_fn, - const int out_flags = FLAGS_OVERWRITE, - const mode_t out_mode = MODE_ALL, - const bool combine_out_err_arg = true) - { - if (!in_fn.empty()) - open_input(in_fn); - open_output(out_fn, out_flags, out_mode); - combine_out_err = combine_out_err_arg; - } - - protected: - RedirectStd() {} - - void open_input(const std::string& fn) - { - // open input file for stdin - in.reset(::open(fn.c_str(), O_RDONLY, 0)); - if (!in.defined()) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "error opening input file: " << fn << " : " << strerror_str(eno)); - } - } - - void open_output(const std::string& fn, - const int flags, - const mode_t mode) - { - // open output file for stdout/stderr - out.reset(::open(fn.c_str(), - flags, - mode)); - if (!out.defined()) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "error opening output file: " << fn << " : " << strerror_str(eno)); - } - } - }; - - class RedirectTemp : public RedirectStd - { - public: - RedirectTemp(const std::string& stdin_fn, - TempFile& stdout_temp, - const bool combine_out_err_arg) - { - open_input(stdin_fn); - out = std::move(stdout_temp.fd); - combine_out_err = combine_out_err_arg; - } - - RedirectTemp(const std::string& stdin_fn, - TempFile& stdout_temp, - TempFile& stderr_temp) - { - open_input(stdin_fn); - out = std::move(stdout_temp.fd); - err = std::move(stderr_temp.fd); - } - }; - - class RedirectPipe : public RedirectStdFD - { - public: - enum { - COMBINE_OUT_ERR = (1<<0), // capture combined stdout/stderr using a pipe - ENABLE_IN = (1<<1), // make a string -> stdin pipe, otherwise redirect stdin from /dev/null - IGNORE_IN = (1<<2), // don't touch stdin - IGNORE_OUT = (1<<3), // don't touch stdout - IGNORE_ERR = (1<<4), // don't touch stderr - }; - - struct InOut - { - std::string in; - std::string out; - std::string err; - }; - - RedirectPipe() {} - - RedirectPipe(RedirectStdFD& remote, - const unsigned int flags_arg) - : flags(flags_arg) - { - // stdout - if (!(flags & IGNORE_OUT)) - { - int fd[2]; - Pipe::make_pipe(fd); - out.reset(cloexec(fd[0])); - remote.out.reset(fd[1]); - } - - // stderr - if (!(flags & IGNORE_ERR)) - { - combine_out_err = remote.combine_out_err = ((flags & (COMBINE_OUT_ERR|IGNORE_OUT)) == COMBINE_OUT_ERR); - if (!combine_out_err) - { - int fd[2]; - Pipe::make_pipe(fd); - err.reset(cloexec(fd[0])); - remote.err.reset(fd[1]); - } - } - - // stdin - if (!(flags & IGNORE_IN)) - { - if (flags & ENABLE_IN) - { - int fd[2]; - Pipe::make_pipe(fd); - in.reset(cloexec(fd[1])); - remote.in.reset(fd[0]); - } - else - { - // open /dev/null for stdin - remote.in.reset(::open("/dev/null", O_RDONLY, 0)); - if (!remote.in.defined()) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "error opening /dev/null : " << strerror_str(eno)); - } - } - } - } - - void transact(InOut& inout) - { - openvpn_io::io_context io_context(1); - - std::unique_ptr<Pipe::SD_OUT> send_in; - std::unique_ptr<Pipe::SD_IN> recv_out; - std::unique_ptr<Pipe::SD_IN> recv_err; - - if (!(flags & IGNORE_IN)) - send_in.reset(new Pipe::SD_OUT(io_context, inout.in, in)); - if (!(flags & IGNORE_OUT)) - recv_out.reset(new Pipe::SD_IN(io_context, out)); - if (!(flags & IGNORE_ERR)) - recv_err.reset(new Pipe::SD_IN(io_context, err)); - - io_context.run(); - - if (recv_out) - inout.out = recv_out->content(); - if (recv_err) - inout.err = recv_err->content(); - } - - private: - // set FD_CLOEXEC to prevent fd from being passed across execs - static int cloexec(const int fd) - { - if (::fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) - { - const int eno = errno; - OPENVPN_THROW(redirect_std_err, "error setting FD_CLOEXEC on pipe : " << strerror_str(eno)); - } - return fd; - } - - const unsigned int flags = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/runcontext.hpp b/Sources/OpenVPN3/openvpn/common/runcontext.hpp deleted file mode 100644 index f85b690..0000000 --- a/Sources/OpenVPN3/openvpn/common/runcontext.hpp +++ /dev/null @@ -1,441 +0,0 @@ -// 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-2020 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/>. - -// Manage a pool of threads for a multi-threaded server. -// -// To stress test this code, in client after serv->start() add: -// if (unit == 3 || unit == 5) -// throw Exception("HIT IT"); -// And after "case PThreadBarrier::ERROR:" -// if (unit & 1) -// break; - -#ifndef OPENVPN_COMMON_RUNCONTEXT_H -#define OPENVPN_COMMON_RUNCONTEXT_H - -#include <string> -#include <vector> -#include <thread> -#include <mutex> -#include <memory> -#include <type_traits> // for std::is_nothrow_move_constructible -#include <utility> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/signal.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/common/environ.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/signal_name.hpp> -#include <openvpn/asio/asiosignal.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/time/timestr.hpp> -#include <openvpn/common/logsetup.hpp> - -#ifdef ASIO_HAS_LOCAL_SOCKETS -#include <openvpn/common/scoped_fd.hpp> -#endif - -namespace openvpn { - - struct RunContextLogEntry - { - RunContextLogEntry(const time_t timestamp_arg, const std::string& text_arg) - : timestamp(timestamp_arg), - text(text_arg) - { - } - - time_t timestamp; - std::string text; - }; - - template <typename RC_TYPE> - struct ServerThreadType : public virtual RC_TYPE - { - typedef RCPtr<ServerThreadType> Ptr; - typedef RCWeakPtr<ServerThreadType> WPtr; - - virtual void thread_safe_stop() = 0; - - virtual void log_notify(const RunContextLogEntry& le) - { - } - }; - - typedef ServerThreadType<RCWeak<thread_safe_refcount>> ServerThreadWeakBase; - typedef ServerThreadType<RC<thread_safe_refcount>> ServerThreadBase; - - struct RunContextBase : public LogBase - { - virtual void cancel() = 0; - virtual std::vector<RunContextLogEntry> add_log_observer(const unsigned int unit) = 0; - virtual void disable_log_history() = 0; - virtual Stop* async_stop() = 0; - }; - - template <typename ServerThread, typename Stats> - class RunContext : public RunContextBase - { - public: - typedef RCPtr<RunContext> Ptr; - - class ThreadContext - { - public: - ThreadContext(RunContext& ctx_arg) - : ctx(ctx_arg) - { - ctx.add_thread(); - } - - ~ThreadContext() - { - ctx.remove_thread(); - } - - private: - RunContext& ctx; - }; - - RunContext() - : exit_timer(io_context), - log_context(this), - log_wrap() - { - signals.reset(new ASIOSignals(io_context)); - signal_rearm(); - schedule_debug_exit(); - } - - void set_async_stop(Stop* async_stop) - { - async_stop_ = async_stop; - } - - void set_log_reopen(LogSetup::Ptr lr) - { - log_reopen = std::move(lr); - } - - void set_thread(const unsigned int unit, std::thread* thread) - { - while (threadlist.size() <= unit) - threadlist.push_back(nullptr); - if (threadlist[unit]) - throw Exception("RunContext::set_thread: overwrite"); - threadlist[unit] = thread; - } - - // called from worker thread - void set_server(const unsigned int unit, ServerThread* serv) - { - std::lock_guard<std::recursive_mutex> lock(mutex); - if (halt) - throw Exception("RunContext::set_server: halting"); - while (servlist.size() <= unit) - servlist.push_back(nullptr); - if (servlist[unit]) - throw Exception("RunContext::set_server: overwrite"); - servlist[unit] = serv; - } - - // called from worker thread - void clear_server(const unsigned int unit) - { - std::lock_guard<std::recursive_mutex> lock(mutex); - if (unit < servlist.size()) - servlist[unit] = nullptr; - - // remove log observer entry, if present - auto lu = std::find(log_observers.begin(), log_observers.end(), unit); - if (lu != log_observers.end()) - log_observers.erase(lu); - } - - std::vector<typename ServerThread::Ptr> get_servers() - { - std::lock_guard<std::recursive_mutex> lock(mutex); - std::vector<typename ServerThread::Ptr> ret; - if (halt) - return ret; - ret.reserve(servlist.size()); - for (auto sp : servlist) - ret.emplace_back(sp); - return ret; - } - - void enable_log_history() - { - std::lock_guard<std::recursive_mutex> lock(mutex); - if (!log_history) - log_history.reset(new std::vector<RunContextLogEntry>()); - } - - virtual void disable_log_history() override - { - std::lock_guard<std::recursive_mutex> lock(mutex); - log_history.reset(); - } - - virtual std::vector<RunContextLogEntry> add_log_observer(const unsigned int unit) override - { - std::lock_guard<std::recursive_mutex> lock(mutex); - auto lu = std::find(log_observers.begin(), log_observers.end(), unit); - if (lu == log_observers.end()) - log_observers.push_back(unit); - if (log_history) - return *log_history; - else - return std::vector<RunContextLogEntry>(); - } - -#ifdef ASIO_HAS_LOCAL_SOCKETS - void set_exit_socket(ScopedFD& fd) - { - exit_sock.reset(new openvpn_io::posix::stream_descriptor(io_context, fd.release())); - exit_sock->async_read_some(openvpn_io::null_buffers(), - [self=Ptr(this)](const openvpn_io::error_code& error, const size_t bytes_recvd) - { - if (!error) - self->cancel(); - }); - } -#endif - - void set_prefix(const std::string& pre) - { - prefix = pre + ": "; - } - - void run() - { - if (!halt) - io_context.run(); - } - - void join() - { - for (size_t i = 0; i < threadlist.size(); ++i) - { - std::thread* t = threadlist[i]; - if (t) - { - t->join(); - delete t; - threadlist[i] = nullptr; - } - } - } - - virtual void log(const std::string& str) override - { - time_t now; - const std::string ts = date_time_store_time_t(now); - { - std::lock_guard<std::recursive_mutex> lock(mutex); - std::cout << ts << ' ' << str << std::flush; - - if (!log_observers.empty() || log_history) - { - const RunContextLogEntry le(now, str); - for (auto &si : log_observers) - { - ServerThread* st = servlist[si]; - if (st) - st->log_notify(le); - } - if (log_history) - log_history->emplace_back(now, str); - } - } - } - - // called from main or worker thread - virtual void cancel() override - { - if (halt) - return; - openvpn_io::post(io_context, [self=Ptr(this)]() - { - std::lock_guard<std::recursive_mutex> lock(self->mutex); - if (self->halt) - return; - self->halt = true; - - // async stop - if (self->async_stop_) - self->async_stop_->stop(); - - self->exit_timer.cancel(); -#ifdef ASIO_HAS_LOCAL_SOCKETS - self->exit_sock.reset(); -#endif - if (self->signals) - self->signals->cancel(); - - // stop threads - { - unsigned int stopped = 0; - for (size_t i = 0; i < self->servlist.size(); ++i) - { - ServerThread* serv = self->servlist[i]; - if (serv) - { - serv->thread_safe_stop(); - ++stopped; - } - self->servlist[i] = nullptr; - } - OPENVPN_LOG(self->prefix << "Stopping " << stopped << '/' << self->servlist.size() << " thread(s)"); - } - }); - } - - const Log::Context::Wrapper& log_wrapper() { return log_wrap; } - - void set_stats_obj(const typename Stats::Ptr& stats_arg) - { - stats = stats_arg; - } - - virtual Stop* async_stop() override - { - return async_stop_; - } - - private: - // called from main or worker thread - void add_thread() - { - std::lock_guard<std::recursive_mutex> lock(mutex); - ++thread_count; - } - - // called from main or worker thread - void remove_thread() - { - bool last = false; - { - std::lock_guard<std::recursive_mutex> lock(mutex); - last = (--thread_count <= 0); - } - if (last) - cancel(); - } - - protected: - virtual void signal(const openvpn_io::error_code& error, int signum) - { - if (!error && !halt) - { - OPENVPN_LOG("ASIO SIGNAL: " << signal_name(signum)); - switch (signum) - { - case SIGINT: - case SIGTERM: - cancel(); - break; -#if !defined(OPENVPN_PLATFORM_WIN) - case SIGUSR2: - if (stats) - OPENVPN_LOG(stats->dump()); - signal_rearm(); - break; - case SIGHUP: - if (log_reopen) - log_reopen->reopen(); - signal_rearm(); - break; -#endif - default: - signal_rearm(); - break; - } - } - } - - private: - void signal_rearm() - { - signals->register_signals_all([self=Ptr(this)](const openvpn_io::error_code& error, int signal_number) - { - self->signal(error, signal_number); - }); - } - - // debugging feature -- exit in n seconds - void schedule_debug_exit() - { - const std::string exit_in = Environ::find_static("EXIT_IN"); - if (exit_in.empty()) - return; - const unsigned int n_sec = parse_number_throw<unsigned int>(exit_in, "error parsing EXIT_IN"); - exit_timer.expires_after(Time::Duration::seconds(n_sec)); - exit_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (error || self->halt) - return; - OPENVPN_LOG("DEBUG EXIT"); - self->cancel(); - }); - } - - // these vars only used by main thread - openvpn_io::io_context io_context{1}; - typename Stats::Ptr stats; - ASIOSignals::Ptr signals; - AsioTimer exit_timer; - std::string prefix; - std::vector<std::thread*> threadlist; -#ifdef ASIO_HAS_LOCAL_SOCKETS - std::unique_ptr<openvpn_io::posix::stream_descriptor> exit_sock; -#endif - - // main lock - std::recursive_mutex mutex; - - // servlist and related vars protected by mutex - std::vector<ServerThread*> servlist; - int thread_count = 0; - - // stop - Stop* async_stop_ = nullptr; - - // log observers - std::vector<unsigned int> log_observers; // unit numbers of log observers - std::unique_ptr<std::vector<RunContextLogEntry>> log_history; - - // logging - Log::Context log_context; - Log::Context::Wrapper log_wrap; // must be constructed after log_context - LogSetup::Ptr log_reopen; - - protected: - volatile bool halt = false; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/scoped_fd.hpp b/Sources/OpenVPN3/openvpn/common/scoped_fd.hpp deleted file mode 100644 index d7d32fd..0000000 --- a/Sources/OpenVPN3/openvpn/common/scoped_fd.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// 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-2020 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/>. - -// A scoped file descriptor that is automatically closed by its destructor. - -#ifndef OPENVPN_COMMON_SCOPED_FD_H -#define OPENVPN_COMMON_SCOPED_FD_H - -#include <unistd.h> // for close() -#include <errno.h> - -namespace openvpn { - - class ScopedFD - { - ScopedFD(const ScopedFD&) = delete; - ScopedFD& operator=(const ScopedFD&) = delete; - - public: - typedef int base_type; - - ScopedFD() : fd(undefined()) {} - - explicit ScopedFD(const int fd_arg) - : fd(fd_arg) {} - - static int undefined() { return -1; } - - int release() - { - const int ret = fd; - fd = -1; - //OPENVPN_LOG("**** SFD RELEASE=" << ret); - return ret; - } - - static bool defined_static(int fd) - { - return fd >= 0; - } - - bool defined() const - { - return defined_static(fd); - } - - int operator()() const - { - return fd; - } - - void reset(const int fd_arg) - { - close(); - fd = fd_arg; - //OPENVPN_LOG("**** SFD RESET=" << fd); - } - - void reset() - { - close(); - } - - // unusual semantics: replace fd without closing it first - void replace(const int fd_arg) - { - //OPENVPN_LOG("**** SFD REPLACE " << fd << " -> " << fd_arg); - fd = fd_arg; - } - - // return false if close error - bool close() - { - return close_with_errno() == 0; - } - - // return errno value if close error, otherwise return 0 - int close_with_errno() - { - int eno = 0; - if (defined()) - { - if (::close(fd) == -1) - eno = errno; - post_close(eno); - //OPENVPN_LOG("**** SFD CLOSE fd=" << fd << " errno=" << eno); - fd = -1; - } - return eno; - } - - virtual void post_close(const int close_errno) - { - } - - virtual ~ScopedFD() - { - //OPENVPN_LOG("**** SFD DESTRUCTOR"); - close(); - } - - ScopedFD(ScopedFD&& other) noexcept - { - fd = other.fd; - other.fd = -1; - } - - ScopedFD& operator=(ScopedFD&& other) noexcept - { - close(); - fd = other.fd; - other.fd = -1; - return *this; - } - - private: - int fd; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_SCOPED_FD_H diff --git a/Sources/OpenVPN3/openvpn/common/sess_id.hpp b/Sources/OpenVPN3/openvpn/common/sess_id.hpp deleted file mode 100644 index 2e4d857..0000000 --- a/Sources/OpenVPN3/openvpn/common/sess_id.hpp +++ /dev/null @@ -1,203 +0,0 @@ -// 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-2020 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/>. - -// A general-purpose Session ID class - -#ifndef OPENVPN_COMMON_SESS_ID_H -#define OPENVPN_COMMON_SESS_ID_H - -#include <string> -#include <cstring> -#include <cstdint> // for std::uint8_t, std::uint64_t - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/common/ostream.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - template <size_t SIZE> - class SessionIDType - { - public: - template <size_t S> friend class SessionIDType; - - // Create a zeroed Sesson ID. - SessionIDType() - { - // compile-time size constraints - static_assert(sizeof(u.data) >= sizeof(std::uint64_t), "SessionIDType SIZE too small"); - static_assert(SIZE % sizeof(std::uint64_t) == size_t(0), "SessionIDType SIZE must be an integer multiple of 64 bits"); - std::memset(u.data, 0, sizeof(u.data)); - } - - // Create a random Session ID. - explicit SessionIDType(RandomAPI& rng, const bool allow_noncrypto_rng=false) - { - if (!allow_noncrypto_rng) - rng.assert_crypto(); - rng.rand_bytes(u.data, sizeof(u.data)); - } - - // Create a Session ID from a base64 (URL-safe) string. - explicit SessionIDType(const std::string& b64) - { - Buffer srcbuf(u.data, sizeof(u.data), false); - try { - base64_urlsafe->decode(srcbuf, b64); - } - catch (const std::exception& e) - { - throw Exception("SessionID: base64 decode: " + std::string(e.what())); - } - if (srcbuf.size() != sizeof(u.data)) - throw Exception("SessionID: wrong input size, actual=" + std::to_string(srcbuf.size()) + " expected=" + std::to_string(sizeof(u.data))); - } - - // Create a Session ID from a byte string of size size(). - explicit SessionIDType(const std::uint8_t* bytes) - { - std::memcpy(u.data, bytes, SIZE); - } - - // Create a Session ID from another Session ID of possibly - // different size. If the other Session ID is larger, - // truncate, if it's smaller, zero our tail. - template <size_t S> - explicit SessionIDType(const SessionIDType<S>& other) - { - for (size_t i = 0; i < array_size(u.dataz); ++i) - u.dataz[i] = (i < array_size(other.u.dataz)) ? other.u.dataz[i] : 0; - } - - // Create an encrypted Session ID. - // Intended to be used with TokenEncrypt. - template <typename CRYPT> - explicit SessionIDType(const SessionIDType& other, CRYPT& crypt) - { - crypt(u.data, other.u.data, SIZE); - } - - // Session ID is considered to be undefined if all bits are zero. - bool defined() const - { - for (size_t i = 0; i < array_size(u.dataz); ++i) - if (u.dataz[i]) - return true; - return false; - } - - // Return the lower 64 bits of Session ID regardless of the size. - std::uint64_t shortform() const - { - return u.dataz[0]; - } - - template <typename HASH> - void hash(HASH& h) const - { - h(u.dataz[0]); - } - - // Use a URL-safe base64 encoding. - std::string to_string() const - { - return base64_urlsafe->encode(u.data, sizeof(u.data)); - } - - bool operator==(const SessionIDType& other) const - { - return std::memcmp(u.data, other.u.data, sizeof(u.data)) == 0; - } - - bool operator!=(const SessionIDType& other) const - { - return !operator==(other); - } - - bool operator<(const SessionIDType& other) const - { - return std::memcmp(u.data, other.u.data, sizeof(u.data)) < 0; - } - - // Weak equality means that the lower 64 bits compare equal. - template <size_t S> - bool eq_weak(const SessionIDType<S>& other) const - { - return shortform() == other.shortform(); - } - - // True if the string looks like a Session ID. - static bool is(const std::string& str) - { - return base64_urlsafe->is_base64(str, SIZE); - } - - static constexpr size_t size() - { - return SIZE; - } - - const std::uint8_t* c_data() const - { - return u.data; - } - - // Find an element in an unordered map (keyed by Session ID) - // using weak equality. If conflict is true, only return - // element that is present by weak equality, but which is - // not equal to *this by strong equality. - template <typename UNORDERED_MAP> - const SessionIDType* find_weak(const UNORDERED_MAP& m, const bool conflict) const - { - if (m.bucket_count()) - { - const size_t bi = m.bucket(*this); - for (auto i = m.cbegin(bi); i != m.cend(bi); ++i) - if (shortform() == i->first.shortform() && (!conflict || *this != i->first)) - return &i->first; - } - return nullptr; - } - - private: - union { - std::uint64_t dataz[SIZE / sizeof(std::uint64_t)]; - std::uint8_t data[SIZE]; - } u; - }; - - // Create two concrete types: 64 and 128-bit Session IDs. - typedef SessionIDType<8> SessionID64; - typedef SessionIDType<16> SessionID128; - - OPENVPN_OSTREAM(SessionID64, to_string); - OPENVPN_OSTREAM(SessionID128, to_string); -} - -OPENVPN_HASH_METHOD(openvpn::SessionID64, shortform); -OPENVPN_HASH_METHOD(openvpn::SessionID128, shortform); - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/sfinae.hpp b/Sources/OpenVPN3/openvpn/common/sfinae.hpp deleted file mode 100644 index 1bc2ef6..0000000 --- a/Sources/OpenVPN3/openvpn/common/sfinae.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// 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-2020 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 - -namespace openvpn { - namespace SFINAE { - - template <int I> struct Rank : Rank<I-1> {}; - template <> struct Rank<0> {}; - - } -} diff --git a/Sources/OpenVPN3/openvpn/common/signal.hpp b/Sources/OpenVPN3/openvpn/common/signal.hpp deleted file mode 100644 index 9d26a52..0000000 --- a/Sources/OpenVPN3/openvpn/common/signal.hpp +++ /dev/null @@ -1,180 +0,0 @@ -// 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-2020 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_COMMON_SIGNAL_H -#define OPENVPN_COMMON_SIGNAL_H - -#include <openvpn/common/platform.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) - -#include <signal.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -namespace openvpn { - class Signal - { - public: - OPENVPN_SIMPLE_EXCEPTION(signal_error); - - typedef void (*handler_t)(int signum); - - enum { - F_SIGINT = (1<<0), - F_SIGTERM = (1<<1), - F_SIGHUP = (1<<2), - F_SIGUSR1 = (1<<3), - F_SIGUSR2 = (1<<4), - F_SIGPIPE = (1<<5), - }; - - Signal(const handler_t handler, const unsigned int flags) - { - struct sigaction sa; - sa.sa_handler = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; // restart functions if interrupted by handler - sigconf(sa, flags_ = flags); - } - - ~Signal() - { - reset_to_defaults(flags_); - } - - static void reset_all_to_defaults() - { - reset_to_defaults(F_SIGINT|F_SIGTERM|F_SIGHUP|F_SIGUSR1|F_SIGUSR2|F_SIGPIPE); - } - - static void reset_to_defaults(const unsigned int flags) - { - struct sigaction sa; - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigconf(sa, flags); - } - - private: - static void sigconf(struct sigaction& sa, const unsigned int flags) - { - if (flags & F_SIGINT) - sigact(sa, SIGINT); - if (flags & F_SIGTERM) - sigact(sa, SIGTERM); - if (flags & F_SIGHUP) - sigact(sa, SIGHUP); - if (flags & F_SIGUSR1) - sigact(sa, SIGUSR1); - if (flags & F_SIGUSR2) - sigact(sa, SIGUSR2); - if (flags & F_SIGPIPE) - sigact(sa, SIGPIPE); - } - - static void sigact(struct sigaction& sa, const int sig) - { - if (sigaction(sig, &sa, nullptr) == -1) - throw signal_error(); - } - - unsigned int flags_; - }; - - // Like Asio posix_signal_blocker, but only block certain signals - class SignalBlocker - { - SignalBlocker(const SignalBlocker&) = delete; - SignalBlocker& operator=(const SignalBlocker&) = delete; - - public: - SignalBlocker(const unsigned int flags) // use signal mask from class Signal - : blocked_(false) - { - sigset_t new_mask; - sigemptyset(&new_mask); - if (flags & Signal::F_SIGINT) - sigaddset(&new_mask, SIGINT); - if (flags & Signal::F_SIGTERM) - sigaddset(&new_mask, SIGTERM); - if (flags & Signal::F_SIGHUP) - sigaddset(&new_mask, SIGHUP); - if (flags & Signal::F_SIGUSR1) - sigaddset(&new_mask, SIGUSR1); - if (flags & Signal::F_SIGUSR2) - sigaddset(&new_mask, SIGUSR2); - if (flags & Signal::F_SIGPIPE) - sigaddset(&new_mask, SIGPIPE); - blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); - } - - const sigset_t* orig_sigset() const - { - if (blocked_) - return &old_mask_; - else - return nullptr; - } - - // Destructor restores the previous signal mask. - ~SignalBlocker() - { - if (blocked_) - pthread_sigmask(SIG_SETMASK, &old_mask_, 0); - } - - private: - // Have signals been blocked. - bool blocked_; - - // The previous signal mask. - sigset_t old_mask_; - }; - - // Like SignalBlocker, but block specific signals in default constructor - struct SignalBlockerDefault : public SignalBlocker - { - SignalBlockerDefault() - : SignalBlocker( // these signals should be handled by parent thread - Signal::F_SIGINT| - Signal::F_SIGTERM| - Signal::F_SIGHUP| - Signal::F_SIGUSR1| - Signal::F_SIGUSR2| - Signal::F_SIGPIPE) - { - } - }; - - struct SignalBlockerPipe : public SignalBlocker - { - SignalBlockerPipe() - : SignalBlocker(Signal::F_SIGPIPE) - { - } - }; - -} -#endif -#endif diff --git a/Sources/OpenVPN3/openvpn/common/signal_name.hpp b/Sources/OpenVPN3/openvpn/common/signal_name.hpp deleted file mode 100644 index 887e179..0000000 --- a/Sources/OpenVPN3/openvpn/common/signal_name.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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 <signal.h> - -namespace openvpn { - - inline std::string signal_name(const int signum) - { - switch (signum) - { - case SIGINT: - return "SIGINT"; - case SIGTERM: - return "SIGTERM"; - case SIGHUP: - return "SIGHUP"; - case SIGUSR1: - return "SIGUSR1"; - case SIGUSR2: - return "SIGUSR2"; - case SIGPIPE: - return "SIGPIPE"; - default: - return std::to_string(signum); - } - } - -} diff --git a/Sources/OpenVPN3/openvpn/common/size.hpp b/Sources/OpenVPN3/openvpn/common/size.hpp deleted file mode 100644 index 7fce591..0000000 --- a/Sources/OpenVPN3/openvpn/common/size.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// 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-2020 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/>. - -// define very basic types such as size_t, ssize_t - -#ifndef OPENVPN_COMMON_SIZE_H -#define OPENVPN_COMMON_SIZE_H - -#include <cstddef> // defines std::size_t - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) -#include <BaseTsd.h> -typedef SSIZE_T ssize_t; -#define _SSIZE_T_ -#define _SSIZE_T_DEFINED -#endif -#else -#include <unistd.h> // get ssize_t -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/sleep.hpp b/Sources/OpenVPN3/openvpn/common/sleep.hpp deleted file mode 100644 index 1213529..0000000 --- a/Sources/OpenVPN3/openvpn/common/sleep.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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/>. - -// Portable millisecond sleep - -#ifndef OPENVPN_COMMON_SLEEP_H -#define OPENVPN_COMMON_SLEEP_H - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#include <windows.h> -#else -#include <time.h> -#endif - -namespace openvpn { - inline bool sleep_milliseconds(const unsigned int milliseconds) - { -#ifdef OPENVPN_PLATFORM_WIN - ::Sleep(milliseconds); - return true; -#else - struct timespec ts; - ts.tv_sec = milliseconds / 1000U; - ts.tv_nsec = (milliseconds % 1000U) * 1000000U; - return ::nanosleep(&ts, nullptr) == 0; -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/sockopt.hpp b/Sources/OpenVPN3/openvpn/common/sockopt.hpp deleted file mode 100644 index 2b5612c..0000000 --- a/Sources/OpenVPN3/openvpn/common/sockopt.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// 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-2020 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_COMMON_SOCKOPT_H -#define OPENVPN_COMMON_SOCKOPT_H - -#include <openvpn/common/platform.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) - -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> - -#include <openvpn/common/exception.hpp> - -namespace openvpn { - namespace SockOpt { - -#ifdef SO_REUSEPORT - // set SO_REUSEPORT for inter-thread load balancing - inline void reuseport(const int fd) - { - int on = 1; - if (::setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, - (void *)&on, sizeof(on)) < 0) - throw Exception("error setting SO_REUSEPORT on socket"); - } -#endif - - // set SO_REUSEADDR for TCP - inline void reuseaddr(const int fd) - { - int on = 1; - if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (void *)&on, sizeof(on)) < 0) - throw Exception("error setting SO_REUSEADDR on socket"); - } - - // set TCP_NODELAY for TCP - inline void tcp_nodelay(const int fd) - { - int state = 1; - if (::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, - (void *)&state, sizeof(state)) != 0) - throw Exception("error setting TCP_NODELAY on socket"); - } - - // set FD_CLOEXEC to prevent fd from being passed across execs - inline void set_cloexec(const int fd) - { - if (::fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) - throw Exception("error setting FD_CLOEXEC on file-descriptor/socket"); - } - - // set non-block mode on socket - static inline void set_nonblock(const int fd) - { - if (::fcntl(fd, F_SETFL, O_NONBLOCK) < 0) - throw Exception("error setting socket to non-blocking mode"); - } - } -} - -#endif -#endif diff --git a/Sources/OpenVPN3/openvpn/common/socktypes.hpp b/Sources/OpenVPN3/openvpn/common/socktypes.hpp deleted file mode 100644 index 5e72547..0000000 --- a/Sources/OpenVPN3/openvpn/common/socktypes.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// 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-2020 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/>. - -// define stuff like ntohl, ntohs, htonl, htons, etc. in a platform-independent way - -#ifndef OPENVPN_COMMON_SOCKTYPES_H -#define OPENVPN_COMMON_SOCKTYPES_H - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#include <winsock2.h> -#else -#include <arpa/inet.h> -#endif - -#endif // OPENVPN_COMMON_SOCKTYPES_H diff --git a/Sources/OpenVPN3/openvpn/common/split.hpp b/Sources/OpenVPN3/openvpn/common/split.hpp deleted file mode 100644 index d7bf3ee..0000000 --- a/Sources/OpenVPN3/openvpn/common/split.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// 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-2020 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/>. - -// General string-splitting methods. These methods along with lexical analyzer -// classes (such as those defined in lex.hpp and OptionList::LexComment) can be -// used as a basis for parsers. - -#ifndef OPENVPN_COMMON_SPLIT_H -#define OPENVPN_COMMON_SPLIT_H - -#include <string> -#include <vector> -#include <utility> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/lex.hpp> - -namespace openvpn { - namespace Split { - enum { - TRIM_LEADING_SPACES=(1<<0), - TRIM_SPECIAL=(1<<1), // trims quotes (but respects their content) - }; - - struct NullLimit - { - void add_term() {} - }; - - // Split a string using a character (such as ',') as a separator. - // Types: - // V : string vector of return data - // LEX : lexical analyzer class such as StandardLex - // LIM : limit class such as OptionList::Limits - // Args: - // ret : return data -- a list of strings - // input : input string to be split - // split_by : separator - // flags : TRIM_LEADING_SPACES, TRIM_SPECIAL - // max_terms : the size of the returned string list will be, at most, this value + 1. Pass - // ~0 to disable. - // lim : an optional limits object such as OptionList::Limits - template <typename V, typename LEX, typename LIM> - inline void by_char_void(V& ret, const std::string& input, const char split_by, const unsigned int flags=0, const unsigned int max_terms=~0, LIM* lim=nullptr) - { - LEX lex; - unsigned int nterms = 0; - std::string term; - for (std::string::const_iterator i = input.begin(); i != input.end(); ++i) - { - const char c = *i; - lex.put(c); - if (!lex.in_quote() && c == split_by && nterms < max_terms) - { - if (lim) - lim->add_term(); - ret.push_back(std::move(term)); - ++nterms; - term = ""; - } - else if ((!(flags & TRIM_SPECIAL) || lex.available()) - && (!(flags & TRIM_LEADING_SPACES) || !term.empty() || !SpaceMatch::is_space(c))) - term += c; - } - if (lim) - lim->add_term(); - ret.push_back(std::move(term)); - } - - // convenience method that returns data rather than modifying an in-place argument - template <typename V, typename LEX, typename LIM> - inline V by_char(const std::string& input, const char split_by, const unsigned int flags=0, const unsigned int max_terms=~0, LIM* lim=nullptr) - { - V ret; - by_char_void<V, LEX, LIM>(ret, input, split_by, flags, max_terms, lim); - return ret; - } - - // Split a string using spaces as a separator. - // Types: - // V : string vector of return data - // LEX : lexical analyzer class such as StandardLex - // SPACE : class that we use to differentiate between space and non-space chars - // LIM : limit class such as OptionList::Limits - // Args: - // ret : return data -- a list of strings - // input : input string to be split - // lim : an optional limits object such as OptionList::Limits - template <typename V, typename LEX, typename SPACE, typename LIM> - inline void by_space_void(V& ret, const std::string& input, LIM* lim=nullptr) - { - LEX lex; - - std::string term; - bool defined = false; - for (std::string::const_iterator i = input.begin(); i != input.end(); ++i) - { - const char c = *i; - lex.put(c); - if (lex.in_quote()) - defined = true; - if (lex.available()) - { - const char tc = lex.get(); - if (!SPACE::is_space(tc) || lex.in_quote()) - { - defined = true; - term += tc; - } - else if (defined) - { - if (lim) - lim->add_term(); - ret.push_back(std::move(term)); - term = ""; - defined = false; - } - } - } - if (defined) - { - if (lim) - lim->add_term(); - ret.push_back(std::move(term)); - } - } - - // convenience method that returns data rather than modifying an in-place argument - template <typename V, typename LEX, typename SPACE, typename LIM> - inline V by_space(const std::string& input, LIM* lim=nullptr) - { - V ret; - by_space_void<V, LEX, SPACE, LIM>(ret, input, lim); - return ret; - } - } -} // namespace openvpn - -#endif // OPENVPN_COMMON_SPLIT_H diff --git a/Sources/OpenVPN3/openvpn/common/splitlines.hpp b/Sources/OpenVPN3/openvpn/common/splitlines.hpp deleted file mode 100644 index 2738874..0000000 --- a/Sources/OpenVPN3/openvpn/common/splitlines.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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/>. - -// General purpose class to split a multi-line string into lines. - -#ifndef OPENVPN_COMMON_SPLITLINES_H -#define OPENVPN_COMMON_SPLITLINES_H - -#include <utility> - -#include <openvpn/common/string.hpp> - -namespace openvpn { - template <typename STRING> - class SplitLinesType - { - public: - // Note: string/buffer passed to constructor is not locally stored, - // so it must remain in scope and not be modified during the lifetime - // of the SplitLines object. - SplitLinesType(const STRING& str, const size_t max_line_len_arg=0) - : data((const char *)str.c_str()), - size(str.length()), - max_line_len(max_line_len_arg) - { - } - - bool operator()(const bool trim=true) - { - line.clear(); - overflow = false; - const size_t overflow_index = index + max_line_len; - while (index < size) - { - if (max_line_len && index >= overflow_index) - { - overflow = true; - return true; - } - const char c = data[index++]; - line += c; - if (c == '\n' || index >= size) - { - if (trim) - string::trim_crlf(line); - return true; - } - } - return false; - } - - bool line_overflow() const - { - return overflow; - } - - std::string& line_ref() - { - return line; - } - - const std::string& line_ref() const - { - return line; - } - - std::string line_move() - { - return std::move(line); - } - - enum Status { - S_OKAY, - S_EOF, - S_ERROR - }; - - Status next(std::string& ln, const bool trim=true) - { - const bool s = (*this)(trim); - if (!s) - return S_EOF; - if (overflow) - return S_ERROR; - ln = std::move(line); - return S_OKAY; - } - - private: - const char *data; - size_t size; - size_t max_line_len; - size_t index = 0; - std::string line; - bool overflow = false; - }; - - typedef SplitLinesType<std::string> SplitLines; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/stat.hpp b/Sources/OpenVPN3/openvpn/common/stat.hpp deleted file mode 100644 index 8d8a9b2..0000000 --- a/Sources/OpenVPN3/openvpn/common/stat.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// 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-2020 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_COMMON_STAT_H -#define OPENVPN_COMMON_STAT_H - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <cstdint> // for std::uint64_t - -namespace openvpn { - - // Return true if file exists - inline bool file_exists(const std::string& filename) - { - if (filename.empty()) - return false; - struct stat buffer; - return stat(filename.c_str(), &buffer) == 0; - } - - // Return true if dirname is a directory - inline bool is_directory(const std::string& pathname, const bool follow_symlinks=false) - { - if (pathname.empty()) - return false; - struct stat sb; - if (follow_symlinks) - return ::stat(pathname.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode); - else - return ::lstat(pathname.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode); - } - - // Return file modification time (in seconds since unix epoch) or 0 on error - inline time_t file_mod_time(const std::string& filename) - { - struct stat buffer; - if (stat(filename.c_str(), &buffer) != 0) - return 0; - else - return buffer.st_mtime; - } - - // Return file modification time from a struct stat - inline std::uint64_t stat_mod_time_nanoseconds(const struct stat& s) - { - typedef std::uint64_t T; -#if defined(__APPLE__) - return T(s.st_mtimespec.tv_sec) * T(1000000000) + T(s.st_mtimespec.tv_nsec); -#else - return T(s.st_mtim.tv_sec) * T(1000000000) + T(s.st_mtim.tv_nsec); -#endif - } - - // Return file modification time from a file path (in nanoseconds since unix epoch) or 0 on error - inline std::uint64_t file_mod_time_nanoseconds(const std::string& filename) - { - struct stat s; - if (::stat(filename.c_str(), &s) == 0) - return stat_mod_time_nanoseconds(s); - else - return 0; - } - - // Return file modification time from a file descriptor (in nanoseconds since unix epoch) or 0 on error - inline std::uint64_t fd_mod_time_nanoseconds(const int fd) - { - struct stat s; - if (::fstat(fd, &s) == 0) - return stat_mod_time_nanoseconds(s); - else - return 0; - } - - // Return file modification time (in milliseconds since unix epoch) or 0 on error - inline std::uint64_t file_mod_time_milliseconds(const std::string& filename) - { - return file_mod_time_nanoseconds(filename) / std::uint64_t(1000000); - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/stop.hpp b/Sources/OpenVPN3/openvpn/common/stop.hpp deleted file mode 100644 index 467d2ed..0000000 --- a/Sources/OpenVPN3/openvpn/common/stop.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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_COMMON_STOP_H -#define OPENVPN_COMMON_STOP_H - -#include <vector> -#include <functional> -#include <utility> -#include <mutex> - -namespace openvpn { - class Stop - { - public: - class Scope - { - friend Stop; - - public: - Scope(Stop* stop_arg, std::function<void()>&& method_arg) - : stop(stop_arg), - method(std::move(method_arg)), - index(-1) - { - if (stop) - { - std::lock_guard<std::recursive_mutex> lock(stop->mutex); - if (stop->stop_called) - { - // stop already called, call method immediately - method(); - } - else - { - index = stop->scopes.size(); - stop->scopes.push_back(this); - } - } - } - - ~Scope() - { - if (stop) - { - std::lock_guard<std::recursive_mutex> lock(stop->mutex); - if (index >= 0 && index < static_cast<int>(stop->scopes.size()) && stop->scopes[index] == this) - { - stop->scopes[index] = nullptr; - stop->prune(); - } - } - } - - private: - Scope(const Scope&) = delete; - Scope& operator=(const Scope&) = delete; - - Stop *const stop; - const std::function<void()> method; - int index; - }; - - Stop() - { - } - - void stop() - { - std::lock_guard<std::recursive_mutex> lock(mutex); - stop_called = true; - while (scopes.size()) - { - Scope* scope = scopes.back(); - scopes.pop_back(); - if (scope) - { - scope->index = -1; - scope->method(); - } - } - } - - private: - Stop(const Stop&) = delete; - Stop& operator=(const Stop&) = delete; - - void prune() - { - while (scopes.size() && !scopes.back()) - scopes.pop_back(); - } - - std::recursive_mutex mutex; - std::vector<Scope*> scopes; - bool stop_called = false; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/strerror.hpp b/Sources/OpenVPN3/openvpn/common/strerror.hpp deleted file mode 100644 index 2eb5b63..0000000 --- a/Sources/OpenVPN3/openvpn/common/strerror.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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_COMMON_STRERROR_H -#define OPENVPN_COMMON_STRERROR_H - -#include <string.h> -#include <string> - -#include <errno.h> - -namespace openvpn { - inline std::string strerror_str(const int errnum) - { - static const char unknown_err[] = "UNKNOWN_SYSTEM_ERROR"; - char buf[128]; - -#if defined(__GLIBC__) && (!defined(__USE_XOPEN2K) || defined(__USE_GNU)) - // GNU - const char *errstr = ::strerror_r(errnum, buf, sizeof(buf)); - if (errstr) - return std::string(errstr); -#else - // POSIX - if (::strerror_r(errnum, buf, sizeof(buf)) == 0) - return std::string(buf); -#endif - return std::string(unknown_err); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/string.hpp b/Sources/OpenVPN3/openvpn/common/string.hpp deleted file mode 100644 index 01885f7..0000000 --- a/Sources/OpenVPN3/openvpn/common/string.hpp +++ /dev/null @@ -1,676 +0,0 @@ -// 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-2020 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/>. - -// General purpose string-manipulation functions. - -#ifndef OPENVPN_COMMON_STRING_H -#define OPENVPN_COMMON_STRING_H - -#include <string> -#include <vector> -#include <cstring> -#include <cctype> -#include <algorithm> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/size.hpp> - -namespace openvpn { - namespace string { - // case insensitive compare functions - - inline int strcasecmp(const char *s1, const char *s2) - { -#ifdef OPENVPN_PLATFORM_WIN - return ::_stricmp(s1, s2); -#else - return ::strcasecmp(s1, s2); -#endif - } - - inline int strcasecmp(const std::string& s1, const char *s2) - { - return strcasecmp(s1.c_str(), s2); - } - - inline int strcasecmp(const char *s1, const std::string& s2) - { - return strcasecmp(s1, s2.c_str()); - } - - inline int strcasecmp(const std::string& s1, const std::string& s2) - { - return strcasecmp(s1.c_str(), s2.c_str()); - } - - // Like strncpy but makes sure dest is always null terminated - inline void strncpynt (char *dest, const char *src, size_t maxlen) - { - strncpy (dest, src, maxlen); - if (maxlen > 0) - dest[maxlen - 1] = 0; - } - - // Copy string to dest, make sure dest is always null terminated, - // and fill out trailing chars in dest with '\0' up to dest_size. - inline void copy_fill (void *dest, const std::string& src, const size_t dest_size) - { - if (dest_size > 0) - { - const size_t ncopy = std::min(dest_size - 1, src.length()); - std::memcpy(dest, src.c_str(), ncopy); - std::memset(static_cast<unsigned char *>(dest) + ncopy, 0, dest_size - ncopy); - } - } - - inline bool is_true(const std::string& str) - { - return str == "1" || !strcasecmp(str.c_str(), "true"); - } - - template <typename STRING> - inline bool starts_with(const STRING& str, const std::string& prefix) - { - const size_t len = str.length(); - const size_t plen = prefix.length(); - if (plen <= len) - return std::memcmp(str.c_str(), prefix.c_str(), plen) == 0; - else - return false; - } - - template <typename STRING> - inline bool starts_with(const STRING& str, const char *prefix) - { - const size_t len = str.length(); - const size_t plen = std::strlen(prefix); - if (plen <= len) - return std::memcmp(str.c_str(), prefix, plen) == 0; - else - return false; - } - - // Return true if str == prefix or if str starts with prefix + delim - template <typename STRING> - inline bool starts_with_delim(const STRING& str, const std::string& prefix, const char delim) - { - if (prefix.length() < str.length()) - return str[prefix.length()] == delim && string::starts_with(str, prefix); - else - return prefix == str; - } - - template <typename STRING> - inline bool ends_with(const STRING& str, const std::string& suffix) - { - const size_t len = str.length(); - const size_t slen = suffix.length(); - if (slen <= len) - return std::memcmp(str.c_str() + (len-slen), suffix.c_str(), slen) == 0; - else - return false; - } - - template <typename STRING> - inline bool ends_with(const STRING& str, const char *suffix) - { - const size_t len = str.length(); - const size_t slen = std::strlen(suffix); - if (slen <= len) - return std::memcmp(str.c_str() + (len-slen), suffix, slen) == 0; - else - return false; - } - - // return true if string ends with char c - template <typename STRING> - inline bool ends_with(const STRING& str, const char c) - { - return str.length() && str.back() == c; - } - - // return true if string ends with a newline - template <typename STRING> - inline bool ends_with_newline(const STRING& str) - { - return ends_with(str, '\n'); - } - - // return true if string ends with a CR or LF - template <typename STRING> - inline bool ends_with_crlf(const STRING& str) - { - if (str.length()) - { - const char c = str.back(); - return c == '\n' || c == '\r'; - } - else - return false; - } - - // Prepend leading characters (c) to str to obtain a minimum string length (min_len). - // Useful for adding leading zeros to numeric values or formatting tables. - inline std::string add_leading(const std::string& str, const size_t min_len, const char c) - { - if (min_len <= str.length()) - return str; - size_t len = min_len - str.length(); - std::string ret; - ret.reserve(min_len); - while (len--) - ret += c; - ret += str; - return ret; - } - - // make sure that string ends with char c, if not append it - inline std::string add_trailing_copy(const std::string& str, const char c) - { - if (ends_with(str, c)) - return str; - else - return str + c; - } - - // make sure that string ends with char c, if not append it - inline void add_trailing(std::string& str, const char c) - { - if (!ends_with(str, c)) - str += c; - } - - // make sure that string ends with CRLF, if not append it - inline void add_trailing_crlf(std::string& str) - { - if (ends_with(str, "\r\n")) - ; - else if (ends_with(str, '\r')) - str += '\n'; - else if (ends_with(str, '\n')) - { - str.pop_back(); - str += "\r\n"; - } - else - str += "\r\n"; - } - - // make sure that string ends with CRLF, if not append it - inline std::string add_trailing_crlf_copy(std::string str) - { - add_trailing_crlf(str); - return str; - } - - // make sure that string ends with char c, if not append it (unless the string is empty) - inline std::string add_trailing_unless_empty_copy(const std::string& str, const char c) - { - if (str.empty() || ends_with(str, c)) - return str; - else - return str + c; - } - - // remove trailing \r or \n chars - template <typename STRING> - inline void trim_crlf(STRING& str) - { - while (ends_with_crlf(str)) - str.pop_back(); - } - - // remove trailing \r or \n chars - inline std::string trim_crlf_copy(std::string str) - { - trim_crlf(str); - return str; - } - - // return true if str of size len contains an embedded null - inline bool embedded_null(const char *str, size_t len) - { - while (len--) - if (!*str++) - return true; - return false; - } - - // return the length of a string, omitting trailing nulls - inline size_t len_without_trailing_nulls(const char *str, size_t len) - { - while (len > 0 && str[len-1] == '\0') - --len; - return len; - } - - // return true if string contains at least one newline - inline bool is_multiline(const std::string& str) - { - return str.find_first_of('\n') != std::string::npos; - } - - // Return string up to a delimiter (without the delimiter). - // Returns the entire string if no delimiter is found. - inline std::string to_delim(const std::string& str, const char delim) - { - const size_t pos = str.find_first_of(delim); - if (pos != std::string::npos) - return str.substr(0, pos); - else - return str; - } - - // return the first line (without newline) of a multi-line string - inline std::string first_line(const std::string& str) - { - return to_delim(str, '\n'); - } - - // Define a common interpretation of what constitutes a space character. - // Return true if c is a space char. - inline bool is_space(const char c) - { - return std::isspace(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_digit(const char c) - { - return std::isdigit(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_alpha(const char c) - { - return std::isalpha(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_alphanumeric(const char c) - { - return std::isalnum(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_printable(const char c) - { - return std::isprint(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_printable(const unsigned char c) - { - return std::isprint(c) != 0; - } - - inline bool is_ctrl(const char c) - { - return std::iscntrl(static_cast<unsigned char>(c)) != 0; - } - - inline bool is_ctrl(const unsigned char c) - { - return std::iscntrl(c) != 0; - } - - // return true if string conforms to regex \w* - inline bool is_word(const std::string& str) - { - for (auto &c : str) - if (!(is_alphanumeric(c) || c == '_')) - return false; - return true; - } - - // return true if all string characters are printable (or if string is empty) - inline bool is_printable(const std::string& str) - { - for (auto &c : str) - if (!is_printable(c)) - return false; - return true; - } - - // return true if str contains at least one non-space control char - inline bool contains_non_space_ctrl(const std::string& str) - { - for (auto &c : str) - if ((!is_space(c) && is_ctrl(c)) || c == 127) - return true; - return false; - } - - // return true if str contains at least one space char - inline bool contains_space(const std::string& str) - { - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) - if (is_space(*i)) - return true; - return false; - } - - // remove all spaces in string - inline std::string remove_spaces(const std::string& str) - { - std::string ret; - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) - { - char c = *i; - if (!is_space(c)) - ret += c; - } - return ret; - } - - // replace all spaces in string with rep - inline std::string replace_spaces(const std::string& str, const char rep) - { - std::string ret; - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) - { - char c = *i; - if (is_space(c)) - c = rep; - ret += c; - } - return ret; - } - - // replace all spaces in string with rep, reducing instances of multiple - // consecutive spaces to a single instance of rep and removing leading - // and trailing spaces - inline std::string reduce_spaces(const std::string& str, const char rep) - { - std::string ret; - bool last_space = true; - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) - { - char c = *i; - const bool space = is_space(c); - if (is_space(c)) - c = rep; - if (!(space && last_space)) - ret += c; - last_space = space; - } - if (last_space && !ret.empty()) - ret.pop_back(); - return ret; - } - - // generate a string with n instances of char c - inline std::string repeat(const char c, int n) - { - std::string ret; - ret.reserve(n); - while (n-- > 0) - ret += c; - return ret; - } - - // generate a string with spaces - inline std::string spaces(int n) - { - return repeat(' ', n); - } - - // indent a multiline string - inline std::string indent(const std::string& str, const int first, const int remaining) - { - std::string ret; - int n_spaces = first; - for (auto &c : str) - { - if (n_spaces) - ret += spaces(n_spaces); - n_spaces = 0; - ret += c; - if (c == '\n') - n_spaces = remaining; - } - return ret; - } - - // replace instances of char 'from' in string with char 'to' - inline std::string replace_copy(const std::string& str, const char from, const char to) - { - std::string ret; - ret.reserve(str.length()); - for (auto &c : str) - ret.push_back(c == from ? to : c); - return ret; - } - - // return true if str is empty or contains only space chars - inline bool is_empty(const std::string& str) - { - for (const auto& c : str) - if (!is_space(c)) - return false; - return true; - } - - // return true if str is empty or contains only space chars - inline bool is_empty(const char *str) - { - if (!str) - return true; - char c; - while ((c = *str++) != '\0') - if (!is_space(c)) - return false; - return true; - } - - // convert \n to \r\n - inline std::string unix2dos(const std::string& str, const bool force_eol=false) - { - std::string ret; - bool last_char_was_cr = false; - - ret.reserve(str.length() + str.length() / 8); - for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) - { - const char c = *i; - if (c == '\n' && !last_char_was_cr) - ret += '\r'; - ret += c; - last_char_was_cr = (c == '\r'); - } - if (force_eol) - add_trailing_crlf(ret); - return ret; - } - - // Split a string on sep delimiter. The size of the - // returned string vector will be at least 1 and at - // most maxsplit + 1 (unless maxsplit is passed as -1). - inline std::vector<std::string> split(const std::string& str, - const char sep, - const int maxsplit = -1) - { - std::vector<std::string> ret; - int nterms = 0; - std::string term; - - if (maxsplit >= 0) - ret.reserve(maxsplit + 1); - - for (const auto c : str) - { - if (c == sep && (maxsplit < 0 || nterms < maxsplit)) - { - ret.push_back(std::move(term)); - ++nterms; - term.clear(); - } - else - term += c; - } - ret.push_back(std::move(term)); - return ret; - } - - inline std::string join(const std::vector<std::string>& strings, - const std::string& delim, - const bool tail=false) - { - std::string ret; - bool first = true; - for (const auto &s : strings) - { - if (!first) - ret += delim; - ret += s; - first = false; - } - if (tail && !ret.empty()) - ret += delim; - return ret; - } - - inline std::vector<std::string> from_argv(int argc, char *argv[], const bool skip_first) - { - std::vector<std::string> ret; - for (int i = (skip_first ? 1 : 0); i < argc; ++i) - ret.emplace_back(argv[i]); - return ret; - } - - inline std::string trim_left_copy(const std::string& str) - { - for (size_t i = 0; i < str.length(); ++i) - { - if (!is_space(str[i])) - return str.substr(i); - } - return std::string(); - } - - inline std::string trim_copy(const std::string& str) - { - for (size_t i = 0; i < str.length(); ++i) - { - if (!is_space(str[i])) - { - size_t last_nonspace = i; - for (size_t j = i + 1; j < str.length(); ++j) - { - if (!is_space(str[j])) - last_nonspace = j; - } - return str.substr(i, last_nonspace - i + 1); - } - } - return std::string(); - } - - inline std::string to_upper_copy(const std::string& str) - { - std::string ret; - ret.reserve(str.length()+1); - for (const auto &c : str) - ret.push_back(std::toupper(static_cast<unsigned char>(c))); - return ret; - } - - inline std::string to_lower_copy(const std::string& str) - { - std::string ret; - ret.reserve(str.length()+1); - for (const auto &c : str) - ret.push_back(std::tolower(static_cast<unsigned char>(c))); - return ret; - } - - inline void trim(std::string& str) - { - str = trim_copy(str); - } - - inline void trim_left(std::string& str) - { - str = trim_left_copy(str); - } - - inline void to_lower(std::string& str) - { - str = to_lower_copy(str); - } - - inline void to_upper(std::string& str) - { - str = to_upper_copy(str); - } - - // Replace any subsequence of consecutive space chars containing - // at least one newline with a single newline char. If string - // is non-empty and doesn't include a trailing newline, add one. - inline std::string remove_blanks(const std::string& str) - { - std::string ret; - ret.reserve(str.length()+1); - - std::string spaces; - bool in_space = false; - bool has_nl = false; - - for (auto &c : str) - { - const bool s = is_space(c); - reprocess: - if (in_space) - { - if (s) - { - if (c == '\n') - has_nl = true; - spaces += c; - } - else - { - if (has_nl) - ret += '\n'; - else - ret += spaces; - in_space = false; - has_nl = false; - spaces.clear(); - goto reprocess; - } - } - else - { - if (s) - { - in_space = true; - goto reprocess; - } - else - ret += c; - } - } - if (!ret.empty() && !ends_with_newline(ret)) - ret += '\n'; - return ret; - } - - } // namespace string - -} // namespace openvpn - -#endif // OPENVPN_COMMON_STRING_H diff --git a/Sources/OpenVPN3/openvpn/common/stringize.hpp b/Sources/OpenVPN3/openvpn/common/stringize.hpp deleted file mode 100644 index 7c54962..0000000 --- a/Sources/OpenVPN3/openvpn/common/stringize.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// 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-2020 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_COMMON_STRINGIZE_H -#define OPENVPN_COMMON_STRINGIZE_H - -// OPENVPN_STRINGIZE(x) -- put double-quotes around x - -#define OPENVPN_STRINGIZE(x) OPENVPN_STRINGIZE2(x) -#define OPENVPN_STRINGIZE2(x) #x - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/stringtempl.hpp b/Sources/OpenVPN3/openvpn/common/stringtempl.hpp deleted file mode 100644 index d0d7050..0000000 --- a/Sources/OpenVPN3/openvpn/common/stringtempl.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// 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-2020 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/>. - - -// Sometimes you want to accept a <typename STRING> in a -// method, without knowing whether it's a const char *, -// const std::string&, or nullptr. These methods help with -// basic type-independent string operations. - -#ifndef OPENVPN_COMMON_STRINGTEMPL_H -#define OPENVPN_COMMON_STRINGTEMPL_H - -#include <string> -#include <cstddef> // for std::nullptr_t -#include <utility> - -namespace openvpn { - namespace StringTempl { - - // empty - - inline bool empty(std::nullptr_t) - { - return true; - } - - inline bool empty(const char *str) - { - return !str || str[0] == '\0'; - } - - inline bool empty(const std::string& str) - { - return str.empty(); - } - - // to_string - - inline std::string to_string(std::nullptr_t) - { - return std::string(); - } - - inline std::string to_string(const char *str) - { - if (str) - return std::string(str); - else - return to_string(nullptr); - } - - inline std::string to_string(std::string&& str) - { - return std::move(str); - } - - inline const std::string& to_string(const std::string& str) - { - return str; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/stringtempl2.hpp b/Sources/OpenVPN3/openvpn/common/stringtempl2.hpp deleted file mode 100644 index a0c52cf..0000000 --- a/Sources/OpenVPN3/openvpn/common/stringtempl2.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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-2020 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 <type_traits> - -#include <openvpn/common/stringtempl.hpp> - -namespace openvpn { - namespace StringTempl { - - // empty - - // for objects that define an empty method - template <typename T> - inline auto empty(const T& t) -> decltype(t.empty()) - { - return t.empty(); - } - - // for numerical values - template <typename T, - typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> - inline bool empty(T value) - { - return false; - } - - // to_string - - // for objects that define a to_string() method - template <typename T> - inline auto to_string(const T& t) -> decltype(t.to_string()) - { - return t.to_string(); - } - - // for numerical values - template <typename T, - typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> - inline std::string to_string(T value) - { - return std::to_string(value); - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/common/strneq.hpp b/Sources/OpenVPN3/openvpn/common/strneq.hpp deleted file mode 100644 index 5ecc7b0..0000000 --- a/Sources/OpenVPN3/openvpn/common/strneq.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// 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-2020 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/>. - -#include <string> -#include <atomic> - -namespace openvpn { - namespace crypto { - - // Compare strings in a way that is more resistant to timing attacks. - // s1 should be the string provided by the user, while s2 is the - // "secret" string that we are comparing s1 against. - // Our goal is to prevent timing data from leaking info about the - // length or content of s2. - // https://nachtimwald.com/2017/04/02/constant-time-string-comparison-in-c/ - inline bool str_neq(const char *s1, const char *s2) - { - unsigned int neq = 0; - size_t i = 0; - size_t j = 0; - size_t k = 0; - - while (true) - { - neq |= s1[i] ^ s2[j]; - - if (s1[i] == '\0') - break; - i++; - - atomic_thread_fence(std::memory_order_acq_rel); - if (s2[j] != '\0') - j++; - atomic_thread_fence(std::memory_order_acq_rel); - if (s2[j] == '\0') - k++; - } - atomic_thread_fence(std::memory_order_acq_rel); - return bool(neq); - } - - inline bool str_neq(const std::string& s1, const std::string& s2) - { - return str_neq(s1.c_str(), s2.c_str()); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/common/tempfile.hpp b/Sources/OpenVPN3/openvpn/common/tempfile.hpp deleted file mode 100644 index 20ca232..0000000 --- a/Sources/OpenVPN3/openvpn/common/tempfile.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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-2020 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_COMMON_TEMPFILE_H -#define OPENVPN_COMMON_TEMPFILE_H - -#include <openvpn/common/platform.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) -#error temporary file methods not supported on Windows -#endif - -#include <stdlib.h> -#include <errno.h> -#include <cstring> // for memcpy -#include <unistd.h> // for write, unlink, lseek -#include <sys/types.h> // for lseek - -#include <string> -#include <memory> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/write.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/buffer/bufread.hpp> - -namespace openvpn { - class TempFile - { - public: - OPENVPN_EXCEPTION(tempfile_exception); - - TempFile(const std::string& fn_template, - const bool fn_delete) - : fn(new char[fn_template.length()+1]), - del(fn_delete) - { - std::memcpy(fn.get(), fn_template.c_str(), fn_template.length()+1); - const size_t pos = fn_template.find("XXXXXX"); - if (pos != std::string::npos) - { - const int suffixlen = fn_template.length() - pos - 6; - if (suffixlen > 0) - fd.reset(::mkstemps(fn.get(), suffixlen)); - else - fd.reset(::mkstemp(fn.get())); - if (!fd.defined()) - { - const int eno = errno; - OPENVPN_THROW(tempfile_exception, "error creating temporary file from template: " << fn_template << " : " << strerror_str(eno)); - } - } - else - OPENVPN_THROW(tempfile_exception, "badly formed temporary file template: " << fn_template); - } - - ~TempFile() - { - fd.close(); - delete_file(); - } - - void reset() - { - const off_t off = ::lseek(fd(), 0, SEEK_SET); - if (off < 0) - { - const int eno = errno; - OPENVPN_THROW(tempfile_exception, "seek error on temporary file: " << filename() << " : " << strerror_str(eno)); - } - if (off) - OPENVPN_THROW(tempfile_exception, "unexpected seek on temporary file: " << filename()); - } - - void truncate() - { - reset(); - if (::ftruncate(fd(), 0) < 0) - { - const int eno = errno; - OPENVPN_THROW(tempfile_exception, "ftruncate error on temporary file: " << filename() << " : " << strerror_str(eno)); - } - } - - void write(const std::string& content) - { - const ssize_t size = write_retry(fd(), content.c_str(), content.length()); - if (size < 0) - { - const int eno = errno; - OPENVPN_THROW(tempfile_exception, "error writing to temporary file: " << filename() << " : " << strerror_str(eno)); - } - else if (static_cast<std::string::size_type>(size) != content.length()) - { - OPENVPN_THROW(tempfile_exception, "incomplete write to temporary file: " << filename()); - } - } - - std::string read() - { - BufferList buflist = buf_read(fd(), filename()); - return buflist.to_string(); - } - - std::string filename() const - { - if (fn) - return fn.get(); - else - return ""; - } - - void close_file() - { - if (!fd.close()) - { - const int eno = errno; - OPENVPN_THROW(tempfile_exception, "error closing temporary file: " << filename() << " : " << strerror_str(eno)); - } - } - - void set_delete(const bool del_flag) - { - del = del_flag; - } - - void delete_file() - { - if (fn && del) - { - ::unlink(fn.get()); - del = false; - } - } - - ScopedFD fd; - - private: - std::unique_ptr<char[]> fn; - bool del; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/to_string.hpp b/Sources/OpenVPN3/openvpn/common/to_string.hpp deleted file mode 100644 index d1427d8..0000000 --- a/Sources/OpenVPN3/openvpn/common/to_string.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// 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-2020 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/>. - -// Define openvpn::to_string() to work around the fact that -// std::to_string() is missing on Android. -// http://stackoverflow.com/questions/22774009/android-ndk-stdto-string-support - -#ifndef OPENVPN_COMMON_TO_STRING_H -#define OPENVPN_COMMON_TO_STRING_H - -#include <string> -#include <sstream> -#include <type_traits> - -#include <openvpn/common/platform.hpp> - -namespace openvpn { - - // Convert an arbitrary argument to a string. - -#ifndef OPENVPN_PLATFORM_ANDROID - // numeric types - template <typename T, - typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0> - inline std::string to_string(T value) - { - return std::to_string(value); - } -#endif - - // non-numeric types - template <typename T -#ifndef OPENVPN_PLATFORM_ANDROID - , typename std::enable_if<!std::is_arithmetic<T>::value, int>::type = 0 -#endif - > - inline std::string to_string(const T& value) - { - std::ostringstream os; - os << value; - return os.str(); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/umask.hpp b/Sources/OpenVPN3/openvpn/common/umask.hpp deleted file mode 100644 index 6e98b12..0000000 --- a/Sources/OpenVPN3/openvpn/common/umask.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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-2020 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_COMMON_UMASK_H -#define OPENVPN_COMMON_UMASK_H - -#include <sys/types.h> -#include <sys/stat.h> - -namespace openvpn { - // Note: not thread safe, since umask() is - // documented to modify the process-wide file - // mode creation mask. - class UMask - { - public: - UMask(mode_t new_umask) - { - umask_save = ::umask(new_umask); - } - - ~UMask() - { - ::umask(umask_save); - } - - private: - UMask(const UMask&) = delete; - UMask& operator=(const UMask&) = delete; - - mode_t umask_save; - }; - - struct UMaskPrivate : public UMask - { - UMaskPrivate() - : UMask(077) - { - } - }; - - struct UMaskDaemon : public UMask - { - UMaskDaemon() - : UMask(S_IWOTH) - { - } - }; -} -#endif diff --git a/Sources/OpenVPN3/openvpn/common/unicode-impl.hpp b/Sources/OpenVPN3/openvpn/common/unicode-impl.hpp deleted file mode 100644 index 0dd65b5..0000000 --- a/Sources/OpenVPN3/openvpn/common/unicode-impl.hpp +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -#ifndef OPENVPN_COMMON_UNICODE_IMPL_H -#define OPENVPN_COMMON_UNICODE_IMPL_H - -namespace openvpn { - namespace Unicode { - /* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, - or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Fixes & updates, Sept 2001. - - ------------------------------------------------------------------------ */ - - /* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. - ------------------------------------------------------------------------ */ - - typedef unsigned int UTF32; /* at least 32 bits */ - typedef unsigned short UTF16; /* at least 16 bits */ - typedef unsigned char UTF8; /* typically 8 bits */ - - /* Some fundamental constants */ - const UTF32 UNI_REPLACEMENT_CHAR = (UTF32)0x0000FFFD; - const UTF32 UNI_MAX_BMP = (UTF32)0x0000FFFF; - const UTF32 UNI_MAX_UTF16 = (UTF32)0x0010FFFF; - const UTF32 UNI_MAX_UTF32 = (UTF32)0x7FFFFFFF; - const UTF32 UNI_MAX_LEGAL_UTF32 = (UTF32)0x0010FFFF; - - typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ - } ConversionResult; - - typedef enum { - strictConversion = 0, - lenientConversion - } ConversionFlags; - - /* --------------------------------------------------------------------- */ - /* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - - /* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Source code file. - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Sept 2001: fixed const & error conditions per - mods suggested by S. Parent & A. Lillich. - June 2002: Tim Dodd added detection and handling of incomplete - source sequences, enhanced error detection, added casts - to eliminate compiler warnings. - July 2003: slight mods to back out aggressive FFFE detection. - Jan 2004: updated switches in from-UTF8 conversions. - Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. - - See the header file "ConvertUTF.h" for complete documentation. - - ------------------------------------------------------------------------ */ - - const int halfShift = 10; /* used for shifting by 10 bits */ - - const UTF32 halfBase = 0x0010000UL; - const UTF32 halfMask = 0x3FFUL; - - const UTF32 UNI_SUR_HIGH_START = (UTF32)0xD800; - const UTF32 UNI_SUR_HIGH_END = (UTF32)0xDBFF; - const UTF32 UNI_SUR_LOW_START = (UTF32)0xDC00; - const UTF32 UNI_SUR_LOW_END = (UTF32)0xDFFF; - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; - } - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF32* target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG - if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); - } -#endif - return result; - } - - /* --------------------------------------------------------------------- */ - - /* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ - const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 - }; - - /* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ - const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - - /* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... etc.). Remember that sequencs - * for *legal* UTF-8 will be 4 or fewer bytes total. - */ - const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - /* --------------------------------------------------------------------- */ - - /* The interface converts a whole buffer to avoid function-call overhead. - * Constants have been gathered. Loops & conditionals have been removed as - * much as possible for efficiency, in favor of drop-through switches. - * (See "Note A" at the bottom of the file for equivalent code.) - * If your compiler supports it, the "isLegalUTF8" call can be turned - * into an inline function. - */ - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; - } - - /* --------------------------------------------------------------------- */ - - /* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - - inline bool isLegalUTF8(const UTF8 *source, int length) { - UTF8 a; - const UTF8 *srcptr = source+length; - switch (length) { - default: return false; - /* Everything else falls through when "true"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) return false; - return true; - } - - /* --------------------------------------------------------------------- */ - - /* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ - inline bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source]+1; - if (source+length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); - } - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead+1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; - } - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion ) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; - } - - /* --------------------------------------------------------------------- */ - - inline ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF32* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; - case 4: ch += *source++; ch <<= 6; - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up the source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } - } - *sourceStart = source; - *targetStart = target; - return result; - } - - /* --------------------------------------------------------------------- - - Note A. - The fall-through switches in UTF-8 reading code save a - temp variable, some decrements & conditionals. The switches - are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } - In UTF-8 writing code, the switches on "bytesToWrite" are - similarly unrolled loops. - - --------------------------------------------------------------------- */ - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/unicode.hpp b/Sources/OpenVPN3/openvpn/common/unicode.hpp deleted file mode 100644 index ee60c34..0000000 --- a/Sources/OpenVPN3/openvpn/common/unicode.hpp +++ /dev/null @@ -1,301 +0,0 @@ -// 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-2020 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/>. - -// General-purpose function for dealing with unicode. - -#ifndef OPENVPN_COMMON_UNICODE_H -#define OPENVPN_COMMON_UNICODE_H - -#include <string> -#include <cstring> // for std::memcpy -#include <algorithm> // for std::min -#include <memory> -#include <cctype> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/unicode-impl.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - namespace Unicode { - - OPENVPN_SIMPLE_EXCEPTION(unicode_src_overflow); - OPENVPN_SIMPLE_EXCEPTION(unicode_dest_overflow); - OPENVPN_SIMPLE_EXCEPTION(unicode_malformed); - - // Return true if the given buffer is a valid UTF-8 string. - // Extra constraints: - enum { - UTF8_NO_CTRL = (1<<30), // no control chars allowed - UTF8_NO_SPACE = (1<<31), // no space chars allowed - }; - inline bool is_valid_utf8_uchar_buf(const unsigned char *source, - size_t size, - const size_t max_len_flags=0) // OR max length (or 0 to disable) with UTF8_x flags above - { - const size_t max_len = max_len_flags & ((size_t)UTF8_NO_CTRL-1); // NOTE -- use smallest flag value here - size_t unicode_len = 0; - while (size) - { - const unsigned char c = *source; - if (c == '\0') - return false; - const int length = trailingBytesForUTF8[c]+1; - if ((size_t)length > size) - return false; - if (!isLegalUTF8(source, length)) - return false; - if (length == 1) - { - if ((max_len_flags & UTF8_NO_CTRL) && std::iscntrl(c)) - return false; - if ((max_len_flags & UTF8_NO_SPACE) && std::isspace(c)) - return false; - } - - source += length; - size -= length; - ++unicode_len; - if (max_len && unicode_len > max_len) - return false; - } - return true; - } - - template <typename STRING> - inline bool is_valid_utf8(const STRING& str, const size_t max_len_flags=0) - { - return is_valid_utf8_uchar_buf((const unsigned char *)str.c_str(), str.length(), max_len_flags); - } - - // Return the byte position in the string that corresponds with - // the given character index. Return values: - enum { - UTF8_GOOD=0, // succeeded, result in index - UTF8_BAD, // failed, string is not legal UTF8 - UTF8_RANGE, // failed, index is beyond end of string - }; - template <typename STRING> - inline int utf8_index(STRING& str, size_t& index) - { - const size_t size = str.length(); - size_t upos = 0; - size_t pos = 0; - while (pos < size) - { - const int len = trailingBytesForUTF8[(unsigned char)str[pos]]+1; - if (pos + len > size || !isLegalUTF8((const unsigned char *)&str[pos], len)) - return UTF8_BAD; - if (upos >= index) - { - index = pos; - return UTF8_GOOD; - } - pos += len; - ++upos; - } - return UTF8_RANGE; - } - - // Truncate a UTF8 string if its length exceeds max_len - template <typename STRING> - inline void utf8_truncate(STRING& str, size_t max_len) - { - const int status = utf8_index(str, max_len); - if (status == UTF8_GOOD || status == UTF8_BAD) - str = str.substr(0, max_len); - } - - // Return a printable UTF-8 string, where bad UTF-8 chars and - // control chars are mapped to '?'. - // If max_len_flags > 0, print a maximum of max_len_flags chars. - // If UTF8_PASS_FMT flag is set in max_len_flags, pass through \r\n\t - enum { - UTF8_PASS_FMT=(1<<31), - UTF8_FILTER=(1<<30), - }; - template <typename STRING> - inline STRING utf8_printable(const STRING& str, size_t max_len_flags) - { - STRING ret; - const size_t size = str.length(); - const size_t max_len = max_len_flags & ((size_t)UTF8_FILTER-1); // NOTE -- use smallest flag value here - size_t upos = 0; - size_t pos = 0; - ret.reserve(std::min(str.length(), max_len) + 3); // add 3 for "..." - while (pos < size) - { - if (!max_len || upos < max_len) - { - unsigned char c = str[pos]; - int len = trailingBytesForUTF8[c]+1; - if (pos + len <= size - && c >= 0x20 && c != 0x7F - && isLegalUTF8((const unsigned char *)&str[pos], len)) - { - // non-control, legal UTF-8 - ret.append(str, pos, len); - } - else - { - // control char or bad UTF-8 char - if (c == '\r' || c == '\n' || c == '\t') - { - if (!(max_len_flags & UTF8_PASS_FMT)) - c = ' '; - } - else if (max_len_flags & UTF8_FILTER) - c = 0; - else - c = '?'; - if (c) - ret += c; - len = 1; - } - pos += len; - ++upos; - } - else - { - ret.append("..."); - break; - } - } - return ret; - } - - template <typename STRING> - inline size_t utf8_length(const STRING& str) - { - const size_t size = str.length(); - size_t upos = 0; - size_t pos = 0; - while (pos < size) - { - int len = std::min((int)trailingBytesForUTF8[(unsigned char)str[pos]]+1, - (int)size); - if (!isLegalUTF8((const unsigned char *)&str[pos], len)) - len = 1; - pos += len; - ++upos; - } - return upos; - } - - inline void conversion_result_throw(const ConversionResult res) - { - switch (res) - { - case conversionOK: - return; - case sourceExhausted: - throw unicode_src_overflow(); - case targetExhausted: - throw unicode_dest_overflow(); - case sourceIllegal: - throw unicode_malformed(); - } - } - - // Convert a UTF-8 string to UTF-16 little endian (no null termination in return) - template <typename STRING> - inline BufferPtr string_to_utf16(const STRING& str) - { - std::unique_ptr<UTF16[]> utf16_dest(new UTF16[str.length()]); - const UTF8 *src = (UTF8 *)str.c_str(); - UTF16 *dest = utf16_dest.get(); - const ConversionResult res = ConvertUTF8toUTF16(&src, src + str.length(), - &dest, dest + str.length(), - lenientConversion); - conversion_result_throw(res); - BufferPtr ret(new BufferAllocated((dest - utf16_dest.get()) * 2, BufferAllocated::ARRAY)); - UTF8 *d = ret->data(); - for (const UTF16 *s = utf16_dest.get(); s < dest; ++s) - { - *d++ = *s & 0xFF; - *d++ = (*s >> 8) & 0xFF; - } - return ret; - } - - class UTF8Iterator - { - public: - struct Char - { - unsigned int len; - unsigned char data[4]; - bool valid; - - const bool is_valid() const - { - return valid && len >= 1 && len <= sizeof(data); - } - - std::string str(const char *malformed) - { - if (is_valid()) - return std::string((char *)data, len); - else - return malformed; - } - }; - - UTF8Iterator(const std::string& str_arg) - : str((unsigned char *)str_arg.c_str()), - size(str_arg.length()) - { - } - - bool get(Char &c) - { - if (size) - { - unsigned int len = std::min((unsigned int)trailingBytesForUTF8[*str]+1, - (unsigned int)size); - if (isLegalUTF8(str, len)) - { - c.valid = true; - c.len = std::min(len, (unsigned int)sizeof(c.data)); - std::memcpy(c.data, str, c.len); - } - else - { - c.valid = false; - c.len = 1; - } - str += c.len; - size -= c.len; - return true; - } - else - return false; - } - - private: - const unsigned char *str; - unsigned int size; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/uniqueptr.hpp b/Sources/OpenVPN3/openvpn/common/uniqueptr.hpp deleted file mode 100644 index 25ae83d..0000000 --- a/Sources/OpenVPN3/openvpn/common/uniqueptr.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// 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-2020 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_COMMON_UNIQUEPTR_H -#define OPENVPN_COMMON_UNIQUEPTR_H - -#include <memory> -#include <functional> - -namespace openvpn { - template<typename T> - using unique_ptr_del = std::unique_ptr<T, std::function<void(T*)>>; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/usecount.hpp b/Sources/OpenVPN3/openvpn/common/usecount.hpp deleted file mode 100644 index 8dc1adb..0000000 --- a/Sources/OpenVPN3/openvpn/common/usecount.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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-2020 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/>. - -// General purpose class for scope accounting. - -#ifndef OPENVPN_COMMON_USECOUNT_H -#define OPENVPN_COMMON_USECOUNT_H - -namespace openvpn { - - class UseCount - { - public: - UseCount(int& count) - : count_(count) - { - ++count_; - } - - ~UseCount() - { - --count_; - } - - private: - int& count_; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_USECOUNT_H diff --git a/Sources/OpenVPN3/openvpn/common/usergroup.hpp b/Sources/OpenVPN3/openvpn/common/usergroup.hpp deleted file mode 100644 index 0aa02f0..0000000 --- a/Sources/OpenVPN3/openvpn/common/usergroup.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// 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-2020 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_COMMON_USERGROUP_H -#define OPENVPN_COMMON_USERGROUP_H - -#include <pwd.h> -#include <grp.h> -#include <unistd.h> -#include <sys/types.h> -#include <errno.h> - -#include <string> - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_LINUX -#include <sys/prctl.h> -#endif - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/strerror.hpp> - -namespace openvpn { - // NOTE: -- SetUserGroup object does not own passwd and group - // objects, therefore *pw and *gr can change under us. - class SetUserGroup - { - public: - OPENVPN_EXCEPTION(user_group_err); - - SetUserGroup(const std::string& user, const std::string& group, const bool strict) - : SetUserGroup(user.empty() ? nullptr : user.c_str(), - group.empty() ? nullptr : group.c_str(), - strict) - { - } - - SetUserGroup(const char *user, const char *group, const bool strict) - : pw(nullptr), - gr(nullptr) - { - if (user) - { - pw = ::getpwnam(user); - if (!pw && strict) - OPENVPN_THROW(user_group_err, "user lookup failed for '" << user << '\''); - user_name = user; - } - if (group) - { - gr = ::getgrnam(group); - if (!gr && strict) - OPENVPN_THROW(user_group_err, "group lookup failed for '" << group << '\''); - group_name = group; - } - } - - const std::string& user() const - { - return user_name; - } - - const std::string& group() const - { - return group_name; - } - - void activate() const - { - if (gr) - { - if (::setgid(gr->gr_gid)) - { - const int eno = errno; - OPENVPN_THROW(user_group_err, "setgid failed for group '" << group_name << "': " << strerror_str(eno)); - } - gid_t gr_list[1]; - gr_list[0] = gr->gr_gid; - if (::setgroups(1, gr_list)) - { - const int eno = errno; - OPENVPN_THROW(user_group_err, "setgroups failed for group '" << group_name << "': " << strerror_str(eno)); - } - OPENVPN_LOG("GID set to '" << group_name << '\''); - } - if (pw) - { - if (::setuid(pw->pw_uid)) - { - const int eno = errno; - OPENVPN_THROW(user_group_err, "setuid failed for user '" << user_name << "': " << strerror_str(eno)); - } - OPENVPN_LOG("UID set to '" << user_name << '\''); - } -#ifdef OPENVPN_PLATFORM_LINUX - // retain core dumpability after setgid/setuid - if (gr || pw) - ::prctl(PR_SET_DUMPABLE, 1); -#endif - } - - void chown(const std::string& fn) const - { - if (pw && gr) - { - const int status = ::chown(fn.c_str(), uid(), gid()); - if (status < 0) - { - const int eno = errno; - OPENVPN_THROW(user_group_err, "chown " << user_name << '.' << group_name << ' ' << fn << " : " << strerror_str(eno)); - } - } - } - - void chown(const int fd, const std::string& title) const - { - if (pw && gr) - { - const int status = ::fchown(fd, uid(), gid()); - if (status < 0) - { - const int eno = errno; - OPENVPN_THROW(user_group_err, "chown " << user_name << '.' << group_name << ' ' << title << " : " << strerror_str(eno)); - } - } - } - - void invalidate() - { - pw = nullptr; - gr = nullptr; - } - - uid_t uid() const - { - if (pw) - return pw->pw_uid; - else - return -1; - } - - gid_t gid() const - { - if (gr) - return gr->gr_gid; - else - return -1; - } - - bool uid_defined() const - { - return bool(pw); - } - - bool gid_defined() const - { - return bool(gr); - } - - bool defined() const - { - return uid_defined() && gid_defined(); - } - - private: - std::string user_name; - std::string group_name; - - struct passwd *pw; - struct group *gr; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/userpass.hpp b/Sources/OpenVPN3/openvpn/common/userpass.hpp deleted file mode 100644 index f8d7701..0000000 --- a/Sources/OpenVPN3/openvpn/common/userpass.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// 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-2020 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_COMMON_USERPASS_H -#define OPENVPN_COMMON_USERPASS_H - -#include <string> -#include <vector> -#include <utility> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/file.hpp> - -namespace openvpn { - namespace UserPass { - - OPENVPN_EXCEPTION(creds_error); - - enum Flags { - OPT_REQUIRED = (1<<0), // option must be present - OPT_OPTIONAL = (1<<1), // if option is not present, USERNAME_REQUIRED and PASSWORD_REQUIRED are ignored - USERNAME_REQUIRED = (1<<2), // username must be present - PASSWORD_REQUIRED = (1<<3), // password must be present - TRY_FILE = (1<<4), // option argument might be a filename, try to load creds from it - }; - - inline bool parse(const OptionList& options, - const std::string& opt_name, - const unsigned int flags, - std::vector<std::string>* user_pass) - { - const Option* auth_user_pass = options.get_ptr(opt_name); - if (!auth_user_pass) - { - if (flags & OPT_REQUIRED) - throw creds_error(opt_name + " : credentials option missing"); - return false; - } - if (auth_user_pass->size() == 1 && !(flags & OPT_REQUIRED)) - return true; - if (auth_user_pass->size() != 2) - throw creds_error(opt_name + " : credentials option incorrectly specified"); - - std::string str = auth_user_pass->get(1, 1024 | Option::MULTILINE); - if ((flags & TRY_FILE) && !string::is_multiline(str)) - str = read_text_utf8(str); - SplitLines in(str, 1024); - for (int i = 0; in(true) && i < 2; ++i) - { - if (user_pass) - user_pass->push_back(in.line_move()); - } - return true; - } - - inline void parse(const OptionList& options, - const std::string& opt_name, - const unsigned int flags, - std::string& user, - std::string& pass) - { - std::vector<std::string> up; - up.reserve(2); - if (!parse(options, opt_name, flags, &up) && (flags & OPT_OPTIONAL)) - return; - if (up.size() >= 1) - { - user = std::move(up[0]); - if (up.size() >= 2) - pass = std::move(up[1]); - } - if ((flags & USERNAME_REQUIRED) && string::is_empty(user)) - throw creds_error(opt_name + " : username empty"); - if ((flags & PASSWORD_REQUIRED) && string::is_empty(pass)) - throw creds_error(opt_name + " : password empty"); - } - - inline void parse(const std::string& path, - const unsigned int flags, - std::string& user, - std::string& pass) - { - user.clear(); - pass.clear(); - const std::string str = read_text_utf8(path); - SplitLines in(str, 1024); - if (in(true)) - { - user = in.line_move(); - if (in(true)) - pass = in.line_move(); - } - if ((flags & USERNAME_REQUIRED) && string::is_empty(user)) - throw creds_error(path + " : username empty"); - if ((flags & PASSWORD_REQUIRED) && string::is_empty(pass)) - throw creds_error(path + " : password empty"); - } - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/valgrind.hpp b/Sources/OpenVPN3/openvpn/common/valgrind.hpp deleted file mode 100644 index 6186f36..0000000 --- a/Sources/OpenVPN3/openvpn/common/valgrind.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// 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-2020 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 - -#if defined(HAVE_VALGRIND) -#include <valgrind/memcheck.h> -#define OPENVPN_MAKE_MEM_DEFINED(addr, len) VALGRIND_MAKE_MEM_DEFINED(addr, len) -#else -#define OPENVPN_MAKE_MEM_DEFINED(addr, len) -#endif diff --git a/Sources/OpenVPN3/openvpn/common/version.hpp b/Sources/OpenVPN3/openvpn/common/version.hpp deleted file mode 100644 index b0840e6..0000000 --- a/Sources/OpenVPN3/openvpn/common/version.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// 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-2020 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/>. - -// Current version of the OpenVPN core - -#pragma once - -#ifndef OPENVPN_VERSION -#define OPENVPN_VERSION "3.6.1" -#endif diff --git a/Sources/OpenVPN3/openvpn/common/waitbarrier.hpp b/Sources/OpenVPN3/openvpn/common/waitbarrier.hpp deleted file mode 100644 index 3ad84d5..0000000 --- a/Sources/OpenVPN3/openvpn/common/waitbarrier.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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_COMMON_WAITBARRIER_H -#define OPENVPN_COMMON_WAITBARRIER_H - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/pthreadcond.hpp> - -namespace openvpn { - -#ifdef HAVE_VALGRIND - static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 300; -#else - static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 30; -#endif - - template <typename THREAD_COMMON> - inline void event_loop_wait_barrier(THREAD_COMMON& tc, - const unsigned int seconds=WAIT_BARRIER_TIMEOUT) - { - // barrier prior to event-loop entry - switch (tc.event_loop_bar.wait(seconds)) - { - case PThreadBarrier::SUCCESS: - break; - case PThreadBarrier::CHOSEN_ONE: - tc.user_group.activate(); - tc.show_unused_options(); - tc.event_loop_bar.signal(); - break; - case PThreadBarrier::TIMEOUT: - throw Exception("event loop barrier timeout"); - case PThreadBarrier::ERROR: - throw Exception("event loop barrier error"); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/write.hpp b/Sources/OpenVPN3/openvpn/common/write.hpp deleted file mode 100644 index 48da5b9..0000000 --- a/Sources/OpenVPN3/openvpn/common/write.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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_COMMON_WRITE_H -#define OPENVPN_COMMON_WRITE_H - -#include <unistd.h> -#include <stdlib.h> // defines std::abort() - -namespace openvpn { - // like posix write() but retry if full buffer is not written - inline ssize_t write_retry(int fd, const void *buf, size_t count) - { - size_t total = 0; - while (true) - { - const ssize_t status = ::write(fd, buf, count); - if (status < 0) - return status; - if (static_cast<size_t>(status) > count) // should never happen - std::abort(); - total += status; - count -= status; - if (!count) - break; - buf = static_cast<const unsigned char*>(buf) + status; - } - return total; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/writeprivate.hpp b/Sources/OpenVPN3/openvpn/common/writeprivate.hpp deleted file mode 100644 index 8ebcc85..0000000 --- a/Sources/OpenVPN3/openvpn/common/writeprivate.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// 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-2020 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 <openvpn/common/platform.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) -#include <sys/types.h> // for open(), ftruncate() -#include <sys/stat.h> // for open() -#include <fcntl.h> // for open() -#include <unistd.h> // for write(), ftruncate() -#include <errno.h> -#endif - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/buffer/buffer.hpp> - -#if !defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/write.hpp> -#include <openvpn/common/strerror.hpp> -#endif - -namespace openvpn { - -#if defined(OPENVPN_PLATFORM_WIN) - - inline void write_private(const std::string& path, const void *buf, size_t count) - { - OPENVPN_THROW_EXCEPTION("write_private('" << path << "') : not implemented on Windows yet"); - } - -#else - - inline void write_private(const std::string& path, const void *buf, ssize_t count) - { - ScopedFD fd(::open(path.c_str(), O_WRONLY|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR)); - if (!fd.defined()) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION(path << " : open error : " << strerror_str(eno)); - } - if (::ftruncate(fd(), 0) < 0) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION(path << " : truncate error : " << strerror_str(eno)); - } - const ssize_t len = write_retry(fd(), buf, count); - if (len == -1) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION(path << " : write error : " << strerror_str(eno)); - } - else if (len != count) - OPENVPN_THROW_EXCEPTION(path << " : unexpected write size"); - if (!fd.close()) - { - const int eno = errno; - OPENVPN_THROW_EXCEPTION(path << " : close error : " << strerror_str(eno)); - } - } - -#endif - - inline void write_private(const std::string& path, const Buffer& buf) - { - write_private(path, buf.c_data(), buf.size()); - } - - inline void write_private(const std::string& path, const std::string& str) - { - write_private(path, str.c_str(), str.length()); - } - -} diff --git a/Sources/OpenVPN3/openvpn/common/wstring.hpp b/Sources/OpenVPN3/openvpn/common/wstring.hpp deleted file mode 100644 index 3a77b26..0000000 --- a/Sources/OpenVPN3/openvpn/common/wstring.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// 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-2020 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_COMMON_WSTRING_H -#define OPENVPN_COMMON_WSTRING_H - -#include <string> -#include <vector> -#include <locale> -#include <codecvt> -#include <memory> - -namespace openvpn { - namespace wstring { - - inline std::wstring from_utf8(const std::string& str) - { -#ifdef __MINGW32__ - // https://sourceforge.net/p/mingw-w64/bugs/538/ - typedef std::codecvt_utf8<wchar_t, 0x10ffff, std::little_endian> cvt_type; -#else - typedef std::codecvt_utf8<wchar_t> cvt_type; -#endif - std::wstring_convert<cvt_type, wchar_t> cvt; - return cvt.from_bytes(str); - } - - inline std::string to_utf8(const std::wstring& wstr) - { -#ifdef __MINGW32__ - typedef std::codecvt_utf8<wchar_t, 0x10ffff, std::little_endian> cvt_type; -#else - typedef std::codecvt_utf8<wchar_t> cvt_type; -#endif - std::wstring_convert<cvt_type, wchar_t> cvt; - return cvt.to_bytes(wstr); - } - - inline std::unique_ptr<wchar_t[]> to_wchar_t(const std::wstring& wstr) - { - const size_t len = wstr.length(); - std::unique_ptr<wchar_t[]> ret(new wchar_t[len+1]); - size_t i; - for (i = 0; i < len; ++i) - ret[i] = wstr[i]; - ret[i] = L'\0'; - return ret; - } - - // return value corresponds to the MULTI_SZ string format on Windows - inline std::wstring pack_string_vector(const std::vector<std::string>& strvec) - { - std::wstring ret; - for (auto &s : strvec) - { - ret += from_utf8(s); - ret += L'\0'; - } - return ret; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/common/xmlhelper.hpp b/Sources/OpenVPN3/openvpn/common/xmlhelper.hpp deleted file mode 100644 index 4067f4c..0000000 --- a/Sources/OpenVPN3/openvpn/common/xmlhelper.hpp +++ /dev/null @@ -1,142 +0,0 @@ -// 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-2020 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 <tinyxml2.h> - -namespace openvpn { - - class Xml - { - public: - OPENVPN_EXCEPTION(xml_parse); - - struct Document : public tinyxml2::XMLDocument - { - Document(const std::string& str, - const std::string& title) - { - if (tinyxml2::XMLDocument::Parse(str.c_str())) - OPENVPN_THROW(xml_parse, title << " : " << format_error(*this)); - } - }; - - static std::string to_string(const tinyxml2::XMLDocument& doc) - { - tinyxml2::XMLPrinter printer; - doc.Print(&printer); - return printer.CStr(); - } - - static std::string format_error(const tinyxml2::XMLDocument& doc) - { -#if OVPN_TINYXML2_HAS_ERROR_NAME - std::string ret = doc.ErrorName(); -#else - tinyxml2::XMLError error = doc.ErrorID(); - std::string ret{"XMLError " + error}; -#endif -#if OVPN_TINYXML2_HAS_ERROR_STR - const char *es = doc.ErrorStr(); - if (es) - { - ret += ' '; - ret += es; - } -#else - const char *es1 = doc.GetErrorStr1(); - const char *es2 = doc.GetErrorStr2(); - if (es1) - { - ret += ' '; - ret += es1; - } - if (es2) - { - ret += ' '; - ret += es2; - } -#endif - return ret; - } - - template<typename T, typename... Args> - static std::string find_text(const tinyxml2::XMLNode* node, - const T& first, - Args... args) - { - const tinyxml2::XMLElement* e = find(node, first, args...); - if (e) - return e->GetText(); - else - return std::string(); - } - - template<typename T, typename... Args> - static const tinyxml2::XMLElement* find(const tinyxml2::XMLNode* node, - const T& first, - Args... args) - { - const tinyxml2::XMLElement *e = find(node, first); - if (e) - e = find(e, args...); - return e; - } - - static const tinyxml2::XMLElement* find(const tinyxml2::XMLNode* node, - const std::string& first) - { - return node->FirstChildElement(first.c_str()); - } - - static const tinyxml2::XMLElement* find(const tinyxml2::XMLNode* node, - const char *first) - { - return node->FirstChildElement(first); - } - - static const tinyxml2::XMLElement* find(const tinyxml2::XMLElement* elem) - { - return elem; - } - - static const tinyxml2::XMLElement* next_sibling(const tinyxml2::XMLNode* node, - const std::string& name) - { - return node->NextSiblingElement(name.c_str()); - } - - static const tinyxml2::XMLElement* next_sibling(const tinyxml2::XMLNode* node, - const char *name) - { - return node->NextSiblingElement(name); - } - - static const tinyxml2::XMLElement* next_sibling(const tinyxml2::XMLNode* node) - { - return node->NextSiblingElement(); - } - - }; -} diff --git a/Sources/OpenVPN3/openvpn/compress/compnull.hpp b/Sources/OpenVPN3/openvpn/compress/compnull.hpp deleted file mode 100644 index 395661b..0000000 --- a/Sources/OpenVPN3/openvpn/compress/compnull.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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-2020 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/>. - -// A null compression class. - -#ifndef OPENVPN_COMPRESS_COMPNULL_H -#define OPENVPN_COMPRESS_COMPNULL_H - -namespace openvpn { - - class CompressNull : public Compress - { - public: - CompressNull(const Frame::Ptr& frame, const SessionStats::Ptr& stats) - : Compress(frame, stats) - { - } - - virtual const char *name() const { return "null"; } - virtual void compress(BufferAllocated& buf, const bool hint) {} - virtual void decompress(BufferAllocated& buf) {} - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_COMPNULL_H diff --git a/Sources/OpenVPN3/openvpn/compress/compress.hpp b/Sources/OpenVPN3/openvpn/compress/compress.hpp deleted file mode 100644 index d3f9027..0000000 --- a/Sources/OpenVPN3/openvpn/compress/compress.hpp +++ /dev/null @@ -1,548 +0,0 @@ -// 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-2020 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/>. - -// Base class and factory for compression/decompression objects. -// Currently we support LZO, Snappy, and LZ4 implementations. - -#ifndef OPENVPN_COMPRESS_COMPRESS_H -#define OPENVPN_COMPRESS_COMPRESS_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> - -#define OPENVPN_LOG_COMPRESS(x) -#define OPENVPN_LOG_COMPRESS_VERBOSE(x) - -#if defined(OPENVPN_DEBUG_COMPRESS) -#if OPENVPN_DEBUG_COMPRESS >= 1 -#undef OPENVPN_LOG_COMPRESS -#define OPENVPN_LOG_COMPRESS(x) OPENVPN_LOG(x) -#endif -#if OPENVPN_DEBUG_COMPRESS >= 2 -#undef OPENVPN_LOG_COMPRESS_VERBOSE -#define OPENVPN_LOG_COMPRESS_VERBOSE(x) OPENVPN_LOG(x) -#endif -#endif - -namespace openvpn { - class Compress : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Compress> Ptr; - - // Compressor name - virtual const char *name() const = 0; - - // Compression method implemented by underlying compression class. - // hint should normally be true to compress the data. If hint is - // false, the data may be uncompressible or already compressed, - // so method shouldn't attempt compression. - virtual void compress(BufferAllocated& buf, const bool hint) = 0; - - // Decompression method implemented by underlying compression class. - virtual void decompress(BufferAllocated& buf) = 0; - - protected: - // magic numbers to indicate no compression - enum { - NO_COMPRESS = 0xFA, - NO_COMPRESS_SWAP = 0xFB, // for better alignment handling, replace this byte with last byte of packet - }; - - // Compress V2 constants - enum { - COMPRESS_V2_ESCAPE=0x50, - - // Compression algs - OVPN_COMPv2_NONE=0, - OVPN_COMPv2_LZ4=1, - }; - - Compress(const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg) - : frame(frame_arg), stats(stats_arg) {} - - void error(BufferAllocated& buf) - { - stats->error(Error::COMPRESS_ERROR); - buf.reset_size(); - } - - void do_swap(Buffer& buf, unsigned char op) - { - if (buf.size()) - { - buf.push_back(buf[0]); - buf[0] = op; - } - else - buf.push_back(op); - } - - void do_unswap(Buffer& buf) - { - if (buf.size() >= 2) - { - const unsigned char first = buf.pop_back(); - buf.push_front(first); - } - } - - // Push a COMPRESS_V2 header byte (value). - // Pass value == 0 to omit push. - void v2_push(Buffer& buf, int value) - { - unsigned char uc = buf[0]; - if (value == 0 && uc != COMPRESS_V2_ESCAPE) - return; - unsigned char *esc = buf.prepend_alloc(2); - esc[0] = COMPRESS_V2_ESCAPE; - esc[1] = value; - } - - // Pull a COMPRESS_V2 header byte. - // Returns the compress op (> 0) on success. - // Returns 0 if no compress op. - int v2_pull(Buffer& buf) - { - unsigned char uc = buf[0]; - if (uc != COMPRESS_V2_ESCAPE) - return 0; - uc = buf[1]; - buf.advance(2); - return uc; - } - - Frame::Ptr frame; - SessionStats::Ptr stats; - }; -} - -// include compressor implementations here -#include <openvpn/compress/compnull.hpp> -#include <openvpn/compress/compstub.hpp> - -#ifndef NO_LZO -#include <openvpn/compress/lzoselect.hpp> -#endif -#ifdef HAVE_LZ4 -#include <openvpn/compress/lz4.hpp> -#endif -#ifdef HAVE_SNAPPY -#include <openvpn/compress/snappy.hpp> -#endif - -namespace openvpn { - class CompressContext - { - public: - enum Type { - NONE, - COMP_STUB, // generic compression stub - COMP_STUBv2, // generic compression stub using v2 protocol - ANY, // placeholder for any method on client, before server assigns it - ANY_LZO, // placeholder for LZO or LZO_STUB methods on client, before server assigns it - LZO, - LZO_SWAP, - LZO_STUB, - LZ4, - LZ4v2, - SNAPPY, - }; - - OPENVPN_SIMPLE_EXCEPTION(compressor_unavailable); - - CompressContext() {} - - CompressContext(const Type t, const bool asym) - : asym_(asym) // asym indicates asymmetrical compression where only downlink is compressed - { - if (!compressor_available(t)) - throw compressor_unavailable(); - type_ = t; - } - - Type type() const { return type_; } - bool asym() const { return asym_; } - - unsigned int extra_payload_bytes() const - { - switch (type_) - { - case NONE: - return 0; - case COMP_STUBv2: - case LZ4v2: - return 2; // worst case - default: - return 1; - } - } - - Compress::Ptr new_compressor(const Frame::Ptr& frame, const SessionStats::Ptr& stats) - { - switch (type_) - { - case NONE: - return new CompressNull(frame, stats); - case ANY: - case ANY_LZO: - case LZO_STUB: - return new CompressStub(frame, stats, false); - case COMP_STUB: - return new CompressStub(frame, stats, true); - case COMP_STUBv2: - return new CompressStubV2(frame, stats); -#ifndef NO_LZO - case LZO: - return new CompressLZO(frame, stats, false, asym_); - case LZO_SWAP: - return new CompressLZO(frame, stats, true, asym_); -#endif -#ifdef HAVE_LZ4 - case LZ4: - return new CompressLZ4(frame, stats, asym_); - case LZ4v2: - return new CompressLZ4v2(frame, stats, asym_); -#endif -#ifdef HAVE_SNAPPY - case SNAPPY: - return new CompressSnappy(frame, stats, asym_); -#endif - default: - throw compressor_unavailable(); - } - } - - static bool compressor_available(const Type t) - { - switch (t) - { - case NONE: - case ANY: - case ANY_LZO: - case LZO_STUB: - case COMP_STUB: - case COMP_STUBv2: - return true; - case LZO: - case LZO_SWAP: -#ifndef NO_LZO - return true; -#else - return false; -#endif - case LZ4: -#ifdef HAVE_LZ4 - return true; -#else - return false; -#endif - case LZ4v2: -#ifdef HAVE_LZ4 - return true; -#else - return false; -#endif - case SNAPPY: -#ifdef HAVE_SNAPPY - return true; -#else - return false; -#endif - default: - return false; - } - } - - // On the client, used to tell server which compression methods we support. - // Includes compression V1 and V2 methods. - const char *peer_info_string() const - { - switch (type_) - { -#ifndef NO_LZO - case LZO: - return "IV_LZO=1\n"; - case LZO_SWAP: - return "IV_LZO_SWAP=1\n"; -#endif -#ifdef HAVE_LZ4 - case LZ4: - return "IV_LZ4=1\n"; -#endif -#ifdef HAVE_LZ4 - case LZ4v2: - return "IV_LZ4v2=1\n"; -#endif -#ifdef HAVE_SNAPPY - case SNAPPY: - return "IV_SNAPPY=1\n"; -#endif - case LZO_STUB: - case COMP_STUB: - case COMP_STUBv2: - return - "IV_LZO_STUB=1\n" - "IV_COMP_STUB=1\n" - "IV_COMP_STUBv2=1\n" - ; - case ANY: - return -#ifdef HAVE_SNAPPY - "IV_SNAPPY=1\n" -#endif -#ifndef NO_LZO - "IV_LZO=1\n" - "IV_LZO_SWAP=1\n" -#else - "IV_LZO_STUB=1\n" -#endif -#ifdef HAVE_LZ4 - "IV_LZ4=1\n" - "IV_LZ4v2=1\n" -#endif - "IV_COMP_STUB=1\n" - "IV_COMP_STUBv2=1\n" - ; - case ANY_LZO: - return -#ifndef NO_LZO - "IV_LZO=1\n" - "IV_LZO_SWAP=1\n" -#else - "IV_LZO_STUB=1\n" -#endif - "IV_COMP_STUB=1\n" - "IV_COMP_STUBv2=1\n" - ; - default: - return nullptr; - } - } - - // On the client, used to tell server which compression methods we support. - // Limited only to compression V1 methods. - const char *peer_info_string_v1() const - { - switch (type_) - { -#ifndef NO_LZO - case LZO: - return "IV_LZO=1\n"; - case LZO_SWAP: - return "IV_LZO_SWAP=1\n"; -#endif -#ifdef HAVE_LZ4 - case LZ4: - return "IV_LZ4=1\n"; -#endif -#ifdef HAVE_SNAPPY - case SNAPPY: - return "IV_SNAPPY=1\n"; -#endif - case LZO_STUB: - case COMP_STUB: - return - "IV_LZO_STUB=1\n" - "IV_COMP_STUB=1\n" - ; - case ANY: - return -#ifdef HAVE_SNAPPY - "IV_SNAPPY=1\n" -#endif -#ifndef NO_LZO - "IV_LZO=1\n" - "IV_LZO_SWAP=1\n" -#else - "IV_LZO_STUB=1\n" -#endif -#ifdef HAVE_LZ4 - "IV_LZ4=1\n" -#endif - "IV_COMP_STUB=1\n" - ; - case ANY_LZO: - return -#ifndef NO_LZO - "IV_LZO=1\n" - "IV_LZO_SWAP=1\n" -#else - "IV_LZO_STUB=1\n" -#endif - "IV_COMP_STUB=1\n" - ; - default: - return nullptr; - } - } - - const char *options_string() const - { - switch (type_) - { - case LZO: - case LZO_STUB: - case SNAPPY: - case LZ4: - case LZ4v2: - case LZO_SWAP: - case COMP_STUB: - case COMP_STUBv2: - case ANY: - case ANY_LZO: - return "comp-lzo"; - default: - return nullptr; - } - } - - const char *str() const - { - switch (type_) - { - case LZO: - return "LZO"; - case LZO_SWAP: - return "LZO_SWAP"; - case LZ4: - return "LZ4"; - case LZ4v2: - return "LZ4v2"; - case SNAPPY: - return "SNAPPY"; - case LZO_STUB: - return "LZO_STUB"; - case COMP_STUB: - return "COMP_STUB"; - case COMP_STUBv2: - return "COMP_STUBv2"; - case ANY: - return "ANY"; - case ANY_LZO: - return "ANY_LZO"; - default: - return "NONE"; - } - } - - /* This function returns a parseable string representation of the compress - * method. NOTE: returns nullptr if no mapping is possible */ - const char *method_to_string() const - { - switch (type_) - { - case LZO: - return "lzo"; - case LZO_SWAP: - return "lzo-swap"; - case LZO_STUB: - return "lzo-stub"; - case LZ4: - return "lz4"; - case LZ4v2: - return "lz4v2"; - case SNAPPY: - return "snappy"; - case COMP_STUB: - return "stub"; - case COMP_STUBv2: - return "stub-v2"; - default: - return nullptr; - } - } - - static Type parse_method(const std::string& method) - { - if (method == "stub-v2") - return COMP_STUBv2; - else if (method == "lz4-v2") - return LZ4v2; - else if (method == "lz4") - return LZ4; - else if (method == "lzo") - return LZO; - else if (method == "lzo-swap") - return LZO_SWAP; - else if (method == "lzo-stub") - return LZO_STUB; - else if (method == "snappy") - return SNAPPY; - else if (method == "stub") - return COMP_STUB; - else - return NONE; - } - - static Type stub(const Type t) - { - switch (t) - { - case COMP_STUBv2: - case LZ4v2: - return COMP_STUBv2; - default: - return COMP_STUB; - } - } - - /** - * Checks if the compression type is one of the available stub modes - * - * @param t The CompressContext::Type value - * @return Returns true if the type is one of the *_STUB{,v2} types, - * otherwise false. - */ - static bool is_any_stub(const Type t) - { - switch (t) - { - case LZO_STUB: - case COMP_STUB: - case COMP_STUBv2: - return true; - default: - return false; - } - } - - static void init_static() - { -#ifndef NO_LZO - CompressLZO::init_static(); -#endif - } - - private: - Type type_ = NONE; - bool asym_ = false; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_COMPRESS_H diff --git a/Sources/OpenVPN3/openvpn/compress/compstub.hpp b/Sources/OpenVPN3/openvpn/compress/compstub.hpp deleted file mode 100644 index 3427319..0000000 --- a/Sources/OpenVPN3/openvpn/compress/compstub.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// 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-2020 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/>. - -// This is a "stub" compression object. It acts like a compressor -// in the sense that it plays along with compression framing in -// the OpenVPN protocol, but it always sends packets with NO_COMPRESS -// or NO_COMPRESS_SWAP compression status. While it's not designed -// to receive compressed packets, it will try to handle received LZO -// packets, but it will never send compressed packets. - -#ifndef OPENVPN_COMPRESS_COMPSTUB_H -#define OPENVPN_COMPRESS_COMPSTUB_H - -#ifndef NO_LZO -#include <openvpn/compress/lzoselect.hpp> -#endif - -namespace openvpn { - - class CompressStub : public Compress - { - public: - CompressStub(const Frame::Ptr& frame, const SessionStats::Ptr& stats, const bool support_swap_arg) - : Compress(frame, stats), - support_swap(support_swap_arg) -#ifndef NO_LZO - ,lzo(frame, stats, false, true) -#endif - { - OPENVPN_LOG_COMPRESS("Comp-stub init swap=" << support_swap_arg); - } - - virtual const char *name() const { return "stub"; } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - // indicate that we didn't compress - if (support_swap) - do_swap(buf, NO_COMPRESS_SWAP); - else - buf.push_front(NO_COMPRESS); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const unsigned char c = buf.pop_front(); - switch (c) - { - case NO_COMPRESS_SWAP: - do_unswap(buf); - case NO_COMPRESS: - break; -#ifndef NO_LZO - // special mode to support older servers that ignore - // compression handshake -- this will handle receiving - // compressed packets even if we didn't ask for them - case CompressLZO::LZO_COMPRESS: - OPENVPN_LOG_COMPRESS_VERBOSE("CompressStub: handled unsolicited LZO packet"); - lzo.decompress_work(buf); - break; -#endif - default: - OPENVPN_LOG_COMPRESS_VERBOSE("CompressStub: unable to handle op=" << int(c)); - error(buf); - } - } - - private: - const bool support_swap; -#ifndef NO_LZO - CompressLZO lzo; -#endif - }; - - // Compression stub using V2 protocol - class CompressStubV2 : public Compress - { - public: - CompressStubV2(const Frame::Ptr& frame, const SessionStats::Ptr& stats) - : Compress(frame, stats) - { - OPENVPN_LOG_COMPRESS("Comp-stubV2 init"); - } - - virtual const char *name() const { return "stubv2"; } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - // indicate that we didn't compress - v2_push(buf, OVPN_COMPv2_NONE); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const int cop = v2_pull(buf); - if (cop) - { - OPENVPN_LOG_COMPRESS_VERBOSE("CompressStubV2: unable to handle op=" << c); - error(buf); - } - } - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_COMPSTUB_H diff --git a/Sources/OpenVPN3/openvpn/compress/lz4.hpp b/Sources/OpenVPN3/openvpn/compress/lz4.hpp deleted file mode 100644 index f2945a2..0000000 --- a/Sources/OpenVPN3/openvpn/compress/lz4.hpp +++ /dev/null @@ -1,227 +0,0 @@ -// 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-2020 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_COMPRESS_LZ4_H -#define OPENVPN_COMPRESS_LZ4_H - -// Implement LZ4 compression. -// Should only be included by compress.hpp - -#include <algorithm> // for std::max - -#include <lz4.h> - -namespace openvpn { - - class CompressLZ4Base : public Compress - { - protected: - CompressLZ4Base(const Frame::Ptr& frame, const SessionStats::Ptr& stats) - : Compress(frame, stats) - { - } - - bool do_decompress(BufferAllocated& buf) - { - // initialize work buffer - const int payload_size = frame->prepare(Frame::DECOMPRESS_WORK, work); - - // do uncompress - const int decomp_size = LZ4_decompress_safe((const char *)buf.c_data(), (char *)work.data(), - (int)buf.size(), payload_size); - if (decomp_size < 0) - { - error(buf); - return false; - } - OPENVPN_LOG_COMPRESS_VERBOSE("LZ4 uncompress " << buf.size() << " -> " << decomp_size); - work.set_size(decomp_size); - buf.swap(work); - return true; - } - - bool do_compress(BufferAllocated& buf) - { - // initialize work buffer - frame->prepare(Frame::COMPRESS_WORK, work); - - // verify that input data length is not too large - if (lz4_extra_buffer(buf.size()) > work.max_size()) - { - error(buf); - return false; - } - - // do compress - const unsigned int comp_size = LZ4_compress_default((const char *)buf.c_data(), (char *)work.data(), - (int)buf.size(), (int)work.capacity()); - - // did compression actually reduce data length? - if (comp_size < buf.size()) - { - if (comp_size <= 0) - { - error(buf); - return false; - } - OPENVPN_LOG_COMPRESS_VERBOSE("LZ4 compress " << buf.size() << " -> " << comp_size); - work.set_size(comp_size); - buf.swap(work); - return true; - } - else - return false; - } - - // Worst case size expansion on compress. - // Official LZ4 worst-case size expansion alg is - // LZ4_COMPRESSBOUND macro in lz4.h. - // However we optimize it slightly here to lose the integer division - // when len < 65535. - size_t lz4_extra_buffer(const size_t len) - { - if (likely(len < 65535)) - return len + len/256 + 17; - else - return len + len/255 + 16; - } - - BufferAllocated work; - }; - - class CompressLZ4 : public CompressLZ4Base - { - // magic number for LZ4 compression - enum { - LZ4_COMPRESS = 0x69, - }; - - public: - CompressLZ4(const Frame::Ptr& frame, const SessionStats::Ptr& stats, const bool asym_arg) - : CompressLZ4Base(frame, stats), - asym(asym_arg) - { - OPENVPN_LOG_COMPRESS("LZ4 init asym=" << asym_arg); - } - - virtual const char *name() const { return "lz4"; } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - if (hint && !asym) - { - if (do_compress(buf)) - { - do_swap(buf, LZ4_COMPRESS); - return; - } - } - - // indicate that we didn't compress - do_swap(buf, NO_COMPRESS_SWAP); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const unsigned char c = buf.pop_front(); - switch (c) - { - case NO_COMPRESS_SWAP: - do_unswap(buf); - break; - case LZ4_COMPRESS: - do_unswap(buf); - do_decompress(buf); - break; - default: - error(buf); // unknown op - } - } - - private: - const bool asym; - }; - - class CompressLZ4v2 : public CompressLZ4Base - { - public: - CompressLZ4v2(const Frame::Ptr& frame, const SessionStats::Ptr& stats, const bool asym_arg) - : CompressLZ4Base(frame, stats), - asym(asym_arg) - { - OPENVPN_LOG_COMPRESS("LZ4v2 init asym=" << asym_arg); - } - - virtual const char *name() const { return "lz4v2"; } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - if (hint && !asym) - { - if (do_compress(buf)) - { - v2_push(buf, OVPN_COMPv2_LZ4); - return; - } - } - - // indicate that we didn't compress - v2_push(buf, OVPN_COMPv2_NONE); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const int c = v2_pull(buf); - switch (c) - { - case OVPN_COMPv2_NONE: - break; - case OVPN_COMPv2_LZ4: - do_decompress(buf); - break; - default: - error(buf); // unknown op - } - } - - private: - const bool asym; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/compress/lzo.hpp b/Sources/OpenVPN3/openvpn/compress/lzo.hpp deleted file mode 100644 index 668a9fc..0000000 --- a/Sources/OpenVPN3/openvpn/compress/lzo.hpp +++ /dev/null @@ -1,169 +0,0 @@ -// 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-2020 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_COMPRESS_LZO_H -#define OPENVPN_COMPRESS_LZO_H - -// Implement LZO compression. -// Should only be included by lzoselect.hpp - -#include "lzo/lzoutil.h" -#include "lzo/lzo1x.h" - -namespace openvpn { - - class CompressLZO : public Compress - { - public: - // magic number for LZO compression - enum { - LZO_COMPRESS = 0x66, - LZO_COMPRESS_SWAP = 0x67, - }; - - OPENVPN_SIMPLE_EXCEPTION(lzo_init_failed); - - CompressLZO(const Frame::Ptr& frame, - const SessionStats::Ptr& stats, - const bool support_swap_arg, - const bool asym_arg) - : Compress(frame, stats), - support_swap(support_swap_arg), - asym(asym_arg) - { - OPENVPN_LOG_COMPRESS("LZO init swap=" << support_swap_arg << " asym=" << asym_arg); - lzo_workspace.init(LZO1X_1_15_MEM_COMPRESS, BufferAllocated::ARRAY); - } - - static void init_static() - { - if (::lzo_init() != LZO_E_OK) - throw lzo_init_failed(); - } - - virtual const char *name() const { return "lzo"; } - - void decompress_work(BufferAllocated& buf) - { - // initialize work buffer - lzo_uint zlen = frame->prepare(Frame::DECOMPRESS_WORK, work); - - // do uncompress - const int err = lzo1x_decompress_safe(buf.c_data(), buf.size(), work.data(), &zlen, lzo_workspace.data()); - if (err != LZO_E_OK) - { - error(buf); - return; - } - OPENVPN_LOG_COMPRESS_VERBOSE("LZO uncompress " << buf.size() << " -> " << zlen); - work.set_size(zlen); - buf.swap(work); - } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - if (hint && !asym) - { - // initialize work buffer - frame->prepare(Frame::COMPRESS_WORK, work); - - // verify that input data length is not too large - if (lzo_extra_buffer(buf.size()) > work.max_size()) - { - error(buf); - return; - } - - // do compress - lzo_uint zlen = 0; - const int err = ::lzo1x_1_15_compress(buf.c_data(), buf.size(), work.data(), &zlen, lzo_workspace.data()); - - // check for errors - if (err != LZO_E_OK) - { - error(buf); - return; - } - - // did compression actually reduce data length? - if (zlen < buf.size()) - { - OPENVPN_LOG_COMPRESS_VERBOSE("LZO compress " << buf.size() << " -> " << zlen); - work.set_size(zlen); - if (support_swap) - do_swap(work, LZO_COMPRESS_SWAP); - else - work.push_front(LZO_COMPRESS); - buf.swap(work); - return; - } - } - - // indicate that we didn't compress - if (support_swap) - do_swap(buf, NO_COMPRESS_SWAP); - else - buf.push_front(NO_COMPRESS); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const unsigned char c = buf.pop_front(); - switch (c) - { - case NO_COMPRESS_SWAP: - do_unswap(buf); - case NO_COMPRESS: - break; - case LZO_COMPRESS_SWAP: - do_unswap(buf); - case LZO_COMPRESS: - decompress_work(buf); - break; - default: - error(buf); // unknown op - } - } - - private: - // worst case size expansion on compress - size_t lzo_extra_buffer(const size_t len) - { - return len + len/8 + 128 + 3; - } - - const bool support_swap; - const bool asym; - BufferAllocated work; - BufferAllocated lzo_workspace; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_LZO_H diff --git a/Sources/OpenVPN3/openvpn/compress/lzoasym.hpp b/Sources/OpenVPN3/openvpn/compress/lzoasym.hpp deleted file mode 100644 index d96ac1c..0000000 --- a/Sources/OpenVPN3/openvpn/compress/lzoasym.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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_COMPRESS_LZOASYM_H -#define OPENVPN_COMPRESS_LZOASYM_H - -#include <openvpn/compress/lzoasym_impl.hpp> - -// Implement asymmetrical LZO compression (only uncompress, don't compress) -// Should only be included by lzoselect.hpp - -namespace openvpn { - - class CompressLZOAsym : public Compress - { - public: - // magic number for LZO compression - enum { - LZO_COMPRESS = 0x66, - LZO_COMPRESS_SWAP = 0x67, - }; - - OPENVPN_SIMPLE_EXCEPTION(lzo_init_failed); - - CompressLZOAsym(const Frame::Ptr& frame, - const SessionStats::Ptr& stats, - const bool support_swap_arg, - const bool asym_arg) // we are always asymmetrical, regardless of setting - : Compress(frame, stats), - support_swap(support_swap_arg) - { - OPENVPN_LOG_COMPRESS("LZO-ASYM init swap=" << support_swap_arg << " asym=" << asym_arg); - } - - static void init_static() - { - } - - virtual const char *name() const { return "lzo-asym"; } - - void decompress_work(BufferAllocated& buf) - { - // initialize work buffer - size_t zlen = frame->prepare(Frame::DECOMPRESS_WORK, work); - - // do uncompress - const int err = lzo_asym_impl::lzo1x_decompress_safe(buf.c_data(), buf.size(), work.data(), &zlen); - if (err != lzo_asym_impl::LZOASYM_E_OK) - { - error(buf); - return; - } - OPENVPN_LOG_COMPRESS_VERBOSE("LZO-ASYM uncompress " << buf.size() << " -> " << zlen); - work.set_size(zlen); - buf.swap(work); - } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - // indicate that we didn't compress - if (support_swap) - do_swap(buf, NO_COMPRESS_SWAP); - else - buf.push_front(NO_COMPRESS); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const unsigned char c = buf.pop_front(); - switch (c) - { - case NO_COMPRESS_SWAP: - do_unswap(buf); - case NO_COMPRESS: - break; - case LZO_COMPRESS_SWAP: - do_unswap(buf); - case LZO_COMPRESS: - decompress_work(buf); - break; - default: - error(buf); // unknown op - } - } - - private: - const bool support_swap; - BufferAllocated work; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_LZOASYM_H diff --git a/Sources/OpenVPN3/openvpn/compress/lzoasym_impl.hpp b/Sources/OpenVPN3/openvpn/compress/lzoasym_impl.hpp deleted file mode 100644 index d7583ee..0000000 --- a/Sources/OpenVPN3/openvpn/compress/lzoasym_impl.hpp +++ /dev/null @@ -1,345 +0,0 @@ -// 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-2020 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/>. - -// This is a special OpenVPN-specific implementation of LZO decompression. -// It is generally only used when OpenVPN is built without linkage to the -// actual LZO library, but where we want to maintain compatibility with -// peers that might send us LZO-compressed packets. -// -// It is significantly faster than LZO 2 on ARM because it makes heavy use -// of branch prediction hints. - -#ifndef OPENVPN_COMPRESS_LZOASYM_IMPL_H -#define OPENVPN_COMPRESS_LZOASYM_IMPL_H - -#include <cstdint> // for std::uint32_t, etc. -#include <cstring> // for memcpy, memmove -#include <algorithm> - -#include <openvpn/common/size.hpp> // for ssize_t -#include <openvpn/common/likely.hpp> // for likely/unlikely - -// Implementation of asymmetrical LZO compression (only uncompress, don't compress) - -// Branch prediction hints (these make a difference on ARM) -# define LZOASYM_LIKELY(x) likely(x) -# define LZOASYM_UNLIKELY(x) unlikely(x) - -// Failure modes -#define LZOASYM_CHECK_INPUT_OVERFLOW(x) if (LZOASYM_UNLIKELY(int(input_ptr_end - input_ptr) < int(x))) goto input_overflow -#define LZOASYM_CHECK_OUTPUT_OVERFLOW(x) if (LZOASYM_UNLIKELY(int(output_ptr_end - output_ptr) < int(x))) goto output_overflow -#define LZOASYM_CHECK_MATCH_OVERFLOW(match_ptr) if (LZOASYM_UNLIKELY(match_ptr < output) || LZOASYM_UNLIKELY(match_ptr >= output_ptr)) goto match_overflow -#define LZOASYM_ASSERT(cond) if (LZOASYM_UNLIKELY(!(cond))) goto assert_fail - -namespace openvpn { - namespace lzo_asym_impl { - // Return status values - enum { - LZOASYM_E_OK=0, - LZOASYM_E_EOF_NOT_FOUND=-1, - LZOASYM_E_INPUT_NOT_CONSUMED=-2, - LZOASYM_E_INPUT_OVERFLOW=-3, - LZOASYM_E_OUTPUT_OVERFLOW=-4, - LZOASYM_E_MATCH_OVERFLOW=-5, - LZOASYM_E_ASSERT_FAILED=-6, - LZOASYM_E_INPUT_TOO_LARGE=-7, - }; - - // Internal constants - enum { - LZOASYM_EOF_CODE=1, - LZOASYM_M2_MAX_OFFSET=0x0800, - }; - - // Polymorphic get/set/copy - - template <typename T> - inline T get_mem(const void *p) - { - typedef volatile const T* cptr; - return *cptr(p); - } - - // take the number of objects difference between two pointers - template <typename T> - inline size_t ptr_diff(const T* a, const T* b) - { - return a - b; - } - - // read uint16_t from memory - inline size_t get_u16(const unsigned char *p) - { - // NOTE: assumes little-endian and unaligned 16-bit access is okay. - // For a slower alternative without these assumptions, try: p[0] | (p[1] << 8) - return get_mem<std::uint16_t>(p); - } - - /** - * This function emulates copying bytes one by one from src to dest. - * if src+len and dest+len overlap it repeats the non-overlapping - * section of src until it copied 'len' bytes - * - * A slow simple version of this method looks like this: - * - * do { - * *dest++ = *src++; - * } while (--len); - * - * @param src Source of the memory - * @param dest Destination of the memory, must be >= src - * @param len Number of bytes to copy from src to dest - */ - inline void incremental_copy(unsigned char* dest, const unsigned char* src, ssize_t len) - { - size_t copylen = dest - src; - while (len > 0) - { - memcpy(dest, src, std::min((size_t)len, (size_t)copylen)); - dest += copylen; - len -= copylen; - - /* we can double copylen every time - * we copied the pattern */ - copylen = copylen * 2; - } - } - - - - inline int lzo1x_decompress_safe(const unsigned char *input, - size_t input_length, - unsigned char *output, - size_t *output_length) - { - size_t z; - const unsigned char *input_ptr; - unsigned char *output_ptr; - const unsigned char *match_ptr; - const unsigned char *const input_ptr_end = input + input_length; - unsigned char *const output_ptr_end = output + *output_length; - - *output_length = 0; - - input_ptr = input; - output_ptr = output; - - if (LZOASYM_UNLIKELY(input_length > 65536)) // quick fix to prevent 16MB integer overflow vulnerability - goto input_too_large; - - if (LZOASYM_LIKELY(*input_ptr <= 17)) - { - while (LZOASYM_LIKELY(input_ptr < input_ptr_end) && LZOASYM_LIKELY(output_ptr <= output_ptr_end)) - { - z = *input_ptr++; - if (z < 16) // literal data? - { - if (LZOASYM_UNLIKELY(z == 0)) - { - LZOASYM_CHECK_INPUT_OVERFLOW(1); - while (LZOASYM_UNLIKELY(*input_ptr == 0)) - { - z += 255; - input_ptr++; - LZOASYM_CHECK_INPUT_OVERFLOW(1); - } - z += 15 + *input_ptr++; - } - - // copy literal data - { - LZOASYM_ASSERT(z > 0); - const size_t len = z + 3; - LZOASYM_CHECK_OUTPUT_OVERFLOW(len); - LZOASYM_CHECK_INPUT_OVERFLOW(len+1); - memcpy(output_ptr, input_ptr, len); - input_ptr += len; - output_ptr += len; - } - - initial_literal: - z = *input_ptr++; - if (LZOASYM_UNLIKELY(z < 16)) - { - match_ptr = output_ptr - (1 + LZOASYM_M2_MAX_OFFSET); - match_ptr -= z >> 2; - match_ptr -= *input_ptr++ << 2; - - LZOASYM_CHECK_MATCH_OVERFLOW(match_ptr); - LZOASYM_CHECK_OUTPUT_OVERFLOW(3); - *output_ptr++ = *match_ptr++; - *output_ptr++ = *match_ptr++; - *output_ptr++ = *match_ptr; - goto match_complete; - } - } - - // found a match (M2, M3, M4, or M1) - do { - if (LZOASYM_LIKELY(z >= 64)) // LZO "M2" match (most likely) - { - match_ptr = output_ptr - 1; - match_ptr -= (z >> 2) & 7; - match_ptr -= *input_ptr++ << 3; - z = (z >> 5) - 1; - } - else if (LZOASYM_LIKELY(z >= 32)) // LZO "M3" match - { - z &= 31; - if (LZOASYM_UNLIKELY(z == 0)) - { - LZOASYM_CHECK_INPUT_OVERFLOW(1); - while (LZOASYM_UNLIKELY(*input_ptr == 0)) - { - z += 255; - input_ptr++; - LZOASYM_CHECK_INPUT_OVERFLOW(1); - } - z += 31 + *input_ptr++; - } - - match_ptr = output_ptr - 1; - match_ptr -= get_u16(input_ptr) >> 2; - input_ptr += 2; - } - else if (LZOASYM_LIKELY(z >= 16)) // LZO "M4" match - { - match_ptr = output_ptr; - match_ptr -= (z & 8) << 11; - z &= 7; - if (LZOASYM_UNLIKELY(z == 0)) - { - LZOASYM_CHECK_INPUT_OVERFLOW(1); - while (LZOASYM_UNLIKELY(*input_ptr == 0)) - { - z += 255; - input_ptr++; - LZOASYM_CHECK_INPUT_OVERFLOW(1); - } - z += 7 + *input_ptr++; - } - - match_ptr -= get_u16(input_ptr) >> 2; - input_ptr += 2; - if (LZOASYM_UNLIKELY(match_ptr == output_ptr)) - goto success; - match_ptr -= 0x4000; - } - else // LZO "M1" match (least likely) - { - match_ptr = output_ptr - 1; - match_ptr -= z >> 2; - match_ptr -= *input_ptr++ << 2; - - LZOASYM_CHECK_MATCH_OVERFLOW(match_ptr); - LZOASYM_CHECK_OUTPUT_OVERFLOW(2); - *output_ptr++ = *match_ptr++; - *output_ptr++ = *match_ptr; - goto match_complete; - } - - // copy the match we found above - { - LZOASYM_CHECK_MATCH_OVERFLOW(match_ptr); - LZOASYM_ASSERT(z > 0); - LZOASYM_CHECK_OUTPUT_OVERFLOW(z+3-1); - - const size_t len = z + 2; - incremental_copy(output_ptr, match_ptr, len); - match_ptr += len; - output_ptr += len; - } - - match_complete: - z = input_ptr[-2] & 3; - if (LZOASYM_LIKELY(z == 0)) - break; - - match_continue: - // copy literal data - LZOASYM_ASSERT(z > 0); - LZOASYM_ASSERT(z < 4); - LZOASYM_CHECK_OUTPUT_OVERFLOW(z); - LZOASYM_CHECK_INPUT_OVERFLOW(z+1); - *output_ptr++ = *input_ptr++; - if (LZOASYM_LIKELY(z > 1)) - { - *output_ptr++ = *input_ptr++; - if (z > 2) - *output_ptr++ = *input_ptr++; - } - z = *input_ptr++; - } while (LZOASYM_LIKELY(input_ptr < input_ptr_end) && LZOASYM_LIKELY(output_ptr <= output_ptr_end)); - } - } - else - { - // input began with a match or a literal (rare) - z = *input_ptr++ - 17; - if (z < 4) - goto match_continue; - LZOASYM_ASSERT(z > 0); - LZOASYM_CHECK_OUTPUT_OVERFLOW(z); - LZOASYM_CHECK_INPUT_OVERFLOW(z+1); - do { - *output_ptr++ = *input_ptr++; - } while (--z > 0); - goto initial_literal; - } - - *output_length = ptr_diff(output_ptr, output); - return LZOASYM_E_EOF_NOT_FOUND; - - success: - LZOASYM_ASSERT(z == 1); - *output_length = ptr_diff(output_ptr, output); - return (input_ptr == input_ptr_end ? LZOASYM_E_OK : - (input_ptr < input_ptr_end ? LZOASYM_E_INPUT_NOT_CONSUMED : LZOASYM_E_INPUT_OVERFLOW)); - - input_overflow: - *output_length = ptr_diff(output_ptr, output); - return LZOASYM_E_INPUT_OVERFLOW; - - output_overflow: - *output_length = ptr_diff(output_ptr, output); - return LZOASYM_E_OUTPUT_OVERFLOW; - - match_overflow: - *output_length = ptr_diff(output_ptr, output); - return LZOASYM_E_MATCH_OVERFLOW; - - assert_fail: - return LZOASYM_E_ASSERT_FAILED; - - input_too_large: - return LZOASYM_E_INPUT_TOO_LARGE; - } - } -} - -#undef LZOASYM_CHECK_INPUT_OVERFLOW -#undef LZOASYM_CHECK_OUTPUT_OVERFLOW -#undef LZOASYM_CHECK_MATCH_OVERFLOW -#undef LZOASYM_ASSERT -#undef LZOASYM_LIKELY -#undef LZOASYM_UNLIKELY - -#endif diff --git a/Sources/OpenVPN3/openvpn/compress/lzoselect.hpp b/Sources/OpenVPN3/openvpn/compress/lzoselect.hpp deleted file mode 100644 index d9ed94a..0000000 --- a/Sources/OpenVPN3/openvpn/compress/lzoselect.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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-2020 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/>. - -// If we are linked with the LZO library, use it. Otherwise default -// to an intrinstic LZO implementation that only handles decompression. - -#ifndef OPENVPN_COMPRESS_LZOSELECT_H -#define OPENVPN_COMPRESS_LZOSELECT_H - -#if defined(HAVE_LZO) -#include <openvpn/compress/lzo.hpp> -#else -#include <openvpn/compress/lzoasym.hpp> -#endif - -namespace openvpn { -#if !defined(HAVE_LZO) - typedef CompressLZOAsym CompressLZO; -#endif -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/compress/snappy.hpp b/Sources/OpenVPN3/openvpn/compress/snappy.hpp deleted file mode 100644 index bfd2a74..0000000 --- a/Sources/OpenVPN3/openvpn/compress/snappy.hpp +++ /dev/null @@ -1,136 +0,0 @@ -// 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-2020 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_COMPRESS_SNAPPY_H -#define OPENVPN_COMPRESS_SNAPPY_H - -// Implement Snappy compression. -// Should only be included by compress.hpp - -#include <snappy.h> - -namespace openvpn { - - class CompressSnappy : public Compress - { - // magic number for Snappy compression - enum { - SNAPPY_COMPRESS = 0x68, - }; - - public: - CompressSnappy(const Frame::Ptr& frame, const SessionStats::Ptr& stats, const bool asym_arg) - : Compress(frame, stats), - asym(asym_arg) - { - OPENVPN_LOG_COMPRESS("SNAPPY init asym=" << asym_arg); - } - - virtual const char *name() const { return "snappy"; } - - virtual void compress(BufferAllocated& buf, const bool hint) - { - // skip null packets - if (!buf.size()) - return; - - if (hint && !asym) - { - // initialize work buffer - frame->prepare(Frame::COMPRESS_WORK, work); - - // verify that input data length is not too large - if (snappy::MaxCompressedLength(buf.size()) > work.max_size()) - { - error(buf); - return; - } - - // do compress - size_t comp_size; - snappy::RawCompress((const char *)buf.c_data(), buf.size(), (char *)work.data(), &comp_size); - - // did compression actually reduce data length? - if (comp_size < buf.size()) - { - OPENVPN_LOG_COMPRESS_VERBOSE("SNAPPY compress " << buf.size() << " -> " << comp_size); - work.set_size(comp_size); - do_swap(work, SNAPPY_COMPRESS); - buf.swap(work); - return; - } - } - - // indicate that we didn't compress - do_swap(buf, NO_COMPRESS_SWAP); - } - - virtual void decompress(BufferAllocated& buf) - { - // skip null packets - if (!buf.size()) - return; - - const unsigned char c = buf.pop_front(); - switch (c) - { - case NO_COMPRESS_SWAP: - do_unswap(buf); - break; - case SNAPPY_COMPRESS: - { - do_unswap(buf); - - // initialize work buffer - const size_t payload_size = frame->prepare(Frame::DECOMPRESS_WORK, work); - - // do uncompress - size_t decomp_size; - if (!snappy::GetUncompressedLength((const char *)buf.c_data(), buf.size(), &decomp_size) - || decomp_size > payload_size) - { - error(buf); - break; - } - if (!snappy::RawUncompress((const char *)buf.c_data(), buf.size(), (char *)work.data())) - { - error(buf); - break; - } - OPENVPN_LOG_COMPRESS_VERBOSE("SNAPPY uncompress " << buf.size() << " -> " << decomp_size); - work.set_size(decomp_size); - buf.swap(work); - } - break; - default: - error(buf); // unknown op - break; - } - } - - private: - const bool asym; - BufferAllocated work; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMPRESS_SNAPPY_H diff --git a/Sources/OpenVPN3/openvpn/crypto/bs64_data_limit.hpp b/Sources/OpenVPN3/openvpn/crypto/bs64_data_limit.hpp deleted file mode 100644 index 6749c36..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/bs64_data_limit.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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/>. - -// Special data limits on Blowfish, Triple DES, and other 64-bit -// block-size ciphers vulnerable to "Sweet32" birthday attack -// (CVE-2016-6329). Limit such cipher keys to no more than 64 MB -// of data encrypted/decrypted. Note that we trigger early at -// 48 MB to compensate for possible delays in renegotiation and -// rollover to the new key. - -#ifndef OPENVPN_CRYPTO_DATALIMIT_H -#define OPENVPN_CRYPTO_DATALIMIT_H - -#include <openvpn/crypto/cryptoalgs.hpp> - -#ifndef OPENVPN_BS64_DATA_LIMIT -#define OPENVPN_BS64_DATA_LIMIT 48000000 -#endif - -namespace openvpn { - inline bool is_bs64_cipher(const CryptoAlgs::Type cipher) - { - return CryptoAlgs::get(cipher).block_size() == 8; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/cipher.hpp b/Sources/OpenVPN3/openvpn/crypto/cipher.hpp deleted file mode 100644 index 7bb3aa5..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/cipher.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// 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-2020 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/>. - -// General-purpose cipher classes that are independent of the underlying CRYPTO_API - -#ifndef OPENVPN_CRYPTO_CIPHER_H -#define OPENVPN_CRYPTO_CIPHER_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> - -namespace openvpn { - template <typename CRYPTO_API> - class CipherContext - { - public: - OPENVPN_SIMPLE_EXCEPTION(cipher_mode_error); - OPENVPN_SIMPLE_EXCEPTION(cipher_uninitialized); - OPENVPN_SIMPLE_EXCEPTION(cipher_init_insufficient_key_material); - OPENVPN_SIMPLE_EXCEPTION(cipher_internal_error); - OPENVPN_SIMPLE_EXCEPTION(cipher_output_buffer); - - public: - CipherContext() : mode_(CRYPTO_API::CipherContext::MODE_UNDEF) {} - - CipherContext(const CryptoAlgs::Type cipher, const StaticKey& key, const int mode) - : mode_(CRYPTO_API::CipherContext::MODE_UNDEF) - { - init(cipher, key, mode); - } - - bool defined() const { return ctx.is_initialized(); } - - // size of iv buffer to pass to encrypt_decrypt - size_t iv_length() const - { - return ctx.iv_length(); - } - - // cipher mode (such as CIPH_CBC_MODE, etc.) - int cipher_mode() const - { - return ctx.cipher_mode(); - } - - // size of out buffer to pass to encrypt_decrypt - size_t output_size(const size_t in_size) const - { - return in_size + ctx.block_size(); - } - - void init(const CryptoAlgs::Type cipher, const StaticKey& key, const int mode) - { - const CryptoAlgs::Alg& alg = CryptoAlgs::get(cipher); - - // check that provided key is large enough - if (key.size() < alg.key_length()) - throw cipher_init_insufficient_key_material(); - - // IV consistency check - if (alg.iv_length() > CRYPTO_API::CipherContext::MAX_IV_LENGTH) - throw cipher_internal_error(); - - // initialize cipher context with cipher type, key, and encrypt/decrypt mode - ctx.init(cipher, key.data(), mode); - - // save mode in object - mode_ = mode; - } - - size_t encrypt(const unsigned char *iv, - unsigned char *out, const size_t out_size, - const unsigned char *in, const size_t in_size) - { - if (mode_ != CRYPTO_API::CipherContext::ENCRYPT) - throw cipher_mode_error(); - return encrypt_decrypt(iv, out, out_size, in, in_size); - } - - size_t decrypt(const unsigned char *iv, - unsigned char *out, const size_t out_size, - const unsigned char *in, const size_t in_size) - { - if (mode_ != CRYPTO_API::CipherContext::DECRYPT) - throw cipher_mode_error(); - return encrypt_decrypt(iv, out, out_size, in, in_size); - } - - size_t encrypt_decrypt(const unsigned char *iv, - unsigned char *out, const size_t out_size, - const unsigned char *in, const size_t in_size) - { - if (out_size < output_size(in_size)) - throw cipher_output_buffer(); - ctx.reset(iv); - size_t outlen = 0; - if (!ctx.update(out, out_size, in, in_size, outlen)) - return 0; - if (!ctx.final(out + outlen, out_size - outlen, outlen)) - return 0; - return outlen; - } - - private: - int mode_; - typename CRYPTO_API::CipherContext ctx; - }; - -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_CIPHER_H diff --git a/Sources/OpenVPN3/openvpn/crypto/crypto_aead.hpp b/Sources/OpenVPN3/openvpn/crypto/crypto_aead.hpp deleted file mode 100644 index f5952fe..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/crypto_aead.hpp +++ /dev/null @@ -1,363 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN AEAD data channel interface - -#ifndef OPENVPN_CRYPTO_CRYPTO_AEAD_H -#define OPENVPN_CRYPTO_CRYPTO_AEAD_H - -#include <cstring> // for std::memcpy, std::memset - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/crypto/cryptodc.hpp> - -// Sample AES-GCM head: -// 48000001 00000005 7e7046bd 444a7e28 cc6387b1 64a4d6c1 380275a... -// [ OP32 ] [seq # ] [ auth tag ] [ payload ... ] -// [4-byte -// IV head] - -namespace openvpn { - namespace AEAD { - - OPENVPN_EXCEPTION(aead_error); - - /** - * Check if a specific algorithm is support or not in the underlying - * crypto library - */ - template <typename CRYPTO_API> - static inline bool is_algorithm_supported(const CryptoAlgs::Type cipher) - { - return CRYPTO_API::CipherContextAEAD::is_supported(cipher); - } - - template <typename CRYPTO_API> - class Crypto : public CryptoDCInstance - { - class Nonce { - public: - Nonce() - { - static_assert(4 + CRYPTO_API::CipherContextAEAD::IV_LEN == sizeof(data), - "AEAD IV_LEN inconsistency"); - ad_op32 = false; - std::memset(data, 0, sizeof(data)); - } - - // setup - void set_tail(const StaticKey& sk) - { - if (sk.size() < 8) - throw aead_error("insufficient key material for nonce tail"); - std::memcpy(data + 8, sk.data(), 8); - } - - // for encrypt - Nonce(const Nonce& ref, PacketIDSend& pid_send, const PacketID::time_t now, - const unsigned char *op32) - { - std::memcpy(data, ref.data, sizeof(data)); - Buffer buf(data + 4, 4, false); - pid_send.write_next(buf, false, now); - if (op32) - { - ad_op32 = true; - std::memcpy(data, op32, 4); - } - else - ad_op32 = false; - } - - // for encrypt - void prepend_ad(Buffer& buf) const - { - buf.prepend(data + 4, 4); - } - - // for decrypt - Nonce(const Nonce& ref, Buffer& buf, const unsigned char *op32) - { - std::memcpy(data, ref.data, sizeof(data)); - buf.read(data + 4, 4); - if (op32) - { - ad_op32 = true; - std::memcpy(data, op32, 4); - } - else - ad_op32 = false; - } - - // for decrypt - bool verify_packet_id(PacketIDReceive& pid_recv, const PacketID::time_t now) - { - Buffer buf(data + 4, 4, true); - const PacketID pid = pid_recv.read_next(buf); - return pid_recv.test_add(pid, now, true); // verify packet ID - } - - const unsigned char *iv() const - { - return data + 4; - } - - const unsigned char *ad() const - { - return ad_op32 ? data : data + 4; - } - - const size_t ad_len() const - { - return ad_op32 ? 8 : 4; - } - - private: - bool ad_op32; // true if AD includes op32 opcode - - // Sample data: - // [ OP32 (optional) ] [ pkt ID ] [ nonce tail ] - // [ 48 00 00 01 ] [ 00 00 00 05 ] [ 7f 45 64 db 33 5b 6c 29 ] - unsigned char data[16]; - }; - - struct Encrypt { - typename CRYPTO_API::CipherContextAEAD impl; - Nonce nonce; - PacketIDSend pid_send; - BufferAllocated work; - }; - - struct Decrypt { - typename CRYPTO_API::CipherContextAEAD impl; - Nonce nonce; - PacketIDReceive pid_recv; - BufferAllocated work; - }; - public: - typedef CryptoDCInstance Base; - - Crypto(const CryptoAlgs::Type cipher_arg, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg) - : cipher(cipher_arg), - frame(frame_arg), - stats(stats_arg) - { - } - - // Encrypt/Decrypt - - // returns true if packet ID is close to wrapping - virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) - { - // only process non-null packets - if (buf.size()) - { - // build nonce/IV/AD - Nonce nonce(e.nonce, e.pid_send, now, op32); - - if (CRYPTO_API::CipherContextAEAD::SUPPORTS_IN_PLACE_ENCRYPT) - { - unsigned char *data = buf.data(); - const size_t size = buf.size(); - - // alloc auth tag in buffer - unsigned char *auth_tag = buf.prepend_alloc(CRYPTO_API::CipherContextAEAD::AUTH_TAG_LEN); - - // encrypt in-place - e.impl.encrypt(data, data, size, nonce.iv(), auth_tag, nonce.ad(), nonce.ad_len()); - } - else - { - // encrypt to work buf - frame->prepare(Frame::ENCRYPT_WORK, e.work); - if (e.work.max_size() < buf.size()) - throw aead_error("encrypt work buffer too small"); - - // alloc auth tag in buffer - unsigned char *auth_tag = e.work.prepend_alloc(CRYPTO_API::CipherContextAEAD::AUTH_TAG_LEN); - - // prepare output buffer - unsigned char *work_data = e.work.write_alloc(buf.size()); - - // encrypt - e.impl.encrypt(buf.data(), work_data, buf.size(), nonce.iv(), auth_tag, nonce.ad(), nonce.ad_len()); - buf.swap(e.work); - } - - // prepend additional data - nonce.prepend_ad(buf); - } - return e.pid_send.wrap_warning(); - } - - virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) - { - // only process non-null packets - if (buf.size()) - { - // get nonce/IV/AD - Nonce nonce(d.nonce, buf, op32); - - // get auth tag - unsigned char *auth_tag = buf.read_alloc(CRYPTO_API::CipherContextAEAD::AUTH_TAG_LEN); - - // initialize work buffer - frame->prepare(Frame::DECRYPT_WORK, d.work); - if (d.work.max_size() < buf.size()) - throw aead_error("decrypt work buffer too small"); - - // decrypt from buf -> work - if (!d.impl.decrypt(buf.c_data(), d.work.data(), buf.size(), nonce.iv(), auth_tag, - nonce.ad(), nonce.ad_len())) - { - buf.reset_size(); - return Error::DECRYPT_ERROR; - } - d.work.set_size(buf.size()); - - // verify packet ID - if (!nonce.verify_packet_id(d.pid_recv, now)) - { - buf.reset_size(); - return Error::REPLAY_ERROR; - } - - // return cleartext result in buf - buf.swap(d.work); - } - return Error::SUCCESS; - } - - // Initialization - - virtual void init_cipher(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) - { - e.impl.init(cipher, encrypt_key.data(), encrypt_key.size(), CRYPTO_API::CipherContextAEAD::ENCRYPT); - d.impl.init(cipher, decrypt_key.data(), decrypt_key.size(), CRYPTO_API::CipherContextAEAD::DECRYPT); - } - - virtual void init_hmac(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) - { - e.nonce.set_tail(encrypt_key); - d.nonce.set_tail(decrypt_key); - } - - virtual void init_pid(const int send_form, - const int recv_mode, - const int recv_form, - const char *recv_name, - const int recv_unit, - const SessionStats::Ptr& recv_stats_arg) - { - e.pid_send.init(send_form); - d.pid_recv.init(recv_mode, recv_form, recv_name, recv_unit, recv_stats_arg); - } - - // Indicate whether or not cipher/digest is defined - - virtual unsigned int defined() const - { - unsigned int ret = CRYPTO_DEFINED; - - // AEAD mode doesn't use HMAC, but we still indicate HMAC_DEFINED - // because we want to use the HMAC keying material for the AEAD nonce tail. - if (CryptoAlgs::defined(cipher)) - ret |= (CIPHER_DEFINED|HMAC_DEFINED); - return ret; - } - - virtual bool consider_compression(const CompressContext& comp_ctx) - { - return true; - } - - // Rekeying - - virtual void rekey(const typename Base::RekeyType type) - { - } - - private: - CryptoAlgs::Type cipher; - Frame::Ptr frame; - SessionStats::Ptr stats; - Encrypt e; - Decrypt d; - }; - - template <typename CRYPTO_API> - class CryptoContext : public CryptoDCContext - { - public: - typedef RCPtr<CryptoContext> Ptr; - - CryptoContext(const CryptoAlgs::Type cipher_arg, - const CryptoAlgs::KeyDerivation key_method, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg) - : CryptoDCContext(key_method), - cipher(CryptoAlgs::legal_dc_cipher(cipher_arg)), - frame(frame_arg), - stats(stats_arg) - { - } - - virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) - { - return new Crypto<CRYPTO_API>(cipher, frame, stats); - } - - // cipher/HMAC/key info - virtual Info crypto_info() - { - Info ret; - ret.cipher_alg = cipher; - ret.hmac_alg = CryptoAlgs::NONE; - ret.key_derivation = key_derivation; - return ret; - } - - // Info for ProtoContext::link_mtu_adjust - - virtual size_t encap_overhead() const - { - return CRYPTO_API::CipherContextAEAD::AUTH_TAG_LEN; - } - - private: - CryptoAlgs::Type cipher; - Frame::Ptr frame; - SessionStats::Ptr stats; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/crypto_chm.hpp b/Sources/OpenVPN3/openvpn/crypto/crypto_chm.hpp deleted file mode 100644 index 7511023..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/crypto_chm.hpp +++ /dev/null @@ -1,185 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN CBC/HMAC data channel - -#ifndef OPENVPN_CRYPTO_CRYPTO_CHM_H -#define OPENVPN_CRYPTO_CRYPTO_CHM_H - -#include <openvpn/crypto/encrypt_chm.hpp> -#include <openvpn/crypto/decrypt_chm.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - template <typename CRYPTO_API> - class CryptoCHM : public CryptoDCInstance - { - public: - typedef CryptoDCInstance Base; - - CryptoCHM(const CryptoAlgs::Type cipher_arg, - const CryptoAlgs::Type digest_arg, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg, - const RandomAPI::Ptr& prng_arg) - : cipher(cipher_arg), - digest(digest_arg), - frame(frame_arg), - stats(stats_arg), - prng(prng_arg) - { - encrypt_.frame = frame; - decrypt_.frame = frame; - encrypt_.set_prng(prng); - } - - // Encrypt/Decrypt - - /* returns true if packet ID is close to wrapping */ - virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) - { - encrypt_.encrypt(buf, now); - return encrypt_.pid_send.wrap_warning(); - } - - virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) - { - return decrypt_.decrypt(buf, now); - } - - // Initialization - - virtual void init_cipher(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) - { - encrypt_.cipher.init(cipher, encrypt_key, CRYPTO_API::CipherContext::ENCRYPT); - decrypt_.cipher.init(cipher, decrypt_key, CRYPTO_API::CipherContext::DECRYPT); - } - - virtual void init_hmac(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) - { - encrypt_.hmac.init(digest, encrypt_key); - decrypt_.hmac.init(digest, decrypt_key); - } - - virtual void init_pid(const int send_form, - const int recv_mode, - const int recv_form, - const char *recv_name, - const int recv_unit, - const SessionStats::Ptr& recv_stats_arg) - { - encrypt_.pid_send.init(send_form); - decrypt_.pid_recv.init(recv_mode, recv_form, recv_name, recv_unit, recv_stats_arg); - } - - virtual bool consider_compression(const CompressContext& comp_ctx) - { - return true; - } - - // Indicate whether or not cipher/digest is defined - - virtual unsigned int defined() const - { - unsigned int ret = CRYPTO_DEFINED; - if (CryptoAlgs::defined(cipher)) - ret |= CIPHER_DEFINED; - if (CryptoAlgs::defined(digest)) - ret |= HMAC_DEFINED; - return ret; - } - - // Rekeying - - virtual void rekey(const typename Base::RekeyType type) - { - } - - private: - CryptoAlgs::Type cipher; - CryptoAlgs::Type digest; - Frame::Ptr frame; - SessionStats::Ptr stats; - RandomAPI::Ptr prng; - - EncryptCHM<CRYPTO_API> encrypt_; - DecryptCHM<CRYPTO_API> decrypt_; - }; - - template <typename CRYPTO_API> - class CryptoContextCHM : public CryptoDCContext - { - public: - typedef RCPtr<CryptoContextCHM> Ptr; - - CryptoContextCHM(const CryptoAlgs::Type cipher_arg, - const CryptoAlgs::Type digest_arg, - const CryptoAlgs::KeyDerivation key_method, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg, - const RandomAPI::Ptr& prng_arg) - : CryptoDCContext(key_method), - cipher(CryptoAlgs::legal_dc_cipher(cipher_arg)), - digest(CryptoAlgs::legal_dc_digest(digest_arg)), - frame(frame_arg), - stats(stats_arg), - prng(prng_arg) - { - } - - virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) - { - return new CryptoCHM<CRYPTO_API>(cipher, digest, frame, stats, prng); - } - - // cipher/HMAC/key info - virtual Info crypto_info() - { - Info ret; - ret.cipher_alg = cipher; - ret.hmac_alg = digest; - ret.key_derivation = key_derivation; - return ret; - } - - // Info for ProtoContext::link_mtu_adjust - - virtual size_t encap_overhead() const - { - return CryptoAlgs::size(digest) + // HMAC - CryptoAlgs::iv_length(cipher) + // Cipher IV - CryptoAlgs::block_size(cipher); // worst-case PKCS#7 padding expansion - } - - private: - CryptoAlgs::Type cipher; - CryptoAlgs::Type digest; - Frame::Ptr frame; - SessionStats::Ptr stats; - RandomAPI::Ptr prng; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/cryptoalgs.hpp b/Sources/OpenVPN3/openvpn/crypto/cryptoalgs.hpp deleted file mode 100644 index 12a63c9..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/cryptoalgs.hpp +++ /dev/null @@ -1,284 +0,0 @@ -// 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-2020 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/>. - -// Crypto algorithms - -#ifndef OPENVPN_CRYPTO_CRYPTOALGS_H -#define OPENVPN_CRYPTO_CRYPTOALGS_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/common/arraysize.hpp> - -namespace openvpn { - namespace CryptoAlgs { - - OPENVPN_EXCEPTION(crypto_alg); - OPENVPN_SIMPLE_EXCEPTION(crypto_alg_index); - - enum class KeyDerivation { - UNDEFINED, - OPENVPN_PRF, - TLS_EKM - }; - - inline const char* name(const KeyDerivation kd) - { - switch (kd) - { - case KeyDerivation::UNDEFINED: - return "[PRF undefined]"; - case KeyDerivation::OPENVPN_PRF: - return "OpenVPN PRF"; - case KeyDerivation::TLS_EKM: - return "TLS Keying Material Exporter [RFC5705]"; - default: - return "Unknown"; - } - } - - enum Type { - NONE=0, - - // CBC ciphers - AES_128_CBC, - AES_192_CBC, - AES_256_CBC, - DES_CBC, - DES_EDE3_CBC, - BF_CBC, - - // CTR ciphers - AES_256_CTR, - - // AEAD ciphers - AES_128_GCM, - AES_192_GCM, - AES_256_GCM, - CHACHA20_POLY1305, - - // digests - MD4, - MD5, - SHA1, - SHA224, - SHA256, - SHA384, - SHA512, - - SIZE, - }; - - enum Mode { - MODE_UNDEF=0, - CBC_HMAC, - AEAD, - MODE_MASK=0x03, - }; - - enum AlgFlags { // bits below must start after Mode bits - F_CIPHER=(1<<2), // alg is a cipher - F_DIGEST=(1<<3), // alg is a digest - F_ALLOW_DC=(1<<4), // alg may be used in OpenVPN data channel - F_NO_CIPHER_DIGEST=(1<<5), // cipher alg does not depend on any additional digest - }; - - // size in bytes of AEAD "nonce tail" normally taken from - // HMAC key material - enum { - AEAD_NONCE_TAIL_SIZE = 8 - }; - - class Alg - { - public: - constexpr Alg(const char *name, - const unsigned int flags, - const unsigned int size, - const unsigned int iv_length, - const unsigned int block_size) - - : name_(name), - flags_(flags), - size_(size), - iv_length_(iv_length), - block_size_(block_size) - { - } - - const char *name() const { return name_; } - unsigned int flags() const { return flags_; } // contains Mode and AlgFlags - Mode mode() const { return Mode(flags_ & MODE_MASK); } - size_t size() const { return size_; } // digest size - size_t key_length() const { return size_; } // cipher key length - size_t iv_length() const { return iv_length_; } // cipher only - size_t block_size() const { return block_size_; } // cipher only - - private: - const char *name_; - unsigned int flags_; - unsigned int size_; - unsigned int iv_length_; - unsigned int block_size_; - }; - - constexpr Alg algs[] = { // NOTE: MUST be indexed by CryptoAlgs::Type (CONST GLOBAL) - { "NONE", F_CIPHER|F_DIGEST|F_ALLOW_DC|CBC_HMAC, 0, 0, 0 }, - { "AES-128-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 16, 16, 16 }, - { "AES-192-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 24, 16, 16 }, - { "AES-256-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 32, 16, 16 }, - { "DES-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 8, 8, 8 }, - { "DES-EDE3-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 24, 8, 8 }, - { "BF-CBC", F_CIPHER|F_ALLOW_DC|CBC_HMAC, 16, 8, 8 }, - { "AES-256-CTR", F_CIPHER, 32, 16, 16 }, - { "AES-128-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 16, 12, 16 }, - { "AES-192-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 24, 12, 16 }, - { "AES-256-GCM", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, - { "CHACHA20-POLY1305", F_CIPHER|F_ALLOW_DC|AEAD|F_NO_CIPHER_DIGEST, 32, 12, 16 }, - { "MD4", F_DIGEST, 16, 0, 0 }, - { "MD5", F_DIGEST|F_ALLOW_DC, 16, 0, 0 }, - { "SHA1", F_DIGEST|F_ALLOW_DC, 20, 0, 0 }, - { "SHA224", F_DIGEST|F_ALLOW_DC, 28, 0, 0 }, - { "SHA256", F_DIGEST|F_ALLOW_DC, 32, 0, 0 }, - { "SHA384", F_DIGEST|F_ALLOW_DC, 48, 0, 0 }, - { "SHA512", F_DIGEST|F_ALLOW_DC, 64, 0, 0 }, - }; - - inline bool defined(const Type type) - { - return type != NONE; - } - - inline const Alg* get_index_ptr(const size_t i) - { - static_assert(SIZE == array_size(algs), "algs array inconsistency"); - if (unlikely(i >= SIZE)) - throw crypto_alg_index(); - return &algs[i]; - } - - inline const Alg& get_index(const size_t i) - { - return *get_index_ptr(i); - } - - inline const Alg* get_ptr(const Type type) - { - return get_index_ptr(static_cast<size_t>(type)); - } - - inline const Alg& get(const Type type) - { - return get_index(static_cast<size_t>(type)); - } - - inline Type lookup(const std::string& name) - { - for (size_t i = 0; i < SIZE; ++i) - { - const Alg& alg = algs[i]; - if (string::strcasecmp(name, alg.name()) == 0) - return static_cast<Type>(i); - } - OPENVPN_THROW(crypto_alg, name << ": not found"); - } - - inline const char *name(const Type type) - { - return get(type).name(); - } - - inline const char *name(const Type type, const char *default_name) - { - if (type == NONE) - return default_name; - else - return get(type).name(); - } - - inline size_t size(const Type type) - { - const Alg& alg = get(type); - return alg.size(); - } - - inline size_t key_length(const Type type) - { - const Alg& alg = get(type); - return alg.key_length(); - } - - inline size_t iv_length(const Type type) - { - const Alg& alg = get(type); - return alg.iv_length(); - } - - inline size_t block_size(const Type type) - { - const Alg& alg = get(type); - return alg.block_size(); - } - - inline Mode mode(const Type type) - { - const Alg& alg = get(type); - return alg.mode(); - } - - inline Type legal_dc_cipher(const Type type) - { - const Alg& alg = get(type); - if ((alg.flags() & (F_CIPHER|F_ALLOW_DC)) != (F_CIPHER|F_ALLOW_DC)) - OPENVPN_THROW(crypto_alg, alg.name() << ": bad cipher for data channel use"); - return type; - } - - inline Type legal_dc_digest(const Type type) - { - const Alg& alg = get(type); - if ((alg.flags() & (F_DIGEST|F_ALLOW_DC)) != (F_DIGEST|F_ALLOW_DC)) - OPENVPN_THROW(crypto_alg, alg.name() << ": bad digest for data channel use"); - return type; - } - - /** - * Check if a specific algorithm depends on an additional digest or not - * - * @param type CryptoAlgs::Type to check - * - * @return Returns true if the queried algorithm depends on a digest, - * otherwise false. The check is done strictly against the - * CryptoAlgs::AlgFlags F_NO_CIPHER_DIGEST flag. - */ - inline bool use_cipher_digest(const Type type) - { - const Alg& alg = get(type); - return !(alg.flags() & F_NO_CIPHER_DIGEST); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/cryptodc.hpp b/Sources/OpenVPN3/openvpn/crypto/cryptodc.hpp deleted file mode 100644 index 69e441a..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/cryptodc.hpp +++ /dev/null @@ -1,227 +0,0 @@ -// 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-2020 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/>. - -// Base class for OpenVPN data channel encryption/decryption - -#ifndef OPENVPN_CRYPTO_CRYPTODC_H -#define OPENVPN_CRYPTO_CRYPTODC_H - -#include <utility> // for std::move -#include <cstdint> // for std::uint32_t, etc. - -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/compress/compress.hpp> - -namespace openvpn { - - // Base class for encryption/decryption of data channel - class CryptoDCInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<CryptoDCInstance> Ptr; - - // Encrypt/Decrypt - - // returns true if packet ID is close to wrapping - virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) = 0; - - virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) = 0; - - // Initialization - - // return value of defined() - enum { - CIPHER_DEFINED=(1<<0), // may call init_cipher method - HMAC_DEFINED=(1<<1), // may call init_hmac method - CRYPTO_DEFINED=(1<<2), // may call encrypt or decrypt methods - EXPLICIT_EXIT_NOTIFY_DEFINED=(1<<3), // may call explicit_exit_notify method - }; - virtual unsigned int defined() const = 0; - - virtual void init_cipher(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) = 0; - - virtual void init_hmac(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) = 0; - - virtual void init_pid(const int send_form, - const int recv_mode, - const int recv_form, - const char *recv_name, - const int recv_unit, - const SessionStats::Ptr& recv_stats_arg) = 0; - - virtual void init_remote_peer_id(const int remote_peer_id) {} - - virtual bool consider_compression(const CompressContext& comp_ctx) = 0; - - virtual void explicit_exit_notify() {} - - // Rekeying - - enum RekeyType { - ACTIVATE_PRIMARY, - ACTIVATE_PRIMARY_MOVE, - NEW_SECONDARY, - PRIMARY_SECONDARY_SWAP, - DEACTIVATE_SECONDARY, - DEACTIVATE_ALL, - }; - - virtual void rekey(const RekeyType type) = 0; - }; - - // Factory for CryptoDCInstance objects - class CryptoDCContext : public RC<thread_unsafe_refcount> - { - public: - explicit CryptoDCContext(const CryptoAlgs::KeyDerivation method): key_derivation(method) {} - - typedef RCPtr<CryptoDCContext> Ptr; - - virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) = 0; - - // cipher/HMAC/key info - struct Info { - Info() {} - CryptoAlgs::Type cipher_alg = CryptoAlgs::NONE; - CryptoAlgs::Type hmac_alg = CryptoAlgs::NONE; - CryptoAlgs::KeyDerivation key_derivation = CryptoAlgs::KeyDerivation::OPENVPN_PRF; - }; - virtual Info crypto_info() = 0; - - // Info for ProtoContext::link_mtu_adjust - virtual size_t encap_overhead() const = 0; - protected: - CryptoAlgs::KeyDerivation key_derivation = CryptoAlgs::KeyDerivation::OPENVPN_PRF;; - }; - - // Factory for CryptoDCContext objects - class CryptoDCFactory : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<CryptoDCFactory> Ptr; - - virtual CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher, - const CryptoAlgs::Type digest, - const CryptoAlgs::KeyDerivation method) = 0; - }; - - // Manage cipher/digest settings, DC factory, and DC context. - class CryptoDCSettings - { - public: - OPENVPN_SIMPLE_EXCEPTION(no_data_channel_factory); - - CryptoDCSettings() - { - } - - void set_factory(const CryptoDCFactory::Ptr& factory) - { - factory_ = factory; - context_.reset(); - dirty = false; - } - - void set_cipher(const CryptoAlgs::Type cipher) - { - if (cipher != cipher_) - { - cipher_ = cipher; - dirty = true; - } - } - - void set_digest(const CryptoAlgs::Type digest) - { - if (digest != digest_) - { - digest_ = digest; - dirty = true; - } - } - - CryptoDCContext& context() - { - if (!context_ || dirty) - { - if (!factory_) - throw no_data_channel_factory(); - context_ = factory_->new_obj(cipher_, digest_, key_derivation_); - dirty = false; - } - return *context_; - } - - void reset() - { - factory_.reset(); - context_.reset(); - dirty = false; - } - - CryptoAlgs::Type cipher() const { return cipher_; } - - /** - * Retrieve the digest configured for the data channel. - * If the configured data channel cipher does not use any - * additional digest, CryptoAlgs::NONE is returned. - * - * @return Returns the cipher digest in use - */ - CryptoAlgs::Type digest() const - { - return (CryptoAlgs::use_cipher_digest(cipher_) ? digest_ : CryptoAlgs::NONE); - } - - - CryptoDCFactory::Ptr factory() const { return factory_; } - - void set_key_derivation(CryptoAlgs::KeyDerivation method) - { - key_derivation_ = method; - } - - CryptoAlgs::KeyDerivation key_derivation() const - { - return key_derivation_; - } - - private: - CryptoAlgs::Type cipher_ = CryptoAlgs::NONE; - CryptoAlgs::Type digest_ = CryptoAlgs::NONE; - CryptoAlgs::KeyDerivation key_derivation_ = CryptoAlgs::KeyDerivation::OPENVPN_PRF; - - CryptoDCFactory::Ptr factory_; - CryptoDCContext::Ptr context_; - bool dirty = false; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/cryptodcsel.hpp b/Sources/OpenVPN3/openvpn/crypto/cryptodcsel.hpp deleted file mode 100644 index de0567e..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/cryptodcsel.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// 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-2020 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/>. - -// Select appropriate OpenVPN protocol data channel implementation - -#ifndef OPENVPN_CRYPTO_CRYPTODCSEL_H -#define OPENVPN_CRYPTO_CRYPTODCSEL_H - -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/crypto/crypto_chm.hpp> -#include <openvpn/crypto/crypto_aead.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - OPENVPN_EXCEPTION(crypto_dc_select); - - template <typename CRYPTO_API> - class CryptoDCSelect : public CryptoDCFactory - { - public: - typedef RCPtr<CryptoDCSelect> Ptr; - - CryptoDCSelect(const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg, - const RandomAPI::Ptr& prng_arg) - : frame(frame_arg), - stats(stats_arg), - prng(prng_arg) - { - } - - virtual CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher, - const CryptoAlgs::Type digest, - const CryptoAlgs::KeyDerivation method) - { - const CryptoAlgs::Alg& alg = CryptoAlgs::get(cipher); - if (alg.flags() & CryptoAlgs::CBC_HMAC) - return new CryptoContextCHM<CRYPTO_API>(cipher, digest, method, frame, stats, prng); - else if (alg.flags() & CryptoAlgs::AEAD) - return new AEAD::CryptoContext<CRYPTO_API>(cipher, method, frame, stats); - else - OPENVPN_THROW(crypto_dc_select, alg.name() << ": only CBC/HMAC and AEAD cipher modes supported"); - } - - private: - Frame::Ptr frame; - SessionStats::Ptr stats; - RandomAPI::Ptr prng; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/decrypt_chm.hpp b/Sources/OpenVPN3/openvpn/crypto/decrypt_chm.hpp deleted file mode 100644 index 3e6b2af..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/decrypt_chm.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// 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-2020 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/>. - -// General-purpose OpenVPN protocol decrypt method (CBC/HMAC) that is independent of the underlying CRYPTO_API - -#ifndef OPENVPN_CRYPTO_DECRYPT_CHM_H -#define OPENVPN_CRYPTO_DECRYPT_CHM_H - -#include <cstring> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/memneq.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/crypto/cipher.hpp> -#include <openvpn/crypto/ovpnhmac.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/log/sessionstats.hpp> - -namespace openvpn { - - template <typename CRYPTO_API> - class DecryptCHM { - public: - OPENVPN_SIMPLE_EXCEPTION(chm_unsupported_cipher_mode); - - Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now) - { - // skip null packets - if (!buf.size()) - return Error::SUCCESS; - - // verify the HMAC - if (hmac.defined()) - { - unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE]; - const size_t hmac_size = hmac.output_size(); - const unsigned char *packet_hmac = buf.read_alloc(hmac_size); - hmac.hmac(local_hmac, hmac_size, buf.c_data(), buf.size()); - if (crypto::memneq(local_hmac, packet_hmac, hmac_size)) - { - buf.reset_size(); - return Error::HMAC_ERROR; - } - } - - // decrypt packet ID + payload - if (cipher.defined()) - { - unsigned char iv_buf[CRYPTO_API::CipherContext::MAX_IV_LENGTH]; - const size_t iv_length = cipher.iv_length(); - - // extract IV from head of packet - buf.read(iv_buf, iv_length); - - // initialize work buffer - frame->prepare(Frame::DECRYPT_WORK, work); - - // decrypt from buf -> work - const size_t decrypt_bytes = cipher.decrypt(iv_buf, work.data(), work.max_size(), buf.c_data(), buf.size()); - if (!decrypt_bytes) - { - buf.reset_size(); - return Error::DECRYPT_ERROR; - } - work.set_size(decrypt_bytes); - - // handle different cipher modes - const int cipher_mode = cipher.cipher_mode(); - if (cipher_mode == CRYPTO_API::CipherContext::CIPH_CBC_MODE) - { - if (!verify_packet_id(work, now)) - { - buf.reset_size(); - return Error::REPLAY_ERROR; - } - } - else - { - throw chm_unsupported_cipher_mode(); - } - - // return cleartext result in buf - buf.swap(work); - } - else // no encryption - { - if (!verify_packet_id(buf, now)) - { - buf.reset_size(); - return Error::REPLAY_ERROR; - } - } - return Error::SUCCESS; - } - - Frame::Ptr frame; - CipherContext<CRYPTO_API> cipher; - OvpnHMAC<CRYPTO_API> hmac; - PacketIDReceive pid_recv; - - private: - bool verify_packet_id(BufferAllocated& buf, const PacketID::time_t now) - { - // ignore packet ID if pid_recv is not initialized - if (pid_recv.initialized()) - { - const PacketID pid = pid_recv.read_next(buf); - if (!pid_recv.test_add(pid, now, true)) // verify packet ID - return false; - } - return true; - } - - BufferAllocated work; - }; - -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_DECRYPT_H diff --git a/Sources/OpenVPN3/openvpn/crypto/digestapi.hpp b/Sources/OpenVPN3/openvpn/crypto/digestapi.hpp deleted file mode 100644 index 6987bcf..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/digestapi.hpp +++ /dev/null @@ -1,210 +0,0 @@ -// 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-2020 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/>. - -// Crypto digest/HMAC API - -#ifndef OPENVPN_CRYPTO_DIGESTAPI_H -#define OPENVPN_CRYPTO_DIGESTAPI_H - -#include <openvpn/common/rc.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> - -namespace openvpn { - - // Digest/HMAC abstract base classes and factories - - class DigestInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<DigestInstance> Ptr; - - virtual void update(const unsigned char *in, const size_t size) = 0; - virtual size_t final(unsigned char *out) = 0; - virtual size_t size() const = 0; - }; - - class HMACInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<HMACInstance> Ptr; - - virtual void reset() = 0; - virtual void update(const unsigned char *in, const size_t size) = 0; - virtual size_t final(unsigned char *out) = 0; - virtual size_t size() const = 0; - }; - - class DigestContext : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<DigestContext> Ptr; - - virtual std::string name() const = 0; - virtual size_t size() const = 0; - - virtual DigestInstance::Ptr new_digest() = 0; - - virtual HMACInstance::Ptr new_hmac(const unsigned char *key, - const size_t key_size) = 0; - }; - - class DigestFactory : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<DigestFactory> Ptr; - - virtual DigestContext::Ptr new_context(const CryptoAlgs::Type digest_type) = 0; - - virtual DigestInstance::Ptr new_digest(const CryptoAlgs::Type digest_type) = 0; - - virtual HMACInstance::Ptr new_hmac(const CryptoAlgs::Type digest_type, - const unsigned char *key, - const size_t key_size) = 0; - }; - - // Digest implementation using CRYPTO_API - - template <typename CRYPTO_API> - class CryptoDigestInstance : public DigestInstance - { - public: - CryptoDigestInstance(const CryptoAlgs::Type digest) - : impl(digest) - { - } - - virtual void update(const unsigned char *in, const size_t size) - { - impl.update(in, size); - } - - virtual size_t final(unsigned char *out) - { - return impl.final(out); - } - - virtual size_t size() const - { - return impl.size(); - } - - private: - typename CRYPTO_API::DigestContext impl; - }; - - template <typename CRYPTO_API> - class CryptoHMACInstance : public HMACInstance - { - public: - CryptoHMACInstance(const CryptoAlgs::Type digest, - const unsigned char *key, - const size_t key_size) - : impl(digest, key, key_size) - { - } - - virtual void reset() - { - impl.reset(); - } - - virtual void update(const unsigned char *in, const size_t size) - { - impl.update(in, size); - } - - virtual size_t final(unsigned char *out) - { - return impl.final(out); - } - - size_t size() const - { - return impl.size(); - } - - private: - typename CRYPTO_API::HMACContext impl; - }; - - template <typename CRYPTO_API> - class CryptoDigestContext : public DigestContext - { - public: - CryptoDigestContext(const CryptoAlgs::Type digest_type) - : digest(digest_type) - { - } - - virtual std::string name() const - { - return CryptoAlgs::name(digest); - } - - virtual size_t size() const - { - return CryptoAlgs::size(digest); - } - - virtual DigestInstance::Ptr new_digest() - { - return new CryptoDigestInstance<CRYPTO_API>(digest); - } - - virtual HMACInstance::Ptr new_hmac(const unsigned char *key, - const size_t key_size) - { - return new CryptoHMACInstance<CRYPTO_API>(digest, - key, - key_size); - } - -private: - CryptoAlgs::Type digest; -}; - -template <typename CRYPTO_API> -class CryptoDigestFactory : public DigestFactory -{ -public: - virtual DigestContext::Ptr new_context(const CryptoAlgs::Type digest_type) - { - return new CryptoDigestContext<CRYPTO_API>(digest_type); - } - - virtual DigestInstance::Ptr new_digest(const CryptoAlgs::Type digest_type) - { - return new CryptoDigestInstance<CRYPTO_API>(digest_type); - } - - virtual HMACInstance::Ptr new_hmac(const CryptoAlgs::Type digest_type, - const unsigned char *key, - const size_t key_size) - { - return new CryptoHMACInstance<CRYPTO_API>(digest_type, - key, - key_size); - } -}; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/encrypt_chm.hpp b/Sources/OpenVPN3/openvpn/crypto/encrypt_chm.hpp deleted file mode 100644 index 1e8e6c9..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/encrypt_chm.hpp +++ /dev/null @@ -1,136 +0,0 @@ -// 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-2020 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/>. - -// General-purpose OpenVPN protocol encrypt method (CBC/HMAC) that is independent of the underlying CRYPTO_API - -#ifndef OPENVPN_CRYPTO_ENCRYPT_CHM_H -#define OPENVPN_CRYPTO_ENCRYPT_CHM_H - -#include <cstring> -#include <utility> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/crypto/cipher.hpp> -#include <openvpn/crypto/ovpnhmac.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/packet_id.hpp> - -namespace openvpn { - template <typename CRYPTO_API> - class EncryptCHM { - public: - OPENVPN_SIMPLE_EXCEPTION(chm_unsupported_cipher_mode); - - void encrypt(BufferAllocated& buf, const PacketID::time_t now) - { - // skip null packets - if (!buf.size()) - return; - - if (cipher.defined()) - { - // workspace for generating IV - unsigned char iv_buf[CRYPTO_API::CipherContext::MAX_IV_LENGTH]; - const size_t iv_length = cipher.iv_length(); - - // IV and packet ID are generated differently depending on cipher mode - const int cipher_mode = cipher.cipher_mode(); - if (cipher_mode == CRYPTO_API::CipherContext::CIPH_CBC_MODE) - { - // in CBC mode, use an explicit, random IV - prng->rand_bytes(iv_buf, iv_length); - - // generate fresh outgoing packet ID and prepend to cleartext buffer - pid_send.write_next(buf, true, now); - } - else - { - throw chm_unsupported_cipher_mode(); - } - - // initialize work buffer - frame->prepare(Frame::ENCRYPT_WORK, work); - - // encrypt from buf -> work - const size_t encrypt_bytes = cipher.encrypt(iv_buf, work.data(), work.max_size(), buf.c_data(), buf.size()); - if (!encrypt_bytes) - { - buf.reset_size(); - return; - } - work.set_size(encrypt_bytes); - - // prepend the IV to the ciphertext - work.prepend(iv_buf, iv_length); - - // HMAC the ciphertext - prepend_hmac(work); - - // return ciphertext result in buf - buf.swap(work); - } - else // no encryption - { - // generate fresh outgoing packet ID and prepend to cleartext buffer - pid_send.write_next(buf, true, now); - - // HMAC the cleartext - prepend_hmac(buf); - } - } - - void set_prng(RandomAPI::Ptr prng_arg) - { - prng_arg->assert_crypto(); - prng = std::move(prng_arg); - } - - Frame::Ptr frame; - CipherContext<CRYPTO_API> cipher; - OvpnHMAC<CRYPTO_API> hmac; - PacketIDSend pid_send; - - private: - // compute HMAC signature of data buffer, - // then prepend the signature to the buffer. - void prepend_hmac(BufferAllocated& buf) - { - if (hmac.defined()) - { - const unsigned char *content = buf.data(); - const size_t content_size = buf.size(); - const size_t hmac_size = hmac.output_size(); - unsigned char *hmac_buf = buf.prepend_alloc(hmac_size); - hmac.hmac(hmac_buf, hmac_size, content, content_size); - } - } - - BufferAllocated work; - RandomAPI::Ptr prng; - }; - -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_ENCRYPT_H diff --git a/Sources/OpenVPN3/openvpn/crypto/hashstr.hpp b/Sources/OpenVPN3/openvpn/crypto/hashstr.hpp deleted file mode 100644 index 8ed1d48..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/hashstr.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// 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-2020 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_CRYPTO_HASHSTR_H -#define OPENVPN_CRYPTO_HASHSTR_H - -#include <string> - -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/crypto/digestapi.hpp> - -namespace openvpn { - class HashString - { - public: - HashString(DigestFactory& digest_factory, - const CryptoAlgs::Type digest_type) - : ctx(digest_factory.new_digest(digest_type)) - { - } - - void update(const std::string& str) - { - ctx->update((unsigned char *)str.c_str(), str.length()); - } - - void update(const char *str) - { - ctx->update((unsigned char *)str, std::strlen(str)); - } - - void update(const char c) - { - ctx->update((unsigned char *)&c, 1); - } - - void update(const Buffer& buf) - { - ctx->update(buf.c_data(), buf.size()); - } - - BufferPtr final() - { - BufferPtr ret(new BufferAllocated(ctx->size(), BufferAllocated::ARRAY)); - ctx->final(ret->data()); - return ret; - } - - void final(Buffer& output) - { - const size_t size = ctx->size(); - if (size > output.max_size()) - OPENVPN_BUFFER_THROW(buffer_overflow); - ctx->final(output.data()); - output.set_size(size); - } - - std::string final_hex() - { - BufferPtr bp = final(); - return render_hex_generic(*bp); - } - - std::string final_base64() - { - BufferPtr bp = final(); - return base64->encode(*bp); - } - - private: - DigestInstance::Ptr ctx; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/ovpnhmac.hpp b/Sources/OpenVPN3/openvpn/crypto/ovpnhmac.hpp deleted file mode 100644 index 7fa8413..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/ovpnhmac.hpp +++ /dev/null @@ -1,240 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN HMAC classes - -#ifndef OPENVPN_CRYPTO_OVPNHMAC_H -#define OPENVPN_CRYPTO_OVPNHMAC_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/memneq.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> - -namespace openvpn { - - // OpenVPN protocol HMAC usage for HMAC/CBC integrity checking and tls-auth - - template <typename CRYPTO_API> - class OvpnHMAC - { - public: - OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_digest_size); - OPENVPN_SIMPLE_EXCEPTION(ovpn_hmac_context_bad_sizing); - - public: - OvpnHMAC() {} - - OvpnHMAC(const CryptoAlgs::Type digest, const StaticKey& key) - { - init(digest, key); - } - - bool defined() const { return ctx.is_initialized(); } - - // size of out buffer to pass to hmac - size_t output_size() const - { - return ctx.size(); - } - - void init(const CryptoAlgs::Type digest, const StaticKey& key) - { - const CryptoAlgs::Alg& alg = CryptoAlgs::get(digest); - - // check that key is large enough - if (key.size() < alg.size()) - throw ovpn_hmac_context_digest_size(); - - // initialize HMAC context with digest type and key - ctx.init(digest, key.data(), alg.size()); - } - - void hmac(unsigned char *out, const size_t out_size, - const unsigned char *in, const size_t in_size) - { - ctx.reset(); - ctx.update(in, in_size); - ctx.final(out); - } - - // Special HMAC for OpenVPN control packets - - void ovpn_hmac_gen(unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) - { - if (ovpn_hmac_pre(data, data_size, l1, l2, l3)) - ctx.final(data + l1); - else - throw ovpn_hmac_context_bad_sizing(); - } - - // verify the HMAC generated by ovpn_hmac_gen, return true if verified - bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) - { - unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE]; - if (ovpn_hmac_pre(data, data_size, l1, l2, l3)) - { - ctx.final(local_hmac); - return !crypto::memneq(data + l1, local_hmac, l2); - } - else - return false; - } - - private: - // Convoluting OpenVPN control channel packets for HMAC: - // <-- L1 --> <-L2> <L3> - // [OP] [PSID] [HMAC] [PID] [...] -> canonical order - // - // [HMAC] [PID] [OP] [PSID] [...] -> HMAC order - - bool ovpn_hmac_pre(const unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) - { - const size_t lsum = l1 + l2 + l3; - if (lsum > data_size || l2 != ctx.size()) - return false; - ctx.reset(); - ctx.update(data + l1 + l2, l3); - ctx.update(data, l1); - ctx.update(data + lsum, data_size - lsum); - return true; - } - - typename CRYPTO_API::HMACContext ctx; - }; - - // OvpnHMAC wrapper API using dynamic polymorphism - - class OvpnHMACInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<OvpnHMACInstance> Ptr; - - virtual void init(const StaticKey& key) = 0; - - virtual size_t output_size() const = 0; - - virtual void ovpn_hmac_gen(unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) = 0; - - virtual bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) = 0; - }; - - class OvpnHMACContext : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<OvpnHMACContext> Ptr; - - virtual size_t size() const = 0; - - virtual OvpnHMACInstance::Ptr new_obj() = 0; - }; - - class OvpnHMACFactory : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<OvpnHMACFactory> Ptr; - - virtual OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type) = 0; - }; - - // OvpnHMAC wrapper implementation using dynamic polymorphism - - template <typename CRYPTO_API> - class CryptoOvpnHMACInstance : public OvpnHMACInstance - { - public: - CryptoOvpnHMACInstance(const CryptoAlgs::Type digest_arg) - : digest(digest_arg) - { - } - - virtual void init(const StaticKey& key) - { - ovpn_hmac.init(digest, key); - } - - virtual size_t output_size() const - { - return ovpn_hmac.output_size(); - } - - virtual void ovpn_hmac_gen(unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) - { - ovpn_hmac.ovpn_hmac_gen(data, data_size, l1, l2, l3); - } - - virtual bool ovpn_hmac_cmp(const unsigned char *data, const size_t data_size, - const size_t l1, const size_t l2, const size_t l3) - { - return ovpn_hmac.ovpn_hmac_cmp(data, data_size, l1, l2, l3); - } - - private: - typename CryptoAlgs::Type digest; - OvpnHMAC<CRYPTO_API> ovpn_hmac; - }; - - template <typename CRYPTO_API> - class CryptoOvpnHMACContext : public OvpnHMACContext - { - public: - CryptoOvpnHMACContext(const CryptoAlgs::Type digest_type) - : digest(CryptoAlgs::legal_dc_digest(digest_type)) - { - } - - virtual size_t size() const - { - return CryptoAlgs::size(digest); - } - - virtual OvpnHMACInstance::Ptr new_obj() - { - return new CryptoOvpnHMACInstance<CRYPTO_API>(digest); - } - - private: - CryptoAlgs::Type digest; - }; - - template <typename CRYPTO_API> - class CryptoOvpnHMACFactory : public OvpnHMACFactory - { - public: - virtual OvpnHMACContext::Ptr new_obj(const CryptoAlgs::Type digest_type) - { - return new CryptoOvpnHMACContext<CRYPTO_API>(digest_type); - } - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/packet_id.hpp b/Sources/OpenVPN3/openvpn/crypto/packet_id.hpp deleted file mode 100644 index 0011823..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/packet_id.hpp +++ /dev/null @@ -1,447 +0,0 @@ -// 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-2020 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/>. - -// Manage OpenVPN protocol Packet IDs for packet replay detection - -#ifndef OPENVPN_CRYPTO_PACKET_ID_H -#define OPENVPN_CRYPTO_PACKET_ID_H - -#include <string> -#include <cstring> -#include <sstream> -#include <cstdint> // for std::uint32_t - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/circ_list.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/log/sessionstats.hpp> - -namespace openvpn { - /* - * Communicate packet-id over the wire. - * A short packet-id is just a 32 bit - * sequence number. A long packet-id - * includes a timestamp as well. - * - * Long packet-ids are used as IVs for - * CFB/OFB ciphers. - * - * This data structure is always sent - * over the net in network byte order, - * by calling htonpid, ntohpid, - * htontime, and ntohtime on the - * data elements to change them - * to and from standard sizes. - * - * In addition, time is converted to - * a PacketID::net_time_t before sending, - * since openvpn always - * uses a 32-bit time_t but some - * 64 bit platforms use a - * 64 bit time_t. - */ - struct PacketID - { - typedef std::uint32_t id_t; - typedef std::uint32_t net_time_t; - typedef Time::base_type time_t; - - enum { - SHORT_FORM = 0, // short form of ID (4 bytes) - LONG_FORM = 1, // long form of ID (8 bytes) - - UNDEF = 0, // special undefined/null id_t value - }; - - id_t id; // legal values are 1 through 2^32-1 - time_t time; // converted to PacketID::net_time_t before transmission - - static size_t size(const int form) - { - if (form == PacketID::LONG_FORM) - return longidsize; - else - return shortidsize; - } - - constexpr static size_t shortidsize = sizeof(id_t); - constexpr static size_t longidsize = sizeof(id_t) + sizeof(net_time_t); - - bool is_valid() const - { - return id != UNDEF; - } - - void reset() - { - id = id_t(0); - time = time_t(0); - } - - void read(Buffer& buf, const int form) - { - id_t net_id; - net_time_t net_time; - - buf.read ((unsigned char *)&net_id, sizeof (net_id)); - id = ntohl (net_id); - - if (form == LONG_FORM) - { - buf.read ((unsigned char *)&net_time, sizeof (net_time)); - time = ntohl (net_time); - } - else - time = time_t(0); - } - - void write(Buffer& buf, const int form, const bool prepend) const - { - const id_t net_id = htonl(id); - const net_time_t net_time = htonl(time); - - if (prepend) - { - if (form == LONG_FORM) - buf.prepend ((unsigned char *)&net_time, sizeof (net_time)); - buf.prepend ((unsigned char *)&net_id, sizeof (net_id)); - } - else - { - buf.write ((unsigned char *)&net_id, sizeof (net_id)); - if (form == LONG_FORM) - buf.write ((unsigned char *)&net_time, sizeof (net_time)); - } - } - - std::string str() const - { - std::ostringstream os; - os << "[" << time << "," << id << "]"; - return os.str(); - } - }; - - struct PacketIDConstruct : public PacketID - { - PacketIDConstruct(const PacketID::time_t v_time = PacketID::time_t(0), const PacketID::id_t v_id = PacketID::id_t(0)) - { - id = v_id; - time = v_time; - } - }; - - class PacketIDSend - { - public: - OPENVPN_SIMPLE_EXCEPTION(packet_id_wrap); - - PacketIDSend() - { - init(PacketID::SHORT_FORM); - } - - void init(const int form) // PacketID::LONG_FORM or PacketID::SHORT_FORM - { - pid_.id = PacketID::id_t(0); - pid_.time = PacketID::time_t(0); - form_ = form; - } - - PacketID next(const PacketID::time_t now) - { - PacketID ret; - if (!pid_.time) - pid_.time = now; - ret.id = ++pid_.id; - if (unlikely(!pid_.id)) // wraparound - { - if (form_ != PacketID::LONG_FORM) - throw packet_id_wrap(); - pid_.time = now; - ret.id = pid_.id = 1; - } - ret.time = pid_.time; - return ret; - } - - void write_next(Buffer& buf, const bool prepend, const PacketID::time_t now) - { - const PacketID pid = next(now); - pid.write(buf, form_, prepend); - } - - /* - * In TLS mode, when a packet ID gets to this level, - * start thinking about triggering a new - * SSL/TLS handshake. - */ - bool wrap_warning() const - { - const PacketID::id_t wrap_at = 0xFF000000; - return pid_.id >= wrap_at; - } - - std::string str() const - { - std::string ret; - ret = pid_.str(); - if (form_ == PacketID::LONG_FORM) - ret += 'L'; - return ret; - } - - private: - PacketID pid_; - int form_; - }; - - /* - * This is the data structure we keep on the receiving side, - * to check that no packet-id (i.e. sequence number + optional timestamp) - * is accepted more than once. - * - * Replay window sizing in bytes = 2^REPLAY_WINDOW_ORDER. - * PKTID_RECV_EXPIRE is backtrack expire in seconds. - */ - template <unsigned int REPLAY_WINDOW_ORDER, - unsigned int PKTID_RECV_EXPIRE> - class PacketIDReceiveType - { - public: - static constexpr unsigned int REPLAY_WINDOW_BYTES = 1 << REPLAY_WINDOW_ORDER; - static constexpr unsigned int REPLAY_WINDOW_SIZE = REPLAY_WINDOW_BYTES * 8; - - // mode - enum { - UDP_MODE = 0, - TCP_MODE = 1 - }; - - OPENVPN_SIMPLE_EXCEPTION(packet_id_not_initialized); - - PacketIDReceiveType() - : initialized_(false) - { - } - - void init(const int mode_arg, - const int form_arg, - const char *name_arg, - const int unit_arg, - const SessionStats::Ptr& stats_arg) - { - initialized_ = true; - base = 0; - extent = 0; - expire = 0; - id_high = 0; - time_high = 0; - id_floor = 0; - max_backtrack = 0; - mode = mode_arg; - form = form_arg; - unit = unit_arg; - name = name_arg; - stats = stats_arg; - std::memset(history, 0, sizeof(history)); - } - - bool initialized() const - { - return initialized_; - } - - bool test_add(const PacketID& pin, - const PacketID::time_t now, - const bool mod) // don't modify history unless mod is true - { - const Error::Type err = do_test_add(pin, now, mod); - if (unlikely(err != Error::SUCCESS)) - { - stats->error(err); - return false; - } - else - return true; - } - - Error::Type do_test_add(const PacketID& pin, - const PacketID::time_t now, - const bool mod) // don't modify history unless mod is true - { - // make sure we were initialized - if (unlikely(!initialized_)) - throw packet_id_not_initialized(); - - // expire backtracks at or below id_floor after PKTID_RECV_EXPIRE time - if (unlikely(now >= expire)) - id_floor = id_high; - expire = now + PKTID_RECV_EXPIRE; - - // ID must not be zero - if (unlikely(!pin.is_valid())) - return Error::PKTID_INVALID; - - // time changed? - if (unlikely(pin.time != time_high)) - { - if (pin.time > time_high) - { - // time moved forward, accept - if (!mod) - return Error::SUCCESS; - base = 0; - extent = 0; - id_high = 0; - time_high = pin.time; - id_floor = 0; - } - else - { - // time moved backward, reject - return Error::PKTID_TIME_BACKTRACK; - } - } - - if (likely(pin.id == id_high + 1)) - { - // well-formed ID sequence (incremented by 1) - if (!mod) - return Error::SUCCESS; - base = REPLAY_INDEX(-1); - history[base / 8] |= (1 << (base % 8)); - if (extent < REPLAY_WINDOW_SIZE) - ++extent; - id_high = pin.id; - } - else if (pin.id > id_high) - { - // ID jumped forward by more than one - if (!mod) - return Error::SUCCESS; - const unsigned int delta = pin.id - id_high; - if (delta < REPLAY_WINDOW_SIZE) - { - base = REPLAY_INDEX(-delta); - history[base / 8] |= (1 << (base % 8)); - extent += delta; - if (extent > REPLAY_WINDOW_SIZE) - extent = REPLAY_WINDOW_SIZE; - for (unsigned i = 1; i < delta; ++i) - { - const unsigned int newbase = REPLAY_INDEX(i); - history[newbase / 8] &= ~(1 << (newbase % 8)); - } - } - else - { - base = 0; - extent = REPLAY_WINDOW_SIZE; - std::memset(history, 0, sizeof(history)); - history[0] = 1; - } - id_high = pin.id; - } - else - { - // ID backtrack - const unsigned int delta = id_high - pin.id; - if (delta > max_backtrack) - max_backtrack = delta; - if (delta < extent) - { - if (pin.id > id_floor) - { - const unsigned int ri = REPLAY_INDEX(delta); - std::uint8_t *p = &history[ri / 8]; - const std::uint8_t mask = (1 << (ri % 8)); - if (*p & mask) - return Error::PKTID_REPLAY; - if (!mod) - return Error::SUCCESS; - *p |= mask; - } - else - return Error::PKTID_EXPIRE; - } - else - return Error::PKTID_BACKTRACK; - } - - return Error::SUCCESS; - } - - PacketID read_next(Buffer& buf) const - { - if (!initialized_) - throw packet_id_not_initialized(); - PacketID pid; - pid.read(buf, form); - return pid; - } - - std::string str() const - { - std::ostringstream os; - os << "[e=" << extent << " f=" << id_floor << " h=" << time_high << '/' << id_high << ']'; - return os.str(); - } - - private: - unsigned int REPLAY_INDEX(const int i) const - { - return (base + i) & (REPLAY_WINDOW_SIZE - 1); - } - - bool initialized_; - - unsigned int base; // bit position of deque base in history - unsigned int extent; // extent (in bits) of deque in history - PacketID::time_t expire; // expiration of history - PacketID::id_t id_high; // highest sequence number received - PacketID::time_t time_high; // highest time stamp received - PacketID::id_t id_floor; // we will only accept backtrack IDs > id_floor - unsigned int max_backtrack; - - int mode; // UDP_MODE or TCP_MODE - int form; // PacketID::LONG_FORM or PacketID::SHORT_FORM - int unit; // unit number of this object (for debugging) - std::string name; // name of this object (for debugging) - - SessionStats::Ptr stats; - - std::uint8_t history[REPLAY_WINDOW_BYTES]; /* "sliding window" bitmask of recent packet IDs received */ - }; - - // Our standard packet ID window with order=8 (window size=2048). - // and recv expire=30 seconds. - typedef PacketIDReceiveType<8, 30> PacketIDReceive; - -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_PACKET_ID_H diff --git a/Sources/OpenVPN3/openvpn/crypto/selftest.hpp b/Sources/OpenVPN3/openvpn/crypto/selftest.hpp deleted file mode 100644 index adc6fed..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/selftest.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// 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-2020 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/>. - -// A general purpose container for OpenVPN protocol encrypt and decrypt objects. - -#ifndef OPENVPN_CRYPTO_SELFTEST_H -#define OPENVPN_CRYPTO_SELFTEST_H - -#include <string> - -#ifdef USE_OPENSSL -//#include <openvpn/openssl/util/selftest.hpp> -#endif - -#ifdef USE_APPLE_SSL -//#include <openvpn/applecrypto/util/selftest.hpp> -#endif - -#ifdef USE_MBEDTLS -#include <openvpn/mbedtls/util/selftest.hpp> -#endif - -#ifdef USE_MBEDTLS_APPLE_HYBRID -//#include <openvpn/applecrypto/util/selftest.hpp> -#include <openvpn/mbedtls/util/selftest.hpp> -#endif - -namespace openvpn { - namespace SelfTest { - inline std::string crypto_self_test() - { - std::string ret; -# ifdef USE_OPENSSL - //ret += crypto_self_test_openssl(); -# endif -# ifdef USE_APPLE_SSL - //ret += crypto_self_test_apple(); -# endif -# if defined(USE_MBEDTLS) || defined(USE_MBEDTLS_APPLE_HYBRID) - ret += crypto_self_test_mbedtls(); -# endif - return ret; - } - } -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_CRYPTO_H diff --git a/Sources/OpenVPN3/openvpn/crypto/static_key.hpp b/Sources/OpenVPN3/openvpn/crypto/static_key.hpp deleted file mode 100644 index 69d06b7..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/static_key.hpp +++ /dev/null @@ -1,183 +0,0 @@ -// 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-2020 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/>. - -// Classes for handling OpenVPN static keys (and tls-auth keys) - -#ifndef OPENVPN_CRYPTO_STATIC_KEY_H -#define OPENVPN_CRYPTO_STATIC_KEY_H - -#include <string> -#include <sstream> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - class StaticKey - { - friend class OpenVPNStaticKey; - typedef BufferAllocated key_t; - - public: - StaticKey() {} - StaticKey(const unsigned char *key_data, const size_t key_size) - : key_data_(key_data, key_size, key_t::DESTRUCT_ZERO) {} - - size_t size() const { return key_data_.size(); } - const unsigned char *data() const { return key_data_.c_data(); } - void erase() { key_data_.clear(); } - - std::string render_hex() const { return openvpn::render_hex_generic(key_data_); } - - void parse_from_base64(const std::string& b64, const size_t capacity) - { - key_data_.reset(capacity, key_t::DESTRUCT_ZERO); - base64->decode(key_data_, b64); - } - - std::string render_to_base64() const - { - return base64->encode(key_data_); - } - - void init_from_rng(RandomAPI& rng, const size_t key_size) - { - rng.assert_crypto(); - key_data_.init(key_size, key_t::DESTRUCT_ZERO); - rng.rand_bytes(key_data_.data(), key_size); - key_data_.set_size(key_size); - } - - private: - key_t key_data_; - }; - - class OpenVPNStaticKey - { - typedef StaticKey::key_t key_t; - - public: - enum { - KEY_SIZE = 256 // bytes - }; - - // key specifier - enum { - // key for cipher and hmac - CIPHER = 0, - HMAC = (1<<0), - - // do we want to encrypt or decrypt with this key - ENCRYPT = 0, - DECRYPT = (1<<1), - - // key direction - NORMAL = 0, - INVERSE = (1<<2) - }; - - OPENVPN_SIMPLE_EXCEPTION(static_key_parse_error); - OPENVPN_SIMPLE_EXCEPTION(static_key_bad_size); - - bool defined() const { return key_data_.defined(); } - - StaticKey slice(unsigned int key_specifier) const - { - if (key_data_.size() != KEY_SIZE) - throw static_key_bad_size(); - static const unsigned char key_table[] = { 0, 1, 2, 3, 2, 3, 0, 1 }; - const unsigned int idx = key_table[key_specifier & 7] * 64; - return StaticKey(key_data_.c_data() + idx, KEY_SIZE / 4); - } - - void parse_from_file(const std::string& filename) - { - const std::string str = read_text(filename); - parse(str); - } - - void parse(const std::string& key_text) - { - SplitLines in(key_text, 0); - key_t data(KEY_SIZE, key_t::DESTRUCT_ZERO); - bool in_body = false; - while (in(true)) - { - const std::string& line = in.line_ref(); - if (line == static_key_head()) - in_body = true; - else if (line == static_key_foot()) - in_body = false; - else if (in_body) - parse_hex(data, line); - } - if (in_body || data.size() != KEY_SIZE) - throw static_key_parse_error(); - key_data_ = data; - } - - std::string render() const - { - if (key_data_.size() != KEY_SIZE) - throw static_key_bad_size(); - std::ostringstream out; - out << static_key_head() << "\n"; - for (size_t i = 0; i < KEY_SIZE; i += 16) - out << render_hex(key_data_.c_data() + i, 16) << "\n"; - out << static_key_foot() << "\n"; - return out.str(); - } - - unsigned char *raw_alloc() - { - key_data_.init(KEY_SIZE, key_t::DESTRUCT_ZERO|key_t::ARRAY); - return key_data_.data(); - } - - void erase() - { - key_data_.clear(); - } - - private: - static const char *static_key_head() - { - return "-----BEGIN OpenVPN Static key V1-----"; - } - - static const char *static_key_foot() - { - return "-----END OpenVPN Static key V1-----"; - } - - key_t key_data_; - }; - - -} // namespace openvpn - -#endif // OPENVPN_CRYPTO_STATIC_KEY_H diff --git a/Sources/OpenVPN3/openvpn/crypto/tls_crypt.hpp b/Sources/OpenVPN3/openvpn/crypto/tls_crypt.hpp deleted file mode 100644 index d670ce1..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/tls_crypt.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN TLS-Crypt classes - -#ifndef OPENVPN_CRYPTO_TLSCRYPT_H -#define OPENVPN_CRYPTO_TLSCRYPT_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/memneq.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/ssl/psid.hpp> - -namespace openvpn { - - // OpenVPN protocol HMAC usage for HMAC/CTR integrity checking and tls-crypt - - // Control packet format when tls-crypt is enabled: - // [OP] [PSID] [PID] [HMAC] [...] - - template <typename CRYPTO_API> - class TLSCrypt - { - public: - OPENVPN_SIMPLE_EXCEPTION(ovpn_tls_crypt_context_digest_size); - OPENVPN_SIMPLE_EXCEPTION(ovpn_tls_crypt_context_bad_sizing); - OPENVPN_SIMPLE_EXCEPTION(ovpn_tls_crypt_wrong_mode); - - TLSCrypt() : mode(CRYPTO_API::CipherContext::MODE_UNDEF) {} - - TLSCrypt(const CryptoAlgs::Type digest, const StaticKey& key_hmac, - const CryptoAlgs::Type cipher, const StaticKey& key_crypt, - const int mode) - { - init(digest, key_hmac, cipher, key_crypt, mode); - } - - bool defined() const { return ctx_hmac.is_initialized() && ctx_crypt.is_initialized(); } - - // size of out buffer to pass to hmac - size_t output_hmac_size() const - { - return ctx_hmac.size(); - } - - void init(const CryptoAlgs::Type digest, const StaticKey& key_hmac, - const CryptoAlgs::Type cipher, const StaticKey& key_crypt, - const int mode_arg) - { - const CryptoAlgs::Alg& alg_hmac = CryptoAlgs::get(digest); - - // check that key is large enough - if (key_hmac.size() < alg_hmac.size()) - throw ovpn_tls_crypt_context_digest_size(); - - // initialize HMAC context with digest type and key - ctx_hmac.init(digest, key_hmac.data(), alg_hmac.size()); - - // initialize Cipher context with cipher, key and mode - ctx_crypt.init(cipher, key_crypt.data(), mode_arg); - - mode = mode_arg; - } - - bool hmac_gen(unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) - { - hmac_pre(header, header_len, payload, payload_len); - ctx_hmac.final(header + header_len); - - return true; - } - - bool hmac_cmp(const unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) - { - unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE]; - - hmac_pre(header, header_len, payload, payload_len); - ctx_hmac.final(local_hmac); - - 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, - const unsigned char *in, const size_t ilen) - { - if (mode != CRYPTO_API::CipherContext::ENCRYPT) - throw ovpn_tls_crypt_wrong_mode(); - - return encrypt_decrypt(iv, out, olen, in, ilen); - } - - size_t decrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) - { - if (mode != CRYPTO_API::CipherContext::DECRYPT) - throw ovpn_tls_crypt_wrong_mode(); - - return encrypt_decrypt(iv, out, olen, in, ilen); - } - - private: - // assume length check on header has already been performed - void hmac_pre(const unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) - { - ctx_hmac.reset(); - ctx_hmac.update(header, header_len); - ctx_hmac.update(payload, payload_len); - } - - size_t encrypt_decrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) - { - ctx_crypt.reset(iv); - - size_t outlen = 0; - - if (!ctx_crypt.update(out, olen, in, ilen, outlen)) - return 0; - - if (!ctx_crypt.final(out + outlen, olen - outlen, outlen)) - return 0; - - return outlen; - } - - typename CRYPTO_API::HMACContext ctx_hmac; - typename CRYPTO_API::CipherContext ctx_crypt; - int mode; - }; - - // OvpnHMAC wrapper API using dynamic polymorphism - - class TLSCryptInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSCryptInstance> Ptr; - - virtual void init(const StaticKey& key_hmac, const StaticKey& key_crypt) = 0; - - virtual size_t output_hmac_size() const = 0; - - virtual bool hmac_gen(unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) = 0; - - virtual bool hmac_cmp(const unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) = 0; - - virtual size_t encrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) = 0; - - virtual size_t decrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) = 0; - }; - - class TLSCryptContext : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSCryptContext> Ptr; - - virtual size_t digest_size() const = 0; - - virtual size_t cipher_key_size() const = 0; - - virtual TLSCryptInstance::Ptr new_obj_send() = 0; - - virtual TLSCryptInstance::Ptr new_obj_recv() = 0; - - // This is the size of the header in a TLSCrypt-wrapped packets, - // excluding the HMAC. Format: - // - // [OP] [PSID] [PID] [HMAC] [...] - // - - constexpr const static size_t hmac_offset = 1 + ProtoSessionID::SIZE + PacketID::longidsize; - - }; - - - - class TLSCryptFactory : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSCryptFactory> Ptr; - - virtual TLSCryptContext::Ptr new_obj(const CryptoAlgs::Type digest_type, - const CryptoAlgs::Type cipher_type) = 0; - }; - - // TLSCrypt wrapper implementation using dynamic polymorphism - - template <typename CRYPTO_API> - class CryptoTLSCryptInstance : public TLSCryptInstance - { - public: - CryptoTLSCryptInstance(const CryptoAlgs::Type digest_arg, - const CryptoAlgs::Type cipher_arg, - int mode_arg) - : digest(digest_arg), - cipher(cipher_arg), - mode(mode_arg) - { - } - - void init(const StaticKey& key_hmac, const StaticKey& key_crypt) - { - tls_crypt.init(digest, key_hmac, cipher, key_crypt, mode); - } - - size_t output_hmac_size() const - { - return tls_crypt.output_hmac_size(); - } - - bool hmac_gen(unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) - { - return tls_crypt.hmac_gen(header, header_len, payload, payload_len); - } - - // verify the HMAC generated by hmac_gen, return true if verified - bool hmac_cmp(const unsigned char *header, const size_t header_len, - const unsigned char *payload, const size_t payload_len) - { - return tls_crypt.hmac_cmp(header, header_len, payload, payload_len); - } - - size_t encrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) - { - return tls_crypt.encrypt(iv, out, olen, in, ilen); - } - - size_t decrypt(const unsigned char *iv, unsigned char *out, const size_t olen, - const unsigned char *in, const size_t ilen) - { - return tls_crypt.decrypt(iv, out, olen, in, ilen); - } - - private: - typename CryptoAlgs::Type digest; - typename CryptoAlgs::Type cipher; - int mode; - TLSCrypt<CRYPTO_API> tls_crypt; - }; - - template <typename CRYPTO_API> - class CryptoTLSCryptContext : public TLSCryptContext - { - public: - CryptoTLSCryptContext(const CryptoAlgs::Type digest_type, - const CryptoAlgs::Type cipher_type) - : digest(digest_type), - cipher(cipher_type) - { - } - - virtual size_t digest_size() const - { - return CryptoAlgs::size(digest); - } - - virtual size_t cipher_key_size() const - { - return CryptoAlgs::key_length(cipher); - } - - virtual TLSCryptInstance::Ptr new_obj_send() - { - return new CryptoTLSCryptInstance<CRYPTO_API>(digest, cipher, - CRYPTO_API::CipherContext::ENCRYPT); - } - - virtual TLSCryptInstance::Ptr new_obj_recv() - { - return new CryptoTLSCryptInstance<CRYPTO_API>(digest, cipher, - CRYPTO_API::CipherContext::DECRYPT); - } - - private: - CryptoAlgs::Type digest; - CryptoAlgs::Type cipher; - }; - - template <typename CRYPTO_API> - class CryptoTLSCryptFactory : public TLSCryptFactory - { - public: - virtual TLSCryptContext::Ptr new_obj(const CryptoAlgs::Type digest_type, - const CryptoAlgs::Type cipher_type) - { - return new CryptoTLSCryptContext<CRYPTO_API>(digest_type, cipher_type); - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/crypto/tls_crypt_v2.hpp b/Sources/OpenVPN3/openvpn/crypto/tls_crypt_v2.hpp deleted file mode 100644 index 00507fc..0000000 --- a/Sources/OpenVPN3/openvpn/crypto/tls_crypt_v2.hpp +++ /dev/null @@ -1,196 +0,0 @@ -// 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 { - constexpr static const char* tls_crypt_v2_server_key_name = "OpenVPN tls-crypt-v2 server key"; - constexpr static const char* tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key"; - - 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; - }; - - - 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; - }; - - // 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 */ diff --git a/Sources/OpenVPN3/openvpn/dco/dcocli.hpp b/Sources/OpenVPN3/openvpn/dco/dcocli.hpp deleted file mode 100644 index cb9563f..0000000 --- a/Sources/OpenVPN3/openvpn/dco/dcocli.hpp +++ /dev/null @@ -1,422 +0,0 @@ -// 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-2020 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 <vector> -#include <memory> -#include <sstream> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/buffer/asiobuf.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/tun/linux/client/tunmethods.hpp> -#include <openvpn/transport/dco.hpp> - -#ifdef ENABLE_KOVPN -#include <openvpn/kovpn/kovpn.hpp> -#include <openvpn/kovpn/kostats.hpp> -#include <openvpn/kovpn/rps_xps.hpp> -#include <openvpn/kovpn/kodevtun.hpp> -#elif ENABLE_OVPNDCO -#include <openvpn/dco/key.hpp> -#include <openvpn/tun/linux/client/sitnl.hpp> -#include <openvpn/common/uniqueptr.hpp> -#include <openvpn/tun/linux/client/genl.hpp> -#include <openvpn/buffer/buffer.hpp> -#else -#error either ENABLE_KOVPN or ENABLE_OVPNDCO must be defined -#endif - -#include <openvpn/dco/korekey.hpp> - -// client-side DCO (Data Channel Offload) module for Linux/kovpn - -namespace openvpn { - namespace DCOTransport { - - OPENVPN_EXCEPTION(dco_error); - - class ClientConfig : public DCO, - public TransportClientFactory, - public TunClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - std::string dev_name; - - DCO::TransportConfig transport; - DCO::TunConfig tun; - - unsigned int ping_restart_override = 0; - - virtual TunClientFactory::Ptr new_tun_factory(const DCO::TunConfig& conf, const OptionList& opt) override - { - tun = conf; - - // set a default MTU - if (!tun.tun_prop.mtu) - tun.tun_prop.mtu = 1500; - - // parse "dev" option - { - const Option* dev = opt.get_ptr("dev"); - if (dev) - dev_name = dev->get(1, 64); - else - dev_name = "ovpnc"; - } - - // parse ping-restart-override - ping_restart_override = opt.get_num<decltype(ping_restart_override)>("ping-restart-override", 1, ping_restart_override, 0, 3600); - - return TunClientFactory::Ptr(this); - } - - virtual TransportClientFactory::Ptr new_transport_factory(const DCO::TransportConfig& conf) override - { - transport = conf; - return TransportClientFactory::Ptr(this); - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) override; - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) override; - - static DCO::Ptr new_controller() - { - return new ClientConfig(); - } - - protected: - ClientConfig() = default; - }; - - class Client : public TransportClient, - public TunClient, - public AsyncResolvableUDP - { - friend class ClientConfig; - - typedef RCPtr<Client> Ptr; - - protected: - struct ProtoBase - { - ProtoBase() = default; - virtual IP::Addr server_endpoint_addr() const = 0; - virtual void close() = 0; - virtual ~ProtoBase() = default; - - ProtoBase(const ProtoBase&) = delete; - ProtoBase& operator=(const ProtoBase&) = delete; - }; - - struct UDP : public ProtoBase - { - explicit UDP(openvpn_io::io_context& io_context) - : resolver(io_context), - socket(io_context) - { - } - - virtual IP::Addr server_endpoint_addr() const override - { - return IP::Addr::from_asio(server_endpoint.address()); - } - - virtual void close() override - { - socket.close(); - resolver.cancel(); - } - - openvpn_io::ip::udp::resolver resolver; - openvpn_io::ip::udp::socket socket; - UDPTransport::AsioEndpoint server_endpoint; - }; - - public: - // transport methods - - virtual bool transport_send_queue_empty() override - { - return false; - } - - virtual bool transport_has_send_queue() override - { - return false; - } - - virtual unsigned int transport_send_queue_size() override - { - return 0; - } - - virtual void reset_align_adjust(const size_t align_adjust) override - { - } - - virtual void transport_stop_requeueing() override - { - } - - virtual void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const override - { - host = server_host; - port = server_port; - const IP::Addr addr = server_endpoint_addr(); - proto = "UDP"; - proto += addr.version_string(); - proto += "-DCO"; - ip_addr = addr.to_string(); - } - - virtual IP::Addr server_endpoint_addr() const override - { - if (proto) - return proto->server_endpoint_addr(); - else - return IP::Addr(); - } - - virtual Protocol transport_protocol() const override - { - switch (server_endpoint_addr().version()) - { - case IP::Addr::V4: - return Protocol(Protocol::UDPv4); - case IP::Addr::V6: - return Protocol(Protocol::UDPv6); - default: - return Protocol(); - } - } - - virtual void stop() override - { - stop_(); - } - - // tun methods - - virtual void set_disconnect() override - { - } - - virtual bool tun_send(BufferAllocated& buf) override // return true if send succeeded - { - return false; - } - - virtual std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - virtual std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - protected: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TransportClientParent* parent_arg) - : AsyncResolvableUDP(io_context_arg), - io_context(io_context_arg), - halt(false), - state(new TunProp::State()), - config(config_arg), - transport_parent(parent_arg), - tun_parent(nullptr), - peer_id(-1) - { - } - - virtual void transport_reparent(TransportClientParent* parent_arg) override - { - transport_parent = parent_arg; - } - - void transport_start_udp() - { - proto.reset(new UDP(io_context)); - if (config->transport.remote_list->endpoint_available(&server_host, &server_port, nullptr)) - { - start_connect_udp(); - } - else - { - transport_parent->transport_pre_resolve(); - async_resolve_name(server_host, server_port); - } - } - - // called after DNS resolution has succeeded or failed - void resolve_callback(const openvpn_io::error_code& error, - openvpn_io::ip::udp::resolver::results_type results) override - { - if (!halt) - { - if (!error) - { - // save resolved endpoint list in remote_list - config->transport.remote_list->set_endpoint_range(results); - start_connect_udp(); - } - else - { - std::ostringstream os; - os << "DNS resolve error on '" << server_host << "' for UDP session: " << error.message(); - config->transport.stats->error(Error::RESOLVE_ERROR); - stop_(); - transport_parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - // do UDP connect - void start_connect_udp() - { - config->transport.remote_list->get_endpoint(udp().server_endpoint); - OPENVPN_LOG("Contacting " << udp().server_endpoint << " via UDP"); - transport_parent->transport_wait(); - udp().socket.open(udp().server_endpoint.protocol()); - - if (config->transport.socket_protect) - { - if (!config->transport.socket_protect->socket_protect(udp().socket.native_handle(), server_endpoint_addr())) - { - stop(); - transport_parent->transport_error(Error::UNDEF, "socket_protect error (UDP)"); - return; - } - } - - udp().socket.async_connect(udp().server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) - { - self->start_impl_udp(error); - }); - } - - // start I/O on UDP socket - virtual void start_impl_udp(const openvpn_io::error_code& error) = 0; - - void transport_start_tcp() - { - OPENVPN_THROW(dco_error, "TCP not implemented yet"); // fixme for DCO - } - - UDP& udp() - { - return *static_cast<UDP*>(proto.get()); - } - - virtual void stop_() = 0; - - openvpn_io::io_context& io_context; - bool halt; - - TunProp::State::Ptr state; - - ClientConfig::Ptr config; - TransportClientParent* transport_parent; - TunClientParent* tun_parent; - - std::unique_ptr<ProtoBase> proto; - - ActionList::Ptr remove_cmds; - - std::string server_host; - std::string server_port; - - int peer_id; - }; - -#ifdef ENABLE_KOVPN - #include <openvpn/kovpn/kovpncli.hpp> - inline DCO::Ptr new_controller() - { - return KovpnClientConfig::new_controller(); - } - inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) - { - return TransportClient::Ptr(new KovpnClient(io_context, this, parent)); - } -#elif ENABLE_OVPNDCO - #include <openvpn/dco/ovpndcocli.hpp> - inline DCO::Ptr new_controller() - { - return ClientConfig::new_controller(); - } - inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) - { - return TransportClient::Ptr(new OvpnDcoClient(io_context, this, parent)); - } -#else -#error either ENABLE_KOVPN or ENABLE_OVPNDCO must be defined -#endif - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - Client* cli = static_cast<Client*>(transcli); - cli->tun_parent = &parent; - return TunClient::Ptr(cli); - } - } -} diff --git a/Sources/OpenVPN3/openvpn/dco/ipcollbase.hpp b/Sources/OpenVPN3/openvpn/dco/ipcollbase.hpp deleted file mode 100644 index dbf7d8d..0000000 --- a/Sources/OpenVPN3/openvpn/dco/ipcollbase.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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-2020 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 <sstream> -#include <unordered_map> -#include <mutex> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - class IPCollisionDetectBase - { - public: - OPENVPN_EXCEPTION(ip_collision); - - virtual void add(const std::string& addr_str, - const unsigned int unit, - ActionList& late_remove) { } - }; - -} diff --git a/Sources/OpenVPN3/openvpn/dco/key.hpp b/Sources/OpenVPN3/openvpn/dco/key.hpp deleted file mode 100644 index a65d473..0000000 --- a/Sources/OpenVPN3/openvpn/dco/key.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2020-2020 Lev Stipakov <lev@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 - -namespace openvpn { -namespace KoRekey { - -struct KeyDirection { - const unsigned char *cipher_key; - const unsigned char *hmac_key; // only CBC - unsigned char nonce_tail[12]; // only GCM - unsigned int cipher_key_size; - unsigned int hmac_key_size; // only CBC -}; - -struct KeyConfig { - KeyDirection encrypt; - KeyDirection decrypt; - - int key_id; - int remote_peer_id; - unsigned int cipher_alg; - unsigned int hmac_alg; // only CBC -}; - -} // namespace KoRekey -} // namespace openvpn \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/dco/kocrypto.hpp b/Sources/OpenVPN3/openvpn/dco/kocrypto.hpp deleted file mode 100644 index de4e8bd..0000000 --- a/Sources/OpenVPN3/openvpn/dco/kocrypto.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// 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-2020 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/>. - -// kovpn crypto wrappers - -#pragma once - -#include <cstring> // for std::memset, std::memcpy -#include <utility> // for std::move - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/crypto/bs64_data_limit.hpp> - -namespace openvpn { - namespace KoRekey { - - OPENVPN_EXCEPTION(korekey_error); - - struct Info { - Info() {} - - Info(const CryptoDCContext::Ptr& dc_context_delegate_arg, - const unsigned int key_id_arg, - const Frame::Ptr& frame_arg) - : dc_context_delegate(dc_context_delegate_arg), - key_id(key_id_arg), - frame(frame_arg) - { - } - - CryptoDCContext::Ptr dc_context_delegate; - CompressContext comp_ctx; - unsigned int key_id = 0; - int remote_peer_id = -1; - bool tcp_linear = false; - StaticKey encrypt_cipher; - StaticKey encrypt_hmac; - StaticKey decrypt_cipher; - StaticKey decrypt_hmac; - Frame::Ptr frame; - }; - - class Key - { - // noncopyable because of "opk.primary = &key" below - Key(const Key&) = delete; - Key& operator=(const Key&) = delete; - - public: - static void validate(const CryptoAlgs::Type cipher, - const CryptoAlgs::Type digest) - { - const CryptoAlgs::Alg& calg = CryptoAlgs::get(cipher); - const CryptoAlgs::Alg& halg = CryptoAlgs::get(digest); - - switch (cipher) - { - case CryptoAlgs::AES_128_GCM: - case CryptoAlgs::AES_192_GCM: - case CryptoAlgs::AES_256_GCM: - case CryptoAlgs::AES_128_CBC: - case CryptoAlgs::AES_192_CBC: - case CryptoAlgs::AES_256_CBC: - case CryptoAlgs::BF_CBC: -#ifdef ENABLE_OVPNDCO - case CryptoAlgs::NONE: -#endif - break; - default: - OPENVPN_THROW(korekey_error, "cipher alg " << calg.name() << " is not currently supported by kovpn"); - } - - if (calg.mode() == CryptoAlgs::CBC_HMAC) - { - switch (digest) - { - case CryptoAlgs::SHA1: - case CryptoAlgs::SHA256: -#ifdef ENABLE_OVPNDCO - case CryptoAlgs::NONE: -#endif - break; - default: - OPENVPN_THROW(korekey_error, "HMAC alg " << halg.name() << " is not currently supported by kovpn"); - } - } - } - - Key() {} - - protected: - const unsigned char *verify_key(const char *title, const StaticKey& sk, const size_t size_required) - { - if (sk.size() < size_required) - OPENVPN_THROW(korekey_error, title << ": insufficient key material, provided=" << sk.size() << " required=" << size_required); - return sk.data(); - } - - void set_nonce_tail(const char *title, unsigned char *dest, const size_t dest_size, const StaticKey& src) - { - const int NONCE_TAIL_SIZE = CryptoAlgs::AEAD_NONCE_TAIL_SIZE; - - const unsigned char *k = verify_key(title, src, NONCE_TAIL_SIZE); - if (dest_size < NONCE_TAIL_SIZE) - OPENVPN_THROW(korekey_error, title << ": cannot set"); - std::memcpy(dest, k, NONCE_TAIL_SIZE); - - // if dest is larger than NONCE_TAIL_SIZE, zero remaining bytes - if (dest_size > NONCE_TAIL_SIZE) - std::memset(dest + NONCE_TAIL_SIZE, 0, dest_size - NONCE_TAIL_SIZE); - } - }; - } -} - -#ifdef ENABLE_KOVPN -#include <openvpn/kovpn/kovpnkocrypto.hpp> -#elif ENABLE_OVPNDCO -#include <openvpn/dco/ovpndcokocrypto.hpp> -#else -#error either ENABLE_KOVPN or ENABLE_OVPNDCO must be defined -#endif diff --git a/Sources/OpenVPN3/openvpn/dco/korekey.hpp b/Sources/OpenVPN3/openvpn/dco/korekey.hpp deleted file mode 100644 index 0503d9d..0000000 --- a/Sources/OpenVPN3/openvpn/dco/korekey.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN 3 wrapper for kovpn crypto - -#ifndef OPENVPN_KOVPN_KOREKEY_H -#define OPENVPN_KOVPN_KOREKEY_H - -#include <openvpn/dco/kocrypto.hpp> - -namespace openvpn { - namespace KoRekey { - - class Receiver : public virtual RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Receiver> Ptr; - - virtual void rekey(const CryptoDCInstance::RekeyType type, - const Info& info) = 0; - - virtual void explicit_exit_notify() {} - }; - - class Instance : public CryptoDCInstance - { - public: - Instance(const Receiver::Ptr& rcv_arg, - const CryptoDCContext::Ptr& dc_context_delegate, - const unsigned int key_id, - const Frame::Ptr& frame) - : rcv(rcv_arg), - info(dc_context_delegate, key_id, frame) - { - } - - // Initialization - - virtual unsigned int defined() const override - { - return CIPHER_DEFINED|HMAC_DEFINED|EXPLICIT_EXIT_NOTIFY_DEFINED; - } - - virtual void init_cipher(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) override - { - info.encrypt_cipher = std::move(encrypt_key); - info.decrypt_cipher = std::move(decrypt_key); - } - - virtual void init_hmac(StaticKey&& encrypt_key, - StaticKey&& decrypt_key) override - { - info.encrypt_hmac = std::move(encrypt_key); - info.decrypt_hmac = std::move(decrypt_key); - } - - virtual void init_pid(const int send_form, - const int recv_mode, - const int recv_form, - const char *recv_name, - const int recv_unit, - const SessionStats::Ptr& recv_stats_arg) override - { - info.tcp_linear = (recv_mode == PacketIDReceive::TCP_MODE); - } - - virtual void init_remote_peer_id(const int remote_peer_id) override - { - info.remote_peer_id = remote_peer_id; - } - - virtual bool consider_compression(const CompressContext& comp_ctx) override - { - info.comp_ctx = comp_ctx; - return false; - } - - // Rekeying - - virtual void rekey(const RekeyType type) override - { - rcv->rekey(type, info); - } - - virtual void explicit_exit_notify() override - { - rcv->explicit_exit_notify(); - } - - // Encrypt/Decrypt -- data channel handled by kernel, so these methods - // should never be reached. - - // returns true if packet ID is close to wrapping - virtual bool encrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) override - { - throw korekey_error("encrypt"); - } - - virtual Error::Type decrypt(BufferAllocated& buf, const PacketID::time_t now, const unsigned char *op32) override - { - throw korekey_error("decrypt"); - } - - private: - Receiver::Ptr rcv; - Info info; - }; - - class Context : public CryptoDCContext - { - public: - Context(const CryptoAlgs::Type cipher, - const CryptoAlgs::Type digest, - const CryptoAlgs::KeyDerivation key_method, - CryptoDCFactory& dc_factory_delegate, - const Receiver::Ptr& rcv_arg, - const Frame::Ptr& frame_arg) - : CryptoDCContext(key_method), - rcv(rcv_arg), - dc_context_delegate(dc_factory_delegate.new_obj(cipher, digest, key_method)), - frame(frame_arg) - { - Key::validate(cipher, digest); - } - - virtual CryptoDCInstance::Ptr new_obj(const unsigned int key_id) override - { - return new Instance(rcv, dc_context_delegate, key_id, frame); - } - - // Info for ProtoContext::options_string - - virtual Info crypto_info() override - { - return dc_context_delegate->crypto_info(); - } - - // Info for ProtoContext::link_mtu_adjust - - virtual size_t encap_overhead() const override - { - return dc_context_delegate->encap_overhead(); - } - - private: - Receiver::Ptr rcv; - CryptoDCContext::Ptr dc_context_delegate; - Frame::Ptr frame; - }; - - class Factory : public CryptoDCFactory - { - public: - Factory(const CryptoDCFactory::Ptr& dc_factory_delegate_arg, - const Receiver::Ptr& rcv_arg, - const Frame::Ptr& frame_arg) - : dc_factory_delegate(dc_factory_delegate_arg), - rcv(rcv_arg), - frame(frame_arg) - { - } - - virtual CryptoDCContext::Ptr new_obj(const CryptoAlgs::Type cipher, - const CryptoAlgs::Type digest, - const CryptoAlgs::KeyDerivation key_method) override - { - return new Context(cipher, digest, key_method, *dc_factory_delegate, rcv, frame); - } - - private: - CryptoDCFactory::Ptr dc_factory_delegate; - Receiver::Ptr rcv; - Frame::Ptr frame; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/dco/ovpndcocli.hpp b/Sources/OpenVPN3/openvpn/dco/ovpndcocli.hpp deleted file mode 100644 index 6a7d73a..0000000 --- a/Sources/OpenVPN3/openvpn/dco/ovpndcocli.hpp +++ /dev/null @@ -1,375 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2020-2020 Lev Stipakov <lev@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/>. - -// tun/transport client for ovpn-dco - -class OvpnDcoClient : public Client, public KoRekey::Receiver { - friend class ClientConfig; - friend class GeNL; - - typedef RCPtr<OvpnDcoClient> Ptr; - typedef GeNL<OvpnDcoClient *> GeNLImpl; - - struct PacketFrom { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - -public: - virtual void tun_start(const OptionList &opt, TransportClient &transcli, - CryptoDCSettings &dc_settings) override { - // notify parent - tun_parent->tun_pre_tun_config(); - - // parse pushed options - TunBuilderCapture::Ptr po; - TunBuilderBase *builder; - - if (config->builder) { - builder = config->builder; - } else { - po.reset(new TunBuilderCapture()); - builder = po.get(); - } - - TunProp::configure_builder( - builder, state.get(), config->transport.stats.get(), - server_endpoint_addr(), config->tun.tun_prop, opt, nullptr, false); - - if (po) - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - - if (config->builder) { - config->builder->tun_builder_dco_establish(); - } else { - ActionList::Ptr add_cmds = new ActionList(); - remove_cmds.reset(new ActionListReversed()); - - std::vector<IP::Route> rtvec; - - TUN_LINUX::tun_config(config->dev_name, *po, &rtvec, *add_cmds, - *remove_cmds, true); - - // execute commands to bring up interface - add_cmds->execute_log(); - } - - // Add a hook so ProtoContext will call back to - // rekey() on rekey ops. - dc_settings.set_factory(CryptoDCFactory::Ptr(new KoRekey::Factory( - dc_settings.factory(), this, config->transport.frame))); - - // signal that we are connected - tun_parent->tun_connected(); - } - - virtual std::string tun_name() const override { return "ovpn-dco"; } - - virtual void transport_start() override { transport_start_udp(); } - - virtual bool transport_send_const(const Buffer &buf) override { - return send(buf); - } - - virtual bool transport_send(BufferAllocated &buf) override { - return send(buf); - } - - bool send(const Buffer &buf) { - if (config->builder) { - pipe->write_some(buf.const_buffer()); - } else { - genl->send_data(buf.c_data(), buf.size()); - } - return true; - } - - virtual void start_impl_udp(const openvpn_io::error_code &error) override { - if (halt) - return; - - if (!error) { - auto &sock = udp().socket; - auto local = sock.local_endpoint(); - auto remote = sock.remote_endpoint(); - - TunBuilderBase *tb = config->builder; - if (tb) { - tb->tun_builder_new(); - // pipe fd which is used to communicate to kernel - int fd = - tb->tun_builder_dco_enable(sock.native_handle(), config->dev_name); - if (fd == -1) { - stop_(); - transport_parent->transport_error(Error::TUN_IFACE_CREATE, - "error creating ovpn-dco device"); - return; - } - pipe.reset(new openvpn_io::posix::stream_descriptor(io_context, fd)); - tb->tun_builder_dco_new_peer(local.address().to_string(), local.port(), - remote.address().to_string(), - remote.port()); - - queue_read_pipe(nullptr); - - transport_parent->transport_connecting(); - } else { - std::ostringstream os; - int res = TunNetlink::iface_new(os, config->dev_name, "ovpn-dco"); - if (res != 0) { - stop_(); - transport_parent->transport_error(Error::TUN_IFACE_CREATE, os.str()); - } else { - genl.reset(new GeNLImpl( - io_context, if_nametoindex(config->dev_name.c_str()), this)); - - genl->start_vpn(sock.native_handle()); - genl->new_peer(local, remote); - - transport_parent->transport_connecting(); - } - } - } else { - std::ostringstream os; - os << "UDP connect error on '" << server_host << ':' << server_port - << "' (" << udp().server_endpoint << "): " << error.message(); - config->transport.stats->error(Error::UDP_CONNECT_ERROR); - stop_(); - transport_parent->transport_error(Error::UNDEF, os.str()); - } - } - - virtual void stop_() override { - if (!halt) { - halt = true; - - if (config->builder) { - config->builder->tun_builder_teardown(true); - if (pipe) - pipe->close(); - } else { - std::ostringstream os; - if (genl) - genl->stop(); - int res = TunNetlink::iface_del(os, config->dev_name); - if (res != 0) { - OPENVPN_LOG("ovpndcocli: error deleting iface ovpn:" << os.str()); - } - } - } - } - - virtual void rekey(const CryptoDCInstance::RekeyType rktype, - const KoRekey::Info &rkinfo) override { - if (halt) - return; - - if (config->builder) - rekey_impl_tb(rktype, rkinfo); - else - rekey_impl(rktype, rkinfo); - } - - void rekey_impl(const CryptoDCInstance::RekeyType rktype, - const KoRekey::Info &rkinfo) { - KoRekey::OvpnDcoKey key(rktype, rkinfo); - auto kc = key(); - - switch (rktype) { - case CryptoDCInstance::ACTIVATE_PRIMARY: - genl->new_key(OVPN_KEY_SLOT_PRIMARY, kc); - - handle_keepalive(); - break; - - case CryptoDCInstance::NEW_SECONDARY: - genl->new_key(OVPN_KEY_SLOT_SECONDARY, kc); - break; - - case CryptoDCInstance::PRIMARY_SECONDARY_SWAP: - genl->swap_keys(); - break; - - case CryptoDCInstance::DEACTIVATE_SECONDARY: - genl->del_key(OVPN_KEY_SLOT_SECONDARY); - break; - - case CryptoDCInstance::DEACTIVATE_ALL: - // TODO: deactivate all keys - OPENVPN_LOG("ovpndcocli: deactivate all keys"); - break; - - default: - OPENVPN_LOG("ovpndcocli: unknown rekey type: " << rktype); - break; - } - } - - void rekey_impl_tb(const CryptoDCInstance::RekeyType rktype, - const KoRekey::Info &rkinfo) { - KoRekey::OvpnDcoKey key(rktype, rkinfo); - auto kc = key(); - - TunBuilderBase *tb = config->builder; - - switch (rktype) { - case CryptoDCInstance::ACTIVATE_PRIMARY: - tb->tun_builder_dco_new_key(OVPN_KEY_SLOT_PRIMARY, kc); - - handle_keepalive(); - break; - - case CryptoDCInstance::NEW_SECONDARY: - tb->tun_builder_dco_new_key(OVPN_KEY_SLOT_SECONDARY, kc); - break; - - case CryptoDCInstance::PRIMARY_SECONDARY_SWAP: - tb->tun_builder_dco_swap_keys(); - break; - - case CryptoDCInstance::DEACTIVATE_SECONDARY: - tb->tun_builder_dco_del_key(OVPN_KEY_SLOT_SECONDARY); - break; - - case CryptoDCInstance::DEACTIVATE_ALL: - // TODO: deactivate all keys - OPENVPN_LOG("ovpndcocli: deactivate all keys"); - break; - - default: - OPENVPN_LOG("ovpndcocli: unknown rekey type: " << rktype); - break; - } - } - - bool tun_read_handler(BufferAllocated &buf) { - if (halt) - return false; - - int8_t cmd = -1; - buf.read(&cmd, sizeof(cmd)); - - switch (cmd) { - case OVPN_CMD_PACKET: - transport_parent->transport_recv(buf); - break; - - case OVPN_CMD_DEL_PEER: { - stop_(); - int8_t reason = -1; - buf.read(&reason, sizeof(reason)); - switch (reason) { - case OVPN_DEL_PEER_REASON_EXPIRED: - transport_parent->transport_error(Error::TRANSPORT_ERROR, - "keepalive timeout"); - break; - - default: - std::ostringstream os; - os << "peer deleted, reason " << reason; - transport_parent->transport_error(Error::TUN_HALT, os.str()); - break; - } - break; - } - - case -1: - // consider all errors as fatal - stop_(); - transport_parent->transport_error(Error::TUN_HALT, buf_to_string(buf)); - return false; - break; - - default: - OPENVPN_LOG("Unknown ovpn-dco cmd " << cmd); - break; - } - - return true; - } - -private: - OvpnDcoClient(openvpn_io::io_context &io_context_arg, - ClientConfig *config_arg, TransportClientParent *parent_arg) - : Client(io_context_arg, config_arg, parent_arg) {} - - void handle_keepalive() { - // since userspace doesn't know anything about presense or - // absense of data channel traffic, ping should be handled in kernel - if (transport_parent->is_keepalive_enabled()) { - unsigned int keepalive_interval = 0; - unsigned int keepalive_timeout = 0; - - // In addition to disabling userspace keepalive, - // this call also assigns keepalive values to provided arguments - // default keepalive values could be overwritten by config values, - // which in turn could be overwritten by pushed options - transport_parent->disable_keepalive(keepalive_interval, - keepalive_timeout); - - // Allow overide of keepalive timeout - if (config->ping_restart_override) - keepalive_timeout = config->ping_restart_override; - - if (config->builder) { - config->builder->tun_builder_dco_set_peer(keepalive_interval, - keepalive_timeout); - } else { - // enable keepalive in kernel - genl->set_peer(keepalive_interval, keepalive_timeout); - } - } - } - - void queue_read_pipe(PacketFrom *pkt) { - if (!pkt) { - pkt = new PacketFrom(); - } - // good enough values for control channel packets - pkt->buf.reset(512, 3072, - BufferAllocated::GROW | BufferAllocated::CONSTRUCT_ZERO | - BufferAllocated::DESTRUCT_ZERO); - pipe->async_read_some( - pkt->buf.mutable_buffer(), - [self = Ptr(this), - pkt = PacketFrom::SPtr(pkt)](const openvpn_io::error_code &error, - const size_t bytes_recvd) mutable { - if (!error) { - pkt->buf.set_size(bytes_recvd); - if (self->tun_read_handler(pkt->buf)) - self->queue_read_pipe(pkt.release()); - } else { - if (!self->halt) { - OPENVPN_LOG("ovpn-dco pipe read error: " << error.message()); - self->stop_(); - self->transport_parent->transport_error(Error::TUN_HALT, - error.message()); - } - } - }); - } - - // used to communicate to kernel via privileged process - std::unique_ptr<openvpn_io::posix::stream_descriptor> pipe; - - GeNLImpl::Ptr genl; -}; \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/dco/ovpndcokocrypto.hpp b/Sources/OpenVPN3/openvpn/dco/ovpndcokocrypto.hpp deleted file mode 100644 index f23585a..0000000 --- a/Sources/OpenVPN3/openvpn/dco/ovpndcokocrypto.hpp +++ /dev/null @@ -1,144 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2020-2020 Lev Stipakov <lev@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/>. - -// ovpn-dco crypto wrappers - -#pragma once - -namespace openvpn { -namespace KoRekey { - -/** - * @brief Parses key information into format consumed by ovpn-dco. - * - */ -class OvpnDcoKey : public Key { -public: - OvpnDcoKey(const CryptoDCInstance::RekeyType rktype, const Info &rkinfo) { - std::memset(&kc, 0, sizeof(kc)); - - kc.remote_peer_id = rkinfo.remote_peer_id; - - const CryptoDCContext::Info ci = rkinfo.dc_context_delegate->crypto_info(); - const CryptoAlgs::Alg &calg = CryptoAlgs::get(ci.cipher_alg); - switch (ci.cipher_alg) { - case CryptoAlgs::NONE: - kc.cipher_alg = OVPN_CIPHER_ALG_NONE; - kc.encrypt.cipher_key_size = 0; - break; - case CryptoAlgs::AES_128_GCM: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_GCM; - kc.encrypt.cipher_key_size = 128 / 8; - break; - case CryptoAlgs::AES_192_GCM: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_GCM; - kc.encrypt.cipher_key_size = 192 / 8; - break; - case CryptoAlgs::AES_256_GCM: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_GCM; - kc.encrypt.cipher_key_size = 256 / 8; - break; - case CryptoAlgs::AES_128_CBC: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_CBC; - kc.encrypt.cipher_key_size = 128 / 8; - break; - case CryptoAlgs::AES_192_CBC: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_CBC; - kc.encrypt.cipher_key_size = 192 / 8; - break; - case CryptoAlgs::AES_256_CBC: - kc.cipher_alg = OVPN_CIPHER_ALG_AES_CBC; - kc.encrypt.cipher_key_size = 256 / 8; - break; - default: - OPENVPN_THROW(korekey_error, - "cipher alg " << calg.name() - << " is not currently supported by ovpn-dco"); - break; - } - kc.decrypt.cipher_key_size = kc.encrypt.cipher_key_size; - - if (kc.cipher_alg != CryptoAlgs::NONE) - { - kc.encrypt.cipher_key = verify_key("cipher encrypt", rkinfo.encrypt_cipher, - kc.encrypt.cipher_key_size); - kc.decrypt.cipher_key = verify_key("cipher decrypt", rkinfo.decrypt_cipher, - kc.decrypt.cipher_key_size); - } - - switch (calg.mode()) { - case CryptoAlgs::CBC_HMAC: - // if CBC mode, process HMAC digest - { - const CryptoAlgs::Alg &halg = CryptoAlgs::get(ci.hmac_alg); - switch (ci.hmac_alg) { - case CryptoAlgs::SHA256: - kc.hmac_alg = OVPN_HMAC_ALG_SHA256; - break; - case CryptoAlgs::SHA512: - kc.hmac_alg = OVPN_HMAC_ALG_SHA512; - break; - case CryptoAlgs::NONE: - kc.hmac_alg = OVPN_HMAC_ALG_NONE; - break; - default: - OPENVPN_THROW(korekey_error, - "HMAC alg " - << halg.name() - << " is not currently supported by ovpn-dco"); - } - kc.encrypt.hmac_key_size = halg.size(); - kc.decrypt.hmac_key_size = kc.encrypt.hmac_key_size; - - // set hmac keys - kc.encrypt.hmac_key = verify_key("hmac encrypt", rkinfo.encrypt_hmac, - kc.encrypt.hmac_key_size); - kc.decrypt.hmac_key = verify_key("hmac decrypt", rkinfo.decrypt_hmac, - kc.decrypt.hmac_key_size); - } - break; - - case CryptoAlgs::AEAD: - set_nonce_tail("AEAD nonce tail encrypt", kc.encrypt.nonce_tail, - sizeof(kc.encrypt.nonce_tail), rkinfo.encrypt_hmac); - set_nonce_tail("AEAD nonce tail decrypt", kc.decrypt.nonce_tail, - sizeof(kc.decrypt.nonce_tail), rkinfo.decrypt_hmac); - - break; - - default: { - // should have been caught above - throw korekey_error("internal error"); - } - } - - kc.key_id = rkinfo.key_id; - } - - const struct KeyConfig *operator()() const { return &kc; } - -private: - struct KeyConfig kc; -}; - -} // namespace KoRekey -} // namespace openvpn \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/error/error.hpp b/Sources/OpenVPN3/openvpn/error/error.hpp deleted file mode 100644 index e371918..0000000 --- a/Sources/OpenVPN3/openvpn/error/error.hpp +++ /dev/null @@ -1,194 +0,0 @@ -// 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-2020 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/>. - -// Define OpenVPN error codes and a method to convert them to a string representation - -#ifndef OPENVPN_ERROR_ERROR_H -#define OPENVPN_ERROR_ERROR_H - -#include <openvpn/common/arraysize.hpp> - -namespace openvpn { - namespace Error { - - enum Type { - SUCCESS=0, // no error - NETWORK_RECV_ERROR, // errors receiving on network socket - NETWORK_EOF_ERROR, // EOF received on TCP network socket - NETWORK_SEND_ERROR, // errors sending on network socket - NETWORK_UNAVAILABLE, // network unavailable - DECRYPT_ERROR, // data channel encrypt/decrypt error - HMAC_ERROR, // HMAC verification failure - REPLAY_ERROR, // error from PacketIDReceive - BUFFER_ERROR, // exception thrown in Buffer methods - CC_ERROR, // general control channel errors - BAD_SRC_ADDR, // packet from unknown source address - COMPRESS_ERROR, // compress/decompress errors on data channel - RESOLVE_ERROR, // DNS resolution error - SOCKET_PROTECT_ERROR, // Error calling protect() method on socket - TUN_READ_ERROR, // read errors on tun/tap interface - TUN_WRITE_ERROR, // write errors on tun/tap interface - TUN_FRAMING_ERROR, // error with tun PF_INET/PF_INET6 prefix - TUN_SETUP_FAILED, // error setting up tun/tap interface - TUN_IFACE_CREATE, // error creating tun/tap interface - TUN_IFACE_DISABLED, // tun/tap interface is disabled - TUN_ERROR, // general tun error - TUN_REGISTER_RINGS_ERROR, // error registering ring buffers with wintun - TAP_NOT_SUPPORTED, // dev tap is present in profile but not supported - REROUTE_GW_NO_DNS, // redirect-gateway specified without alt DNS servers - TRANSPORT_ERROR, // general transport error - TCP_OVERFLOW, // TCP output queue overflow - TCP_SIZE_ERROR, // bad embedded uint16_t TCP packet size - TCP_CONNECT_ERROR, // client error on TCP connect - UDP_CONNECT_ERROR, // client error on UDP connect - SSL_ERROR, // errors resulting from read/write on SSL object - SSL_PARTIAL_WRITE, // SSL object did not process all written cleartext - SSL_CA_MD_TOO_WEAK, // CA message digest is too weak - SSL_CA_KEY_TOO_SMALL, // CA key is too small - SSL_DH_KEY_TOO_SMALL, // DH key is too small - ENCAPSULATION_ERROR, // exceptions thrown during packet encapsulation - EPKI_CERT_ERROR, // error obtaining certificate from External PKI provider - EPKI_SIGN_ERROR, // error obtaining RSA signature from External PKI provider - HANDSHAKE_TIMEOUT, // handshake failed to complete within given time frame - KEEPALIVE_TIMEOUT, // lost contact with peer - INACTIVE_TIMEOUT, // disconnected due to inactive timer - CONNECTION_TIMEOUT, // connection failed to establish within given time - PRIMARY_EXPIRE, // primary key context expired - TLS_VERSION_MIN, // peer cannot handshake at our minimum required TLS version - TLS_AUTH_FAIL, // tls-auth HMAC verification failed - TLS_CRYPT_META_FAIL, // tls-crypt-v2 metadata verification failed - CERT_VERIFY_FAIL, // peer certificate verification failure - PEM_PASSWORD_FAIL, // incorrect or missing PEM private key decryption password - AUTH_FAILED, // general authentication failure - CLIENT_HALT, // HALT message from server received - CLIENT_RESTART, // RESTART message from server received - TUN_HALT, // halt command from tun interface - RELAY, // RELAY message from server received - RELAY_ERROR, // RELAY error - N_PAUSE, // Number of transitions to Pause state - N_RECONNECT, // Number of reconnections - N_KEY_LIMIT_RENEG, // Number of renegotiations triggered by per-key limits such as data or packet limits - KEY_STATE_ERROR, // Received packet didn't match expected key state - PROXY_ERROR, // HTTP proxy error - PROXY_NEED_CREDS, // HTTP proxy needs credentials - - // key event errors - KEV_NEGOTIATE_ERROR, - KEV_PENDING_ERROR, - N_KEV_EXPIRE, - KEY_EXPANSION_ERROR, - - // Packet ID error detail - PKTID_INVALID, - PKTID_BACKTRACK, - PKTID_EXPIRE, - PKTID_REPLAY, - PKTID_TIME_BACKTRACK, - - N_ERRORS, - - // undefined error - UNDEF=SUCCESS, - }; - - inline const char *name(const size_t type) - { - static const char *names[] = { - "SUCCESS", - "NETWORK_RECV_ERROR", - "NETWORK_EOF_ERROR", - "NETWORK_SEND_ERROR", - "NETWORK_UNAVAILABLE", - "DECRYPT_ERROR", - "HMAC_ERROR", - "REPLAY_ERROR", - "BUFFER_ERROR", - "CC_ERROR", - "BAD_SRC_ADDR", - "COMPRESS_ERROR", - "RESOLVE_ERROR", - "SOCKET_PROTECT_ERROR", - "TUN_READ_ERROR", - "TUN_WRITE_ERROR", - "TUN_FRAMING_ERROR", - "TUN_SETUP_FAILED", - "TUN_IFACE_CREATE", - "TUN_IFACE_DISABLED", - "TUN_ERROR", - "TUN_REGISTER_RINGS_ERROR", - "TAP_NOT_SUPPORTED", - "REROUTE_GW_NO_DNS", - "TRANSPORT_ERROR", - "TCP_OVERFLOW", - "TCP_SIZE_ERROR", - "TCP_CONNECT_ERROR", - "UDP_CONNECT_ERROR", - "SSL_ERROR", - "SSL_PARTIAL_WRITE", - "SSL_CA_MD_TOO_WEAK", - "SSL_CA_KEY_TOO_SMALL", - "SSL_DH_KEY_TOO_SMALL", - "ENCAPSULATION_ERROR", - "EPKI_CERT_ERROR", - "EPKI_SIGN_ERROR", - "HANDSHAKE_TIMEOUT", - "KEEPALIVE_TIMEOUT", - "INACTIVE_TIMEOUT", - "CONNECTION_TIMEOUT", - "PRIMARY_EXPIRE", - "TLS_VERSION_MIN", - "TLS_AUTH_FAIL", - "TLS_CRYPT_META_FAIL", - "CERT_VERIFY_FAIL", - "PEM_PASSWORD_FAIL", - "AUTH_FAILED", - "CLIENT_HALT", - "CLIENT_RESTART", - "TUN_HALT", - "RELAY", - "RELAY_ERROR", - "N_PAUSE", - "N_RECONNECT", - "N_KEY_LIMIT_RENEG", - "KEY_STATE_ERROR", - "PROXY_ERROR", - "PROXY_NEED_CREDS", - "KEV_NEGOTIATE_ERROR", - "KEV_PENDING_ERROR", - "N_KEV_EXPIRE", - "KEV_EXPANSION_ERROR", - "PKTID_INVALID", - "PKTID_BACKTRACK", - "PKTID_EXPIRE", - "PKTID_REPLAY", - "PKTID_TIME_BACKTRACK", - }; - - static_assert(N_ERRORS == array_size(names), "error names array inconsistency"); - if (type < N_ERRORS) - return names[type]; - else - return "UNKNOWN_ERROR_TYPE"; - } - } -} // namespace openvpn - -#endif // OPENVPN_ERROR_ERROR_H diff --git a/Sources/OpenVPN3/openvpn/error/excode.hpp b/Sources/OpenVPN3/openvpn/error/excode.hpp deleted file mode 100644 index 874e3c4..0000000 --- a/Sources/OpenVPN3/openvpn/error/excode.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// 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-2020 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_ERROR_EXCODE_H -#define OPENVPN_ERROR_EXCODE_H - -#include <string> -#include <exception> - -#include <openvpn/error/error.hpp> - -namespace openvpn { - - // Define an exception object that allows an Error::Type code to be thrown - class ExceptionCode : public std::exception - { - enum { - FATAL_FLAG = 0x80000000 - }; - - public: - ExceptionCode() - : code_(0) {} - ExceptionCode(const Error::Type code) - : code_(code) {} - ExceptionCode(const Error::Type code, const bool fatal) - : code_(mkcode(code, fatal)) {} - - void set_code(const Error::Type code) - { - code_ = code; - } - - void set_code(const Error::Type code, const bool fatal) - { - code_ = mkcode(code, fatal); - } - - Error::Type code() const { return Error::Type(code_ & ~FATAL_FLAG); } - bool fatal() const { return (code_ & FATAL_FLAG) != 0; } - - bool code_defined() const { return code_ != 0; } - - virtual ~ExceptionCode() throw() {} - - private: - static unsigned int mkcode(const Error::Type code, const bool fatal) - { - unsigned int ret = code; - if (fatal) - ret |= FATAL_FLAG; - return ret; - } - - unsigned int code_; - }; - - class ErrorCode : public ExceptionCode - { - public: - ErrorCode(const Error::Type code, const bool fatal, const std::string& err) - : ExceptionCode(code, fatal) , err_(err) {} - - virtual const char* what() const throw() { return err_.c_str(); } - - virtual ~ErrorCode() throw() {} - - private: - std::string err_; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/frame/frame.hpp b/Sources/OpenVPN3/openvpn/frame/frame.hpp deleted file mode 100644 index 83d290d..0000000 --- a/Sources/OpenVPN3/openvpn/frame/frame.hpp +++ /dev/null @@ -1,309 +0,0 @@ -// 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-2020 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/>. - -// Define Frame classes. These classes act as a factory for standard protocol -// buffers and also try to optimize the buffers for alignment. - -#ifndef OPENVPN_FRAME_FRAME_H -#define OPENVPN_FRAME_FRAME_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - class Frame : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Frame> Ptr; - - // Frame context types -- we maintain a Context object for each context type - enum { - ENCRYPT_WORK=0, - DECRYPT_WORK, - COMPRESS_WORK, - DECOMPRESS_WORK, - READ_LINK_UDP, - READ_LINK_TCP, - READ_TUN, - READ_BIO_MEMQ_DGRAM, - READ_BIO_MEMQ_STREAM, - READ_SSL_CLEARTEXT, - WRITE_SSL_INIT, - WRITE_SSL_CLEARTEXT, - WRITE_ACK_STANDALONE, - WRITE_DC_MSG, - WRITE_HTTP, - READ_HTTP, - - N_ALIGN_CONTEXTS - }; - - OPENVPN_SIMPLE_EXCEPTION(frame_context_index); - - // We manage an array of Context objects, one for each - // Frame context above. - class Context - { - public: - Context() - { - headroom_ = 0; - payload_ = 0; - tailroom_ = 0; - buffer_flags_ = 0; - align_adjust_ = 0; - - adj_headroom_ = 0; - adj_capacity_ = 0; - } - - Context(const size_t headroom, - const size_t payload, - const size_t tailroom, - const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary - const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size - const unsigned int buffer_flags) // flags passed to BufferAllocated constructor - { - headroom_ = headroom; - payload_ = payload; - tailroom_ = tailroom; - buffer_flags_ = buffer_flags; - align_adjust_ = align_adjust; - align_block_ = align_block; - recalc_derived(); - } - - void reset_align_adjust(const size_t align_adjust) - { - align_adjust_ = align_adjust; - } - - size_t headroom() const { return adj_headroom_; } - size_t payload() const { return payload_; } - size_t tailroom() const { return tailroom_; } - size_t capacity() const { return adj_capacity_; } - unsigned int buffer_flags() const { return buffer_flags_; } - - // Calculate a starting offset into a buffer object, dealing with - // headroom and alignment issues. - size_t prepare(Buffer& buf) const - { - buf.reset(capacity(), buffer_flags()); - buf.init_headroom(actual_headroom(buf.c_data_raw())); - return payload(); - } - - // Realign a buffer to headroom - void realign(Buffer& buf) const - { - buf.realign(actual_headroom(buf.c_data_raw())); - } - - // Return a new BufferAllocated object initialized with the given data. - BufferPtr copy(const unsigned char *data, const size_t size) const - { - const size_t cap = size + headroom() + tailroom(); - BufferPtr b = new BufferAllocated(cap, buffer_flags()); - b->init_headroom(actual_headroom(b->c_data_raw())); - b->write(data, size); - return b; - } - - // Return a new BufferAllocated object by value initialized with the given data. - BufferAllocated copy_by_value(const unsigned char *data, const size_t size) const - { - const size_t cap = size + headroom() + tailroom(); - BufferAllocated b(cap, buffer_flags()); - b.init_headroom(actual_headroom(b.c_data_raw())); - b.write(data, size); - return b; - } - - // Return a new BufferAllocated object initialized with - // the data in given buffer. buf may be empty or undefined. - BufferPtr copy(const BufferPtr& buf) const - { - const size_t size = buf ? buf->size() : 0; - const size_t cap = size + headroom() + tailroom(); - BufferPtr b = new BufferAllocated(cap, buffer_flags()); - b->init_headroom(actual_headroom(b->c_data_raw())); - if (size) - b->write(buf->c_data(), size); - return b; - } - - // How much payload space left in buffer - size_t remaining_payload(const Buffer& buf) const - { - if (payload() > buf.size()) - return payload() - buf.size(); - else - return 0; - } - - // Used to set the capacity of a group of Context objects - // to the highest capacity of any one of the members. - void standardize_capacity(const size_t newcap) - { - if (newcap > adj_capacity_) - adj_capacity_ = newcap; - } - -#ifndef OPENVPN_NO_IO - // return a openvpn_io::mutable_buffer object used by - // asio read methods. - openvpn_io::mutable_buffer mutable_buffer(Buffer& buf) const - { - return openvpn_io::mutable_buffer(buf.data(), remaining_payload(buf)); - } - - // clamped version of mutable_buffer - openvpn_io::mutable_buffer mutable_buffer_clamp(Buffer& buf) const - { - return openvpn_io::mutable_buffer(buf.data(), buf_clamp_read(remaining_payload(buf))); - } -#endif - - std::string info() const - { - std::ostringstream info; - info << "head=" << headroom_ << "[" << adj_headroom_ << "] " - << "pay=" << payload_ << ' ' - << "tail=" << tailroom_ << ' ' - << "cap=" << adj_capacity_ << ' ' - << "bf=" << buffer_flags_ << ' ' - << "align_adj=" << align_adjust_ << ' ' - << "align_block=" << align_block_; - return info.str(); - } - - private: - // recalculate derived values when object parameters are modified - void recalc_derived() - { - // calculate adjusted headroom due to worst-case alignment loss - adj_headroom_ = headroom_ + align_block_; - - // calculate capacity - adj_capacity_ = adj_headroom_ + payload_ + tailroom_; - } - - // add a small delta ( < align_block) to headroom so that the point - // after the first align_adjust bytes of the buffer starting at base - // will be aligned on an align_block boundary - size_t actual_headroom(const void *base) const - { - return headroom_ + (-(size_t(base) + headroom_ + align_adjust_) & (align_block_ - 1)); - } - - // parameters - size_t headroom_; - size_t payload_; - size_t tailroom_; - size_t align_adjust_; - size_t align_block_; - unsigned int buffer_flags_; - - // derived - size_t adj_headroom_; - size_t adj_capacity_; - }; - - Frame() {} - - explicit Frame(const Context& c) { set_default_context(c); } - - // set the default context - void set_default_context(const Context& c) - { - for (int i = 0; i < N_ALIGN_CONTEXTS; ++i) - contexts[i] = c; - } - - // Calculate a starting offset into a buffer object, dealing with - // headroom and alignment issues. context should be one of - // the context types above. Returns payload size of buffer. - size_t prepare(const unsigned int context, Buffer& buf) const - { - return (*this)[context].prepare(buf); - } - - BufferPtr prepare(const unsigned int context) const - { - BufferPtr buf(new BufferAllocated()); - prepare(context, *buf); - return buf; - } - - size_t n_contexts() const { return N_ALIGN_CONTEXTS; } - - Context& operator[](const size_t i) - { - if (i >= N_ALIGN_CONTEXTS) - throw frame_context_index(); - return contexts[i]; - } - - const Context& operator[](const size_t i) const - { - if (i >= N_ALIGN_CONTEXTS) - throw frame_context_index(); - return contexts[i]; - } - - void standardize_capacity(const unsigned int context_mask) - { - size_t i; - size_t max_cap = 0; - unsigned int mask = context_mask; - - // find the largest capacity in the group - for (i = 0; i < N_ALIGN_CONTEXTS; ++i) - { - if (mask & 1) - { - const size_t cap = contexts[i].capacity(); - if (cap > max_cap) - max_cap = cap; - } - mask >>= 1; - } - - // set all members of group to largest capacity found - mask = context_mask; - for (i = 0; i < N_ALIGN_CONTEXTS; ++i) - { - if (mask & 1) - contexts[i].standardize_capacity(max_cap); - mask >>= 1; - } - } - - private: - Context contexts[N_ALIGN_CONTEXTS]; - }; - -} // namespace openvpn - -#endif // OPENVPN_FRAME_FRAME_H diff --git a/Sources/OpenVPN3/openvpn/frame/frame_init.hpp b/Sources/OpenVPN3/openvpn/frame/frame_init.hpp deleted file mode 100644 index 7c51617..0000000 --- a/Sources/OpenVPN3/openvpn/frame/frame_init.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// 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-2020 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/>. - -// Method to generate a Frame object for typical OpenVPN usage - -#ifndef OPENVPN_FRAME_FRAME_INIT_H -#define OPENVPN_FRAME_FRAME_INIT_H - -#include <algorithm> - -#include <openvpn/frame/frame.hpp> - -namespace openvpn { - - inline Frame::Ptr frame_init(const bool align_adjust_3_1, - const size_t tun_mtu, - const size_t control_channel_payload, - const bool verbose) - { - const size_t payload = std::max(tun_mtu + 512, size_t(2048)); - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; - - Frame::Ptr frame(new Frame(Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags))); - if (align_adjust_3_1) - { - (*frame)[Frame::READ_LINK_TCP] = Frame::Context(headroom, payload, tailroom, 3, align_block, buffer_flags); - (*frame)[Frame::READ_LINK_UDP] = Frame::Context(headroom, payload, tailroom, 1, align_block, buffer_flags); - } - (*frame)[Frame::READ_BIO_MEMQ_STREAM] = Frame::Context(headroom, std::min(control_channel_payload, payload), - tailroom, 0, align_block, buffer_flags); - (*frame)[Frame::WRITE_SSL_CLEARTEXT] = Frame::Context(headroom, payload, tailroom, 0, align_block, BufferAllocated::GROW); - frame->standardize_capacity(~0); - - if (verbose) - OPENVPN_LOG("Frame=" << headroom << '/' << payload << '/' << tailroom - << " mssfix-ctrl=" << (*frame)[Frame::READ_BIO_MEMQ_STREAM].payload()); - - return frame; - } - - inline Frame::Context frame_init_context_simple(const size_t payload) - { - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; - return Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags); - } - - inline Frame::Ptr frame_init_simple(const size_t payload) - { - Frame::Ptr frame = new Frame(frame_init_context_simple(payload)); - frame->standardize_capacity(~0); - return frame; - } - -} // namespace openvpn - -#endif // OPENVPN_FRAME_FRAME_INIT_H diff --git a/Sources/OpenVPN3/openvpn/frame/memq_dgram.hpp b/Sources/OpenVPN3/openvpn/frame/memq_dgram.hpp deleted file mode 100644 index 90ac932..0000000 --- a/Sources/OpenVPN3/openvpn/frame/memq_dgram.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// 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-2020 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/>. - -// A queue of datagram buffers for handling sequences of UDP packets - -#ifndef OPENVPN_FRAME_MEMQ_DGRAM_H -#define OPENVPN_FRAME_MEMQ_DGRAM_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/memq.hpp> -#include <openvpn/frame/frame.hpp> - -namespace openvpn { - - class MemQDgram : public MemQBase { - public: - OPENVPN_SIMPLE_EXCEPTION(frame_uninitialized); - - MemQDgram() {} - explicit MemQDgram(const Frame::Ptr& frame) : frame_(frame) {} - void set_frame(const Frame::Ptr& frame) { frame_ = frame; } - - size_t pending() const - { - return empty() ? 0 : q.front()->size(); - } - - void write(const unsigned char *data, size_t size) - { - if (frame_) - { - const Frame::Context& fc = (*frame_)[Frame::READ_BIO_MEMQ_STREAM]; - q.push_back(fc.copy(data, size)); - length += size; - } - else - throw frame_uninitialized(); - } - - size_t read(unsigned char *data, size_t len) - { - BufferPtr& b = q.front(); - if (len > b->size()) - len = b->size(); - b->read(data, len); - if (b->empty()) - q.pop_front(); - length -= len; - return len; - } - - private: - Frame::Ptr frame_; - }; - -} // namespace openvpn - -#endif // OPENVPN_FRAME_MEMQ_DGRAM_H diff --git a/Sources/OpenVPN3/openvpn/frame/memq_stream.hpp b/Sources/OpenVPN3/openvpn/frame/memq_stream.hpp deleted file mode 100644 index 3c2a533..0000000 --- a/Sources/OpenVPN3/openvpn/frame/memq_stream.hpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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-2020 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/>. - -// A queue of buffers for handling streamed data such as data received -// from or to be sent to a TCP socket - -#ifndef OPENVPN_FRAME_MEMQ_STREAM_H -#define OPENVPN_FRAME_MEMQ_STREAM_H - -#include <algorithm> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/memq.hpp> -#include <openvpn/frame/frame.hpp> - -namespace openvpn { - - class MemQStream : public MemQBase { - public: - OPENVPN_SIMPLE_EXCEPTION(frame_uninitialized); - - MemQStream() {} - explicit MemQStream(const Frame::Ptr& frame) : frame_(frame) {} - void set_frame(const Frame::Ptr& frame) { frame_ = frame; } - - size_t pending() const - { - return total_length(); - } - - void write(const unsigned char *data, size_t size) - { - if (frame_) - { - const Frame::Context& fc = (*frame_)[Frame::READ_BIO_MEMQ_STREAM]; - if (size) - { - ConstBuffer b(data, size, true); - // Any residual space remaining in most recently pushed buffer? - if (!q.empty()) - { - BufferPtr& qb = q.back(); - const size_t write_size = std::min(b.size(), fc.remaining_payload(*qb)); - const unsigned char *from = b.read_alloc(write_size); - qb->write(from, write_size); - length += write_size; - } - - // Start a new buffer - while (b.size()) - { - BufferPtr newbuf(new BufferAllocated); - fc.prepare(*newbuf); - const size_t write_size = std::min(b.size(), fc.payload()); - const unsigned char *from = b.read_alloc(write_size); - newbuf->write(from, write_size); - q.push_back(newbuf); - length += write_size; - } - } - } - else - throw frame_uninitialized(); - } - - size_t read(unsigned char *data, size_t len) - { - Buffer b(data, len, false); - while (!q.empty()) - { - const size_t remaining = b.remaining(); - if (!remaining) - break; - BufferPtr& qf = q.front(); - const size_t read_size = std::min(remaining, qf->size()); - unsigned char *to = b.write_alloc(read_size); - qf->read(to, read_size); - length -= read_size; - if (qf->empty()) - q.pop_front(); - } - return b.size(); - } - - private: - Frame::Ptr frame_; - }; - -} // namespace openvpn - -#endif // OPENVPN_FRAME_MEMQ_STREAM_H diff --git a/Sources/OpenVPN3/openvpn/http/header.hpp b/Sources/OpenVPN3/openvpn/http/header.hpp deleted file mode 100644 index da32d59..0000000 --- a/Sources/OpenVPN3/openvpn/http/header.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// 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-2020 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/>. - -// Denote the data in an HTTP header - -#ifndef OPENVPN_HTTP_HEADER_H -#define OPENVPN_HTTP_HEADER_H - -#include <string> -#include <sstream> -#include <utility> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> - -namespace openvpn { - namespace HTTP { - - struct Header { - Header() {} - Header(std::string name_arg, std::string value_arg) - : name(std::move(name_arg)), value(std::move(value_arg)) {} - - bool name_match(const std::string& n) const - { - return string::strcasecmp(n, name) == 0; - } - - std::string to_string() const - { - std::ostringstream out; - out << name << '=' << value; - return out.str(); - } - - std::string name; - std::string value; - }; - - struct HeaderList : public std::vector<Header> - { - const Header* get(const std::string& key) const - { - for (auto &h : *this) - { - if (h.name_match(key)) - return &h; - } - return nullptr; - } - - Header* get(const std::string& key) - { - for (auto &h : *this) - { - if (h.name_match(key)) - return &h; - } - return nullptr; - } - - std::string get_value(const std::string& key) const - { - const Header* h = get(key); - if (h) - return h->value; - else - return std::string(); - } - - std::string get_value_trim(const std::string& key) const - { - return string::trim_copy(get_value(key)); - } - - std::string get_value_trim_lower(const std::string& key) const - { - return string::to_lower_copy(get_value_trim(key)); - } - - std::string to_string() const - { - std::ostringstream out; - for (size_t i = 0; i < size(); ++i) - out << '[' << i << "] " << (*this)[i].to_string() << std::endl; - return out.str(); - } - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/headredact.hpp b/Sources/OpenVPN3/openvpn/http/headredact.hpp deleted file mode 100644 index e2e11db..0000000 --- a/Sources/OpenVPN3/openvpn/http/headredact.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// 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-2020 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 <regex> - -namespace openvpn { - namespace HTTP { - - inline std::string headers_redact(const std::string& headers) - { -#ifdef OPENVPN_HTTP_HEADERS_NO_REDACT - return headers; -#else - // C++14 only solution (not compatible with RHEL7/CentOS7) - //static const std::regex re(R"((authorization[\s:=]+basic\s+)([^\s]+))", std::regex_constants::ECMAScript | std::regex_constants::icase); - //return std::regex_replace(headers, re, "$1[REDACTED]"); - std::stringstream result; - - std::istringstream iss(headers); - - for (std::string line; std::getline(iss, line);) - { - int authpos; - if ((authpos = line.find("Authorization: ")) !=-1) - { - auto auth = line.substr(authpos); - auto argument = auth.substr(auth.find(' ') + 1); - std::string authtype; - int arg1=-1; - if ((arg1 = argument.find(' ')) != -1) - { - authtype = argument.substr(0, arg1); - } - result << line.substr(0, authpos) << "Authorization: " << authtype << " [REDACTED]\r" << std::endl; - } - else if ((authpos = line.find("authorization=basic ")) != -1) - { - result << line.substr(0, authpos) << "authorization=basic [REDACTED]\r" << std::endl; - } - else - { - result << line << std::endl; - } - } - return result.str(); -#endif - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/http/htmlskip.hpp b/Sources/OpenVPN3/openvpn/http/htmlskip.hpp deleted file mode 100644 index a58d468..0000000 --- a/Sources/OpenVPN3/openvpn/http/htmlskip.hpp +++ /dev/null @@ -1,283 +0,0 @@ -// 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-2020 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/>. - -// A state machine to skip extraneous HTML in an -// HTTP CONNECT proxy response. - -// Matches on typical HTML blocks: -// -// <!doctype html> ... </html> -// <html> ... </html> -// -// Notes: -// 1. Case insensitive -// 2. </html> can be followed by CR/LF chars - -#ifndef OPENVPN_HTTP_HTMLSKIP_H -#define OPENVPN_HTTP_HTMLSKIP_H - -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - namespace HTTP { - - class HTMLSkip - { - public: - enum Status { - PENDING, - MATCH, - NOMATCH, - }; - - HTMLSkip() - : state(INITIAL), - residual(64, 0), - bytes(0) - {} - - Status add(unsigned char c) - { - bool retain = false; - - ++bytes; - switch (state) - { - case INITIAL: - retain = true; - if (c == '<') - state = O_OPEN; - else - state = FAIL; - break; - case O_OPEN: - retain = true; - if (c == '!') - state = O_BANG; - else if (c == 'h' || c == 'H') - state = O_HTML_H; - else - state = FAIL; - break; - case O_BANG: - retain = true; - if (c == 'd' || c == 'D') - state = O_DOCTYPE_D; - else - state = FAIL; - break; - case O_DOCTYPE_D: - retain = true; - if (c == 'o' || c == 'O') - state = O_DOCTYPE_O; - else - state = FAIL; - break; - case O_DOCTYPE_O: - retain = true; - if (c == 'c' || c == 'C') - state = O_DOCTYPE_C; - else - state = FAIL; - break; - case O_DOCTYPE_C: - retain = true; - if (c == 't' || c == 'T') - state = O_DOCTYPE_T; - else - state = FAIL; - break; - case O_DOCTYPE_T: - retain = true; - if (c == 'y' || c == 'Y') - state = O_DOCTYPE_Y; - else - state = FAIL; - break; - case O_DOCTYPE_Y: - retain = true; - if (c == 'p' || c == 'P') - state = O_DOCTYPE_P; - else - state = FAIL; - break; - case O_DOCTYPE_P: - retain = true; - if (c == 'e' || c == 'E') - state = O_DOCTYPE_SPACE; - else - state = FAIL; - break; - case O_DOCTYPE_SPACE: - retain = true; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - break; - else if (c == 'h' || c == 'H') - state = O_HTML_H; - else - state = FAIL; - break; - case O_HTML_H: - retain = true; - if (c == 't' || c == 'T') - state = O_HTML_T; - else - state = FAIL; - break; - case O_HTML_T: - retain = true; - if (c == 'm' || c == 'M') - state = O_HTML_M; - else - state = FAIL; - break; - case O_HTML_M: - if (c == 'l' || c == 'L') - { - state = CONTENT; - residual.reset_content(); - } - else - { - state = FAIL; - retain = true; - } - break; - case CONTENT: - if (c == '<') - state = C_OPEN; - break; - case C_OPEN: - if (c == '/') - state = C_SLASH; - else - state = CONTENT; - break; - case C_SLASH: - if (c == 'h' || c == 'H') - state = C_HTML_H; - else - state = CONTENT; - break; - case C_HTML_H: - if (c == 't' || c == 'T') - state = C_HTML_T; - else - state = CONTENT; - break; - case C_HTML_T: - if (c == 'm' || c == 'M') - state = C_HTML_M; - else - state = CONTENT; - break; - case C_HTML_M: - if (c == 'l' || c == 'L') - state = C_HTML_L; - else - state = CONTENT; - break; - case C_HTML_L: - if (c == '>') - state = C_CRLF; - else - state = CONTENT; - break; - case C_CRLF: - if (!(c == '\n' || c == '\r')) - { - residual.reset_content(); - residual.push_back(c); - state = DONE; - } - break; - default: - retain = true; - break; - } - - if (retain) - residual.push_back(c); - - switch (state) - { - case DONE: - return MATCH; - case FAIL: - return NOMATCH; - default: - return PENDING; - } - } - - void get_residual(BufferAllocated& buf) const - { - if (residual.size() <= buf.offset()) - { - buf.prepend(residual.c_data(), residual.size()); - } - else - { - BufferAllocated newbuf(residual.size() + buf.size(), 0); - newbuf.write(residual.c_data(), residual.size()); - newbuf.write(buf.c_data(), buf.size()); - buf.move(newbuf); - } - } - - unsigned long n_bytes() const { return bytes; } - - private: - enum State { - DONE, - FAIL, - INITIAL, - O_OPEN, - O_BANG, - O_DOCTYPE_D, - O_DOCTYPE_O, - O_DOCTYPE_C, - O_DOCTYPE_T, - O_DOCTYPE_Y, - O_DOCTYPE_P, - O_DOCTYPE_SPACE, - O_HTML_H, - O_HTML_T, - O_HTML_M, - CONTENT, - C_OPEN, - C_SLASH, - C_HTML_H, - C_HTML_T, - C_HTML_M, - C_HTML_L, - C_CRLF, - }; - - State state; - BufferAllocated residual; - unsigned long bytes; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/method.hpp b/Sources/OpenVPN3/openvpn/http/method.hpp deleted file mode 100644 index e95f33f..0000000 --- a/Sources/OpenVPN3/openvpn/http/method.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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-2020 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_HTTP_METHOD_H -#define OPENVPN_HTTP_METHOD_H - -namespace openvpn { - namespace HTTP { - namespace Method { - enum Type { - OTHER, - GET, - POST, - }; - - Type parse(const std::string& methstr) - { - if (methstr == "GET") - return GET; - else if (methstr == "POST") - return POST; - else - return OTHER; - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/parseutil.hpp b/Sources/OpenVPN3/openvpn/http/parseutil.hpp deleted file mode 100644 index 593dd8d..0000000 --- a/Sources/OpenVPN3/openvpn/http/parseutil.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// 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-2020 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/>. -// -// Adapted from code Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// Common utility methods for HTTP classes - -#ifndef OPENVPN_HTTP_PARSEUTIL_H -#define OPENVPN_HTTP_PARSEUTIL_H - -namespace openvpn { - namespace HTTP { - namespace Util { - - // Check if a byte is an HTTP character. - inline bool is_char(const unsigned char c) - { - return c <= 127; - } - - // Check if a byte is an HTTP control character. - inline bool is_ctl(const unsigned char c) - { - return (c <= 31)|| (c == 127); - } - - // Check if a byte is defined as an HTTP tspecial character. - inline bool is_tspecial(const unsigned char c) - { - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } - } - - // Check if a byte is a digit. - inline bool is_digit(const unsigned char c) - { - return c >= '0' && c <= '9'; - } - - // Check if char should be URL-escaped - inline bool is_escaped(const unsigned char c) - { - if (c >= 'a' && c <= 'z') - return false; - if (c >= 'A' && c <= 'Z') - return false; - if (c >= '0' && c <= '9') - return false; - if (c == '.' || c == '-' || c == '_') - return false; - return true; - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/reply.hpp b/Sources/OpenVPN3/openvpn/http/reply.hpp deleted file mode 100644 index 8a8755d..0000000 --- a/Sources/OpenVPN3/openvpn/http/reply.hpp +++ /dev/null @@ -1,403 +0,0 @@ -// 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-2020 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/>. -// -// Adapted from code Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// Parse an HTTP reply - -#ifndef OPENVPN_HTTP_REPLY_H -#define OPENVPN_HTTP_REPLY_H - -#include <openvpn/http/header.hpp> -#include <openvpn/http/parseutil.hpp> - -namespace openvpn { - namespace HTTP { - - struct Reply { - Reply() : http_version_major(0), http_version_minor(0), status_code(0) {} - - void reset() - { - http_version_major = 0; - http_version_minor = 0; - status_code = 0; - status_text = ""; - headers.clear(); - } - - std::string to_string() const - { - std::ostringstream out; - out << "HTTP Reply" << std::endl; - out << "version=" << http_version_major << '/' << http_version_minor << std::endl; - out << "status_code=" << status_code << std::endl; - out << "status_text=" << status_text << std::endl; - out << headers.to_string(); - return out.str(); - } - - int http_version_major; - int http_version_minor; - int status_code; - std::string status_text; - HeaderList headers; - }; - - class ReplyParser { - enum state - { - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - status_code_start, - status_code, - status_text_start, - status_text, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - }; - - public: - enum status { - pending, - fail, - success, - }; - - ReplyParser() - : state_(http_version_h) - { - } - - // Reset to initial parser state. - void reset() - { - state_ = http_version_h; - } - - // Parse some HTTP reply data. - status consume(Reply& req, const unsigned char input) - { - switch (state_) - { - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return pending; - } - else - { - return fail; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return pending; - } - else - { - return fail; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return pending; - } - else - { - return fail; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return pending; - } - else - { - return fail; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return pending; - } - else - { - return fail; - } - case http_version_major_start: - if (Util::is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return pending; - } - else - { - return fail; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return pending; - } - else if (Util::is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return pending; - } - else - { - return fail; - } - case http_version_minor_start: - if (Util::is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return pending; - } - else - { - return fail; - } - case http_version_minor: - if (input == ' ') - { - state_ = status_code_start; - return pending; - } - else if (Util::is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return pending; - } - else - { - return fail; - } - case status_code_start: - if (Util::is_digit(input)) - { - req.status_code = req.status_code * 10 + input - '0'; - state_ = status_code; - return pending; - } - else - { - return fail; - } - case status_code: - if (input == ' ') - { - state_ = status_text_start; - return pending; - } - else if (Util::is_digit(input)) - { - req.status_code = req.status_code * 10 + input - '0'; - return pending; - } - else - { - return fail; - } - case status_text_start: - if (input == '\r') - { - state_ = expecting_newline_1; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - state_ = status_text; - req.status_text.push_back(input); - return pending; - } - case status_text: - if (input == '\r') - { - state_ = expecting_newline_1; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input)) - { - return fail; - } - else - { - req.status_text.push_back(input); - return pending; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return pending; - } - else - { - return fail; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return pending; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - req.headers.push_back(Header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return pending; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return pending; - } - else if (input == ' ' || input == '\t') - { - return pending; - } - else if (Util::is_ctl(input)) - { - return fail; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return pending; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - req.headers.back().name.push_back(input); - return pending; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return pending; - } - else - { - return fail; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return pending; - } - else if (Util::is_ctl(input)) - { - return fail; - } - else - { - req.headers.back().value.push_back(input); - return pending; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return pending; - } - else - { - return fail; - } - case expecting_newline_3: - if (input == '\n') - return success; - else - return fail; - default: - return fail; - } - } - - private: - // The current state of the parser. - state state_; - }; - - struct ReplyType - { - typedef Reply State; - typedef ReplyParser Parser; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/request.hpp b/Sources/OpenVPN3/openvpn/http/request.hpp deleted file mode 100644 index a88cdbf..0000000 --- a/Sources/OpenVPN3/openvpn/http/request.hpp +++ /dev/null @@ -1,398 +0,0 @@ -// 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-2020 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/>. -// -// Adapted from code Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// Parse an HTTP request - -#ifndef OPENVPN_HTTP_REQUEST_H -#define OPENVPN_HTTP_REQUEST_H - -#include <openvpn/http/header.hpp> -#include <openvpn/http/parseutil.hpp> - -namespace openvpn { - namespace HTTP { - - struct Request { - Request() : http_version_major(0), http_version_minor(0) {} - - void reset() - { - method = ""; - uri = ""; - http_version_major = 0; - http_version_minor = 0; - headers.clear(); - } - - std::string to_string() const - { - std::ostringstream out; - out << "HTTP Request" << std::endl; - out << "method=" << method << std::endl; - out << "uri=" << uri << std::endl; - out << "version=" << http_version_major << '/' << http_version_minor << std::endl; - out << headers.to_string(); - return out.str(); - } - - std::string to_string_compact() const - { - std::ostringstream out; - out << method << ' ' << uri << " HTTP/" << http_version_major << '.' << http_version_minor; - return out.str(); - } - - bool at_least_http_1_1() const - { - return http_version_major > 1 || (http_version_major == 1 && http_version_minor >= 1); - } - - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - HeaderList headers; - }; - - class RequestParser { - enum state - { - method_start, - method, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - }; - - public: - enum status { - pending, - fail, - success, - }; - - RequestParser() - : state_(method_start) - { - } - - // Reset to initial parser state. - void reset() - { - state_ = method_start; - } - - // Parse some HTTP request data. - status consume(Request& req, const unsigned char input) - { - switch (state_) - { - case method_start: - if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - state_ = method; - req.method.push_back(input); - return pending; - } - case method: - if (input == ' ') - { - state_ = uri; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - req.method.push_back(input); - return pending; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return pending; - } - else if (Util::is_ctl(input)) - { - return fail; - } - else - { - req.uri.push_back(input); - return pending; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return pending; - } - else - { - return fail; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return pending; - } - else - { - return fail; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return pending; - } - else - { - return fail; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return pending; - } - else - { - return fail; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return pending; - } - else - { - return fail; - } - case http_version_major_start: - if (Util::is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return pending; - } - else - { - return fail; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return pending; - } - else if (Util::is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return pending; - } - else - { - return fail; - } - case http_version_minor_start: - if (Util::is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return pending; - } - else - { - return fail; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return pending; - } - else if (Util::is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return pending; - } - else - { - return fail; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return pending; - } - else - { - return fail; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return pending; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - req.headers.push_back(Header()); - req.headers.back().name.push_back(input); - state_ = header_name; - return pending; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return pending; - } - else if (input == ' ' || input == '\t') - { - return pending; - } - else if (Util::is_ctl(input)) - { - return fail; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return pending; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return pending; - } - else if (!Util::is_char(input) || Util::is_ctl(input) || Util::is_tspecial(input)) - { - return fail; - } - else - { - req.headers.back().name.push_back(input); - return pending; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return pending; - } - else - { - return fail; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return pending; - } - else if (Util::is_ctl(input)) - { - return fail; - } - else - { - req.headers.back().value.push_back(input); - return pending; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return pending; - } - else - { - return fail; - } - case expecting_newline_3: - if (input == '\n') - return success; - else - return fail; - default: - return fail; - } - } - - private: - // The current state of the parser. - state state_; - }; - - struct RequestType - { - typedef Request State; - typedef RequestParser Parser; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/status.hpp b/Sources/OpenVPN3/openvpn/http/status.hpp deleted file mode 100644 index d2e3d15..0000000 --- a/Sources/OpenVPN3/openvpn/http/status.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// 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-2020 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_HTTP_STATUS_H -#define OPENVPN_HTTP_STATUS_H - -// HTTP status codes - -namespace openvpn { - namespace HTTP { - namespace Status { - enum { - OK=200, - Connected=200, - SwitchingProtocols=101, - BadRequest=400, - Unauthorized=401, - Forbidden=403, - NotFound=404, - ProxyAuthenticationRequired=407, - PreconditionFailed=412, - InternalServerError=500, - ProxyError=502, - ServiceUnavailable=503, - }; - - inline const char *to_string(const int status) - { - switch (status) - { - case OK: - return "OK"; - case SwitchingProtocols: - return "Switching Protocols"; - case BadRequest: - return "Bad Request"; - case Unauthorized: - return "Unauthorized"; - case Forbidden: - return "Forbidden"; - case NotFound: - return "Not Found"; - case ProxyAuthenticationRequired: - return "Proxy Authentication Required"; - case PreconditionFailed: - return "Precondition Failed"; - case InternalServerError: - return "Internal Server Error"; - case ProxyError: - return "Proxy Error"; - case ServiceUnavailable: - return "Service Unavailable"; - default: - return ""; - } - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/urlencode.hpp b/Sources/OpenVPN3/openvpn/http/urlencode.hpp deleted file mode 100644 index 1d32199..0000000 --- a/Sources/OpenVPN3/openvpn/http/urlencode.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// 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-2020 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_HTTP_URLENCODE_H -#define OPENVPN_HTTP_URLENCODE_H - -#include <string> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/http/parseutil.hpp> - -namespace openvpn { - namespace URL { - OPENVPN_EXCEPTION(url_error); - - inline std::string encode(const std::string& str) - { - std::string ret; - ret.reserve(str.length() * 2); // just a guess - for (auto &c : str) - { - if (HTTP::Util::is_escaped(c)) - { - ret += '%'; - ret += render_hex_number((unsigned char)c, true); - } - else - ret += c; - } - return ret; - } - - inline std::string decode(const std::string& encoded) - { - enum State { - TEXT, - PERCENT, - DIGIT - }; - - int value = 0; - State state = TEXT; - std::string ret; - ret.reserve(encoded.size()); // just a guess - - for (auto &c : encoded) - { - switch (state) - { - case TEXT: - { - if (c == '%') - state = PERCENT; - else - ret += c; - break; - } - case PERCENT: - { - const int v = parse_hex_char(c); - if (v < 0) - throw url_error(std::string("decode error after %: ") + encoded); - value = v; - state = DIGIT; - break; - } - case DIGIT: - { - const int v = parse_hex_char(c); - if (v < 0) - throw url_error(std::string("decode error after %: ") + encoded); - ret += static_cast<unsigned char>((value * 16) + v); - state = TEXT; - } - } - } - if (state != TEXT) - throw url_error(std::string("decode error: %-encoding item not closed out: ") + encoded); - if (!Unicode::is_valid_utf8(ret)) - throw url_error(std::string("not UTF-8: ") + encoded); - return ret; - } - - inline std::vector<std::string> decode_path(std::string path) - { - std::vector<std::string> list; - if (!path.empty() && path[0] == '/') - path = path.substr(1); - Split::by_char_void<decltype(list), NullLex, Split::NullLimit>(list, path, '/'); - for (auto &i : list) - i = decode(i); - return list; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/urlparm.hpp b/Sources/OpenVPN3/openvpn/http/urlparm.hpp deleted file mode 100644 index 5f7c521..0000000 --- a/Sources/OpenVPN3/openvpn/http/urlparm.hpp +++ /dev/null @@ -1,211 +0,0 @@ -// 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-2020 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_HTTP_URLPARM_H -#define OPENVPN_HTTP_URLPARM_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/number.hpp> -#include <openvpn/http/urlencode.hpp> -#include <openvpn/http/webexcept.hpp> -#include <openvpn/common/string.hpp> - -namespace openvpn { - namespace URL { - OPENVPN_EXCEPTION(url_parameter_error); - - struct Parm - { - Parm() {} - - Parm(const std::string& name_arg, const std::string& value_arg) - : name(name_arg), value(value_arg) - { - } - - std::string to_string() const - { - std::ostringstream out; - out << name << '=' << value; - return out.str(); - } - - std::string name; - std::string value; - }; - - class ParmList : public std::vector<Parm> - { - public: - ParmList(const std::string& uri) - { - try { - const std::vector<std::string> req_parms = string::split(uri, '?', 1); - request_ = req_parms[0]; - if (req_parms.size() == 2) - { - const std::vector<std::string> kv_list = string::split(req_parms[1], '&'); - for (auto &kvstr : kv_list) - { - const std::vector<std::string> kv = string::split(kvstr, '=', 1); - Parm p; - p.name = decode(kv[0]); - if (kv.size() == 2) - p.value = decode(kv[1]); - push_back(std::move(p)); - } - } - } - catch (const std::exception& e) - { - throw HTTP::WebException(HTTP::Status::BadRequest, e.what()); - } - } - - const Parm* get(const std::string& key) const - { - for (auto &p : *this) - { - if (key == p.name) - return &p; - } - return nullptr; - } - - std::string get_value(const std::string& key) const - { - const Parm* p = get(key); - if (p) - return p->value; - else - return ""; - } - - const std::string& get_value_required(const std::string& key) const - { - const Parm* p = get(key); - if (p) - return p->value; - else - throw url_parameter_error(key + " : not found"); - } - - template <typename T> - T get_num(const std::string& name, const std::string& short_name, const T default_value) const - { - const Parm* p = get(name); - if (!p && !short_name.empty()) - p = get(short_name); - if (p) - return parse_number_throw<T>(p->value, name); - else - return default_value; - } - - template <typename T> - T get_num_required(const std::string& name, const std::string& short_name) const - { - const Parm* p = get(name); - if (!p && !short_name.empty()) - p = get(short_name); - if (!p) - throw url_parameter_error(name + " : not found"); - return parse_number_throw<T>(p->value, name); - } - - bool get_bool(const std::string& name, const std::string& short_name, const bool default_value) const - { - const Parm* p = get(name); - if (!p && !short_name.empty()) - p = get(short_name); - if (p) - { - if (p->value == "0") - return false; - else if (p->value == "1") - return true; - else - throw url_parameter_error(name + ": parameter must be 0 or 1"); - } - else - return default_value; - } - - std::string get_string(const std::string& name, const std::string& short_name) const - { - const Parm* p = get(name); - if (!p && !short_name.empty()) - p = get(short_name); - if (p) - return p->value; - else - return ""; - } - - std::string get_string_required(const std::string& name, const std::string& short_name) const - { - const Parm* p = get(name); - if (!p && !short_name.empty()) - p = get(short_name); - if (!p) - throw url_parameter_error(name + " : not found"); - return p->value; - } - - std::string to_string() const - { - std::ostringstream out; - for (size_t i = 0; i < size(); ++i) - out << '[' << i << "] " << (*this)[i].to_string() << std::endl; - return out.str(); - } - - std::string request(const bool remove_leading_slash) const - { - std::string ret = request_; - if (remove_leading_slash) - { - if (ret.length() > 0 && ret[0] == '/') - ret = ret.substr(1); - else - throw HTTP::WebException(HTTP::Status::BadRequest, "URI missing leading slash"); - } - if (ret.empty()) - throw HTTP::WebException(HTTP::Status::BadRequest, "URI resource is empty"); - return ret; - } - - const std::string& request() const - { - return request_; - } - - private: - std::string request_; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/urlparse.hpp b/Sources/OpenVPN3/openvpn/http/urlparse.hpp deleted file mode 100644 index bcf2f2b..0000000 --- a/Sources/OpenVPN3/openvpn/http/urlparse.hpp +++ /dev/null @@ -1,262 +0,0 @@ -// 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-2020 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_HTTP_URLPARSE_H -#define OPENVPN_HTTP_URLPARSE_H - -#include <string> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/common/format.hpp> -#include <openvpn/http/validate_uri.hpp> -#include <openvpn/http/parseutil.hpp> - -namespace openvpn { - namespace URL { - OPENVPN_EXCEPTION(url_parse_error); - - class Parse - { - public: - Parse() {} - - Parse(const std::string& url, - const bool set_default_port=false, - const bool loose_validation=false) - { - enum State { - Scheme, - PostSchemeSlash1, - PostSchemeSlash2, - StartHost, - Host, - BracketedHost, - PostBracketedHost, - Port, - URI, - }; - - State state = Scheme; - for (auto &c : url) - { - reprocess: - switch (state) - { - case Scheme: - if (c == ':') - state = PostSchemeSlash1; - else if (is_valid_scheme_char(c)) - scheme += c; - else - throw url_parse_error("bad scheme char"); - break; - case PostSchemeSlash1: - if (c == '/') - state = PostSchemeSlash2; - else - throw url_parse_error("expected '://' after scheme"); - break; - case PostSchemeSlash2: - if (c == '/') - state = StartHost; - else - throw url_parse_error("expected '://' after scheme"); - break; - case StartHost: - if (c == '[') - state = BracketedHost; - else - { - state = Host; - goto reprocess; - } - break; - case Host: - if (c == ':') - state = Port; - else if (c == '/') - { - state = URI; - goto reprocess; - } - else - host += c; - break; - case BracketedHost: - if (c == ']') - state = PostBracketedHost; - else - host += c; - break; - case PostBracketedHost: - if (c == ':') - { - state = Port; - break; - } - else - { - state = URI; - goto reprocess; - } - break; - case Port: - if (c == '/') - { - state = URI; - goto reprocess; - } - else - port += c; - break; - case URI: - if (!HTTP::is_valid_uri_char(c) && !loose_validation) - throw url_parse_error("bad URI char"); - uri += c; - break; - } - } - if (set_default_port) - default_port(); - if (uri.empty()) - uri = "/"; - validate(); - } - - // Note that special address types such as unix domain - // sockets or windows named pipes store a tag such as - // "unix" or "np" as the port component of an address/port - // tuple. Here, we move such tags into the scheme. - static Parse from_components(const bool https, - const std::string& host, - const std::string& port, - const std::string& uri) - { - Parse p; - p.scheme = https ? "https" : "http"; - p.host = host; - if (port.size() >= 1 && !string::is_digit(port[0])) // non-INET address - p.scheme = port; - else - p.port = port; - p.uri = uri; - return p; - } - - void validate() const - { - if (scheme.empty()) - throw url_parse_error("undefined scheme"); - if (host.empty()) - throw url_parse_error("undefined host"); - if (uri.empty()) - throw url_parse_error("undefined uri"); - - if (!port.empty() && !HostPort::is_valid_port(port)) - throw url_parse_error("bad port"); - if ((scheme == "http" || scheme == "https") && !HostPort::is_valid_host(host)) - throw url_parse_error("bad host"); - } - - void default_port() - { - if (port.empty()) - { - if (scheme == "http") - port = "80"; - else if (scheme == "https") - port = "443"; - } - } - - bool port_implied() const - { - return (scheme == "http" && port == "80") || (scheme == "https" && port == "443"); - } - - std::string to_string() const - { - const bool bracket_host = (host.find_first_of(":/\\") != std::string::npos); - - std::string ret; - ret.reserve(256); - ret += scheme; - ret += "://"; - if (bracket_host) - ret += '['; - ret += host; - if (bracket_host) - ret += ']'; - if (!port.empty() && !port_implied()) - { - ret += ':'; - ret += port; - } - ret += uri; - return ret; - } - - std::string format_components() const - { - return printfmt("[scheme=%r host=%r port=%r uri=%r]", scheme, host, port, uri); - } - - // Note that special address types such as unix domain - // sockets or windows named pipes store a tag such as - // "unix" or "np" as the port component of an address/port - // tuple. This method returns the port number for INET - // addresses or a special tag for non-INET addresses. - // Internally, we store the tag as an alternative - // scheme such as "unix" or "np". - std::string port_for_scheme() const - { -#ifdef OPENVPN_PLATFORM_WIN - if (scheme == "np") // named pipe - return scheme; -#else - if (scheme == "unix") // unix domain socket - return scheme; -#endif - if (scheme == "http" || scheme == "https") - return port; - - throw url_parse_error("unknown scheme"); - } - - std::string scheme; - std::string host; - std::string port; - std::string uri; - - private: - bool is_valid_scheme_char(const char c) - { - return (c >= 'a' && c <= 'z') || c == '_'; - } - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/http/validate_uri.hpp b/Sources/OpenVPN3/openvpn/http/validate_uri.hpp deleted file mode 100644 index b6d2ff5..0000000 --- a/Sources/OpenVPN3/openvpn/http/validate_uri.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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/exception.hpp> - -namespace openvpn { - namespace HTTP { - inline bool is_valid_uri_char(const unsigned char c) - { - return c >= 0x21 && c <= 0x7E; - } - - inline bool is_valid_uri_char(const char c) - { - return is_valid_uri_char((unsigned char)c); - } - - inline void validate_uri(const std::string& uri, const std::string& title) - { - if (uri.empty()) - throw Exception(title + " : URI is empty"); - if (uri[0] != '/') - throw Exception(title + " : URI must begin with '/'"); - for (auto &c : uri) - { - if (!is_valid_uri_char(c)) - throw Exception(title + " : URI contains illegal character"); - } - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/http/webexcept.hpp b/Sources/OpenVPN3/openvpn/http/webexcept.hpp deleted file mode 100644 index 65b20cf..0000000 --- a/Sources/OpenVPN3/openvpn/http/webexcept.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// 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-2020 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_HTTP_EXCEPT_H -#define OPENVPN_HTTP_EXCEPT_H - -#include <string> -#include <sstream> -#include <exception> - -#include <openvpn/http/status.hpp> - -# define OPENVPN_THROW_WEB(exc, status, stuff) \ - do { \ - std::ostringstream _ovpn_exc; \ - _ovpn_exc << stuff; \ - throw exc(status, _ovpn_exc.str()); \ - } while (0) - -namespace openvpn { - namespace HTTP { - class WebException : public std::exception - { - public: - WebException(const int status, const std::string& error) - : status_(status), - error_(error), - formatted(std::string(Status::to_string(status_)) + " : " + error_) - { - } - - WebException(const int status) - : status_(status), - error_(Status::to_string(status_)), - formatted(error_) - { - } - - int status() const { return status_; } - const std::string& error() const { return error_; } - - virtual const char* what() const throw() { return formatted.c_str(); } - - private: - const int status_; - const std::string error_; - const std::string formatted; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/init/cryptoinit.hpp b/Sources/OpenVPN3/openvpn/init/cryptoinit.hpp deleted file mode 100644 index 693a2e5..0000000 --- a/Sources/OpenVPN3/openvpn/init/cryptoinit.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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> - -#ifdef USE_OPENSSL -#include <openvpn/openssl/util/init.hpp> -#endif - -namespace openvpn { - - // process-wide initialization for crypto subsystem - class crypto_init - { -#if defined(OPENSSL_NEEDS_INIT) - openssl_init openssl_init_; -#endif - /* - * We add a dummy member so this class does not count as trivial - * class. Otherwise it will trigger: - * warning: private field 'crypto_init_' is not used [-Wunused-private-field] - */ - std::string dummy; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/init/engineinit.hpp b/Sources/OpenVPN3/openvpn/init/engineinit.hpp deleted file mode 100644 index 897c13b..0000000 --- a/Sources/OpenVPN3/openvpn/init/engineinit.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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-2020 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/>. - -// process-wide initialization for underlying cryptographic engines - -#ifndef OPENVPN_INIT_ENGINEINIT_H -#define OPENVPN_INIT_ENGINEINIT_H - -#include <string> - -#include <openvpn/common/arch.hpp> - -#if defined(USE_OPENSSL) -#include <openvpn/openssl/util/engine.hpp> -#include <openvpn/openssl/ssl/sslctx.hpp> -#endif - -#if defined(USE_MINICRYPTO) && (defined(OPENVPN_ARCH_x86_64) || defined(OPENVPN_ARCH_i386)) -extern "C" { - void OPENSSL_cpuid_setup(); -} -#endif - -namespace openvpn { - - inline void init_openssl(const std::string& engine) - { -#if defined(USE_OPENSSL) - openssl_setup_engine(engine); - OpenSSLContext::SSL::init_static(); -#elif defined(USE_MINICRYPTO) && (defined(OPENVPN_ARCH_x86_64) || defined(OPENVPN_ARCH_i386)) - OPENSSL_cpuid_setup(); -#endif - } - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/init/initprocess.hpp b/Sources/OpenVPN3/openvpn/init/initprocess.hpp deleted file mode 100644 index 9d7105a..0000000 --- a/Sources/OpenVPN3/openvpn/init/initprocess.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// 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-2020 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/>. - -// Process-wide static initialization - -#pragma once - -#include <thread> -#include <mutex> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/extern.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/compress/compress.hpp> -#include <openvpn/init/cryptoinit.hpp> -#include <openvpn/init/engineinit.hpp> - -namespace openvpn { - namespace InitProcess { - class Init - { - private: - class InitImpl - { - public: - InitImpl() - { - // initialize time base - Time::reset_base(); - - // initialize compression - CompressContext::init_static(); - - // init OpenSSL if included - init_openssl("auto"); - - base64_init_static(); - } - - ~InitImpl() - { - base64_uninit_static(); - } - - private: - // SSL library init happens when instantiated - crypto_init crypto_init_; - }; - - // process-wide singular instance - static std::weak_ptr<InitImpl> init_instance; // GLOBAL - static std::mutex the_instance_mutex; // GLOBAL - - // istance of this class to refcount - std::shared_ptr<InitImpl> initptr; - - public: - Init() - { - std::lock_guard<std::mutex> lock(the_instance_mutex); - - initptr = init_instance.lock(); - if (!initptr) - { - initptr = std::make_shared<InitImpl>(); - init_instance = initptr; - } - } - - ~Init() - { - //explicitly reset smart pointer to make the destructor run under the lock_guard - std::lock_guard<std::mutex> lock(the_instance_mutex); - initptr.reset(); - } - }; - -#ifdef OPENVPN_NO_EXTERN - std::weak_ptr<Init::InitImpl> Init::init_instance; // GLOBAL - std::mutex Init::the_instance_mutex; // GLOBAL -#endif - } -} - - - - diff --git a/Sources/OpenVPN3/openvpn/io/io.hpp b/Sources/OpenVPN3/openvpn/io/io.hpp deleted file mode 100644 index 70080e8..0000000 --- a/Sources/OpenVPN3/openvpn/io/io.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// 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-2020 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/>. - -// Select the i/o reactor - -#ifndef OPENVPN_IO_IO_H -#define OPENVPN_IO_IO_H - -#ifdef USE_ASIO -#include <asio.hpp> -#define openvpn_io asio -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/ip/csum.hpp b/Sources/OpenVPN3/openvpn/ip/csum.hpp deleted file mode 100644 index eb08998..0000000 --- a/Sources/OpenVPN3/openvpn/ip/csum.hpp +++ /dev/null @@ -1,171 +0,0 @@ -// 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-2020 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)); - } - } -} \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/ip/dhcp.hpp b/Sources/OpenVPN3/openvpn/ip/dhcp.hpp deleted file mode 100644 index 18e6d68..0000000 --- a/Sources/OpenVPN3/openvpn/ip/dhcp.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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-2020 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_IP_DHCP_H -#define OPENVPN_IP_DHCP_H - -#include <openvpn/ip/eth.hpp> -#include <openvpn/ip/ip4.hpp> -#include <openvpn/ip/udp.hpp> - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - struct DHCP { - enum { - /* DHCP Option types */ - DHCP_PAD = 0, - DHCP_NETMASK = 1, - DHCP_ROUTER = 3, - DHCP_DNS = 6, - DHCP_MSG_TYPE = 53 /* message type (u8) */, - DHCP_END = 255, - - /* DHCP Messages types */ - DHCPDISCOVER = 1, - DHCPOFFER = 2, - DHCPREQUEST = 3, - DHCPDECLINE = 4, - DHCPACK = 5, - DHCPNAK = 6, - DHCPRELEASE = 7, - DHCPINFORM = 8, - - /* DHCP UDP port numbers */ - BOOTPS_PORT = 67, - BOOTPC_PORT = 68, - - /* DHCP message op */ - BOOTREQUEST = 1, - BOOTREPLY = 2, - }; - - std::uint8_t op; /* message op */ - std::uint8_t htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */ - std::uint8_t hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */ - std::uint8_t hops; /* client sets to 0, may be used by relay agents */ - std::uint32_t xid; /* transaction ID, chosen by client */ - std::uint16_t secs; /* seconds since request process began, set by client */ - std::uint16_t flags; - std::uint32_t ciaddr; /* client IP address, client sets if known */ - std::uint32_t yiaddr; /* 'your' IP address -- server's response to client */ - std::uint32_t siaddr; /* server IP address */ - std::uint32_t giaddr; /* relay agent IP address */ - std::uint8_t chaddr[16]; /* client hardware address */ - std::uint8_t sname[64]; /* optional server host name */ - std::uint8_t file[128]; /* boot file name */ - std::uint32_t magic; /* must be 0x63825363 (network order) */ - }; - - struct DHCPPacket { - EthHeader eth; - IPv4Header ip; - UDPHeader udp; - DHCP dhcp; - std::uint8_t options[]; - }; -} - -#pragma pack(pop) - -#endif diff --git a/Sources/OpenVPN3/openvpn/ip/eth.hpp b/Sources/OpenVPN3/openvpn/ip/eth.hpp deleted file mode 100644 index f42596b..0000000 --- a/Sources/OpenVPN3/openvpn/ip/eth.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// 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-2020 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/>. - -// Define the Ethernet header - -#ifndef OPENVPN_IP_ETH_H -#define OPENVPN_IP_ETH_H - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - struct EthHeader { - std::uint8_t dest_mac[6]; - std::uint8_t src_mac[6]; - std::uint16_t ethertype; - }; -} - -#pragma pack(pop) - -#endif diff --git a/Sources/OpenVPN3/openvpn/ip/icmp4.hpp b/Sources/OpenVPN3/openvpn/ip/icmp4.hpp deleted file mode 100644 index 93469e2..0000000 --- a/Sources/OpenVPN3/openvpn/ip/icmp4.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// 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-2020 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/>. - -// Define the ICMPv4 header - -#pragma once - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -#include <openvpn/ip/ip4.hpp> - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - struct ICMPv4 { - enum { - ECHO_REQUEST = 8, - ECHO_REPLY = 0, - DEST_UNREACH = 3, - FRAG_NEEDED = 4, - MIN_DATA_SIZE = 8 - }; - - struct IPv4Header head; - - union { - struct { - std::uint8_t type; - std::uint8_t code; - }; - std::uint16_t type_code; - }; - std::uint16_t checksum; - - union { - struct { - std::uint16_t id; - std::uint16_t seq_num; - }; - struct { - std::uint16_t unused; - std::uint16_t nexthop_mtu; - }; - }; - }; -} - -#pragma pack(pop) diff --git a/Sources/OpenVPN3/openvpn/ip/icmp6.hpp b/Sources/OpenVPN3/openvpn/ip/icmp6.hpp deleted file mode 100644 index 5533e42..0000000 --- a/Sources/OpenVPN3/openvpn/ip/icmp6.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// 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-2020 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/>. - -// Define the ICMPv6 header - -#pragma once - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -#include <openvpn/ip/ip6.hpp> - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - - struct ICMPv6 { - enum { - ECHO_REQUEST = 128, - ECHO_REPLY = 129, - DEST_UNREACH = 1, - PACKET_TOO_BIG = 2 - }; - - struct IPv6Header head; - - union { - struct { - std::uint8_t type; - std::uint8_t code; - }; - std::uint16_t type_code; - }; - std::uint16_t checksum; - - union { - struct { - std::uint16_t id; - std::uint16_t seq_num; - }; - std::uint32_t mtu; - }; - }; -} - -#pragma pack(pop) diff --git a/Sources/OpenVPN3/openvpn/ip/ip4.hpp b/Sources/OpenVPN3/openvpn/ip/ip4.hpp deleted file mode 100644 index b5ad414..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ip4.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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-2020 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/>. - -// IPv4 header - -#pragma once - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - - struct IPv4Header - { - static unsigned int length(const std::uint8_t version_len) - { - return (version_len & 0x0F) << 2; - } - - static std::uint8_t ver_len(const unsigned int version, - const unsigned int len) - { - return ((len >> 2) & 0x0F) | (version & 0x0F) << 4; - } - - std::uint8_t version_len; - - std::uint8_t tos; - std::uint16_t tot_len; - std::uint16_t id; - - enum { - OFFMASK=0x1fff, - }; - std::uint16_t frag_off; - - std::uint8_t ttl; - - std::uint8_t protocol; - - std::uint16_t check; - std::uint32_t saddr; - std::uint32_t daddr; - /* The options start here. */ - }; -} - -#pragma pack(pop) diff --git a/Sources/OpenVPN3/openvpn/ip/ip6.hpp b/Sources/OpenVPN3/openvpn/ip/ip6.hpp deleted file mode 100644 index cb944bc..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ip6.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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/>. - -// IPv6 header - -#pragma once - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -#include <openvpn/common/socktypes.hpp> - -#pragma pack(push) -#pragma pack(1) - -namespace openvpn { - - struct IPv6Header - { - std::uint8_t version_prio; - - std::uint8_t flow_lbl[3]; - - std::uint16_t payload_len; - std::uint8_t nexthdr; - std::uint8_t hop_limit; - - struct in6_addr saddr; - struct in6_addr daddr; - }; -} - -#pragma pack(pop) diff --git a/Sources/OpenVPN3/openvpn/ip/ipcommon.hpp b/Sources/OpenVPN3/openvpn/ip/ipcommon.hpp deleted file mode 100644 index 4d8fb0f..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ipcommon.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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/>. - -// Common declarations for IPv4 and IPv6 - -#pragma once - -#include <cstdint> // for std::uint32_t, uint16_t, uint8_t - -namespace openvpn { - namespace IPCommon { - - enum { - ICMPv4 = 1, /* ICMPv4 protocol */ - ICMPv6 = 58, /* ICMPv6 protocol */ - IGMP = 2, /* IGMP protocol */ - TCP = 6, /* TCP protocol */ - UDP = 17, /* UDP protocol */ - }; - - enum { - IPv4 = 4, - IPv6 = 6 - }; - - inline unsigned int version(const std::uint8_t version_len_prio) - { - return (version_len_prio >> 4) & 0x0F; - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/ip/ping4.hpp b/Sources/OpenVPN3/openvpn/ip/ping4.hpp deleted file mode 100644 index e1cc81d..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ping4.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// 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-2020 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(); - } - } -} \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/ip/ping6.hpp b/Sources/OpenVPN3/openvpn/ip/ping6.hpp deleted file mode 100644 index 5e9c526..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ping6.hpp +++ /dev/null @@ -1,171 +0,0 @@ -// 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-2020 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(_WIN32) - return addr->u.Word; -#elif defined(__APPLE__) - return addr->__u6_addr.__u6_addr16; -#else - return addr->s6_addr16; -#endif - } - - inline std::uint16_t csum_ipv6_pseudo(const struct in6_addr *saddr, - const struct in6_addr *daddr, - const std::uint32_t len, - const std::uint16_t proto, - std::uint32_t sum) - { - int carry = 0; - std::uint32_t val = 0; - - const std::uint16_t* addr = get_addr16(saddr); - for (int i = 0; i < 4; ++i) - { - val = (std::uint32_t)(addr[i * 2] << 16) + addr[i * 2 + 1]; - sum += val; - carry = (sum < val); - sum += carry; - } - - addr = get_addr16(daddr); - for (int i = 0; i < 4; ++i) - { - val = (std::uint32_t)(addr[i * 2] << 16) + addr[i * 2 + 1]; - sum += val; - carry = (sum < val); - sum += carry; - } - - const std::uint32_t ulen = (std::uint32_t)htonl((std::uint32_t) len); - sum += ulen; - carry = (sum < ulen); - sum += carry; - - const std::uint32_t uproto = (std::uint32_t)htonl(proto); - sum += uproto; - carry = (sum < uproto); - sum += carry; - - return IPChecksum::cfold(sum); - } - - // len must be >= sizeof(ICMPv6) - inline std::uint16_t csum_icmp(const ICMPv6 *icmp, const size_t len) - { - return csum_ipv6_pseudo(&icmp->head.saddr, - &icmp->head.daddr, - len - sizeof(IPv6Header), - IPCommon::ICMPv6, - IPChecksum::compute((std::uint8_t *)icmp + sizeof(IPv6Header), len - sizeof(IPv6Header))); - } - - inline void generate_echo_request(Buffer& buf, - const IPv6::Addr& src, - const IPv6::Addr& dest, - const void *extra_data, - const size_t extra_data_size, - const unsigned int id, - const unsigned int seq_num, - const size_t total_size, - std::string* log_info) - { - const unsigned int data_size = std::max(int(extra_data_size), int(total_size) - int(sizeof(ICMPv6))); - - if (log_info) - *log_info = "PING6 " + src.to_string() + " -> " + dest.to_string() + " id=" + std::to_string(id) + " seq_num=" + std::to_string(seq_num) + " data_size=" + std::to_string(data_size); - - std::uint8_t *b = buf.write_alloc(sizeof(ICMPv6) + data_size); - ICMPv6 *icmp = (ICMPv6 *)b; - - // IP Header - icmp->head.version_prio = (6 << 4); - icmp->head.flow_lbl[0] = 0; - icmp->head.flow_lbl[1] = 0; - icmp->head.flow_lbl[2] = 0; - icmp->head.payload_len = htons(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size); - icmp->head.nexthdr = IPCommon::ICMPv6; - icmp->head.hop_limit = 64; - icmp->head.saddr = src.to_in6_addr(); - icmp->head.daddr = dest.to_in6_addr(); - - // ICMP header - icmp->type = ICMPv6::ECHO_REQUEST; - icmp->code = 0; - icmp->checksum = 0; - icmp->id = ntohs(id); - icmp->seq_num = ntohs(seq_num); - - // Data - std::uint8_t *data = b + sizeof(ICMPv6); - for (size_t i = 0; i < data_size; ++i) - data[i] = (std::uint8_t)i; - - // Extra data - std::memcpy(data, extra_data, extra_data_size); - - // ICMP checksum - icmp->checksum = csum_icmp(icmp, sizeof(ICMPv6) + data_size); - - //std::cout << dump_hex(buf); - } - - // assumes that buf is a validated ECHO_REQUEST - inline void generate_echo_reply(Buffer& buf, - std::string* log_info) - { - if (buf.size() < sizeof(ICMPv6)) - { - if (log_info) - *log_info = "Invalid ECHO6_REQUEST"; - return; - } - - ICMPv6* icmp = (ICMPv6*) buf.c_data(); - std::swap(icmp->head.saddr, icmp->head.daddr); - const std::uint16_t old_type_code = icmp->type_code; - icmp->type = ICMPv6::ECHO_REPLY; - icmp->checksum = IPChecksum::cfold(IPChecksum::diff2(old_type_code, icmp->type_code, IPChecksum::cunfold(icmp->checksum))); - - if (log_info) - *log_info = "ECHO6_REPLY size=" + std::to_string(buf.size()) + ' ' + IPv6::Addr::from_in6_addr(&icmp->head.saddr).to_string() + " -> " + IPv6::Addr::from_in6_addr(&icmp->head.daddr).to_string(); - } - } -} \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/ip/ptb.hpp b/Sources/OpenVPN3/openvpn/ip/ptb.hpp deleted file mode 100644 index 3c8005b..0000000 --- a/Sources/OpenVPN3/openvpn/ip/ptb.hpp +++ /dev/null @@ -1,136 +0,0 @@ -// 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-2020 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); - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/ip/tcp.hpp b/Sources/OpenVPN3/openvpn/ip/tcp.hpp deleted file mode 100644 index 9566b94..0000000 --- a/Sources/OpenVPN3/openvpn/ip/tcp.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// 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-2020 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; - } - } -} - diff --git a/Sources/OpenVPN3/openvpn/ip/udp.hpp b/Sources/OpenVPN3/openvpn/ip/udp.hpp deleted file mode 100644 index 4687179..0000000 --- a/Sources/OpenVPN3/openvpn/ip/udp.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// 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-2020 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/>. - -// Define the UDP header - -#ifndef OPENVPN_IP_UDP_H -#define OPENVPN_IP_UDP_H - -#include <openvpn/ip/ipcommon.hpp> - -namespace openvpn { - -#pragma pack(push) -#pragma pack(1) - - struct UDPHeader { - std::uint16_t source; - std::uint16_t dest; - std::uint16_t len; - std::uint16_t check; - }; - -#pragma pack(pop) - - inline std::uint16_t udp_checksum (const std::uint8_t *buf, - const unsigned int len_udp, - const std::uint8_t *src_addr, - const std::uint8_t *dest_addr) - { - std::uint32_t sum = 0; - - /* make 16 bit words out of every two adjacent 8 bit words and */ - /* calculate the sum of all 16 bit words */ - for (unsigned int i = 0; i < len_udp; i += 2) - { - std::uint16_t word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0); - sum += word16; - } - - /* add the UDP pseudo header which contains the IP source and destination addresses */ - for (unsigned int i = 0; i < 4; i += 2) - { - std::uint16_t word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF); - sum += word16; - } - for (unsigned int i = 0; i < 4; i += 2) - { - std::uint16_t word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF); - sum += word16; - } - - /* the protocol number and the length of the UDP packet */ - sum += (std::uint16_t)IPCommon::UDP + (std::uint16_t)len_udp; - - /* keep only the last 16 bits of the 32 bit calculated sum and add the carries */ - while (sum >> 16) - sum = (sum & 0xFFFF) + (sum >> 16); - - /* take the one's complement of sum */ - return std::uint16_t(~sum); - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/legal/copyright.hpp b/Sources/OpenVPN3/openvpn/legal/copyright.hpp deleted file mode 100644 index ddb42ba..0000000 --- a/Sources/OpenVPN3/openvpn/legal/copyright.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// 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-2020 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_LEGAL_COPYRIGHT_H -#define OPENVPN_LEGAL_COPYRIGHT_H - -// Define copyright strings - -namespace { - const char openvpn_copyright[] = "Copyright (C) 2012-2020 OpenVPN Inc. All rights reserved."; // CONST GLOBAL -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/linux/core.hpp b/Sources/OpenVPN3/openvpn/linux/core.hpp deleted file mode 100644 index 6d0b306..0000000 --- a/Sources/OpenVPN3/openvpn/linux/core.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// 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-2020 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/>. - -// Linux method for binding a thread to a particular core. - -#ifndef OPENVPN_LINUX_CORE_H -#define OPENVPN_LINUX_CORE_H - -#include <pthread.h> - -#include <openvpn/common/core.hpp> - -namespace openvpn { - - inline int bind_to_core(const int core_id) - { - const int num_cores = n_cores(); - if (core_id >= num_cores) - return EINVAL; - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(core_id, &cpuset); - - pthread_t current_thread = pthread_self(); - return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); - } - - inline int exclude_from_core(const int core_id) - { - const int num_cores = n_cores(); - if (num_cores <= 1 || core_id >= num_cores) - return EINVAL; - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - for (int i = 0; i < num_cores; ++i) - if (i != core_id) - CPU_SET(i, &cpuset); - - pthread_t current_thread = pthread_self(); - return pthread_setaffinity_np(current_thread, sizeof(cpu_set_t), &cpuset); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/linux/daemon_alive.hpp b/Sources/OpenVPN3/openvpn/linux/daemon_alive.hpp deleted file mode 100644 index fa85acc..0000000 --- a/Sources/OpenVPN3/openvpn/linux/daemon_alive.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// 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-2020 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_LINUX_DAEMON_ALIVE_H -#define OPENVPN_LINUX_DAEMON_ALIVE_H - -#include <openvpn/common/file.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/number.hpp> - -namespace openvpn { - inline int daemon_pid(const std::string& cmd, - const std::string& pidfile) - { - try { - std::string pidstr = read_text(pidfile); - string::trim_crlf(pidstr); - const std::string cmdline_fn = "/proc/" + pidstr + "/cmdline"; - BufferPtr cmdbuf = read_binary_linear(cmdline_fn); - const size_t len = ::strnlen((const char *)cmdbuf->c_data(), cmdbuf->size()); - if (cmd == std::string((const char *)cmdbuf->c_data(), len)) - { - int ret; - if (parse_number(pidstr, ret)) - return ret; - } - } - catch (const std::exception& e) - { - } - return -1; - } - - inline bool is_daemon_alive(const std::string& cmd, - const std::string& pidfile) - { - return daemon_pid(cmd, pidfile) >= 0; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/linux/procfs.hpp b/Sources/OpenVPN3/openvpn/linux/procfs.hpp deleted file mode 100644 index b3acf28..0000000 --- a/Sources/OpenVPN3/openvpn/linux/procfs.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// Private Gateway -// Copyright (C) 2012-2020 OpenVPN Technologies, Inc. -// All rights reserved - -#pragma once - -//#define OPENVPN_PROCFS_DEBUG - -#include <string> - -#include <openvpn/common/string.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/fileunix.hpp> -#include <openvpn/common/sleep.hpp> -#include <openvpn/common/stat.hpp> -#include <openvpn/common/format.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/buffer/bufstr.hpp> - -namespace openvpn { - - class ProcFS : public Action - { - public: - OPENVPN_EXCEPTION(procfs_error); - - ProcFS(std::string fn_arg, std::string text_arg) - : fn(std::move(fn_arg)), - text(std::move(text_arg)) - { - } - - virtual void execute(std::ostream& os) override - { - os << to_string() << std::endl; - try { - write_sys(fn, text); - } - catch (const std::exception& e) - { - os << "ProcFS exception: " << e.what() << std::endl; - } - } - - virtual std::string to_string() const override - { - return to_string(fn, text); - } - - static std::string to_string(const std::string& fn, const std::string& text) - { - return "ProcFS: " + fn + " -> " + string::trim_crlf_copy(text); - } - - static void write_sys(const std::string& fn, const std::string& text, Stop* async_stop=nullptr) - { - const unsigned int n_retries = 200; - const unsigned int milliseconds_per_retry = 100; - volatile bool stop = false; - - // allow asynchronous stop - Stop::Scope stop_scope(async_stop, [&stop]() { - stop = true; - }); - - for (unsigned int i = 0; i < n_retries && !stop; ++i) - { - if (file_exists(fn)) - { - try { - OPENVPN_LOG("ProcFS: " << fn << " -> '" << string::trim_crlf_copy(text) << '\''); - write_text_unix(fn, 0777, 0, text); - } - catch (const std::exception& e) - { - OPENVPN_LOG("ProcFS exception: " << e.what()); - } -#ifdef OPENVPN_PROCFS_DEBUG - sleep_milliseconds(100); - std::string text_verify; - BufferAllocated buf(256, 0); - const int status = read_binary_unix_fast(fn, buf); - if (status) - { - text_verify = strerror_str(status); - } - else - { - string::trim_crlf(buf); - text_verify = buf_to_string(buf); - } - OPENVPN_LOG("WRITE_SYS verify fn=" << fn << " text=" << string::trim_crlf_copy(text) << " verify=" << text_verify); -#endif - return; - } - sleep_milliseconds(milliseconds_per_retry); - } - if (stop) - OPENVPN_THROW(procfs_error, "file " << fn << " : aborting write attempt due to stop signal"); - else - OPENVPN_THROW(procfs_error, "file " << fn << " failed to appear within " << (n_retries * milliseconds_per_retry / 1000) << " seconds"); - } - - private: - std::string fn; - std::string text; - }; - - class IPv4ReversePathFilter : public ProcFS - { - public: - IPv4ReversePathFilter(const std::string& dev, const unsigned int value) - : ProcFS(key_fn(dev), openvpn::to_string(value)) - { - OPENVPN_LOG("IPv4ReversePathFilter " << dev << " -> " << value); - } - - static void write(const std::string& dev, const unsigned int value, Stop* stop=nullptr) - { - ProcFS::write_sys(key_fn(dev), openvpn::to_string(value), stop); - } - - private: - static std::string key_fn(const std::string& dev) - { - return printfmt("/proc/sys/net/ipv4/conf/%s/rp_filter", dev); - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/log/logbase.hpp b/Sources/OpenVPN3/openvpn/log/logbase.hpp deleted file mode 100644 index 9399f3c..0000000 --- a/Sources/OpenVPN3/openvpn/log/logbase.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// 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-2020 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_LOG_LOGBASE_H -#define OPENVPN_LOG_LOGBASE_H - -#include <string> - -#include <openvpn/common/rc.hpp> - -#define OPENVPN_LOG_CLASS openvpn::LogBase -#define OPENVPN_LOG_INFO(x) x - -namespace openvpn { - -#ifdef OPENVPN_LOGBASE_NO_RC - - struct LogBase - { - virtual void log(const std::string& str) = 0; - }; - -#else - - struct LogBase : public RC<thread_safe_refcount> - { - typedef RCPtr<LogBase> Ptr; - virtual void log(const std::string& str) = 0; - }; - -#endif -} - -#include <openvpn/log/logthread.hpp> - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/logbasesimple.hpp b/Sources/OpenVPN3/openvpn/log/logbasesimple.hpp deleted file mode 100644 index 3782faf..0000000 --- a/Sources/OpenVPN3/openvpn/log/logbasesimple.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// 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-2020 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_LOG_LOGBASESIMPLE_H -#define OPENVPN_LOG_LOGBASESIMPLE_H - -#include <iostream> -#include <mutex> - -#include <openvpn/log/logbase.hpp> -#include <openvpn/time/timestr.hpp> - -namespace openvpn { - class LogBaseSimple : public LogBase - { - public: - typedef RCPtr<LogBaseSimple> Ptr; - - LogBaseSimple() - : log_context(this) - { - } - - virtual void log(const std::string& str) override - { - const std::string ts = date_time(); - { - std::lock_guard<std::mutex> lock(mutex); - std::cout << ts << ' ' << str << std::flush; - } - } - - private: - std::mutex mutex; - Log::Context log_context; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/logbasesimplemac.hpp b/Sources/OpenVPN3/openvpn/log/logbasesimplemac.hpp deleted file mode 100644 index eec8759..0000000 --- a/Sources/OpenVPN3/openvpn/log/logbasesimplemac.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// 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-2020 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_LOG_LOGBASESIMPLEMAC_H -#define OPENVPN_LOG_LOGBASESIMPLEMAC_H - -#include <iostream> -#include <mutex> - -#include <openvpn/log/logbase.hpp> -#include <openvpn/time/timestr.hpp> - -#include <os/log.h> - -namespace openvpn { - class LogBaseSimpleMac : public LogBase - { - public: - typedef RCPtr<LogBaseSimpleMac> Ptr; - - LogBaseSimpleMac() - : log_context(this) - { - os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, - "LogBaseSimple for macOS/iOS initialized"); - } - - virtual void log(const std::string& str) override - { - std::lock_guard<std::mutex> lock(mutex); - os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, - "OVPN-CORE: %{public}s", str.c_str()); - } - - private: - std::mutex mutex; - Log::Context log_context; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/logdatetime.hpp b/Sources/OpenVPN3/openvpn/log/logdatetime.hpp deleted file mode 100644 index f36075c..0000000 --- a/Sources/OpenVPN3/openvpn/log/logdatetime.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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-2020 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/>. - -// Simple logging with data/time prepend - -#pragma once - -#include <iostream> -#include <openvpn/time/timestr.hpp> - -#ifndef OPENVPN_LOG_STREAM -#define OPENVPN_LOG_STREAM std::cout -#endif - -#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << date_time() << ' ' << args << std::endl - -// like OPENVPN_LOG but no trailing newline -#define OPENVPN_LOG_NTNL(args) OPENVPN_LOG_STREAM << date_time() << ' ' << args - -#define OPENVPN_LOG_STRING(str) OPENVPN_LOG_STREAM << date_time() << ' ' << (str) - -// no-op constructs normally used with logthread.hpp -namespace openvpn { - namespace Log { - struct Context - { - struct Wrapper {}; - Context(const Wrapper&) {} - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/log/lognull.hpp b/Sources/OpenVPN3/openvpn/log/lognull.hpp deleted file mode 100644 index 5612a43..0000000 --- a/Sources/OpenVPN3/openvpn/log/lognull.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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-2020 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/>. - -// Define null logging macros - -#ifndef OPENVPN_LOG_LOGNULL_H -#define OPENVPN_LOG_LOGNULL_H - -#define OPENVPN_LOG(args) - -// like OPENVPN_LOG but no trailing newline -#define OPENVPN_LOG_NTNL(args) - -#define OPENVPN_LOG_STRING(str) - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/logperiod.hpp b/Sources/OpenVPN3/openvpn/log/logperiod.hpp deleted file mode 100644 index 6d638f9..0000000 --- a/Sources/OpenVPN3/openvpn/log/logperiod.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// 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-2020 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_LOG_LOGPERIOD_H -#define OPENVPN_LOG_LOGPERIOD_H - -#include <sys/time.h> // for time_t - -#include <string> -#include <sstream> -#include <iomanip> // for setfill and setw - -#include <openvpn/common/olong.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/time/timestr.hpp> - -namespace openvpn { - class LogPeriod - { - public: - OPENVPN_EXCEPTION(log_period_error); - - enum Period { - UNDEF, - DAILY, - HOURLY, - BY_MINUTE, - }; - - LogPeriod() - : start_(0), - end_(0), - period_(UNDEF) - { - } - - LogPeriod(const Period period, const time_t base) - { - period_ = period; - const olong p = period_sec(period_); - start_ = period_base(period_, base); - end_ = start_ + p; - } - - LogPeriod(const LogPeriod& other, const int index) - { - period_ = other.period_; - const olong p = period_sec(period_); - start_ = other.start_ + p * olong(index); - end_ = start_ + p; - } - - bool is_current(const time_t now) const - { - const olong onow = olong(now); - return onow >= start_ && onow < end_; - } - - bool defined() const - { - return period_ != UNDEF; - } - - unsigned int expires_in(const time_t now) - { - const olong onow = olong(now); - if (onow < end_) - return end_ - onow; - else - return 0; - } - - std::string to_string_verbose() const - { - return date_time(start_) + " -> " + date_time(end_); - } - - std::string to_string() const - { - std::ostringstream os; - struct tm lt; - const time_t time = time_t(start_); - if (!localtime_r(&time, <)) - throw log_period_error("to_string localtime_r"); - os << std::setfill('0'); - os << std::setw(4) << (lt.tm_year + 1900) << '.' << std::setw(2) << (lt.tm_mon + 1) << '.' << std::setw(2) << lt.tm_mday; - if (period_ == HOURLY || period_ == BY_MINUTE) - os << '-' << std::setw(2) << lt.tm_hour << ':' << std::setw(2) << lt.tm_min; - return os.str(); - } - - static Period period_from_string(const std::string& str) - { - if (str == "daily") - return DAILY; - else if (str == "hourly") - return HOURLY; - else if (str == "by_minute") - return BY_MINUTE; - else - throw log_period_error("unknown period: " + str); - } - - private: - static olong period_sec(const Period p) - { - switch (p) - { - case DAILY: - return 86400; - case HOURLY: - return 3600; - case BY_MINUTE: - return 60; - default: - throw log_period_error("undefined period"); - } - } - - static olong period_base(const Period p, const time_t time) - { - struct tm lt; - if (!localtime_r(&time, <)) - throw log_period_error("period_base localtime_r"); - switch (p) - { - case DAILY: - lt.tm_hour = 0; - lt.tm_min = 0; - lt.tm_sec = 0; - break; - case HOURLY: - lt.tm_min = 0; - lt.tm_sec = 0; - break; - case BY_MINUTE: - lt.tm_sec = 0; - break; - default: - throw log_period_error("unknown period"); - } - const time_t ret = mktime(<); - if (ret == -1) - throw log_period_error("mktime"); - return olong(ret); - } - - private: - olong start_; - olong end_; - Period period_; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/logsimple.hpp b/Sources/OpenVPN3/openvpn/log/logsimple.hpp deleted file mode 100644 index 5de2fae..0000000 --- a/Sources/OpenVPN3/openvpn/log/logsimple.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// 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-2020 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/>. - -// Define simple logging macros that simply output to stdout - -#ifndef OPENVPN_LOG_LOGSIMPLE_H -#define OPENVPN_LOG_LOGSIMPLE_H - -#include <iostream> - -#ifndef OPENVPN_LOG_STREAM -#define OPENVPN_LOG_STREAM std::cout -#endif - -#define OPENVPN_LOG(args) OPENVPN_LOG_STREAM << args << std::endl - -// like OPENVPN_LOG but no trailing newline -#define OPENVPN_LOG_NTNL(args) OPENVPN_LOG_STREAM << args << std::flush - -#define OPENVPN_LOG_STRING(str) OPENVPN_LOG_STREAM << (str) << std::flush - -// no-op constructs normally used with logthread.hpp -namespace openvpn { - namespace Log { - struct Context - { - struct Wrapper {}; - Context(const Wrapper&) {} - }; - } -} - -#endif // OPENVPN_LOG_LOGSIMPLE_H diff --git a/Sources/OpenVPN3/openvpn/log/logthread.hpp b/Sources/OpenVPN3/openvpn/log/logthread.hpp deleted file mode 100644 index cf081b0..0000000 --- a/Sources/OpenVPN3/openvpn/log/logthread.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// 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-2020 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/>. - -// This is a general-purpose logging framework that allows for OPENVPN_LOG and -// OPENVPN_LOG_NTNL macros to dispatch logging data to a thread-local handler. - -// NOTE: define USE_ASIO_THREADLOCAL if your C++ doesn't support the -// "thread_local" attribute. - -#ifndef OPENVPN_LOG_LOGTHREAD_H -#define OPENVPN_LOG_LOGTHREAD_H - -#include <string> -#include <sstream> -#include <thread> - -#if defined(USE_ASIO) && defined(USE_ASIO_THREADLOCAL) -#include <asio/detail/tss_ptr.hpp> -#endif - -#include <openvpn/common/size.hpp> -#include <openvpn/common/extern.hpp> - -// Define these parameters before including this header: - -// OPENVPN_LOG_CLASS -- client class that exposes a log() method -// OPENVPN_LOG_INFO -- converts a log string to the form that should be passed to log() - -#ifndef OPENVPN_LOG_CLASS -#error OPENVPN_LOG_CLASS must be defined -#endif - -#ifndef OPENVPN_LOG_INFO -#error OPENVPN_LOG_INFO must be defined -#endif - -# define OPENVPN_LOG(args) \ - do { \ - if (openvpn::Log::Context::defined()) { \ - std::ostringstream _ovpn_log; \ - _ovpn_log << args << '\n'; \ - (openvpn::Log::Context::obj()->log(OPENVPN_LOG_INFO(_ovpn_log.str()))); \ - } \ - } while (0) - -// like OPENVPN_LOG but no trailing newline -#define OPENVPN_LOG_NTNL(args) \ - do { \ - if (openvpn::Log::Context::defined()) { \ - std::ostringstream _ovpn_log; \ - _ovpn_log << args; \ - (openvpn::Log::Context::obj()->log(OPENVPN_LOG_INFO(_ovpn_log.str()))); \ - } \ - } while (0) - -# define OPENVPN_LOG_STRING(str) \ - do { \ - if (openvpn::Log::Context::defined()) { \ - (openvpn::Log::Context::obj()->log(OPENVPN_LOG_INFO(str))); \ - } \ - } while (0) - -namespace openvpn { - namespace Log { - -#ifdef OPENVPN_LOG_GLOBAL - // OPENVPN_LOG uses global object pointer - OPENVPN_EXTERN OPENVPN_LOG_CLASS* global_log; // GLOBAL - struct Context - { - struct Wrapper - { - }; - - Context(const Wrapper& wrap) - { - } - - Context(OPENVPN_LOG_CLASS *cli) - { - global_log = cli; - } - - ~Context() - { - global_log = nullptr; - } - - static bool defined() - { - return global_log != nullptr; - } - - static OPENVPN_LOG_CLASS* obj() - { - return global_log; - } - }; -#else - // OPENVPN_LOG uses thread-local object pointer -#if defined(USE_ASIO) && defined(USE_ASIO_THREADLOCAL) - OPENVPN_EXTERN asio::detail::tss_ptr<OPENVPN_LOG_CLASS> global_log; // GLOBAL -#else - OPENVPN_EXTERN thread_local OPENVPN_LOG_CLASS* global_log; // GLOBAL -#endif - struct Context - { - // Mechanism for passing thread-local - // global_log to another thread. - class Wrapper - { - public: - Wrapper() : log(obj()) {} - private: - friend struct Context; - OPENVPN_LOG_CLASS *log; - }; - - // While in scope, turns on global_log - // for this thread. - Context(const Wrapper& wrap) - { - global_log = wrap.log; - } - - Context(OPENVPN_LOG_CLASS *cli) - { - global_log = cli; - } - - ~Context() - { - global_log = nullptr; - } - - static bool defined() - { - return global_log != nullptr; - } - - static OPENVPN_LOG_CLASS* obj() - { - return global_log; - } - }; -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/log/sessionstats.hpp b/Sources/OpenVPN3/openvpn/log/sessionstats.hpp deleted file mode 100644 index 450bc6d..0000000 --- a/Sources/OpenVPN3/openvpn/log/sessionstats.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// 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-2020 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/>. - -// A class that handles statistics tracking in an OpenVPN session - -#ifndef OPENVPN_LOG_SESSIONSTATS_H -#define OPENVPN_LOG_SESSIONSTATS_H - -#include <cstring> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/count.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/time/time.hpp> - -namespace openvpn { - - class SessionStats : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<SessionStats> Ptr; - - enum Stats { - // operating stats - BYTES_IN = 0, // network bytes in - BYTES_OUT, // network bytes out - PACKETS_IN, // network packets in - PACKETS_OUT, // network packets out - TUN_BYTES_IN, // tun/tap bytes in - TUN_BYTES_OUT, // tun/tap bytes out - TUN_PACKETS_IN, // tun/tap packets in - TUN_PACKETS_OUT, // tun/tap packets out - N_STATS, - }; - - SessionStats() - : verbose_(false) - { - std::memset((void *)stats_, 0, sizeof(stats_)); - } - - virtual void error(const size_t type, const std::string* text=nullptr) {} - - // if true, clients may provide additional detail to error() method above - // via text argument. - bool verbose() const { return verbose_; } - -#ifdef OPENVPN_STATS_VIRTUAL - virtual -#endif - void inc_stat(const size_t type, const count_t value) - { - if (type < N_STATS) - stats_[type] += value; - } - - count_t get_stat(const size_t type) const - { - if (type < N_STATS) - return stats_[type]; - else - return 0; - } - - count_t get_stat_fast(const size_t type) const - { - return stats_[type]; - } - - static const char *stat_name(const size_t type) - { - static const char *names[] = { - "BYTES_IN", - "BYTES_OUT", - "PACKETS_IN", - "PACKETS_OUT", - "TUN_BYTES_IN", - "TUN_BYTES_OUT", - "TUN_PACKETS_IN", - "TUN_PACKETS_OUT", - }; - - if (type < N_STATS) - return names[type]; - else - return "UNKNOWN_STAT_TYPE"; - } - - void update_last_packet_received(const Time& now) - { - last_packet_received_ = now; - } - - const Time& last_packet_received() const { return last_packet_received_; } - - struct DCOTransportSource : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<DCOTransportSource> Ptr; - - struct Data { - count_t bytes_in; - count_t bytes_out; - - Data() - : bytes_in(0), - bytes_out(0) - { - } - - Data(count_t bytes_in_arg, count_t bytes_out_arg) - : bytes_in(bytes_in_arg), - bytes_out(bytes_out_arg) - { - } - - Data operator-(const Data& rhs) const - { - Data data; - if (bytes_in > rhs.bytes_in) - data.bytes_in = bytes_in - rhs.bytes_in; - if (bytes_out > rhs.bytes_out) - data.bytes_out = bytes_out - rhs.bytes_out; - return data; - } - }; - - virtual Data dco_transport_stats_delta() = 0; - }; - - void dco_configure(SessionStats::DCOTransportSource* source) - { - dco_.reset(source); - } - - void dco_update() - { - if (dco_) - { - const DCOTransportSource::Data data = dco_->dco_transport_stats_delta(); - stats_[BYTES_IN] += data.bytes_in; - stats_[BYTES_OUT] += data.bytes_out; - } - } - - protected: - void session_stats_set_verbose(const bool v) { verbose_ = v; } - - private: - bool verbose_; - Time last_packet_received_; - DCOTransportSource::Ptr dco_; - volatile count_t stats_[N_STATS]; - }; - -} // namespace openvpn - -#endif // OPENVPN_LOG_SESSIONSTATS_H diff --git a/Sources/OpenVPN3/openvpn/mbedtls/crypto/api.hpp b/Sources/OpenVPN3/openvpn/mbedtls/crypto/api.hpp deleted file mode 100644 index 0d34889..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/crypto/api.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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_MBEDTLS_CRYPTO_API_H -#define OPENVPN_MBEDTLS_CRYPTO_API_H - -#include <openvpn/mbedtls/crypto/cipher.hpp> -#include <openvpn/mbedtls/crypto/cipheraead.hpp> -#include <openvpn/mbedtls/crypto/digest.hpp> -#include <openvpn/mbedtls/crypto/hmac.hpp> - -namespace openvpn { - - // type container for MbedTLS Crypto-level API - struct MbedTLSCryptoAPI { - // cipher - typedef MbedTLSCrypto::CipherContext CipherContext; - typedef MbedTLSCrypto::CipherContextAEAD CipherContextAEAD; - - // digest - typedef MbedTLSCrypto::DigestContext DigestContext; - - // HMAC - typedef MbedTLSCrypto::HMACContext HMACContext; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipher.hpp b/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipher.hpp deleted file mode 100644 index 3387fb1..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipher.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS cipher API defined in <mbedtls/cipher.h> so -// that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_MBEDTLS_CRYPTO_CIPHER_H -#define OPENVPN_MBEDTLS_CRYPTO_CIPHER_H - -#include <string> - -#include <mbedtls/cipher.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> - -namespace openvpn { - namespace MbedTLSCrypto { - class CipherContextCommon { - public: - OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_mode_error); - OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_uninitialized); - - // mode parameter for constructor - enum { - MODE_UNDEF = MBEDTLS_OPERATION_NONE, - ENCRYPT = MBEDTLS_ENCRYPT, - DECRYPT = MBEDTLS_DECRYPT - }; - - protected: - static void check_mode(int mode) - { - // check that mode is valid - if (!(mode == ENCRYPT || mode == DECRYPT)) - throw mbedtls_cipher_mode_error(); - } - - void erase() - { - if (initialized) - { - mbedtls_cipher_free(&ctx); - initialized = false; - } - } - - void check_initialized() const - { - if (unlikely(!initialized)) - throw mbedtls_cipher_uninitialized(); - } - - bool initialized = false; - mbedtls_cipher_context_t ctx; - }; - - class CipherContext - : public CipherContextCommon - { - CipherContext(const CipherContext&) = delete; - CipherContext& operator=(const CipherContext&) = delete; - - public: - OPENVPN_EXCEPTION(mbedtls_cipher_error); - - // mode parameter for constructor - enum { - MODE_UNDEF = MBEDTLS_OPERATION_NONE, - ENCRYPT = MBEDTLS_ENCRYPT, - DECRYPT = MBEDTLS_DECRYPT - }; - - // mbed TLS cipher constants - enum { - MAX_IV_LENGTH = MBEDTLS_MAX_IV_LENGTH, - CIPH_CBC_MODE = MBEDTLS_MODE_CBC - }; - - CipherContext() = default; - - ~CipherContext() { erase() ; } - - void init(const CryptoAlgs::Type alg, const unsigned char *key, const int mode) - { - erase(); - - check_mode(mode); - - // get cipher type - const mbedtls_cipher_info_t *ci = cipher_type(alg); - - // initialize cipher context with cipher type - if (mbedtls_cipher_setup(&ctx, ci) < 0) - throw mbedtls_cipher_error("mbedtls_cipher_setup"); - - // set key and encrypt/decrypt mode - if (mbedtls_cipher_setkey(&ctx, key, ci->key_bitlen, (mbedtls_operation_t)mode) < 0) - throw mbedtls_cipher_error("mbedtls_cipher_setkey"); - - initialized = true; - } - - void reset(const unsigned char *iv) - { - check_initialized(); - if (mbedtls_cipher_reset(&ctx) < 0) - throw mbedtls_cipher_error("mbedtls_cipher_reset"); - if (mbedtls_cipher_set_iv(&ctx, iv, iv_length())) - throw mbedtls_cipher_error("mbedtls_cipher_set_iv"); - } - - bool update(unsigned char *out, const size_t max_out_size, - const unsigned char *in, const size_t in_size, - size_t& out_acc) - { - check_initialized(); - size_t outlen; - if (mbedtls_cipher_update(&ctx, in, in_size, out, &outlen) >= 0) - { - out_acc += outlen; - return true; - } - else - return false; - } - - bool final(unsigned char *out, const size_t max_out_size, size_t& out_acc) - { - check_initialized(); - size_t outlen; - if (mbedtls_cipher_finish (&ctx, out, &outlen) >= 0) - { - out_acc += outlen; - return true; - } - else - return false; - } - - bool is_initialized() const { return initialized; } - - size_t iv_length() const - { - check_initialized(); - return mbedtls_cipher_get_iv_size(&ctx); - } - - size_t block_size() const - { - check_initialized(); - return mbedtls_cipher_get_block_size(&ctx); - } - - // return cipher mode (such as CIPH_CBC_MODE, etc.) - int cipher_mode() const - { - check_initialized(); - return mbedtls_cipher_get_cipher_mode(&ctx); - } - - private: - static const mbedtls_cipher_info_t *cipher_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::AES_128_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CBC); - case CryptoAlgs::AES_192_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_CBC); - case CryptoAlgs::AES_256_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC); - case CryptoAlgs::AES_256_CTR: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR); - case CryptoAlgs::DES_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); - case CryptoAlgs::DES_EDE3_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC); - case CryptoAlgs::BF_CBC: - return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_BLOWFISH_CBC); - default: - OPENVPN_THROW(mbedtls_cipher_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipheraead.hpp b/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipheraead.hpp deleted file mode 100644 index 2e45ba6..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/crypto/cipheraead.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS AEAD API. - -#pragma once - -#include <string> - -#include <mbedtls/gcm.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/mbedtls/crypto/cipher.hpp> - -namespace openvpn { - namespace MbedTLSCrypto { - class CipherContextAEAD : public CipherContextCommon - { - CipherContextAEAD(const CipherContextAEAD&) = delete; - CipherContextAEAD& operator=(const CipherContextAEAD&) = delete; - - public: - OPENVPN_EXCEPTION(mbedtls_aead_error); - - - // mbed TLS cipher constants - enum { - IV_LEN = 12, - AUTH_TAG_LEN = 16, - SUPPORTS_IN_PLACE_ENCRYPT = 1, - }; - -#if 0 - // mbed TLS encrypt/decrypt return values - enum { - GCM_AUTH_FAILED = MBEDTLS_ERR_GCM_AUTH_FAILED, - SUCCESS = 0, - }; -#endif - - CipherContextAEAD() = default; - - ~CipherContextAEAD() { erase() ; } - - void init(const CryptoAlgs::Type alg, - const unsigned char *key, - const unsigned int keysize, - const int mode) - { - erase(); - - check_mode(mode); - - // get cipher type - unsigned int ckeysz = 0; - const mbedtls_cipher_type_t cid = cipher_type(alg, ckeysz); - if (cid == MBEDTLS_CIPHER_NONE) - OPENVPN_THROW(mbedtls_aead_error, CryptoAlgs::name(alg) << ": not usable"); - - if (ckeysz > keysize) - throw mbedtls_aead_error("insufficient key material"); - - auto* ci = mbedtls_cipher_info_from_type(cid); - - // initialize cipher context with cipher type - if (mbedtls_cipher_setup(&ctx, ci) < 0) - throw mbedtls_aead_error("mbedtls_cipher_setup"); - - if (mbedtls_cipher_setkey(&ctx, key, ckeysz * 8, (mbedtls_operation_t)mode) < 0) - throw mbedtls_aead_error("mbedtls_cipher_setkey"); - - initialized = true; - } - - void encrypt(const unsigned char *input, - unsigned char *output, - size_t length, - const unsigned char *iv, - unsigned char *tag, - const unsigned char *ad, - size_t ad_len) - { - check_initialized(); - const int status = mbedtls_cipher_auth_encrypt(&ctx, iv, IV_LEN, ad, ad_len, input, length, - output, &length, tag, AUTH_TAG_LEN); - if (unlikely(status)) - OPENVPN_THROW(mbedtls_aead_error, "mbedtls_gcm_crypt_and_tag failed with status=" << status); - } - - // input and output may NOT be equal - bool decrypt(const unsigned char *input, - unsigned char *output, - size_t length, - const unsigned char *iv, - const unsigned char *tag, - const unsigned char *ad, - size_t ad_len) - { - check_initialized(); - - // Older versions of mbed TLS have the tag a non const, even though it is - // not modified, const cast it here - const int status = mbedtls_cipher_auth_encrypt(&ctx, iv, IV_LEN, ad, ad_len, input, length, output, &length, - const_cast<unsigned char*>(tag), AUTH_TAG_LEN); - return status == 0; - } - - bool is_initialized() const { return initialized; } - - static bool is_supported(const CryptoAlgs::Type alg) - { - unsigned int keysize; - return (cipher_type(alg, keysize) != MBEDTLS_CIPHER_NONE); - } - - private: - static mbedtls_cipher_type_t cipher_type(const CryptoAlgs::Type alg, unsigned int& keysize) - { - switch (alg) - { - case CryptoAlgs::AES_128_GCM: - keysize = 16; - return MBEDTLS_CIPHER_AES_128_GCM; - case CryptoAlgs::AES_192_GCM: - keysize = 24; - return MBEDTLS_CIPHER_AES_192_GCM; - case CryptoAlgs::AES_256_GCM: - keysize = 32; - return MBEDTLS_CIPHER_AES_256_GCM; -#ifdef MBEDTLS_CHACHAPOLY_C - case CryptoAlgs::CHACHA20_POLY1305: - keysize = 32; - return MBEDTLS_CIPHER_CHACHA20_POLY1305; -#endif - default: - keysize =0; - return MBEDTLS_CIPHER_NONE; - } - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/mbedtls/crypto/digest.hpp b/Sources/OpenVPN3/openvpn/mbedtls/crypto/digest.hpp deleted file mode 100644 index 541a0df..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/crypto/digest.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS digest API defined in <mbedtls/md.h> -// so that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_MBEDTLS_CRYPTO_DIGEST_H -#define OPENVPN_MBEDTLS_CRYPTO_DIGEST_H - -#include <string> - -#include <mbedtls/md.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> - -namespace openvpn { - namespace MbedTLSCrypto { - class HMACContext; - - class DigestContext - { - DigestContext(const DigestContext&) = delete; - DigestContext& operator=(const DigestContext&) = delete; - - public: - friend class HMACContext; - - OPENVPN_SIMPLE_EXCEPTION(mbedtls_digest_uninitialized); - OPENVPN_SIMPLE_EXCEPTION(mbedtls_digest_final_overflow); - OPENVPN_EXCEPTION(mbedtls_digest_error); - - enum { - MAX_DIGEST_SIZE = MBEDTLS_MD_MAX_SIZE - }; - - DigestContext() - : initialized(false) - { - } - - DigestContext(const CryptoAlgs::Type alg) - : initialized(false) - { - init(alg); - } - - ~DigestContext() { erase() ; } - - void init(const CryptoAlgs::Type alg) - { - erase(); - ctx.md_ctx = nullptr; - - mbedtls_md_init(&ctx); - if ( mbedtls_md_setup(&ctx, digest_type(alg), 1) < 0) - throw mbedtls_digest_error("mbedtls_md_setup"); - if (mbedtls_md_starts(&ctx) < 0) - throw mbedtls_digest_error("mbedtls_md_starts"); - initialized = true; - } - - void update(const unsigned char *in, const size_t size) - { - check_initialized(); - if (mbedtls_md_update(&ctx, in, size) < 0) - throw mbedtls_digest_error("mbedtls_md_update"); - } - - size_t final(unsigned char *out) - { - check_initialized(); - if (mbedtls_md_finish(&ctx, out) < 0) - throw mbedtls_digest_error("mbedtls_md_finish"); - return size_(); - } - - size_t size() const - { - check_initialized(); - return size_(); - } - - bool is_initialized() const { return initialized; } - - private: - static const mbedtls_md_info_t *digest_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::MD4: - return mbedtls_md_info_from_type(MBEDTLS_MD_MD4); - case CryptoAlgs::MD5: - return mbedtls_md_info_from_type(MBEDTLS_MD_MD5); - case CryptoAlgs::SHA1: - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - case CryptoAlgs::SHA224: - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); - case CryptoAlgs::SHA256: - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - case CryptoAlgs::SHA384: - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); - case CryptoAlgs::SHA512: - return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); - default: - OPENVPN_THROW(mbedtls_digest_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - - void erase() - { - if (initialized) - { - mbedtls_md_free(&ctx); - initialized = false; - } - } - - size_t size_() const - { - return mbedtls_md_get_size(ctx.md_info); - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!initialized) - throw mbedtls_digest_uninitialized(); -#endif - } - - bool initialized; - mbedtls_md_context_t ctx; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/crypto/hmac.hpp b/Sources/OpenVPN3/openvpn/mbedtls/crypto/hmac.hpp deleted file mode 100644 index a6ebcd9..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/crypto/hmac.hpp +++ /dev/null @@ -1,134 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS HMAC API defined in <mbedtls/md.h> so -// that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_MBEDTLS_CRYPTO_HMAC_H -#define OPENVPN_MBEDTLS_CRYPTO_HMAC_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/mbedtls/crypto/digest.hpp> - -namespace openvpn { - namespace MbedTLSCrypto { - class HMACContext - { - HMACContext(const HMACContext&) = delete; - HMACContext& operator=(const HMACContext&) = delete; - - public: - OPENVPN_SIMPLE_EXCEPTION(mbedtls_hmac_uninitialized); - OPENVPN_EXCEPTION(mbedtls_hmac_error); - - enum { - MAX_HMAC_SIZE = MBEDTLS_MD_MAX_SIZE - }; - - HMACContext() - : initialized(false) - { - } - - HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - : initialized(false) - { - init(digest, key, key_size); - } - - ~HMACContext() { erase() ; } - - void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - { - erase(); - ctx.md_ctx = nullptr; - - mbedtls_md_init(&ctx); - if (mbedtls_md_setup(&ctx, DigestContext::digest_type(digest), 1) < 0) - throw mbedtls_hmac_error("mbedtls_md_setup"); - if (mbedtls_md_hmac_starts(&ctx, key, key_size) < 0) - throw mbedtls_hmac_error("mbedtls_md_hmac_starts"); - initialized = true; - } - - void reset() - { - check_initialized(); - if (mbedtls_md_hmac_reset(&ctx) < 0) - throw mbedtls_hmac_error("mbedtls_md_hmac_reset"); - } - - void update(const unsigned char *in, const size_t size) - { - check_initialized(); - if (mbedtls_md_hmac_update(&ctx, in, size) < 0) - throw mbedtls_hmac_error("mbedtls_md_hmac_update"); - } - - size_t final(unsigned char *out) - { - check_initialized(); - if (mbedtls_md_hmac_finish(&ctx, out) < 0) - throw mbedtls_hmac_error("mbedtls_md_hmac_finish"); - return size_(); - } - - size_t size() const - { - check_initialized(); - return size_(); - } - - bool is_initialized() const { return initialized; } - - private: - void erase() - { - if (initialized) - { - mbedtls_md_free(&ctx); - initialized = false; - } - } - - size_t size_() const - { - return mbedtls_md_get_size(ctx.md_info); - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!initialized) - throw mbedtls_hmac_uninitialized(); -#endif - } - - bool initialized; - mbedtls_md_context_t ctx; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/pki/dh.hpp b/Sources/OpenVPN3/openvpn/mbedtls/pki/dh.hpp deleted file mode 100644 index dba3bf9..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/pki/dh.hpp +++ /dev/null @@ -1,124 +0,0 @@ -// 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-2020 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/>. - -// Wrap a mbed TLS dhm_context object (Diffie Hellman parameters). - -#ifndef OPENVPN_MBEDTLS_PKI_DH_H -#define OPENVPN_MBEDTLS_PKI_DH_H - -#include <string> -#include <sstream> -#include <cstring> - -#include <mbedtls/x509.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -namespace openvpn { - namespace MbedTLSPKI { - - class DH : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<DH> Ptr; - - DH() : dhc(nullptr) {} - - DH(const std::string& dh_txt, const std::string& title) - : dhc(nullptr) - { - try { - parse(dh_txt, title); - } - catch (...) - { - dealloc(); - throw; - } - } - - void parse(const std::string& dh_txt, const std::string& title) - { - alloc(); - // dh_txt.length() is increased by 1 as it does not include the NULL-terminator - // which mbedtls_dhm_parse_dhm() expects to see. - const int status = mbedtls_dhm_parse_dhm(dhc, - (const unsigned char *)dh_txt.c_str(), - dh_txt.length() + 1); - if (status < 0) - { - throw MbedTLSException("error parsing " + title + " DH parameters", status); - } - if (status > 0) - { - std::ostringstream os; - os << status << " DH parameters in " << title << " failed to parse"; - throw MbedTLSException(os.str()); - } - // store PEM data to allow extraction - pem_dhc = dh_txt; - } - - std::string extract() const - { - return std::string(pem_dhc); - } - - mbedtls_dhm_context* get() const - { - return dhc; - } - - ~DH() - { - dealloc(); - } - - private: - void alloc() - { - if (!dhc) - { - dhc = new mbedtls_dhm_context; - mbedtls_dhm_init(dhc); - } - } - - void dealloc() - { - if (dhc) - { - mbedtls_dhm_free(dhc); - delete dhc; - dhc = nullptr; - } - } - - mbedtls_dhm_context *dhc; - std::string pem_dhc; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/pki/pkctx.hpp b/Sources/OpenVPN3/openvpn/mbedtls/pki/pkctx.hpp deleted file mode 100644 index 85dcf7e..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/pki/pkctx.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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-2020 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/>. - -// Wrap a mbed TLS pk_context object. - -#ifndef OPENVPN_MBEDTLS_PKI_PKCTX_H -#define OPENVPN_MBEDTLS_PKI_PKCTX_H - -#include <string> -#include <sstream> -#include <cstring> - -#include <mbedtls/pk.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -namespace openvpn { - namespace MbedTLSPKI { - - class PKContext : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<PKContext> Ptr; - - PKContext() : ctx(nullptr) {} - - PKContext(const std::string& key_txt, const std::string& title, const std::string& priv_key_pwd) - : ctx(nullptr) - { - try { - parse(key_txt, title, priv_key_pwd); - } - catch (...) - { - dealloc(); - throw; - } - } - - bool defined() const - { - return ctx != nullptr; - } - - PKType::Type key_type() const - { - switch (mbedtls_pk_get_type(ctx)) - { - case MBEDTLS_PK_RSA: - case MBEDTLS_PK_RSA_ALT: - case MBEDTLS_PK_RSASSA_PSS: - return PKType::PK_RSA; - case MBEDTLS_PK_ECKEY: - case MBEDTLS_PK_ECKEY_DH: - return PKType::PK_EC; - case MBEDTLS_PK_ECDSA: - return PKType::PK_ECDSA; - case MBEDTLS_PK_NONE: - return PKType::PK_NONE; - default: - return PKType::PK_UNKNOWN; - } - } - - size_t key_length() const - { - return mbedtls_pk_get_bitlen(ctx); - } - - void parse(const std::string& key_txt, const std::string& title, const std::string& priv_key_pwd) - { - alloc(); - // key_txt.length() is increased by 1 as it does not include the NULL-terminator - // which mbedtls_pk_parse_key() expects to see. - const int status = mbedtls_pk_parse_key(ctx, - (const unsigned char *)key_txt.c_str(), - key_txt.length() + 1, - (const unsigned char *)priv_key_pwd.c_str(), - priv_key_pwd.length()); - if (status < 0) - throw MbedTLSException("error parsing " + title + " private key", status); - } - - std::string extract() const - { - // maximum size of the PEM data is not available at this point - BufferAllocated buff(16000, 0); - - int ret = mbedtls_pk_write_key_pem(ctx, buff.data(), buff.max_size()); - if (ret < 0) - throw MbedTLSException("extract priv_key: can't write to buffer", ret); - - return std::string((const char *)buff.data()); - } - - void epki_enable(void *arg, - mbedtls_pk_rsa_alt_decrypt_func epki_decrypt, - mbedtls_pk_rsa_alt_sign_func epki_sign, - mbedtls_pk_rsa_alt_key_len_func epki_key_len) - { - alloc(); - const int status = mbedtls_pk_setup_rsa_alt(ctx, arg, epki_decrypt, epki_sign, epki_key_len); - if (status < 0) - throw MbedTLSException("error in mbedtls_pk_setup_rsa_alt", status); - } - - mbedtls_pk_context* get() const - { - return ctx; - } - - ~PKContext() - { - dealloc(); - } - - private: - void alloc() - { - if (!ctx) - { - ctx = new mbedtls_pk_context; - mbedtls_pk_init(ctx); - } - } - - void dealloc() - { - if (ctx) - { - mbedtls_pk_free(ctx); - delete ctx; - ctx = nullptr; - } - } - - mbedtls_pk_context *ctx; - }; - - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509cert.hpp b/Sources/OpenVPN3/openvpn/mbedtls/pki/x509cert.hpp deleted file mode 100644 index fe4a21b..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509cert.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// 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-2020 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/>. - -// Wrap a mbed TLS x509_crt object - -#ifndef OPENVPN_MBEDTLS_PKI_X509CERT_H -#define OPENVPN_MBEDTLS_PKI_X509CERT_H - -#include <string> -#include <sstream> -#include <cstring> -#include <iostream> - -#include <mbedtls/x509.h> -#include <mbedtls/pem.h> -#include <mbedtls/base64.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -namespace openvpn { - namespace MbedTLSPKI { - - class X509Cert : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<X509Cert> Ptr; - - X509Cert() : chain(nullptr) {} - - X509Cert(const std::string& cert_txt, const std::string& title, const bool strict) - : chain(nullptr) - { - try { - parse(cert_txt, title, strict); - } - catch (...) - { - dealloc(); - throw; - } - } - - void parse(const std::string& cert_txt, const std::string& title, const bool strict) - { - alloc(); - - if (cert_txt.empty()) - throw MbedTLSException(title + " certificate is undefined"); - - // cert_txt.length() is increased by 1 as it does not include the NULL-terminator - // which mbedtls_x509_crt_parse() expects to see. - const int status = mbedtls_x509_crt_parse(chain, - (const unsigned char *)cert_txt.c_str(), - cert_txt.length() + 1); - if (status < 0) - { - throw MbedTLSException("error parsing " + title + " certificate", status); - } - if (status > 0) - { - std::ostringstream os; - os << status << " certificate(s) in " << title << " bundle failed to parse"; - if (strict) - throw MbedTLSException(os.str()); - else - OPENVPN_LOG("MBEDTLS: " << os.str()); - } - } - - static std::string der_to_pem(const unsigned char* der, size_t der_size) - { - size_t olen = 0; - int ret; - - ret = mbedtls_pem_write_buffer(begin_cert, end_cert, der, - der_size, NULL, 0, &olen); - if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) - throw MbedTLSException("X509Cert::extract: can't calculate PEM size"); - - BufferAllocated buff(olen, 0); - - ret = mbedtls_pem_write_buffer(begin_cert, end_cert, der, - der_size, buff.data(), buff.max_size(), &olen); - if (ret) - throw MbedTLSException("X509Cert::extract: can't write PEM buffer"); - - return std::string((const char *)buff.data()); - } - - std::string extract() const - { - return der_to_pem(chain->raw.p, chain->raw.len); - } - - std::vector<std::string> extract_extra_certs() const - { - std::vector<std::string> extra_certs; - - /* extra certificates are appended to the main one */ - for (mbedtls_x509_crt *cert = chain->next; cert; cert = cert->next) - { - extra_certs.push_back(der_to_pem(cert->raw.p, cert->raw.len)); - } - return extra_certs; - } - - mbedtls_x509_crt* get() const - { - return chain; - } - - virtual ~X509Cert() - { - dealloc(); - } - - protected: - void alloc() - { - if (!chain) - { - chain = new mbedtls_x509_crt; - mbedtls_x509_crt_init(chain); - } - } - - mbedtls_x509_crt *chain; - - private: - void dealloc() - { - if (chain) - { - mbedtls_x509_crt_free(chain); - delete chain; - chain = nullptr; - } - } - - constexpr static const char* begin_cert = "-----BEGIN CERTIFICATE-----\n";; - constexpr static const char* end_cert = "-----END CERTIFICATE-----\n";; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509certinfo.hpp b/Sources/OpenVPN3/openvpn/mbedtls/pki/x509certinfo.hpp deleted file mode 100644 index 513e5f8..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509certinfo.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// 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-2020 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 <cstring> -#include <string> -#include <vector> - -#include <mbedtls/x509.h> -#include <mbedtls/x509_crt.h> -#include <mbedtls/oid.h> - -#include "openvpn/common/hexstr.hpp" - -#define MBEDTLS_MAX_SUBJECT_LENGTH 256 - -namespace openvpn { -namespace MbedTLSPKI { - -/** - * Retrieve the complete X.509 Certificate Subject field - * - * OpenSSL supports two ways of representing the subject line. The old - * format is deprecated, but there might be code expecting this old format. - * The old format looks like this: - * - * /C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server/emailAddress=me@myhost.mydomain - * - * The new format is UTF-8 compliant and has a different formatting scheme: - * - * C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, - *emailAddress=me@myhost.mydomain - * - * This mbed TLS implementation supports generating a subject line formatted - * as the deprecated OpenSSL format. This is the default behaviour, to - * preserve OpenSSL compatibility with existing OpenVPN code. - * - * @param cert Pointer to a native mbed TLS X509 object containing the - * certificate - * @param new_format (optional, default: false) Which format to use, - * true indicates the new format - * - * @return Returns a std::string containing the complete certificate subject. - * If it was not possible to retrieve the subject, and empty string - * is returned. - */ -static std::string x509_get_subject(const mbedtls_x509_crt *cert, - bool new_format = false) { - if (!new_format) { - // Try to return the x509 subject formatted like the OpenSSL - // X509_NAME_oneline method. Only attributes matched in the switch - // statements below will be rendered. All other attributes will be - // ignored. - - std::string ret; - for (const mbedtls_x509_name *name = &cert->subject; name != nullptr; - name = name->next) { - const char *key = nullptr; - if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) - key = "CN"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_COUNTRY, &name->oid)) - key = "C"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_LOCALITY, &name->oid)) - key = "L"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_STATE, &name->oid)) - key = "ST"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORGANIZATION, &name->oid)) - key = "O"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORG_UNIT, &name->oid)) - key = "OU"; - else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_EMAIL, &name->oid)) - key = "emailAddress"; - - // make sure that key is defined and value has no embedded nulls - if (key && - !string::embedded_null((const char *)name->val.p, name->val.len)) - ret += "/" + std::string(key) + "=" + - std::string((const char *)name->val.p, name->val.len); - } - return ret; - } - - char tmp_subj[MBEDTLS_MAX_SUBJECT_LENGTH] = {0}; - int ret = mbedtls_x509_dn_gets(tmp_subj, MBEDTLS_MAX_SUBJECT_LENGTH - 1, - &cert->subject); - return (ret > 0 ? std::string(tmp_subj) : std::string("")); -} - -/** - * Retrieves just the common name of the X.509 Certificate subject field - * - * @param cert Pointer to a native mbedTLS X509 object containing the - * certificate - * - * @return Returns the contents of the extracted field on success. The - * resulting string may be empty if the extraction failed or the field - * is empty. - */ -static std::string x509_get_common_name(const mbedtls_x509_crt *cert) { - const mbedtls_x509_name *name = &cert->subject; - - // find common name - while (name != nullptr) { - if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) { - break; - } - name = name->next; - } - - return (name ? std::string((const char *)name->val.p, name->val.len) - : std::string("")); -} - -} // namespace MbedTLSPKI -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509crl.hpp b/Sources/OpenVPN3/openvpn/mbedtls/pki/x509crl.hpp deleted file mode 100644 index c8b9ee5..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/pki/x509crl.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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/>. - -// Wrap a mbed TLS x509_crl object - -#ifndef OPENVPN_MBEDTLS_PKI_X509CRL_H -#define OPENVPN_MBEDTLS_PKI_X509CRL_H - -#include <string> -#include <sstream> -#include <cstring> - -#include <mbedtls/x509_crl.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -namespace openvpn { - namespace MbedTLSPKI { - - class X509CRL : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<X509CRL> Ptr; - - X509CRL() : chain(nullptr) {} - - X509CRL(const std::string& crl_txt) - : chain(nullptr) - { - try { - parse(crl_txt); - } - catch (...) - { - dealloc(); - throw; - } - } - - void parse(const std::string& crl_txt) - { - alloc(); - - // crl_txt.length() is increased by 1 as it does not include the NULL-terminator - // which mbedtls_x509_crl_parse() expects to see. - const int status = mbedtls_x509_crl_parse(chain, - (const unsigned char *)crl_txt.c_str(), - crl_txt.length() + 1); - if (status < 0) - { - throw MbedTLSException("error parsing CRL", status); - } - - pem_chain = crl_txt; - } - - std::string extract() const - { - return std::string(pem_chain); - } - - mbedtls_x509_crl* get() const - { - return chain; - } - - ~X509CRL() - { - dealloc(); - } - - private: - void alloc() - { - if (!chain) - { - chain = new mbedtls_x509_crl; - std::memset(chain, 0, sizeof(mbedtls_x509_crl)); - } - } - - void dealloc() - { - if (chain) - { - mbedtls_x509_crl_free(chain); - delete chain; - chain = nullptr; - } - } - - mbedtls_x509_crl *chain; - std::string pem_chain; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/ssl/sslctx.hpp b/Sources/OpenVPN3/openvpn/mbedtls/ssl/sslctx.hpp deleted file mode 100644 index 3a1ca41..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/ssl/sslctx.hpp +++ /dev/null @@ -1,1564 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS 2.3 SSL API as defined in <mbedtls/ssl.h> -// so that it can be used as the SSL layer by the OpenVPN core. - -#ifndef OPENVPN_MBEDTLS_SSL_SSLCTX_H -#define OPENVPN_MBEDTLS_SSL_SSLCTX_H - -#include <vector> -#include <string> -#include <sstream> -#include <cstring> -#include <memory> - -#include <mbedtls/ssl.h> -#include <mbedtls/oid.h> -#include <mbedtls/sha1.h> -#include <mbedtls/debug.h> -#include <mbedtls/asn1.h> -#include <mbedtls/version.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/binprefix.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/frame/memq_stream.hpp> -#include <openvpn/pki/cclist.hpp> -#include <openvpn/pki/pkcs1.hpp> -#include <openvpn/ssl/sslconsts.hpp> -#include <openvpn/ssl/sslapi.hpp> -#include <openvpn/ssl/ssllog.hpp> -#include <openvpn/ssl/verify_x509_name.hpp> -#include <openvpn/ssl/iana_ciphers.hpp> - -#include <openvpn/mbedtls/pki/x509cert.hpp> -#include <openvpn/mbedtls/pki/x509certinfo.hpp> -#include <openvpn/mbedtls/pki/x509crl.hpp> -#include <openvpn/mbedtls/pki/dh.hpp> -#include <openvpn/mbedtls/pki/pkctx.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -// An SSL Context is essentially a configuration that can be used -// to generate an arbitrary number of actual SSL connections objects. - -// MbedTLSContext is an SSL Context implementation that uses the -// mbed TLS library as a backend. - -namespace openvpn { - - namespace mbedtls_ctx_private { - namespace { - /* - * This is a modified list from mbed TLS ssl_ciphersuites.c. - * We removed some SHA1 methods near the top of the list to - * avoid Chrome warnings about "obsolete cryptography". - * We also removed ECDSA, CCM, PSK, and CAMELLIA algs. - */ - const int ciphersuites[] = // CONST GLOBAL - { - /* Selected AES-256 ephemeral suites */ - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - - /* Selected AES-128 ephemeral suites */ - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - - /* Selected remaining >= 128-bit ephemeral suites */ - MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - - MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - - /* Selected AES-256 suites */ - MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - - /* Selected AES-128 suites */ - MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - - /* Selected remaining >= 128-bit suites */ - MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - - MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - - 0 - }; - - /* - * X509 cert profiles. - */ - -#ifdef OPENVPN_USE_TLS_MD5 - // This profile includes the broken MD5 alrogithm. - // We are going to ship support for this algorithm for a limited - // amount of time to allow our users to switch to something else - const mbedtls_x509_crt_profile crt_profile_insecure = // CONST GLOBAL - { - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_MD5 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 1024, /* Minimum size for RSA keys */ - }; -#endif - - const mbedtls_x509_crt_profile crt_profile_legacy = // CONST GLOBAL - { - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 1024, /* Minimum size for RSA keys */ - }; - - const mbedtls_x509_crt_profile crt_profile_preferred = // CONST GLOBAL - { - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 2048, /* Minimum size for RSA keys */ - }; - } - } - - // Represents an SSL configuration that can be used - // to instantiate actual SSL sessions. - class MbedTLSContext : public SSLFactoryAPI - { - public: - typedef RCPtr<MbedTLSContext> Ptr; - - enum { - MAX_CIPHERTEXT_IN = 64 // maximum number of queued input ciphertext packets - }; - - // The data needed to construct a MbedTLSContext. - class Config : public SSLConfigAPI - { - friend class MbedTLSContext; - - public: - typedef RCPtr<Config> Ptr; - - Config() : external_pki(nullptr), - ssl_debug_level(0), - flags(0), - ns_cert_type(NSCert::NONE), - tls_version_min(TLSVersion::UNDEF), - tls_cert_profile(TLSCertProfile::UNDEF), - local_cert_enabled(true) {} - - virtual SSLFactoryAPI::Ptr new_factory() - { - return SSLFactoryAPI::Ptr(new MbedTLSContext(this)); - } - - virtual void set_mode(const Mode& mode_arg) - { - mode = mode_arg; - } - - virtual const Mode& get_mode() const - { - return mode; - } - - // if this callback is defined, no private key needs to be loaded - virtual void set_external_pki_callback(ExternalPKIBase* external_pki_arg) - { - external_pki = external_pki_arg; - } - - virtual void set_session_ticket_handler(TLSSessionTicketBase* session_ticket_handler_arg) - { - // fixme -- this method should be implemented for server-side TLS session resumption tickets - throw MbedTLSException("set_session_ticket_handler not implemented"); - } - - virtual void set_client_session_tickets(const bool v) - { - // fixme -- this method should be implemented for client-side TLS session resumption tickets - throw MbedTLSException("set_client_session_tickets not implemented"); - } - - virtual void set_sni_handler(SNI::HandlerBase* sni_handler) - { - // fixme -- this method should be implemented on the server-side for SNI - throw MbedTLSException("set_sni_handler not implemented"); - } - - virtual void set_sni_name(const std::string& sni_name_arg) - { - // fixme -- this method should be implemented on the client-side for SNI - throw MbedTLSException("set_sni_name not implemented"); - } - - virtual void set_private_key_password(const std::string& pwd) - { - priv_key_pwd = pwd; - } - - virtual void load_ca(const std::string& ca_txt, bool strict) - { - MbedTLSPKI::X509Cert::Ptr c = new MbedTLSPKI::X509Cert(); - c->parse(ca_txt, "ca", strict); - ca_chain = c; - } - - virtual void load_crl(const std::string& crl_txt) - { - MbedTLSPKI::X509CRL::Ptr c = new MbedTLSPKI::X509CRL(); - c->parse(crl_txt); - crl_chain = c; - } - - virtual void load_cert(const std::string& cert_txt) - { - MbedTLSPKI::X509Cert::Ptr c = new MbedTLSPKI::X509Cert(); - c->parse(cert_txt, "cert", true); - crt_chain = c; - } - - virtual void load_cert(const std::string& cert_txt, const std::string& extra_certs_txt) - { - MbedTLSPKI::X509Cert::Ptr c = new MbedTLSPKI::X509Cert(); - c->parse(cert_txt, "cert", true); - if (!extra_certs_txt.empty()) - c->parse(extra_certs_txt, "extra-certs", true); - crt_chain = c; - } - - virtual void load_private_key(const std::string& key_txt) - { - MbedTLSPKI::PKContext::Ptr p = new MbedTLSPKI::PKContext(); - p->parse(key_txt, "config", priv_key_pwd); - priv_key = p; - } - - virtual void load_dh(const std::string& dh_txt) - { - MbedTLSPKI::DH::Ptr mydh = new MbedTLSPKI::DH(); - mydh->parse(dh_txt, "server-config"); - dh = mydh; - } - - virtual std::string extract_ca() const - { - if (!ca_chain) - return std::string(); - return ca_chain->extract(); - } - - virtual std::string extract_crl() const - { - if (!crl_chain) - return std::string(); - return crl_chain->extract(); - } - - virtual std::string extract_cert() const - { - if (!crt_chain) - return std::string(); - return crt_chain->extract(); - } - - virtual std::vector<std::string> extract_extra_certs() const - { - if (!crt_chain) - return std::vector<std::string>(); - return crt_chain->extract_extra_certs(); - } - - virtual std::string extract_private_key() const - { - if (!priv_key) - return std::string(); - return priv_key->extract(); - } - - virtual std::string extract_dh() const - { - if (!dh) - return std::string(); - return dh->extract(); - } - - virtual PKType::Type private_key_type() const - { - if (!priv_key) - return PKType::PK_NONE; - return priv_key->key_type(); - } - - virtual size_t private_key_length() const - { - if (!priv_key) - return 0; - return priv_key->key_length(); - } - - virtual void set_frame(const Frame::Ptr& frame_arg) - { - frame = frame_arg; - } - - virtual void set_debug_level(const int debug_level) - { - ssl_debug_level = debug_level; - } - - virtual void set_flags(const unsigned int flags_arg) - { - flags = flags_arg; - } - - virtual void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) - { - ns_cert_type = ns_cert_type_arg; - } - - virtual void set_remote_cert_tls(const KUParse::TLSWebType wt) - { - KUParse::remote_cert_tls(wt, ku, eku); - } - - virtual void set_tls_remote(const std::string& tls_remote_arg) - { - tls_remote = tls_remote_arg; - } - - virtual void set_tls_version_min(const TLSVersion::Type tvm) - { - tls_version_min = tvm; - } - - virtual void set_tls_version_min_override(const std::string& override) - { - TLSVersion::apply_override(tls_version_min, override); - } - - virtual void set_tls_cert_profile(const TLSCertProfile::Type type) - { - tls_cert_profile = type; - } - - virtual void set_tls_cipher_list(const std::string& override) - { - if(!override.empty()) - tls_cipher_list = override; - } - - virtual void set_tls_ciphersuite_list(const std::string& override) - { - // mbed TLS does not have TLS 1.3 support - } - - virtual void set_tls_groups(const std::string& groups) - { - if (!groups.empty()) - tls_groups = groups; - } - - virtual void set_tls_cert_profile_override(const std::string& override) - { - TLSCertProfile::apply_override(tls_cert_profile, override); - } - - virtual void set_local_cert_enabled(const bool v) - { - local_cert_enabled = v; - } - - virtual void set_x509_track(X509Track::ConfigSet x509_track_config_arg) - { - x509_track_config = std::move(x509_track_config_arg); - } - - virtual void set_rng(const RandomAPI::Ptr& rng_arg) - { - rng_arg->assert_crypto(); - rng = rng_arg; - } - - virtual std::string validate_cert(const std::string& cert_txt) const - { - MbedTLSPKI::X509Cert::Ptr cert = new MbedTLSPKI::X509Cert(cert_txt, "validation cert", true); - return cert_txt; // fixme -- implement parse/re-render semantics - } - - virtual std::string validate_cert_list(const std::string& certs_txt) const - { - MbedTLSPKI::X509Cert::Ptr cert = new MbedTLSPKI::X509Cert(certs_txt, "validation cert list", true); - return certs_txt; // fixme -- implement parse/re-render semantics - } - - virtual std::string validate_private_key(const std::string& key_txt) const - { - MbedTLSPKI::PKContext::Ptr pkey = new MbedTLSPKI::PKContext(key_txt, "validation", ""); - return key_txt; // fixme -- implement parse/re-render semantics - } - - virtual std::string validate_dh(const std::string& dh_txt) const - { - MbedTLSPKI::DH::Ptr dh = new MbedTLSPKI::DH(dh_txt, "validation"); - return dh_txt; // fixme -- implement parse/re-render semantics - } - - virtual std::string validate_crl(const std::string& crl_txt) const - { - MbedTLSPKI::X509CRL::Ptr crl = new MbedTLSPKI::X509CRL(crl_txt); - return crl_txt; // fixme -- implement parse/re-render semantics - } - - virtual void load(const OptionList& opt, const unsigned int lflags) - { - // client/server - if (lflags & LF_PARSE_MODE) - mode = opt.exists("client") ? Mode(Mode::CLIENT) : Mode(Mode::SERVER); - - // possibly disable peer cert verification - if ((lflags & LF_ALLOW_CLIENT_CERT_NOT_REQUIRED) - && opt.exists("client-cert-not-required")) - flags |= SSLConst::NO_VERIFY_PEER; - - // sni - { - const std::string name = opt.get_optional("sni", 1, 256); - if (!name.empty()) - set_sni_name(name); - } - - // ca - { - std::string ca_txt = opt.cat("ca"); - if (lflags & LF_RELAY_MODE) - ca_txt += opt.cat("relay-extra-ca"); - load_ca(ca_txt, true); - } - - // CRL - { - const std::string crl_txt = opt.cat("crl-verify"); - if (!crl_txt.empty()) - load_crl(crl_txt); - } - - // local cert/key - if (local_cert_enabled) - { - // cert/extra-certs - { - const std::string& cert_txt = opt.get("cert", 1, Option::MULTILINE); - const std::string ec_txt = opt.cat("extra-certs"); - load_cert(cert_txt, ec_txt); - } - - // private key - if (!external_pki) - { - const std::string& key_txt = opt.get("key", 1, Option::MULTILINE); - load_private_key(key_txt); - } - } - - // DH - if (mode.is_server()) - { - const std::string& dh_txt = opt.get("dh", 1, Option::MULTILINE); - load_dh(dh_txt); - } - - // relay mode - std::string relay_prefix; - if (lflags & LF_RELAY_MODE) - relay_prefix = "relay-"; - - // parse ns-cert-type - ns_cert_type = NSCert::ns_cert_type(opt, relay_prefix); - - // parse remote-cert-x options - KUParse::remote_cert_tls(opt, relay_prefix, ku, eku); - KUParse::remote_cert_ku(opt, relay_prefix, ku); - KUParse::remote_cert_eku(opt, relay_prefix, eku); - - // parse tls-remote - tls_remote = opt.get_optional(relay_prefix + "tls-remote", 1, 256); - - // parse verify-x509-name - verify_x509_name.init(opt, relay_prefix); - - // parse tls-version-min option - { -# if defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_3) - const TLSVersion::Type maxver = TLSVersion::V1_2; -# elif defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_2) - const TLSVersion::Type maxver = TLSVersion::V1_1; -# else - const TLSVersion::Type maxver = TLSVersion::V1_0; -# endif - tls_version_min = TLSVersion::parse_tls_version_min(opt, relay_prefix, maxver); - } - - // parse tls-cert-profile - tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(opt, relay_prefix); - - // Overrides for tls cipher suites - if (opt.exists("tls-cipher")) - tls_cipher_list = opt.get_optional("tls-cipher", 1, 256); - - if (opt.exists("tls-groups")) - tls_groups = opt.get_optional("tls-groups", 1, 256); - - // unsupported cert verification options - { - } - } - -#ifdef OPENVPN_JSON_INTERNAL - virtual SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const - { - throw MbedTLSException("json_override not implemented"); - } -#endif - - bool is_server() const - { - return mode.is_server(); - } - - private: - const mbedtls_x509_crt_profile *select_crt_profile() const - { - switch (TLSCertProfile::default_if_undef(tls_cert_profile)) - { -#ifdef OPENVPN_USE_TLS_MD5 - case TLSCertProfile::INSECURE: - return &mbedtls_ctx_private::crt_profile_insecure; -#endif - case TLSCertProfile::LEGACY: - return &mbedtls_ctx_private::crt_profile_legacy; - case TLSCertProfile::PREFERRED: - return &mbedtls_ctx_private::crt_profile_preferred; - case TLSCertProfile::SUITEB: - return &mbedtls_x509_crt_profile_suiteb; - default: - throw MbedTLSException("select_crt_profile: unknown cert profile"); - } - } - - Mode mode; - - protected: - MbedTLSPKI::X509Cert::Ptr crt_chain; // local cert chain (including client cert + extra certs) - MbedTLSPKI::X509Cert::Ptr ca_chain; // CA chain for remote verification - - private: - MbedTLSPKI::X509CRL::Ptr crl_chain; // CRL chain for remote verification - MbedTLSPKI::PKContext::Ptr priv_key; // private key - std::string priv_key_pwd; // private key password - MbedTLSPKI::DH::Ptr dh; // diffie-hellman parameters (only needed in server mode) - ExternalPKIBase* external_pki; - Frame::Ptr frame; - int ssl_debug_level; - unsigned int flags; // defined in sslconsts.hpp - NSCert::Type ns_cert_type; - std::vector<unsigned int> ku; // if defined, peer cert X509 key usage must match one of these values - std::string eku; // if defined, peer cert X509 extended key usage must match this OID/string - std::string tls_remote; - VerifyX509Name verify_x509_name; // --verify-x509-name feature - TLSVersion::Type tls_version_min; // minimum TLS version that we will negotiate - TLSCertProfile::Type tls_cert_profile; - std::string tls_cipher_list; - std::string tls_groups; - X509Track::ConfigSet x509_track_config; - bool local_cert_enabled; - RandomAPI::Ptr rng; // random data source - }; - - // Represents an actual SSL session. - // Normally instantiated by MbedTLSContext::ssl(). - class SSL : public SSLAPI - { - // read/write callback errors - enum { - // assumes that mbed TLS user-defined errors may start at -0x8000 - CT_WOULD_BLOCK = -0x8000, - CT_INTERNAL_ERROR = -0x8001 - }; - - friend class MbedTLSContext; - - public: - typedef RCPtr<SSL> Ptr; - - virtual void start_handshake() override - { - mbedtls_ssl_handshake(ssl); - } - - virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) override - { - const int status = mbedtls_ssl_write(ssl, (const unsigned char*)data, size); - if (status < 0) - { - if (status == CT_WOULD_BLOCK) - return SSLConst::SHOULD_RETRY; - else if (status == CT_INTERNAL_ERROR) - throw MbedTLSException("SSL write: internal error"); - else - throw MbedTLSException("SSL write error", status); - } - else - return status; - } - - virtual ssize_t read_cleartext(void *data, const size_t capacity) override - { - if (!overflow) - { - const int status = mbedtls_ssl_read(ssl, (unsigned char*)data, capacity); - if (status < 0) - { - if (status == CT_WOULD_BLOCK) - return SSLConst::SHOULD_RETRY; - else if (status == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) - return SSLConst::PEER_CLOSE_NOTIFY; - else if (status == CT_INTERNAL_ERROR) - throw MbedTLSException("SSL read: internal error"); - else - throw MbedTLSException("SSL read error", status); - } - else - return status; - } - else - throw ssl_ciphertext_in_overflow(); - } - - virtual bool read_cleartext_ready() const override - { - return !ct_in.empty() || mbedtls_ssl_get_bytes_avail(ssl); - } - - virtual void write_ciphertext(const BufferPtr& buf) override - { - if (ct_in.size() < MAX_CIPHERTEXT_IN) - ct_in.write_buf(buf); - else - overflow = true; - } - - virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) override - { - if (ct_in.size() < MAX_CIPHERTEXT_IN) - ct_in.write(data, size); - else - overflow = true; - } - - virtual bool read_ciphertext_ready() const override - { - return !ct_out.empty(); - } - - virtual BufferPtr read_ciphertext() override - { - return ct_out.read_buf(); - } - - virtual std::string ssl_handshake_details() const override - { - if (ssl) - { - const char *ver = mbedtls_ssl_get_version(ssl); - const char *cs = mbedtls_ssl_get_ciphersuite(ssl); - if (ver && cs) - return ver + std::string("/") + cs; - } - return ""; - } - - virtual bool export_keying_material(const std::string& label, unsigned char*, size_t size) override - { - return false; // not implemented in our mbed TLS implementation - } - - virtual bool did_full_handshake() override - { - return false; // fixme -- not implemented - } - - virtual const AuthCert::Ptr& auth_cert() const override - { - return authcert; - } - - virtual void mark_no_cache() override - { - // fixme -- this method should be implemented for client-side TLS session resumption tickets - } - - virtual ~SSL() - { - erase(); - } - - protected: - SSL(MbedTLSContext* ctx, const char *hostname) - { - clear(); - try { - const Config& c = *ctx->config; - int endpoint, status; - - // set pointer back to parent - parent = ctx; - - // set client/server mode - if (c.mode.is_server()) - { - endpoint = MBEDTLS_SSL_IS_SERVER; - authcert.reset(new AuthCert()); - } - else if (c.mode.is_client()) - endpoint = MBEDTLS_SSL_IS_CLIENT; - else - throw MbedTLSException("unknown client/server mode"); - - // init SSL configuration object - sslconf = new mbedtls_ssl_config; - mbedtls_ssl_config_init(sslconf); - mbedtls_ssl_config_defaults(sslconf, endpoint, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT); - - // init X509 cert profile - mbedtls_ssl_conf_cert_profile(sslconf, c.select_crt_profile()); - - // init SSL object - ssl = new mbedtls_ssl_context; - mbedtls_ssl_init(ssl); - - // set minimum TLS version - int major; - int minor; - switch (c.tls_version_min) - { - case TLSVersion::V1_0: - default: - major = MBEDTLS_SSL_MAJOR_VERSION_3; - minor = MBEDTLS_SSL_MINOR_VERSION_1; - break; -#if defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_2) - case TLSVersion::V1_1: - major = MBEDTLS_SSL_MAJOR_VERSION_3; - minor = MBEDTLS_SSL_MINOR_VERSION_2; - break; -#endif -#if defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_3) - case TLSVersion::V1_2: - major = MBEDTLS_SSL_MAJOR_VERSION_3; - minor = MBEDTLS_SSL_MINOR_VERSION_3; - break; -#endif - } - mbedtls_ssl_conf_min_version(sslconf, major, minor); -#if 0 // force TLS 1.0 as maximum version (debugging only, disable in production) - mbedtls_ssl_conf_max_version(sslconf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); -#endif - - { - // peer must present a valid certificate unless SSLConst::NO_VERIFY_PEER. - // Presenting a valid certificate can be made optional by specifying - // SSL:Const::PEER_CERT_OPTIONAL - - int authmode; - - if (c.flags & SSLConst::NO_VERIFY_PEER) - authmode = MBEDTLS_SSL_VERIFY_NONE; - else if (c.flags & SSLConst::PEER_CERT_OPTIONAL) - throw MbedTLSException("Optional peer verification not supported"); - else - authmode = MBEDTLS_SSL_VERIFY_REQUIRED; - - mbedtls_ssl_conf_authmode(sslconf, authmode); - } - - // set verify callback - mbedtls_ssl_conf_verify(sslconf, c.mode.is_server() ? verify_callback_server : verify_callback_client, this); - - // Notes on SSL resume/renegotiation: - // SSL resume on server side is controlled by ssl_set_session_cache. - // SSL renegotiation is disabled here via MBEDTLS_SSL_RENEGOTIATION_DISABLED - // and ssl_legacy_renegotiation defaults to - // MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION. To enable session tickets, - // MBEDTLS_SSL_SESSION_TICKETS (compile flag) must be defined - // in mbed TLS config.h. - mbedtls_ssl_conf_renegotiation(sslconf, MBEDTLS_SSL_RENEGOTIATION_DISABLED); - - if (!c.tls_cipher_list.empty()) - { - set_mbedtls_cipherlist(c.tls_cipher_list); - } - else - { - mbedtls_ssl_conf_ciphersuites(sslconf, mbedtls_ctx_private::ciphersuites); - } - - if (!c.tls_groups.empty()) - { - set_mbedtls_groups(c.tls_groups); - } - // set CA chain - if (c.ca_chain) - mbedtls_ssl_conf_ca_chain(sslconf, - c.ca_chain->get(), - c.crl_chain ? c.crl_chain->get() : nullptr); - else if (!(c.flags & SSLConst::NO_VERIFY_PEER)) - throw MbedTLSException("CA chain not defined"); - - // Set hostname for SNI or if a CA chain is configured - // In pre-mbedtls-2.x the hostname for the CA chain was set in ssl_set_ca_chain(). - // From mbedtls-2.x, the hostname must be set via mbedtls_ssl_set_hostname() - // https://tls.mbed.org/kb/how-to/upgrade-2.0 - if (hostname && ((c.flags & SSLConst::ENABLE_CLIENT_SNI) || c.ca_chain)) - { - if (mbedtls_ssl_set_hostname(ssl, hostname)) - throw MbedTLSException("mbedtls_ssl_set_hostname failed"); - } - - // client cert+key - if (c.local_cert_enabled) - { - if (c.external_pki) - { - // set our own certificate, supporting chain (i.e. extra-certs), and external private key - if (c.crt_chain) - { - if (mbedtls_pk_get_type(&c.crt_chain.get()->get()->pk) == MBEDTLS_PK_RSA) - { - epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len); - mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get()); - } - else - { - throw MbedTLSException("cert has unsupported type for external pki support"); - } - } - else - throw MbedTLSException("cert is undefined"); - } - else - { - // set our own certificate, supporting chain (i.e. extra-certs), and private key - if (c.crt_chain && c.priv_key) - mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), c.priv_key->get()); - else - throw MbedTLSException("cert and/or private key is undefined"); - } - } - - // set DH - if (c.dh) - { - status = mbedtls_ssl_conf_dh_param_ctx(sslconf, c.dh->get()); - if (status < 0) - throw MbedTLSException("error in ssl_set_dh_param_ctx", status); - } - - // configure ciphertext buffers - ct_in.set_frame(c.frame); - ct_out.set_frame(c.frame); - - // set BIO - mbedtls_ssl_set_bio(ssl, this, ct_write_func, ct_read_func, NULL); - - // set RNG - if (c.rng) - { - rng = c.rng; - mbedtls_ssl_conf_rng(sslconf, rng_callback, this); - } - else - throw MbedTLSException("RNG not defined"); - - // set debug callback - if (c.ssl_debug_level) - mbedtls_ssl_conf_dbg(sslconf, dbg_callback, ctx); - - /* OpenVPN 2.x disables cbc_record_splitting by default, therefore - * we have to do the same here to keep compatibility. - * If not disabled, this setting will trigger bad behaviours on - * TLS1.0 and possibly on other setups */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - mbedtls_ssl_conf_cbc_record_splitting(sslconf, - MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - - // Apply the configuration to the SSL connection object - if (mbedtls_ssl_setup(ssl, sslconf) < 0) - throw MbedTLSException("mbedtls_ssl_setup failed"); - } - catch (...) - { - erase(); - throw; - } - } - - mbedtls_ssl_config *sslconf; // SSL configuration parameters for SSL connection object - std::unique_ptr<int[]> allowed_ciphers; //! Hold the array that is used for setting the allowed ciphers - // must have the same lifetime as sslconf - std::unique_ptr<mbedtls_ecp_group_id[]> groups; //! Hold the array that is used for setting the curves - - - MbedTLSContext *parent; - - private: - - void set_mbedtls_cipherlist(const std::string& cipher_list) - { - auto num_ciphers = std::count(cipher_list.begin(), cipher_list.end(), ':') + 1; - - allowed_ciphers.reset(new int[num_ciphers+1]); - - std::stringstream cipher_list_ss(cipher_list); - std::string ciphersuite; - - int i=0; - while(std::getline(cipher_list_ss, ciphersuite, ':')) - { - const tls_cipher_name_pair* pair = tls_get_cipher_name_pair(ciphersuite); - - if (pair && pair->iana_name != ciphersuite) - { - OPENVPN_LOG_SSL("mbed TLS -- Deprecated cipher suite name '" - << pair->openssl_name << "' please use IANA name ' " - << pair->iana_name << "'"); - } - - auto cipher_id = mbedtls_ssl_get_ciphersuite_id(ciphersuite.c_str()); - if (cipher_id != 0) - { - allowed_ciphers[i] = cipher_id; - i++; - } - else - { - /* OpenVPN 2.x ignores silently ignores unknown cipher suites with - * mbed TLS. We warn about them in OpenVPN 3.x */ - OPENVPN_LOG_SSL("mbed TLS -- warning ignoring unknown cipher suite '" - << ciphersuite << "' in tls-cipher"); - } - } - - // Last element needs to be null - allowed_ciphers[i] = 0; - mbedtls_ssl_conf_ciphersuites(sslconf, allowed_ciphers.get()); - } - - void set_mbedtls_groups(const std::string& tls_groups) - { - auto num_groups = std::count(tls_groups.begin(), tls_groups.end(), ':') + 1; - - /* add extra space for sentinel at the end */ - groups.reset(new mbedtls_ecp_group_id[num_groups + 1]); - - std::stringstream groups_ss(tls_groups); - std::string group; - - int i=0; - while(std::getline(groups_ss, group, ':')) - { - const mbedtls_ecp_curve_info *ci = - mbedtls_ecp_curve_info_from_name(group.c_str()); - - if (ci) - { - groups[i] = ci->grp_id; - i++; - } - else - { - OPENVPN_LOG_SSL("mbed TLS -- warning ignoring unknown group '" - << group << "' in tls-groups"); - } - } - - groups[i] = MBEDTLS_ECP_DP_NONE; - mbedtls_ssl_conf_curves(sslconf, groups.get()); - } - - // cleartext read callback - static int ct_read_func(void *arg, unsigned char *data, size_t length) - { - try { - SSL *self = (SSL *)arg; - const size_t actual = self->ct_in.read(data, length); - return actual > 0 ? (int)actual : CT_WOULD_BLOCK; - } - catch (...) - { - return CT_INTERNAL_ERROR; - } - } - - // cleartext write callback - static int ct_write_func(void *arg, const unsigned char *data, size_t length) - { - try { - SSL *self = (SSL *)arg; - self->ct_out.write(data, length); - return (int)length; - } - catch (...) - { - return CT_INTERNAL_ERROR; - } - } - - // RNG callback -- return random data to mbed TLS - static int rng_callback(void *arg, unsigned char *data, size_t len) - { - SSL *self = (SSL *)arg; - return self->rng->rand_bytes_noexcept(data, len) ? 0 : -1; // using -1 as a general-purpose mbed TLS error code - } - - static void dbg_callback(void *arg, int level, const char *filename, int linenum, const char *text) - { - MbedTLSContext *self = (MbedTLSContext *)arg; - if (level <= self->config->ssl_debug_level) - OPENVPN_LOG_NTNL("mbed TLS[" << filename << ":" << linenum << " "<< level << "]: " << text); - } - - void clear() - { - parent = nullptr; - ssl = nullptr; - sslconf = nullptr; - overflow = false; - allowed_ciphers = nullptr; - } - - void erase() - { - if (ssl) - { - mbedtls_ssl_free(ssl); - mbedtls_ssl_config_free(sslconf); - delete ssl; - delete sslconf; - } - clear(); - } - - mbedtls_ssl_context *ssl; // underlying SSL connection object - MbedTLSPKI::PKContext epki_ctx; // external PKI context - RandomAPI::Ptr rng; // random data source - MemQStream ct_in; // write ciphertext to here - MemQStream ct_out; // read ciphertext from here - AuthCert::Ptr authcert; - bool overflow; - }; - - /////// start of main class implementation - - // create a new SSL instance - virtual SSLAPI::Ptr ssl() - { - return SSL::Ptr(new SSL(this, nullptr)); - } - - // like ssl() above but verify hostname against cert CommonName and/or SubjectAltName - virtual SSLAPI::Ptr ssl(const std::string* hostname, const std::string* cache_key) - { - return SSL::Ptr(new SSL(this, hostname ? hostname->c_str() : nullptr)); - } - - virtual const Mode& mode() const - { - return config->mode; - } - - virtual ~MbedTLSContext() - { - erase(); - } - - constexpr static bool support_key_material_export() - { - /* mbed TLS 2.18+ can support RFC5705 but the API is painful to use */ - return false; - } - protected: - MbedTLSContext(Config* config_arg) - : config(config_arg) - { - if (config->local_cert_enabled) - { - // Verify that cert is defined - if (!config->crt_chain) - throw MbedTLSException("cert is undefined"); - } - } - - private: - size_t key_len() const - { - return mbedtls_pk_get_bitlen(&config->crt_chain->get()->pk) / 8; - } - - // ns-cert-type verification - - bool ns_cert_type_defined() const - { - return config->ns_cert_type != NSCert::NONE; - } - - bool verify_ns_cert_type(const mbedtls_x509_crt *cert) const - { - if (config->ns_cert_type == NSCert::SERVER) - return bool(cert->ns_cert_type & MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER); - else if (config->ns_cert_type == NSCert::CLIENT) - return bool(cert->ns_cert_type & MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT); - else - return false; - } - - // remote-cert-ku verification - - bool x509_cert_ku_defined() const - { - return config->ku.size() > 0; - } - - bool verify_x509_cert_ku(const mbedtls_x509_crt *cert) - { - if (cert->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) - { - const unsigned int ku = cert->key_usage; - for (std::vector<unsigned int>::const_iterator i = config->ku.begin(); i != config->ku.end(); ++i) - { - if (ku == *i) - return true; - } - } - return false; - } - - // remote-cert-eku verification - - bool x509_cert_eku_defined() const - { - return !config->eku.empty(); - } - - bool verify_x509_cert_eku(mbedtls_x509_crt *cert) - { - if (cert->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) - { - mbedtls_x509_sequence *oid_seq = &cert->ext_key_usage; - while (oid_seq != nullptr) - { - mbedtls_x509_buf *oid = &oid_seq->buf; - - // first compare against description - { - const char *oid_str; - const int status = mbedtls_oid_get_extended_key_usage(oid, &oid_str); - if (status >= 0 && config->eku == oid_str) - return true; - } - - // next compare against OID numeric string - { - char oid_num_str[256]; - const int status = mbedtls_oid_get_numeric_string(oid_num_str, sizeof(oid_num_str), oid); - if (status >= 0 && config->eku == oid_num_str) - return true; - } - oid_seq = oid_seq->next; - } - } - return false; - } - - static std::string status_string(const mbedtls_x509_crt *cert, const int depth, const uint32_t *flags) - { - std::ostringstream os; - std::string status_str = "OK"; - if (*flags) - status_str = "FAIL -- " + MbedTLSException::mbedtls_verify_flags_errtext(*flags); - os << "VERIFY " - << status_str - << " : depth=" << depth - << std::endl << cert_info(cert); - return os.str(); - } - - protected: - static int verify_callback_client(void *arg, mbedtls_x509_crt *cert, int depth, uint32_t *flags) - { - MbedTLSContext::SSL *ssl = (MbedTLSContext::SSL *)arg; - MbedTLSContext *self = ssl->parent; - bool fail = false; - - // log status - if (self->config->flags & SSLConst::LOG_VERIFY_STATUS) - OPENVPN_LOG_SSL(status_string(cert, depth, flags)); - - // notify if connection is happening with an insecurely signed cert - if (cert->sig_md == MBEDTLS_MD_MD5) - { - ssl->tls_warnings |= SSLAPI::TLS_WARN_SIG_MD5; - } - - if (cert->sig_md == MBEDTLS_MD_SHA1) - { - ssl->tls_warnings |= SSLAPI::TLS_WARN_SIG_SHA1; - } - - // leaf-cert verification - if (depth == 0) - { - // verify ns-cert-type - if (self->ns_cert_type_defined() && !self->verify_ns_cert_type(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad ns-cert-type in leaf certificate"); - fail = true; - } - - // verify X509 key usage - if (self->x509_cert_ku_defined() && !self->verify_x509_cert_ku(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 key usage in leaf certificate"); - fail = true; - } - - // verify X509 extended key usage - if (self->x509_cert_eku_defined() && !self->verify_x509_cert_eku(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 extended key usage in leaf certificate"); - fail = true; - } - - // verify tls-remote - if (!self->config->tls_remote.empty()) - { - const std::string subject = TLSRemote::sanitize_x509_name(MbedTLSPKI::x509_get_subject(cert)); - const std::string common_name = TLSRemote::sanitize_common_name(MbedTLSPKI::x509_get_common_name(cert)); - TLSRemote::log(self->config->tls_remote, subject, common_name); - if (!TLSRemote::test(self->config->tls_remote, subject, common_name)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- tls-remote match failed"); - fail = true; - } - } - - // verify-x509-name - const VerifyX509Name& verify_x509 = self->config->verify_x509_name; - if (verify_x509.get_mode() != VerifyX509Name::VERIFY_X509_NONE) - { - bool res = false; - switch (verify_x509.get_mode()) - { - case VerifyX509Name::VERIFY_X509_SUBJECT_DN: - res = verify_x509.verify(MbedTLSPKI::x509_get_subject(cert, true)); - break; - - case VerifyX509Name::VERIFY_X509_SUBJECT_RDN: - case VerifyX509Name::VERIFY_X509_SUBJECT_RDN_PREFIX: - res = verify_x509.verify(MbedTLSPKI::x509_get_common_name(cert)); - break; - - default: - break; - } - if (!res) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- verify-x509-name failed"); - fail = true; - } - - } - } - - if (fail) - *flags |= MBEDTLS_X509_BADCERT_OTHER; - return 0; - } - - static int verify_callback_server(void *arg, mbedtls_x509_crt *cert, int depth, uint32_t *flags) - { - MbedTLSContext::SSL *ssl = (MbedTLSContext::SSL *)arg; - MbedTLSContext *self = ssl->parent; - bool fail = false; - - if (depth == 1) // issuer cert - { - // save the issuer cert fingerprint - if (ssl->authcert) - { - const int SHA_DIGEST_LEN = 20; - static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LEN, "size inconsistency"); -#if MBEDTLS_VERSION_NUMBER < 0x02070000 - // mbed TLS 2.7.0 and newer deprecates mbedtls_sha1() - // in favour of mbedtls_sha1_ret(). - - // We support for older mbed TLS versions - // to be able to build on Debian 9 and Ubuntu 16. - mbedtls_sha1(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp); -#else - if(mbedtls_sha1_ret(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- SHA1 calculation failed."); - fail = true; - } -#endif - } - } - else if (depth == 0) // leaf-cert - { - // verify ns-cert-type - if (self->ns_cert_type_defined() && !self->verify_ns_cert_type(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad ns-cert-type in leaf certificate"); - fail = true; - } - - // verify X509 key usage - if (self->x509_cert_ku_defined() && !self->verify_x509_cert_ku(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 key usage in leaf certificate"); - fail = true; - } - - // verify X509 extended key usage - if (self->x509_cert_eku_defined() && !self->verify_x509_cert_eku(cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 extended key usage in leaf certificate"); - fail = true; - } - - if (ssl->authcert) - { - // save the Common Name - ssl->authcert->cn = MbedTLSPKI::x509_get_common_name(cert); - - // save the leaf cert serial number - const mbedtls_x509_buf *s = &cert->serial; - if (s->len > 0 && s->len <= sizeof(ssl->authcert->sn)) - ssl->authcert->sn = bin_prefix_floor<decltype(ssl->authcert->sn)>(s->p, s->len, -1); - else - ssl->authcert->sn = -1; - } - } - - if (fail) - *flags |= MBEDTLS_X509_BADCERT_OTHER; - return 0; - } - - Config::Ptr config; - - private: - static std::string cert_info(const mbedtls_x509_crt *cert, const char *prefix = nullptr) - { - const size_t buf_size = 4096; - std::unique_ptr<char[]> buf(new char[buf_size]); - const int size = mbedtls_x509_crt_info(buf.get(), buf_size, prefix ? prefix : "", cert); - if (size >= 0) - return std::string(buf.get()); - else - return "error rendering cert"; - } - - void erase() - { - } - - static int epki_decrypt(void *arg, - int mode, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) - { - OPENVPN_LOG_SSL("MbedTLSContext::epki_decrypt is unimplemented, mode=" << mode - << " output_max_len=" << output_max_len); - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - static int epki_sign(void *arg, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig) - { - MbedTLSContext *self = (MbedTLSContext *) arg; - try { - if (mode == MBEDTLS_RSA_PRIVATE) - { - size_t digest_prefix_len = 0; - const unsigned char *digest_prefix = nullptr; - - /* get signature type */ - switch (md_alg) { - case MBEDTLS_MD_NONE: - break; - case MBEDTLS_MD_MD2: - digest_prefix = PKCS1::DigestPrefix::MD2; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::MD2); - break; - case MBEDTLS_MD_MD5: - digest_prefix = PKCS1::DigestPrefix::MD5; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::MD5); - break; - case MBEDTLS_MD_SHA1: - digest_prefix = PKCS1::DigestPrefix::SHA1; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::SHA1); - break; - case MBEDTLS_MD_SHA256: - digest_prefix = PKCS1::DigestPrefix::SHA256; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::SHA256); - break; - case MBEDTLS_MD_SHA384: - digest_prefix = PKCS1::DigestPrefix::SHA384; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::SHA384); - break; - case MBEDTLS_MD_SHA512: - digest_prefix = PKCS1::DigestPrefix::SHA512; - digest_prefix_len = sizeof(PKCS1::DigestPrefix::SHA512); - break; - default: - OPENVPN_LOG_SSL("MbedTLSContext::epki_sign unrecognized hash_id, mode=" << mode - << " md_alg=" << md_alg << " hashlen=" << hashlen); - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - /* concatenate digest prefix with hash */ - BufferAllocated from_buf(digest_prefix_len + hashlen, 0); - if (digest_prefix_len) - from_buf.write(digest_prefix, digest_prefix_len); - from_buf.write(hash, hashlen); - - /* convert from_buf to base64 */ - const std::string from_b64 = base64->encode(from_buf); - - /* get signature */ - std::string sig_b64; - const bool status = self->config->external_pki->sign(from_b64, sig_b64, "RSA_PKCS1_PADDING"); - if (!status) - throw ssl_external_pki("MbedTLS: could not obtain signature"); - - /* decode base64 signature to binary */ - const size_t len = self->key_len(); - Buffer sigbuf(sig, len, false); - base64->decode(sigbuf, sig_b64); - - /* verify length */ - if (sigbuf.size() != len) - throw ssl_external_pki("mbed TLS: incorrect signature length"); - - /* success */ - return 0; - } - else - { - OPENVPN_LOG_SSL("MbedTLSContext::epki_sign unrecognized parameters, mode=" << mode - << " md_alg=" << md_alg << " hashlen=" << hashlen); - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - } - catch (const std::exception& e) - { - OPENVPN_LOG("MbedTLSContext::epki_sign exception: " << e.what()); - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - } - - static size_t epki_key_len(void *arg) - { - MbedTLSContext *self = (MbedTLSContext *) arg; - return self->key_len(); - } - }; - - inline const std::string get_ssl_library_version() - { - unsigned int ver = mbedtls_version_get_number(); - std::string version = "mbed TLS " + - std::to_string((ver>>24)&0xff) + - "." + std::to_string((ver>>16)&0xff) + - "." + std::to_string((ver>>8)&0xff); - - return version; - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/util/error.hpp b/Sources/OpenVPN3/openvpn/mbedtls/util/error.hpp deleted file mode 100644 index 5ba76a8..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/util/error.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// 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-2020 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/>. - -// mbed TLS exception class that allows a error code -// to be represented. - -#ifndef OPENVPN_MBEDTLS_UTIL_ERROR_H -#define OPENVPN_MBEDTLS_UTIL_ERROR_H - -#include <string> - -#include <mbedtls/ssl.h> -#include <mbedtls/pem.h> -#include <mbedtls/error.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/error/excode.hpp> - -namespace openvpn { - - // string exception class - class MbedTLSException : public ExceptionCode - { - public: - MbedTLSException() - { - errnum = 0; - errtxt = "mbed TLS"; - } - - explicit MbedTLSException(const std::string& error_text) - { - errnum = 0; - errtxt = "mbed TLS: " + error_text; - } - - explicit MbedTLSException(const std::string& error_text, const Error::Type code, const bool fatal) - : ExceptionCode(code, fatal) - { - errnum = 0; - errtxt = "mbed TLS: " + error_text; - } - - explicit MbedTLSException(const std::string& error_text, const int mbedtls_errnum) - { - errnum = mbedtls_errnum; - errtxt = "mbed TLS: " + error_text + " : " + mbedtls_errtext(mbedtls_errnum); - - // cite forum URL for mbed TLS invalid date - // TODO: Get a better URL for such knowledge information record - if (mbedtls_errnum == MBEDTLS_ERR_X509_INVALID_DATE) - errtxt += ", please see https://forums.openvpn.net/viewtopic.php?f=36&t=21873 for more info"; - - // for certain mbed TLS errors, translate them to an OpenVPN error code, - // so they can be propagated up to the higher levels (such as UI level) - switch (errnum) { - case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: - set_code(Error::CERT_VERIFY_FAIL, true); - break; - case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: - case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: - set_code(Error::PEM_PASSWORD_FAIL, true); - break; - case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION: - set_code(Error::TLS_VERSION_MIN, true); - break; - } - } - - virtual const char* what() const throw() { return errtxt.c_str(); } - std::string what_str() const { return errtxt; } - - int get_errnum() const { return errnum; } - - virtual ~MbedTLSException() throw() {} - - static std::string mbedtls_errtext(int errnum) - { - char buf[256]; - mbedtls_strerror(errnum, buf, sizeof(buf)); - return buf; - } - - static std::string mbedtls_verify_flags_errtext(const uint32_t flags) - { - // get string rendition of flags - const size_t BUF_SIZE = 1024; - std::unique_ptr<char[]> buf(new char[BUF_SIZE]); - buf[0] = '\0'; - mbedtls_x509_crt_verify_info(buf.get(), BUF_SIZE, "", flags); - - // postprocess string - std::string ret; - ret.reserve(std::strlen(buf.get()) + 64); - bool newline = false; - for (size_t i = 0; i < BUF_SIZE; ++i) - { - const char c = buf[i]; - if (c == '\0') - break; - else if (c == '\n') - newline = true; - else - { - if (newline) - { - ret += ", "; - newline = false; - } - ret += c; - } - } - return ret; - } - - private: - std::string errtxt; - int errnum; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/util/pem.hpp b/Sources/OpenVPN3/openvpn/mbedtls/util/pem.hpp deleted file mode 100644 index f663fff..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/util/pem.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// 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 = { }; - size_t out_len = 0; - - int ret = mbedtls_pem_read_buffer(&ctx, header.c_str(), footer.c_str(), - (unsigned char *)src, nullptr, 0, - &out_len); - if (ret == 0) - dst.init(ctx.buf, ctx.buflen, BufferAllocated::DESTRUCT_ZERO); - - mbedtls_pem_free(&ctx); - - return (ret == 0); - } - }; -}; - -#endif /* OPENVPN_MBEDTLS_UTIL_PEM_H */ diff --git a/Sources/OpenVPN3/openvpn/mbedtls/util/pkcs1.hpp b/Sources/OpenVPN3/openvpn/mbedtls/util/pkcs1.hpp deleted file mode 100644 index 6cf5d7e..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/util/pkcs1.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// 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-2020 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_MBEDTLS_UTIL_PKCS1_H -#define OPENVPN_MBEDTLS_UTIL_PKCS1_H - -#include <openvpn/pki/pkcs1.hpp> - -namespace openvpn { - namespace PKCS1 { - namespace DigestPrefix { - class MbedTLSParse : public Parse<mbedtls_md_type_t> - { - public: - MbedTLSParse() - : Parse(MBEDTLS_MD_NONE, - MBEDTLS_MD_MD2, - MBEDTLS_MD_MD5, - MBEDTLS_MD_SHA1, - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_SHA512) - { - } - - static const char *to_string(const mbedtls_md_type_t t) - { - switch (t) - { - case MBEDTLS_MD_NONE: - return "MBEDTLS_MD_NONE"; - case MBEDTLS_MD_MD2: - return "MBEDTLS_MD_MD2"; - case MBEDTLS_MD_MD5: - return "MBEDTLS_MD_MD5"; - case MBEDTLS_MD_SHA1: - return "MBEDTLS_MD_SHA1"; - case MBEDTLS_MD_SHA256: - return "MBEDTLS_MD_SHA256"; - case MBEDTLS_MD_SHA384: - return "MBEDTLS_MD_SHA384"; - case MBEDTLS_MD_SHA512: - return "MBEDTLS_MD_SHA512"; - default: - return "MBEDTLS_MD_???"; - } - } - }; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/util/rand.hpp b/Sources/OpenVPN3/openvpn/mbedtls/util/rand.hpp deleted file mode 100644 index 27cbdcc..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/util/rand.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// 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-2020 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/>. - -// Wrap the mbed TLS Cryptographic Random API defined in <mbedtls/ctr_drbg.h> -// so that it can be used as the primary source of cryptographic entropy by -// the OpenVPN core. - -#ifndef OPENVPN_MBEDTLS_UTIL_RAND_H -#define OPENVPN_MBEDTLS_UTIL_RAND_H - -#include <mbedtls/entropy.h> -#include <mbedtls/entropy_poll.h> -#include <mbedtls/ctr_drbg.h> - -#include <openvpn/random/randapi.hpp> -#include <openvpn/mbedtls/util/error.hpp> - -namespace openvpn { - - class MbedTLSRandom : public RandomAPI - { - public: - OPENVPN_EXCEPTION(rand_error_mbedtls); - - typedef RCPtr<MbedTLSRandom> Ptr; - - MbedTLSRandom(const bool prng, RandomAPI::Ptr entropy_source) - : entropy(std::move(entropy_source)) - { - // Init RNG context - mbedtls_ctr_drbg_init(&ctx); - - // Seed RNG - const int errnum = mbedtls_ctr_drbg_seed(&ctx, entropy_poll, entropy.get(), nullptr, 0); - if (errnum < 0) - throw MbedTLSException("mbedtls_ctr_drbg_seed", errnum); - - // If prng is set, configure for higher performance - // by reseeding less frequently. - if (prng) - mbedtls_ctr_drbg_set_reseed_interval(&ctx, 1000000); - } - - MbedTLSRandom(const bool prng) - : MbedTLSRandom(prng, RandomAPI::Ptr()) { } - - virtual ~MbedTLSRandom() - { - // Free RNG context - mbedtls_ctr_drbg_free(&ctx); - } - - // Random algorithm name - virtual std::string name() const - { - const std::string n = "mbedTLS-CTR_DRBG"; - if (entropy) - return n + '+' + entropy->name(); - else - return n; - } - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const - { - return true; - } - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) - { - const int errnum = rndbytes(buf, size); - if (errnum < 0) - throw MbedTLSException("mbedtls_ctr_drbg_random", errnum); - } - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) - { - return rndbytes(buf, size) >= 0; - } - - private: - int rndbytes(unsigned char *buf, size_t size) - { - return mbedtls_ctr_drbg_random(&ctx, buf, size); - } - - static int entropy_poll(void *arg, unsigned char *output, size_t len) - { - if (arg) - { - RandomAPI* entropy = (RandomAPI*)arg; - if (entropy->rand_bytes_noexcept(output, len)) - return 0; - else - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; - } - else - { -#ifndef OPENVPN_DISABLE_MBEDTLS_PLATFORM_ENTROPY_POLL - size_t olen; - return mbedtls_platform_entropy_poll(nullptr, output, len, &olen); -#else - return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; -#endif - } - } - - mbedtls_ctr_drbg_context ctx; - RandomAPI::Ptr entropy; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/mbedtls/util/selftest.hpp b/Sources/OpenVPN3/openvpn/mbedtls/util/selftest.hpp deleted file mode 100644 index 7eeaf6e..0000000 --- a/Sources/OpenVPN3/openvpn/mbedtls/util/selftest.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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-2020 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/>. - -// Call various mbed TLS self-test functions - -#ifndef OPENVPN_MBEDTLS_UTIL_SELFTEST_H -#define OPENVPN_MBEDTLS_UTIL_SELFTEST_H - -#include <sstream> - -#include <mbedtls/bignum.h> -#include <mbedtls/config.h> -#include <mbedtls/cipher.h> -#include <mbedtls/aes.h> -#include <mbedtls/sha1.h> -#include <mbedtls/sha256.h> -#include <mbedtls/sha512.h> - -namespace openvpn { - inline std::string crypto_self_test_mbedtls() - { - std::ostringstream os; -#ifdef MBEDTLS_SELF_TEST - const int verbose = 1; - os << "mbed TLS self test (tests return 0 if successful):" << std::endl; - os << " mbedlts_aes_self_test status=" << mbedtls_aes_self_test(verbose) << std::endl; - os << " mbedtls_sha1_self_test status=" << mbedtls_sha1_self_test(verbose) << std::endl; - os << " mbedtls_sha256_self_test status=" << mbedtls_sha256_self_test(verbose) << std::endl; - os << " mbedtls_sha512_self_test status=" << mbedtls_sha512_self_test(verbose) << std::endl; - os << " mbedtls_mpi_self_test status=" << mbedtls_mpi_self_test(verbose) << std::endl; -#else - os << "mbed TLS self test: not compiled" << std::endl; -#endif - return os.str(); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/netconf/enumiface.hpp b/Sources/OpenVPN3/openvpn/netconf/enumiface.hpp deleted file mode 100644 index 629f093..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/enumiface.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// 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-2020 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/>. - -// Enumerate iOS network interfaces - -#ifndef OPENVPN_NETCONF_ENUMIFACE_H -#define OPENVPN_NETCONF_ENUMIFACE_H - -#include <sys/types.h> -#include <sys/socket.h> -#include <ifaddrs.h> - -#ifdef OPENVPN_PLATFORM_IPHONE -#include <openvpn/netconf/ios/net-route.h> -#else -#include <net/route.h> -#endif - -#include <cstring> -#include <string> -#include <sstream> -#include <memory> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - class EnumIface - { - public: - OPENVPN_EXCEPTION(enum_iface_error); - - EnumIface() - : ifinfo(alloc_if_addrs(), free_if_addrs) - { - } - - std::string to_string() const - { - std::ostringstream os; - os << "INTERFACES:" << std::endl; - for (const ifaddrs* i = ifinfo.get(); i->ifa_next; i = i->ifa_next) - render(i, os); - return os.str(); - } - - bool iface_up(const char *iface) const - { - for (const ifaddrs* i = ifinfo.get(); i->ifa_next; i = i->ifa_next) - { - if (!std::strcmp(iface, i->ifa_name) - && (i->ifa_flags & RTF_UP) - && IP::Addr::sockaddr_defined(i->ifa_addr)) - return true; - } - return false; - } - - protected: - static void render(const ifaddrs* i, std::ostream& os) - { - try { - os << i->ifa_name; - os << ' ' << render_flags(i->ifa_flags); - if (i->ifa_addr) - { - const IP::Addr a = IP::Addr::from_sockaddr(i->ifa_addr); - if (a.defined()) - os << ' ' << a; - } - if (i->ifa_netmask) - { - const IP::Addr nm = IP::Addr::from_sockaddr(i->ifa_netmask); - if (nm.defined()) - { - try { - unsigned int pl = nm.prefix_len(); - os << '/' << pl; - } - catch (const std::exception&) - { - } - } - } - if (i->ifa_dstaddr) - { - const IP::Addr dst = IP::Addr::from_sockaddr(i->ifa_dstaddr); - if (dst.defined()) - os << " (" << dst << ')'; - } - } - catch (const std::exception&) - { - os << " ERROR"; - } - os << std::endl; - } - - static std::string render_flags(const u_int flags) - { - struct flag_info { - u_int flag; - char c; - }; - static const struct flag_info flag_info[] = { -# ifdef RTF_UP - { RTF_UP, 'U' }, // Route usable -# endif -# ifdef RTF_GATEWAY - { RTF_GATEWAY, 'G' }, // Destination requires forwarding by intermediary -# endif -# ifdef RTF_HOST - { RTF_HOST, 'H' }, // Host entry (net otherwise) -# endif -# ifdef RTF_REJECT - { RTF_REJECT, 'R' }, // Host or net unreachable -# endif -# ifdef RTF_DYNAMIC - { RTF_DYNAMIC, 'D' }, // Created dynamically (by redirect) -# endif -# ifdef RTF_MODIFIED - { RTF_MODIFIED, 'M' }, // Modified dynamically (by redirect) -# endif -# ifdef RTF_CLONING - { RTF_CLONING, 'C' }, // Generate new routes on use -# endif -# ifdef RTF_XRESOLVE - { RTF_XRESOLVE, 'X' }, // External daemon translates proto to link address -# endif -# ifdef RTF_LLINFO - { RTF_LLINFO, 'L' }, // Valid protocol to link address translation -# endif -# ifdef RTF_STATIC - { RTF_STATIC, 'S' }, // Manually added -# endif -# ifdef RTF_BLACKHOLE - { RTF_BLACKHOLE, 'B' }, // Just discard packets (during updates) -# endif -# ifdef RTF_PROTO2 - { RTF_PROTO2, '2' }, // Protocol specific routing flag #2 -# endif -# ifdef RTF_PROTO1 - { RTF_PROTO1, '1' }, // Protocol specific routing flag #1 -# endif -# ifdef RTF_PRCLONING - { RTF_PRCLONING, 'c' }, // Protocol-specified generate new routes on use -# endif -# ifdef RTF_WASCLONED - { RTF_WASCLONED, 'W' }, // Route was generated as a result of cloning -# endif -# ifdef RTF_PROTO3 - { RTF_PROTO3, '3' }, // Protocol specific routing flag #3 -# endif -# ifdef RTF_BROADCAST - { RTF_BROADCAST, 'b' }, // The route represents a broadcast address -# endif -# ifdef RTF_MULTICAST - { RTF_MULTICAST, 'm' }, // The route represents a multicast address -# endif -# ifdef RTF_IFSCOPE - { RTF_IFSCOPE, 'I' }, // Route is associated with an interface scope -# endif -# ifdef RTF_IFREF - { RTF_IFREF, 'i' }, // Route is holding a reference to the interface -# endif -# ifdef RTF_PROXY - { RTF_PROXY, 'Y' }, // Proxying; cloned routes will not be scoped -# endif -# ifdef RTF_ROUTER - { RTF_ROUTER, 'r' }, // Host is a default router -# endif - { 0, '\0' }, - }; - - std::string ret; - for (const struct flag_info *fi = flag_info; fi->flag; ++fi) - if (flags & fi->flag) - ret += fi->c; - return ret; - } - - static ifaddrs* alloc_if_addrs() - { - ifaddrs* ifa = nullptr; - ::getifaddrs(&ifa); - return ifa; - } - - static void free_if_addrs(ifaddrs* p) - { - // delete method for pointer returned by getifaddrs - freeifaddrs(p); - } - - std::unique_ptr<ifaddrs, decltype(&free_if_addrs)> ifinfo; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/netconf/hwaddr.hpp b/Sources/OpenVPN3/openvpn/netconf/hwaddr.hpp deleted file mode 100644 index dec8d4a..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/hwaddr.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// 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-2020 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/>. - -// Get the local MAC addr of the interface that owns the default route - -#ifndef OPENVPN_NETCONF_HWADDR_H -#define OPENVPN_NETCONF_HWADDR_H - -#include <string> - -#include <openvpn/common/platform.hpp> -#include <openvpn/addr/macaddr.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_PLATFORM_UWP) -#include <openvpn/tun/win/tunutil.hpp> -#elif defined(OPENVPN_PLATFORM_MAC) -#include <openvpn/tun/mac/gwv4.hpp> -#elif defined(TARGET_OS_IPHONE) -#include <UIKit/UIKit.h> -#endif - -namespace openvpn { - inline std::string get_hwaddr() - { -#if defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_PLATFORM_UWP) - const TunWin::Util::BestGateway dg; - if (dg.defined()) - { - const TunWin::Util::IPAdaptersInfo ai_list; - const IP_ADAPTER_INFO* ai = ai_list.adapter(dg.interface_index()); - if (ai) - { - const MACAddr mac(ai->Address); - return mac.to_string(); - } - } -#elif defined(OPENVPN_PLATFORM_MAC) - const MacGatewayInfoV4 gw; - if (gw.hwaddr_defined()) - { - const MACAddr& mac = gw.hwaddr(); - return mac.to_string(); - } -#elif defined(TARGET_OS_IPHONE) - // as reported at https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW34 - // we can't get the MAC address from iOS for privacy reasons, but we can - // use the UUID as unique identifier. It is unique among the App domain, - // meaning that a different app will get a different UUID from this call - const NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; - return std::string([uuid UTF8String]); -#endif - return std::string(); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/netconf/ios/net-route.h b/Sources/OpenVPN3/openvpn/netconf/ios/net-route.h deleted file mode 100644 index c51d895..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/ios/net-route.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2000-2013 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1980, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)route.h 8.3 (Berkeley) 4/19/94 - * $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $ - */ - -#ifndef _NET_ROUTE_H_ -#define _NET_ROUTE_H_ -#include <sys/appleapiopts.h> -#include <stdint.h> -#include <sys/types.h> -#include <sys/socket.h> - -/* - * These numbers are used by reliable protocols for determining - * retransmission behavior and are included in the routing structure. - */ -struct rt_metrics { - u_int32_t rmx_locks; /* Kernel leaves these values alone */ - u_int32_t rmx_mtu; /* MTU for this path */ - u_int32_t rmx_hopcount; /* max hops expected */ - int32_t rmx_expire; /* lifetime for route, e.g. redirect */ - u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */ - u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */ - u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */ - u_int32_t rmx_rtt; /* estimated round trip time */ - u_int32_t rmx_rttvar; /* estimated rtt variance */ - u_int32_t rmx_pksent; /* packets sent using this route */ - u_int32_t rmx_filler[4]; /* will be used for T/TCP later */ -}; - -/* - * rmx_rtt and rmx_rttvar are stored as microseconds; - */ -#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */ - - - -#define RTF_UP 0x1 /* route usable */ -#define RTF_GATEWAY 0x2 /* destination is a gateway */ -#define RTF_HOST 0x4 /* host entry (net otherwise) */ -#define RTF_REJECT 0x8 /* host or net unreachable */ -#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */ -#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */ -#define RTF_DONE 0x40 /* message confirmed */ -#define RTF_DELCLONE 0x80 /* delete cloned route */ -#define RTF_CLONING 0x100 /* generate new routes on use */ -#define RTF_XRESOLVE 0x200 /* external daemon resolves name */ -#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */ -#define RTF_STATIC 0x800 /* manually added */ -#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ -#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */ -#define RTF_PROTO2 0x4000 /* protocol specific routing flag */ -#define RTF_PROTO1 0x8000 /* protocol specific routing flag */ - -#define RTF_PRCLONING 0x10000 /* protocol requires cloning */ -#define RTF_WASCLONED 0x20000 /* route generated through cloning */ -#define RTF_PROTO3 0x40000 /* protocol specific routing flag */ - /* 0x80000 unused */ -#define RTF_PINNED 0x100000 /* future use */ -#define RTF_LOCAL 0x200000 /* route represents a local address */ -#define RTF_BROADCAST 0x400000 /* route represents a bcast address */ -#define RTF_MULTICAST 0x800000 /* route represents a mcast address */ -#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */ -#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */ -#define RTF_IFREF 0x4000000 /* route holds a ref to interface */ -#define RTF_PROXY 0x8000000 /* proxying, no interface scope */ -#define RTF_ROUTER 0x10000000 /* host is a router */ - /* 0x20000000 and up unassigned */ - -#define RTF_BITS \ - "\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \ - "\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \ - "\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \ - "\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \ - "\33IFREF\34PROXY\35ROUTER" - -/* - * Routing statistics. - */ -struct rtstat { - short rts_badredirect; /* bogus redirect calls */ - short rts_dynamic; /* routes created by redirects */ - short rts_newgateway; /* routes modified by redirects */ - short rts_unreach; /* lookups which failed */ - short rts_wildcard; /* lookups satisfied by a wildcard */ -}; - -/* - * Structures for routing messages. - */ -struct rt_msghdr { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - pid_t rtm_pid; /* identify sender */ - int rtm_seq; /* for sender to identify action */ - int rtm_errno; /* why failed */ - int rtm_use; /* from rtentry */ - u_int32_t rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ -}; - -struct rt_msghdr2 { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - int32_t rtm_refcnt; /* reference count */ - int rtm_parentflags; /* flags of the parent route */ - int rtm_reserved; /* reserved field set to 0 */ - int rtm_use; /* from rtentry */ - u_int32_t rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ -}; - - -#define RTM_VERSION 5 /* Up the ante and ignore older versions */ - -/* - * Message types. - */ -#define RTM_ADD 0x1 /* Add Route */ -#define RTM_DELETE 0x2 /* Delete Route */ -#define RTM_CHANGE 0x3 /* Change Metrics or flags */ -#define RTM_GET 0x4 /* Report Metrics */ -#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */ -#define RTM_REDIRECT 0x6 /* Told to use different route */ -#define RTM_MISS 0x7 /* Lookup failed on this address */ -#define RTM_LOCK 0x8 /* fix specified metrics */ -#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */ -#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */ -#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ -#define RTM_NEWADDR 0xc /* address being added to iface */ -#define RTM_DELADDR 0xd /* address being removed from iface */ -#define RTM_IFINFO 0xe /* iface going up/down etc. */ -#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */ -#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */ -#define RTM_IFINFO2 0x12 /* */ -#define RTM_NEWMADDR2 0x13 /* */ -#define RTM_GET2 0x14 /* */ - -/* - * Bitmask values for rtm_inits and rmx_locks. - */ -#define RTV_MTU 0x1 /* init or lock _mtu */ -#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ -#define RTV_EXPIRE 0x4 /* init or lock _expire */ -#define RTV_RPIPE 0x8 /* init or lock _recvpipe */ -#define RTV_SPIPE 0x10 /* init or lock _sendpipe */ -#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ -#define RTV_RTT 0x40 /* init or lock _rtt */ -#define RTV_RTTVAR 0x80 /* init or lock _rttvar */ - -/* - * Bitmask values for rtm_addrs. - */ -#define RTA_DST 0x1 /* destination sockaddr present */ -#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ -#define RTA_NETMASK 0x4 /* netmask sockaddr present */ -#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */ -#define RTA_IFP 0x10 /* interface name sockaddr present */ -#define RTA_IFA 0x20 /* interface addr sockaddr present */ -#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ -#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ - -/* - * Index offsets for sockaddr array for alternate internal encoding. - */ -#define RTAX_DST 0 /* destination sockaddr present */ -#define RTAX_GATEWAY 1 /* gateway sockaddr present */ -#define RTAX_NETMASK 2 /* netmask sockaddr present */ -#define RTAX_GENMASK 3 /* cloning mask sockaddr present */ -#define RTAX_IFP 4 /* interface name sockaddr present */ -#define RTAX_IFA 5 /* interface addr sockaddr present */ -#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ -#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ -#define RTAX_MAX 8 /* size of array to allocate */ - -struct rt_addrinfo { - int rti_addrs; - struct sockaddr *rti_info[RTAX_MAX]; -}; - - -#endif /* _NET_ROUTE_H_ */ diff --git a/Sources/OpenVPN3/openvpn/netconf/linux/gw.hpp b/Sources/OpenVPN3/openvpn/netconf/linux/gw.hpp deleted file mode 100644 index fdd4ff8..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/linux/gw.hpp +++ /dev/null @@ -1,211 +0,0 @@ -// 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-2020 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 - -#ifndef OPENVPN_NETCONF_LINUX_GW_H -#define OPENVPN_NETCONF_LINUX_GW_H - -#include <string> -#include <limits> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/addr/route.hpp> - -namespace openvpn { - class LinuxGW - { - public: - OPENVPN_EXCEPTION(linux_gw_error); - - LinuxGW(const std::string& ip_route_show_txt, const bool ignore_errors) - { - int best_metric = std::numeric_limits<int>::max(); - - SplitLines sl(ip_route_show_txt); - while (sl()) - { - const std::string& line = sl.line_ref(); - - try { - // parse an output line generated by "ip [-6] route show" - const std::vector<std::string> v = Split::by_space<std::vector<std::string>, NullLex, SpaceMatch, Split::NullLimit>(line); - - // blank line? - if (v.empty()) - continue; - - // only interested in default routes - if (v[0] != "default") - continue; - - // parse out route information - enum RouteInfo { - INITIAL, - VIA, - DEV, - METRIC, - }; - - std::string d; - IP::Addr a; - int m = std::numeric_limits<int>::max(); - - RouteInfo ri = INITIAL; - for (const auto &term : v) - { - switch (ri) - { - case INITIAL: - if (term == "via") - ri = VIA; - else if (term == "dev") - ri = DEV; - else if (term == "metric") - ri = METRIC; - else - ri = INITIAL; - break; - case VIA: - a = IP::Addr(term, "via"); - ri = INITIAL; - break; - case DEV: - d = validate_dev(term); - ri = INITIAL; - break; - case METRIC: - m = parse_number_throw<int>(term, "bad metric"); - ri = INITIAL; - break; - } - } - - // best metric? - if (m < best_metric || best_metric == std::numeric_limits<int>::max()) - { - best_metric = m; - dev_ = d; - addr_ = a; - } - } - catch (const std::exception& e) - { - if (!ignore_errors) - OPENVPN_THROW(linux_gw_error, "error parsing line: " << line << " : " << e.what()); - } - } - } - - static std::string ip_route_show(const bool ipv6) - { - RedirectPipe::InOut pipe; - Argv argv; - argv.emplace_back("/sbin/ip"); - if (ipv6) - argv.emplace_back("-6"); - argv.emplace_back("route"); - argv.emplace_back("show"); - const int status = system_cmd(argv[0], argv, nullptr, pipe, 0, nullptr); - if (status != 0) - OPENVPN_THROW(linux_gw_error, "command returned error status " << status << " : " << argv.to_string()); - return pipe.out; - } - - 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: - std::string validate_dev(const std::string& dev) - { - if (dev.empty()) - OPENVPN_THROW_EXCEPTION("dev is empty"); - return dev; - } - - std::string dev_; - IP::Addr addr_; - }; - - struct LinuxGW46 - { - LinuxGW46(const bool ignore_errors) - : v4(LinuxGW::ip_route_show(false), ignore_errors), - v6(LinuxGW::ip_route_show(true), ignore_errors) - { - } - - 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 LinuxGW::linux_gw_error("cannot determine gateway interface"); - } - - LinuxGW v4; - LinuxGW v6; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/netconf/linux/gwnetlink.hpp b/Sources/OpenVPN3/openvpn/netconf/linux/gwnetlink.hpp deleted file mode 100644 index 8bc71b0..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/linux/gwnetlink.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// 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-2020 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); - - /** - * Provides gateway which is used to reach given address - * - * @param addr address which we want to reach - * @param iface_to_ignore this allows to exclude certain interface - * from discovered gateways. Used when we want to exclude VPN interface - * when there is active VPN connection with redirected default gateway - * - * @param ipv6 true if address is IPv6 - */ - LinuxGWNetlink(const std::string& addr, const std::string& iface_to_ignore, bool ipv6) - { - try - { - if (ipv6) - { - IPv6::Addr addr6; - - if (TunNetlink::SITNL::net_route_best_gw(IP::Route6::from_string(addr), - addr6, dev_, iface_to_ignore) < 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::from_string(addr), - addr4, dev_, iface_to_ignore) < 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_; - }; - - /** - * Provides IPv4/6 gateway which is used to reach given address - * - * @param iface_to_ignore this allows to exclude certain interface - * from discovered gateways. Used when we want to exclude VPN interface - * when there is active VPN connection with redirected default gateway - * @param addr address which we want to reach - */ - struct LinuxGW46Netlink - { - LinuxGW46Netlink(const std::string& iface_to_ignore, const std::string& addr = "") - : v4(addr.empty() ? IPv4::Addr::from_zero().to_string() : addr, iface_to_ignore, false), - v6(addr.empty() ? IPv6::Addr::from_zero().to_string() : addr, iface_to_ignore, true) - { - } - - std::string to_string() const - { - std::string ret = "["; - if (v4.defined()) - { - ret += "4:"; - ret += v4.to_string(); - } - if (v6.defined()) - { - if (v4.defined()) - ret += ' '; - ret += "6:"; - ret += v6.to_string(); - } - ret += "]"; - return ret; - } - - std::string dev() const - { - if (v4.defined()) - return v4.dev(); - else if (v6.defined()) - return v6.dev(); - else - throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface"); - } - - LinuxGWNetlink v4; - LinuxGWNetlink v6; - }; -} diff --git a/Sources/OpenVPN3/openvpn/netconf/linux/route.hpp b/Sources/OpenVPN3/openvpn/netconf/linux/route.hpp deleted file mode 100644 index 3705cfe..0000000 --- a/Sources/OpenVPN3/openvpn/netconf/linux/route.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// 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-2020 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/>. - -// Add routes on Linux using AF_NETLINK socket - -#ifndef OPENVPN_NETCONF_LINUX_ROUTE_H -#define OPENVPN_NETCONF_LINUX_ROUTE_H - -#include <cstring> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <linux/netlink.h> -#include <linux/rtnetlink.h> -#include <net/if.h> -#include <errno.h> - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/strerror.hpp> -#include <openvpn/addr/route.hpp> - -namespace openvpn { - - class LinuxRoute - { - public: - OPENVPN_EXCEPTION(linux_route_error); - - LinuxRoute() - { - fd.reset(::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)); - if (!fd.defined()) - throw linux_route_error("creating AF_NETLINK socket"); - - struct sockaddr_nl local; - ::memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_pad = 0; - local.nl_pid = 0; // only use getpid() if unique instantiation per process - local.nl_groups = 0; - if (::bind(fd(), (struct sockaddr*)&local, sizeof(local)) < 0) - throw linux_route_error("binding to AF_NETLINK socket"); - } - - void add_delete(const bool add, - const IP::Route& route, - const int if_index, - const int table=RT_TABLE_MAIN) - { - typedef struct { - struct nlmsghdr nlmsg_info; - struct rtmsg rtmsg_info; - char buffer[64]; // must be large enough to contain request - } netlink_req_t; - - struct rtattr *rtattr_ptr; - int rtmsg_len; - struct sockaddr_nl peer; - struct msghdr msg_info; - struct iovec iov_info; - netlink_req_t netlink_req; - - ::memset(&peer, 0, sizeof(peer)); - peer.nl_family = AF_NETLINK; - peer.nl_pad = 0; - peer.nl_pid = 0; - peer.nl_groups = 0; - - ::memset(&msg_info, 0, sizeof(msg_info)); - msg_info.msg_name = (void *) &peer; - msg_info.msg_namelen = sizeof(peer); - - ::memset(&netlink_req, 0, sizeof(netlink_req)); - - rtmsg_len = sizeof(struct rtmsg); - - // add destination addr - rtattr_ptr = (struct rtattr *) netlink_req.buffer; - rtattr_ptr->rta_type = RTA_DST; - rtattr_ptr->rta_len = sizeof(struct rtattr) + route.addr.size_bytes(); - route.addr.to_byte_string_variable(((unsigned char *)rtattr_ptr) + sizeof(struct rtattr)); - rtmsg_len += rtattr_ptr->rta_len; - - // add if_index - rtattr_ptr = (struct rtattr *) (((unsigned char *)rtattr_ptr) + rtattr_ptr->rta_len); - rtattr_ptr->rta_type = RTA_OIF; - rtattr_ptr->rta_len = sizeof(struct rtattr) + 4; - ::memcpy(((unsigned char *)rtattr_ptr) + sizeof(struct rtattr), &if_index, 4); - rtmsg_len += rtattr_ptr->rta_len; - - netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(rtmsg_len); - - if (add) - { - netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; - netlink_req.nlmsg_info.nlmsg_type = RTM_NEWROUTE; - } - else // delete - { - netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST; - netlink_req.nlmsg_info.nlmsg_type = RTM_DELROUTE; - } - - netlink_req.rtmsg_info.rtm_family = route.addr.family(); - netlink_req.rtmsg_info.rtm_table = table; - netlink_req.rtmsg_info.rtm_dst_len = route.prefix_len; // add prefix - - netlink_req.rtmsg_info.rtm_protocol = RTPROT_STATIC; - netlink_req.rtmsg_info.rtm_scope = RT_SCOPE_UNIVERSE; - netlink_req.rtmsg_info.rtm_type = RTN_UNICAST; - - iov_info.iov_base = (void *) &netlink_req.nlmsg_info; - iov_info.iov_len = netlink_req.nlmsg_info.nlmsg_len; - msg_info.msg_iov = &iov_info; - msg_info.msg_iovlen = 1; - - const ssize_t status = ::sendmsg(fd(), &msg_info, 0); - if (status < 0) - { - const int eno = errno; - OPENVPN_THROW(linux_route_error, "add_delete: sendmsg failed: " << strerror_str(eno)); - } - } - - static int if_index(const std::string& iface) - { - const unsigned int ret = ::if_nametoindex(iface.c_str()); - if (!ret) - OPENVPN_THROW(linux_route_error, "if_index: no such interface: " << iface); - return ret; - } - - private: - ScopedFD fd; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/omi/CMakeLists.txt b/Sources/OpenVPN3/openvpn/omi/CMakeLists.txt deleted file mode 100644 index 76fa4c5..0000000 --- a/Sources/OpenVPN3/openvpn/omi/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(omicli) -set(CMAKE_CXX_STANDARD 14) - -include(findcoredeps) - -add_executable(omicliagent openvpn.cpp) -add_core_dependencies(omicliagent) -add_json_library(omicliagent) -target_compile_definitions(omicliagent PRIVATE -DOPENVPN_COMMAND_AGENT -DOVPNAGENT_DISABLE_PATH_CHECK) - -add_executable(omicli openvpn.cpp) -add_core_dependencies(omicli) diff --git a/Sources/OpenVPN3/openvpn/omi/omi.hpp b/Sources/OpenVPN3/openvpn/omi/omi.hpp deleted file mode 100644 index 7a7d910..0000000 --- a/Sources/OpenVPN3/openvpn/omi/omi.hpp +++ /dev/null @@ -1,1069 +0,0 @@ -// 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-2020 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 <sstream> -#include <vector> -#include <deque> -#include <memory> -#include <utility> -#include <algorithm> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/time/timestr.hpp> -#include <openvpn/time/asiotimersafe.hpp> -#include <openvpn/asio/asiowork.hpp> - -// include acceptors for different protocols -#include <openvpn/acceptor/base.hpp> -#include <openvpn/acceptor/tcp.hpp> -#ifdef ASIO_HAS_LOCAL_SOCKETS -#include <openvpn/acceptor/unix.hpp> -#endif - -#if defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/win/logutil.hpp> -#else -#include <openvpn/common/redir.hpp> -#endif - -namespace openvpn { - class OMICore : public Acceptor::ListenerBase - { - public: - OPENVPN_EXCEPTION(omi_error); - - struct LogFn - { - LogFn(const OptionList& opt) - { - fn = opt.get_optional("log", 1, 256); - if (fn.empty()) - { - fn = opt.get_optional("log-append", 1, 256); - append = true; - } - errors_to_stderr = opt.exists("errors-to-stderr"); - } - - std::string fn; - bool append = false; - bool errors_to_stderr = false; - }; - - void stop() - { - if (stop_called) - return; - stop_called = true; - - asio_work.reset(); - - // close acceptor - if (acceptor) - acceptor->close(); - - // Call derived class stop method and close OMI socket, - // but if omi_stop() returns true, wait for content_out - // to be flushed to OMI socket before closing it. - if (!omi_stop() || content_out.empty()) - stop_omi_client(false, 250); - } - - protected: - struct Command - { - Option option; - std::vector<std::string> extra; - bool valid_utf8 = false; - - std::string to_string() const - { - std::ostringstream os; - os << option.render(Option::RENDER_BRACKET); - if (!valid_utf8) - os << " >>>!UTF8"; - os << '\n'; - for (auto &line : extra) - os << line << '\n'; - return os.str(); - } - }; - - class History - { - public: - History(const std::string& type_arg, - const size_t max_size_arg) - : type(type_arg), - max_size(max_size_arg) - { - } - - bool is_cmd(const Option& o) const - { - return o.get_optional(0, 0) == type; - } - - std::string process_cmd(const Option& o) - { - try { - const std::string arg1 = o.get(1, 16); - if (arg1 == "on") - { - const std::string arg2 = o.get_optional(2, 16); - real_time = true; - std::string ret = real_time_status(); - if (arg2 == "all") - ret += show(hist.size()); - else if (!arg2.empty()) - return error(); - return ret; - } - else if (arg1 == "all") - { - return show(hist.size()); - } - else if (arg1 == "off") - { - real_time = false; - return real_time_status(); - } - else - { - unsigned int n; - if (parse_number(arg1, n)) - return show(n); - else - return error(); - } - } - catch (const option_error&) - { - return error(); - } - catch (const std::exception& e) - { - return "ERROR: " + type + " processing error: " + e.what() + "\r\n"; - } - } - - std::string notify(const std::string& msg) - { - hist.push_front(msg); - while (hist.size() > max_size) - hist.pop_back(); - if (real_time) - return notify_prefix() + msg; - else - return std::string(); - } - - private: - std::string show(size_t n) const - { - std::string ret = ""; - n = std::min(n, hist.size()); - for (size_t i = 0; i < n; ++i) - ret += hist[n - i - 1]; - ret += "END\r\n"; - return ret; - } - - std::string notify_prefix() const - { - return ">" + string::to_upper_copy(type) + ":"; - } - - std::string real_time_status() const - { - std::string ret = "SUCCESS: real-time " + type + " notification set to "; - if (real_time) - ret += "ON"; - else - ret += "OFF"; - ret += "\r\n"; - return ret; - } - - std::string error() const - { - return "ERROR: " + type + " parameter must be 'on' or 'off' or some number n or 'all'\r\n"; - } - - std::string type; - size_t max_size; - bool real_time = false; - std::deque<std::string> hist; - }; - - OMICore(openvpn_io::io_context& io_context_arg) - : io_context(io_context_arg), - stop_timer(io_context_arg) - { - } - - void log_setup(const LogFn& log) - { - if (!log.fn.empty()) - { -#if defined(OPENVPN_PLATFORM_WIN) - log_handle = Win::LogUtil::create_file(log.fn, "", log.append); -#else - RedirectStd redir("", - log.fn, - log.append ? RedirectStd::FLAGS_APPEND : RedirectStd::FLAGS_OVERWRITE, - RedirectStd::MODE_ALL, - false); - redir.redirect(); -#endif - } - errors_to_stderr = log.errors_to_stderr; - } - - static std::string get_config(const OptionList& opt) - { - // get config file - const std::string config_fn = opt.get("config", 1, 256); - return read_config(config_fn); - } - - void start(const OptionList& opt) - { - const Option& o = opt.get("management"); - const std::string addr = o.get(1, 256); - const std::string port = o.get(2, 16); - const std::string password_file = o.get_optional(3, 256); - - if (password_file == "stdin") - { - password_defined = true; - std::cout << "Enter Management Password:"; - std::cin >> password; - } - - hold_flag = opt.exists("management-hold"); - - // management-queue-limit low_water high_water - { - const Option* o = opt.get_ptr("management-queue-limit"); - if (o) - { - const size_t low_water = o->get_num<size_t>(1, 0, 0, 1000000); - const size_t high_water = o->get_num<size_t>(2, 0, 0, 1000000); - content_out_throttle.reset(new BufferThrottle(low_water, high_water)); - } - } - - // management-client-user root - { - const Option* o = opt.get_ptr("management-client-user"); - if (o) - { - if (o->get(1, 64) == "root") - management_client_root = true; - else - throw Exception("only --management-client-user root supported"); - } - } - - if (opt.exists("management-client")) - { - if (port == "unix") - { - OPENVPN_LOG("OMI Connecting to " << addr << " [unix]"); - connect_unix(addr); - } - else - { - OPENVPN_LOG("OMI Connecting to [" << addr << "]:" << port << " [tcp]"); - connect_tcp(addr, port); - } - } - else - { - if (port == "unix") - { - OPENVPN_LOG("OMI Listening on " << addr << " [unix]"); - listen_unix(addr); - } - else - { - OPENVPN_LOG("OMI Listening on [" << addr << "]:" << port << " [tcp]"); - listen_tcp(addr, port); - } - } - - // don't exit Asio event loop until AsioWork object is deleted - asio_work.reset(new AsioWork(io_context)); - } - - void start_connection_if_not_hold() - { - if (!hold_flag) - omi_start_connection(); - } - - void send(BufferPtr buf) - { - if (!is_sock_open()) - return; - content_out.push_back(std::move(buf)); - if (content_out_throttle) - content_out_throttle->size_change(content_out.size()); - if (content_out.size() == 1) // send operation not currently active? - queue_send(); - } - - void send(const std::string& str) - { - if (!str.empty()) - send(buf_from_string(str)); - } - - bool send_ready() const - { - if (content_out_throttle) - return content_out_throttle->ready(); - else - return true; - } - - void async_done() - { - process_recv(); - } - - void log_full(const std::string& text) // logs to OMI buffer and log file - { - const time_t now = ::time(NULL); - const std::string textcrlf = string::unix2dos(text, true); - log_line(openvpn::to_string(now) + ",," + textcrlf); -#if defined(OPENVPN_PLATFORM_WIN) - if (log_handle.defined()) - Win::LogUtil::log(log_handle(), date_time(now) + ' ' + textcrlf); - else -#endif - std::cout << date_time(now) << ' ' << text << std::flush; - } - - void log_timestamp(const time_t timestamp, const std::string& text) // logs to OMI buffer only - { - const std::string textcrlf = string::unix2dos(text, true); - log_line(openvpn::to_string(timestamp) + ",," + textcrlf); - } - - void log_line(const std::string& line) // logs to OMI buffer only - { - if (!stop_called) - send(hist_log.notify(line)); - } - - void state_line(const std::string& line) - { - if (!stop_called) - send(hist_state.notify(line)); - } - - void echo_line(const std::string& line) - { - if (!stop_called) - send(hist_echo.notify(line)); - } - - bool is_errors_to_stderr() const - { - return errors_to_stderr; - } - - bool is_stopping() const - { - return stop_called; - } - - unsigned int get_bytecount() const - { - return bytecount; - } - - virtual bool omi_command_is_multiline(const std::string& arg0, const Option& option) = 0; - virtual bool omi_command_in(const std::string& arg0, const Command& cmd) = 0; - virtual void omi_start_connection() = 0; - virtual void omi_done(const bool eof) = 0; - virtual void omi_sigterm() = 0; - virtual bool omi_stop() = 0; - - virtual bool omi_is_sighup_implemented() - { - return false; - } - - virtual void omi_sighup() - { - } - - openvpn_io::io_context& io_context; - - private: - typedef RCPtr<OMICore> Ptr; - - class BufferThrottle - { - public: - BufferThrottle(const size_t low_water_arg, - const size_t high_water_arg) - : low_water(low_water_arg), - high_water(high_water_arg) - { - if (low_water > high_water) - throw Exception("bad management-queue-limit values"); - } - - void size_change(const size_t size) - { - if (ready_) - { - if (size > high_water) - ready_ = false; - } - else - { - if (size <= low_water) - ready_ = true; - } - } - - bool ready() const - { - return ready_; - } - - private: - const size_t low_water; - const size_t high_water; - volatile bool ready_ = true; - }; - - bool command_in(std::unique_ptr<Command> cmd) - { - try { - const std::string arg0 = cmd->option.get_optional(0, 64); - if (arg0.empty()) - return false; - if (!cmd->valid_utf8) - throw Exception("invalid UTF8"); - switch (arg0[0]) - { - case 'b': - { - if (arg0 == "bytecount") - { - process_bytecount_cmd(cmd->option); - return false; - } - break; - } - case 'e': - { - if (hist_echo.is_cmd(cmd->option)) - { - send(hist_echo.process_cmd(cmd->option)); - return false; - } - if (arg0 == "exit") - { - conditional_stop(true); - return false; - } - break; - } - case 'h': - { - if (is_hold_cmd(cmd->option)) - { - bool release = false; - send(hold_cmd(cmd->option, release)); - if (release) - hold_release(); - return false; - } - break; - } - case 'l': - { - if (hist_log.is_cmd(cmd->option)) - { - send(hist_log.process_cmd(cmd->option)); - return false; - } - break; - } - case 'q': - { - if (arg0 == "quit") - { - conditional_stop(true); - return false; - } - break; - } - case 's': - { - if (hist_state.is_cmd(cmd->option)) - { - send(hist_state.process_cmd(cmd->option)); - return false; - } - if (arg0 == "signal") - { - process_signal_cmd(cmd->option); - return false; - } - break; - } - } - return omi_command_in(arg0, *cmd); - } - catch (const std::exception& e) - { - std::string err_ref = "option"; - if (cmd) - err_ref = cmd->option.err_ref(); - send("ERROR: error processing " + err_ref + " : " + e.what() + "\r\n"); - } - return false; - } - - bool is_hold_cmd(const Option& o) const - { - return o.get_optional(0, 0) == "hold"; - } - - std::string hold_cmd(const Option& o, bool& release) - { - try { - const std::string arg1 = o.get_optional(1, 16); - if (arg1.empty()) - { - if (hold_flag) - return "SUCCESS: hold=1\r\n"; - else - return "SUCCESS: hold=0\r\n"; - } - else if (arg1 == "on") - { - hold_flag = true; - return "SUCCESS: hold flag set to ON\r\n"; - } - else if (arg1 == "off") - { - hold_flag = false; - return "SUCCESS: hold flag set to OFF\r\n"; - } - else if (arg1 == "release") - { - release = true; - return "SUCCESS: hold release succeeded\r\n"; - } - } - catch (const option_error&) - { - } - return "ERROR: bad hold command parameter\r\n"; - } - - void hold_cycle() - { - hold_wait = true; - if (hold_flag) - send(">HOLD:Waiting for hold release\r\n"); - else - hold_release(); - } - - void hold_release() - { - if (hold_wait) - { - hold_wait = false; - omi_start_connection(); - } - } - - void process_bytecount_cmd(const Option& o) - { - bytecount = o.get_num<decltype(bytecount)>(1, 0, 0, 86400); - send("SUCCESS: bytecount interval changed\r\n"); - } - - void process_signal_cmd(const Option& o) - { - const std::string type = o.get(1, 16); - if (type == "SIGTERM") - { - send("SUCCESS: signal SIGTERM thrown\r\n"); - omi_sigterm(); - } - else if (type == "SIGHUP" && omi_is_sighup_implemented()) - { - send("SUCCESS: signal SIGHUP thrown\r\n"); - omi_sighup(); - } - else - send("ERROR: signal not supported\r\n"); - } - - bool command_is_multiline(const Option& o) - { - const std::string arg0 = o.get_optional(0, 64); - if (arg0.empty()) - return false; - return omi_command_is_multiline(arg0, o); - } - - bool is_sock_open() const - { - return socket && socket->is_open(); - } - - void conditional_stop(const bool eof) - { - if (acceptor || stop_called) - stop_omi_client(eof, 250); - else - stop(); // if running in management-client mode, do a full stop - } - - void stop_omi_client(const bool eof, const unsigned int milliseconds) - { - stop_timer.expires_after(Time::Duration::milliseconds(milliseconds)); - stop_timer.async_wait([self=Ptr(this), eof](const openvpn_io::error_code& error) - { - if (!error) - self->stop_omi_client(eof); - }); - } - - void stop_omi_client(const bool eof) - { - stop_timer.cancel(); - const bool is_open = is_sock_open(); - if (is_open) - socket->close(); - content_out.clear(); - if (content_out_throttle) - content_out_throttle->size_change(content_out.size()); - in_partial.clear(); - if (is_open) - omi_done(eof); - } - - void send_title_message() - { - send(">INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info\r\n"); - } - - void send_password_prompt() - { - send("ENTER PASSWORD:"); - } - - void send_password_correct() - { - send("SUCCESS: password is correct"); - } - - bool process_password() - { - if (password_defined && !password_verified) - { - if (password == in_partial) - { - password_verified = true; - send_password_correct(); - send_title_message(); - hold_cycle(); - } - else - { - // wrong password, kick the client - stop_omi_client(false, 250); - } - return true; - } - - return false; - } - - bool process_in_line() // process incoming line in in_partial - { - bool ret = false; - const bool utf8 = Unicode::is_valid_utf8(in_partial); - string::trim_crlf(in_partial); - - if (process_password()) - return false; - - if (multiline) - { - if (!command) - throw omi_error("process_in_line: internal error"); - if (in_partial == "END") - { - ret = command_in(std::move(command)); - command.reset(); - multiline = false; - } - else - { - if (!utf8) - command->valid_utf8 = false; - command->extra.push_back(std::move(in_partial)); - } - } - else - { - command.reset(new Command); - command->option = OptionList::parse_option_from_line(in_partial, nullptr); - command->valid_utf8 = utf8; - multiline = command_is_multiline(command->option); - if (!multiline) - { - ret = command_in(std::move(command)); - command.reset(); - } - } - return ret; - } - - static std::string read_config(const std::string& fn) - { - if (fn == "stdin") - return read_stdin(); - else - return read_text_utf8(fn); - } - - void listen_tcp(const std::string& addr, const std::string& port) - { - // init TCP acceptor - Acceptor::TCP::Ptr a(new Acceptor::TCP(io_context)); - - // parse address/port of local endpoint - const IP::Addr ip_addr = IP::Addr::from_string(addr); - a->local_endpoint.address(ip_addr.to_asio()); - a->local_endpoint.port(HostPort::parse_port(port, "OMI TCP listen")); - - // open socket - a->acceptor.open(a->local_endpoint.protocol()); - - // set options - a->set_socket_options(0); - - // bind to local address - a->acceptor.bind(a->local_endpoint); - - // listen for incoming client connections - a->acceptor.listen(); - - // save acceptor - acceptor = a; - - // dispatch accepts to handle_except() - queue_accept(); - } - - void listen_unix(const std::string& socket_path) - { -#ifdef ASIO_HAS_LOCAL_SOCKETS - // init unix socket acceptor - Acceptor::Unix::Ptr a(new Acceptor::Unix(io_context)); - - // set endpoint - a->pre_listen(socket_path); - a->local_endpoint.path(socket_path); - - // open socket - a->acceptor.open(a->local_endpoint.protocol()); - - // bind to local address - a->acceptor.bind(a->local_endpoint); - - // set socket permissions in filesystem - a->set_socket_permissions(socket_path, 0777); - - // listen for incoming client connections - a->acceptor.listen(); - - // save acceptor - acceptor = a; - - // dispatch accepts to handle_except() - queue_accept(); -#else - throw Exception("unix sockets not supported on this platform"); -#endif - } - - void queue_accept() - { - if (acceptor) - acceptor->async_accept(this, 0, io_context); - } - - void verify_sock_peer(AsioPolySock::Base& sock) - { -#ifdef ASIO_HAS_LOCAL_SOCKETS - SockOpt::Creds cr; - if (management_client_root && sock.peercreds(cr)) - { - if (!cr.root_uid()) - throw Exception("peer must be root"); - } -#endif - } - - // despite its name, this method handles both accept and connect events - virtual void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code& error) override - { - if (stop_called) - return; - - try { - if (error) - throw Exception("accept/connect failed: " + error.message()); - if (is_sock_open()) - throw Exception("client already connected"); - - verify_sock_peer(*sock); - - sock->non_blocking(true); - sock->set_cloexec(); - socket = std::move(sock); - - password_verified = false; - - if (password_defined) - send_password_prompt(); - else - send_title_message(); - - queue_recv(); - - if (!password_defined) - hold_cycle(); - } - catch (const std::exception& e) - { - const std::string msg = "exception in accept/connect handler: " + std::string(e.what()) + '\n'; - if (errors_to_stderr) - std::cerr << msg << std::flush; - OPENVPN_LOG_STRING(msg); - } - queue_accept(); - } - - void connect_tcp(const std::string& addr, const std::string& port) - { - openvpn_io::ip::tcp::endpoint ep(IP::Addr::from_string(addr).to_asio(), - HostPort::parse_port(port, "OMI TCP connect")); - AsioPolySock::TCP* s = new AsioPolySock::TCP(io_context, 0); - AsioPolySock::Base::Ptr sock(s); - s->socket.async_connect(ep, - [self=Ptr(this), sock](const openvpn_io::error_code& error) mutable - { - // this is a connect, but we reuse the accept method - self->handle_accept(std::move(sock), error); - }); - } - - void connect_unix(const std::string& socket_path) - { -#ifdef ASIO_HAS_LOCAL_SOCKETS - openvpn_io::local::stream_protocol::endpoint ep(socket_path); - AsioPolySock::Unix* s = new AsioPolySock::Unix(io_context, 0); - AsioPolySock::Base::Ptr sock(s); - s->socket.async_connect(ep, - [self=Ptr(this), sock](const openvpn_io::error_code& error) mutable - { - // this is a connect, but we reuse the accept method - self->handle_accept(std::move(sock), error); - }); -#else - throw Exception("unix sockets not supported on this platform"); -#endif - } - - void queue_recv() - { - if (!is_sock_open() || recv_queued) - return; - BufferPtr buf(new BufferAllocated(256, 0)); - socket->async_receive(buf->mutable_buffer_clamp(), - [self=Ptr(this), sock=socket, buf](const openvpn_io::error_code& error, const size_t bytes_recvd) - { - self->handle_recv(error, bytes_recvd, std::move(buf), sock.get()); - }); - recv_queued = true; - } - - void handle_recv(const openvpn_io::error_code& error, const size_t bytes_recvd, - BufferPtr buf, const AsioPolySock::Base* queued_socket) - { - recv_queued = false; - if (!is_sock_open() || socket.get() != queued_socket) - return; - if (error) - { - const bool eof = (error == openvpn_io::error::eof); - if (!eof) - OPENVPN_LOG("client socket recv error: " << error.message()); - conditional_stop(eof); - return; - } - buf->set_size(bytes_recvd); - in_buf = std::move(buf); - process_recv(); - } - - void process_recv() - { - while (in_buf->size()) - { - const char c = (char)in_buf->pop_front(); - in_partial += c; - if (c == '\n') - { - bool defer = false; - try { - defer = process_in_line(); - } - catch (const std::exception& e) - { - send("ERROR: in OMI command: " + std::string(e.what()) + "\r\n"); - } - in_partial.clear(); - if (defer) - return; - } - } - - queue_recv(); - } - - void queue_send() - { - if (!is_sock_open()) - return; - BufferAllocated& buf = *content_out.front(); - socket->async_send(buf.const_buffer_clamp(), - [self=Ptr(this), sock=socket](const openvpn_io::error_code& error, const size_t bytes_sent) - { - self->handle_send(error, bytes_sent, sock.get()); - }); - } - - void handle_send(const openvpn_io::error_code& error, const size_t bytes_sent, - const AsioPolySock::Base* queued_socket) - { - if (!is_sock_open() || socket.get() != queued_socket) - return; - - if (error) - { - OPENVPN_LOG("client socket send error: " << error.message()); - conditional_stop(false); - return; - } - - BufferPtr buf = content_out.front(); - if (bytes_sent == buf->size()) - { - content_out.pop_front(); - if (content_out_throttle) - content_out_throttle->size_change(content_out.size()); - } - else if (bytes_sent < buf->size()) - buf->advance(bytes_sent); - else - { - OPENVPN_LOG("client socket unexpected send size: " << bytes_sent << '/' << buf->size()); - conditional_stop(false); - return; - } - - if (!content_out.empty()) - queue_send(); - else if (stop_called) - conditional_stop(false); - } - - // I/O - Acceptor::Base::Ptr acceptor; - AsioPolySock::Base::Ptr socket; - std::unique_ptr<AsioWork> asio_work; - std::deque<BufferPtr> content_out; - std::string in_partial; - std::unique_ptr<Command> command; - BufferPtr in_buf; - bool management_client_root = false; - bool multiline = false; - bool errors_to_stderr = false; - bool recv_queued = false; - bool password_defined = false; - bool password_verified = false; - std::string password; - - // stopping - volatile bool stop_called = false; - AsioTimerSafe stop_timer; - - // hold - bool hold_wait = false; - bool hold_flag = false; - - // bandwidth stats - unsigned int bytecount = 0; - - // histories - History hist_log {"log", 100}; - History hist_state {"state", 100}; - History hist_echo {"echo", 100}; - - // throttling - std::unique_ptr<BufferThrottle> content_out_throttle; - -#if defined(OPENVPN_PLATFORM_WIN) - Win::ScopedHANDLE log_handle; -#endif - }; -} diff --git a/Sources/OpenVPN3/openvpn/omi/openvpn.cpp b/Sources/OpenVPN3/openvpn/omi/openvpn.cpp deleted file mode 100644 index 882b449..0000000 --- a/Sources/OpenVPN3/openvpn/omi/openvpn.cpp +++ /dev/null @@ -1,1099 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN 3 client with Management Interface - -#define OMI_VERSION "1.0.0" - -#include <string> -#include <vector> -#include <thread> -#include <memory> -#include <utility> -#include <mutex> -#include <condition_variable> - -// don't export core symbols -#define OPENVPN_CORE_API_VISIBILITY_HIDDEN - -// should be included before other openvpn includes, -// with the exception of openvpn/log includes -#include <client/ovpncli.cpp> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/platform_string.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/asio/asiosignal.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/time/asiotimersafe.hpp> -#include <openvpn/omi/omi.hpp> - -using namespace openvpn; - -std::string log_version() -{ - return platform_string("OpenVPN Management Interface", OMI_VERSION) - + " [" SSL_LIB_NAME "] built on " __DATE__ " " __TIME__; -} - -class OMI; - -class Client : public ClientAPI::OpenVPNClient -{ -public: - Client(OMI* omi) - : parent(omi) - { - } - -private: - bool socket_protect(int socket, std::string remote, bool ipv6) override - { - return true; - } - - virtual bool pause_on_connection_timeout() override - { - return false; - } - - virtual void event(const ClientAPI::Event& ev) override; - virtual void log(const ClientAPI::LogInfo& msg) override; - virtual void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override; - virtual void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override; - - OMI* parent; -}; - -class OMI : public OMICore, public ClientAPI::LogReceiver -{ -public: - typedef RCPtr<OMI> Ptr; - - OMI(openvpn_io::io_context& io_context, OptionList opt_arg) - : OMICore(io_context), - opt(std::move(opt_arg)), - reconnect_timer(io_context), - bytecount_timer(io_context), - exit_event(io_context), - log_context(this) - { - signals.reset(new ASIOSignals(io_context)); - signal_rearm(); - } - - void start() - { - log_setup(OMICore::LogFn(opt)); - - OPENVPN_LOG(log_version()); - - // command line options - connection_timeout = opt.get_num<decltype(connection_timeout)>("connection-timeout", 1, 30); - management_query_passwords = opt.exists("management-query-passwords"); - auth_nocache = opt.exists("auth-nocache"); - management_external_key = opt.exists("management-external-key"); - proto_override = opt.get_default("proto-force", 1, 16, "adaptive"); - remote_override = opt.get_optional("remote-override", 1, 256); - management_up_down = opt.exists("management-up-down"); - management_query_remote = opt.exists("management-query-remote"); - exit_event_name = opt.get_optional("exit-event-name", 1, 256); - - // passed by OpenVPN GUI to trigger exit - if (!exit_event_name.empty()) - { - exit_event.assign(::CreateEvent(NULL, FALSE, FALSE, exit_event_name.c_str())); - exit_event.async_wait([self = Ptr(this)](const openvpn_io::error_code& error) - { - if (error) - return; - self->stop(); - }); - } - - // http-proxy-override - { - const Option* o = opt.get_ptr("http-proxy-override"); - if (o) - { - http_proxy_host = o->get(1, 128); - http_proxy_port = o->get(2, 16); - } - } - - // begin listening/connecting on OMI port - OMICore::start(opt); - } - - virtual void log(const ClientAPI::LogInfo& msg) override - { - openvpn_io::post(io_context, [this, msg]() { - log_msg(msg); - }); - } - - void event(const ClientAPI::Event& ev) - { - openvpn_io::post(io_context, [this, ev]() { - event_msg(ev, nullptr); - }); - } - - void event(const ClientAPI::Event& ev, const ClientAPI::ConnectionInfo& ci) - { - openvpn_io::post(io_context, [this, ev, ci]() { - event_msg(ev, &ci); - }); - } - - void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) - { - // not currently supported, <cert> must be in config - } - - void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) - { - try { - // publish signreq to main thread - { - std::lock_guard<std::mutex> lock(epki_mutex); - epki_signreq = &signreq; - } - - // message main thread that signreq is published and pending - openvpn_io::post(io_context, [this]() { - epki_sign_request(); - }); - - // allow asynchronous stop - Stop::Scope stop_scope(&async_stop, [this, &signreq]() { - { - std::lock_guard<std::mutex> lock(epki_mutex); - epki_signreq = nullptr; - signreq.error = true; - signreq.errorText = "External PKI OMI: stop"; - } - epki_cv.notify_all(); - }); - - // wait for main thread to signal readiness by nulling epki_signreq ptr - { - std::unique_lock<std::mutex> lock(epki_mutex); - epki_cv.wait(lock, [this]() { - return epki_signreq == nullptr; - }); - } - } - catch (const std::exception& e) - { - std::lock_guard<std::mutex> lock(epki_mutex); - epki_signreq = nullptr; - signreq.error = true; - signreq.errorText = std::string("External PKI OMI: ") + e.what(); - } - } - - void epki_sign_request() - { - std::string sr; - { - std::lock_guard<std::mutex> lock(epki_mutex); - if (epki_signreq) - sr = epki_signreq->data; - } - send(">RSA_SIGN:" + sr + "\r\n"); - } - - void epki_sign_reply(const Command& cmd) - { - // get base64 signature from command - std::string sig64; - for (auto &line : cmd.extra) - { - sig64 += line; - } - - // commit to connection thread - bool fail = false; - { - std::lock_guard<std::mutex> lock(epki_mutex); - if (epki_signreq) - { - epki_signreq->sig = sig64; - epki_signreq = nullptr; - } - else - fail = true; - } - if (fail) - send("ERROR: unsolicited rsa-sig command\r\n"); - else - { - epki_cv.notify_all(); - send("SUCCESS: rsa-sig command succeeded\r\n"); - } - } - - virtual bool omi_command_is_multiline(const std::string& arg0, const Option& o) override - { - if (arg0 == "rsa-sig") - return true; - return false; - } - -private: - virtual bool omi_command_in(const std::string& arg0, const Command& cmd) override - { - switch (arg0.at(0)) - { - case 'p': - { - if (is_auth_cmd(arg0)) - { - process_auth_cmd(cmd.option); - return false; - } - break; - } - case 'r': - { - if (arg0 == "remote") - { - process_remote_cmd(cmd.option); - return false; - } - else if (arg0 == "rsa-sig") - { - epki_sign_reply(cmd); - return false; - } - break; - } - case 'u': - { - if (is_auth_cmd(arg0)) - { - process_auth_cmd(cmd.option); - return false; - } - break; - } - } - send("ERROR: unknown command, enter 'help' for more options\r\n"); - return false; - } - - virtual void omi_done(const bool eof) override - { - //OPENVPN_LOG("OMI DONE eof=" << eof); - } - - std::vector<ClientAPI::KeyValue> get_peer_info() const - { - std::vector<ClientAPI::KeyValue> ret; - OptionList::IndexMap::const_iterator se = opt.map().find("setenv"); - if (se != opt.map().end()) - { - for (OptionList::IndexList::const_iterator i = se->second.begin(); i != se->second.end(); ++i) - { - const Option& o = opt[*i]; - o.touch(); - const std::string& k = o.get(1, 64); - if (string::starts_with(k, "IV_") || string::starts_with(k, "UV_")) - { - const std::string& v = o.get(2, 256); - ret.emplace_back(k, v); - } - } - } - return ret; - } - - virtual void omi_start_connection() override - { - try { - //OPENVPN_LOG("OMI START CONNECTION"); - - // reset state - reconnect_timer.cancel(); - reconnect_reason = ""; - - if (!config) - { - config.reset(new ClientAPI::Config); - config->guiVersion = "ovpnmi " OMI_VERSION; - config->content = get_config(opt); - config->peerInfo = get_peer_info(); - config->connTimeout = connection_timeout; - config->protoOverride = proto_override; - config->serverOverride = remote_override; - config->tunPersist = true; - config->googleDnsFallback = true; - config->autologinSessions = true; - config->compressionMode = "yes"; - config->proxyHost = http_proxy_host; - config->proxyPort = http_proxy_port; - config->echo = true; - - if (management_external_key) - config->externalPkiAlias = "EPKI"; // dummy alias - - did_query_remote = false; - } - - const ClientAPI::EvalConfig eval = Client::eval_config_static(*config); - if (eval.error) - OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message); - - autologin = eval.autologin; - - // for compatibility with openvpn2 - if (eval.windowsDriver == "wintun") - config->wintun = true; - - if (!eval.autologin && management_query_passwords && !creds) - query_username_password("Auth", !dc_cookie.empty(), eval.staticChallenge, eval.staticChallengeEcho); - else if (proxy_need_creds) - query_username_password("HTTP Proxy", false, "", false); - else if (management_query_remote && !did_query_remote) - query_remote(eval.remoteHost, eval.remotePort, eval.remoteProto); - else - start_connection_thread(); - } - catch (const std::exception& e) - { - set_final_error(e.what()); - stop(); - } - } - - void query_username_password(const std::string& type, - const bool password_only, - const std::string& static_challenge, - const bool static_challenge_echo) - { - reset_auth_cmd(); - auth_type = type; - auth_password_only = password_only; - - std::string notify = ">PASSWORD:Need '" + type + "' "; - if (password_only) - notify += "password"; - else - notify += "username/password"; - - // static challenge - if (!static_challenge.empty()) - { - notify += " SC:"; - if (static_challenge_echo) - notify += '1'; - else - notify += '0'; - notify += ','; - notify += static_challenge; - } - - notify += "\r\n"; - send(notify); - } - - bool is_auth_cmd(const std::string& arg0) const - { - return arg0 == "username" || arg0 == "password"; - } - - void process_auth_cmd(const Option& o) - { - const std::string up = o.get(0, 0); - const std::string type = o.get(1, 64); - const std::string cred = o.get(2, 512); - if (auth_type.empty() || type != auth_type || (up == "username" && auth_password_only)) - { - send("ERROR: no " + up + " is currently needed at this time\r\n"); - return; - } - bool changed = false; - if (up == "username") - { - auth_username = cred; - changed = true; - } - else if (up == "password") - { - auth_password = cred; - changed = true; - } - if (changed) - send("SUCCESS: '" + auth_type + "' " + up + " entered, but not yet verified\r\n"); - if ((!auth_username.empty() || auth_password_only) && !auth_password.empty()) - { - provide_username_password(auth_type, auth_username, auth_password); - reset_auth_cmd(); - } - } - - void reset_auth_cmd() - { - auth_type = ""; - auth_password_only = false; - auth_username = ""; - auth_password = ""; - } - - void provide_username_password(const std::string& type, const std::string& username, const std::string& password) - { - if (!dc_cookie.empty()) - { - creds.reset(new ClientAPI::ProvideCreds); - creds->dynamicChallengeCookie = dc_cookie; - try { - // response could be whole challenge string in case of connect 2.x - ChallengeResponse cr{ auth_password }; - creds->response = std::string{ cr.get_challenge_text() }; - } - catch (const ChallengeResponse::dynamic_challenge_parse_error&) { - // response contains only challenge text - creds->response = auth_password; - } - creds->cachePassword = !auth_nocache; - creds->replacePasswordWithSessionID = true; - } - else if (type == "Auth") - { - creds.reset(new ClientAPI::ProvideCreds); - creds->username = username; - creds->password = password; - creds->replacePasswordWithSessionID = true; - creds->cachePassword = !auth_nocache; - } - else if (type == "HTTP Proxy") - { - if (config) - { - config->proxyUsername = username; - config->proxyPassword = password; - } - proxy_need_creds = false; - } - omi_start_connection(); - } - - void query_remote(const std::string& host, const std::string& port, const std::string& proto) - { - send(">REMOTE:" + host + ',' + port + ',' + proto + "\r\n"); - remote_pending = true; - } - - void process_remote_cmd(const Option& o) - { - if (!remote_pending) - { - send("ERROR: no pending remote query\r\n"); - return; - } - - std::string host; - std::string port; - bool mod = false; - - const std::string type = o.get(1, 16); - if (type == "MOD") - { - host = o.get(2, 256); - port = o.get_optional(3, 16); - mod = true; - } - else if (type == "ACCEPT") - { - ; - } - else - { - send("ERROR: remote type must be MOD or ACCEPT\r\n"); - return; - } - - send("SUCCESS: remote command succeeded\r\n"); - remote_pending = false; - - if (mod && config) - { - config->serverOverride = host; - // fixme -- override port - } - did_query_remote = true; - omi_start_connection(); - } - - void schedule_bytecount_timer() - { - if (get_bytecount()) - { - bytecount_timer.expires_after(Time::Duration::seconds(get_bytecount())); - bytecount_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - self->report_bytecount(); - }); - } - else - bytecount_timer.cancel(); - } - - void report_bytecount() - { - if (client && get_bytecount()) - { - const ClientAPI::TransportStats ts = client->transport_stats(); - send(">BYTECOUNT:" + openvpn::to_string(ts.bytesIn) + ',' + openvpn::to_string(ts.bytesOut) + "\r\n"); - } - schedule_bytecount_timer(); - } - - void start_connection_thread() - { - try { - // reset client instance - client.reset(new Client(this)); - - // evaluate config - const ClientAPI::EvalConfig eval = client->eval_config(*config); - if (eval.error) - OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message); - - // add credentials, if available - if (creds) - { - const ClientAPI::Status creds_status = client->provide_creds(*creds); - if (creds_status.error) - OPENVPN_THROW_EXCEPTION("creds error: " << creds_status.message); - } - - // bytecount - schedule_bytecount_timer(); - - // start connection thread - thread.reset(new std::thread([this]() { - connection_thread(); - })); - } - catch (const std::exception& e) - { - set_final_error(e.what()); - stop(); - } - } - - void connection_thread() - { - openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread - std::string error; - try { - const ClientAPI::Status cs = client->connect(); - if (cs.error) - { - error = "connect error: "; - if (!cs.status.empty()) - { - error += cs.status; - error += ": "; - } - error += cs.message; - } - } - catch (const std::exception& e) - { - error = "connect thread exception: "; - error += e.what(); - } - - // generate an internal event for client exceptions - if (!error.empty()) - { - ClientAPI::Event ev; - ev.error = true; - ev.fatal = true; - ev.name = "CLIENT_EXCEPTION"; - ev.info = error; - event(ev); - } - } - - void join_thread() - { - try { - if (thread) - thread->join(); // may throw if thread has already exited - } - catch (const std::exception& e) - { - } - } - - virtual bool omi_stop() override - { - bool ret = false; - - // in case connect thread is blocking in external_pki_sign_request - async_stop.stop(); - - // cancel wait on exit_event - if (exit_event.is_open()) - exit_event.cancel(); - - // stop timers - reconnect_timer.cancel(); - bytecount_timer.cancel(); - - // stop the client - if (client) - client->stop(); - - // wait for client thread to exit - join_thread(); - - // if there's a final error, dump to management interface - const std::string fe = get_final_error(); - if (!fe.empty()) - { - send(string::add_trailing_crlf_copy(fe)); - if (is_errors_to_stderr()) - std::cerr << fe << std::endl; - OPENVPN_LOG_STRING(fe + '\n'); - ret = true; - } - - // cancel signals - if (signals) - signals->cancel(); - - return ret; - } - - void retry() - { - // wait for client thread to exit - join_thread(); - - // restart connection - omi_start_connection(); - } - - void deferred_reconnect(const unsigned int seconds, const std::string& reason) - { - reconnect_timer.expires_after(Time::Duration::seconds(seconds)); - reconnect_timer.async_wait([self=Ptr(this), reason](const openvpn_io::error_code& error) - { - if (!error) - { - self->state_line(gen_state_msg(false, "RECONNECTING", reason)); - self->retry(); - } - }); - } - - virtual void omi_sigterm() override - { - if (client) - set_final_error(gen_state_msg(true, "EXITING", "exit-with-notification")); - stop(); - } - - virtual bool omi_is_sighup_implemented() override - { - return true; - } - - virtual void omi_sighup() override - { - if (client) - client->reconnect(1); - } - - void log_msg(const ClientAPI::LogInfo& msg) - { - log_full(msg.text); - } - - static std::string event_format(const ClientAPI::Event& ev, const ClientAPI::ConnectionInfo* ci) - { - const time_t now = ::time(NULL); - std::string evstr = openvpn::to_string(now) + ',' + ev.name; - if (ev.name == "CONNECTED" && ci) - evstr += ",SUCCESS," + ci->vpnIp4 + ',' + ci->serverIp + ',' + ci->serverPort + ",,," + ci->vpnIp6; - else - evstr += ',' + ev.info + ",,"; - evstr += "\r\n"; - return evstr; - } - - static std::string gen_state_msg(const bool prefix, std::string name, std::string info) - { - ClientAPI::Event ev; - ev.name = std::move(name); - ev.info = std::move(info); - std::string ret; - if (prefix) - ret = ">STATE:"; - ret += event_format(ev, nullptr); - return ret; - } - - void event_msg(const ClientAPI::Event& ev, const ClientAPI::ConnectionInfo* ci) - { - // log events (even if in stopping state) - { - ClientAPI::LogInfo li; - li.text = ev.name; - if (!ev.info.empty()) - { - li.text += " : "; - li.text += ev.info; - } - if (ev.fatal) - li.text += " [FATAL-ERR]"; - else if (ev.error) - li.text += " [ERR]"; - li.text += '\n'; - log_msg(li); - } - - // if we are in a stopping state, don't process the event - if (is_stopping()) - return; - - // process events - if ((ev.name == "AUTH_FAILED" || ev.name == "DYNAMIC_CHALLENGE") && management_query_passwords) - { - if (ev.name == "DYNAMIC_CHALLENGE") - { - dc_cookie = ev.info; - } - else - { - dc_cookie = ""; - } - - // handle auth failures - std::string msg = ">PASSWORD:Verification Failed: 'Auth'"; - if (!ev.info.empty()) - msg += " ['" + ev.info + "']"; - msg += "\r\n"; - send(msg); - - // reset query state - creds.reset(); - did_query_remote = false; - - // exit/reconnect - if (autologin) - { - set_final_error(">FATAL: auth-failure: " + ev.info + "\r\n"); - stop(); - } - else - deferred_reconnect(1, "auth-failure"); - } - - else if (ev.name == "CLIENT_HALT") - { - std::string reason = ev.info; - if (reason.empty()) - reason = "client was disconnected from server"; - send(">NOTIFY:info,server-pushed-halt," + reason + "\r\n"); - set_final_error(gen_state_msg(true, "EXITING", "exit-with-notification")); - stop(); - } - - else if (ev.name == "CLIENT_RESTART") - { - // fixme -- handle PSID - std::string reason = ev.info; - if (reason.empty()) - reason = "server requested a client reconnect"; - reconnect_reason = "server-pushed-connection-reset"; - send(">NOTIFY:info,"+ reconnect_reason + ',' + reason + "\r\n"); - omi_sighup(); - } - - else if (ev.name == "RECONNECTING") - { - ClientAPI::Event nev(ev); - if (nev.info.empty()) - nev.info = reconnect_reason; - reconnect_reason = ""; - state_line(event_format(nev, nullptr)); - } - - else if (ev.name == "PROXY_NEED_CREDS" && management_query_passwords) - { - // need proxy credentials, retry - proxy_need_creds = true; - state_line(event_format(ev, nullptr)); - retry(); - } - - else if (ev.name == "DISCONNECTED") - { - // for now, we ignore DISCONNECTED messages - } - - else if (ev.fatal) - { - // this event is a fatal error - std::string reason = ev.name; - if (!ev.info.empty()) - { - reason += ": "; - reason += ev.info; - } - set_final_error(">FATAL:" + reason + "\r\n"); - stop(); - } - - else if (ev.name == "ECHO") - { - echo_line(openvpn::to_string(::time(NULL)) + ',' + ev.info + "\r\n"); - } - - else if (ev.name == "CONNECTED") - { - // generate >UPDOWN: event - if (management_up_down) - emit_up_down("UP"); - - // reset pre-connection state - creds.reset(); - reconnect_reason = ""; - - // generate a TCP_CONNECT event if TCP connection - if (ci && string::starts_with(ci->serverProto, "TCP")) - state_line(gen_state_msg(false, "TCP_CONNECT", "")); - - // push the event string to state notification/history - state_line(event_format(ev, ci)); - } - - else - { - // push the event string to state notification/history - state_line(event_format(ev, ci)); - } - } - - void emit_up_down(const std::string& state) - { - std::string out = ">UPDOWN:" + state + "\r\n"; - out += ">UPDOWN:ENV,END\r\n"; - send(out); - } - - void set_final_error(const std::string& err) - { - if (!err.empty()) - final_error = string::trim_crlf_copy(err); - } - - std::string get_final_error() - { - return final_error; - } - - void signal(const openvpn_io::error_code& error, int signum) - { - if (!error && !is_stopping()) - { - OPENVPN_LOG("ASIO SIGNAL " << signum); - switch (signum) - { - case SIGINT: - case SIGTERM: - omi_sigterm(); - break; -#if !defined(OPENVPN_PLATFORM_WIN) - case SIGHUP: - omi_sighup(); - signal_rearm(); - break; -#endif - } - } - } - - void signal_rearm() - { - signals->register_signals_all([self=Ptr(this)](const openvpn_io::error_code& error, int signal_number) - { - self->signal(error, signal_number); - }); - } - - // options - OptionList opt; - - // general - std::unique_ptr<Client> client; - std::unique_ptr<ClientAPI::Config> config; - std::unique_ptr<ClientAPI::ProvideCreds> creds; - std::unique_ptr<std::thread> thread; - std::string final_error; - Stop async_stop; - - // timeout - int connection_timeout = 0; - - // auth - bool management_query_passwords = false; - bool auth_nocache = false; - std::string auth_type; - bool auth_password_only = false; - std::string auth_username; - std::string auth_password; - std::string dc_cookie; - - // remote override - bool management_query_remote = false; - bool did_query_remote = false; - bool remote_pending = false; - std::string remote_override; - - // protocol override (udp/tcp) - std::string proto_override; - - // proxy - std::string http_proxy_host; - std::string http_proxy_port; - bool proxy_need_creds = false; - - // reconnections - std::string reconnect_reason; - - // reconnect - AsioTimerSafe reconnect_timer; - - // bytecount - AsioTimerSafe bytecount_timer; - - // external PKI - bool management_external_key = false; - std::mutex epki_mutex; - std::condition_variable epki_cv; - ClientAPI::ExternalPKISignRequest* epki_signreq = nullptr; // protected by epki_mutex - - // up/down - bool management_up_down = false; - - // autologin - bool autologin = false; - - // signals - ASIOSignals::Ptr signals; - - typedef openvpn_io::windows::object_handle AsioEvent; - AsioEvent exit_event; - std::string exit_event_name; - - Log::Context log_context; // should be initialized last -}; - -void Client::event(const ClientAPI::Event& ev) -{ - if (ev.name == "CONNECTED") - { - const ClientAPI::ConnectionInfo ci = connection_info(); - parent->event(ev, ci); - } - else - parent->event(ev); -} - -void Client::log(const ClientAPI::LogInfo& msg) -{ - parent->log(msg); -} - -void Client::external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) -{ - parent->external_pki_cert_request(certreq); -} - -void Client::external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) -{ - parent->external_pki_sign_request(signreq); -} - -int run(OptionList opt) -{ - openvpn_io::io_context io_context(1); - bool io_context_run_called = false; - int ret = 0; - OMI::Ptr omi; - - try { -#if _WIN32_WINNT >= 0x0600 // Vista+ - TunWin::NRPT::delete_rule(); // delete stale NRPT rules -#endif - omi.reset(new OMI(io_context, std::move(opt))); - omi->start(); - io_context_run_called = true; - io_context.run(); - omi->stop(); - } - catch (const std::exception& e) - { - if (omi) - omi->stop(); - if (io_context_run_called) - io_context.poll(); // execute completion handlers, - std::cerr << "openvpn: run loop exception: " << e.what() << std::endl; - ret = 1; - } - return ret; -} - -int main(int argc, char *argv[]) -{ - int ret = 0; - - try { - if (argc >= 2) - { - ret = run(OptionList::parse_from_argv_static(string::from_argv(argc, argv, true))); - } - else - { - std::cout << log_version() << std::endl; - std::cout << "Usage: openvpn [args...]" << std::endl; - ret = 2; - } - } - catch (const std::exception& e) - { - std::cerr << "openvpn: " << e.what() << std::endl; - ret = 1; - } - return ret; -} diff --git a/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_dgram.hpp b/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_dgram.hpp deleted file mode 100644 index d775408..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_dgram.hpp +++ /dev/null @@ -1,262 +0,0 @@ -// 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-2020 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/>. - -// This code implements an OpenSSL BIO object for datagrams based on the -// MemQ buffer queue object. - -#ifndef OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H -#define OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H - -#include <cstring> // for std::strlen - -#include <openssl/err.h> -#include <openssl/bio.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/frame/memq_dgram.hpp> - -namespace openvpn { - namespace bmq_dgram { - - class MemQ : public MemQDgram { - public: - MemQ() - { - mtu = 0; - query_mtu_return = 0; - std::memset(&next_timeout, 0, sizeof(next_timeout)); - } - - void set_mtu(long mtu) { query_mtu_return = mtu; } - const struct timeval *get_next_timeout(void) const { return &next_timeout; } - - long ctrl (BIO *b, int cmd, long num, void *ptr) - { - long ret = 1; - - switch (cmd) - { - case BIO_CTRL_RESET: - clear(); - break; - case BIO_CTRL_EOF: - ret = (long)empty(); - break; - case BIO_C_SET_BUF_MEM_EOF_RETURN: - return_eof_on_empty = (num == 0); - break; - case BIO_CTRL_GET_CLOSE: - ret = (long)(BIO_get_shutdown (b)); - break; - case BIO_CTRL_SET_CLOSE: - BIO_set_shutdown (b, (int)num); - break; - case BIO_CTRL_WPENDING: - ret = 0L; - break; - case BIO_CTRL_PENDING: - ret = (long)pending(); - break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - ret = 1; - break; - case BIO_CTRL_DGRAM_QUERY_MTU: - ret = mtu = query_mtu_return; - break; - case BIO_CTRL_DGRAM_GET_MTU: - ret = mtu; - break; - case BIO_CTRL_DGRAM_SET_MTU: - ret = mtu = num; - break; - case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: - std::memcpy(&next_timeout, ptr, sizeof(struct timeval)); - break; - default: - //OPENVPN_LOG("*** MemQ-dgram unimplemented ctrl method=" << cmd); - ret = 0; - break; - } - return (ret); - } - - private: - long mtu; - long query_mtu_return; - bool return_eof_on_empty; - struct timeval next_timeout; - }; - - namespace bio_memq_internal { - static int memq_method_type=0; - static BIO_METHOD* memq_method = nullptr; - - inline int memq_new (BIO *b) - { - MemQ *bmq = new(std::nothrow) MemQ(); - if (!bmq) - return 0; - BIO_set_shutdown(b, 1); - BIO_set_init(b, 1); - b->return_eof_on_empty = false; - BIO_set_data(b, (void *)bmq); - return 1; - } - - inline int memq_free (BIO *b) - { - if (b == nullptr) - return (0); - if (BIO_get_shutdown (b)) - { - MemQ *bmq = (MemQ*) (BIO_get_data (b)); - if (BIO_get_init (b) && (bmq != nullptr)) - { - delete bmq; - BIO_set_data (b, nullptr); - } - } - return 1; - } - - inline int memq_write (BIO *b, const char *in, int len) - { - MemQ *bmq = (MemQ*) (BIO_get_data (b)); - if (in) - { - BIO_clear_retry_flags (b); - try { - if (len) - bmq->write((const unsigned char *)in, (size_t)len); - return len; - } - catch (...) - { - BIOerr(BIO_F_MEM_WRITE, BIO_R_INVALID_ARGUMENT); - return -1; - } - } - else - { - BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); - return -1; - } - } - - inline int memq_read (BIO *b, char *out, int size) - { - MemQ *bmq = (MemQ*) (BIO_get_data (b)); - int ret = -1; - BIO_clear_retry_flags (b); - if (!bmq->empty()) - { - try { - ret = (int)bmq->read((unsigned char *)out, (size_t)size); - } - catch (...) - { - BIOerr(BIO_F_MEM_READ, BIO_R_INVALID_ARGUMENT); - return -1; - } - } - else - { - ret = b->num; - if (ret != 0) - BIO_set_retry_read (b); - } - return ret; - } - - inline long memq_ctrl (BIO *b, int cmd, long arg1, void *arg2) - { - MemQ *bmq = (MemQ*) (BIO_get_data (b)); - return bmq->ctrl(b, cmd, arg1, arg2); - } - - inline int memq_puts (BIO *b, const char *str) - { - const int len = std::strlen (str); - const int ret = memq_write (b, str, len); - return ret; - } - - inline void create_bio_method () - { - if (!memq_method_type) - memq_method_type = BIO_get_new_index (); - - memq_method = BIO_meth_new (memq_method_type, "datagram memory queue"); - BIO_meth_set_write (memq_method, memq_write); - BIO_meth_set_read (memq_read); - BIO_meth_set_puts (memq_puts); - BIO_meth_set_create (memq_new); - BIO_meth_set_destroy (memq_destroy); - BIO_meth_set_gets (nullptr); - BIO_meth_set_ctrl (memq_method, memq_ctrl); - } - - inline void free_bio_method() - { - BIO_meth_free (memq_method); - } - } // namespace bio_memq_internal - - inline BIO_METHOD *BIO_s_memq(void) - { - // TODO: call free in some cleanup - bio_memq_internal::create_bio_method (); - return bio_memq_internal::memq_method; - } - - inline MemQ *memq_from_bio(BIO *b) - { - if (BIO_method_type (b) == bio_memq_internal::memq_method_type) - return (MemQ *)(BIO_get_data (b)); - else - return nullptr; - } - - inline const MemQ *const_memq_from_bio(const BIO *b) - { - if (BIO_method_type (b) == bio_memq_internal::memq_method_type) - return (const MemQ *)(BIO_get_data (const_cast<BIO*>(b))); - else - return nullptr; - } - - MemQ() - { - mtu = 0; - query_mtu_return = 0; - std::memset(&next_timeout, 0, sizeof(next_timeout)); - - bio_memq_internal::create_bio_method (); - } - - ~MemQ() { bio_memq_internal::free_bio_method(); } - } // namespace bmq_dgram -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H diff --git a/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_stream.hpp b/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_stream.hpp deleted file mode 100644 index 355488d..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/bio/bio_memq_stream.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// 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-2020 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/>. - -// This code implements an OpenSSL BIO object for streams based on the -// MemQ buffer queue object. - -#pragma once - -#include <cstring> // for std::strlen and others - -#include <openssl/err.h> -#include <openssl/bio.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/frame/memq_stream.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - namespace bmq_stream { - - class MemQ : public MemQStream { - public: - MemQ() {} - - long ctrl (BIO *b, int cmd, long num, void *ptr) - { - long ret = 1; - - switch (cmd) - { - case BIO_CTRL_RESET: - clear(); - break; - case BIO_CTRL_EOF: - ret = (long)empty(); - break; - case BIO_C_SET_BUF_MEM_EOF_RETURN: - return_eof_on_empty = (num == 0); - break; - case BIO_CTRL_GET_CLOSE: - ret = BIO_get_shutdown(b); - break; - case BIO_CTRL_SET_CLOSE: - BIO_set_shutdown(b, (int) num); - break; - case BIO_CTRL_WPENDING: - ret = 0L; - break; - case BIO_CTRL_PENDING: - ret = (long)pending(); - break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - ret = 1; - break; - default: - //OPENVPN_LOG("*** MemQ-stream unimplemented ctrl method=" << cmd); - ret = 0; - break; - } - return (ret); - } - - bool return_eof_on_empty = false; - }; - - class bio_memq_internal { - public: - static int memq_method_type; - static BIO_METHOD* memq_method; - - - static inline int memq_new (BIO *b) - { - MemQ *bmq = new(std::nothrow) MemQ(); - if (!bmq) - return 0; - BIO_set_shutdown(b, 1); - BIO_set_init(b, 1); - BIO_set_data(b, (void *)bmq); - return 1; - } - - static inline int memq_free (BIO *b) - { - if (b == nullptr) - return (0); - if (BIO_get_shutdown (b)) - { - MemQ *bmq = (MemQ*) (BIO_get_data (b)); - if (BIO_get_init (b) && (bmq != nullptr)) - { - delete bmq; - BIO_set_data (b, nullptr); - } - } - return 1; - } - - static inline int memq_write (BIO *b, const char *in, int len) - { - MemQ *bmq = (MemQ*)(BIO_get_data(b)); - if (in) - { - BIO_clear_retry_flags (b); - try { - if (len) - bmq->write((const unsigned char *)in, (size_t)len); - return len; - } - catch (...) - { - BIOerr(BIO_F_MEM_WRITE, BIO_R_INVALID_ARGUMENT); - return -1; - } - } - else - { - BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); - return -1; - } - } - - static inline int memq_read (BIO *b, char *out, int size) - { - MemQ *bmq = (MemQ*)(BIO_get_data(b)); - int ret = -1; - BIO_clear_retry_flags (b); - if (!bmq->empty()) - { - try { - ret = (int)bmq->read((unsigned char *)out, (size_t)size); - } - catch (...) - { - BIOerr(memq_method_type, BIO_R_INVALID_ARGUMENT); - return -1; - } - } - else - { - if (!bmq->return_eof_on_empty) - BIO_set_retry_read (b); - } - return ret; - } - - static inline long memq_ctrl (BIO *b, int cmd, long arg1, void *arg2) - { - MemQ *bmq = (MemQ*)(BIO_get_data(b)); - return bmq->ctrl(b, cmd, arg1, arg2); - } - - static inline int memq_puts (BIO *b, const char *str) - { - const int len = std::strlen (str); - const int ret = memq_write (b, str, len); - return ret; - } - - static inline void init_static () - { - memq_method_type = BIO_get_new_index (); - memq_method = BIO_meth_new (memq_method_type, "stream memory queue"); - BIO_meth_set_write (memq_method, memq_write); - BIO_meth_set_read (memq_method, memq_read); - BIO_meth_set_puts (memq_method, memq_puts); - BIO_meth_set_create (memq_method, memq_new); - BIO_meth_set_destroy (memq_method, memq_free); - BIO_meth_set_gets (memq_method, nullptr); - BIO_meth_set_ctrl (memq_method, memq_ctrl); - } - - static inline void free_bio_method() - { - BIO_meth_free (memq_method); - memq_method = nullptr; - } - }; // class bio_memq_internal - -#if defined(OPENVPN_NO_EXTERN) - int bio_memq_internal::memq_method_type = -1; - BIO_METHOD* bio_memq_internal::memq_method = nullptr; -#endif - - inline void init_static() - { - bio_memq_internal::init_static(); - } - - inline BIO_METHOD *BIO_s_memq(void) - { - return (bio_memq_internal::memq_method); - } - - inline MemQ *memq_from_bio(BIO *b) - { - if (BIO_method_type(b) == bio_memq_internal::memq_method_type) - return (MemQ *)(BIO_get_data (b)); - else - return nullptr; - } - - inline const MemQ *const_memq_from_bio(const BIO *b) - { - if (BIO_method_type(b) == bio_memq_internal::memq_method_type) - return (const MemQ *)(BIO_get_data (const_cast<BIO*>(b))); - else - return nullptr; - } - } // namespace bmq_dgram -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/openssl/compat.hpp b/Sources/OpenVPN3/openvpn/openssl/compat.hpp deleted file mode 100644 index f77e6fb..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/compat.hpp +++ /dev/null @@ -1,374 +0,0 @@ -// 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-2020 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 - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - -#include <openssl/bio.h> -#include <openssl/crypto.h> -#include <openssl/rsa.h> -#include <openssl/dsa.h> -#include <openssl/hmac.h> -#include <openssl/err.h> - -// make sure type 94 doesn't collide with anything in bio.h -// Start with the same number as before - -static int lastindex = 94; -inline int BIO_get_new_index(void) -{ - int newval = lastindex | BIO_TYPE_SOURCE_SINK; - lastindex++; - return newval; -} - -inline BIO_METHOD *BIO_meth_new(int type, const char *name) -{ - BIO_METHOD *biom = new BIO_METHOD(); - - if ((biom->name = OPENSSL_strdup(name)) == nullptr) - { - delete biom; - BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); - return nullptr; - } - biom->type = type; - return biom; -} - -inline void BIO_meth_free(BIO_METHOD *biom) -{ - if (biom != nullptr) - { - OPENSSL_free((void *)biom->name); - delete biom; - } -} - -inline RSA_METHOD *RSA_meth_new(const char *name, int flags) -{ - RSA_METHOD *meth = new RSA_METHOD(); - - meth->flags = flags; - meth->name = name; - - return meth; -} - -inline void RSA_meth_free(RSA_METHOD *meth) -{ - delete meth; -} - -inline HMAC_CTX *HMAC_CTX_new() -{ - HMAC_CTX *ctx = new HMAC_CTX(); - HMAC_CTX_init(ctx); - return ctx; -} - -inline void HMAC_CTX_free(HMAC_CTX *ctx) -{ - if (ctx) { - HMAC_CTX_cleanup(ctx); - delete ctx; - } -} - -inline EVP_MD_CTX *EVP_MD_CTX_new() -{ - return new EVP_MD_CTX(); -} - -inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx) -{ - delete ctx; -} - -inline void BIO_set_shutdown(BIO *a, int shut) -{ - a->shutdown = shut; -} - -inline int BIO_get_shutdown(BIO *a) -{ - return a->shutdown; -} - -inline void BIO_set_data(BIO *a, void *ptr) -{ - a->ptr = ptr; -} - -inline void *BIO_get_data(BIO *a) -{ - return a->ptr; -} - -inline void BIO_set_init(BIO *a, int init) -{ - a->init = init; -} - -inline int BIO_get_init(BIO *a) -{ - return a->init; -} - -inline int BIO_meth_set_write(BIO_METHOD *biom, - int (*bwrite)(BIO *, const char *, int)) -{ - biom->bwrite = bwrite; - return 1; -} - -inline int BIO_meth_set_read(BIO_METHOD *biom, - int (*bread)(BIO *, char *, int)) -{ - biom->bread = bread; - return 1; -} - -inline int BIO_meth_set_puts(BIO_METHOD *biom, - int (*bputs)(BIO *, const char *)) -{ - biom->bputs = bputs; - return 1; -} - -inline int BIO_meth_set_gets(BIO_METHOD *biom, - int (*bgets)(BIO *, char *, int)) -{ - biom->bgets = bgets; - return 1; -} - -inline int BIO_meth_set_ctrl(BIO_METHOD *biom, - long (*ctrl)(BIO *, int, long, void *)) -{ - biom->ctrl = ctrl; - return 1; -} - -inline int BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *)) -{ - biom->create = create; - return 1; -} - -inline int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *)) -{ - biom->destroy = destroy; - return 1; -} - -inline RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) -{ - return pkey->pkey.rsa; -} - -inline int RSA_meth_set_pub_enc(RSA_METHOD *meth, - int (*pub_enc)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, - int padding)) -{ - meth->rsa_pub_enc = pub_enc; - return 1; -} - -inline int RSA_meth_set_pub_dec(RSA_METHOD *meth, - int (*pub_dec)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, - int padding)) -{ - meth->rsa_pub_dec = pub_dec; - return 1; -} - -inline int RSA_meth_set_priv_enc(RSA_METHOD *meth, - int (*priv_enc)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, - int padding)) -{ - meth->rsa_priv_enc = priv_enc; - return 1; -} - -inline int RSA_meth_set_priv_dec(RSA_METHOD *meth, - int (*priv_dec)(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, - int padding)) -{ - meth->rsa_priv_dec = priv_dec; - return 1; -} - -inline int RSA_meth_set_init(RSA_METHOD *meth, int (*init)(RSA *rsa)) -{ - meth->init = init; - return 1; -} - -inline int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa)) -{ - meth->finish = finish; - return 1; -} - -inline int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) -{ - meth->app_data = (char *) app_data; - return 1; -} - -inline void *RSA_meth_get0_app_data(const RSA_METHOD *meth) -{ - return (void *) meth->app_data; -} - -inline DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) -{ - return pkey->pkey.dsa; -} - -inline void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -{ - if (p != nullptr) - *p = d->p; - - if (q != nullptr) - *q = d->q; - - if (g != nullptr) - *g = d->g; -} - -inline void RSA_set_flags(RSA *r, int flags) -{ - r->flags |= flags; -} - -inline int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) -{ - if ((rsa->n == nullptr && n == nullptr) - || (rsa->e == nullptr && e == nullptr)) - return 0; - - if (n != nullptr) - { - BN_free(rsa->n); - rsa->n = n; - } - - if (e != nullptr) - { - BN_free(rsa->e); - rsa->e = e; - } - - if (d != nullptr) - { - BN_free(rsa->d); - rsa->d = d; - } - - return 1; -} - -inline void RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -{ - if (n != nullptr) - *n = rsa->n; - - if (e != nullptr) - *e = rsa->e; - - if (d != nullptr) - *d = rsa->d; -} - -inline EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) -{ - if (pkey->type != EVP_PKEY_EC) { - return NULL; - } - return pkey->pkey.ec; -} - -inline int EC_GROUP_order_bits(const EC_GROUP *group) -{ - BIGNUM *order = BN_new(); - EC_GROUP_get_order(group, order, NULL); - int bits = BN_num_bits(order); - BN_free(order); - return bits; -} - -/* Renamed in OpenSSL 1.1 */ -#define X509_get0_pubkey X509_get_pubkey -#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT - -/* - * EVP_CIPHER_CTX_init and EVP_CIPHER_CTX_cleanup are both replaced by - * EVP_CIPHER_CTX_reset in OpenSSL 1.1 but replacing them both with - * reset is wrong for older version. The man page mention cleanup - * being officially removed and init to be an alias for reset. - * - * So we only use reset as alias for init in older versions. - * - * EVP_CIPHER_CTX_free already implicitly calls EVP_CIPHER_CTX_cleanup in - * 1.0.2, so we can avoid using the old API. - */ -#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_init -#endif - -#if OPENSSL_VERSION_NUMBER < 0x10101000L -#include <openssl/rsa.h> -#include <openssl/dsa.h> - -inline const BIGNUM *RSA_get0_n(const RSA *r) -{ - const BIGNUM *n; - RSA_get0_key(r, &n, nullptr, nullptr); - return n; -} - -inline const BIGNUM *RSA_get0_e(const RSA *r) -{ - const BIGNUM *e; - RSA_get0_key(r, nullptr, &e, nullptr); - return e; -} - -inline const BIGNUM *DSA_get0_p(const DSA *d) -{ - const BIGNUM *p; - DSA_get0_pqg(d, &p, nullptr, nullptr); - return p; -} - -inline int SSL_CTX_set1_groups(SSL_CTX *ctx, int *glist, int glistlen) -{ - return SSL_CTX_set1_curves(ctx, glist, glistlen); -} -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/crypto/api.hpp b/Sources/OpenVPN3/openvpn/openssl/crypto/api.hpp deleted file mode 100644 index de84e67..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/crypto/api.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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_OPENSSL_CRYPTO_API_H -#define OPENVPN_OPENSSL_CRYPTO_API_H - -#include <openvpn/openssl/crypto/cipher.hpp> -#include <openvpn/openssl/crypto/cipheraead.hpp> -#include <openvpn/openssl/crypto/digest.hpp> -#include <openvpn/openssl/crypto/hmac.hpp> - -namespace openvpn { - - // type container for OpenSSL Crypto-level API - struct OpenSSLCryptoAPI { - // cipher - typedef OpenSSLCrypto::CipherContext CipherContext; - typedef OpenSSLCrypto::CipherContextAEAD CipherContextAEAD; - - // digest - typedef OpenSSLCrypto::DigestContext DigestContext; - - // HMAC - typedef OpenSSLCrypto::HMACContext HMACContext; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/crypto/cipher.hpp b/Sources/OpenVPN3/openvpn/openssl/crypto/cipher.hpp deleted file mode 100644 index bb5ee1e..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/crypto/cipher.hpp +++ /dev/null @@ -1,193 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL cipher API defined in <openssl/evp.h> so -// that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_OPENSSL_CRYPTO_CIPHER_H -#define OPENVPN_OPENSSL_CRYPTO_CIPHER_H - -#include <string> - -#include <openssl/objects.h> -#include <openssl/evp.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/openssl/util/error.hpp> -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - namespace OpenSSLCrypto { - class CipherContext - { - CipherContext(const CipherContext&) = delete; - CipherContext& operator=(const CipherContext&) = delete; - - public: - OPENVPN_SIMPLE_EXCEPTION(openssl_cipher_mode_error); - OPENVPN_SIMPLE_EXCEPTION(openssl_cipher_uninitialized); - OPENVPN_EXCEPTION(openssl_cipher_error); - - // mode parameter for constructor - enum { - MODE_UNDEF = -1, - ENCRYPT = 1, - DECRYPT = 0 - }; - - // OpenSSL cipher constants - enum { - MAX_IV_LENGTH = EVP_MAX_IV_LENGTH, - CIPH_CBC_MODE = EVP_CIPH_CBC_MODE - }; - - CipherContext() = default; - - ~CipherContext() { free_cipher_context() ; } - - void init(const CryptoAlgs::Type alg, const unsigned char *key, const int mode) - { - // check that mode is valid - if (!(mode == ENCRYPT || mode == DECRYPT)) - throw openssl_cipher_mode_error(); - free_cipher_context(); - ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_reset (ctx); - if (!EVP_CipherInit_ex (ctx, cipher_type(alg), nullptr, key, nullptr, mode)) - { - openssl_clear_error_stack(); - free_cipher_context(); - throw openssl_cipher_error("EVP_CipherInit_ex (init)"); - } - } - - void reset(const unsigned char *iv) - { - check_initialized(); - if (!EVP_CipherInit_ex (ctx, nullptr, nullptr, nullptr, iv, -1)) - { - openssl_clear_error_stack(); - throw openssl_cipher_error("EVP_CipherInit_ex (reset)"); - } - } - - bool update(unsigned char *out, const size_t max_out_size, - const unsigned char *in, const size_t in_size, - size_t& out_acc) - { - check_initialized(); - int outlen; - if (EVP_CipherUpdate (ctx, out, &outlen, in, int(in_size))) - { - out_acc += outlen; - return true; - } - else - { - openssl_clear_error_stack(); - return false; - } - } - - bool final(unsigned char *out, const size_t max_out_size, size_t& out_acc) - { - check_initialized(); - int outlen; - if (EVP_CipherFinal_ex (ctx, out, &outlen)) - { - out_acc += outlen; - return true; - } - else - { - openssl_clear_error_stack(); - return false; - } - } - - bool is_initialized() const { return ctx != nullptr; } - - size_t iv_length() const - { - check_initialized(); - return EVP_CIPHER_CTX_iv_length (ctx); - } - - size_t block_size() const - { - check_initialized(); - return EVP_CIPHER_CTX_block_size (ctx); - } - - // return cipher mode (such as CIPH_CBC_MODE, etc.) - int cipher_mode() const - { - check_initialized(); - return EVP_CIPHER_CTX_mode (ctx); - } - - private: - static const EVP_CIPHER *cipher_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::AES_128_CBC: - return EVP_aes_128_cbc(); - case CryptoAlgs::AES_192_CBC: - return EVP_aes_192_cbc(); - case CryptoAlgs::AES_256_CBC: - return EVP_aes_256_cbc(); - case CryptoAlgs::AES_256_CTR: - return EVP_aes_256_ctr(); - case CryptoAlgs::DES_CBC: - return EVP_des_cbc(); - case CryptoAlgs::DES_EDE3_CBC: - return EVP_des_ede3_cbc(); - case CryptoAlgs::BF_CBC: - return EVP_bf_cbc(); - default: - OPENVPN_THROW(openssl_cipher_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - - void free_cipher_context() - { - EVP_CIPHER_CTX_free(ctx); - ctx = nullptr; - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (ctx == nullptr) - throw openssl_cipher_uninitialized(); -#endif - } - - EVP_CIPHER_CTX* ctx = nullptr; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/crypto/cipheraead.hpp b/Sources/OpenVPN3/openvpn/openssl/crypto/cipheraead.hpp deleted file mode 100644 index 29af6b6..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/crypto/cipheraead.hpp +++ /dev/null @@ -1,255 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL GCM API. - -#pragma once - -#include <string> - -#include <openssl/objects.h> -#include <openssl/evp.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/openssl/util/error.hpp> - -namespace openvpn { - namespace OpenSSLCrypto { - class CipherContextAEAD - { - public: - CipherContextAEAD(const CipherContextAEAD&) = delete; - CipherContextAEAD& operator=(const CipherContextAEAD&) = delete; - - OPENVPN_EXCEPTION(openssl_gcm_error); - - // mode parameter for constructor - enum { - MODE_UNDEF = -1, - ENCRYPT = 1, - DECRYPT = 0 - }; - - // OpenSSL cipher constants - enum { - IV_LEN = 12, - AUTH_TAG_LEN = 16, - SUPPORTS_IN_PLACE_ENCRYPT = 0, - }; - - CipherContextAEAD() = default; - - ~CipherContextAEAD() { free_cipher_context(); } - - void init(const CryptoAlgs::Type alg, - const unsigned char *key, - const unsigned int keysize, - const int mode) - { - free_cipher_context(); - unsigned int ckeysz = 0; - const EVP_CIPHER *ciph = cipher_type(alg, ckeysz); - - if (ciph == nullptr) - OPENVPN_THROW(openssl_gcm_error, CryptoAlgs::name(alg) << ": not usable"); - - if (ckeysz > keysize) - throw openssl_gcm_error("insufficient key material"); - ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_reset(ctx); - switch (mode) - { - case ENCRYPT: - if (!EVP_EncryptInit_ex(ctx, ciph, nullptr, key, nullptr)) - { - openssl_clear_error_stack(); - free_cipher_context(); - throw openssl_gcm_error("EVP_EncryptInit_ex (init)"); - } - break; - case DECRYPT: - if (!EVP_DecryptInit_ex(ctx, ciph, nullptr, key, nullptr)) - { - openssl_clear_error_stack(); - free_cipher_context(); - throw openssl_gcm_error("EVP_DecryptInit_ex (init)"); - } - break; - default: - throw openssl_gcm_error("bad mode"); - } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IV_LEN, nullptr) != 1) - { - openssl_clear_error_stack(); - free_cipher_context(); - throw openssl_gcm_error("EVP_CIPHER_CTX_ctrl set IV len"); - } - } - - void encrypt(const unsigned char *input, - unsigned char *output, - size_t length, - const unsigned char *iv, - unsigned char *tag, - const unsigned char *ad, - size_t ad_len) - { - int len; - int ciphertext_len; - - check_initialized(); - if (!EVP_EncryptInit_ex(ctx, nullptr, nullptr, nullptr, iv)) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_EncryptInit_ex (reset)"); - } - if (!EVP_EncryptUpdate(ctx, nullptr, &len, ad, int(ad_len))) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_EncryptUpdate AD"); - } - if (!EVP_EncryptUpdate(ctx, output, &len, input, int(length))) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_EncryptUpdate data"); - } - ciphertext_len = len; - if (!EVP_EncryptFinal_ex(ctx, output+len, &len)) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_EncryptFinal_ex"); - } - ciphertext_len += len; - if ((size_t) ciphertext_len != length) - { - throw openssl_gcm_error("encrypt size inconsistency"); - } - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AUTH_TAG_LEN, tag)) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_CIPHER_CTX_ctrl get tag"); - } - } - - bool decrypt(const unsigned char *input, - unsigned char *output, - size_t length, - const unsigned char *iv, - unsigned char *tag, - const unsigned char *ad, - size_t ad_len) - { - int len; - int plaintext_len; - - check_initialized(); - if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, nullptr, iv)) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_DecryptInit_ex (reset)"); - } - if (!EVP_DecryptUpdate(ctx, nullptr, &len, ad, int(ad_len))) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_DecryptUpdate AD"); - } - if (!EVP_DecryptUpdate(ctx, output, &len, input, int(length))) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_DecryptUpdate data"); - } - plaintext_len = len; - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AUTH_TAG_LEN, tag)) - { - openssl_clear_error_stack(); - throw openssl_gcm_error("EVP_CIPHER_CTX_ctrl set tag"); - } - if (!EVP_DecryptFinal_ex(ctx, output+len, &len)) - { - openssl_clear_error_stack(); - return false; - } - plaintext_len += len; - if (static_cast<size_t>(plaintext_len) != length) - { - throw openssl_gcm_error("decrypt size inconsistency"); - } - return true; - } - - bool is_initialized() const { return ctx != nullptr; } - - static bool is_supported(const CryptoAlgs::Type alg) - { - unsigned int keysize; - return (cipher_type(alg, keysize) != nullptr); - } - - - private: - static const EVP_CIPHER *cipher_type(const CryptoAlgs::Type alg, - unsigned int& keysize) - { - switch (alg) - { - case CryptoAlgs::AES_128_GCM: - keysize = 16; - return EVP_aes_128_gcm(); - case CryptoAlgs::AES_192_GCM: - keysize = 24; - return EVP_aes_192_gcm(); - case CryptoAlgs::AES_256_GCM: - keysize = 32; - return EVP_aes_256_gcm(); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_POLY1305) && !defined(OPENSSL_NO_CHACHA) - case CryptoAlgs::CHACHA20_POLY1305: - keysize = 32; - return EVP_chacha20_poly1305(); -#endif - default: - keysize = 0; - return nullptr; - } - } - - void free_cipher_context() - { - EVP_CIPHER_CTX_free(ctx); - ctx = nullptr; - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!ctx) - throw openssl_gcm_error("uninitialized"); -#endif - } - - EVP_CIPHER_CTX *ctx = nullptr; - }; - } -} - diff --git a/Sources/OpenVPN3/openvpn/openssl/crypto/digest.hpp b/Sources/OpenVPN3/openvpn/openssl/crypto/digest.hpp deleted file mode 100644 index 56516ff..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/crypto/digest.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL digest API defined in <openssl/evp.h> -// so that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_OPENSSL_CRYPTO_DIGEST_H -#define OPENVPN_OPENSSL_CRYPTO_DIGEST_H - -#include <string> - -#include <openssl/objects.h> -#include <openssl/evp.h> -#include <openssl/md4.h> -#include <openssl/md5.h> -#include <openssl/sha.h> -#include <openssl/hmac.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/openssl/util/error.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - namespace OpenSSLCrypto { - class HMACContext; - - class DigestContext - { - DigestContext(const DigestContext&) = delete; - DigestContext& operator=(const DigestContext&) = delete; - - public: - friend class HMACContext; - - OPENVPN_SIMPLE_EXCEPTION(openssl_digest_uninitialized); - OPENVPN_EXCEPTION(openssl_digest_error); - - enum { - MAX_DIGEST_SIZE = EVP_MAX_MD_SIZE - }; - - DigestContext() - : initialized(false) - { - } - - DigestContext(const CryptoAlgs::Type alg) - : initialized(false) - { - init(alg); - } - - ~DigestContext() { erase() ; } - - void init(const CryptoAlgs::Type alg) - { - erase(); - ctx=EVP_MD_CTX_new (); - if (!EVP_DigestInit(ctx, digest_type(alg))) - { - openssl_clear_error_stack(); - throw openssl_digest_error("EVP_DigestInit"); - } - initialized = true; - } - - void update(const unsigned char *in, const size_t size) - { - check_initialized(); - if (!EVP_DigestUpdate(ctx, in, int(size))) - { - openssl_clear_error_stack(); - throw openssl_digest_error("EVP_DigestUpdate"); - } - } - - size_t final(unsigned char *out) - { - check_initialized(); - unsigned int outlen; - if (!EVP_DigestFinal(ctx, out, &outlen)) - { - openssl_clear_error_stack(); - throw openssl_digest_error("EVP_DigestFinal"); - } - return outlen; - } - - size_t size() const - { - check_initialized(); - return EVP_MD_CTX_size(ctx); - } - - bool is_initialized() const { return initialized; } - - private: - static const EVP_MD *digest_type(const CryptoAlgs::Type alg) - { - switch (alg) - { - case CryptoAlgs::MD4: - return EVP_md4(); - case CryptoAlgs::MD5: - return EVP_md5(); - case CryptoAlgs::SHA1: - return EVP_sha1(); - case CryptoAlgs::SHA224: - return EVP_sha224(); - case CryptoAlgs::SHA256: - return EVP_sha256(); - case CryptoAlgs::SHA384: - return EVP_sha384(); - case CryptoAlgs::SHA512: - return EVP_sha512(); - default: - OPENVPN_THROW(openssl_digest_error, CryptoAlgs::name(alg) << ": not usable"); - } - } - - void erase() - { - if (initialized) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_MD_CTX_cleanup(ctx); -#endif - EVP_MD_CTX_free(ctx); - initialized = false; - } - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!initialized) - throw openssl_digest_uninitialized(); -#endif - } - - bool initialized; - EVP_MD_CTX *ctx; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/crypto/hmac.hpp b/Sources/OpenVPN3/openvpn/openssl/crypto/hmac.hpp deleted file mode 100644 index 6c3ad8d..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/crypto/hmac.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL HMAC API defined in <openssl/hmac.h> so -// that it can be used as part of the crypto layer of the OpenVPN core. - -#ifndef OPENVPN_OPENSSL_CRYPTO_HMAC_H -#define OPENVPN_OPENSSL_CRYPTO_HMAC_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/crypto/digest.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - namespace OpenSSLCrypto { - class HMACContext - { - HMACContext(const HMACContext&) = delete; - HMACContext& operator=(const HMACContext&) = delete; - - public: - OPENVPN_SIMPLE_EXCEPTION(openssl_hmac_uninitialized); - OPENVPN_EXCEPTION(openssl_hmac_error); - - enum { - MAX_HMAC_SIZE = EVP_MAX_MD_SIZE - }; - - HMACContext() = default; - - HMACContext(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - { - init(digest, key, key_size); - } - - ~HMACContext() { erase() ; } - - void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size) - { - erase(); - ctx = HMAC_CTX_new (); - if (!HMAC_Init_ex (ctx, key, int(key_size), DigestContext::digest_type(digest), nullptr)) - { - openssl_clear_error_stack(); - HMAC_CTX_free(ctx); - ctx = nullptr; - throw openssl_hmac_error("HMAC_Init_ex (init)"); - } - } - - void reset() - { - check_initialized(); - if (!HMAC_Init_ex (ctx, nullptr, 0, nullptr, nullptr)) - { - openssl_clear_error_stack(); - throw openssl_hmac_error("HMAC_Init_ex (reset)"); - } - } - - void update(const unsigned char *in, const size_t size) - { - check_initialized(); - - if (!HMAC_Update(ctx, in, int(size))) - { - openssl_clear_error_stack(); - throw openssl_hmac_error("HMAC_Update"); - } - } - - size_t final(unsigned char *out) - { - check_initialized(); - unsigned int outlen; - if (!HMAC_Final(ctx, out, &outlen)) - { - openssl_clear_error_stack(); - throw openssl_hmac_error("HMAC_Final"); - } - return outlen; - } - - size_t size() const - { - check_initialized(); - return size_(); - } - - bool is_initialized() const { return ctx != nullptr; } - - private: - void erase() - { - HMAC_CTX_free(ctx); - ctx = nullptr; - } - - size_t size_() const - { - return HMAC_size(ctx); - } - - void check_initialized() const - { -#ifdef OPENVPN_ENABLE_ASSERT - if (!ctx) - throw openssl_hmac_uninitialized(); -#endif - } - - HMAC_CTX* ctx = nullptr; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/crl.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/crl.hpp deleted file mode 100644 index 33983b3..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/crl.hpp +++ /dev/null @@ -1,169 +0,0 @@ -// 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-2020 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/>. - -// Wrap an OpenSSL X509_CRL object - -#pragma once - -#include <string> -#include <vector> - -#include <openssl/ssl.h> -#include <openssl/bio.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/util/error.hpp> - -namespace openvpn { - namespace OpenSSLPKI { - - class CRL - { - public: - CRL() - : crl_(nullptr) - { - } - - explicit CRL(const std::string& crl_txt) - : crl_(nullptr) - { - parse_pem(crl_txt); - } - - CRL(const CRL& other) - : crl_(dup(other.crl_)) - { - } - - CRL(CRL&& other) noexcept - : crl_(other.crl_) - { - other.crl_ = nullptr; - } - - CRL& operator=(const CRL& other) - { - if (this != &other) - { - erase(); - crl_ = dup(other.crl_); - } - return *this; - } - - CRL& operator=(CRL&& other) noexcept - { - if (this != &other) - { - erase(); - crl_ = other.crl_; - other.crl_ = nullptr; - } - return *this; - } - - bool defined() const { return crl_ != nullptr; } - ::X509_CRL* obj() const { return crl_; } - - void parse_pem(const std::string& crl_txt) - { - BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(crl_txt.c_str()), crl_txt.length()); - if (!bio) - throw OpenSSLException(); - - ::X509_CRL *crl = ::PEM_read_bio_X509_CRL(bio, nullptr, nullptr, nullptr); - ::BIO_free(bio); - if (!crl) - throw OpenSSLException("CRL::parse_pem"); - - erase(); - crl_ = crl; - } - - std::string render_pem() const - { - if (crl_) - { - BIO *bio = ::BIO_new(BIO_s_mem()); - const int ret = ::PEM_write_bio_X509_CRL(bio, crl_); - if (ret == 0) - { - ::BIO_free(bio); - throw OpenSSLException("CRL::render_pem"); - } - - { - char *temp; - const int buf_len = ::BIO_get_mem_data(bio, &temp); - std::string ret = std::string(temp, buf_len); - ::BIO_free(bio); - return ret; - } - } - else - return ""; - } - - ~CRL() - { - erase(); - } - - private: - void erase() - { - if (crl_) - ::X509_CRL_free(crl_); - } - - static X509_CRL *dup(const X509_CRL *crl) - { - if (crl) - return ::X509_CRL_dup(const_cast<X509_CRL *>(crl)); - else - return nullptr; - } - - ::X509_CRL *crl_; - }; - - class CRLList : public std::vector<CRL> - { - public: - typedef X509 CRL; - - bool defined() const - { - return !empty(); - } - - std::string render_pem() const - { - std::string ret; - for (const auto &e : *this) - ret += e.render_pem(); - return ret; - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/dh.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/dh.hpp deleted file mode 100644 index d14680b..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/dh.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// 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-2020 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/>. - -// Wrap an OpenSSL DH object - -#pragma once - -#include <string> - -#include <openssl/ssl.h> -#include <openssl/bio.h> -#include <openssl/dh.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/util/error.hpp> - -// workaround for bug in DHparams_dup macro on OpenSSL 0.9.8 and lower -#if SSLEAY_VERSION_NUMBER <= 0x00908000L -#undef CHECKED_PTR_OF -#define CHECKED_PTR_OF(type, p) ((char*) (1 ? p : (type*)0)) -#endif - -namespace openvpn { - namespace OpenSSLPKI { - - namespace DH_private { - // defined outside of DH class to avoid symbol collision in way - // that DHparams_dup macro is defined - inline ::DH *dup(const ::DH *dh) - { - if (dh) - return DHparams_dup(const_cast< ::DH * >(dh)); - else - return nullptr; - } - } - - class DH - { - public: - DH() - : dh_(nullptr) - { - } - - explicit DH(const std::string& dh_txt) - : dh_(nullptr) - { - parse_pem(dh_txt); - } - - DH(const DH& other) - { - dup(other.dh_); - } - - DH(DH&& other) noexcept - : dh_(other.dh_) - { - other.dh_ = nullptr; - } - - void operator=(const DH& other) - { - if (this != &other) - { - erase(); - dup(other.dh_); - } - } - - DH& operator=(DH&& other) noexcept - { - if (this != &other) - { - erase(); - dh_ = other.dh_; - other.dh_ = nullptr; - } - return *this; - } - - bool defined() const { return dh_ != nullptr; } - ::DH* obj() const { return dh_; } - - void parse_pem(const std::string& dh_txt) - { - BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(dh_txt.c_str()), dh_txt.length()); - if (!bio) - throw OpenSSLException(); - - ::DH *dh = ::PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); - ::BIO_free(bio); - if (!dh) - throw OpenSSLException("DH::parse_pem"); - - erase(); - dh_ = dh; - } - - std::string render_pem() const - { - if (dh_) - { - BIO *bio = ::BIO_new(BIO_s_mem()); - const int ret = ::PEM_write_bio_DHparams(bio, dh_); - if (ret == 0) - { - ::BIO_free(bio); - throw OpenSSLException("DH::render_pem"); - } - - { - char *temp; - const int buf_len = ::BIO_get_mem_data(bio, &temp); - std::string ret = std::string(temp, buf_len); - ::BIO_free(bio); - return ret; - } - } - else - return ""; - } - - ~DH() - { - erase(); - } - - private: - void erase() - { - if (dh_) - ::DH_free(dh_); - } - - void dup(const ::DH *dh) - { - dh_ = DH_private::dup(dh); - } - - ::DH *dh_; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/extpki.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/extpki.hpp deleted file mode 100644 index 9bc220e..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/extpki.hpp +++ /dev/null @@ -1,413 +0,0 @@ -// 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-2020 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 <openssl/rsa.h> -#include <openssl/evp.h> - -#include <openssl/ec.h> -#include <openssl/ecdsa.h> - -#include <openvpn/pki/epkibase.hpp> -#include <openvpn/ssl/sslapi.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - using ssl_external_pki = SSLFactoryAPI::ssl_external_pki; - - class ExternalPKIImpl - { - public: - virtual ~ExternalPKIImpl() = default; - }; - - class ExternalPKIRsaImpl : public ExternalPKIImpl - { - public: - ExternalPKIRsaImpl(SSL_CTX* ssl_ctx, ::X509* cert, ExternalPKIBase* external_pki_arg) - : external_pki(external_pki_arg), n_errors(0) - { - RSA* rsa = nullptr; - RSA* pub_rsa = nullptr; - RSA_METHOD* rsa_meth = nullptr; - const char* errtext = ""; - - /* allocate custom RSA method object */ - rsa_meth = RSA_meth_new("OpenSSLContext::ExternalPKIRsaImpl private key RSA Method", RSA_METHOD_FLAG_NO_CHECK); - - RSA_meth_set_pub_enc(rsa_meth, rsa_pub_enc); - RSA_meth_set_pub_dec(rsa_meth, rsa_pub_dec); - RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc); - RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec); - RSA_meth_set_init(rsa_meth, nullptr); - RSA_meth_set_finish(rsa_meth, rsa_finish); - RSA_meth_set0_app_data(rsa_meth, this); - - - /* get the public key */ - if (X509_get0_pubkey(cert) == nullptr) /* nullptr before SSL_CTX_use_certificate() is called */ - { - errtext = "pkey is NULL"; - goto err; - } - - if (EVP_PKEY_id(X509_get0_pubkey(cert)) != EVP_PKEY_RSA) - { - errtext = "pkey is not RSA"; - goto err; - } - pub_rsa = EVP_PKEY_get0_RSA(X509_get0_pubkey(cert)); - - /* allocate RSA object */ - rsa = RSA_new(); - if (rsa == nullptr) - { - SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE); - errtext = "RSA_new"; - goto err; - } - - /* only set e and n as d (private key) is outside our control */ - RSA_set0_key(rsa, BN_dup(RSA_get0_n(pub_rsa)), BN_dup(RSA_get0_e(pub_rsa)), nullptr); - RSA_set_flags(rsa, RSA_FLAG_EXT_PKEY); - - if (!RSA_set_method(rsa, rsa_meth)) - { - errtext = "RSA_set_method"; - goto err; - } - /* rsa_meth will be freed when rsa is freed from this point, - * set pointer to nullptr so the err does not try to free it - */ - rsa_meth = nullptr; - - /* bind our custom RSA object to ssl_ctx */ - if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa)) - { - errtext = "SSL_CTX_use_RSAPrivateKey"; - goto err; - } - - RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */ - return; - - err: - RSA_free(rsa); - RSA_meth_free(rsa_meth); - - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::ExternalPKIRsaImpl: " << errtext); - } - - ~ExternalPKIRsaImpl() override = default; - - unsigned int get_n_errors() const - { return n_errors; } - - private: - /* called at RSA_free */ - static int rsa_finish(RSA* rsa) - { - RSA_meth_free(const_cast<RSA_METHOD*>(RSA_get_method(rsa))); - return 1; - } - - /* sign arbitrary data */ - static int - rsa_priv_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, int padding) - { - ExternalPKIRsaImpl* self = (ExternalPKIRsaImpl*) (RSA_meth_get0_app_data(RSA_get_method(rsa))); - - try - { - if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING) - { - RSAerr (RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); - throw ssl_external_pki("OpenSSL: bad padding type"); - } - std::string padding_algo; - if (padding == RSA_PKCS1_PADDING) - { - padding_algo = "RSA_PKCS1_PADDING"; - } - else if (padding == RSA_NO_PADDING) - { - padding_algo = "RSA_NO_PADDING"; - } - - /* convert 'from' to base64 */ - ConstBuffer from_buf(from, flen, true); - const std::string from_b64 = base64->encode(from_buf); - - /* get signature */ - std::string sig_b64; - const bool status = self->external_pki->sign(from_b64, sig_b64, padding_algo); - if (!status) - throw ssl_external_pki("OpenSSL: could not obtain signature"); - - /* decode base64 signature to binary */ - const int len = RSA_size(rsa); - Buffer sig(to, len, false); - base64->decode(sig, sig_b64); - - /* verify length */ - if (sig.size() != static_cast<size_t>(len)) - throw ssl_external_pki("OpenSSL: incorrect signature length"); - - /* return length of signature */ - return len; - } - catch (const std::exception& e) - { - OPENVPN_LOG("OpenSSLContext::ExternalPKIRsaImpl::rsa_priv_enc exception: " << e.what()); - ++self->n_errors; - return -1; - } - } - - static void not_implemented(RSA* rsa) - { - ExternalPKIRsaImpl* self = (ExternalPKIRsaImpl*) (RSA_meth_get0_app_data(RSA_get_method(rsa))); - ++self->n_errors; - } - - /* encrypt */ - static int - rsa_pub_enc(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, int padding) - { - not_implemented(rsa); - return -1; - } - - /* verify arbitrary data */ - static int - rsa_pub_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, int padding) - { - not_implemented(rsa); - return -1; - } - - /* decrypt */ - static int - rsa_priv_dec(int flen, const unsigned char* from, unsigned char* to, RSA* rsa, int padding) - { - not_implemented(rsa); - return -1; - } - - ExternalPKIBase* external_pki; - unsigned int n_errors; - }; - - /* The OpenSSL EC_* methods we are using here are only available for OpennSSL 1.1.0 and later */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_EC) - class ExternalPKIECImpl : public ExternalPKIImpl - { - - public: - ExternalPKIECImpl(SSL_CTX* ssl_ctx, ::X509* cert, ExternalPKIBase* external_pki_arg) - : external_pki(external_pki_arg) - { - - if (ec_self_data_index < 0) - throw ssl_external_pki("ExternalPKIECImpl::ec_self_data_index is uninitialized"); - - std::string errtext; - - EVP_PKEY* privkey = nullptr; - EC_KEY* ec = nullptr; - EC_KEY_METHOD* ec_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); - - /* we only need to override a small number of methods */ - EC_KEY_METHOD_set_init(ec_method, NULL, ec_finish, NULL, NULL, NULL, NULL); - EC_KEY_METHOD_set_sign(ec_method, ecdsa_sign, ecdsa_sign_setup, ecdsa_sign_sig); - - /* get the public key */ - EVP_PKEY* pubkey = X509_get0_pubkey(cert); - - if (pubkey == nullptr) /* nullptr before SSL_CTX_use_certificate() is called */ - { - errtext = "public key is NULL"; - goto err; - } - - if (EVP_PKEY_id(pubkey) != EVP_PKEY_EC) - { - errtext = "public key is not EC"; - goto err; - } - - ec = EC_KEY_dup(static_cast<const EC_KEY*>(EVP_PKEY_get0(pubkey))); - - /* This will move responsibility to free ec_method to ec */ - if (!EC_KEY_set_method(ec, ec_method)) - { - errtext = "Could not set EC method"; - EC_KEY_METHOD_free(ec_method); - goto err; - } - - if (!EC_KEY_set_ex_data(ec, ec_self_data_index, this)) - { - errtext = "Could not set EC Key ex data"; - EC_KEY_METHOD_free(ec_method); - goto err; - } - - privkey = EVP_PKEY_new(); - if (!EVP_PKEY_assign_EC_KEY(privkey, ec)) - { - errtext = "assigning EC key methods failed"; - goto err; - } - - if (!SSL_CTX_use_PrivateKey(ssl_ctx, privkey)) - { - errtext = "assigning EC private key to SSL context failed"; - goto err; - } - - EVP_PKEY_free(privkey); /* release ref to privkey and ec */ - - return; - - err: - if (privkey) - { - EVP_PKEY_free(privkey); - } - else - { - EC_KEY_free(ec); - } - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::ExternalPKIECImpl: " << errtext); - } - - ~ExternalPKIECImpl() override = default; - - static void init_static() - { - ec_self_data_index = EC_KEY_get_ex_new_index(0, (char*) "ExternalPKIECImpl", nullptr, nullptr, nullptr); - } - - private: - static void ec_finish(EC_KEY* ec) - { - EC_KEY_METHOD_free(const_cast<EC_KEY_METHOD*>(EC_KEY_get_method(ec))); - } - - /* sign arbitrary data */ - static int - ecdsa_sign(int type, const unsigned char* dgst, - int dlen, unsigned char* sig, - unsigned int* siglen, - const BIGNUM* kinv, const BIGNUM* r, - EC_KEY* eckey) - { - ExternalPKIECImpl* self = (ExternalPKIECImpl*) (EC_KEY_get_ex_data(eckey, ec_self_data_index)); - - try - { - *siglen = ECDSA_size(eckey); - self->do_sign(dgst, dlen, sig, *siglen); - /* No error */ - return 1; - } - catch (const std::exception& e) - { - OPENVPN_LOG("OpenSSLContext::ExternalPKIECImpl::ecdsa_sign exception: " << e.what()); - return 0; - } - } - - static int ecdsa_sign_setup(EC_KEY* eckey, BN_CTX* ctx_in, BIGNUM** kinvp, BIGNUM** rp) - { - /* No precomputation, return success */ - return 1; - } - - static ECDSA_SIG* - ecdsa_sign_sig(const unsigned char* dgst, int dgstlen, const BIGNUM* kinvp, - const BIGNUM* rp, EC_KEY* eckey) - { - ExternalPKIECImpl* self = (ExternalPKIECImpl*) (EC_KEY_get_ex_data(eckey, ec_self_data_index)); - - unsigned len = ECDSA_size(eckey); - - auto sig = new unsigned char[len]; - - ECDSA_SIG* ecsig = nullptr; - try - { - unsigned int siglen = len; - self->do_sign(dgst, dgstlen, sig, siglen); - - ecsig = d2i_ECDSA_SIG(NULL, (const unsigned char**) &sig, siglen); - } - catch (const std::exception& e) - { - OPENVPN_LOG("OpenSSLContext::ExternalPKIECImpl::ecdsa_sign_sig exception: " << e.what()); - } - - delete[] sig; - return ecsig; - } - - /** - * Sign the input via external pki callback - * - * @param dgst digest to be signed - * @param dlen length of the digest to be signed - * @param sig buffer backing the signature - * @param siglen maximum size for the signature, and length of the signature - * returned in sig - * @return - */ - void do_sign(const unsigned char* dgst, int dlen, - unsigned char* sig, unsigned int& siglen) - { - /* convert 'dgst' to base64 */ - ConstBuffer dgst_buf(dgst, dlen, true); - const std::string dgst_b64 = base64->encode(dgst_buf); - - /* get signature */ - std::string sig_b64; - const bool status = external_pki->sign(dgst_b64, sig_b64, "ECDSA"); - if (!status) - throw ssl_external_pki("OpenSSL: could not obtain signature"); - - /* decode base64 signature to binary */ - Buffer sigout(sig, siglen, false); - base64->decode(sigout, sig_b64); - - siglen = sigout.size(); - } - - ExternalPKIBase* external_pki; - static int ec_self_data_index; - }; - -#ifdef OPENVPN_NO_EXTERN - int ExternalPKIECImpl::ec_self_data_index = -1; -#endif -#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_EC) */ -} diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/pkey.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/pkey.hpp deleted file mode 100644 index c5bd691..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/pkey.hpp +++ /dev/null @@ -1,214 +0,0 @@ -// 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-2020 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/>. - -// Wrap an OpenSSL EVP_PKEY object - -#pragma once - -#include <string> -#include <utility> - -#include <openssl/ssl.h> -#include <openssl/bio.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/util/error.hpp> -#include <openvpn/pki/pktype.hpp> - -namespace openvpn { - namespace OpenSSLPKI { - - class PKey - { - public: - PKey() - : pkey_(nullptr) - { - } - - PKey(const std::string& pkey_txt, const std::string& title) - : pkey_(nullptr) - { - parse_pem(pkey_txt, title); - } - - PKey(const PKey& other) - : pkey_(dup(other.pkey_)), - priv_key_pwd(other.priv_key_pwd) - { - } - - PKey(PKey&& other) noexcept - : pkey_(other.pkey_), - priv_key_pwd(std::move(other.priv_key_pwd)) - { - other.pkey_ = nullptr; - } - - PKey& operator=(const PKey& other) - { - if (this != &other) - { - erase(); - pkey_ = dup(other.pkey_); - priv_key_pwd = other.priv_key_pwd; - } - return *this; - } - - PKey& operator=(PKey&& other) noexcept - { - if (this != &other) - { - erase(); - pkey_ = other.pkey_; - other.pkey_ = nullptr; - priv_key_pwd = std::move(other.priv_key_pwd); - } - return *this; - } - - bool defined() const { return pkey_ != nullptr; } - ::EVP_PKEY* obj() const { return pkey_; } - - PKType::Type key_type() const - { - switch (::EVP_PKEY_id(pkey_)) - { - case EVP_PKEY_RSA: - case EVP_PKEY_RSA2: - return PKType::PK_RSA; - case EVP_PKEY_EC: - return PKType::PK_EC; - case EVP_PKEY_DSA: - case EVP_PKEY_DSA1: - case EVP_PKEY_DSA2: - case EVP_PKEY_DSA3: - case EVP_PKEY_DSA4: - return PKType::PK_DSA; - case EVP_PKEY_NONE: - return PKType::PK_NONE; - default: - return PKType::PK_UNKNOWN; - } - } - - size_t key_length() const - { - int ret = ::i2d_PrivateKey(pkey_, NULL); - if (ret < 0) - return 0; - - /* convert to bits */ - return ret * 8; - } - - void set_private_key_password(const std::string& pwd) - { - priv_key_pwd = pwd; - } - - void parse_pem(const std::string& pkey_txt, const std::string& title) - { - BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(pkey_txt.c_str()), pkey_txt.length()); - if (!bio) - throw OpenSSLException(); - - ::EVP_PKEY *pkey = ::PEM_read_bio_PrivateKey(bio, nullptr, pem_password_callback, this); - ::BIO_free(bio); - if (!pkey) - throw OpenSSLException(std::string("PKey::parse_pem: error in ") + title + std::string(":")); - - erase(); - pkey_ = pkey; - } - - std::string render_pem() const - { - if (pkey_) - { - BIO *bio = ::BIO_new(BIO_s_mem()); - const int ret = ::PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr); - if (ret == 0) - { - ::BIO_free(bio); - throw OpenSSLException("PKey::render_pem"); - } - - { - char *temp; - const int buf_len = ::BIO_get_mem_data(bio, &temp); - std::string ret = std::string(temp, buf_len); - ::BIO_free(bio); - return ret; - } - } - else - return ""; - } - - ~PKey() - { - erase(); - } - - private: - static int pem_password_callback (char *buf, int size, int rwflag, void *userdata) - { - // get this - const PKey* self = (PKey*) userdata; - if (buf) - { - string::strncpynt(buf, self->priv_key_pwd.c_str(), size); - return std::strlen(buf); - } - return 0; - } - - void erase() - { - if (pkey_) - ::EVP_PKEY_free(pkey_); - } - - static ::EVP_PKEY *dup(const ::EVP_PKEY *pkey) - { - // No OpenSSL EVP_PKEY_dup method so we roll our own - if (pkey) - { - ::EVP_PKEY* pDupKey = ::EVP_PKEY_new(); - ::RSA* pRSA = ::EVP_PKEY_get1_RSA(const_cast<::EVP_PKEY *>(pkey)); - ::RSA* pRSADupKey = ::RSAPrivateKey_dup(pRSA); - ::RSA_free(pRSA); - ::EVP_PKEY_set1_RSA(pDupKey, pRSADupKey); - ::RSA_free(pRSADupKey); - return pDupKey; - } - else - return nullptr; - } - - ::EVP_PKEY *pkey_; - std::string priv_key_pwd; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/x509.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/x509.hpp deleted file mode 100644 index 4343bc7..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/x509.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// 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-2020 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/>. - -// Wrap an OpenSSL X509 object - -#pragma once - -#include <string> -#include <vector> - -#include <openssl/ssl.h> -#include <openssl/bio.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/util/error.hpp> - -namespace openvpn { - namespace OpenSSLPKI { - - class X509 - { - public: - X509() - : x509_(nullptr) - { - } - - X509(const std::string& cert_txt, const std::string& title) - : x509_(nullptr) - { - parse_pem(cert_txt, title); - } - - explicit X509(::X509 *x509, const bool create=true) - { - if (create) - x509_ = x509; - else - x509_ = dup(x509); - } - - X509(const X509& other) - : x509_(dup(other.x509_)) - { - } - - X509(X509&& other) noexcept - : x509_(other.x509_) - { - other.x509_ = nullptr; - } - - X509& operator=(const X509& other) - { - if (this != &other) - { - erase(); - x509_ = dup(other.x509_); - } - return *this; - } - - X509& operator=(X509&& other) noexcept - { - if (this != &other) - { - erase(); - x509_ = other.x509_; - other.x509_ = nullptr; - } - return *this; - } - - bool defined() const { return x509_ != nullptr; } - ::X509* obj() const { return x509_; } - ::X509* obj_dup() const { return dup(x509_); } - - void parse_pem(const std::string& cert_txt, const std::string& title) - { - BIO *bio = ::BIO_new_mem_buf(const_cast<char *>(cert_txt.c_str()), cert_txt.length()); - if (!bio) - throw OpenSSLException(); - - ::X509 *cert = ::PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); - ::BIO_free(bio); - if (!cert) - throw OpenSSLException(std::string("X509::parse_pem: error in ") + title + std::string(":")); - - erase(); - x509_ = cert; - } - - std::string render_pem() const - { - if (x509_) - { - BIO *bio = ::BIO_new(BIO_s_mem()); - const int ret = ::PEM_write_bio_X509(bio, x509_); - if (ret == 0) - { - ::BIO_free(bio); - throw OpenSSLException("X509::render_pem"); - } - - { - char *temp; - const int buf_len = ::BIO_get_mem_data(bio, &temp); - std::string ret = std::string(temp, buf_len); - ::BIO_free(bio); - return ret; - } - } - else - return ""; - } - - ~X509() - { - erase(); - } - - private: - static ::X509 *dup(const ::X509 *x509) - { - if (x509) - return ::X509_dup(const_cast< ::X509 * >(x509)); - else - return nullptr; - } - - void erase() - { - if (x509_) - ::X509_free(x509_); - } - - ::X509 *x509_; - }; - - class X509List : public std::vector<X509> - { - public: - typedef X509 Item; - - bool defined() const - { - return !empty(); - } - - std::string render_pem() const - { - std::string ret; - for (const auto &e : *this) - ret += e.render_pem(); - return ret; - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/x509certinfo.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/x509certinfo.hpp deleted file mode 100644 index 531639e..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/x509certinfo.hpp +++ /dev/null @@ -1,208 +0,0 @@ -// 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-2020 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/>. -// -// -// Generic functions for extracting X.509 Certificate info from -// OpenSSL X509 objects - -#pragma once - -#include <cstring> -#include <string> -#include <vector> - -#include <openssl/ssl.h> -#include <openssl/bio.h> -#include <openssl/x509v3.h> -#include <openssl/x509.h> - -#include "openvpn/common/hexstr.hpp" -#include "openvpn/common/uniqueptr.hpp" - -namespace openvpn { -namespace OpenSSLPKI { - -/** - * Retrieve the complete X.509 Certificate Subject field - * - * OpenSSL supports two ways of representing the subject line. The old - * format is deprecated, but there might be code expecting this old format. - * The old format looks like this: - * - * /C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server/emailAddress=me@myhost.mydomain - * - * The new format is UTF-8 compliant and has a different formatting scheme: - * - * C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, - *emailAddress=me@myhost.mydomain - * - * - * @param cert Pointer to a native OpenSSL X509 object containing the - * certificate - * @param new_format (optional, default: false) Which format to use, - * true indicates the new format - * - * @return Returns a std::string containing the complete certificate subject. - * If it was not possible to retrieve the subject, and empty string - * is returned. - */ -static std::string x509_get_subject(::X509 *cert, bool new_format = false) { - if (!new_format) { - unique_ptr_del<char> subject( - X509_NAME_oneline(X509_get_subject_name(cert), nullptr, 0), - [](char *p) { OPENSSL_free(p); }); - if (subject) - return std::string(subject.get()); - else - return std::string(""); - } - - unique_ptr_del<BIO> subject_bio(BIO_new(BIO_s_mem()), - [](BIO *p) { BIO_free(p); }); - if (subject_bio == nullptr) { - return std::string(""); - } - - X509_NAME_print_ex(subject_bio.get(), X509_get_subject_name(cert), 0, - XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN | - ASN1_STRFLGS_UTF8_CONVERT | ASN1_STRFLGS_ESC_CTRL); - if (BIO_eof(subject_bio.get())) { - return std::string(""); - } - - BUF_MEM *subject_mem = nullptr; - BIO_get_mem_ptr(subject_bio.get(), &subject_mem); - return std::string(subject_mem->data, - subject_mem->data + subject_mem->length); -} - -/** - * Retrives the algorithm used to sign a X509 certificate - * @param cert OpenSSL certificate - * @return - */ -static const std::string x509_get_signature_algorithm(const ::X509* cert) -{ - int nid = X509_get_signature_nid(cert); - const char *sig = OBJ_nid2sn(nid); - - if (sig) - { - return sig; - } - else - return "(error getting signature algorithm)"; -} - -/** - * Retrieves a specific portion of the X.509 Certificate subject field - * - * @param cert Pointer to a native OpenSSL X509 object containing the - * certificate - * @param nid Subject name ID to retrieve. See openssl/obj_mac.h for - * list of valid NID_* references. - * - * @return Returns the contents of the extracted field on success. The - * resulting string may be empty if the extraction failed or the field - * is empty. - */ -static std::string x509_get_field(::X509 *cert, const int nid) { - static const char nullc = '\0'; - std::string ret; - X509_NAME *x509_name = X509_get_subject_name(cert); - int i = X509_NAME_get_index_by_NID(x509_name, nid, -1); - if (i >= 0) { - X509_NAME_ENTRY *ent = X509_NAME_get_entry(x509_name, i); - if (ent) { - ASN1_STRING *val = X509_NAME_ENTRY_get_data(ent); - unsigned char *buf; - buf = (unsigned char *)1; // bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 - // requires this workaround - const int len = ASN1_STRING_to_UTF8(&buf, val); - if (len > 0) { - if (std::strlen((char *)buf) == static_cast<unsigned int>(len)) ret = (char *)buf; - OPENSSL_free(buf); - } - } - } else { - i = X509_get_ext_by_NID(cert, nid, -1); - if (i >= 0) { - X509_EXTENSION *ext = X509_get_ext(cert, i); - if (ext) { - BIO *bio = BIO_new(BIO_s_mem()); - if (bio) { - if (X509V3_EXT_print(bio, ext, 0, 0)) { - if (BIO_write(bio, &nullc, 1) == 1) { - char *str; - const long len = BIO_get_mem_data(bio, &str); - if (std::strlen(str) == static_cast<size_t>(len)) ret = str; - } - } - BIO_free(bio); - } - } - } - } - return ret; -} - -/** - * Retrieves the X.509 certificate serial number - * - * @param cert Pointer to a native OpenSSL X509 object containing the - * certificate - * - * @return Returns the numeric representation of the certificate serial number - * as a std::string. - */ -static std::string x509_get_serial(::X509 *cert) { - ASN1_INTEGER *asn1_i; - BIGNUM *bignum; - char *openssl_serial; - - asn1_i = X509_get_serialNumber(cert); - bignum = ASN1_INTEGER_to_BN(asn1_i, NULL); - openssl_serial = BN_bn2dec(bignum); - - const std::string ret = openssl_serial; - - BN_free(bignum); - OPENSSL_free(openssl_serial); - - return ret; -} - -/** - * Retrieves the X.509 certificate serial number as hexadecimal - * - * @param cert Pointer to a native OpenSSL X509 object containing the - * certificate - * - * @return Returns the hexadecimal representation of the certificate - * serial number as a std::string. - */ -static std::string x509_get_serial_hex(::X509 *cert) { - const ASN1_INTEGER *asn1_i = X509_get_serialNumber(cert); - return render_hex_sep(asn1_i->data, asn1_i->length, ':', false); -} - -} // namespace OpenSSLPKI -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/openssl/pki/x509store.hpp b/Sources/OpenVPN3/openvpn/openssl/pki/x509store.hpp deleted file mode 100644 index 7eb9aaa..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/pki/x509store.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// 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-2020 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/>. - -// Wrap an OpenSSL X509Store object - -#pragma once - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/pki/cclist.hpp> -#include <openvpn/openssl/util/error.hpp> -#include <openvpn/openssl/pki/x509.hpp> -#include <openvpn/openssl/pki/crl.hpp> - -namespace openvpn { - namespace OpenSSLPKI { - - class X509Store - { - public: - OPENVPN_EXCEPTION(x509_store_error); - - typedef CertCRLListTemplate<X509List, CRLList> CertCRLList; - - X509Store() - : x509_store_(nullptr) - { - } - - explicit X509Store(const CertCRLList& cc) - { - init(); - - // Load cert list - { - for (const auto &e : cc.certs) - { - if (!::X509_STORE_add_cert(x509_store_, e.obj())) - throw x509_store_error("X509_STORE_add_cert("); - } - } - - // Load CRL list - { - if (cc.crls.defined()) - { - ::X509_STORE_set_flags(x509_store_, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); - for (const auto &e : cc.crls) - { - if (!::X509_STORE_add_crl(x509_store_, e.obj())) - throw x509_store_error("X509_STORE_add_crl"); - } - } - } - } - - X509_STORE* obj() const - { - return x509_store_; - } - - X509_STORE* release() - { - X509_STORE* ret = x509_store_; - x509_store_ = nullptr; - return ret; - } - - ~X509Store() - { - if (x509_store_) - ::X509_STORE_free(x509_store_); - } - - private: - void init() - { - x509_store_ = ::X509_STORE_new(); - if (!x509_store_) - throw x509_store_error("X509_STORE_new"); - } - - ::X509_STORE* x509_store_; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/sign/pkcs7verify.hpp b/Sources/OpenVPN3/openvpn/openssl/sign/pkcs7verify.hpp deleted file mode 100644 index 923187b..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/sign/pkcs7verify.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// 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-2020 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/>. - -// Verify a PKCS7 signature - -#ifndef OPENVPN_OPENSSL_SIGN_PKCS7VERIFY_H -#define OPENVPN_OPENSSL_SIGN_PKCS7VERIFY_H - -#include <string> - -#include <openssl/ssl.h> -#include <openssl/bio.h> -#include <openssl/pkcs7.h> - -#include <openvpn/common/cleanup.hpp> -#include <openvpn/openssl/pki/x509.hpp> -#include <openvpn/openssl/util/error.hpp> - -namespace openvpn { - namespace OpenSSLSign { - /* - * Verify PKCS7 signature. - * On success, return. - * On fail, throw exception. - */ - inline void verify_pkcs7(const std::list<OpenSSLPKI::X509>& certs, - const std::string& sig, - const std::string& data) - { - STACK_OF(X509) *x509_stack = nullptr; - BIO *in = nullptr; - PKCS7 *p7 = nullptr; - - auto clean = Cleanup([&]() { - if (x509_stack) - sk_X509_free(x509_stack); - if (in) - BIO_free(in); - if (p7) - PKCS7_free(p7); - }); - - /* create x509_stack from cert */ - x509_stack = sk_X509_new_null(); - for (const auto& cert : certs) - sk_X509_push(x509_stack, cert.obj()); - - /* get signature */ - in = BIO_new_mem_buf(sig.c_str(), sig.length()); - p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); - if (!p7) - throw OpenSSLException("OpenSSLSign::verify_pkcs7: failed to parse pkcs7 signature"); - BIO_free(in); - in = nullptr; - - /* get data */ - in = BIO_new_mem_buf(data.c_str(), data.length()); - - /* OpenSSL 1.0.2e and higher no longer allows calling PKCS7_verify - with both data and content. Empty out the content. */ - p7->d.sign->contents->d.ptr = 0; - - /* do the verify */ - if (PKCS7_verify(p7, x509_stack, NULL, in, NULL, PKCS7_NOVERIFY) != 1) - throw OpenSSLException("OpenSSLSign::verify_pkcs7: verification failed"); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/sign/verify.hpp b/Sources/OpenVPN3/openvpn/openssl/sign/verify.hpp deleted file mode 100644 index f3188a6..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/sign/verify.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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-2020 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/>. - -// Verify a signature using OpenSSL EVP interface - -#ifndef OPENVPN_OPENSSL_SIGN_VERIFY_H -#define OPENVPN_OPENSSL_SIGN_VERIFY_H - -#include <string> - -#include <openssl/ssl.h> -#include <openssl/bio.h> - -#include <openvpn/common/cleanup.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/openssl/pki/x509.hpp> -#include <openvpn/openssl/util/error.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - namespace OpenSSLSign { - /* - * Verify signature. - * On success, return. - * On fail, throw exception. - */ - inline void verify(const OpenSSLPKI::X509& cert, - const std::string& sig, - const std::string& data, - const std::string& digest) - { - const EVP_MD *dig; - EVP_MD_CTX* md_ctx = nullptr; - EVP_PKEY *pkey = nullptr; - - auto clean = Cleanup([&]() { - if (pkey) - EVP_PKEY_free(pkey); - if (md_ctx) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - EVP_MD_CTX_cleanup(md_ctx); -#endif - EVP_MD_CTX_free(md_ctx); - } - }); - - // get digest - dig = EVP_get_digestbyname(digest.c_str()); - if (!dig) - throw Exception("OpenSSLSign::verify: unknown digest: " + digest); - - // get public key - pkey = X509_get_pubkey(cert.obj()); - if (!pkey) - throw Exception("OpenSSLSign::verify: no public key"); - - // convert signature from base64 to binary - BufferAllocated binsig(1024, 0); - try { - base64->decode(binsig, sig); - } - catch (const std::exception& e) - { - throw Exception(std::string("OpenSSLSign::verify: base64 decode error on signature: ") + e.what()); - } - - // initialize digest context - md_ctx = EVP_MD_CTX_new(); - - // verify signature - EVP_VerifyInit (md_ctx, dig); - EVP_VerifyUpdate(md_ctx, data.c_str(), data.length()); - if (EVP_VerifyFinal(md_ctx, binsig.c_data(), binsig.length(), pkey) != 1) - throw OpenSSLException("OpenSSLSign::verify: verification failed"); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/ssl/sess_cache.hpp b/Sources/OpenVPN3/openvpn/openssl/ssl/sess_cache.hpp deleted file mode 100644 index 7400975..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/ssl/sess_cache.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// 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-2020 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 <map> -#include <set> -#include <tuple> -#include <memory> -#include <utility> - -#include <openssl/ssl.h> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/msfind.hpp> - -namespace openvpn { - - // Client-side session cache. - // (We don't cache server-side sessions because we use TLS - // session resumption tickets which are stateless on the server). - class OpenSSLSessionCache : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<OpenSSLSessionCache> Ptr; - - OPENVPN_EXCEPTION(openssl_sess_cache_error); - - // Wrapper for OpenSSL SSL_SESSION pointers that manages reference counts. - class Session - { - public: - Session(::SSL_SESSION* sess) // caller must pre-increment refcount on sess - : sess_(sess) - { - } - - Session(Session&& other) noexcept - { - sess_ = other.sess_; - other.sess_ = nullptr; - } - - Session& operator=(Session&& other) noexcept - { - if (sess_) - ::SSL_SESSION_free(sess_); - sess_ = other.sess_; - other.sess_ = nullptr; - return *this; - } - - ::SSL_SESSION* openssl_session() const - { - return sess_; - } - - bool operator<(const Session& rhs) const // used when Session is a std::set key - { - return sess_ < rhs.sess_; - } - - explicit operator bool() const - { - return sess_ != nullptr; - } - - ~Session() - { - if (sess_) - ::SSL_SESSION_free(sess_); - } - - private: - // These methods are deleted because we have no way to increment - // an SSL_SESSION refcount until OpenSSL 1.1. - Session(const Session&) = delete; - Session& operator=(const Session&) = delete; - - ::SSL_SESSION* sess_; - }; - - class Key - { - public: - typedef std::unique_ptr<Key> UPtr; - - Key(const std::string& key_arg, - OpenSSLSessionCache::Ptr cache_arg) - : key(key_arg), - cache(std::move(cache_arg)) - { - //OPENVPN_LOG("OpenSSLSessionCache::Key CONSTRUCT key=" << key); - } - - void commit(::SSL_SESSION* sess) - { - if (!sess) - return; - auto mi = MSF::find(cache->map, key); - if (mi) - { - /* auto ins = */ mi->second.emplace(sess); - //OPENVPN_LOG("OpenSSLSessionCache::Key::commit ADD=" << ins.second << " key=" << key); - } - else - { - //OPENVPN_LOG("OpenSSLSessionCache::Key::commit CREATE key=" << key); - auto ins = cache->map.emplace(std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple()); - ins.first->second.emplace(sess); - } - } - - private: - const std::string key; - OpenSSLSessionCache::Ptr cache; - }; - - // Remove a session from the map after calling func() on it. - // This would be a lot cleaner if we had C++17 std::set::extract(). - template <typename FUNC> - void extract(const std::string& key, FUNC func) - { - auto mi = MSF::find(map, key); - if (mi) - { - //OPENVPN_LOG("OpenSSLSessionCache::Key::lookup EXISTS key=" << key); - SessionSet& ss = mi->second; - if (ss.empty()) - throw openssl_sess_cache_error("internal error: SessionSet is empty"); - auto ssi = ss.begin(); - try { - func(ssi->openssl_session()); - } - catch (...) - { - remove_session(mi, ss, ssi); - throw; - } - remove_session(mi, ss, ssi); - } - else - { - //OPENVPN_LOG("OpenSSLSessionCache::Key::lookup NOT_FOUND key=" << key); - } - } - - private: - struct SessionSet : public std::set<Session> - { - }; - - typedef std::map<std::string, SessionSet> Map; - - void remove_session(Map::iterator mi, SessionSet& ss, SessionSet::iterator ssi) - { - ss.erase(ssi); - if (ss.empty()) - map.erase(mi); - } - - Map map; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/openssl/ssl/sslctx.hpp b/Sources/OpenVPN3/openvpn/openssl/ssl/sslctx.hpp deleted file mode 100644 index c9e56db..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/ssl/sslctx.hpp +++ /dev/null @@ -1,2147 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL SSL API as defined in <openssl/ssl.h> -// so that it can be used as the SSL layer by the OpenVPN core. - -#ifndef OPENVPN_OPENSSL_SSL_SSLCTX_H -#define OPENVPN_OPENSSL_SSL_SSLCTX_H - -#include <string> -#include <cstring> -#include <cstdint> -#include <sstream> -#include <utility> - -#include <openssl/ssl.h> -#include <openssl/x509v3.h> -#include <openssl/rsa.h> -#include <openssl/dsa.h> -#include <openssl/ec.h> -#include <openssl/bn.h> -#include <openssl/rand.h> -#include <openssl/evp.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/mode.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/uniqueptr.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/pki/cclist.hpp> -#include <openvpn/pki/epkibase.hpp> -#include <openvpn/ssl/kuparse.hpp> -#include <openvpn/ssl/nscert.hpp> -#include <openvpn/ssl/tlsver.hpp> -#include <openvpn/ssl/tls_remote.hpp> -#include <openvpn/ssl/verify_x509_name.hpp> -#include <openvpn/ssl/sslconsts.hpp> -#include <openvpn/ssl/sslapi.hpp> -#include <openvpn/ssl/ssllog.hpp> -#include <openvpn/ssl/sni_handler.hpp> -#include <openvpn/ssl/iana_ciphers.hpp> -#include <openvpn/openssl/util/error.hpp> -#include <openvpn/openssl/pki/extpki.hpp> -#include <openvpn/openssl/pki/x509.hpp> -#include <openvpn/openssl/pki/crl.hpp> -#include <openvpn/openssl/pki/pkey.hpp> -#include <openvpn/openssl/pki/dh.hpp> -#include <openvpn/openssl/pki/x509store.hpp> -#include <openvpn/openssl/pki/x509certinfo.hpp> -#include <openvpn/openssl/bio/bio_memq_stream.hpp> -#include <openvpn/openssl/ssl/sess_cache.hpp> -#include <openvpn/openssl/ssl/tlsver.hpp> - - -#ifdef HAVE_JSON -#include <openvpn/common/jsonhelper.hpp> -#endif - -// An SSL Context is essentially a configuration that can be used -// to generate an arbitrary number of actual SSL connections objects. - -// OpenSSLContext is an SSL Context implementation that uses the -// OpenSSL library as a backend. - -namespace openvpn { - - // Represents an SSL configuration that can be used - // to instantiate actual SSL sessions. - class OpenSSLContext : public SSLFactoryAPI - { - public: - typedef RCPtr<OpenSSLContext> Ptr; - typedef CertCRLListTemplate<OpenSSLPKI::X509List, OpenSSLPKI::CRLList> CertCRLList; - - enum { - MAX_CIPHERTEXT_IN = 64 // maximum number of queued input ciphertext packets - }; - - // The data needed to construct an OpenSSLContext. - class Config : public SSLConfigAPI - { - friend class OpenSSLContext; - - public: - typedef RCPtr<Config> Ptr; - - SSLFactoryAPI::Ptr new_factory() override - { - return SSLFactoryAPI::Ptr(new OpenSSLContext(this)); - } - - void set_mode(const Mode& mode_arg) override - { - mode = mode_arg; - } - - const Mode& get_mode() const override - { - return mode; - } - - // if this callback is defined, no private key needs to be loaded - void set_external_pki_callback(ExternalPKIBase* external_pki_arg) override - { - external_pki = external_pki_arg; - } - - // server side - void set_session_ticket_handler(TLSSessionTicketBase* session_ticket_handler_arg) override - { - session_ticket_handler = session_ticket_handler_arg; - } - - // client side - void set_client_session_tickets(const bool v) override - { - client_session_tickets = v; - } - - // server side - void set_sni_handler(SNI::HandlerBase* sni_handler_arg) override - { - sni_handler = sni_handler_arg; - } - - // client side - void set_sni_name(const std::string& sni_name_arg) override - { - sni_name = sni_name_arg; - } - - void set_private_key_password(const std::string& pwd) override - { - pkey.set_private_key_password(pwd); - } - - void load_ca(const std::string& ca_txt, bool strict) override - { - ca.parse_pem(ca_txt, "ca"); - } - - void load_crl(const std::string& crl_txt) override - { - ca.parse_pem(crl_txt, "crl"); - } - - void load_cert(const std::string& cert_txt) override - { - cert.parse_pem(cert_txt, "cert"); - } - - void load_cert(const std::string& cert_txt, const std::string& extra_certs_txt) override - { - load_cert(cert_txt); - if (!extra_certs_txt.empty()) - CertCRLList::from_string(extra_certs_txt, "extra-certs", &extra_certs, nullptr); - } - - void load_private_key(const std::string& key_txt) override - { - pkey.parse_pem(key_txt, "private key"); - } - - void load_dh(const std::string& dh_txt) override - { - dh.parse_pem(dh_txt); - } - - std::string extract_ca() const override - { - return ca.certs.render_pem(); - } - - std::string extract_crl() const override - { - return ca.crls.render_pem(); - } - - std::string extract_cert() const override - { - return cert.render_pem(); - } - - std::vector<std::string> extract_extra_certs() const override - { - std::vector<std::string> ret; - - for (auto const& cert : extra_certs) - ret.push_back(cert.render_pem()); - - return ret; - } - - std::string extract_private_key() const override - { - return pkey.render_pem(); - } - - std::string extract_dh() const override - { - return dh.render_pem(); - } - - PKType::Type private_key_type() const override - { - if (!pkey.defined()) - return PKType::PK_NONE; - return pkey.key_type(); - } - - size_t private_key_length() const override - { - return pkey.key_length(); - } - - void set_frame(const Frame::Ptr& frame_arg) override - { - frame = frame_arg; - } - - void set_debug_level(const int debug_level) override - { - ssl_debug_level = debug_level; - } - - void set_flags(const unsigned int flags_arg) override - { - flags = flags_arg; - } - - void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) override - { - ns_cert_type = ns_cert_type_arg; - } - - void set_remote_cert_tls(const KUParse::TLSWebType wt) override - { - KUParse::remote_cert_tls(wt, ku, eku); - } - - void set_tls_remote(const std::string& tls_remote_arg) override - { - tls_remote = tls_remote_arg; - } - - void set_tls_version_min(const TLSVersion::Type tvm) override - { - tls_version_min = tvm; - } - - void set_tls_version_min_override(const std::string& override) override - { - TLSVersion::apply_override(tls_version_min, override); - } - - void set_tls_cert_profile(const TLSCertProfile::Type type) override - { - tls_cert_profile = type; - } - - void set_tls_cert_profile_override(const std::string& override) override - { - TLSCertProfile::apply_override(tls_cert_profile, override); - } - - virtual void set_tls_cipher_list(const std::string& override) - { - if(!override.empty()) - tls_cipher_list = override; - } - - virtual void set_tls_ciphersuite_list(const std::string& override) - { - if(!override.empty()) - tls_ciphersuite_list = override; - } - - virtual void set_tls_groups(const std::string& groups) - { - if (!groups.empty()) - tls_groups = groups; - } - - void set_local_cert_enabled(const bool v) override - { - local_cert_enabled = v; - } - - void set_x509_track(X509Track::ConfigSet x509_track_config_arg) override - { - x509_track_config = std::move(x509_track_config_arg); - } - - void set_rng(const RandomAPI::Ptr& rng_arg) override - { - // Not implemented (other than assert_crypto check) - // because OpenSSL is hardcoded to use its own RNG. - rng_arg->assert_crypto(); - } - - std::string validate_cert(const std::string& cert_txt) const override - { - OpenSSLPKI::X509 cert(cert_txt, "cert"); - return cert.render_pem(); - } - - std::string validate_cert_list(const std::string& certs_txt) const override - { - CertCRLList certs(certs_txt, "cert list"); - return certs.render_pem(); - } - - std::string validate_private_key(const std::string& key_txt) const override - { - OpenSSLPKI::PKey pkey(key_txt, "private key"); - return pkey.render_pem(); - } - - std::string validate_dh(const std::string& dh_txt) const override - { - OpenSSLPKI::DH dh(dh_txt); - return dh.render_pem(); - } - - std::string validate_crl(const std::string& crl_txt) const override - { - OpenSSLPKI::CRL crl(crl_txt); - return crl.render_pem(); - } - - void load(const OptionList& opt, const unsigned int lflags) override - { - // client/server - if (lflags & LF_PARSE_MODE) - mode = opt.exists("client") ? Mode(Mode::CLIENT) : Mode(Mode::SERVER); - - // possibly disable peer cert verification - if ((lflags & LF_ALLOW_CLIENT_CERT_NOT_REQUIRED) - && opt.exists("client-cert-not-required")) - flags |= SSLConst::NO_VERIFY_PEER; - - // sni - { - const std::string name = opt.get_optional("sni", 1, 256); - if (!name.empty()) - set_sni_name(name); - } - - // ca - { - std::string ca_txt = opt.cat("ca"); - if (lflags & LF_RELAY_MODE) - ca_txt += opt.cat("relay-extra-ca"); - load_ca(ca_txt, true); - } - - // CRL - { - const std::string crl_txt = opt.cat("crl-verify"); - if (!crl_txt.empty()) - load_crl(crl_txt); - } - - // local cert/key - if (local_cert_enabled) - { - // cert - { - const std::string& cert_txt = opt.get("cert", 1, Option::MULTILINE); - const std::string ec_txt = opt.cat("extra-certs"); - load_cert(cert_txt, ec_txt); - } - - // private key - if (!external_pki) - { - const std::string& key_txt = opt.get("key", 1, Option::MULTILINE); - load_private_key(key_txt); - } - } - - // DH - if (mode.is_server()) - { - const std::string& dh_txt = opt.get("dh", 1, Option::MULTILINE); - load_dh(dh_txt); - } - - // relay mode - std::string relay_prefix; - if (lflags & LF_RELAY_MODE) - relay_prefix = "relay-"; - - // ns-cert-type - ns_cert_type = NSCert::ns_cert_type(opt, relay_prefix); - - // parse remote-cert-x options - KUParse::remote_cert_tls(opt, relay_prefix, ku, eku); - KUParse::remote_cert_ku(opt, relay_prefix, ku); - KUParse::remote_cert_eku(opt, relay_prefix, eku); - - // parse tls-remote - tls_remote = opt.get_optional(relay_prefix + "tls-remote", 1, 256); - - // parse verify-x509-name - verify_x509_name.init(opt, relay_prefix); - - // Parse tls-version-min option. - tls_version_min = TLSVersion::parse_tls_version_min(opt, relay_prefix, maxver()); - - // parse tls-cert-profile - tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(opt, relay_prefix); - - // Overrides for tls cipher suites - if (opt.exists("tls-cipher")) - tls_cipher_list = opt.get_optional("tls-cipher", 1, 256); - - if (opt.exists("tls-ciphersuites")) - tls_ciphersuite_list = opt.get_optional("tls-ciphersuites", 1, 256); - - if (opt.exists("tls-groups")) - tls_groups = opt.get_optional("tls-groups", 1, 256); - - // unsupported cert checkers - { - } - } - -#ifdef OPENVPN_JSON_INTERNAL - // The get_string_ref methods require internal JSON and do not work with jsoncpp - SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const override - { - static const char title[] = "json_override"; - - Config::Ptr ret(new Config); - - // inherit from self - ret->mode = mode; - ret->dh = dh; - ret->frame = frame; - ret->ssl_debug_level = ssl_debug_level; - ret->flags = flags; - ret->local_cert_enabled = local_cert_enabled; - - // ca - { - const std::string& ca_txt = json::get_string_ref(root, "ca", title); - ret->load_ca(ca_txt, true); - } - - // CRL - { - const std::string crl_txt = json::get_string_optional(root, "crl_verify", std::string(), title); - if (!crl_txt.empty()) - ret->load_crl(crl_txt); - } - - // cert/key - if (load_cert_key && local_cert_enabled) - { - bool loaded_cert = false; - - // cert/extra_certs - { - const std::string cert_txt = json::get_string_optional(root, "cert", std::string(), title); - if (!cert_txt.empty()) - { - const std::string ec_txt = json::get_string_optional(root, "extra_certs", std::string(), title); - ret->load_cert(cert_txt, ec_txt); - loaded_cert = true; - } - else - { - ret->cert = cert; - ret->extra_certs = extra_certs; - } - } - - // private key - if (loaded_cert && !external_pki) - { - const std::string& key_txt = json::get_string_ref(root, "key", title); - if (!key_txt.empty()) - ret->load_private_key(key_txt); - else - ret->pkey = pkey; - } - } - else - { - // inherit from self - ret->cert = cert; - ret->extra_certs = extra_certs; - ret->pkey = pkey; - } - - // ns_cert_type - { - const std::string ct = json::get_string_optional(root, "ns_cert_type", std::string(), title); - if (!ct.empty()) - ret->ns_cert_type = NSCert::ns_cert_type(ct); - } - - // ku, eku - { - const std::string ct = json::get_string_optional(root, "remote_cert_tls", std::string(), title); - if (!ct.empty()) - KUParse::remote_cert_tls(ct, ret->ku, ret->eku); - } - - // tls_version_min - { - const std::string tvm = json::get_string_optional(root, "tls_version_min", std::string(), title); - if (!tvm.empty()) - ret->tls_version_min = TLSVersion::parse_tls_version_min(tvm, false, maxver()); - } - - // tls_cert_profile - { - const std::string prof = json::get_string_optional(root, "tls_cert_profile", std::string(), title); - if (!prof.empty()) - ret->tls_cert_profile = TLSCertProfile::parse_tls_cert_profile(prof); - } - - return ret; - } -#endif - - private: - static TLSVersion::Type maxver() - { - // Return maximum TLS version supported by OpenSSL. - // Assume that presence of SSL_OP_NO_TLSvX macro indicates - // that local OpenSSL library implements TLSvX. -#if defined(SSL_OP_NO_TLSv1_3) - return TLSVersion::V1_3; -#elif defined(SSL_OP_NO_TLSv1_2) - return TLSVersion::V1_2; -#elif defined(SSL_OP_NO_TLSv1_1) - return TLSVersion::V1_1; -#else - return TLSVersion::V1_0; -#endif - } - - Mode mode; - CertCRLList ca; // from OpenVPN "ca" and "crl-verify" option - OpenSSLPKI::X509 cert; // from OpenVPN "cert" option - OpenSSLPKI::X509List extra_certs; // from OpenVPN "extra-certs" option - OpenSSLPKI::PKey pkey; // private key - OpenSSLPKI::DH dh; // diffie-hellman parameters (only needed in server mode) - ExternalPKIBase* external_pki = nullptr; - TLSSessionTicketBase* session_ticket_handler = nullptr; // server side only - SNI::HandlerBase* sni_handler = nullptr; // server side only - Frame::Ptr frame; - int ssl_debug_level = 0; - unsigned int flags = 0; // defined in sslconsts.hpp - std::string sni_name; // client side only - NSCert::Type ns_cert_type{NSCert::NONE}; - std::vector<unsigned int> ku; // if defined, peer cert X509 key usage must match one of these values - std::string eku; // if defined, peer cert X509 extended key usage must match this OID/string - std::string tls_remote; - VerifyX509Name verify_x509_name; // --verify-x509-name feature - TLSVersion::Type tls_version_min{TLSVersion::UNDEF}; // minimum TLS version that we will negotiate - TLSCertProfile::Type tls_cert_profile{TLSCertProfile::UNDEF}; - std::string tls_cipher_list; - std::string tls_ciphersuite_list; - std::string tls_groups; - X509Track::ConfigSet x509_track_config; - bool local_cert_enabled = true; - bool client_session_tickets = false; - }; - - // Represents an actual SSL session. - // Normally instantiated by OpenSSLContext::ssl(). - class SSL : public SSLAPI - { - friend class OpenSSLContext; - - public: - typedef RCPtr<SSL> Ptr; - - void start_handshake() override - { - SSL_do_handshake(ssl); - } - - ssize_t write_cleartext_unbuffered(const void *data, const size_t size) override - { - const int status = BIO_write(ssl_bio, data, size); - if (status < 0) - { - if (status == -1 && BIO_should_retry(ssl_bio)) - return SSLConst::SHOULD_RETRY; - else - { - mark_no_cache(); - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::write_cleartext: BIO_write failed, size=" << size << " status=" << status); - } - } - else - return status; - } - - ssize_t read_cleartext(void *data, const size_t capacity) override - { - if (!overflow) - { - const int status = BIO_read(ssl_bio, data, capacity); - if (status < 0) - { - if (status == -1 && BIO_should_retry(ssl_bio)) - return SSLConst::SHOULD_RETRY; - else - { - mark_no_cache(); - OPENVPN_THROW(OpenSSLException, "OpenSSLContext::SSL::read_cleartext: BIO_read failed, cap=" << capacity << " status=" << status); - } - } - else - return status; - } - else - throw ssl_ciphertext_in_overflow(); - } - - bool read_cleartext_ready() const override - { - return !bmq_stream::memq_from_bio(ct_in)->empty() || SSL_pending(ssl) > 0; - } - - void write_ciphertext(const BufferPtr& buf) override - { - bmq_stream::MemQ* in = bmq_stream::memq_from_bio(ct_in); - if (in->size() < MAX_CIPHERTEXT_IN) - in->write_buf(buf); - else - overflow = true; - } - - void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) override - { - bmq_stream::MemQ* in = bmq_stream::memq_from_bio(ct_in); - if (in->size() < MAX_CIPHERTEXT_IN) - in->write(data, size); - else - overflow = true; - } - - bool read_ciphertext_ready() const override - { - return !bmq_stream::memq_from_bio(ct_out)->empty(); - } - - BufferPtr read_ciphertext() override - { - return bmq_stream::memq_from_bio(ct_out)->read_buf(); - } - - std::string ssl_handshake_details() const override - { - return ssl_handshake_details(ssl); - } - - virtual bool export_keying_material(const std::string& label, unsigned char *dest, size_t size) override - { - return SSL_export_keying_material(ssl, dest, size, label.c_str(), label.size(), nullptr, 0, 0) == 1; - } - - // Return true if we did a full SSL handshake/negotiation. - // Return false for cached, reused, or persisted sessions. - // Also returns false if previously called on this session. - virtual bool did_full_handshake() override - { - if (called_did_full_handshake) - return false; - called_did_full_handshake = true; - return !SSL_session_reused(ssl); - } - - const AuthCert::Ptr& auth_cert() const override - { - // Reused sessions don't call the cert verify callbacks, - // so we must use an alternative method to build authcert. - if (authcert && authcert->is_uninitialized()) - rebuild_authcert(); - return authcert; - } - - void mark_no_cache() override - { - sess_cache_key.reset(); - } - - ~SSL() - { - ssl_erase(); - } - - static void init_static() - { - bmq_stream::init_static(); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_EC) - ExternalPKIECImpl::init_static(); -#endif - - - ssl_data_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr); - context_data_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext", nullptr, nullptr, nullptr); - - /* - * We actually override some of the OpenSSL SSLv23 methods here, - * in particular the ssl_pending method. We want ssl_pending - * to return 0 until the SSL negotiation establishes the - * actual method. The default OpenSSL SSLv23 ssl_pending method - * (ssl_undefined_const_function) triggers an OpenSSL error condition - * when calling SSL_pending early which is not what we want. - * - * This depends on SSL23 being a generic method and OpenSSL later - * switching to a spefic TLS method (TLS10method etc..) with - * ssl23_get_client_method that has the proper ssl3_pending pending method. - * - * OpenSSL 1.1.x does not allow hacks like this anymore. So overriding is not - * possible. Fortunately OpenSSL 1.1 also always defines ssl_pending method to - * be ssl3_pending, so this hack is no longer needed. - */ - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - ssl23_method_client_ = *SSLv23_client_method(); - ssl23_method_client_.ssl_pending = ssl_pending_override; - - ssl23_method_server_ = *SSLv23_server_method(); - ssl23_method_server_.ssl_pending = ssl_pending_override; -#endif - } - - private: - SSL(const OpenSSLContext& ctx, const std::string* hostname, const std::string* cache_key) - { - ssl_clear(); - try { - // init SSL objects - ssl = SSL_new(ctx.ctx); - if (!ssl) - throw OpenSSLException("OpenSSLContext::SSL: SSL_new failed"); - - // release unneeded buffers - SSL_set_mode(ssl, SSL_MODE_RELEASE_BUFFERS); - - // verify hostname - if (hostname && !(ctx.config->flags & SSLConst::NO_VERIFY_HOSTNAME)) - { - X509_VERIFY_PARAM *param = SSL_get0_param(ssl); - X509_VERIFY_PARAM_set_hostflags(param, 0); - X509_VERIFY_PARAM_set1_host(param, hostname->c_str(), 0); - } - - // init BIOs - ssl_bio = BIO_new(BIO_f_ssl()); - if (!ssl_bio) - throw OpenSSLException("OpenSSLContext::SSL: BIO_new BIO_f_ssl failed"); - ct_in = mem_bio(ctx.config->frame); - ct_out = mem_bio(ctx.config->frame); - - // set client/server mode - if (ctx.config->mode.is_server()) - { - SSL_set_accept_state(ssl); - authcert.reset(new AuthCert()); - if (!ctx.config->x509_track_config.empty()) - authcert->x509_track.reset(new X509Track::Set); - } - else if (ctx.config->mode.is_client()) - { - if (cache_key && ctx.sess_cache) - { - // see if a cached session already exists for our cache_key - ctx.sess_cache->extract(*cache_key, [this](SSL_SESSION* sess) { - if (!SSL_set_session(ssl, sess)) - throw OpenSSLException("SSL_set_session failed"); - }); - - // cache the session before its end-of-life if no errors occur - sess_cache_key.reset(new OpenSSLSessionCache::Key(*cache_key, ctx.sess_cache)); - } - SSL_set_connect_state(ssl); - - // client-side SNI - if (!ctx.config->sni_name.empty()) - { - if (SSL_set_tlsext_host_name(ssl, ctx.config->sni_name.c_str()) != 1) - throw OpenSSLException("OpenSSLContext::SSL: SSL_set_tlsext_host_name failed (sni_name)"); - } - else if ((ctx.config->flags & SSLConst::ENABLE_CLIENT_SNI) && hostname) - { - if (SSL_set_tlsext_host_name(ssl, hostname->c_str()) != 1) - throw OpenSSLException("OpenSSLContext::SSL: SSL_set_tlsext_host_name failed (hostname)"); - } - } - else - OPENVPN_THROW(ssl_context_error, "OpenSSLContext::SSL: unknown client/server mode"); - - // effect SSL/BIO linkage - ssl_bio_linkage = true; // after this point, no need to explicitly BIO_free ct_in/ct_out - SSL_set_bio (ssl, ct_in, ct_out); - BIO_set_ssl (ssl_bio, ssl, BIO_NOCLOSE); - - if (ssl_data_index < 0) - throw ssl_context_error("OpenSSLContext::SSL: ssl_data_index is uninitialized"); - SSL_set_ex_data (ssl, ssl_data_index, this); - set_parent(&ctx); - } - catch (...) - { - ssl_erase(); - throw; - } - } - - void set_parent(const OpenSSLContext* ctx) - { - if (context_data_index < 0) - throw ssl_context_error("OpenSSLContext::SSL: context_data_index is uninitialized"); - SSL_set_ex_data(ssl, context_data_index, (void *)ctx); - } - - void rebuild_authcert() const - { - ::X509 *cert = SSL_get_peer_certificate(ssl); - if (cert) - { - // save the issuer cert fingerprint - static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LENGTH, "size inconsistency"); - - unsigned int md_len = sizeof(AuthCert::issuer_fp); - X509_digest (cert, EVP_sha1 (), authcert->issuer_fp, &md_len); - - // save the Common Name - authcert->cn = OpenSSLPKI::x509_get_field(cert, NID_commonName); - - // save the leaf cert serial number - const ASN1_INTEGER *ai = X509_get_serialNumber(cert); - authcert->sn = extract_serial_number(ai); - - X509_free (cert); - } - } - - // Indicate no data available for our custom SSLv23 method - static int ssl_pending_override(const ::SSL *) - { - return 0; - } - - // Print a one line summary of SSL/TLS session handshake. - static std::string ssl_handshake_details (const ::SSL *c_ssl) - { - std::ostringstream os; - - ::X509 *cert = SSL_get_peer_certificate (c_ssl); - - if (cert) - os << "peer certificate: CN=" << OpenSSLPKI::x509_get_field(cert, NID_commonName); - - if (cert != nullptr) - { - EVP_PKEY *pkey = X509_get_pubkey (cert); - if (pkey != nullptr) - { -#ifndef OPENSSL_NO_EC - if ((EVP_PKEY_id(pkey) == EVP_PKEY_EC) && (EVP_PKEY_get0_EC_KEY(pkey) != nullptr && - EVP_PKEY_get0_EC_KEY(pkey) != nullptr)) - { - EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey); - const EC_GROUP* group = EC_KEY_get0_group(ec); - const char* curve = nullptr; - - int nid = EC_GROUP_get_curve_name(group); - - if (nid != 0) - { - curve = OBJ_nid2sn(nid); - } - - if(!curve) - { - curve = "Error getting curve name"; - } - - os << ", " << EC_GROUP_order_bits(group) << " bit EC, curve:" << curve; - } - - else -#endif - { - int pkeyId = EVP_PKEY_id(pkey); - const char* pkeySN = OBJ_nid2sn(pkeyId); - if (!pkeySN) - pkeySN = "Unknown"; - - // Nicer names instead of rsaEncryption and dsaEncryption - if (pkeyId == EVP_PKEY_RSA) - pkeySN = "RSA"; - else if (pkeyId == EVP_PKEY_DSA) - pkeySN = "DSA"; - - os << ", " << EVP_PKEY_bits(pkey) << " bit " << pkeySN; - } - EVP_PKEY_free(pkey); - } - X509_free (cert); - } - - const SSL_CIPHER *ciph = SSL_get_current_cipher (c_ssl); - if (ciph) - { - char* desc = SSL_CIPHER_description(ciph, nullptr, 0); - if (!desc) - { - os << ", cipher: Error getting TLS cipher description from SSL_CIPHER_description"; - } - else - { - os << ", cipher: " << desc; - OPENSSL_free(desc); - } - } - // This has been changed in upstream SSL to have a const - // parameter, so we cast away const for older versions compatibility - // (Upstream commit: c04b66b18d1a90f0c6326858e4b8367be5444582) - if (SSL_session_reused(const_cast<::SSL *>(c_ssl))) - os << " [REUSED]"; - return os.str(); - } - - void ssl_clear() - { - ssl_bio_linkage = false; - ssl = nullptr; - ssl_bio = nullptr; - ct_in = nullptr; - ct_out = nullptr; - overflow = false; - called_did_full_handshake = false; - sess_cache_key.reset(); - } - - void ssl_erase() - { - if (!ssl_bio_linkage) - { - if (ct_in) - BIO_free(ct_in); - if (ct_out) - BIO_free(ct_out); - } - if (ssl_bio) - BIO_free_all(ssl_bio); - if (ssl) - { - if (sess_cache_key) - { - SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); - sess_cache_key->commit(SSL_get1_session(ssl)); - } - SSL_free(ssl); - } - openssl_clear_error_stack(); - ssl_clear(); - } - - static BIO* mem_bio(const Frame::Ptr& frame) - { - BIO *bio = BIO_new(bmq_stream::BIO_s_memq()); - if (!bio) - throw OpenSSLException("OpenSSLContext::SSL: BIO_new failed on bmq_stream"); - bmq_stream::memq_from_bio(bio)->set_frame(frame); - return bio; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - /* - * Return modified OpenSSL SSLv23 methods, - * as configured in init_static(). - */ - - static const SSL_METHOD* tls_method_client() - { - return &ssl23_method_client_; - } - - static const SSL_METHOD* tls_method_server() - { - return &ssl23_method_server_; - } -#else - static const SSL_METHOD* tls_method_client () - { - return TLS_client_method (); - } - - static const SSL_METHOD* tls_method_server () - { - return TLS_server_method (); - } -#endif - ::SSL *ssl; // OpenSSL SSL object - BIO *ssl_bio; // read/write cleartext from here - BIO *ct_in; // write ciphertext to here - BIO *ct_out; // read ciphertext from here - AuthCert::Ptr authcert; - OpenSSLSessionCache::Key::UPtr sess_cache_key; // client-side only - OpenSSLContext::Ptr sni_ctx; - bool ssl_bio_linkage; - bool overflow; - bool called_did_full_handshake; - - // Helps us to store pointer to self in ::SSL object - static int ssl_data_index; - static int context_data_index; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - // Modified SSLv23 methods - static SSL_METHOD ssl23_method_client_; - static SSL_METHOD ssl23_method_server_; -#endif - }; - - /////// start of main class implementation - static std::string translate_cipher_list(std::string cipherlist) - { - // OpenVPN 2.x accepts IANA ciphers instead in the cipher list, we need - // to do the same - - std::stringstream cipher_list_ss(cipherlist); - std::string ciphersuite; - - std::stringstream result; - - - while(std::getline(cipher_list_ss, ciphersuite, ':')) - { - const tls_cipher_name_pair* pair = tls_get_cipher_name_pair(ciphersuite); - - if (!result.str().empty()) - result << ":"; - - if (pair) - { - if (pair->iana_name != ciphersuite) - { - OPENVPN_LOG_SSL("OpenSSLContext: Deprecated cipher suite name '" - << pair->openssl_name << "' please use IANA name ' " - << pair->iana_name << "'"); - } - result << pair->openssl_name; - } - else - { - result << ciphersuite; - } - } - - return result.str(); - } - - private: - OpenSSLContext(Config* config_arg) - : config(config_arg) - { - try - { - // Create new SSL_CTX for server or client mode - if (config->mode.is_server()) - { - ctx = SSL_CTX_new(SSL::tls_method_server()); - if (ctx == nullptr) - throw OpenSSLException("OpenSSLContext: SSL_CTX_new failed for server method"); - - // Set DH object - if (!config->dh.defined()) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: DH not defined"); - if (!SSL_CTX_set_tmp_dh(ctx, config->dh.obj())) - throw OpenSSLException("OpenSSLContext: SSL_CTX_set_tmp_dh failed"); - if (config->flags & SSLConst::SERVER_TO_SERVER) - SSL_CTX_set_purpose(ctx, X509_PURPOSE_SSL_SERVER); - - // server-side SNI - if (config->sni_handler) - { -#if OPENSSL_VERSION_NUMBER >= 0x10101000L -#define OPENSSL_SERVER_SNI - SSL_CTX_set_client_hello_cb(ctx, client_hello_callback, nullptr); -#else - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: server-side SNI requires OpenSSL 1.1 or higher"); -#endif - } - } - else if (config->mode.is_client()) - { - ctx = SSL_CTX_new(SSL::tls_method_client()); - if (ctx == nullptr) - throw OpenSSLException("OpenSSLContext: SSL_CTX_new failed for client method"); - } - else - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: unknown config->mode"); - - // Set SSL options - if (!(config->flags & SSLConst::NO_VERIFY_PEER)) - { - int vf = SSL_VERIFY_PEER; - if (!(config->flags & SSLConst::PEER_CERT_OPTIONAL)) - vf |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - SSL_CTX_set_verify(ctx, vf, - config->mode.is_client() ? verify_callback_client : verify_callback_server); - SSL_CTX_set_verify_depth(ctx, 16); - } - - /* Disable SSLv2 and SSLv3, might be a noop but does not hurt */ - long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - - if (config->mode.is_server()) - { - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); - if (config->session_ticket_handler) - { - const std::string sess_id_context = config->session_ticket_handler->session_id_context(); - if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)sess_id_context.c_str(), sess_id_context.length())) - throw OpenSSLException("OpenSSLContext: SSL_CTX_set_session_id_context failed"); - - if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, tls_ticket_key_callback)) - throw OpenSSLException("OpenSSLContext: SSL_CTX_set_tlsext_ticket_key_cb failed"); - } - else - sslopt |= SSL_OP_NO_TICKET; - - // send a client CA list to the client - if (config->flags & SSLConst::SEND_CLIENT_CA_LIST) - { - for (const auto& e : config->ca.certs) - { - if (SSL_CTX_add_client_CA(ctx, e.obj()) != 1) - throw OpenSSLException("OpenSSLContext: SSL_CTX_add_client_CA failed"); - } - } - } - else - { - if (config->client_session_tickets) - { - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT); - sess_cache.reset(new OpenSSLSessionCache); - } - else - { - SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); - sslopt |= SSL_OP_NO_TICKET; - } - } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - if (config->tls_version_min > TLSVersion::V1_0) - { - SSL_CTX_set_min_proto_version(ctx, TLSVersion::toTLSVersion(config->tls_version_min)); - } -#else - if (config->tls_version_min > TLSVersion::V1_0) - sslopt |= SSL_OP_NO_TLSv1; -#ifdef SSL_OP_NO_TLSv1_1 - if (config->tls_version_min > TLSVersion::V1_1) - sslopt |= SSL_OP_NO_TLSv1_1; -#endif -#ifdef SSL_OP_NO_TLSv1_2 - if (config->tls_version_min > TLSVersion::V1_2) - sslopt |= SSL_OP_NO_TLSv1_2; -#endif -#ifdef SSL_OP_NO_TLSv1_3 - if (config->tls_version_min > TLSVersion::V1_3) - sslopt |= SSL_OP_NO_TLSv1_3; -#endif -#endif - SSL_CTX_set_options(ctx, sslopt); - - if (!config->tls_groups.empty()) - { - set_openssl_tls_groups(config->tls_groups); - } -#if defined(TLS1_3_VERSION) - if (!config->tls_ciphersuite_list.empty()) - { - if(!SSL_CTX_set_ciphersuites(ctx, config->tls_ciphersuite_list.c_str())) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set_ciphersuites_list failed"); - } -#endif - const char* tls_cipher_list = - /* default list as a basis */ - "DEFAULT" - /* Disable export ciphers, low and medium */ - ":!EXP:!LOW:!MEDIUM" - /* Disable static (EC)DH keys (no forward secrecy) */ - ":!kDH:!kECDH" - /* Disable DSA private keys */ - ":!DSS" - /* Disable RC4 cipher */ - ":!RC4" - /* Disable MD5 */ - ":!MD5" - /* Disable unsupported TLS modes */ - ":!PSK:!SRP:!kRSA" - /* Disable SSLv2 cipher suites*/ - ":!SSLv2"; - - std::string translated_cipherlist; - - if (!config->tls_cipher_list.empty()) - { - translated_cipherlist = translate_cipher_list(config->tls_cipher_list); - - tls_cipher_list = translated_cipherlist.c_str(); - } - - if (!SSL_CTX_set_cipher_list(ctx, tls_cipher_list)) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set_cipher_list failed"); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && OPENSSL_VERSION_NUMBER < 0x10100000L - SSL_CTX_set_ecdh_auto(ctx, 1); // this method becomes a no-op in OpenSSL 1.1 -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - switch(TLSCertProfile::default_if_undef(config->tls_cert_profile)) - { - case TLSCertProfile::UNDEF: - OPENVPN_THROW(ssl_context_error, - "OpenSSLContext: undefined tls-cert-profile"); - break; -#ifdef OPENVPN_USE_TLS_MD5 - case TLSCertProfile::INSECURE: - SSL_CTX_set_security_level(ctx, 0); - break; -#endif - case TLSCertProfile::LEGACY: - SSL_CTX_set_security_level(ctx, 1); - break; - case TLSCertProfile::PREFERRED: - SSL_CTX_set_security_level(ctx, 2); - break; - case TLSCertProfile::SUITEB: - SSL_CTX_set_security_level(ctx, 3); - break; - default: - OPENVPN_THROW(ssl_context_error, - "OpenSSLContext: unexpected tls-cert-profile value"); - break; - } -#else - // when OpenSSL does not CertProfile support we force the user to set 'legacy' - if (TLSCertProfile::default_if_undef(config->tls_cert_profile) != TLSCertProfile::LEGACY) - { - OPENVPN_THROW(ssl_context_error, - "OpenSSLContext: tls-cert-profile not supported by this OpenSSL build. Use 'legacy' instead"); - } -#endif - - if (config->local_cert_enabled) - { - // Set certificate - if (!config->cert.defined()) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: cert not defined"); - if (SSL_CTX_use_certificate(ctx, config->cert.obj()) != 1) - throw OpenSSLException("OpenSSLContext: SSL_CTX_use_certificate failed"); - - // Set private key - if (config->external_pki) - { - auto certType = EVP_PKEY_id (X509_get0_pubkey(config->cert.obj())); - if (certType == EVP_PKEY_RSA ) - { - epki = new ExternalPKIRsaImpl (ctx, config->cert.obj(), config->external_pki); - } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_NO_EC) - else if (certType == EVP_PKEY_EC) - { - epki = new ExternalPKIECImpl (ctx, config->cert.obj(), config->external_pki); - } -#endif - else - { - throw OpenSSLException("OpenSSLContext: pkey is neither RSA nor EC. Unsupported with external pki"); - } - } - else - { - if (!config->pkey.defined()) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: private key not defined"); - if (SSL_CTX_use_PrivateKey(ctx, config->pkey.obj()) != 1) - throw OpenSSLException("OpenSSLContext: SSL_CTX_use_PrivateKey failed"); - - // Check cert/private key compatibility - if (!SSL_CTX_check_private_key(ctx)) - throw OpenSSLException("OpenSSLContext: private key does not match the certificate"); - } - - // Set extra certificates that are part of our own certificate - // chain but shouldn't be included in the verify chain. - if (config->extra_certs.defined()) - { - for (const auto& e : config->extra_certs) - { - if (SSL_CTX_add_extra_chain_cert(ctx, e.obj_dup()) != 1) - throw OpenSSLException("OpenSSLContext: SSL_CTX_add_extra_chain_cert failed"); - } - } - } - - // Set CAs/CRLs - if (config->ca.certs.defined()) - update_trust(config->ca); - else if (!(config->flags & SSLConst::NO_VERIFY_PEER)) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: CA not defined"); - - // Show handshake debugging info - if (config->ssl_debug_level) - SSL_CTX_set_info_callback (ctx, info_callback); - } - catch (...) - { - erase(); - throw; - } - } - - public: - // create a new SSL instance - virtual SSLAPI::Ptr ssl() - { - return SSL::Ptr(new SSL(*this, nullptr, nullptr)); - } - - // like ssl() above but verify hostname against cert CommonName and/or SubjectAltName - virtual SSLAPI::Ptr ssl(const std::string* hostname, const std::string* cache_key) - { - return SSL::Ptr(new SSL(*this, hostname, cache_key)); - } - - void update_trust(const CertCRLList& cc) - { - OpenSSLPKI::X509Store store(cc); - SSL_CTX_set_cert_store(ctx, store.release()); - } - - ~OpenSSLContext() - { - erase(); - } - - virtual const Mode& mode() const - { - return config->mode; - } - - constexpr static bool support_key_material_export() - { - return true; - } - private: - // ns-cert-type verification - - bool ns_cert_type_defined() const - { - return config->ns_cert_type != NSCert::NONE; - } - - bool verify_ns_cert_type(::X509* cert) const - { - if (config->ns_cert_type == NSCert::SERVER) - return X509_check_purpose (cert, X509_PURPOSE_SSL_SERVER, 0); - else if (config->ns_cert_type == NSCert::CLIENT) - return X509_check_purpose (cert, X509_PURPOSE_SSL_CLIENT, 0); - else - return true; - } - - - void set_openssl_tls_groups(const std::string& tls_groups) - { - auto num_groups = std::count(tls_groups.begin(), tls_groups.end(), ':') + 1; - - std::unique_ptr<int[]> glist(new int[num_groups]); - - std::stringstream groups_ss(tls_groups); - std::string group; - - int glistlen = 0; - while (std::getline(groups_ss, group, ':')) - { - /* Dance around that the fact that even though OpenSSL authors - * call this group secp256r1 in their own source code, OpenSSL - * externally only knows this by prime256v1 or P-256 */ - if (group == "secp256r1") - { - group = "prime256v1"; - } - - int nid = OBJ_sn2nid(group.c_str()); - if (nid != 0) - { - glist[glistlen] = nid; - glistlen++; - } - else - { - OPENVPN_LOG_SSL("OpenSSL -- warning ignoring unknown group '" - << group << "' in tls-groups"); - } - } - - if (!SSL_CTX_set1_groups(ctx, glist.get(), glistlen)) - OPENVPN_THROW(ssl_context_error, "OpenSSLContext: SSL_CTX_set1_groups failed"); - - } - - // remote-cert-ku verification - - bool x509_cert_ku_defined() const - { - return config->ku.size() > 0; - } - - bool verify_x509_cert_ku(::X509 *cert) const - { - bool found = false; - ASN1_BIT_STRING *ku = (ASN1_BIT_STRING *)X509_get_ext_d2i(cert, NID_key_usage, nullptr, nullptr); - - if (ku) - { - // Extract key usage bits - unsigned int nku = 0; - { - for (int i = 0; i < 8; i++) - { - if (ASN1_BIT_STRING_get_bit(ku, i)) - nku |= 1 << (7 - i); - } - } - - // Fixup if no LSB bits - if ((nku & 0xff) == 0) - nku >>= 8; - - // Validating certificate key usage - { - for (std::vector<unsigned int>::const_iterator i = config->ku.begin(); i != config->ku.end(); ++i) - { - if (nku == *i) - { - found = true; - break; - } - } - } - - ASN1_BIT_STRING_free(ku); - } - return found; - } - - // remote-cert-eku verification - - bool x509_cert_eku_defined() const - { - return !config->eku.empty(); - } - - bool verify_x509_cert_eku(::X509 *cert) const - { - bool found = false; - EXTENDED_KEY_USAGE *eku = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i(cert, NID_ext_key_usage, nullptr, nullptr); - - if (eku) - { - // Validating certificate extended key usage - for (int i = 0; !found && i < sk_ASN1_OBJECT_num(eku); i++) - { - ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(eku, i); - char oid_str[256]; - - if (!found && OBJ_obj2txt(oid_str, sizeof(oid_str), oid, 0) != -1) - { - // Compare EKU against string - if (config->eku == oid_str) - found = true; - } - - if (!found && OBJ_obj2txt(oid_str, sizeof(oid_str), oid, 1) != -1) - { - // Compare EKU against OID - if (config->eku == oid_str) - found = true; - } - } - - sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free); - } - return found; - } - - static void x509_track_extract_nid(const X509Track::Type xt_type, - const int nid, - ::X509 *cert, - const int depth, - X509Track::Set& xts) - { - const std::string value = OpenSSLPKI::x509_get_field(cert, nid); - if (!value.empty()) - xts.emplace_back(xt_type, depth, OpenSSLPKI::x509_get_field(cert, nid)); - } - - static void x509_track_extract_from_cert(::X509 *cert, - const int depth, - const X509Track::ConfigSet& cs, - X509Track::Set& xts) - { - for (auto &c : cs) - { - if (c.depth_match(depth)) - { - switch (c.type) - { - case X509Track::SERIAL: - xts.emplace_back(X509Track::SERIAL, - depth, - OpenSSLPKI::x509_get_serial(cert)); - break; - case X509Track::SERIAL_HEX: - xts.emplace_back(X509Track::SERIAL_HEX, - depth, - OpenSSLPKI::x509_get_serial_hex(cert)); - break; - case X509Track::SHA1: - { - unsigned char buf[EVP_MAX_MD_SIZE]; - unsigned int len = EVP_MAX_MD_SIZE; - X509_digest (cert, EVP_sha1 (), buf, &len); - xts.emplace_back (X509Track::SHA1, - depth, - render_hex_sep (buf, len, ':', true)); - } - break; - case X509Track::CN: - x509_track_extract_nid(X509Track::CN, NID_commonName, cert, depth, xts); - break; - case X509Track::C: - x509_track_extract_nid(X509Track::C, NID_countryName, cert, depth, xts); - break; - case X509Track::L: - x509_track_extract_nid(X509Track::L, NID_localityName, cert, depth, xts); - break; - case X509Track::ST: - x509_track_extract_nid(X509Track::ST, NID_stateOrProvinceName, cert, depth, xts); - break; - case X509Track::O: - x509_track_extract_nid(X509Track::O, NID_organizationName, cert, depth, xts); - break; - case X509Track::OU: - x509_track_extract_nid(X509Track::OU, NID_organizationalUnitName, cert, depth, xts); - break; - case X509Track::EMAIL: - x509_track_extract_nid(X509Track::EMAIL, NID_pkcs9_emailAddress, cert, depth, xts); - break; - default: - break; - } - } - } - } - - static std::int64_t extract_serial_number(const ASN1_INTEGER *ai) - { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - std::int64_t ret; - if (ASN1_INTEGER_get_int64(&ret, ai) == 0) - return -1; - return ret; -#else - return ai ? ASN1_INTEGER_get(ai) : -1; -#endif - } - - static std::string cert_status_line(int preverify_ok, - int depth, - int err, - const std::string& signature, - const std::string& subject) - { - std::string ret; - ret.reserve(128); - ret = "VERIFY"; - if (preverify_ok) - ret += " OK"; - else - ret += " FAIL"; - ret += ": depth="; - ret += openvpn::to_string(depth); - ret += ", "; - if (!subject.empty()) - ret += subject; - else - ret += "NO_SUBJECT"; - ret += ", signature: " + signature; - if (!preverify_ok) - { - ret += " ["; - ret += X509_verify_cert_error_string(err); - ret += ']'; - } - return ret; - } - - static AuthCert::Fail::Type cert_fail_code(const int openssl_err) - { - // NOTE: this method should never return OK - switch (openssl_err) - { - case X509_V_ERR_CERT_HAS_EXPIRED: - return AuthCert::Fail::EXPIRED; - default: - return AuthCert::Fail::CERT_FAIL; - } - } - - - static int check_cert_warnings(const X509* cert) - { - int nid = X509_get_signature_nid(cert); - - switch (nid) { - case NID_ecdsa_with_SHA1: - case NID_dsaWithSHA: - case NID_dsaWithSHA1: - case NID_sha1WithRSAEncryption: - return SSLAPI::TLS_WARN_SIG_SHA1; - case NID_md5WithRSA: - case NID_md5WithRSAEncryption: - return SSLAPI::TLS_WARN_SIG_MD5; - default: - return SSLAPI::TLS_WARN_NONE; - } - } - - static int verify_callback_client(int preverify_ok, X509_STORE_CTX *ctx) - { - // get the OpenSSL SSL object - ::SSL* ssl = (::SSL*) X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - - // get OpenSSLContext - const OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data (ssl, SSL::context_data_index); - - // get OpenSSLContext::SSL - SSL* self_ssl = (SSL *) SSL_get_ex_data (ssl, SSL::ssl_data_index); - - // get depth - const int depth = X509_STORE_CTX_get_error_depth(ctx); - - // get current certificate - X509* current_cert = X509_STORE_CTX_get_current_cert (ctx); - - // log subject - const std::string subject = OpenSSLPKI::x509_get_subject(current_cert); - auto signature = OpenSSLPKI::x509_get_signature_algorithm(current_cert); - if (self->config->flags & SSLConst::LOG_VERIFY_STATUS) - OPENVPN_LOG_SSL(cert_status_line(preverify_ok, depth, X509_STORE_CTX_get_error(ctx), - signature, subject)); - - // Add warnings if Cert parameters are wrong - self_ssl->tls_warnings |= self->check_cert_warnings(current_cert); - - // leaf-cert verification - if (depth == 0) - { - // verify ns-cert-type - if (self->ns_cert_type_defined() && !self->verify_ns_cert_type(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad ns-cert-type in leaf certificate"); - preverify_ok = false; - } - - // verify X509 key usage - if (self->x509_cert_ku_defined() && !self->verify_x509_cert_ku(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 key usage in leaf certificate"); - preverify_ok = false; - } - - // verify X509 extended key usage - if (self->x509_cert_eku_defined() && !self->verify_x509_cert_eku(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 extended key usage in leaf certificate"); - preverify_ok = false; - } - - // verify-x509-name - const VerifyX509Name& verify_x509 = self->config->verify_x509_name; - if (verify_x509.get_mode() != VerifyX509Name::VERIFY_X509_NONE) - { - switch (verify_x509.get_mode()) - { - case VerifyX509Name::VERIFY_X509_SUBJECT_DN: - preverify_ok = verify_x509.verify(OpenSSLPKI::x509_get_subject(current_cert, true)); - break; - - case VerifyX509Name::VERIFY_X509_SUBJECT_RDN: - case VerifyX509Name::VERIFY_X509_SUBJECT_RDN_PREFIX: - preverify_ok = verify_x509.verify(OpenSSLPKI::x509_get_field(current_cert, NID_commonName)); - break; - - default: - break; - } - if (!preverify_ok) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- verify-x509-name failed"); - } - } - - // verify tls-remote - if (!self->config->tls_remote.empty()) - { - const std::string subj = TLSRemote::sanitize_x509_name(subject); - const std::string common_name = TLSRemote::sanitize_common_name(OpenSSLPKI::x509_get_field(current_cert, NID_commonName)); - TLSRemote::log(self->config->tls_remote, subj, common_name); - if (!TLSRemote::test(self->config->tls_remote, subj, common_name)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- tls-remote match failed"); - preverify_ok = false; - } - } - } - - return preverify_ok; - } - - static int verify_callback_server(int preverify_ok, X509_STORE_CTX *ctx) - { - // get the OpenSSL SSL object - ::SSL* ssl = (::SSL*) X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - - // get OpenSSLContext - const OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data (ssl, SSL::context_data_index); - - // get OpenSSLContext::SSL - SSL* self_ssl = (SSL *) SSL_get_ex_data (ssl, SSL::ssl_data_index); - - // get error code - const int err = X509_STORE_CTX_get_error(ctx); - - // get depth - const int depth = X509_STORE_CTX_get_error_depth(ctx); - - // get current certificate - X509* current_cert = X509_STORE_CTX_get_current_cert (ctx); - - // log subject - if (self->config->flags & SSLConst::LOG_VERIFY_STATUS) - OPENVPN_LOG_SSL(cert_status_line(preverify_ok, depth, err, - OpenSSLPKI::x509_get_subject(current_cert), - OpenSSLPKI::x509_get_signature_algorithm(current_cert))); - - // record cert error in authcert - if (!preverify_ok && self_ssl->authcert) - self_ssl->authcert->add_fail(depth, cert_fail_code(err), X509_verify_cert_error_string(err)); - - if (depth == 1) // issuer cert - { - // save the issuer cert fingerprint - if (self_ssl->authcert) - { - static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LENGTH, "size inconsistency"); - unsigned int digest_len = sizeof(AuthCert::issuer_fp); - if (!X509_digest (current_cert, EVP_sha1 (), self_ssl->authcert->issuer_fp, &digest_len)) - preverify_ok = false; - } - } - else if (depth == 0) // leaf cert - { - // verify ns-cert-type - if (self->ns_cert_type_defined() && !self->verify_ns_cert_type(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad ns-cert-type in leaf certificate"); - if (self_ssl->authcert) - self_ssl->authcert->add_fail(depth, AuthCert::Fail::BAD_CERT_TYPE, "bad ns-cert-type in leaf certificate"); - preverify_ok = false; - } - - // verify X509 key usage - if (self->x509_cert_ku_defined() && !self->verify_x509_cert_ku(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 key usage in leaf certificate"); - if (self_ssl->authcert) - self_ssl->authcert->add_fail(depth, AuthCert::Fail::BAD_CERT_TYPE, "bad X509 key usage in leaf certificate"); - preverify_ok = false; - } - - // verify X509 extended key usage - if (self->x509_cert_eku_defined() && !self->verify_x509_cert_eku(current_cert)) - { - OPENVPN_LOG_SSL("VERIFY FAIL -- bad X509 extended key usage in leaf certificate"); - if (self_ssl->authcert) - self_ssl->authcert->add_fail(depth, AuthCert::Fail::BAD_CERT_TYPE, "bad X509 extended key usage in leaf certificate"); - preverify_ok = false; - } - - if (self_ssl->authcert) - { - // save the Common Name - self_ssl->authcert->cn = OpenSSLPKI::x509_get_field(current_cert, NID_commonName); - - // save the leaf cert serial number - const ASN1_INTEGER *ai = X509_get_serialNumber(current_cert); - self_ssl->authcert->sn = extract_serial_number(ai); - } - } - - // x509-track enabled? - if (self_ssl->authcert && self_ssl->authcert->x509_track) - x509_track_extract_from_cert(current_cert, - depth, - self->config->x509_track_config, - *self_ssl->authcert->x509_track); - - return preverify_ok || self->deferred_cert_verify_failsafe(*self_ssl); - } - - // Print debugging information on SSL/TLS session negotiation. - static void info_callback (const ::SSL *s, int where, int ret) - { - if (where & SSL_CB_LOOP) - { - OPENVPN_LOG_SSL("SSL state (" << (where & SSL_ST_CONNECT ? "connect" : where & SSL_ST_ACCEPT ? "accept" : "undefined") << "): " << SSL_state_string_long(s)); - } - else if (where & SSL_CB_ALERT) - { - OPENVPN_LOG_SSL("SSL alert (" << (where & SSL_CB_READ ? "read" : "write") << "): " << SSL_alert_type_string_long(ret) << ": " << SSL_alert_desc_string_long(ret)); - } - } - - static int tls_ticket_key_callback(::SSL *ssl, - unsigned char key_name[16], - unsigned char iv[EVP_MAX_IV_LENGTH], - ::EVP_CIPHER_CTX *ctx, - ::HMAC_CTX *hctx, - int enc) - { - // get OpenSSLContext - const OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data (ssl, SSL::context_data_index); - if (!self) - return -1; - - // get user-defined session ticket handler - TLSSessionTicketBase* t = self->config->session_ticket_handler; - if (!t) - return -1; - - if (enc) - { - // create new ticket - TLSSessionTicketBase::Name name; - TLSSessionTicketBase::Key key; - - switch (t->create_session_ticket_key(name, key)) - { - case TLSSessionTicketBase::NO_TICKET: - case TLSSessionTicketBase::TICKET_EXPIRING: // doesn't really make sense for enc==1? - // NOTE: OpenSSL may segfault on a zero return. - // This appears to be fixed by: - // commit dbdb96617cce2bd4356d57f53ecc327d0e31f2ad - // Author: Todd Short <tshort@akamai.com> - // Date: Thu May 12 18:16:52 2016 -0400 - // Fix session ticket and SNI - //OPENVPN_LOG("tls_ticket_key_callback: create: no ticket or expiring ticket"); -#if OPENSSL_VERSION_NUMBER < 0x1000212fL // 1.0.2r - if (!randomize_name_key(name, key)) - return -1; - // fallthrough -#else - return 0; -#endif - case TLSSessionTicketBase::TICKET_AVAILABLE: - if (!RAND_bytes(iv, EVP_MAX_IV_LENGTH)) - return -1; - if (!tls_ticket_init_cipher_hmac(key, iv, ctx, hctx, enc)) - return -1; - static_assert(TLSSessionTicketBase::Name::SIZE == 16, "unexpected name size"); - std::memcpy(key_name, name.value_, TLSSessionTicketBase::Name::SIZE); - //OPENVPN_LOG("tls_ticket_key_callback: created ticket"); - return 1; - default: - //OPENVPN_LOG("tls_ticket_key_callback: create: bad ticket"); - return -1; - } - } - else - { - // lookup existing ticket - static_assert(TLSSessionTicketBase::Name::SIZE == 16, "unexpected name size"); - const TLSSessionTicketBase::Name name(key_name); - TLSSessionTicketBase::Key key; - - switch (t->lookup_session_ticket_key(name, key)) - { - case TLSSessionTicketBase::TICKET_AVAILABLE: - if (!tls_ticket_init_cipher_hmac(key, iv, ctx, hctx, enc)) - return -1; - //OPENVPN_LOG("tls_ticket_key_callback: found ticket"); - return 1; - case TLSSessionTicketBase::TICKET_EXPIRING: - if (!tls_ticket_init_cipher_hmac(key, iv, ctx, hctx, enc)) - return -1; - //OPENVPN_LOG("tls_ticket_key_callback: expiring ticket"); - return 2; - case TLSSessionTicketBase::NO_TICKET: - //OPENVPN_LOG("tls_ticket_key_callback: lookup: no ticket"); - return 0; - default: - //OPENVPN_LOG("tls_ticket_key_callback: lookup: bad ticket"); - return -1; - } - } - } - - static bool tls_ticket_init_cipher_hmac(const TLSSessionTicketBase::Key& key, - unsigned char iv[EVP_MAX_IV_LENGTH], - ::EVP_CIPHER_CTX *ctx, - ::HMAC_CTX *hctx, - const int enc) - { - static_assert(TLSSessionTicketBase::Key::CIPHER_KEY_SIZE == 32, "unexpected cipher key size"); - if (!EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key.cipher_value_, iv, enc)) - return false; - if (!HMAC_Init_ex(hctx, key.hmac_value_, TLSSessionTicketBase::Key::HMAC_KEY_SIZE, EVP_sha256(), nullptr)) - return false; - return true; - } - - static bool randomize_name_key(TLSSessionTicketBase::Name& name, - TLSSessionTicketBase::Key& key) - { - if (!RAND_bytes(name.value_, TLSSessionTicketBase::Name::SIZE)) - return false; - if (!RAND_bytes(key.cipher_value_, TLSSessionTicketBase::Key::CIPHER_KEY_SIZE)) - return false; - if (!RAND_bytes(key.hmac_value_, TLSSessionTicketBase::Key::HMAC_KEY_SIZE)) - return false; - return true; - } - -#if OPENSSL_VERSION_NUMBER >= 0x10101000L - - static int client_hello_callback(::SSL *s, int *al, void *) - { - std::string sni_name; - - // get OpenSSLContext - OpenSSLContext* self = (OpenSSLContext*) SSL_get_ex_data(s, SSL::context_data_index); - - // get OpenSSLContext::SSL - SSL* self_ssl = (SSL *) SSL_get_ex_data(s, SSL::ssl_data_index); - - try { - // get the SNI from the client hello - sni_name = client_hello_get_sni(s); - - // process the SNI name, if provided - if (!sni_name.empty()) - { - // save the SNI name in authcert - if (self_ssl->authcert) - self_ssl->authcert->sni = sni_name; - - // ignore the SNI if no handler was provided - if (self->config->sni_handler) - { - // get an alternative SSLFactoryAPI from the sni_handler - SSLFactoryAPI::Ptr fapi; - try { - SNI::Metadata::UPtr sm; - fapi = self->config->sni_handler->sni_hello(sni_name, sm, self->config); - if (self_ssl->authcert) - self_ssl->authcert->sni_metadata = std::move(sm); - } - catch (const std::exception& e) - { - OPENVPN_LOG("SNI HANDLER ERROR: " << e.what()); - return sni_error(e.what(), SSL_AD_INTERNAL_ERROR, self, self_ssl, al); - } - if (!fapi) - return sni_error("SNI name not found", SSL_AD_UNRECOGNIZED_NAME, self, self_ssl, al); - - // make sure that returned SSLFactoryAPI is an OpenSSLContext - self_ssl->sni_ctx = fapi.dynamic_pointer_cast<OpenSSLContext>(); - if (!self_ssl->sni_ctx) - throw Exception("sni_handler returned wrong kind of SSLFactoryAPI"); - - // don't modify SSL CTX if the returned SSLFactoryAPI is ourself - if (fapi.get() != self) - { - SSL_set_SSL_CTX(s, self_ssl->sni_ctx->ctx); - self_ssl->set_parent(self_ssl->sni_ctx.get()); - } - } - } - return SSL_CLIENT_HELLO_SUCCESS; - } - catch (const std::exception& e) - { - OPENVPN_LOG("SNI exception in OpenSSLContext, SNI=" << sni_name << " : " << e.what()); - *al = SSL_AD_INTERNAL_ERROR; - return SSL_CLIENT_HELLO_ERROR; - } - } - - static int sni_error(std::string err, - const int ssl_ad_error, - OpenSSLContext* self, - SSL* self_ssl, - int* al) - { - if (self_ssl->authcert) - self_ssl->authcert->add_fail(0, AuthCert::Fail::SNI_ERROR, std::move(err)); - if (self->deferred_cert_verify_failsafe(*self_ssl)) - return SSL_CLIENT_HELLO_SUCCESS; - *al = ssl_ad_error; - return SSL_CLIENT_HELLO_ERROR; - } - - static size_t sni_get_len(ConstBuffer& buf) - { - size_t ret = buf.pop_front() << 8; - ret += buf.pop_front(); - return ret; - } - - static std::string client_hello_get_sni(::SSL* s) - { - const unsigned char *p; - size_t remaining; - if (!SSL_client_hello_get0_ext(s, TLSEXT_TYPE_server_name, &p, &remaining)) - return std::string(); - - // For safety, map a ConstBuffer onto returned OpenSSL TLSEXT_TYPE_server_name data. - ConstBuffer buf(p, remaining, true); - - // Extract the length of the supplied list of names, - // and check that it matches size of remaining data - // in buf. - { - const size_t len = sni_get_len(buf); - if (len != buf.size()) - throw Exception("bad name list size"); - } - - // Next byte must be TLSEXT_NAMETYPE_host_name. - if (buf.pop_front() != TLSEXT_NAMETYPE_host_name) - throw Exception("expecting TLSEXT_NAMETYPE_host_name"); - - // Now try to extract the SNI name. - { - const size_t len = sni_get_len(buf); - if (len > buf.size()) - throw Exception("bad name size"); - if (!Unicode::is_valid_utf8_uchar_buf(buf.c_data(), len, 1024 | Unicode::UTF8_NO_CTRL)) - throw Exception("invalid UTF-8"); - return std::string((const char *)buf.c_data(), len); - } - } -#endif - - // Return true if we should continue with authentication - // even though there was an error, because the user has - // enabled SSLConst::DEFERRED_CERT_VERIFY and wants the - // error to be logged in authcert so that it can be handled - // by a higher layer. - bool deferred_cert_verify_failsafe(const SSL& ssl) const - { - return (config->flags & SSLConst::DEFERRED_CERT_VERIFY) - && ssl.authcert // failsafe: don't defer error unless - && ssl.authcert->is_fail(); // authcert has recorded it - } - - void erase() - { - if (epki) - { - delete epki; - epki = nullptr; - } - if (ctx) - { - SSL_CTX_free(ctx); - ctx = nullptr; - } - } - - Config::Ptr config; - SSL_CTX* ctx = nullptr; - ExternalPKIImpl* epki = nullptr; - OpenSSLSessionCache::Ptr sess_cache; // client-side only - }; - -#ifdef OPENVPN_NO_EXTERN - int OpenSSLContext::SSL::ssl_data_index = -1; - int OpenSSLContext::SSL::context_data_index = -1; -#endif - -#if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(OPENVPN_NO_EXTERN) - SSL_METHOD OpenSSLContext::SSL::ssl23_method_client_; - SSL_METHOD OpenSSLContext::SSL::ssl23_method_server_; -#endif - - inline const std::string get_ssl_library_version() - { - return OPENSSL_VERSION_TEXT; - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/ssl/tlsver.hpp b/Sources/OpenVPN3/openvpn/openssl/ssl/tlsver.hpp deleted file mode 100644 index 631be00..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/ssl/tlsver.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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-2020 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/>. - -// OpenSSL specific methods for TLS version - -#pragma once - -#include <openvpn/ssl/tlsver.hpp> - -namespace openvpn { - namespace TLSVersion { - - inline int toTLSVersion(const Type version) - { - - switch (version) - { - case UNDEF: - default: - return 0; - case V1_0: - return TLS1_VERSION; - case V1_1: - return TLS1_1_VERSION; - case V1_2: - return TLS1_2_VERSION; - case V1_3: -#ifdef TLS1_3_VERSION - return TLS1_3_VERSION; -#else - // TLS 1.3 is SSL 3.4 - return 0x0304; -#endif - } - } - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/util/engine.hpp b/Sources/OpenVPN3/openvpn/openssl/util/engine.hpp deleted file mode 100644 index 1589d77..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/engine.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// 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-2020 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/>. - -// Method to set up a particular OpenSSL engine type - -#ifndef OPENVPN_OPENSSL_UTIL_ENGINE_H -#define OPENVPN_OPENSSL_UTIL_ENGINE_H - -#include <string> - -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif - -#include <openvpn/common/exception.hpp> -#include <openvpn/openssl/util/error.hpp> - -namespace openvpn { - - OPENVPN_EXCEPTION(openssl_engine_error); - - inline void openssl_setup_engine (const std::string& engine) - { -#ifndef OPENSSL_NO_ENGINE - ENGINE_load_builtin_engines (); - - if (engine == "auto") - { - ENGINE_register_all_complete (); - return; - } - - ENGINE *e = ENGINE_by_id (engine.c_str()); - if (!e) - throw openssl_engine_error(); - if (!ENGINE_set_default (e, ENGINE_METHOD_ALL)) - throw openssl_engine_error(); -#endif - } - -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_UTIL_ENGINE_H diff --git a/Sources/OpenVPN3/openvpn/openssl/util/error.hpp b/Sources/OpenVPN3/openvpn/openssl/util/error.hpp deleted file mode 100644 index db5620e..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/error.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// 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-2020 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/>. - -// OpenSSL exception class that allows a full OpenSSL error stack -// to be represented. - -#ifndef OPENVPN_OPENSSL_UTIL_ERROR_H -#define OPENVPN_OPENSSL_UTIL_ERROR_H - -#include <string> -#include <openssl/err.h> -#include <openssl/ssl.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/error/excode.hpp> - -namespace openvpn { - - // string exception class - class OpenSSLException : public ExceptionCode - { - public: - OPENVPN_EXCEPTION(ssl_exception_index); - - enum { - MAX_ERRORS = 8 - }; - - OpenSSLException() - { - ssl_err = -1; - init_error("OpenSSL"); - } - - explicit OpenSSLException(const std::string& error_text) - { - ssl_err = -1; - init_error(error_text.c_str()); - } - - explicit OpenSSLException(const int ssl_error) - { - init_ssl_error(ssl_error, "OpenSSL"); - } - - explicit OpenSSLException(const std::string& error_text, const int ssl_error) - { - init_ssl_error(ssl_error, error_text.c_str()); - } - - virtual const char* what() const throw() { return errtxt.c_str(); } - std::string what_str() const { return errtxt; } - - size_t len() const { return n_err; } - unsigned long operator[](const size_t i) const - { - if (i < n_err) - return errstack[i]; - else - throw ssl_exception_index(); - } - - int ssl_error() const { return ssl_err; } - - virtual ~OpenSSLException() throw() {} - - static const char *ssl_error_text(const int ssl_error, bool *unknown = nullptr) - { - switch (ssl_error) - { - case SSL_ERROR_NONE: - return "SSL_ERROR_NONE"; - case SSL_ERROR_ZERO_RETURN: - return "SSL_ERROR_ZERO_RETURN"; - case SSL_ERROR_WANT_READ: - return "SSL_ERROR_WANT_READ"; - case SSL_ERROR_WANT_WRITE: - return "SSL_ERROR_WANT_WRITE"; - case SSL_ERROR_WANT_CONNECT: - return "SSL_ERROR_WANT_CONNECT"; - case SSL_ERROR_WANT_ACCEPT: - return "SSL_ERROR_WANT_ACCEPT"; - case SSL_ERROR_WANT_X509_LOOKUP: - return "SSL_ERROR_WANT_X509_LOOKUP"; - case SSL_ERROR_SYSCALL: - return "SSL_ERROR_SYSCALL"; - case SSL_ERROR_SSL: - return "SSL_ERROR_SSL"; - default: - if (unknown) - *unknown = true; - return "(unknown SSL error)"; - } - } - - private: - void init_error(const char *error_text) - { - const char *prefix = ": "; - std::ostringstream tmp; - char buf[256]; - - tmp << error_text; - - n_err = 0; - while (unsigned long err = ERR_get_error()) - { - if (n_err < MAX_ERRORS) - errstack[n_err++] = err; - ERR_error_string_n(err, buf, sizeof(buf)); - tmp << prefix << buf; - prefix = " / "; - - // for certain OpenSSL errors, translate them to an OpenVPN error code, - // so they can be propagated up to the higher levels (such as UI level) - switch (ERR_GET_REASON(err)) - { - case SSL_R_CERTIFICATE_VERIFY_FAILED: - set_code(Error::CERT_VERIFY_FAIL, true); - break; - case PEM_R_BAD_PASSWORD_READ: - case PEM_R_BAD_DECRYPT: - set_code(Error::PEM_PASSWORD_FAIL, true); - break; - case SSL_R_UNSUPPORTED_PROTOCOL: - set_code(Error::TLS_VERSION_MIN, true); - break; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - // These error codes are not available in older OpenSSL versions - case SSL_R_CA_MD_TOO_WEAK: - set_code(Error::SSL_CA_MD_TOO_WEAK, true); - break; - case SSL_R_CA_KEY_TOO_SMALL: - set_code(Error::SSL_CA_KEY_TOO_SMALL, true); - break; -#endif // OpenSSL >= 1.1.0 - case SSL_R_DH_KEY_TOO_SMALL: - set_code(Error::SSL_DH_KEY_TOO_SMALL, true); - break; - } - } - errtxt = tmp.str(); - } - - void init_ssl_error(const int ssl_error, const char *error_text) - { - bool unknown = false; - ssl_err = ssl_error; - const char *text = ssl_error_text(ssl_error, &unknown); - if (unknown || ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL) - { - init_error(error_text); - errtxt += " ("; - errtxt += text; - errtxt += ")"; - } - else - { - errtxt = error_text; - errtxt += ": "; - errtxt += text; - } - } - - size_t n_err; - unsigned long errstack[MAX_ERRORS]; - std::string errtxt; - int ssl_err; - }; - - // return an OpenSSL error string - - inline std::string openssl_error() - { - OpenSSLException err; - return err.what_str(); - } - - inline std::string openssl_error(const int ssl_error) - { - OpenSSLException err(ssl_error); - return err.what_str(); - } - - inline void openssl_clear_error_stack() - { - while (ERR_get_error()) - ; - } - -} // namespace openvpn - -#endif // OPENVPN_OPENSSL_UTIL_ERROR_H diff --git a/Sources/OpenVPN3/openvpn/openssl/util/init.hpp b/Sources/OpenVPN3/openvpn/openssl/util/init.hpp deleted file mode 100644 index 7b121f3..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/init.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// 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-2020 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 <openssl/opensslv.h> - -// OpenSSL 1.1.0 does not require an explicit init, in fact the -// asio init for 1.1.0 is a noop, see also OPENSSL_init_ssl man page - -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) -#define OPENSSL_NEEDS_INIT - -// Instantiate this object to ensure openssl is initialised. -#ifdef USE_ASIO -#include <asio/ssl/detail/openssl_init.hpp> - typedef asio::ssl::detail::openssl_init<> openssl_init; -#else - #error no OpenSSL init code (USE_ASIO needed for OpenSSL < 1.1) -#endif -#endif \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/openssl/util/pem.hpp b/Sources/OpenVPN3/openvpn/openssl/util/pem.hpp deleted file mode 100644 index a3ea1cb..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/pem.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// 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 */ diff --git a/Sources/OpenVPN3/openvpn/openssl/util/rand.hpp b/Sources/OpenVPN3/openvpn/openssl/util/rand.hpp deleted file mode 100644 index 6fecee6..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/rand.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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-2020 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/>. - -// Wrap the OpenSSL Cryptographic Random API defined in <openssl/rand.h> -// so that it can be used as the primary source of cryptographic entropy by -// the OpenVPN core. - -#ifndef OPENVPN_OPENSSL_UTIL_RAND_H -#define OPENVPN_OPENSSL_UTIL_RAND_H - -#include <openssl/rand.h> - -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - class OpenSSLRandom : public RandomAPI - { - public: - OPENVPN_EXCEPTION(rand_error_openssl); - - typedef RCPtr<OpenSSLRandom> Ptr; - - OpenSSLRandom(const bool prng) - { - } - - virtual std::string name() const - { - return "OpenSSLRandom"; - } - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const - { - return true; - } - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) - { - if (!rndbytes(buf, size)) - throw rand_error_openssl("rand_bytes"); - } - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) - { - return rndbytes(buf, size); - } - - private: - bool rndbytes(unsigned char *buf, size_t size) - { - return RAND_bytes(buf, size) == 1; - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/openssl/util/reseed.hpp b/Sources/OpenVPN3/openvpn/openssl/util/reseed.hpp deleted file mode 100644 index 3a7078c..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/reseed.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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-2020 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 - -// seed OpenSSL's random number generator with /dev/urandom - -#include <openssl/rand.h> - -#include <openvpn/random/devurand.hpp> - -namespace openvpn { - inline void openssl_reseed_rng() - { - unsigned char entropy[64]; - - RandomAPI::Ptr rng(new DevURand); - rng->rand_bytes(entropy, sizeof(entropy)); - - RAND_seed(entropy, sizeof(entropy)); - } -} diff --git a/Sources/OpenVPN3/openvpn/openssl/util/tokenencrypt.hpp b/Sources/OpenVPN3/openvpn/openssl/util/tokenencrypt.hpp deleted file mode 100644 index 08ac6a1..0000000 --- a/Sources/OpenVPN3/openvpn/openssl/util/tokenencrypt.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// 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-2020 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_CRYPTO_TOKENENCRYPT_H -#define OPENVPN_CRYPTO_TOKENENCRYPT_H - -#include <string> -#include <atomic> -#include <cstdint> // for std::uint8_t - -#include <openssl/evp.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/openssl/util/error.hpp> - -#include <openvpn/openssl/compat.hpp> - -namespace openvpn { - class TokenEncrypt - { - public: - class Key - { - public: - static constexpr size_t SIZE = 16; - - Key(RandomAPI& rng) - { - rng.assert_crypto(); - rng.rand_bytes(data, sizeof(data)); - } - - private: - friend class TokenEncrypt; - std::uint8_t data[SIZE]; - }; - - // mode parameter for constructor - enum { - ENCRYPT = 1, - DECRYPT = 0 - }; - - TokenEncrypt(const Key& key, const int mode) - { - ctx = EVP_CIPHER_CTX_new (); - EVP_CIPHER_CTX_reset (ctx); - if (!EVP_CipherInit_ex(ctx, EVP_aes_128_ecb(), nullptr, key.data, nullptr, mode)) - { - EVP_CIPHER_CTX_free(ctx); - throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[1] failed"); - } - EVP_CIPHER_CTX_set_padding(ctx, 0); - } - - ~TokenEncrypt() - { - EVP_CIPHER_CTX_free(ctx); - } - - // Do the encrypt/decrypt - void operator()(std::uint8_t* dest, const std::uint8_t* src, const int size) - { - // NOTE: since this algorithm uses the ECB block cipher mode, - // it should only be used to encrypt/decrypt a message which - // is exactly equal to the AES block size (16 bytes). - if (size != EVP_CIPHER_CTX_block_size(ctx)) - throw Exception("TokenEncrypt: encrypt/decrypt data must be equal to AES block size"); - int outlen=0; - if (!EVP_CipherInit_ex(ctx, nullptr, nullptr, nullptr, nullptr, -1)) - throw OpenSSLException("TokenEncrypt: EVP_CipherInit_ex[2] failed"); - if (!EVP_CipherUpdate(ctx, dest, &outlen, src, size)) - throw OpenSSLException("TokenEncrypt: EVP_CipherUpdate failed"); - // NOTE: we skip EVP_CipherFinal_ex because we are running in ECB mode without padding - if (outlen != size) - throw Exception("TokenEncrypt: unexpected output length=" + std::to_string(outlen) + " expected=" + std::to_string(size)); - } - - private: - TokenEncrypt(const TokenEncrypt&) = delete; - TokenEncrypt& operator=(const TokenEncrypt&) = delete; - - EVP_CIPHER_CTX* ctx; - }; - - struct TokenEncryptDecrypt - { - TokenEncryptDecrypt(const TokenEncrypt::Key& key) - : encrypt(key, TokenEncrypt::ENCRYPT), - decrypt(key, TokenEncrypt::DECRYPT) - { - } - - TokenEncrypt encrypt; - TokenEncrypt decrypt; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/options/continuation.hpp b/Sources/OpenVPN3/openvpn/options/continuation.hpp deleted file mode 100644 index 192b17b..0000000 --- a/Sources/OpenVPN3/openvpn/options/continuation.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// 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-2020 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/>. - -// Client-side code to handle pushed option list "continuations". -// This is where multiple option lists are pushed by the server, -// if an option list doesn't fit into the standard 1024 byte buffer. -// This class will aggregate the options. - -#pragma once - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - - struct PushOptionsBase : public RC<thread_unsafe_refcount> - { - typedef RCPtr<PushOptionsBase> Ptr; - - OptionList multi; - OptionList singleton; - }; - - // Aggregate pushed option continuations into a singular option list. - // Note that map is not updated until list is complete. - class OptionListContinuation : public OptionList - { - public: - OPENVPN_SIMPLE_EXCEPTION(olc_complete); // add called when object is already complete - - OptionListContinuation(const PushOptionsBase::Ptr& push_base_arg) - : push_base(push_base_arg) - { - // Prepend from base where multiple options of the same type can aggregate, - // so that server-pushed options will be at the end of list. - if (push_base) - extend(push_base->multi, nullptr); - } - - OptionListContinuation() - { - } - - // call with option list fragments - void add(const OptionList& other, OptionList::FilterBase* filt) - { - if (!complete_) - { - partial_ = true; - extend(other, filt); - if (!continuation(other)) - { - if (push_base) - { - // Append from base where only a single instance of each option makes sense, - // provided that option wasn't already pushed by server. - update_map(); - extend_nonexistent(push_base->singleton); - } - update_map(); - complete_ = true; - } - } - else - throw olc_complete(); - } - - // returns true if add() was called at least once - bool partial() const { return partial_; } - - // returns true if option list is complete - bool complete() const { return complete_; } - - private: - static bool continuation(const OptionList& opt) - { - const Option *o = opt.get_ptr("push-continuation"); - return o && o->size() >= 2 && o->ref(1) == "2"; - } - - bool partial_ = false; - bool complete_ = false; - - PushOptionsBase::Ptr push_base; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/options/continuation_fragment.hpp b/Sources/OpenVPN3/openvpn/options/continuation_fragment.hpp deleted file mode 100644 index 5356d05..0000000 --- a/Sources/OpenVPN3/openvpn/options/continuation_fragment.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// 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-2020 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/>. - -// Server-side code to fragment an oversized options buffer -// into multiple buffers using the push-continuation option. - -#pragma once - -#include <string> -#include <vector> - -#include <openvpn/common/lex.hpp> -#include <openvpn/buffer/bufstr.hpp> - -namespace openvpn { - - // Fragment a long PUSH_REPLY buffer into multiple - // buffers using the push-continuation option. - class PushContinuationFragment : public std::vector<BufferPtr> - { - public: - // maximum allowable fragment size (excluding null termination - // that will be appended by push_reply() in servproto.hpp). - static constexpr size_t FRAGMENT_SIZE = 1023; - - OPENVPN_EXCEPTION(push_continuation_fragment_error); - - static bool should_fragment(const Buffer& buf) - { - return buf.size() > FRAGMENT_SIZE; - } - - PushContinuationFragment(const Buffer& buf) - { - // size of ",push-continuation n" - const size_t push_continuation_len = 20; - - // loop over options - bool did_continuation = false; - Lex lex(buf); - while (lex.defined()) - { - // get escaped opt - const std::string escaped_opt = lex.next(); - - // create first buffer on loop startup - if (empty()) - append_new_buffer(); - - // ready to finalize this outbut buffer and move on to next? - // (the +1 is for escaped_opt comma) - if (back()->size() + escaped_opt.size() + push_continuation_len + 1 > FRAGMENT_SIZE) - { - did_continuation = true; - append_push_continuation(*back(), false); - append_new_buffer(); - } - - back()->push_back(','); - buf_append_string(*back(), escaped_opt); - } - - // push final push-continuation - if (!empty() && did_continuation) - append_push_continuation(*back(), true); - } - - static BufferPtr defragment(const std::vector<BufferPtr>& bv) - { - // exit cases where no need to defrag - if (bv.empty()) - return BufferPtr(); - if (bv.size() == 1) - return bv[0]; - - // compute length - size_t total_size = 0; - for (const auto &e : bv) - total_size += e->size(); - - // allocate return buffer - BufferPtr ret(new BufferAllocated(total_size, 0)); - buf_append_string(*ret, "PUSH_REPLY"); - - // terminators - static const char pc1[] = ",push-continuation 1"; - static const char pc2[] = ",push-continuation 2"; - - // build return buffer - const size_t size = bv.size(); - for (size_t i = 0; i < size; ++i) - { - const Buffer& buf = *bv[i]; - const char *pc = (i == size - 1) ? pc1 : pc2; - if (string::starts_with(buf, "PUSH_REPLY,") && string::ends_with(buf, pc)) - { - Buffer b = buf; - b.advance(10); // advance past "PUSH_REPLY" - b.set_size(b.size() - 20); // truncate ",push-continuation n" - ret->append(b); - } - else - throw push_continuation_fragment_error("badly formatted fragments"); - } - return ret; - } - - private: - class Lex - { - public: - Lex(const Buffer& buf) - : buf_(buf) - { - if (!string::starts_with(buf_, "PUSH_REPLY,")) - throw push_continuation_fragment_error("not a valid PUSH_REPLY message"); - buf_.advance(11); - } - - bool defined() - { - return !buf_.empty(); - } - - std::string next() - { - StandardLex lex; - std::string ret; - while (defined()) - { - const char c = buf_.pop_front(); - lex.put(c); - if (lex.get() == ',' && !(lex.in_quote() || lex.in_backslash())) - return ret; - ret += c; - } - return ret; - } - - private: - Buffer buf_; - }; - - // create a new PUSH_REPLY buffer - void append_new_buffer() - { - // include extra byte for null termination - BufferPtr bp = new BufferAllocated(FRAGMENT_SIZE+1, 0); - buf_append_string(*bp, "PUSH_REPLY"); - push_back(std::move(bp)); - } - - // append a push-continuation directive to buffer - static void append_push_continuation(Buffer& buf, bool end) - { - buf_append_string(buf, ",push-continuation "); - buf.push_back(end ? '1' : '2'); - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/options/merge.hpp b/Sources/OpenVPN3/openvpn/options/merge.hpp deleted file mode 100644 index 7699678..0000000 --- a/Sources/OpenVPN3/openvpn/options/merge.hpp +++ /dev/null @@ -1,496 +0,0 @@ -// 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-2020 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/>. - -// This class will read a standard OpenVPN config file that might contain -// references to other files, and it will merge the included files into the -// config file, using inline configuration syntax, to produce a single, -// unified config file. - -#ifndef OPENVPN_OPTIONS_MERGE_H -#define OPENVPN_OPTIONS_MERGE_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/path.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/splitlines.hpp> - -namespace openvpn { - - class ProfileMerge - { - // internal flags - enum { - F_MAY_INCLUDE_KEY_DIRECTION = (1<<0), - F_PKCS12 = (1<<1), - F_HTTP_PROXY = (1<<2), - }; - - // limits - enum { - MAX_FN_LIST_SIZE=16, - }; - - public: - OPENVPN_EXCEPTION(merge_error); - - // public status values - enum Status { - MERGE_UNDEFINED, - MERGE_SUCCESS, - MERGE_EXCEPTION, - MERGE_OVPN_EXT_FAIL, - MERGE_OVPN_FILE_FAIL, - MERGE_REF_FAIL, - MERGE_MULTIPLE_REF_FAIL, - }; - - // merge status - Status status() const { return status_; } - const std::string& error() const { return error_; } - - // merge path basename - const std::string& basename() const { return basename_; } - - // final unified profile - const std::string& profile_content() const { return profile_content_; } - - // list of all reference paths successfully read - const std::vector<std::string>& ref_path_list() const { return ref_succeed_list_; } - - // merge status as a string - const char *status_string() const - { - switch (status_) - { - case MERGE_UNDEFINED: - return "MERGE_UNDEFINED"; - case MERGE_SUCCESS: - return "MERGE_SUCCESS"; - case MERGE_EXCEPTION: - return "MERGE_EXCEPTION"; - case MERGE_OVPN_EXT_FAIL: - return "MERGE_OVPN_EXT_FAIL"; - case MERGE_OVPN_FILE_FAIL: - return "MERGE_OVPN_FILE_FAIL"; - case MERGE_REF_FAIL: - return "MERGE_REF_FAIL"; - case MERGE_MULTIPLE_REF_FAIL: - return "MERGE_MULTIPLE_REF_FAIL"; - default: - return "MERGE_?"; - } - } - - // allow following of external file references - enum Follow { - FOLLOW_NONE, - FOLLOW_PARTIAL, - FOLLOW_FULL, - }; - - ProfileMerge(const std::string& profile_path, - const std::string& profile_ext, - const std::string& profile_dir_override, - const Follow follow_references, - const size_t max_line_len, - const size_t max_size) - : status_(MERGE_UNDEFINED) - { - try { - size_t total_size = 0; - - // read the profile - std::string orig_profile_content; - std::string profile_dir; - try { - profile_dir = !profile_dir_override.empty() ? profile_dir_override : path::dirname(profile_path); - basename_ = path::basename(profile_path); - const std::string ext = path::ext(basename_); - if (profile_ext.empty() || string::strcasecmp(ext, profile_ext) == 0) - { - orig_profile_content = read_text_utf8(profile_path, max_size); - total_size = orig_profile_content.size(); - } - else - { - status_ = MERGE_OVPN_EXT_FAIL; - error_ = std::string("ERR_PROFILE_NO_OVPN_EXTENSION: ") + basename_; - return; - } - } - catch (const file_is_binary& e) - { - status_ = MERGE_OVPN_FILE_FAIL; - error_ = std::string("ERR_PROFILE_FILE_IS_BINARY: ") + e.what(); - return; - } - catch (const file_too_large& e) - { - status_ = MERGE_OVPN_FILE_FAIL; - error_ = std::string("ERR_PROFILE_FILE_TOO_LARGE: ") + e.what(); - return; - } - catch (const std::exception& e) - { - status_ = MERGE_OVPN_FILE_FAIL; - error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); - return; - } - - // expand the profile - expand_profile(orig_profile_content, profile_dir, follow_references, max_line_len, max_size, total_size); - } - catch (const std::exception& e) - { - status_ = MERGE_EXCEPTION; - error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); - } - } - - static std::string merge(const std::string& profile_path, - const std::string& profile_ext, - const std::string& profile_dir_override, - const Follow follow_references, - const size_t max_line_len, - const size_t max_size) - { - const ProfileMerge pm(profile_path, profile_ext, profile_dir_override, - follow_references, max_line_len, max_size); - if (pm.status() == ProfileMerge::MERGE_SUCCESS) - return pm.profile_content(); - else - OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); - } - - protected: - ProfileMerge() : status_(MERGE_UNDEFINED) {} - - void expand_profile(const std::string& orig_profile_content, - const std::string& profile_dir, - const Follow follow_references, - const size_t max_line_len, - const size_t max_size, - size_t total_size) - { - if (total_size > max_size) - { - status_ = MERGE_EXCEPTION; - error_ = "ERR_PROFILE_FILE_TOO_LARGE: file too large"; - return; - } - - status_ = MERGE_SUCCESS; - - SplitLines in(orig_profile_content, max_line_len); - int line_num = 0; - bool in_multiline = false; - bool opaque_multiline = false; - Option multiline; - - profile_content_.reserve(orig_profile_content.length()); - while (in(true)) - { - if (in.line_overflow()) - { - status_ = MERGE_EXCEPTION; - error_ = "ERR_PROFILE_LINE_TOO_LONG: line too long"; - return; - } - const std::string& line = in.line_ref(); - bool echo = true; - ++line_num; - if (in_multiline) - { - if (OptionList::is_close_tag(line, multiline.ref(0))) - { - multiline.clear(); - in_multiline = false; - opaque_multiline = false; - } - } - else if (!OptionList::ignore_line(line)) - { - Option opt = Split::by_space<Option, OptionList::LexComment, SpaceMatch, Split::NullLimit>(line); - if (opt.size()) - { - if (OptionList::is_open_tag(opt.ref(0)) && opt.size() == 1) - { - OptionList::untag_open_tag(opt.ref(0)); - multiline = opt; - in_multiline = true; - unsigned int flags = 0; // not used - opaque_multiline = is_fileref_directive(multiline.ref(0), flags); - } - else - { - unsigned int flags = 0; - bool is_fileref = (!opaque_multiline - && opt.size() >= 2 - && is_fileref_directive(opt.ref(0), flags)); - if (is_fileref) - { - // check if http-proxy directive references a creds file - if (flags & F_HTTP_PROXY) - { - is_fileref = false; - if (opt.size() >= 4) - { - const std::string authfile = opt.get(3, 256); - if (authfile != "auto" && authfile != "auto-nct") - { - opt.ref(3) = "auto"; - profile_content_ += opt.escape(false); - profile_content_ += '\n'; - opt.ref(0) = "http-proxy-user-pass"; - opt.ref(1) = authfile; - opt.resize(2); - is_fileref = true; - } - } - } - } - if (is_fileref) - { - // found a directive referencing a file - - // get basename of file and make sure that it doesn't - // attempt to traverse directories (unless - // follow_references == FOLLOW_FULL) - const std::string fn_str = opt.get(1, 256); - const std::string fn = (follow_references == FOLLOW_FULL ? fn_str : path::basename(fn_str)); - if (fn.empty()) - { - echo = false; - status_ = MERGE_REF_FAIL; - error_ = "ERR_PROFILE_NO_FILENAME: filename not provided"; - } - else if (follow_references != FOLLOW_FULL && !path::is_flat(fn)) - { - echo = false; - status_ = MERGE_REF_FAIL; - error_ = std::string("ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn; - if (ref_fail_list_.size() < MAX_FN_LIST_SIZE) - ref_fail_list_.push_back(fn); - } - else - { - std::string path; - std::string file_content; - bool error = false; - try { - if (follow_references == FOLLOW_NONE) - { - status_ = MERGE_EXCEPTION; - error_ = std::string("ERR_PROFILE_CANT_FOLLOW_LINK: ") + fn + ": cannot follow file reference"; - return; - } - path = path::join(profile_dir, fn); - file_content = read_text_utf8(path, max_size); - total_size += file_content.size(); - if (total_size > max_size) - { - status_ = MERGE_EXCEPTION; - error_ = std::string("ERR_PROFILE_FILE_TOO_LARGE: ") + fn + ": file too large"; - return; - } - OptionList::detect_multiline_breakout(file_content, opt.ref(0)); - } - catch (const std::exception& e) - { - error = true; - status_ = MERGE_REF_FAIL; - error_ = std::string("ERR_PROFILE_GENERIC: ") + fn + " : " + e.what(); - if (ref_fail_list_.size() < MAX_FN_LIST_SIZE) - ref_fail_list_.push_back(fn); - } - - if (!error) // succeeded in reading file? - { - // don't echo this line, i.e. opt[], instead expand file_content into profile - echo = false; - - // tls-auth or secret directive may include key-direction parameter - if (flags & F_MAY_INCLUDE_KEY_DIRECTION) - { - std::string key_direction; - if (opt.size() >= 3) - key_direction = opt.get(2, 16); - else - key_direction = "bidirectional"; - profile_content_ += "key-direction " + key_direction + "\n"; - } - - // format file_content for appending to profile - { - std::ostringstream os; - const std::string& tag = opt.ref(0); - string::add_trailing(file_content, '\n'); - os << '<' << tag << ">\n" << file_content << "</" << tag << ">\n"; - profile_content_ += os.str(); - } - - // save file we referenced - if (ref_succeed_list_.size() < MAX_FN_LIST_SIZE) - ref_succeed_list_.push_back(path); - } - } - } - } - } - } - if (echo) - { - profile_content_ += line; - profile_content_ += '\n'; - } - } - - // If more than 2 errors occurred, change status to - // MERGE_MULTIPLE_REF_FAIL and enumerate each failed file. - if (ref_fail_list_.size() >= 2) - { - status_ = MERGE_MULTIPLE_REF_FAIL; - error_ = "ERR_PROFILE_GENERIC: "; - for (size_t i = 0; i < ref_fail_list_.size(); ++i) - { - if (i) - error_ += ", "; - error_ += ref_fail_list_[i]; - } - } - } - - static bool is_fileref_directive(const std::string& d, unsigned int& flags) - { - if (d.length() > 0) - { - switch (d[0]) - { - case 'a': - return d == "auth-user-pass"; - case 'c': - return d == "ca" || d == "cert" || d == "crl-verify"; - case 'd': - return d == "dh"; - case 'e': - return d == "extra-certs"; - case 'h': - if (d == "http-proxy") - { - flags |= F_HTTP_PROXY; - return true; - } - return false; - case 'k': - return d == "key"; -#if 0 // define when we have capability to parse out pkcs12 from profile and add to Keychain (fixme) - case 'p': - if (d == "pkcs12") - { - flags |= F_PKCS12; - return true; - } - return false; -#endif - case 'r': - if (d == "relay-extra-ca") - return true; - if (d == "relay-tls-auth") - { - flags |= F_MAY_INCLUDE_KEY_DIRECTION; - return true; - } - return false; - case 's': - if (d == "static-key") - return true; - return false; - case 't': - if (d == "tls-auth") - { - flags |= F_MAY_INCLUDE_KEY_DIRECTION; - return true; - } - if (d == "tls-crypt") - return true; - if (d == "tls-crypt-v2") - return true; - return false; - } - } - return false; - } - - Status status_; - std::string profile_content_; - std::string basename_; - std::string error_; - std::vector<std::string> ref_fail_list_; - std::vector<std::string> ref_succeed_list_; - }; - - class ProfileMergeFromString : public ProfileMerge - { - public: - ProfileMergeFromString(const std::string& profile_content, - const std::string& ref_dir, - const Follow follow_references, - const size_t max_line_len, - const size_t max_size) - { - try { - // expand the profile - expand_profile(profile_content, ref_dir, follow_references, - max_line_len, max_size, profile_content.size()); - } - catch (const std::exception& e) - { - status_ = MERGE_EXCEPTION; - error_ = std::string("ERR_PROFILE_GENERIC: ") + e.what(); - } - } - - static std::string merge(const std::string& profile_content, - const std::string& ref_dir, - const Follow follow_references, - const size_t max_line_len, - const size_t max_size) - { - const ProfileMergeFromString pm(profile_content, ref_dir, - follow_references, max_line_len, max_size); - if (pm.status() == ProfileMerge::MERGE_SUCCESS) - return pm.profile_content(); - else - OPENVPN_THROW(merge_error, pm.status_string() << ": " << pm.error()); - } - - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/options/sanitize.hpp b/Sources/OpenVPN3/openvpn/options/sanitize.hpp deleted file mode 100644 index b034346..0000000 --- a/Sources/OpenVPN3/openvpn/options/sanitize.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// 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-2020 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/>. - -// Sanitize certain kinds of strings before they are output to the log file. - -#ifndef OPENVPN_OPTIONS_SANITIZE_H -#define OPENVPN_OPTIONS_SANITIZE_H - -#include <string> -#include <cstring> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - - inline std::string render_options_sanitized(const OptionList& opt, const unsigned int render_flags) - { - std::ostringstream out; - for (size_t i = 0; i < opt.size(); i++) - { - const Option& o = opt[i]; -#ifndef OPENVPN_SHOW_SESSION_TOKEN - if (o.get_optional(0, 0) == "auth-token") - out << i << " [auth-token] ..." << std::endl; - else -#endif - out << i << ' ' << o.render(render_flags) << std::endl; - } - return out.str(); - } - - // Remove security-sensitive strings from control message - // so that they will not be output to log file. - inline std::string sanitize_control_message(const std::string& src_str) - { -#ifdef OPENVPN_SHOW_SESSION_TOKEN - return src_str; -#else - const char *src = src_str.c_str(); - char *ret = new char[src_str.length()+1]; - char *dest = ret; - bool redact = false; - int skip = 0; - - for (;;) - { - const char c = *src; - if (c == '\0') - break; - if (c == 'S' && !::strncmp(src, "SESS_ID_", 8)) - { - skip = 7; - redact = true; - } - else if (c == 'e' && !::strncmp(src, "echo ", 5)) - { - skip = 4; - redact = true; - } - - if (c == ',') /* end of redacted item? */ - { - skip = 0; - redact = false; - } - - if (redact) - { - if (skip > 0) - { - --skip; - *dest++ = c; - } - } - else - *dest++ = c; - - ++src; - } - *dest = '\0'; - - const std::string ret_str(ret); - delete [] ret; - return ret_str; -#endif - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/options/servpush.hpp b/Sources/OpenVPN3/openvpn/options/servpush.hpp deleted file mode 100644 index 305775c..0000000 --- a/Sources/OpenVPN3/openvpn/options/servpush.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// 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-2020 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_OPTIONS_SERVPUSH_H -#define OPENVPN_OPTIONS_SERVPUSH_H - -#include <string> -#include <sstream> -#include <ostream> -#include <vector> -#include <utility> // for std::move - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/jsonlib.hpp> - -#ifdef HAVE_JSON -#include <openvpn/common/jsonhelper.hpp> -#endif - -namespace openvpn { - class ServerPushList : public std::vector<std::string> - { - public: - void parse(const std::string& opt_name, const OptionList& opt) - { - const auto* push = opt.get_index_ptr(opt_name); - if (push) - { - reserve(size() + push->size()); - for (auto &i : *push) - { - const Option& o = opt[i]; - o.touch(); - push_back(o.get(1, 512)); - } - } - } - -#ifdef HAVE_JSON - // Parse JSON representation of a push list. - // Each push list array element can be one of: - // 1. simple JSON string, - // 2. dictionary containing an "item" string, or - // 3. dictionary containing an "item" array of strings. - void parse(const std::string& title, const Json::Value& push_list) // push_list is JSON array - { - reserve(16); // arbitrary, just a guess - const auto& ja = json::cast_array(push_list, false, title).array(); - for (size_t i = 0; i < ja.size(); ++i) - { - const Json::Value& jv = ja[i]; - if (jv.isString()) - push_back(jv.asStringRef()); - else if (jv.isObject()) - { - const Json::Value& ji = jv["item"]; - if (ji.isString()) - push_back(ji.asStringRef()); - else if (ji.isArray()) - { - const auto& ia = ji.array(); - for (size_t j = 0; j < ia.size(); ++j) - { - const Json::Value& iv = ia[j]; - if (iv.isString()) - push_back(iv.asStringRef()); - else - throw json::json_parse(json::fmt_name(i, title) + " object contains 'item' array that includes non-string element at index=" + std::to_string(j)); - } - } - else - throw json::json_parse(json::fmt_name(i, title) + " object must contain 'item' string or array"); - } - else - throw json::json_parse(json::fmt_name(i, title) + " must be of type string or object"); - } - } -#endif - - void extend(const std::vector<std::string>& other) - { - reserve(size() + other.size()); - for (auto &e : other) - push_back(e); - } - - // do a roundtrip to csv and back to OptionList - OptionList to_option_list() const - { - std::ostringstream os; - output_csv(os); - return OptionList::parse_from_csv_static(os.str(), nullptr); - } - - void output_csv(std::ostream& os) const - { - for (auto &e : *this) - { - os << ','; - output_arg(e, os); - } - } - - static void output_arg(const std::string& e, std::ostream& os) - { - const bool must_quote = (e.find_first_of(',') != std::string::npos); - Option::escape_string(os, e, must_quote); - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ovpnagent/win/CMakeLists.txt b/Sources/OpenVPN3/openvpn/ovpnagent/win/CMakeLists.txt deleted file mode 100644 index 0c3f357..0000000 --- a/Sources/OpenVPN3/openvpn/ovpnagent/win/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include(findcoredeps) - -add_executable(ovpnagent ovpnagent.cpp) -add_core_dependencies(ovpnagent) -add_json_library(ovpnagent) -target_compile_definitions(ovpnagent PRIVATE -DOVPNAGENT_DISABLE_PATH_CHECK -DOPENVPN_AGENT_START_PROCESS) diff --git a/Sources/OpenVPN3/openvpn/ovpnagent/win/ovpnagent.cpp b/Sources/OpenVPN3/openvpn/ovpnagent/win/ovpnagent.cpp deleted file mode 100644 index 871c1f9..0000000 --- a/Sources/OpenVPN3/openvpn/ovpnagent/win/ovpnagent.cpp +++ /dev/null @@ -1,945 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN agent for Windows - -#include <iostream> -#include <string> -#include <vector> -#include <memory> -#include <utility> - -#include <openvpn/io/io.hpp> - -// debug settings (production setting in parentheses) -#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x) - -#include <openvpn/common/stringize.hpp> -// VERSION version can be passed on build command line -#ifdef VERSION -#define HTTP_SERVER_VERSION OPENVPN_STRINGIZE(VERSION) -#else -#define HTTP_SERVER_VERSION "0.1.0" -#endif -// OVPNAGENT_NAME can be passed on build command line. -// Customized agent name is needed with purpose to install -// few app with agents on one OS (e.g OC 3.0 and PT) -#ifdef OVPNAGENT_NAME -#define OVPNAGENT_NAME_STRING OPENVPN_STRINGIZE(OVPNAGENT_NAME) -#else -#define OVPNAGENT_NAME_STRING "ovpnagent" -#endif - -#include <openvpn/log/logbase.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/path.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/log/logbasesimple.hpp> -#include <openvpn/buffer/buflist.hpp> -#include <openvpn/buffer/bufhex.hpp> -#include <openvpn/init/initprocess.hpp> -#include <openvpn/ssl/sslchoose.hpp> -#include <openvpn/ws/httpserv.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/client/win/agentconfig.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/winsvc.hpp> -#include <openvpn/win/logfile.hpp> -#include <openvpn/tun/win/client/tunsetup.hpp> -#include <openvpn/win/npinfo.hpp> -#include <openvpn/win/handlecomm.hpp> - -void log_version() -{ - OPENVPN_LOG("OpenVPN Agent " HTTP_SERVER_VERSION " [" SSL_LIB_NAME "] built on " __DATE__ " " __TIME__); -} - -using namespace openvpn; - -struct MyConfig -{ - MyConfig() - { - pipe_name = Agent::named_pipe_path(); - server_exe = Win::module_name_utf8(); -#ifdef OPENVPN_AGENT_START_PROCESS - omiclient_exe = Win::omiclient_path(); -#endif - n_pipe_instances = 4; - } - - std::string pipe_name; - std::string server_exe; - std::string omiclient_exe; - unsigned int n_pipe_instances; -}; - -class MySessionStats : public SessionStats -{ -public: - typedef RCPtr<MySessionStats> Ptr; - - virtual void error(const size_t err_type, const std::string* text=nullptr) override - { - OPENVPN_LOG(openvpn::Error::name(err_type)); - } - - std::string dump() const - { - std::ostringstream os; - os << "OpenVPN Agent Stats" << std::endl; - return os.str(); - } -}; - -class MyListener : public WS::Server::Listener -{ -public: - typedef RCPtr<MyListener> Ptr; - - MyListener(const MyConfig& config_arg, - openvpn_io::io_context& io_context, - const WS::Server::Config::Ptr& hconf, - const Listen::List& listen_list, - const WS::Server::Listener::Client::Factory::Ptr& client_factory) - : WS::Server::Listener(io_context, hconf, listen_list, client_factory), - config(config_arg), - client_process(io_context), - client_confirm_event(io_context), - client_destroy_event(io_context), - io_context_(io_context) - { - } - - Win::ScopedHANDLE establish_tun(const TunBuilderCapture& tbc, - const std::wstring& openvpn_app_path, - Stop* stop, - std::ostream& os, - bool wintun) - { - if (!tun) - tun.reset(new TunWin::Setup(io_context_, wintun)); - auto th = tun->establish(tbc, openvpn_app_path, stop, os, ring_buffer); - // store VPN interface index to be able to exclude it - // when next time adding bypass route - vpn_interface_index = tun->vpn_interface_index(); - return Win::ScopedHANDLE(th); - } - - // return true if we did any work - bool destroy_tun(std::ostream& os) - { - bool ret = false; - try { - // close the remote tap handle in the client process - if (client_process.is_open() && !remote_tap_handle_hex.empty()) - { - ret = true; - const HANDLE remote_tap_handle = BufHex::parse<HANDLE>(remote_tap_handle_hex, "remote TAP handle"); - Win::ScopedHANDLE local_tap_handle; // dummy handle, immediately closed after duplication - if (::DuplicateHandle(client_process.native_handle(), - remote_tap_handle, - GetCurrentProcess(), - local_tap_handle.ref(), - 0, - FALSE, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) - { - os << "destroy_tun: no client confirm, DuplicateHandle (close) succeeded" << std::endl; - } - else - { - const Win::LastError err; - os << "destroy_tun: no client confirm, DuplicateHandle (close) failed: " << err.message() << std::endl; - } - } - } - catch (const std::exception& e) - { - os << "destroy_tun: exception in remote tap handle close: " << e.what() << std::endl; - } - - try { - ring_buffer.reset(); - - // undo the effects of establish_tun - if (tun) - { - ret = true; - tun->destroy(os); - } - } - catch (const std::exception& e) - { - os << "destroy_tun: exception in tun teardown: " << e.what() << std::endl; - } - - try { - tun.reset(); - remote_tap_handle_hex.clear(); - client_process.close(); - client_confirm_event.close(); - client_destroy_event.close(); - } - catch (const std::exception& e) - { - os << "destroy_tun: exception in cleanup: " << e.what() << std::endl; - } - vpn_interface_index = DWORD(-1); - return ret; - } - - void destroy_tun_exit() - { - std::ostringstream os; - destroy_tun(os); - OPENVPN_LOG_NTNL("TUN CLOSE (exit)\n" << os.str()); - } - - void set_client_process(Win::ScopedHANDLE&& proc) - { - client_process.close(); - client_process.assign(proc.release()); - - // special failsafe to destroy tun in case client crashes without closing it - client_process.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { - if (!error) - { - { - std::ostringstream os; - self->remove_cmds_bypass_hosts.execute(os); - self->remove_cmds_bypass_hosts.clear(); - OPENVPN_LOG_NTNL("remove bypass route (failsafe)\n" << os.str()); - } - - if (self->tun) - { - std::ostringstream os; - self->destroy_tun(os); - OPENVPN_LOG_NTNL("TUN CLOSE (failsafe)\n" << os.str()); - } - } - }); - } - - void set_client_confirm_event(const std::string& confirm_handle_hex) - { - client_confirm_event.close(); - - const HANDLE remote_event = BufHex::parse<HANDLE>(confirm_handle_hex, "confirm event handle"); - HANDLE event_handle; - if (!::DuplicateHandle(get_client_process(), - remote_event, - GetCurrentProcess(), - &event_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("set_client_confirm_event: DuplicateHandle failed: " << err.message()); - } - client_confirm_event.assign(event_handle); - - // Check if the event is okay - { - const DWORD status = ::WaitForSingleObject(client_confirm_event.native_handle(), 0); - const Win::LastError err; - switch (status) - { - case WAIT_OBJECT_0: // acceptable status - case WAIT_TIMEOUT: // acceptable status - break; - case WAIT_ABANDONED: - throw Exception("set_client_confirm_event: confirm event is abandoned"); - default: - OPENVPN_THROW_EXCEPTION("set_client_confirm_event: WaitForSingleObject failed: " << err.message()); - } - } - - // When the client signals the client_confirm event, it means - // that the client has taken ownership of the TAP device HANDLE, - // so we locally release ownership by clearing remote_tap_handle_hex, - // effectively preventing the cross-process release of TAP device - // HANDLE in destroy_tun() above. - client_confirm_event.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { - if (!error) - { - self->remote_tap_handle_hex.clear(); - OPENVPN_LOG_STRING("TUN CONFIRM\n"); - } - }); - } - - void set_client_destroy_event(const std::string& event_handle_hex) - { - client_destroy_event.close(); - - // Move the remote event HANDLE (already duplicated in remote process) - // to local process. - const HANDLE remote_event = BufHex::parse<HANDLE>(event_handle_hex, "destroy event handle"); - HANDLE event_handle; - if (!::DuplicateHandle(get_client_process(), - remote_event, - GetCurrentProcess(), - &event_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("set_client_destroy_event: DuplicateHandle failed: " << err.message()); - } - client_destroy_event.assign(event_handle); - - // Check if the event is already signaled, or has some other error - { - const DWORD status = ::WaitForSingleObject(client_destroy_event.native_handle(), 0); - const Win::LastError err; - switch (status) - { - case WAIT_TIMEOUT: // expected status - break; - case WAIT_OBJECT_0: - throw Exception("set_client_destroy_event: destroy event is already signaled"); - case WAIT_ABANDONED: - throw Exception("set_client_destroy_event: destroy event is abandoned"); - default: - OPENVPN_THROW_EXCEPTION("set_client_destroy_event: WaitForSingleObject failed: " << err.message()); - } - } - - // normal event-based tun close processing - client_destroy_event.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) { - if (!error) - { - { - std::ostringstream os; - self->remove_cmds_bypass_hosts.execute(os); - self->remove_cmds_bypass_hosts.clear(); - OPENVPN_LOG_NTNL("remove bypass route (event)\n" << os.str()); - } - - if (self->tun) - { - std::ostringstream os; - self->destroy_tun(os); - OPENVPN_LOG_NTNL("TUN CLOSE (event)\n" << os.str()); - } - } - }); - } - - HANDLE get_client_process() - { - if (!client_process.is_open()) - throw Exception("no client process"); - return client_process.native_handle(); - } - - void set_remote_tap_handle_hex(const HANDLE tap_handle) - { - remote_tap_handle_hex = Win::HandleComm::send_handle(tap_handle, get_client_process()); - } - - const std::string& get_remote_tap_handle_hex() - { - return remote_tap_handle_hex; - } - - void assign_ring_buffer(TunWin::RingBuffer* ring_buffer_arg) - { - ring_buffer.reset(ring_buffer_arg); - } - - void add_bypass_route(const std::string& host, bool ipv6) - { - std::ostringstream os; - remove_cmds_bypass_hosts.execute(os); - remove_cmds_bypass_hosts.clear(); - - ActionList add_cmds; - // we might have broken VPN connection up, so we must - // exclude VPN interface whe searching for the best gateway - const TunWin::Util::BestGateway gw { host, vpn_interface_index }; - TunWin::Setup::add_bypass_route(gw, host, ipv6, add_cmds, remove_cmds_bypass_hosts); - add_cmds.execute(os); - - OPENVPN_LOG(os.str()); - } - -#ifdef OPENVPN_AGENT_START_PROCESS - void start_openvpn_process(HANDLE client_pipe, - const std::string& config_file, - const std::string& config_dir, - const std::string& exit_event_name, - const std::string& management_host, - const std::string& management_password, - const int management_port, - const std::string& log, - const bool log_append) - { - // impersonate pipe client - Win::NamedPipeImpersonate impersonate{ client_pipe }; - - { - // create primary token from impersonation token - HANDLE imp_token = NULL, pri_token = NULL; - BOOL res = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, FALSE, &imp_token); - if (res == 0) - { - const openvpn_io::error_code err(::GetLastError(), openvpn_io::error::get_system_category()); - OPENVPN_THROW_EXCEPTION("failed to open thread token: " << err.message()); - } - res = DuplicateTokenEx(imp_token, 0, NULL, SECURITY_IMPERSONATION_LEVEL::SecurityAnonymous, TokenPrimary, &pri_token); - if (res == 0) - { - const openvpn_io::error_code err(::GetLastError(), openvpn_io::error::get_system_category()); - OPENVPN_THROW_EXCEPTION("failed to duplicate token: " << err.message()); - } - - // create pipe which is used to write password to openvpn process's stdin - HANDLE stdin_read = NULL, stdin_write = NULL; - SECURITY_ATTRIBUTES inheritable = { sizeof(inheritable), NULL, TRUE }; - if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0) - || !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0)) - { - const openvpn_io::error_code err(::GetLastError(), openvpn_io::error::get_system_category()); - OPENVPN_THROW_EXCEPTION("failed to set up pipe: " << err.message()); - } - - // create command line for openvpn process - std::ostringstream ss; - ss << "client --config " << config_dir << "\\" << config_file << " --exit-event-name " - << exit_event_name << " --auth-retry interact --management " << management_host << " " - << management_port << " stdin --management-query-passwords --management-hold " << "--log" - << (log_append ? "-append " : " ") << log; - std::string cmd = ss.str(); - std::unique_ptr<char[]> buf(new char[cmd.length() + 1]); - strcpy(buf.get(), cmd.c_str()); - - STARTUPINFO startup_info = { 0 }; - startup_info.cb = sizeof(startup_info); - startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = stdin_read; - - // create openvpn process - PROCESS_INFORMATION proc_info; - ZeroMemory(&proc_info, sizeof(proc_info)); - res = CreateProcessAsUser(pri_token, - config.omiclient_exe.c_str(), - buf.get(), - NULL, - NULL, - TRUE, - CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, - 0, - 0, - &startup_info, - &proc_info); - if (res == 0) - { - const openvpn_io::error_code err(::GetLastError(), openvpn_io::error::get_system_category()); - OPENVPN_THROW_EXCEPTION("failed to create openvpn process: " << err.message()); - } - CloseHandle(proc_info.hProcess); - CloseHandle(proc_info.hThread); - - // write management password to process's stdin - DWORD written; - WriteFile(stdin_write, management_password.c_str(), management_password.length(), &written, NULL); - } - } -#endif - - const MyConfig& config; - ActionList remove_cmds_bypass_hosts; - - TunWin::RingBuffer::Ptr ring_buffer; - -private: - virtual bool allow_client(AsioPolySock::Base& sock) override - { - AsioPolySock::NamedPipe* np = dynamic_cast<AsioPolySock::NamedPipe*>(&sock); - if (np) - { -#if _WIN32_WINNT >= 0x0600 // Vista and higher - Win::NamedPipePeerInfoClient npinfo(np->handle.native_handle()); - const std::string client_exe = wstring::to_utf8(npinfo.exe_path); - OPENVPN_LOG("connection from " << client_exe); - if (Agent::valid_pipe(client_exe, config.server_exe)) - return true; - OPENVPN_LOG(client_exe << " not recognized as a valid client"); -#else - return true; -#endif - } - else - OPENVPN_LOG("only named pipe clients are allowed"); - return false; - } - - TunWin::Setup::Ptr tun; - openvpn_io::windows::object_handle client_process; - openvpn_io::windows::object_handle client_confirm_event; - openvpn_io::windows::object_handle client_destroy_event; - std::string remote_tap_handle_hex; - openvpn_io::io_context& io_context_; - - // with persist tunnel and redirect-gw we must exclude - // VPN interface when searching for best gateway when - // adding bypass route for the next remote - DWORD vpn_interface_index = DWORD(-1); -}; - -class MyClientInstance : public WS::Server::Listener::Client -{ -public: - typedef RCPtr<MyClientInstance> Ptr; - - MyClientInstance(WS::Server::Listener::Client::Initializer& ci) - : WS::Server::Listener::Client(ci) - { - //OPENVPN_LOG("INSTANCE START"); - } - - virtual ~MyClientInstance() - { - //OPENVPN_LOG("INSTANCE DESTRUCT"); - } - -private: - void generate_reply(const Json::Value& jout) - { - out = buf_from_string(jout.toStyledString()); - - WS::Server::ContentInfo ci; - ci.http_status = HTTP::Status::OK; - ci.type = "application/json"; - ci.length = out->size(); - ci.keepalive = keepalive_request(); - generate_reply_headers(ci); - } - - virtual void http_request_received() override - { - // alloc output buffer - std::ostringstream os; - - try { - const HANDLE client_pipe = get_client_pipe(); - const std::wstring client_exe = get_client_exe(client_pipe); - - const HTTP::Request& req = request(); - OPENVPN_LOG("HTTP request received from " << sock->remote_endpoint_str() << '\n' << req.to_string()); - - // get content-type - const std::string content_type = req.headers.get_value_trim("content-type"); - - if (req.method == "POST") - { - // verify correct content-type - if (string::strcasecmp(content_type, "application/json")) - throw Exception("bad content-type"); - - // parse the json dict - const Json::Value root = json::parse(in.to_string(), "JSON request"); - if (!root.isObject()) - throw Exception("json parse error: top level json object is not a dictionary"); - - if (req.uri == "/tun-setup") - { - // get PID - ULONG pid = json::get_uint_optional(root, "pid", 0); - - bool wintun = json::get_bool_optional(root, "wintun"); - - // get remote event handles for tun object confirmation/destruction - const std::string confirm_event_hex = json::get_string(root, "confirm_event"); - const std::string destroy_event_hex = json::get_string(root, "destroy_event"); - - // parse JSON data into a TunBuilderCapture object - TunBuilderCapture::Ptr tbc = TunBuilderCapture::from_json(json::get_dict(root, "tun", false)); - tbc->validate(); - - // destroy previous instance - if (parent()->destroy_tun(os)) - { - os << "Destroyed previous TAP instance" << std::endl; - ::Sleep(1000); - } - - // pre-establish impersonation - { - Win::NamedPipeImpersonate impersonate(client_pipe); - - // remember the client process that sent the request - parent()->set_client_process(get_client_process(client_pipe, pid)); - - // save the confirm/destroy events - parent()->set_client_destroy_event(destroy_event_hex); - parent()->set_client_confirm_event(confirm_event_hex); - } - - if (wintun) - { - parent()->assign_ring_buffer(new TunWin::RingBuffer(io_context, - parent()->get_client_process(), - json::get_string(root, "send_ring_hmem"), - json::get_string(root, "receive_ring_hmem"), - json::get_string(root, "send_ring_tail_moved"), - json::get_string(root, "receive_ring_tail_moved"))); - } - - // establish the tun setup object - Win::ScopedHANDLE tap_handle(parent()->establish_tun(*tbc, client_exe, nullptr, os, wintun)); - - // post-establish impersonation - { - Win::NamedPipeImpersonate impersonate(client_pipe); - - // duplicate the TAP handle into the client process - parent()->set_remote_tap_handle_hex(tap_handle()); - } - - // build JSON return dictionary - const std::string log_txt = string::remove_blanks(os.str()); - Json::Value jout(Json::objectValue); - jout["log_txt"] = log_txt; - jout["tap_handle_hex"] = parent()->get_remote_tap_handle_hex(); - OPENVPN_LOG_NTNL("TUN SETUP\n" << log_txt); - - generate_reply(jout); - } - else if (req.uri == "/add-bypass-route") - { - ULONG pid = json::get_uint_optional(root, "pid", 0); - bool ipv6 = json::get_bool(root, "ipv6"); - const std::string host = json::get_string(root, "host"); - - // pre-establish impersonation - { - Win::NamedPipeImpersonate impersonate(client_pipe); - - // remember the client process that sent the request - parent()->set_client_process(get_client_process(client_pipe, pid)); - } - - parent()->add_bypass_route(host, ipv6); - - Json::Value jout(Json::objectValue); - - generate_reply(jout); - } -#ifdef OPENVPN_AGENT_START_PROCESS - else if (req.uri == "/start") - { - const std::string config_file = json::get_string(root, "config_file"); - const std::string config_dir = json::get_string(root, "config_dir"); - const std::string exit_event_name = json::get_string(root, "exit_event_name"); - const std::string management_host = json::get_string(root, "management_host"); - const std::string management_password = json::get_string(root, "management_password") + "\n"; - const int management_port = json::get_int(root, "management_port"); - const std::string log = json::get_string(root, "log"); - const bool log_append = json::get_int(root, "log-append") == 1; - - parent()->start_openvpn_process(client_pipe, config_file, config_dir, exit_event_name, - management_host, management_password, management_port, - log, log_append); - - Json::Value jout(Json::objectValue); - generate_reply(jout); - } -#endif - else - { - OPENVPN_LOG("PAGE NOT FOUND"); - out = buf_from_string("page not found\n"); - WS::Server::ContentInfo ci; - ci.http_status = HTTP::Status::NotFound; - ci.type = "text/plain"; - ci.length = out->size(); - generate_reply_headers(ci); - } - } - } - catch (const std::exception& e) - { - if (parent()->destroy_tun(os)) - os << "Destroyed previous TAP instance due to exception" << std::endl; - - const std::string error_msg = string::remove_blanks(os.str() + e.what() + '\n'); - OPENVPN_LOG_NTNL("EXCEPTION\n" << error_msg); - - out = buf_from_string(error_msg); - WS::Server::ContentInfo ci; - ci.http_status = HTTP::Status::BadRequest; - ci.type = "text/plain"; - ci.length = out->size(); - generate_reply_headers(ci); - } - } - - virtual void http_content_in(BufferAllocated& buf) override - { - if (buf.defined()) - in.emplace_back(new BufferAllocated(std::move(buf))); - } - - virtual BufferPtr http_content_out() override - { - BufferPtr ret; - ret.swap(out); - return ret; - } - - virtual bool http_out_eof() override - { - //OPENVPN_LOG("HTTP output EOF"); - return true; - } - - virtual bool http_stop(const int status, const std::string& description) override - { - if (status != WS::Server::Status::E_SUCCESS) - { - OPENVPN_LOG("INSTANCE STOP : " << WS::Server::Status::error_str(status) << " : " << description); - return false; - } - else - return true; - } - - HANDLE get_client_pipe() const - { - AsioPolySock::NamedPipe* np = dynamic_cast<AsioPolySock::NamedPipe*>(sock.get()); - if (!np) - throw Exception("only named pipe clients are allowed"); - return np->handle.native_handle(); - } - - std::wstring get_client_exe(const HANDLE client_pipe) - { -#if _WIN32_WINNT >= 0x0600 // Vista and higher - Win::NamedPipePeerInfoClient npinfo(client_pipe); - return npinfo.exe_path; -#else - return std::wstring(); -#endif - } - - Win::ScopedHANDLE get_client_process(const HANDLE pipe, ULONG pid_hint) const - { -#if _WIN32_WINNT >= 0x0600 // Vista and higher - pid_hint = Win::NamedPipePeerInfo::get_pid(pipe, true); -#endif - if (!pid_hint) - throw Exception("cannot determine client PID"); - return Win::NamedPipePeerInfo::get_process(pid_hint, false); - } - - MyListener* parent() - { - return static_cast<MyListener*>(get_parent()); - } - - BufferList in; - BufferPtr out; -}; - -class MyClientFactory : public WS::Server::Listener::Client::Factory -{ -public: - typedef RCPtr<MyClientFactory> Ptr; - - virtual WS::Server::Listener::Client::Ptr new_client(WS::Server::Listener::Client::Initializer& ci) override - { - return new MyClientInstance(ci); - } -}; - -class MyService : public Win::Service -{ -public: - MyService() - : Win::Service(config()) - { - } - - virtual void service_work(DWORD argc, LPWSTR *argv) override - { - if (is_service()) - { - try { - log.reset(new Win::LogFile(log_fn(), "", false)); - } - catch (const std::exception& e) - { - std::cerr << e.what() << std::endl; - } - } - if (!log) - log.reset(new LogBaseSimple()); - - io_context.reset(new openvpn_io::io_context(1)); // concurrency hint=1 - - log_version(); - - MyConfig conf; - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - Win::NamedPipePeerInfo::allow_client_query(); - TunWin::NRPT::delete_rule(); // remove stale NRPT rules -#endif - - WS::Server::Config::Ptr hconf = new WS::Server::Config(); - hconf->http_server_id = OVPNAGENT_NAME_STRING "/" HTTP_SERVER_VERSION; - hconf->frame = frame_init_simple(2048); - hconf->stats.reset(new MySessionStats); - - // DACL string for creating named pipe - hconf->sddl_string = - "D:" // discretionary ACL - "(D;OICI;GA;;;S-1-5-2)" // deny all access for network users - "(A;OICI;GA;;;S-1-5-32-544)" // allow full access to Admin group - "(A;OICI;GA;;;S-1-5-18)" // allow full access to Local System account - "(D;OICI;0x4;;;S-1-1-0)" // deny FILE_CREATE_PIPE_INSTANCE for Everyone - "(A;OICI;GRGW;;;S-1-5-11)" // allow read/write access for authenticated users - "(A;OICI;GRGW;;;S-1-5-32-546)" // allow read/write access for built-in guest account - ; - - Listen::List ll; - const unsigned int n_pipe_instances = 4; - for (unsigned int i = 0; i < n_pipe_instances; ++i) - { - Listen::Item li; - li.directive = "http-listen"; - li.addr = conf.pipe_name; - li.proto = Protocol(Protocol::NamedPipe); - li.ssl = Listen::Item::SSLOff; - li.n_threads = n_pipe_instances; - ll.push_back(std::move(li)); - } - - MyClientFactory::Ptr factory = new MyClientFactory(); - listener.reset(new MyListener(conf, *io_context, hconf, ll, factory)); - listener->start(); - - report_service_running(); - - io_context->run(); - } - - // Called by service control manager in another thread - // to signal the service_work() method to exit. - virtual void service_stop() override - { - openvpn_io::post(*io_context, [this]() { - if (listener) - { - listener->destroy_tun_exit(); - listener->stop(); - } - }); - } - -private: - static Config config() - { - Config c; - c.name = OVPNAGENT_NAME_STRING; - c.display_name = "OpenVPN Agent " OVPNAGENT_NAME_STRING; -#if _WIN32_WINNT < 0x0600 // pre-Vista - c.dependencies.push_back("Dhcp"); // DHCP client -#endif - c.autostart = true; - c.restart_on_fail = true; - return c; - } - - static std::string log_fn() - { - const std::string modname = Win::module_name_utf8(); - const std::string moddir = path::dirname(modname); - const std::string fn = path::join(moddir, "agent.log"); - return fn; - } - - std::unique_ptr<openvpn_io::io_context> io_context; - MyListener::Ptr listener; - LogBase::Ptr log; -}; - -OPENVPN_SIMPLE_EXCEPTION(usage); - -int main(int argc, char* argv[]) -{ - int ret = 0; - - // process-wide initialization - InitProcess::Init init; - - try { - MyService serv; - if (argc >= 2) - { - const std::string arg = argv[1]; - if (arg == "run") - serv.service_work(0, nullptr); - else if (arg == "install") - serv.install(); - else if (arg == "remove") - serv.remove(); - else if (arg == "modname") - std::wcout << Win::module_name() << std::endl; - else if (arg == "help") - { - std::cout << "usage: ovpnagent [options]" << std::endl; - std::cout << " run -- run in foreground (for debugging)" << std::endl; - std::cout << " install -- install as service" << std::endl; - std::cout << " remove -- uninstall" << std::endl; - std::cout << " modname -- show module name" << std::endl; - std::cout << " help -- show help message" << std::endl; - std::cout << " [default] -- start as service" << std::endl; - } - else - { - std::cout << "unrecognized option, use 'help' for more info" << std::endl; - ret = 2; - } - } - else - serv.start(); - } - catch (const std::exception& e) - { - std::cout << "ovpnagent: " << e.what() << std::endl; - ret = 1; - } - - return ret; -} diff --git a/Sources/OpenVPN3/openvpn/pki/cclist.hpp b/Sources/OpenVPN3/openvpn/pki/cclist.hpp deleted file mode 100644 index 3847345..0000000 --- a/Sources/OpenVPN3/openvpn/pki/cclist.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// 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-2020 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_PKI_CCLIST_H -#define OPENVPN_PKI_CCLIST_H - -#include <string> -#include <sstream> -#include <fstream> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/string.hpp> - -namespace openvpn { - - // Parse a concatenated list of certs and CRLs (PEM format). - // Abstracts CertList and CRLList, so can be used with any crypto lib. - // CertList and CRLList must define Item type. - template <typename CertList, typename CRLList> - class CertCRLListTemplate - { - public: - OPENVPN_EXCEPTION(parse_cert_crl_error); - - CertCRLListTemplate() {} - - explicit CertCRLListTemplate(const std::string& content, const std::string& title) - { - from_string(content, title, &certs, &crls); - } - - void parse_pem(const std::string& content, const std::string& title) - { - from_string(content, title, &certs, &crls); - } - - void parse_pem_file(const std::string& filename) - { - from_file(filename, &certs, &crls); - } - - std::string render_pem() const - { - return certs.render_pem() + crls.render_pem(); - } - - static void from_istream(std::istream& in, const std::string& title, CertList* cert_list, CRLList* crl_list) - { - static const char cert_start[] = "-----BEGIN CERTIFICATE-----"; - static const char cert_end[] = "-----END CERTIFICATE-----"; - static const char crl_start[] = "-----BEGIN X509 CRL-----"; - static const char crl_end[] = "-----END X509 CRL-----"; - - enum { - S_OUTSIDE, // outside of CERT or CRL block - S_IN_CERT, // in CERT block - S_IN_CRL, // in CRL block - }; - - std::string line; - int state = S_OUTSIDE; - std::string item = ""; - int line_num = 0; - - while (std::getline(in, line)) - { - line_num++; - string::trim(line); - if (state == S_OUTSIDE) - { - if (line == cert_start) - { - if (!cert_list) - OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : not expecting a CERT"); - state = S_IN_CERT; - } - else if (line == crl_start) - { - if (!crl_list) - OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : not expecting a CRL"); - state = S_IN_CRL; - } - } - if (state != S_OUTSIDE) - { - item += line; - item += "\n"; - } - if (state == S_IN_CERT && line == cert_end) - { - try { - cert_list->emplace_back(item, title); - } - catch (const std::exception& e) - { - OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : error parsing CERT: " << e.what()); - } - state = S_OUTSIDE; - item = ""; - } - if (state == S_IN_CRL && line == crl_end) - { - try { - crl_list->emplace_back(item); - } - catch (const std::exception& e) - { - OPENVPN_THROW(parse_cert_crl_error, title << ":" << line_num << " : error parsing CRL: " << e.what()); - } - state = S_OUTSIDE; - item = ""; - } - } - if (state != S_OUTSIDE) - OPENVPN_THROW(parse_cert_crl_error, title << " : CERT/CRL content ended unexpectedly without END marker"); - } - - static void from_string(const std::string& content, const std::string& title, CertList* cert_list, CRLList* crl_list = nullptr) - { - std::stringstream in(content); - from_istream(in, title, cert_list, crl_list); - } - - static void from_file(const std::string& filename, CertList* cert_list, CRLList* crl_list = nullptr) - { - std::ifstream ifs(filename.c_str()); - if (!ifs) - OPENVPN_THROW(open_file_error, "cannot open CERT/CRL file " << filename); - from_istream(ifs, filename, cert_list, crl_list); - if (ifs.bad()) - OPENVPN_THROW(open_file_error, "cannot read CERT/CRL file " << filename); - } - - CertList certs; - CRLList crls; - }; - -} // namespace openvpn - -#endif // OPENVPN_PKI_CCLIST_H diff --git a/Sources/OpenVPN3/openvpn/pki/epkibase.hpp b/Sources/OpenVPN3/openvpn/pki/epkibase.hpp deleted file mode 100644 index 9af118a..0000000 --- a/Sources/OpenVPN3/openvpn/pki/epkibase.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// 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-2020 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_PKI_EPKIBASE_H -#define OPENVPN_PKI_EPKIBASE_H - -#include <string> - -namespace openvpn { - - // Abstract base class used to provide an interface where core SSL implementation - // can use an external private key. - class ExternalPKIBase - { - public: - // Sign data (base64) and return signature as sig (base64). - // Return true on success or false on error. - virtual bool sign(const std::string& data, std::string& sig, const std::string& algorithm) = 0; - - virtual ~ExternalPKIBase() {} - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/pki/pkcs1.hpp b/Sources/OpenVPN3/openvpn/pki/pkcs1.hpp deleted file mode 100644 index b393fd7..0000000 --- a/Sources/OpenVPN3/openvpn/pki/pkcs1.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// 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-2020 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_PKI_PKCS1_H -#define OPENVPN_PKI_PKCS1_H - -#include <cstring> - -#include <openvpn/common/size.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - namespace PKCS1 { - // from http://www.ietf.org/rfc/rfc3447.txt - namespace DigestPrefix { // CONST GLOBAL - namespace { - const unsigned char MD2[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 }; - const unsigned char MD5[] = { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; - const unsigned char SHA1[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, - 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x04, 0x14 }; - const unsigned char SHA256[] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, - 0x20 }; - const unsigned char SHA384[] = { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, - 0x30 }; - const unsigned char SHA512[] = { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, - 0x40 }; - } - - template <typename T> - class Parse - { - public: - Parse(const T none, - const T md2, - const T md5, - const T sha1, - const T sha256, - const T sha384, - const T sha512) - : none_(none), - md2_(md2), - md5_(md5), - sha1_(sha1), - sha256_(sha256), - sha384_(sha384), - sha512_(sha512) - { - } - - T alg_from_prefix(Buffer& buf) const - { - if (match(buf, MD2, sizeof(MD2))) - return md2_; - else if (match(buf, MD5, sizeof(MD5))) - return md5_; - else if (match(buf, SHA1, sizeof(SHA1))) - return sha1_; - else if (match(buf, SHA256, sizeof(SHA256))) - return sha256_; - else if (match(buf, SHA384, sizeof(SHA384))) - return sha384_; - else if (match(buf, SHA512, sizeof(SHA512))) - return sha512_; - else - return none_; - } - - private: - bool match(Buffer& buf, const unsigned char *data, const size_t size) const - { - if (buf.size() < size) - return false; - else if (std::memcmp(buf.c_data(), data, size) == 0) - { - buf.advance(size); - return true; - } - else - return false; - } - - const T none_, md2_, md5_, sha1_, sha256_, sha384_, sha512_; - }; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/pki/pktype.hpp b/Sources/OpenVPN3/openvpn/pki/pktype.hpp deleted file mode 100644 index f25fb03..0000000 --- a/Sources/OpenVPN3/openvpn/pki/pktype.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// 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-2020 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 - -// private key types - -namespace openvpn { - namespace PKType { - - enum Type { - PK_UNKNOWN = 0, - PK_NONE, - PK_DSA, - PK_RSA, - PK_EC, - PK_ECDSA, - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/pki/x509track.hpp b/Sources/OpenVPN3/openvpn/pki/x509track.hpp deleted file mode 100644 index 013bd2e..0000000 --- a/Sources/OpenVPN3/openvpn/pki/x509track.hpp +++ /dev/null @@ -1,230 +0,0 @@ -// 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-2020 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_PKI_X509TRACK_H -#define OPENVPN_PKI_X509TRACK_H - -#include <string> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - namespace X509Track { - - enum Type { - UNDEF=-1, - SERIAL, - SERIAL_HEX, - SHA1, - CN, - C, - L, - ST, - O, - OU, - EMAIL, - N_TYPES, - }; - - static const char *const names[] = { // CONST GLOBAL - "SERIAL", - "SERIAL_HEX", - "SHA1", - "CN", - "C", - "L", - "ST", - "O", - "OU", - "emailAddress", - }; - - OPENVPN_EXCEPTION(x509_track_error); - - inline const char *name(const Type type) - { - static_assert(N_TYPES == array_size(names), "x509 names array inconsistency"); - if (type >= 0 && type < N_TYPES) - return names[type]; - else - return "UNDEF"; - } - - inline Type parse_type(const std::string& name) - { - for (size_t i = 0; i < N_TYPES; ++i) - if (name == names[i]) - return Type(i); - return UNDEF; - } - - struct Config - { - Config(const Type type_arg, const bool full_chain_arg) - : type(type_arg), - full_chain(full_chain_arg) - { - } - - Config(const std::string& spec) - { - full_chain = (spec.length() > 0 && spec[0] == '+'); - type = parse_type(spec.substr(full_chain ? 1 : 0)); - if (type == UNDEF) - throw Exception("cannot parse attribute '" + spec + "'"); - } - - std::string to_string() const - { - std::string ret; - if (full_chain) - ret += '+'; - ret += name(type); - return ret; - } - - bool depth_match(const int depth) const - { - return !depth || full_chain; - } - - Type type; - bool full_chain; - }; - - struct ConfigSet : public std::vector<Config> - { - ConfigSet() {} - - ConfigSet(const OptionList& opt, - const bool include_serial, - const bool include_serial_hex) - { - const auto* xt = opt.get_index_ptr("x509-track"); - if (xt) - { - for (const auto &i : *xt) - { - try { - const Option& o = opt[i]; - o.touch(); - emplace_back(o.get(1, 64)); - } - catch (const std::exception& e) - { - throw x509_track_error(e.what()); - } - } - } - - if (include_serial && !exists(SERIAL)) - emplace_back(SERIAL, true); - if (include_serial_hex && !exists(SERIAL_HEX)) - emplace_back(SERIAL_HEX, true); - } - - bool exists(const Type t) const - { - for (auto &c : *this) - if (c.type == t) - return true; - return false; - } - - std::string to_string() const - { - std::string ret; - for (auto &c : *this) - { - ret += c.to_string(); - ret += '\n'; - } - return ret; - } - }; - - struct KeyValue - { - KeyValue(const Type type_arg, - const int depth_arg, - std::string value_arg) - : type(type_arg), - depth(depth_arg), - value(std::move(value_arg)) - { - } - - std::string to_string(const bool omi_form) const - { - std::string ret; - ret.reserve(128); - if (omi_form) - ret += ">CLIENT:ENV,"; - ret += key_name(); - ret += '='; - ret += string::reduce_spaces(value, ' '); - return ret; - } - - std::string key_name() const - { - switch (type) - { - case SERIAL: - return "tls_serial_" + openvpn::to_string(depth); - case SERIAL_HEX: - return "tls_serial_hex_" + openvpn::to_string(depth); - default: - return "X509_" + openvpn::to_string(depth) + '_' + name(type); - } - } - - Type type = UNDEF; - int depth = 0; - std::string value; - }; - - struct Set : public std::vector<KeyValue> - { - std::string to_string(const bool omi_form) const - { - std::string ret; - ret.reserve(512); - for (auto &kv : *this) - { - ret += kv.to_string(omi_form); - if (omi_form) - ret += '\r'; - ret += '\n'; - } - return ret; - } - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/proxy/httpdigest.hpp b/Sources/OpenVPN3/openvpn/proxy/httpdigest.hpp deleted file mode 100644 index c005b25..0000000 --- a/Sources/OpenVPN3/openvpn/proxy/httpdigest.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// 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-2020 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/>. - -// Low-level methods used to implement HTTP Digest authentication - -#ifndef OPENVPN_PROXY_HTTPDIGEST_H -#define OPENVPN_PROXY_HTTPDIGEST_H - -#include <cstring> // for std::strlen and others -#include <string> - -#include <openvpn/crypto/hashstr.hpp> - -namespace openvpn { - namespace HTTPProxy { - - class Digest - { - public: - // calculate H(A1) as per spec - static std::string calcHA1(DigestFactory& digest_factory, - const std::string& alg, - const std::string& username, - const std::string& realm, - const std::string& password, - const std::string& nonce, - const std::string& cnonce) - { - HashString h1(digest_factory, CryptoAlgs::MD5); - h1.update(username); - h1.update(':'); - h1.update(realm); - h1.update(':'); - h1.update(password); - BufferPtr result = h1.final(); - - if (string::strcasecmp(alg, "md5-sess") == 0) - { - HashString h2(digest_factory, CryptoAlgs::MD5); - h2.update(*result); - h2.update(':'); - h2.update(nonce); - h2.update(':'); - h2.update(cnonce); - result = h2.final(); - } - return render_hex_generic(*result); - } - - // calculate request-digest/response-digest as per HTTP Digest spec - static std::string calcResponse(DigestFactory& digest_factory, - const std::string& hA1, // H(A1) - const std::string& nonce, // nonce from server - const std::string& nonce_count, // 8 hex digits - const std::string& cnonce, // client nonce - const std::string& qop, // qop-value: "", "auth", "auth-int" - const std::string& method, // method from the request - const std::string& digestUri, // requested URI - const std::string& hEntity) // H(entity body) if qop="auth-int" - { - // calculate H(A2) - HashString h1(digest_factory, CryptoAlgs::MD5); - h1.update(method); - h1.update(':'); - h1.update(digestUri); - if (string::strcasecmp(qop, "auth-int") == 0) - { - h1.update(':'); - h1.update(hEntity); - } - const std::string hA2 = h1.final_hex(); - - // calculate response - HashString h2(digest_factory, CryptoAlgs::MD5); - h2.update(hA1); - h2.update(':'); - h2.update(nonce); - h2.update(':'); - if (!qop.empty()) - { - h2.update(nonce_count); - h2.update(':'); - h2.update(cnonce); - h2.update(':'); - h2.update(qop); - h2.update(':'); - } - h2.update(hA2); - return h2.final_hex(); - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/proxy/listener.hpp b/Sources/OpenVPN3/openvpn/proxy/listener.hpp deleted file mode 100644 index efb68d9..0000000 --- a/Sources/OpenVPN3/openvpn/proxy/listener.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// 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-2020 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/rc.hpp> -#include <openvpn/acceptor/base.hpp> - -namespace openvpn -{ - // generic structure implemented by the various proxies used by PGProxy - struct ProxyListener : public Acceptor::ListenerBase - { - typedef RCPtr<ProxyListener> Ptr; - - virtual void start() = 0; - virtual void stop() = 0; - }; -} diff --git a/Sources/OpenVPN3/openvpn/proxy/ntlm.hpp b/Sources/OpenVPN3/openvpn/proxy/ntlm.hpp deleted file mode 100644 index 6979a68..0000000 --- a/Sources/OpenVPN3/openvpn/proxy/ntlm.hpp +++ /dev/null @@ -1,229 +0,0 @@ -// 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-2020 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/>. - -// Low-level methods used to implement NTLMv2 proxy authentication - -#ifndef OPENVPN_PROXY_NTLM_H -#define OPENVPN_PROXY_NTLM_H - -#include <cstring> -#include <string> -#include <vector> -#include <cstdint> // for std::uint32_t, uint64_t - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/crypto/digestapi.hpp> - -namespace openvpn { - namespace HTTPProxy { - - class NTLM - { - public: - /* - * NTLMv2 handshake - * http://davenport.sourceforge.net/ntlm.html - * - */ - - static std::string phase_1() - { - return "TlRMTVNTUAABAAAAAgIAAA=="; - } - - static std::string phase_3(DigestFactory& digest_factory, - const std::string& phase_2_response, - const std::string& dom_username, - const std::string& password, - RandomAPI& rng) - { - // sanity checks - if (dom_username.empty()) - throw Exception("username is blank"); - if (password.empty()) - throw Exception("password is blank"); - - // ensure that RNG is crypto-strength - rng.assert_crypto(); - - // split domain\username - std::string domain; - std::string username; - split_domain_username(dom_username, domain, username); - - // convert password from utf-8 to utf-16 and take an MD4 hash of it - BufferPtr password_u = Unicode::string_to_utf16(password); - DigestInstance::Ptr md4_ctx(digest_factory.new_digest(CryptoAlgs::MD4)); - md4_ctx->update(password_u->c_data(), password_u->size()); - unsigned char md4_hash[21]; - md4_ctx->final(md4_hash); - std::memset(md4_hash + 16, 0, 5); // pad to 21 bytes - - // decode phase_2_response from base64 to raw data - BufferAllocated response(phase_2_response.size(), 0); - base64->decode(response, phase_2_response); - - // extract the challenge from bytes 24-31 in the response - unsigned char challenge[8]; - for (size_t i = 0; i < 8; ++i) - challenge[i] = response[i+24]; - - // concatenate uppercase(username) + domain, - // convert to utf-16, and run it through HMAC-MD5 - // keyed to md4_hash - const std::string ud = string::to_upper_copy(username) + domain; - BufferPtr ud_u = Unicode::string_to_utf16(ud); - HMACInstance::Ptr hmac_ctx1(digest_factory.new_hmac(CryptoAlgs::MD5, md4_hash, 16)); - hmac_ctx1->update(ud_u->c_data(), ud_u->size()); - unsigned char ntlmv2_hash[16]; - hmac_ctx1->final(ntlmv2_hash); - - // NTLMv2 Blob - unsigned char ntlmv2_response[144]; - unsigned char *ntlmv2_blob = ntlmv2_response + 16; // inside ntlmv2_response, length: 128 - memset(ntlmv2_blob, 0, 128); // clear blob buffer - ntlmv2_blob[0x00]=1; // signature - ntlmv2_blob[0x01]=1; // signature - ntlmv2_blob[0x04]=0; // reserved - store_win_time(ntlmv2_blob + 0x08); // 64-bit Windows-style timestamp - rng.rand_bytes(ntlmv2_blob + 0x10, 8); // 64-bit client nonce - ntlmv2_blob[0x18]=0; // unknown, zero should work - - // add target information block to the blob - size_t tib_len = 0; - if (response[0x16] & 0x80) // check for Target Information block (TIB) - { - tib_len = response[0x28]; // get TIB size - if (tib_len > 96) - tib_len = 96; - const size_t tib_offset = response[0x2c]; - if (tib_offset + tib_len < response.size()) - { - const unsigned char *tib_ptr = response.c_data() + tib_offset; // get TIB pointer - std::memcpy(&ntlmv2_blob[0x1c], tib_ptr, tib_len); // copy TIB into the blob - } - else - tib_len = 0; - } - ntlmv2_blob[0x1c + tib_len] = 0; // unknown, zero works - - // Get blob length - const size_t ntlmv2_blob_size = 0x20 + tib_len; - - // Add challenge from message 2 - std::memcpy(&ntlmv2_response[8], challenge, 8); - - // hmac-md5 - HMACInstance::Ptr hmac_ctx2(digest_factory.new_hmac(CryptoAlgs::MD5, ntlmv2_hash, 16)); - hmac_ctx2->update(&ntlmv2_response[8], ntlmv2_blob_size + 8); - unsigned char ntlmv2_hmacmd5[16]; - hmac_ctx2->final(ntlmv2_hmacmd5); - - // add hmac-md5 result to the blob - // Note: This overwrites challenge previously written at ntlmv2_response[8..15] - std::memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16); - - // start building phase3 message (what we return to caller) - BufferAllocated phase3(0x40, BufferAllocated::ARRAY|BufferAllocated::CONSTRUCT_ZERO|BufferAllocated::GROW); - std::strcpy((char *)phase3.data(), "NTLMSSP"); // signature - phase3[8] = 3; // type 3 - - // NTLMv2 response - add_security_buffer(0x14, ntlmv2_response, ntlmv2_blob_size + 16, phase3); - - // username - add_security_buffer(0x24, username.c_str(), username.length(), phase3); - - // Set domain. If <domain> is empty, default domain will be used (i.e. proxy's domain). - add_security_buffer(0x1c, domain.c_str(), domain.size(), phase3); - - // other security buffers will be empty - phase3[0x10] = phase3.size(); // lm not used - phase3[0x30] = phase3.size(); // no workstation name supplied - phase3[0x38] = phase3.size(); // no session key - - // flags - phase3[0x3c] = 0x02; // negotiate oem - phase3[0x3d] = 0x02; // negotiate ntlm - - return base64->encode(phase3); - } - - private: - // adds security buffer data to a message and sets security buffer's offset and length - static void add_security_buffer(const size_t sb_offset, - const void *data, - const unsigned char length, - Buffer& msg_buf) - { - msg_buf[sb_offset] = length; - msg_buf[sb_offset + 2] = length; - msg_buf[sb_offset + 4] = msg_buf.size() & 0xff; - msg_buf[sb_offset + 5] = (msg_buf.size() >> 8) & 0xff; - msg_buf.write((unsigned char *)data, length); - } - - // store 64-bit windows time into a little-endian 8-byte buffer - static void store_win_time(unsigned char *dest) - { - const std::uint64_t wt = Time::win_time(); - dest[0]= (unsigned char)wt; - dest[1]= (unsigned char)(wt >> 8); - dest[2]= (unsigned char)(wt >> 16); - dest[3]= (unsigned char)(wt >> 24); - dest[4]= (unsigned char)(wt >> 32); - dest[5]= (unsigned char)(wt >> 40); - dest[6]= (unsigned char)(wt >> 48); - dest[7]= (unsigned char)(wt >> 56); - } - - static void split_domain_username(const std::string& combined, std::string& domain, std::string& username) - { - typedef std::vector<std::string> StringList; - StringList sl; - sl.reserve(2); - Split::by_char_void<StringList, NullLex, Split::NullLimit>(sl, combined, '\\', 1); - if (sl.size() == 1) - { - domain = ""; - username = sl[0]; - } - else if (sl.size() == 2) - { - domain = sl[0]; - username = sl[1]; - } - else - throw Exception("split_domain_username failed"); - } - - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/proxy/proxyauth.hpp b/Sources/OpenVPN3/openvpn/proxy/proxyauth.hpp deleted file mode 100644 index 59ed594..0000000 --- a/Sources/OpenVPN3/openvpn/proxy/proxyauth.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// 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-2020 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_PROXY_PROXYAUTH_H -#define OPENVPN_PROXY_PROXYAUTH_H - -#include <vector> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/http/header.hpp> - -namespace openvpn { - namespace HTTPProxy { - - // parse the Proxy-Authenticate HTTP header - class ProxyAuthenticate : public RC<thread_unsafe_refcount> { - public: - typedef RCPtr<ProxyAuthenticate> Ptr; - - ProxyAuthenticate() {} - - ProxyAuthenticate(const std::string& line) - { - do_parse(line); - } - - void parse(const std::string& line) - { - method = ""; - parms.clear(); - do_parse(line); - } - - std::string to_string() const - { - std::ostringstream out; - out << "Proxy-Authenticate header" << std::endl; - out << "method=" << method << std::endl; - out << parms.to_string(); - return out.str(); - } - - std::string method; - HTTP::HeaderList parms; - - private: - void do_parse(const std::string& line) - { - std::vector<std::string> tuple = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(line, ' ', 0, 1); - if (tuple.size() >= 1) - method = tuple[0]; - if (tuple.size() == 2) - { - std::vector<std::string> list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(tuple[1], ',', Split::TRIM_LEADING_SPACES|Split::TRIM_SPECIAL); - for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); ++i) - { - std::vector<std::string> pair = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(*i, '=', 0, 1); - if (pair.size() == 2) - parms.push_back(HTTP::Header(pair[0], pair[1])); - } - } - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/random/devurand.hpp b/Sources/OpenVPN3/openvpn/random/devurand.hpp deleted file mode 100644 index 0f230b2..0000000 --- a/Sources/OpenVPN3/openvpn/random/devurand.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// 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-2020 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_RANDOM_DEVURAND_H -#define OPENVPN_RANDOM_DEVURAND_H - -#include <sys/types.h> // for open() -#include <sys/stat.h> // for open() -#include <fcntl.h> // for open() - -#include <unistd.h> // for read() - -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - class DevURand : public RandomAPI - { - public: - OPENVPN_EXCEPTION(dev_urand_error); - - typedef RCPtr<DevURand> Ptr; - - DevURand() - : dev_urandom(::open("/dev/urandom", O_RDONLY)) - { - if (!dev_urandom.defined()) - throw dev_urand_error("init failed"); - } - - // Random algorithm name - virtual std::string name() const - { - return "DevURand"; - } - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const - { - return true; - } - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) - { - if (!rndbytes(buf, size)) - throw dev_urand_error("rand_bytes failed"); - } - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) - { - return rndbytes(buf, size); - } - - private: - bool rndbytes(unsigned char *buf, ssize_t size) - { - const ssize_t actual = ::read(dev_urandom(), buf, size); - return size == actual; - } - - ScopedFD dev_urandom; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/random/mtrandapi.hpp b/Sources/OpenVPN3/openvpn/random/mtrandapi.hpp deleted file mode 100644 index 91b00f2..0000000 --- a/Sources/OpenVPN3/openvpn/random/mtrandapi.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// 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-2020 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/>. - -// Non-cryptographic random number generator - -#ifndef OPENVPN_RANDOM_MTRANDAPI_H -#define OPENVPN_RANDOM_MTRANDAPI_H - -#include <random> - -#include <openvpn/common/size.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/random/randbytestore.hpp> - -namespace openvpn { - - class MTRand : public RandomAPI - { - public: - OPENVPN_EXCEPTION(mtrand_error); - - typedef RCPtr<MTRand> Ptr; - typedef std::mt19937_64 rand_type; - - MTRand(RandomAPI& seed) - : rng(gen_seed(seed)) - { - } - - MTRand() - : rng(gen_seed()) - { - } - - MTRand(const rand_type::result_type seed) - : rng(seed) - { - } - - // Random algorithm name - virtual std::string name() const - { - return "MTRand"; - } - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const - { - return false; - } - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) - { - if (!rndbytes(buf, size)) - throw mtrand_error("rand_bytes failed"); - } - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) - { - return rndbytes(buf, size); - } - - rand_type::result_type rand() - { - return rng(); - } - - private: - bool rndbytes(unsigned char *buf, size_t size) - { - while (size--) - *buf++ = rbs.get_byte(rng); - return true; - } - - static rand_type::result_type gen_seed(RandomAPI& seed) - { - return seed.rand_get<rand_type::result_type>(); - } - - static rand_type::result_type gen_seed() - { - std::random_device rd; - RandomByteStore<decltype(rd)> rbs; - rand_type::result_type ret; - rbs.fill(ret, rd); - return ret; - } - - rand_type rng; - RandomByteStore<rand_type> rbs; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/random/rand2.hpp b/Sources/OpenVPN3/openvpn/random/rand2.hpp deleted file mode 100644 index 89962b4..0000000 --- a/Sources/OpenVPN3/openvpn/random/rand2.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 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-2020 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 <utility> - -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - // By convention, rng is crypto-strength while prng is - // not. Be sure to always call RandomAPI::assert_crypto() - // before using an rng for crypto purposes, to verify that - // it is crypto-capable. - struct Rand2 - { - Rand2() {} - - Rand2(RandomAPI::Ptr rng_arg, - RandomAPI::Ptr prng_arg) - : rng(std::move(rng_arg)), - prng(std::move(prng_arg)) - { - } - - Rand2(RandomAPI::Ptr rng_arg) - : rng(std::move(rng_arg)), - prng(std::move(rng_arg)) - { - } - - RandomAPI::Ptr rng; - RandomAPI::Ptr prng; - }; - -} diff --git a/Sources/OpenVPN3/openvpn/random/randapi.hpp b/Sources/OpenVPN3/openvpn/random/randapi.hpp deleted file mode 100644 index cd18ec6..0000000 --- a/Sources/OpenVPN3/openvpn/random/randapi.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// 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-2020 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/>. - -// API for random number implementations. - -#pragma once - -#include <string> -#include <cstdint> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/random/randistrib.hpp> - -namespace openvpn { - - class RandomAPI : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<RandomAPI> Ptr; - - // Random algorithm name - virtual std::string name() const = 0; - - // Return true if algorithm is crypto-strength - virtual bool is_crypto() const = 0; - - // Fill buffer with random bytes - virtual void rand_bytes(unsigned char *buf, size_t size) = 0; - - // Like rand_bytes, but don't throw exception. - // Return true on successs, false on fail. - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) = 0; - - // Fill a data object with random bits - template <typename T> - void rand_fill(T& obj) - { - rand_bytes(reinterpret_cast<unsigned char *>(&obj), sizeof(T)); - } - - // Return a data object with random bits - template <typename T> - T rand_get() - { - T ret; - rand_fill(ret); - return ret; - } - - // Return a data object with random bits, always >= 0 for signed types - template <typename T> - T rand_get_positive() - { - T ret = rand_get<T>(); - if (ret < 0) - ret = -ret; - return ret; - } - - // Return a uniformly distributed random number in the range [0, end). - // end must be > 0. - template <typename T> - T randrange(const T end) - { - return rand_get_positive<T>() % end; - } - - // Return a uniformly distributed random number in the range [start, end]. - template <typename T> - T randrange(const T start, const T end) - { - if (start >= end) - return start; - else - return start + rand_get_positive<T>() % (end - start + 1); - } - - // Return a uniformly distributed random number in the range [0, end). - // This version is strictly 32-bit only and optimizes by avoiding - // integer division. - std::uint32_t randrange32(const std::uint32_t end) - { - std::uint32_t r; - rand_fill(r); - return rand32_distribute(r, end); - } - - // Return a uniformly distributed random number in the range [start, end]. - // This version is strictly 32-bit only and optimizes by avoiding - // integer division. - std::uint32_t randrange32(const std::uint32_t start, const std::uint32_t end) - { - if (start >= end) - return start; - else - return start + randrange32(end - start + 1); - } - - // Return a random byte - std::uint8_t randbyte() - { - std::uint8_t byte; - rand_fill(byte); - return byte; - } - - // Return a random boolean - bool randbool() - { - return bool(randbyte() & 1); - } - - // Throw an exception if algorithm is not crypto-strength. - // Be sure to always call this method before using an rng - // for crypto purposes. - void assert_crypto() const - { - if (!is_crypto()) - throw Exception("RandomAPI: " + name() + " algorithm is not crypto-strength"); - } - - // UniformRandomBitGenerator for std::shuffle - typedef unsigned int result_type; - static constexpr result_type min() { return result_type(0); } - static constexpr result_type max() { return ~result_type(0); } - result_type operator()() { return rand_get<result_type>(); } - }; - -} diff --git a/Sources/OpenVPN3/openvpn/random/randbytestore.hpp b/Sources/OpenVPN3/openvpn/random/randbytestore.hpp deleted file mode 100644 index 6c4563e..0000000 --- a/Sources/OpenVPN3/openvpn/random/randbytestore.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// 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-2020 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_RANDOM_RANDBYTESTORE_H -#define OPENVPN_RANDOM_RANDBYTESTORE_H - -#include <openvpn/common/size.hpp> - -namespace openvpn { - - template <typename RAND_TYPE> - class RandomByteStore - { - public: - static constexpr size_t SIZE = sizeof(typename RAND_TYPE::result_type); - - unsigned char get_byte(RAND_TYPE& rng) - { - if (n_bytes == 0) - { - res.rt = rng(); - n_bytes = SIZE; - } - unsigned char ret = res.bytes[0]; - res.rt >>= 8; - --n_bytes; - return ret; - } - - template <typename T> - void fill(T& obj, RAND_TYPE& rng) - { - unsigned char *data = reinterpret_cast<unsigned char *>(&obj); - for (size_t i = 0; i < sizeof(obj); ++i) - data[i] = get_byte(rng); - } - - private: - union Result { - unsigned char bytes[SIZE]; - typename RAND_TYPE::result_type rt; - }; - - Result res; - unsigned int n_bytes = 0; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/random/randistrib.hpp b/Sources/OpenVPN3/openvpn/random/randistrib.hpp deleted file mode 100644 index 34870a0..0000000 --- a/Sources/OpenVPN3/openvpn/random/randistrib.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// 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-2020 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 <cstdint> - -namespace openvpn { - - // Return a uniformly distributed random number in the range [0, end) - // using seed as a random seed. This version is strictly 32-bit only - // and optimizes by avoiding integer division. - inline std::uint32_t rand32_distribute(const std::uint32_t seed, - const std::uint32_t end) - { - return (std::uint64_t(seed) * end) >> 32; - } - -} diff --git a/Sources/OpenVPN3/openvpn/reliable/relack.hpp b/Sources/OpenVPN3/openvpn/reliable/relack.hpp deleted file mode 100644 index de21996..0000000 --- a/Sources/OpenVPN3/openvpn/reliable/relack.hpp +++ /dev/null @@ -1,119 +0,0 @@ -// 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-2020 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/>. - -// Handle ACK tracking for reliability layer - -#ifndef OPENVPN_RELIABLE_RELACK_H -#define OPENVPN_RELIABLE_RELACK_H - -#include <deque> -#include <algorithm> -#include <limits> - -#include <openvpn/common/socktypes.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/reliable/relcommon.hpp> - -namespace openvpn { - - class ReliableAck - { - public: - typedef reliable::id_t id_t; - - ReliableAck(const size_t max_ack_list) - : max_ack_list_(max_ack_list ? max_ack_list : std::numeric_limits<size_t>::max()) {} - - size_t size() const { return data.size(); } - bool empty() const { return data.empty(); } - void push_back(id_t value) { data.push_back(value); } - id_t front() const { return data.front(); } - void pop_front() { data.pop_front(); } - - // Called to read incoming ACK IDs from buf and mark them as ACKed in rel_send. - // If live is false, read the ACK IDs, but don't modify rel_send. - // Return the number of ACK IDs read. - template <typename REL_SEND> - static size_t ack(REL_SEND& rel_send, Buffer& buf, const bool live) - { - const size_t len = buf.pop_front(); - for (size_t i = 0; i < len; ++i) - { - const id_t id = read_id(buf); - if (live) - rel_send.ack(id); - } - return len; - } - - static size_t ack_skip(Buffer& buf) - { - const size_t len = buf.pop_front(); - for (size_t i = 0; i < len; ++i) - read_id(buf); - return len; - } - - // copy ACKs from buffer to self - void read(Buffer& buf) - { - const size_t len = buf.pop_front(); - for (size_t i = 0; i < len; ++i) - { - const id_t id = read_id(buf); - data.push_back(id); - } - } - - // called to write outgoing ACKs to buf - void prepend(Buffer& buf) - { - const size_t len = std::min(data.size(), max_ack_list_); - for (size_t i = len; i > 0; --i) - { - prepend_id(buf, data[i-1]); - } - buf.push_front((unsigned char)len); - data.erase (data.begin(), data.begin()+len); - } - - static void prepend_id(Buffer& buf, const id_t id) - { - const id_t net_id = htonl(id); - buf.prepend ((unsigned char *)&net_id, sizeof (net_id)); - } - - static id_t read_id(Buffer& buf) - { - id_t net_id; - buf.read ((unsigned char *)&net_id, sizeof (net_id)); - return ntohl(net_id); - } - - private: - size_t max_ack_list_; // Maximum number of ACKs placed in a single message by prepend_acklist() - std::deque<id_t> data; - }; - -} // namespace openvpn - -#endif // OPENVPN_RELIABLE_RELACK_H diff --git a/Sources/OpenVPN3/openvpn/reliable/relcommon.hpp b/Sources/OpenVPN3/openvpn/reliable/relcommon.hpp deleted file mode 100644 index 0846952..0000000 --- a/Sources/OpenVPN3/openvpn/reliable/relcommon.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// 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-2020 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/>. - -// Common reliability layer classes - -#ifndef OPENVPN_RELIABLE_RELCOMMON_H -#define OPENVPN_RELIABLE_RELCOMMON_H - -#include <openvpn/crypto/packet_id.hpp> - -namespace openvpn { - - namespace reliable { - typedef PacketID::id_t id_t; - } - - template <typename PACKET> - class ReliableMessageBase - { - public: - typedef reliable::id_t id_t; - - ReliableMessageBase() : id_(0), erased_(false) {} - bool defined() const { return bool(packet); } - bool erased() const { return erased_; } - - void erase() - { - id_ = id_t(0); - packet.reset(); - erased_ = true; - } - - id_t id() const { return id_; } - - PACKET packet; - - protected: - id_t id_; - bool erased_; - }; - -} // namespace openvpn - -#endif // OPENVPN_RELIABLE_RELCOMMON_H diff --git a/Sources/OpenVPN3/openvpn/reliable/relrecv.hpp b/Sources/OpenVPN3/openvpn/reliable/relrecv.hpp deleted file mode 100644 index 8184c5d..0000000 --- a/Sources/OpenVPN3/openvpn/reliable/relrecv.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// 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-2020 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/>. - -// Receiver side of reliability layer - -#ifndef OPENVPN_RELIABLE_RELRECV_H -#define OPENVPN_RELIABLE_RELRECV_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/msgwin.hpp> -#include <openvpn/reliable/relcommon.hpp> - -namespace openvpn { - - template <typename PACKET> - class ReliableRecvTemplate - { - public: - OPENVPN_SIMPLE_EXCEPTION(rel_next_sequenced_not_ready); - - typedef reliable::id_t id_t; - - class Message : public ReliableMessageBase<PACKET> - { - friend class ReliableRecvTemplate; - }; - - ReliableRecvTemplate() {} - ReliableRecvTemplate(const id_t span) { init(span); } - - void init(const id_t span) - { - window_.init(0, span); - } - - // Call with unsequenced packet off of the wire. - // Will return receive flags below. - enum { - ACK_TO_SENDER = (1<<0), // ACK for this packet should be returned to sender - IN_WINDOW = (1<<1) // Packet is in-window (otherwise, packet is dropped) - }; - unsigned int receive(const PACKET& packet, const id_t id) - { - if (window_.in_window(id)) - { - Message& m = window_.ref_by_id(id); - m.id_ = id; - m.packet = packet; - return ACK_TO_SENDER|IN_WINDOW; - } - else - return window_.pre_window(id) ? ACK_TO_SENDER : 0; - } - - // Return true if next_sequenced() is ready to return next message - bool ready() const { return window_.head_defined(); } - - // Return next message in sequence. - // Requires that ready() returns true. - Message& next_sequenced() - { - return window_.ref_head(); - } - - // Call after message returned by receive is ready to - // be disposed of. - void advance() - { - window_.rm_head_nocheck(); - } - - private: - MessageWindow<Message, id_t> window_; - }; - -} // namespace openvpn - -#endif // OPENVPN_RELIABLE_RELRECV_H diff --git a/Sources/OpenVPN3/openvpn/reliable/relsend.hpp b/Sources/OpenVPN3/openvpn/reliable/relsend.hpp deleted file mode 100644 index 1d37b0b..0000000 --- a/Sources/OpenVPN3/openvpn/reliable/relsend.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// 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-2020 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/>. - -// Sender side of reliability layer - -#ifndef OPENVPN_RELIABLE_RELSEND_H -#define OPENVPN_RELIABLE_RELSEND_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/msgwin.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/reliable/relcommon.hpp> - -namespace openvpn { - - template <typename PACKET> - class ReliableSendTemplate - { - public: - typedef reliable::id_t id_t; - - class Message : public ReliableMessageBase<PACKET> - { - friend class ReliableSendTemplate; - using ReliableMessageBase<PACKET>::defined; - - public: - bool ready_retransmit(const Time& now) const - { - return defined() && now >= retransmit_at_; - } - - Time::Duration until_retransmit(const Time& now) const - { - Time::Duration ret; - if (now < retransmit_at_) - ret = retransmit_at_ - now; - return ret; - } - - void reset_retransmit(const Time& now, const Time::Duration& tls_timeout) - { - retransmit_at_ = now + tls_timeout; - } - - private: - Time retransmit_at_; - }; - - ReliableSendTemplate() : next(0) {} - ReliableSendTemplate(const id_t span) { init(span); } - - void init(const id_t span) - { - next = 0; - window_.init(next, span); - } - - // Return the id that the object at the head of the queue - // would have (even if it isn't defined yet). - id_t head_id() const { return window_.head_id(); } - - // Return the ID of one past the end of the window - id_t tail_id() const { return window_.tail_id(); } - - // Return the window size - id_t span() const { return window_.span(); } - - // Return a reference to M object at id, throw exception - // if id is not in current window - Message& ref_by_id(const id_t id) - { - return window_.ref_by_id(id); - } - - // Return the shortest duration for any pending retransmissions - Time::Duration until_retransmit(const Time& now) - { - Time::Duration ret = Time::Duration::infinite(); - for (id_t i = head_id(); i < tail_id(); ++i) - { - const Message& msg = ref_by_id(i); - if (msg.defined()) - { - Time::Duration ut = msg.until_retransmit(now); - if (ut < ret) - ret = ut; - } - } - return ret; - } - - // Return number of unacknowleged packets in send queue - unsigned int n_unacked() - { - unsigned int ret = 0; - for (id_t i = head_id(); i < tail_id(); ++i) - { - if (ref_by_id(i).defined()) - ++ret; - } - return ret; - } - - // Return a fresh Message object that can be used to - // construct the next packet in the sequence. Don't call - // unless ready() returns true. - Message& send(const Time& now, const Time::Duration& tls_timeout) - { - Message& msg = window_.ref_by_id(next); - msg.id_ = next++; - msg.reset_retransmit(now, tls_timeout); - return msg; - } - - // Return true if send queue is ready to receive another packet - bool ready() const { return window_.in_window(next); } - - // Remove a message from send queue that has been acknowledged - void ack(const id_t id) { window_.rm_by_id(id); } - - private: - id_t next; - MessageWindow<Message, id_t> window_; - }; - -} // namespace openvpn - -#endif // OPENVPN_RELIABLE_RELSEND_H diff --git a/Sources/OpenVPN3/openvpn/server/listenlist.hpp b/Sources/OpenVPN3/openvpn/server/listenlist.hpp deleted file mode 100644 index 817bf08..0000000 --- a/Sources/OpenVPN3/openvpn/server/listenlist.hpp +++ /dev/null @@ -1,345 +0,0 @@ -// 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-2020 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_SERVER_LISTENLIST_H -#define OPENVPN_SERVER_LISTENLIST_H - -#include <string> -#include <vector> -#include <utility> // for std::move - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/format.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/transport/protocol.hpp> - -namespace openvpn { - namespace Listen { - struct Item - { - enum SSLMode { - SSLUnspecified, - SSLOn, - SSLOff, -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - AltRouting, -#endif - }; - - std::string directive; - std::string addr; - std::string port; - Protocol proto; - SSLMode ssl = SSLUnspecified; - unsigned int n_threads = 0; - - std::string to_string() const - { - std::string ret; - ret += directive + ' ' + addr; - if (!proto.is_local()) - ret += ' ' + port; - ret += ' ' + std::string(proto.str()) + ' ' + openvpn::to_string(n_threads); - switch (ssl) - { - case SSLUnspecified: - break; - case SSLOn: - ret += " ssl"; - break; - case SSLOff: - ret += " !ssl"; - break; -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - case AltRouting: - ret += " alt"; - break; -#endif - } - return ret; - } - - Item port_offset(const unsigned int offset) const - { - Item ret(*this); - if (ret.proto.is_unix()) // unix socket filenames should contain %s for "port" substitution - ret.addr = printfmt(ret.addr, offset); - else - ret.port = openvpn::to_string(HostPort::parse_port(ret.port, "offset") + offset); - ret.n_threads = 0; - return ret; - } - }; - - class List : public std::vector<Item> - { - public: - enum LoadMode { - Nominal, - AllowDefault, - AllowEmpty - }; - - List() {} - - List(const Item& item) - { - push_back(item); - } - - List(Item&& item) - { - push_back(std::move(item)); - } - - List(const OptionList& opt, - const std::string& directive, - const LoadMode load_mode, - const unsigned int n_cores) - { - size_t n_listen = 0; - - for (auto &o : opt) - { - if (match(directive, o)) - ++n_listen; - } - - if (n_listen) - { - reserve(n_listen); - - for (auto &o : opt) - { - if (match(directive, o)) - { - o.touch(); - - unsigned int mult = 1; - unsigned int local = 0; - - Item e; - - // directive - e.directive = o.get(0, 64); - - // IP address - e.addr = o.get(1, 128); - - // port number - e.port = o.get(2, 16); - if (Protocol::is_local_type(e.port)) - { - local = 1; - e.port = ""; - } - else - HostPort::validate_port(e.port, e.directive); - - // protocol - { - const std::string title = e.directive + " protocol"; - e.proto = Protocol::parse(o.get(3-local, 16), Protocol::NO_SUFFIX, title.c_str()); - } - if (!local) - { - // modify protocol based on IP version of given address - const std::string title = e.directive + " addr"; - const IP::Addr addr = IP::Addr(e.addr, title.c_str()); - e.proto.mod_addr_version(addr); - } - - // number of threads - int n_threads_exists = 0; - { - const std::string ntstr = o.get_optional(4-local, 16); - if (ntstr.length() > 0 && string::is_digit(ntstr[0])) - n_threads_exists = 1; - } - if (n_threads_exists) - { - std::string n_threads = o.get(4-local, 16); - if (string::ends_with(n_threads, "*N")) - { - mult = n_cores; - n_threads = n_threads.substr(0, n_threads.length() - 2); - } - if (!parse_number_validate<unsigned int>(n_threads, 3, 1, 100, &e.n_threads)) - OPENVPN_THROW(option_error, e.directive << ": bad num threads: " << n_threads); -#ifndef OPENVPN_PLATFORM_WIN - if (local && e.n_threads != 1) - OPENVPN_THROW(option_error, e.directive << ": local socket only supports one thread per pathname (not " << n_threads << ')'); -#endif - e.n_threads *= mult; - } - else - e.n_threads = 1; - - // SSL - if (o.size() >= 5-local+n_threads_exists) - { - const std::string& ssl_qualifier = o.get(4-local+n_threads_exists, 16); - if (ssl_qualifier == "ssl") - { - if (local) - OPENVPN_THROW(option_error, e.directive << ": SSL not supported on local sockets"); - e.ssl = Item::SSLOn; - } - else if (ssl_qualifier == "!ssl") - e.ssl = Item::SSLOff; -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - else if (ssl_qualifier == "alt") - e.ssl = Item::AltRouting; -#endif - else - OPENVPN_THROW(option_error, e.directive << ": unrecognized SSL qualifier"); - } - - push_back(std::move(e)); - } - } - } - else if (load_mode == AllowDefault) - { - Item e; - - // parse "proto" option if present - { - const Option* o = opt.get_ptr("proto"); - if (o) - e.proto = Protocol::parse(o->get(1, 16), Protocol::SERVER_SUFFIX); - else - e.proto = Protocol(Protocol::UDPv4); - } - - // parse "port" option if present - { - const Option* o = opt.get_ptr("lport"); - if (!o) - o = opt.get_ptr("port"); - if (o) - { - e.port = o->get(1, 16); - HostPort::validate_port(e.port, "listen"); - } - else - e.port = "1194"; - } - - // parse "local" option if present - { - const Option* o = opt.get_ptr("local"); - if (o) - { - e.addr = o->get(1, 128); - const IP::Addr addr = IP::Addr(e.addr, "local addr"); - e.proto.mod_addr_version(addr); - } - else if (e.proto.is_ipv6()) - e.addr = "::0"; - else - e.addr = "0.0.0.0"; - } - - // n_threads defaults to one unless "listen" directive is used - e.n_threads = 1; - - push_back(std::move(e)); - } - else if (load_mode != AllowEmpty) - OPENVPN_THROW(option_error, "no " << directive << " directives found"); - } - - unsigned int total_threads() const - { - unsigned int ret = 0; - for (auto &i : *this) - ret += i.n_threads; - return ret; - } - - std::string to_string() const - { - std::string ret; - for (auto &i : *this) - { - ret += i.to_string(); - ret += '\n'; - } - return ret; - } - - std::string local_addr() const - { - for (auto &i : *this) - if (i.proto.is_local()) - return i.addr; - return std::string(); - } - - List expand_ports_by_n_threads(const size_t max_size) const - { - List ret; - for (const auto &e : *this) - { - unsigned int offset = 0; - do { - if (ret.size() >= max_size) - OPENVPN_THROW(option_error, e.directive << ": max_size=" << max_size << " exceeded"); - ret.emplace_back(e.port_offset(offset)); - } while (++offset < e.n_threads); - } - return ret; - } - - List expand_ports_by_unit(const unsigned int unit) const - { - List ret; - for (const auto &e : *this) - ret.emplace_back(e.port_offset(unit)); - return ret; - } - - private: - static bool match(const std::string& directive, const Option& o) - { - const size_t len = directive.length(); - if (len && o.size()) - { - if (directive[len-1] == '-') - return string::starts_with(o.ref(0), directive); - else - return o.ref(0) == directive; - } - else - return false; - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/manage.hpp b/Sources/OpenVPN3/openvpn/server/manage.hpp deleted file mode 100644 index 56ccf5c..0000000 --- a/Sources/OpenVPN3/openvpn/server/manage.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// 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-2020 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/>. - -// Server-side client manager - -#ifndef OPENVPN_SERVER_MANAGE_H -#define OPENVPN_SERVER_MANAGE_H - -#include <string> -#include <vector> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/tun/server/tunbase.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/auth/authcreds.hpp> -#include <openvpn/ssl/proto.hpp> -#include <openvpn/server/servhalt.hpp> -#include <openvpn/server/peerstats.hpp> -#include <openvpn/server/peeraddr.hpp> -#include <openvpn/auth/authcert.hpp> -#include <openvpn/auth/authstatusconst.hpp> - -namespace openvpn { - namespace ManClientInstance { - - // Base class for the per-client-instance state of the ManServer. - // Each client instance uses this class to send data to the man layer. - struct Send : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Send> Ptr; - - virtual void pre_stop() = 0; - virtual void stop() = 0; - - virtual void auth_request(const AuthCreds::Ptr& auth_creds, - const AuthCert::Ptr& auth_cert, - const PeerAddr::Ptr& peer_addr) = 0; - virtual void push_request(ProtoContext::Config::Ptr pconf) = 0; - - // INFO notification - virtual void info_request(const std::string& imsg) = 0; - - // bandwidth stats notification - virtual void stats_notify(const PeerStats& ps, const bool final) = 0; - - // client float notification - virtual void float_notify(const PeerAddr::Ptr& addr) = 0; - - // ID - virtual std::string instance_name() const = 0; - virtual std::uint64_t instance_id() const = 0; - - // return a JSON string describing connected user - virtual std::string describe_user(const bool show_userprop) = 0; - - // disconnect - virtual void disconnect_user(const HaltRestart::Type type, - const AuthStatus::Type auth_status, - const std::string& reason, - const bool tell_client) = 0; - - // send control channel message - virtual void post_info_user(BufferPtr&& info) = 0; - - // set ACL index for user - virtual void set_acl_index(const int acl_index, - const std::string* username, - const bool challenge) = 0; - - // notify of local user properties update - virtual void userprop_local_update() = 0; - - // create, update, or delete a DOMA ACL - virtual Json::Value doma_acl(const Json::Value& root) = 0; - - // override keepalive parameters - virtual void keepalive_override(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) = 0; - }; - - // Base class for the client instance receiver. Note that all - // client instance receivers (transport, routing, management, - // etc.) must inherit virtually from RC because the client instance - // object will inherit from multiple receivers. - struct Recv : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Recv> Ptr; - - virtual void stop() = 0; - - virtual void auth_failed(const std::string& reason, - const bool tell_client) = 0; - - virtual void push_reply(std::vector<BufferPtr>&& push_msgs) = 0; - - // push a halt or restart message to client - virtual void push_halt_restart_msg(const HaltRestart::Type type, - const std::string& reason, - const bool tell_client) = 0; - - - // send control channel message - virtual void post_cc_msg(BufferPtr&& msg) = 0; - - // schedule a low-level connection disconnect in seconds - virtual void schedule_disconnect(const unsigned int seconds) = 0; - - // schedule an auth pending disconnect in seconds - virtual void schedule_auth_pending_timeout(const unsigned int seconds) = 0; - - // set up relay to target - virtual void relay(const IP::Addr& target, const int port) = 0; - - // get client bandwidth stats - virtual PeerStats stats_poll() = 0; - - // return true if management layer should preserve session ID - virtual bool should_preserve_session_id() = 0; - - // get native reference to client instance - virtual TunClientInstance::NativeHandle tun_native_handle() = 0; - }; - - struct Factory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Factory> Ptr; - - virtual void start() = 0; - virtual void stop() = 0; - - virtual Send::Ptr new_obj(Recv* instance) = 0; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/peeraddr.hpp b/Sources/OpenVPN3/openvpn/server/peeraddr.hpp deleted file mode 100644 index c1b7688..0000000 --- a/Sources/OpenVPN3/openvpn/server/peeraddr.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// 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-2020 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_SERVER_PEERADDR_H -#define OPENVPN_SERVER_PEERADDR_H - -#include <cstdint> // for std::uint32_t, uint64_t, etc. - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - struct AddrPort - { - AddrPort() : port(0) {} - - std::string to_string() const - { - return addr.to_string_bracket_ipv6() + ':' + openvpn::to_string(port); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value jret(Json::objectValue); - jret["addr"] = Json::Value(addr.to_string()); - jret["port"] = Json::Value(port); - return jret; - } -#endif - - IP::Addr addr; - std::uint16_t port; - }; - - struct PeerAddr : public RCCopyable<thread_unsafe_refcount> - { - typedef RCPtr<PeerAddr> Ptr; - - PeerAddr() - : tcp(false) - { - } - - std::string to_string() const - { - std::string proto; - if (tcp) - proto = "TCP "; - else - proto = "UDP "; - return proto + remote.to_string() + " -> " + local.to_string(); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value jret(Json::objectValue); - jret["tcp"] = Json::Value(tcp); - jret["local"] = local.to_json(); - jret["remote"] = remote.to_json(); - return jret; - } -#endif - - AddrPort remote; - AddrPort local; - bool tcp; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/peerstats.hpp b/Sources/OpenVPN3/openvpn/server/peerstats.hpp deleted file mode 100644 index 34306ba..0000000 --- a/Sources/OpenVPN3/openvpn/server/peerstats.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// 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-2020 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_SERVER_PEERSTATS_H -#define OPENVPN_SERVER_PEERSTATS_H - -#include <string> -#include <cstdint> // for std::uint32_t, uint64_t, etc. - -namespace openvpn { - - struct PeerStats - { - std::string to_string() const - { - std::string ret; - ret.reserve(64); - ret += "[rx="; - ret += std::to_string(rx_bytes); - ret += " tx="; - ret += std::to_string(tx_bytes); - ret += " status="; - ret += std::to_string(status); - ret += ']'; - return ret; - } - - std::uint64_t rx_bytes = 0; - std::uint64_t tx_bytes = 0; - int status = 0; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/servhalt.hpp b/Sources/OpenVPN3/openvpn/server/servhalt.hpp deleted file mode 100644 index 0f8de71..0000000 --- a/Sources/OpenVPN3/openvpn/server/servhalt.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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> - -namespace openvpn { - namespace HaltRestart { - enum Type { - HALT, // disconnect - RESTART, // restart, don't preserve session token - RESTART_PSID, // restart, preserve session token - RESTART_PASSIVE, // restart, preserve session token and local client instance object - AUTH_FAILED, // auth fail, don't preserve session token - RAW, // pass raw message to client - }; - - inline std::string to_string(Type type) - { - switch (type) - { - case HALT: - return "HALT"; - case RESTART: - return "RESTART"; - case RESTART_PSID: - return "RESTART_PSID"; - case RESTART_PASSIVE: - return "RESTART_PASSIVE"; - case AUTH_FAILED: - return "AUTH_FAILED"; - case RAW: - return "RAW"; - default: - return "HaltRestart_?"; - } - } - } -} diff --git a/Sources/OpenVPN3/openvpn/server/servproto.hpp b/Sources/OpenVPN3/openvpn/server/servproto.hpp deleted file mode 100644 index 3a1ece0..0000000 --- a/Sources/OpenVPN3/openvpn/server/servproto.hpp +++ /dev/null @@ -1,752 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN protocol implementation for client-instance object on server - -#ifndef OPENVPN_SERVER_SERVPROTO_H -#define OPENVPN_SERVER_SERVPROTO_H - -#include <memory> -#include <utility> // for std::move - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/abort.hpp> -#include <openvpn/common/link.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/buffer/bufstream.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/time/coarsetime.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/ssl/proto.hpp> -#include <openvpn/transport/server/transbase.hpp> -#include <openvpn/tun/server/tunbase.hpp> -#include <openvpn/server/manage.hpp> - -#ifdef OPENVPN_DEBUG_SERVPROTO -#define OPENVPN_LOG_SERVPROTO(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_SERVPROTO(x) -#endif - -namespace openvpn { - - class ServerProto - { - typedef ProtoContext Base; - typedef Link<TransportClientInstance::Send, TransportClientInstance::Recv> TransportLink; - typedef Link<TunClientInstance::Send, TunClientInstance::Recv> TunLink; - typedef Link<ManClientInstance::Send, ManClientInstance::Recv> ManLink; - - public: - class Session; - - class Factory : public TransportClientInstance::Factory - { - public: - typedef RCPtr<Factory> Ptr; - typedef Base::Config ProtoConfig; - - Factory(openvpn_io::io_context& io_context_arg, - const Base::Config& c) - : io_context(io_context_arg) - { - if (c.tls_crypt_enabled()) - preval.reset(new Base::TLSCryptPreValidate(c, true)); - else if (c.tls_auth_enabled()) - preval.reset(new Base::TLSAuthPreValidate(c, true)); - } - - virtual TransportClientInstance::Recv::Ptr new_client_instance() override; - - virtual bool validate_initial_packet(const BufferAllocated& net_buf) override - { - if (preval) - { - const bool ret = preval->validate(net_buf); - if (!ret) - stats->error(Error::TLS_AUTH_FAIL); - return ret; - } - else - return true; - } - - ProtoConfig::Ptr clone_proto_config() const - { - return new ProtoConfig(*proto_context_config); - } - - openvpn_io::io_context& io_context; - ProtoConfig::Ptr proto_context_config; - - ManClientInstance::Factory::Ptr man_factory; - TunClientInstance::Factory::Ptr tun_factory; - - SessionStats::Ptr stats; - - private: - Base::TLSWrapPreValidate::Ptr preval; - }; - - // This is the main server-side client instance object - class Session : Base, // OpenVPN protocol implementation - public TransportLink, // Transport layer - public TunLink, // Tun/routing layer - public ManLink // Management layer - { - friend class Factory; // calls constructor - - typedef Base::PacketType PacketType; - - using Base::now; - using Base::stat; - - public: - typedef RCPtr<Session> Ptr; - - virtual bool defined() const override - { - return defined_(); - } - - virtual TunClientInstance::Recv* override_tun(TunClientInstance::Send* tun) override - { - TunLink::send.reset(tun); - return this; - } - - virtual void start(const TransportClientInstance::Send::Ptr& parent, - const PeerAddr::Ptr& addr, - const int local_peer_id) override - { - TransportLink::send = parent; - peer_addr = addr; - - // init OpenVPN protocol handshake - Base::update_now(); - Base::reset(); - Base::set_local_peer_id(local_peer_id); - Base::start(); - Base::flush(true); - - // coarse wakeup range - housekeeping_schedule.init(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024)); - } - - virtual PeerStats stats_poll() override - { - if (TransportLink::send) - return TransportLink::send->stats_poll(); - else - return PeerStats(); - } - - virtual bool should_preserve_session_id() override - { - return preserve_session_id; - } - - virtual void stop() override - { - if (!halt) - { - halt = true; - housekeeping_timer.cancel(); - - if (ManLink::send) - ManLink::send->pre_stop(); - - // deliver final peer stats to management layer - if (TransportLink::send && ManLink::send) - { - if (TransportLink::send->stats_pending()) - ManLink::send->stats_notify(TransportLink::send->stats_poll(), true); - } - - Base::pre_destroy(); - Base::reset_dc_factory(); - if (TransportLink::send) - { - TransportLink::send->stop(); - TransportLink::send.reset(); - } - if (TunLink::send) - { - TunLink::send->stop(); - TunLink::send.reset(); - } - if (ManLink::send) - { - ManLink::send->stop(); - ManLink::send.reset(); - } - } - } - - // called with OpenVPN-encapsulated packets from transport layer - virtual bool transport_recv(BufferAllocated& buf) override - { - bool ret = false; - if (!Base::primary_defined()) - return false; - try { - OPENVPN_LOG_SERVPROTO("Transport RECV[" << buf.size() << "] " << client_endpoint_render() << ' ' << Base::dump_packet(buf)); - - // update current time - Base::update_now(); - - // get packet type - Base::PacketType pt = Base::packet_type(buf); - - // process packet - if (pt.is_data()) - { - // data packet - ret = Base::data_decrypt(pt, buf); - if (buf.size()) - { -#ifdef OPENVPN_PACKET_LOG - log_packet(buf, false); -#endif - // make packet appear as incoming on tun interface - if (true) // fixme: was tun - { - OPENVPN_LOG_SERVPROTO("TUN SEND[" << buf.size() << ']'); - // fixme -- code me - } - } - - // do a lightweight flush - Base::flush(false); - } - else if (pt.is_control()) - { - // control packet - ret = Base::control_net_recv(pt, std::move(buf)); - - // do a full flush - Base::flush(true); - } - - // schedule housekeeping wakeup - set_housekeeping_timer(); - } - catch (const std::exception& e) - { - error(e); - ret = false; - } - - return ret; - } - - // called with cleartext IP packets from routing layer - virtual void tun_recv(BufferAllocated& buf) override - { - // fixme -- code me - } - - // Return true if keepalive parameter(s) are enabled. - virtual bool is_keepalive_enabled() const override - { - return Base::is_keepalive_enabled(); - } - - // Disable keepalive for rest of session, but fetch - // the keepalive parameters (in seconds). - // Also, allow the management layer to override parameters. - virtual void disable_keepalive(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) override - { - Base::disable_keepalive(keepalive_ping, keepalive_timeout); - if (ManLink::send) - ManLink::send->keepalive_override(keepalive_ping, keepalive_timeout); - } - - // override the data channel factory - virtual void override_dc_factory(const CryptoDCFactory::Ptr& dc_factory) override - { - Base::dc_settings().set_factory(dc_factory); - } - - virtual ~Session() - { - // fatal error if destructor called while Session is active - if (defined_()) - std::abort(); - } - - private: - Session(openvpn_io::io_context& io_context_arg, - const Factory& factory, - ManClientInstance::Factory::Ptr man_factory_arg, - TunClientInstance::Factory::Ptr tun_factory_arg) - : Base(factory.clone_proto_config(), factory.stats), - housekeeping_timer(io_context_arg), - disconnect_at(Time::infinite()), - stats(factory.stats), - man_factory(man_factory_arg), - tun_factory(tun_factory_arg) - {} - - bool defined_() const - { - return !halt && TransportLink::send; - } - - // proto base class calls here for control channel network sends - virtual void control_net_send(const Buffer& net_buf) override - { - OPENVPN_LOG_SERVPROTO("Transport SEND[" << net_buf.size() << "] " << client_endpoint_render() << ' ' << Base::dump_packet(net_buf)); - if (TransportLink::send) - { - if (TransportLink::send->transport_send_const(net_buf)) - Base::update_last_sent(); - } - } - - // Called on server with credentials and peer info provided by client. - // Should be overriden by derived class if credentials are required. - virtual void server_auth(const std::string& username, - const SafeString& password, - const std::string& peer_info, - const AuthCert::Ptr& auth_cert) override - { - constexpr size_t MAX_USERNAME_SIZE = 256; - constexpr size_t MAX_PASSWORD_SIZE = 16384; - - if (get_management()) - { - AuthCreds::Ptr auth_creds(new AuthCreds(Unicode::utf8_printable(username, MAX_USERNAME_SIZE|Unicode::UTF8_FILTER), - Unicode::utf8_printable(password, MAX_PASSWORD_SIZE|Unicode::UTF8_FILTER|Unicode::UTF8_PASS_FMT), - Unicode::utf8_printable(peer_info, Unicode::UTF8_FILTER|Unicode::UTF8_PASS_FMT))); - ManLink::send->auth_request(auth_creds, auth_cert, peer_addr); - } - } - - // proto base class calls here for app-level control-channel messages received - virtual void control_recv(BufferPtr&& app_bp) override - { - const std::string msg = Unicode::utf8_printable(Base::template read_control_string<std::string>(*app_bp), - Unicode::UTF8_FILTER); - if (msg == "PUSH_REQUEST") - { - if (get_management()) - ManLink::send->push_request(Base::conf_ptr()); - else - auth_failed("no management provider", false); - } - else if (string::starts_with(msg, "INFO,")) - { - if (get_management()) - ManLink::send->info_request(msg.substr(5)); - } - else - { - OPENVPN_LOG("Unrecognized client request: " << msg); - } - } - - virtual void auth_failed(const std::string& reason, - const bool tell_client) override - { - push_halt_restart_msg(HaltRestart::AUTH_FAILED, reason, tell_client); - } - - virtual void relay(const IP::Addr& target, const int port) override - { - if (halt || disconnect_type == DT_HALT_RESTART) - return; - - Base::update_now(); - - if (TunLink::send && (disconnect_type < DT_RELAY_TRANSITION)) - { - disconnect_type = DT_RELAY_TRANSITION; - TunLink::send->relay(target, port); - disconnect_in(Time::Duration::seconds(10)); // not a real disconnect, just complete transition to relay - } - - if (Base::primary_defined()) - { - BufferPtr buf(new BufferAllocated(64, 0)); - buf_append_string(*buf, "RELAY"); - buf->null_terminate(); - Base::control_send(std::move(buf)); - Base::flush(true); - } - - set_housekeeping_timer(); - } - - virtual void push_reply(std::vector<BufferPtr>&& push_msgs) override - { - if (halt || (disconnect_type >= DT_RELAY_TRANSITION) || !Base::primary_defined()) - return; - - if (disconnect_type == DT_AUTH_PENDING) - { - disconnect_type = DT_NONE; - cancel_disconnect(); - } - - Base::update_now(); - - if (get_tun()) - { - Base::init_data_channel(); - for (auto &msg : push_msgs) - { - msg->null_terminate(); - Base::control_send(std::move(msg)); - } - Base::flush(true); - set_housekeeping_timer(); - } - else - { - auth_failed("no tun provider", false); - } - } - - virtual TunClientInstance::NativeHandle tun_native_handle() override - { - if (get_tun()) - return TunLink::send->tun_native_handle(); - else - return TunClientInstance::NativeHandle(); - } - - virtual void push_halt_restart_msg(const HaltRestart::Type type, - const std::string& reason, - const bool tell_client) override - { - if (halt || disconnect_type == DT_HALT_RESTART) - return; - - Base::update_now(); - - BufferPtr buf(new BufferAllocated(128, BufferAllocated::GROW)); - BufferStreamOut os(*buf); - - std::string ts; - - switch (type) - { - case HaltRestart::HALT: - ts = "HALT"; - os << "HALT,"; - if (tell_client && !reason.empty()) - os << reason; - else - os << "client was disconnected from server"; - disconnect_type = DT_HALT_RESTART; - disconnect_in(Time::Duration::seconds(1)); - preserve_session_id = false; - break; - case HaltRestart::RESTART: - ts = "RESTART"; - os << "RESTART,"; - if (tell_client && !reason.empty()) - os << reason; - else - os << "server requested a client reconnect"; - disconnect_type = DT_HALT_RESTART; - disconnect_in(Time::Duration::seconds(1)); - preserve_session_id = false; - break; - case HaltRestart::RESTART_PASSIVE: - ts = "RESTART_PASSIVE"; - os << "RESTART,[P]:"; - if (tell_client && !reason.empty()) - os << reason; - else - os << "server requested a client reconnect"; - break; - case HaltRestart::RESTART_PSID: - ts = "RESTART_PSID"; - os << "RESTART,[P]:"; - if (tell_client && !reason.empty()) - os << reason; - else - os << "server requested a client reconnect"; - disconnect_type = DT_HALT_RESTART; - disconnect_in(Time::Duration::seconds(1)); - break; - case HaltRestart::AUTH_FAILED: - ts = "AUTH_FAILED"; - os << ts; - if (tell_client && !reason.empty()) - os << ',' << reason; - disconnect_type = DT_HALT_RESTART; - disconnect_in(Time::Duration::seconds(1)); - preserve_session_id = false; - break; - case HaltRestart::RAW: - { - const size_t pos = reason.find_first_of(','); - if (pos != std::string::npos) - ts = reason.substr(0, pos); - else - ts = reason; - os << reason; - disconnect_type = DT_HALT_RESTART; - disconnect_in(Time::Duration::seconds(1)); - preserve_session_id = false; - break; - } - } - - OPENVPN_LOG("Disconnect: " << ts << ' ' << reason); - - if (Base::primary_defined()) - { - buf->null_terminate(); - Base::control_send(std::move(buf)); - Base::flush(true); - } - - set_housekeeping_timer(); - } - - virtual void schedule_disconnect(const unsigned int seconds) override - { - if (halt || disconnect_type == DT_HALT_RESTART) - return; - Base::update_now(); - disconnect_in(Time::Duration::seconds(seconds)); - set_housekeeping_timer(); - } - - virtual void schedule_auth_pending_timeout(const unsigned int seconds) override - { - if (halt || (disconnect_type >= DT_RELAY_TRANSITION) || !seconds) - return; - Base::update_now(); - disconnect_type = DT_AUTH_PENDING; - disconnect_in(Time::Duration::seconds(seconds)); - set_housekeeping_timer(); - } - - virtual void post_cc_msg(BufferPtr&& msg) override - { - if (halt || !Base::primary_defined()) - return; - - Base::update_now(); - msg->null_terminate(); - Base::control_send(std::move(msg)); - Base::flush(true); - set_housekeeping_timer(); - } - - virtual void stats_notify(const PeerStats& ps, const bool final) override - { - if (ManLink::send) - ManLink::send->stats_notify(ps, final); - } - - virtual void float_notify(const PeerAddr::Ptr& addr) override - { - if (ManLink::send) - ManLink::send->float_notify(addr); - } - - virtual void data_limit_notify(const int key_id, - const DataLimit::Mode cdl_mode, - const DataLimit::State cdl_status) override - { - Base::update_now(); - Base::data_limit_notify(key_id, cdl_mode, cdl_status); - Base::flush(true); - set_housekeeping_timer(); - } - - bool get_management() - { - if (!ManLink::send) - { - if (man_factory) - ManLink::send = man_factory->new_obj(this); - } - return bool(ManLink::send); - } - - bool get_tun() - { - if (!TunLink::send) - { - if (tun_factory) - TunLink::send = tun_factory->new_obj(this); - } - return bool(TunLink::send); - } - - // caller must ensure that update_now() was called before - // and set_housekeeping_timer() called after this method - void disconnect_in(const Time::Duration& dur) - { - disconnect_at = now() + dur; - } - - void cancel_disconnect() - { - disconnect_at = Time::infinite(); - } - - void housekeeping_callback(const openvpn_io::error_code& e) - { - try { - if (!e && !halt) - { - // update current time - Base::update_now(); - - housekeeping_schedule.reset(); - Base::housekeeping(); - if (Base::invalidated()) - invalidation_error(Base::invalidation_reason()); - else if (now() >= disconnect_at) - { - switch (disconnect_type) - { - case DT_HALT_RESTART: - error("disconnect triggered"); - break; - case DT_RELAY_TRANSITION: - Base::pre_destroy(); - break; - case DT_AUTH_PENDING: - auth_failed("Auth Pending Timeout", true); - break; - default: - error("unknown disconnect"); - break; - } - } - else - set_housekeeping_timer(); - } - } - catch (const std::exception& e) - { - error(e); - } - } - - void set_housekeeping_timer() - { - Time next = Base::next_housekeeping(); - next.min(disconnect_at); - if (!housekeeping_schedule.similar(next)) - { - if (!next.is_infinite()) - { - next.max(now()); - housekeeping_schedule.reset(next); - housekeeping_timer.expires_at(next); - housekeeping_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - self->housekeeping_callback(error); - }); - } - else - { - housekeeping_timer.cancel(); - housekeeping_schedule.reset(); - } - } - } - - std::string client_endpoint_render() - { - if (TransportLink::send) - return TransportLink::send->transport_info(); - else - return ""; - } - - void error(const std::string& error) - { - OPENVPN_LOG("ServerProto: " << error); - stop(); - } - - void error(const std::exception& e) - { - error(e.what()); - } - - void error() - { - stop(); - } - - void invalidation_error(const Error::Type err) - { - switch (err) - { - case Error::KEV_NEGOTIATE_ERROR: - case Error::KEEPALIVE_TIMEOUT: - error(); - break; - default: - error(std::string("Session invalidated: ") + Error::name(err)); - break; - } - } - - // higher values are higher priority - enum DisconnectType { - DT_NONE=0, - DT_AUTH_PENDING, - DT_RELAY_TRANSITION, - DT_HALT_RESTART, - }; - int disconnect_type = DT_NONE; - bool preserve_session_id = true; - - bool halt = false; - - PeerAddr::Ptr peer_addr; - - CoarseTime housekeeping_schedule; - AsioTimer housekeeping_timer; - - Time disconnect_at; - - SessionStats::Ptr stats; - - ManClientInstance::Factory::Ptr man_factory; - TunClientInstance::Factory::Ptr tun_factory; - }; - }; - - inline TransportClientInstance::Recv::Ptr ServerProto::Factory::new_client_instance() - { - return new Session(io_context, *this, man_factory, tun_factory); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/vpnservnetblock.hpp b/Sources/OpenVPN3/openvpn/server/vpnservnetblock.hpp deleted file mode 100644 index d206727..0000000 --- a/Sources/OpenVPN3/openvpn/server/vpnservnetblock.hpp +++ /dev/null @@ -1,223 +0,0 @@ -// 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-2020 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_SERVER_VPNSERVNETBLOCK_H -#define OPENVPN_SERVER_VPNSERVNETBLOCK_H - -#include <sstream> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/addr/range.hpp> - -namespace openvpn { - - class VPNServerNetblock - { - public: - OPENVPN_EXCEPTION(vpn_serv_netblock); - - struct Netblock - { - Netblock() {} - - Netblock(const IP::Route& route) - { - if (!route.is_canonical()) - throw vpn_serv_netblock("not canonical"); - if (route.host_bits() < 2) - throw vpn_serv_netblock("need at least 4 addresses in netblock"); - net = route.addr; - server_gw = net + 1; - prefix_len = route.prefix_len; - } - - bool defined() const { return net.defined(); } - - IP::Addr netmask() const - { - return IP::Addr::netmask_from_prefix_len(net.version(), prefix_len); - } - - bool contains(const IP::Addr& a) const - { - if (net.defined() && net.version() == a.version()) - return (a & netmask()) == net; - else - return false; - } - - std::string to_string() const - { - return '[' + net.to_string() + '/' + std::to_string(prefix_len) + ',' + server_gw.to_string() + ']'; - } - - IP::Addr net; - IP::Addr server_gw; - unsigned int prefix_len = 0; - }; - - struct ClientNetblock : public Netblock - { - ClientNetblock() {} - - ClientNetblock(const IP::Route& route) - : Netblock(route) - { - const size_t extent = route.extent(); - bcast = net + (extent - 1); - clients = IP::Range(net + 2, extent - 3); - } - - std::string to_string() const - { - return '[' + Netblock::to_string() + ',' - + clients.to_string() + ',' - + bcast.to_string() + ']'; - } - - IP::Range clients; - IP::Addr bcast; - }; - - class PerThread - { - friend class VPNServerNetblock; - - public: - const IP::Range& range4() const { return range4_; } - - bool range6_defined() const { return range6_.defined(); } - const IP::Range& range6() const { return range6_; } - - private: - IP::Range range4_; - IP::Range range6_; - }; - - VPNServerNetblock(const OptionList& opt, - const std::string& opt_name, - const bool ipv4_optional, - const unsigned int n_threads) - { - // ifconfig - if (!ipv4_optional || opt.exists(opt_name)) - { - const Option& o = opt.get(opt_name); - const IP::Addr gw(o.get(1, 64), opt_name + " gateway"); - const IP::Addr nm(o.get(2, 64), opt_name + " netmask"); - IP::Route rt(gw, nm.prefix_len()); - if (rt.version() != IP::Addr::V4) - throw vpn_serv_netblock(opt_name + " address is not IPv4"); - rt.force_canonical(); - snb4 = ClientNetblock(rt); - if (snb4.server_gw != gw) - throw vpn_serv_netblock(opt_name + " local gateway must be first usable address of subnet"); - } - - // ifconfig-ipv6 - { - const Option* o = opt.get_ptr(opt_name + "-ipv6"); - if (o) - { - IP::Route rt(o->get(1, 64), opt_name + "-ipv6 network"); - if (rt.version() != IP::Addr::V6) - throw vpn_serv_netblock(opt_name + "-ipv6 network is not IPv6"); - if (!rt.is_canonical()) - throw vpn_serv_netblock(opt_name + "-ipv6 network is not canonical"); - snb6 = ClientNetblock(rt); - } - } - - if (n_threads) - { - // IPv4 per-thread partition - { - IP::RangePartition rp(snb4.clients, n_threads); - IP::Range crange; - for (unsigned int i = 0; i < n_threads; ++i) - { - if (!rp.next(crange)) - throw vpn_serv_netblock(opt_name + " : unexpected ServerNetblock4 partition fail"); - PerThread pt; - pt.range4_ = crange; - thr.push_back(pt); - } - } - - // IPv6 per-thread partition - if (snb6.defined()) - { - IP::RangePartition rp(snb6.clients, n_threads); - IP::Range crange; - for (unsigned int i = 0; i < n_threads; ++i) - { - if (!rp.next(crange)) - throw vpn_serv_netblock(opt_name + " : unexpected ServerNetblock6 partition fail"); - thr[i].range6_ = crange; - } - } - } - } - - const ClientNetblock& netblock4() const { return snb4; } - const ClientNetblock& netblock6() const { return snb6; } - - bool netblock_contains(const IP::Addr& a) const - { - return snb4.contains(a) || snb6.contains(a); - } - - const size_t size() const { return thr.size(); } - - const PerThread& per_thread(const size_t index) const - { - return thr[index]; - } - - std::string to_string() const - { - std::ostringstream os; - os << "IPv4: " << snb4.to_string() << std::endl; - if (snb6.defined()) - os << "IPv6: " << snb6.to_string() << std::endl; - for (size_t i = 0; i < thr.size(); ++i) - { - const PerThread& pt = thr[i]; - os << '[' << i << ']'; - os << " v4=" << pt.range4().to_string(); - if (pt.range6_defined()) - os << " v6=" << pt.range6().to_string(); - os << std::endl; - } - return os.str(); - } - - private: - ClientNetblock snb4; - ClientNetblock snb6; - std::vector<PerThread> thr; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/server/vpnservpool.hpp b/Sources/OpenVPN3/openvpn/server/vpnservpool.hpp deleted file mode 100644 index bd3d8bc..0000000 --- a/Sources/OpenVPN3/openvpn/server/vpnservpool.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// 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-2020 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_SERVER_VPNSERVPOOL_H -#define OPENVPN_SERVER_VPNSERVPOOL_H - -#include <sstream> -#include <vector> -#include <memory> -#include <mutex> -#include <thread> -#include <cstdint> // for std::uint32_t - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/server/vpnservnetblock.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/addr/pool.hpp> - -namespace openvpn { - namespace VPNServerPool { - - OPENVPN_EXCEPTION(vpn_serv_pool_error); - - struct IP46 - { - void add_routes(std::vector<IP::Route>& rtvec) - { - if (ip4.defined()) - rtvec.emplace_back(ip4, ip4.size()); - if (ip6.defined()) - rtvec.emplace_back(ip6, ip6.size()); - } - - std::string to_string() const - { - std::ostringstream os; - os << '[' << ip4 << ' ' << ip6 << ']'; - return os.str(); - } - - bool defined() const - { - return ip4.defined() || ip6.defined(); - } - - IP::Addr ip4; - IP::Addr ip6; - }; - - class Pool : public VPNServerNetblock - { - public: - enum Flags { - IPv4_DEPLETION=(1<<0), - IPv6_DEPLETION=(1<<1), - }; - - Pool(const OptionList& opt) - : VPNServerNetblock(init_snb_from_opt(opt)) - { - if (configured(opt, "server")) - { - pool4.add_range(netblock4().clients); - pool6.add_range(netblock6().clients); - } - } - - // returns flags - unsigned int acquire(IP46& addr_pair, const bool request_ipv6) - { - std::lock_guard<std::mutex> lock(mutex); - unsigned int flags = 0; - if (!pool4.acquire_addr(addr_pair.ip4)) - flags |= IPv4_DEPLETION; - if (request_ipv6 && netblock6().defined()) - { - if (!pool6.acquire_addr(addr_pair.ip6)) - flags |= IPv6_DEPLETION; - } - return flags; - } - - void release(IP46& addr_pair) - { - std::lock_guard<std::mutex> lock(mutex); - if (addr_pair.ip4.defined()) - pool4.release_addr(addr_pair.ip4); - if (addr_pair.ip6.defined()) - pool6.release_addr(addr_pair.ip6); - } - - private: - static VPNServerNetblock init_snb_from_opt(const OptionList& opt) - { - if (configured(opt, "server")) - return VPNServerNetblock(opt, "server", false, 0); - else if (configured(opt, "ifconfig")) - return VPNServerNetblock(opt, "ifconfig", false, 0); - else - throw vpn_serv_pool_error("one of 'server' or 'ifconfig' directives is required"); - } - - static bool configured(const OptionList& opt, - const std::string& opt_name) - { - return opt.exists(opt_name) || opt.exists(opt_name + "-ipv6"); - } - - std::mutex mutex; - - IP::Pool pool4; - IP::Pool pool6; - }; - - class IP46AutoRelease : public IP46, public RC<thread_safe_refcount> - { - public: - typedef RCPtr<IP46AutoRelease> Ptr; - - IP46AutoRelease(Pool* pool_arg) - : pool(pool_arg) - { - } - - ~IP46AutoRelease() - { - if (pool) - pool->release(*this); - } - - private: - Pool* pool; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/datalimit.hpp b/Sources/OpenVPN3/openvpn/ssl/datalimit.hpp deleted file mode 100644 index de0ffd6..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/datalimit.hpp +++ /dev/null @@ -1,206 +0,0 @@ -// 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-2020 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_SSL_DATALIMIT_H -#define OPENVPN_SSL_DATALIMIT_H - -#include <openvpn/common/exception.hpp> - -namespace openvpn { - // Helper for handling keys which can have an upper limit - // on maximum amount of data encrypted/decrypted, such - // as Blowfish. - class DataLimit - { - public: - typedef unsigned int size_type; - - enum Mode { - Encrypt=0, - Decrypt=1, - }; - - enum State { - None=0, - Green=1, - Red=2, - }; - - struct Parameters - { - size_type encrypt_red_limit = 0; - size_type decrypt_red_limit = 0; - }; - - DataLimit(const Parameters& p) - : encrypt(p.encrypt_red_limit), - decrypt(p.decrypt_red_limit) - { - } - - State update_state(const Mode mode, const State newstate) - { - return elgible(mode, component(mode).update_state(newstate)); - } - - State add(const Mode mode, const size_type n) - { - return elgible(mode, component(mode).add(n)); - } - - bool is_decrypt_green() - { - return decrypt.get_state() >= Green; - } - - static const char *mode_str(const Mode m) - { - switch (m) - { - case Encrypt: - return "Encrypt"; - case Decrypt: - return "Decrypt"; - default: - return "Mode_???"; - } - } - - static const char *state_str(const State s) - { - switch (s) - { - case None: - return "None"; - case Green: - return "Green"; - case Red: - return "Red"; - default: - return "State_???"; - } - } - - private: - // Don't return Encrypt-Red until Decrypt-Green - // has been received. This confirms that the peer - // is now transmitting on the key ID, making it - // eligible for renegotiation. - State elgible(const Mode mode, const State state) - { - // Bit positions for Encrypt/Decrypt and Green/Red - enum { - EG = 1<<0, - ER = 1<<1, - DG = 1<<2, - DR = 1<<3, - }; - if (state > None) - { - const unsigned int mask = 1 << ((int(state) - 1) + (int(mode) << 1)); - if (!(flags & mask)) - { - flags |= mask; - if ((mask & (ER|DG)) && ((flags & (ER|DG)) == (ER|DG))) - return Red; - else if (mask & ER) - return None; - else - return state; - } - } - return None; - } - - class Component - { - public: - Component(const size_type red_limit_arg) - : red_limit(red_limit_arg) - { - } - - State add(const size_type n) - { - bytes += n; - return update_state(transition(state)); - } - - State update_state(const State newstate) - { - State ret = None; - if (newstate > state) - state = ret = newstate; - return ret; - } - - State get_state() const - { - return state; - } - - private: - State transition(State s) const - { - switch (s) - { - case None: - if (bytes) - return Green; - else - return None; - case Green: - if (red_limit && bytes >= red_limit) - return Red; - else - return None; - case Red: - default: - return None; - } - } - - const size_type red_limit; - size_type bytes = 0; - State state = None; - }; - - Component& component(const Mode m) - { - switch (m) - { - case Encrypt: - return encrypt; - case Decrypt: - return decrypt; - default: - throw Exception("DataLimit::Component: unknown mode"); - } - } - - Component encrypt; - Component decrypt; - unsigned int flags = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/iana_ciphers.hpp b/Sources/OpenVPN3/openvpn/ssl/iana_ciphers.hpp deleted file mode 100644 index bc4f7f4..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/iana_ciphers.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// 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) 2020 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 - -namespace openvpn { - - struct tls_cipher_name_pair - { - const char* openssl_name; - const char* iana_name; - }; - - /** - * SSL/TLS Cipher suite name translation table - */ - static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { - {"ADH-SEED-SHA", "TLS-DH-anon-WITH-SEED-CBC-SHA"}, - {"AES128-GCM-SHA256", "TLS-RSA-WITH-AES-128-GCM-SHA256"}, - {"AES128-SHA256", "TLS-RSA-WITH-AES-128-CBC-SHA256"}, - {"AES128-SHA", "TLS-RSA-WITH-AES-128-CBC-SHA"}, - {"AES256-GCM-SHA384", "TLS-RSA-WITH-AES-256-GCM-SHA384"}, - {"AES256-SHA256", "TLS-RSA-WITH-AES-256-CBC-SHA256"}, - {"AES256-SHA", "TLS-RSA-WITH-AES-256-CBC-SHA"}, - {"CAMELLIA128-SHA256", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"CAMELLIA128-SHA", "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"CAMELLIA256-SHA256", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"CAMELLIA256-SHA", "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"DES-CBC3-SHA", "TLS-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"DES-CBC-SHA", "TLS-RSA-WITH-DES-CBC-SHA"}, - {"DH-DSS-SEED-SHA", "TLS-DH-DSS-WITH-SEED-CBC-SHA"}, - {"DHE-DSS-AES128-GCM-SHA256", "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256"}, - {"DHE-DSS-AES128-SHA256", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256"}, - {"DHE-DSS-AES128-SHA", "TLS-DHE-DSS-WITH-AES-128-CBC-SHA"}, - {"DHE-DSS-AES256-GCM-SHA384", "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384"}, - {"DHE-DSS-AES256-SHA256", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256"}, - {"DHE-DSS-AES256-SHA", "TLS-DHE-DSS-WITH-AES-256-CBC-SHA"}, - {"DHE-DSS-CAMELLIA128-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256"}, - {"DHE-DSS-CAMELLIA128-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA"}, - {"DHE-DSS-CAMELLIA256-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256"}, - {"DHE-DSS-CAMELLIA256-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-DSS-SEED-SHA", "TLS-DHE-DSS-WITH-SEED-CBC-SHA"}, - {"DHE-RSA-AES128-GCM-SHA256", "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"}, - {"DHE-RSA-AES128-SHA256", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"}, - {"DHE-RSA-AES128-SHA", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA"}, - {"DHE-RSA-AES256-GCM-SHA384", "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384"}, - {"DHE-RSA-AES256-SHA256", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256"}, - {"DHE-RSA-AES256-SHA", "TLS-DHE-RSA-WITH-AES-256-CBC-SHA"}, - {"DHE-RSA-CAMELLIA128-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"DHE-RSA-CAMELLIA128-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"DHE-RSA-CAMELLIA256-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"DHE-RSA-CAMELLIA256-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-RSA-CHACHA20-POLY1305", "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"DHE-RSA-SEED-SHA", "TLS-DHE-RSA-WITH-SEED-CBC-SHA"}, - {"DH-RSA-SEED-SHA", "TLS-DH-RSA-WITH-SEED-CBC-SHA"}, - {"ECDH-ECDSA-AES128-GCM-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256"}, - {"ECDH-ECDSA-AES128-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256"}, - {"ECDH-ECDSA-AES128-SHA", "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA"}, - {"ECDH-ECDSA-AES256-GCM-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384"}, - {"ECDH-ECDSA-AES256-SHA256", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA256"}, - {"ECDH-ECDSA-AES256-SHA384", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384"}, - {"ECDH-ECDSA-AES256-SHA", "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA"}, - {"ECDH-ECDSA-CAMELLIA128-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDH-ECDSA-CAMELLIA128-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDH-ECDSA-CAMELLIA256-SHA256", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDH-ECDSA-CAMELLIA256-SHA", "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDH-ECDSA-DES-CBC3-SHA", "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDH-ECDSA-DES-CBC-SHA", "TLS-ECDH-ECDSA-WITH-DES-CBC-SHA"}, - {"ECDH-ECDSA-RC4-SHA", "TLS-ECDH-ECDSA-WITH-RC4-128-SHA"}, - {"ECDHE-ECDSA-AES128-GCM-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"}, - {"ECDHE-ECDSA-AES128-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256"}, - {"ECDHE-ECDSA-AES128-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA384"}, - {"ECDHE-ECDSA-AES128-SHA", "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA"}, - {"ECDHE-ECDSA-AES256-GCM-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384"}, - {"ECDHE-ECDSA-AES256-SHA256", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA256"}, - {"ECDHE-ECDSA-AES256-SHA384", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384"}, - {"ECDHE-ECDSA-AES256-SHA", "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA"}, - {"ECDHE-ECDSA-CAMELLIA128-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDHE-ECDSA-CAMELLIA128-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDHE-ECDSA-CAMELLIA256-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDHE-ECDSA-CAMELLIA256-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDHE-ECDSA-CHACHA20-POLY1305", "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"ECDHE-ECDSA-DES-CBC3-SHA", "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDHE-ECDSA-DES-CBC-SHA", "TLS-ECDHE-ECDSA-WITH-DES-CBC-SHA"}, - {"ECDHE-ECDSA-RC4-SHA", "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA"}, - {"ECDHE-RSA-AES128-GCM-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256"}, - {"ECDHE-RSA-AES128-SHA256", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256"}, - {"ECDHE-RSA-AES128-SHA384", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA384"}, - {"ECDHE-RSA-AES128-SHA", "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA"}, - {"ECDHE-RSA-AES256-GCM-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"}, - {"ECDHE-RSA-AES256-SHA256", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA256"}, - {"ECDHE-RSA-AES256-SHA384", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384"}, - {"ECDHE-RSA-AES256-SHA", "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA"}, - {"ECDHE-RSA-CAMELLIA128-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDHE-RSA-CAMELLIA128-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDHE-RSA-CAMELLIA256-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDHE-RSA-CAMELLIA256-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDHE-RSA-CHACHA20-POLY1305", "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, - {"ECDHE-RSA-DES-CBC3-SHA", "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDHE-RSA-DES-CBC-SHA", "TLS-ECDHE-RSA-WITH-DES-CBC-SHA"}, - {"ECDHE-RSA-RC4-SHA", "TLS-ECDHE-RSA-WITH-RC4-128-SHA"}, - {"ECDH-RSA-AES128-GCM-SHA256", "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256"}, - {"ECDH-RSA-AES128-SHA256", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256"}, - {"ECDH-RSA-AES128-SHA384", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA384"}, - {"ECDH-RSA-AES128-SHA", "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA"}, - {"ECDH-RSA-AES256-GCM-SHA384", "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384"}, - {"ECDH-RSA-AES256-SHA256", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA256"}, - {"ECDH-RSA-AES256-SHA384", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384"}, - {"ECDH-RSA-AES256-SHA", "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA"}, - {"ECDH-RSA-CAMELLIA128-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256"}, - {"ECDH-RSA-CAMELLIA128-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA"}, - {"ECDH-RSA-CAMELLIA256-SHA256", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, - {"ECDH-RSA-CAMELLIA256-SHA", "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"ECDH-RSA-DES-CBC3-SHA", "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"ECDH-RSA-DES-CBC-SHA", "TLS-ECDH-RSA-WITH-DES-CBC-SHA"}, - {"ECDH-RSA-RC4-SHA", "TLS-ECDH-RSA-WITH-RC4-128-SHA"}, - {"EDH-DSS-DES-CBC3-SHA", "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA"}, - {"EDH-DSS-DES-CBC-SHA", "TLS-DHE-DSS-WITH-DES-CBC-SHA"}, - {"EDH-RSA-DES-CBC3-SHA", "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"EDH-RSA-DES-CBC-SHA", "TLS-DHE-RSA-WITH-DES-CBC-SHA"}, - {"EXP-DES-CBC-SHA", "TLS-RSA-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-EDH-DSS-DES-CBC-SHA", "TLS-DH-DSS-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-EDH-RSA-DES-CBC-SHA", "TLS-DH-RSA-EXPORT-WITH-DES40-CBC-SHA"}, - {"EXP-RC2-CBC-MD5", "TLS-RSA-EXPORT-WITH-RC2-CBC-40-MD5"}, - {"EXP-RC4-MD5", "TLS-RSA-EXPORT-WITH-RC4-40-MD5"}, - {"NULL-MD5", "TLS-RSA-WITH-NULL-MD5"}, - {"NULL-SHA256", "TLS-RSA-WITH-NULL-SHA256"}, - {"NULL-SHA", "TLS-RSA-WITH-NULL-SHA"}, - {"PSK-3DES-EDE-CBC-SHA", "TLS-PSK-WITH-3DES-EDE-CBC-SHA"}, - {"PSK-AES128-CBC-SHA", "TLS-PSK-WITH-AES-128-CBC-SHA"}, - {"PSK-AES256-CBC-SHA", "TLS-PSK-WITH-AES-256-CBC-SHA"}, - {"PSK-RC4-SHA", "TLS-PSK-WITH-RC4-128-SHA"}, - {"RC4-MD5", "TLS-RSA-WITH-RC4-128-MD5"}, - {"RC4-SHA", "TLS-RSA-WITH-RC4-128-SHA"}, - {"SEED-SHA", "TLS-RSA-WITH-SEED-CBC-SHA"}, - {"SRP-DSS-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-3DES-EDE-CBC-SHA"}, - {"SRP-DSS-AES-128-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-128-CBC-SHA"}, - {"SRP-DSS-AES-256-CBC-SHA", "TLS-SRP-SHA-DSS-WITH-AES-256-CBC-SHA"}, - {"SRP-RSA-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"SRP-RSA-AES-128-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA"}, - {"SRP-RSA-AES-256-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"} - }; - - inline const tls_cipher_name_pair* - tls_get_cipher_name_pair(const std::string& ciphername) - { - for (auto& pair: tls_cipher_name_translation_table) - { - if (pair.iana_name == ciphername || pair.openssl_name == ciphername) - return &pair; - } - - /* No entry found, return NULL */ - return NULL; - } -} \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/ssl/is_openvpn_protocol.hpp b/Sources/OpenVPN3/openvpn/ssl/is_openvpn_protocol.hpp deleted file mode 100644 index 8213e22..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/is_openvpn_protocol.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// 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-2020 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_SSL_IS_OPENVPN_PROTOCOL_H -#define OPENVPN_SSL_IS_OPENVPN_PROTOCOL_H - -#include <algorithm> // for std::min - -#include <openvpn/common/size.hpp> // for size_t - -namespace openvpn { - - // Peek at the first few bytes of a session and - // distinguishing between OpenVPN or SSL protocols. - inline bool is_openvpn_protocol(const unsigned char *p, const size_t len) - { - const int CONTROL_HARD_RESET_CLIENT_V2 = 7; - const int CONTROL_HARD_RESET_CLIENT_V3 = 10; - const int OPCODE_SHIFT = 3; - const int MIN_INITIAL_PKT_SIZE = 14; - - switch (std::min(len, size_t(3))) - { - case 3: - return p[0] == 0 - && p[1] >= MIN_INITIAL_PKT_SIZE - && (p[2] == (CONTROL_HARD_RESET_CLIENT_V2 << OPCODE_SHIFT) - || p[2] == (CONTROL_HARD_RESET_CLIENT_V3 << OPCODE_SHIFT)); - case 2: - return p[0] == 0 && p[1] >= MIN_INITIAL_PKT_SIZE; - case 1: - return p[0] == 0; - default: - return true; - } - } - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/kuparse.hpp b/Sources/OpenVPN3/openvpn/ssl/kuparse.hpp deleted file mode 100644 index 3f634c0..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/kuparse.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// 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-2020 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/>. - -// Parse the remote-cert-tls, remote-cert-ku, and remote-cert-eku options. - -#ifndef OPENVPN_SSL_KUPARSE_H -#define OPENVPN_SSL_KUPARSE_H - -#include <vector> -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - namespace KUParse { - enum TLSWebType { - TLS_WEB_NONE, - TLS_WEB_SERVER, - TLS_WEB_CLIENT, - }; - - inline void remote_cert_tls(const TLSWebType wt, std::vector<unsigned int>& ku, std::string& eku) - { - ku.clear(); - eku = ""; - - switch (wt) - { - case TLS_WEB_NONE: - break; - case TLS_WEB_SERVER: - ku.clear(); - ku.push_back(0xa0); - ku.push_back(0x88); - eku = "TLS Web Server Authentication"; - break; - case TLS_WEB_CLIENT: - ku.clear(); - ku.push_back(0x80); - ku.push_back(0x08); - ku.push_back(0x88); - eku = "TLS Web Client Authentication"; - break; - } - } - - inline TLSWebType remote_cert_type(const std::string& ct) - { - if (ct == "server") - return TLS_WEB_SERVER; - else if (ct == "client") - return TLS_WEB_CLIENT; - else - throw option_error("remote-cert-tls must be 'client' or 'server'"); - } - - inline void remote_cert_tls(const std::string& ct, - std::vector<unsigned int>& ku, - std::string& eku) - { - remote_cert_tls(remote_cert_type(ct), ku, eku); - } - - inline void remote_cert_tls(const OptionList& opt, - const std::string& relay_prefix, - std::vector<unsigned int>& ku, - std::string& eku) - { - TLSWebType wt = TLS_WEB_NONE; - const Option* o = opt.get_ptr(relay_prefix + "remote-cert-tls"); - if (o) - { - const std::string ct = o->get_optional(1, 16); - wt = remote_cert_type(ct); - } - remote_cert_tls(wt, ku, eku); - } - - inline void remote_cert_ku(const OptionList& opt, - const std::string& relay_prefix, - std::vector<unsigned int>& ku) - { - ku.clear(); - - const Option* o = opt.get_ptr(relay_prefix + "remote-cert-ku"); - if (o) - { - if (o->empty()) - throw option_error("remote-cert-ku: no hex values specified"); - else if (o->size() >= 64) - throw option_error("remote-cert-ku: too many parameters"); - else - { - try { - for (size_t i = 1; i < o->size(); ++i) - ku.push_back(parse_hex_number<unsigned int>(o->get(i, 16))); - } - catch (parse_hex_error&) - { - throw option_error("remote-cert-ku: error parsing hex value list"); - } - } - } - } - - inline void remote_cert_eku(const OptionList& opt, - const std::string& relay_prefix, - std::string& eku) - { - eku = ""; - - const Option* o = opt.get_ptr(relay_prefix + "remote-cert-eku"); - if (o) - eku = o->get(1, 256); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/mssparms.hpp b/Sources/OpenVPN3/openvpn/ssl/mssparms.hpp deleted file mode 100644 index 7289fb0..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/mssparms.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// 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-2020 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_SSL_MSSPARMS_H -#define OPENVPN_SSL_MSSPARMS_H - -#include <openvpn/common/options.hpp> -#include <openvpn/common/number.hpp> - -namespace openvpn { - struct MSSParms - { - MSSParms() : mssfix(0), - mtu(false) - { - } - - void parse(const OptionList& opt, bool nothrow=false) - { - const Option *o = opt.get_ptr("mssfix"); - if (o) - { - const std::string* val = o->get_ptr(1, 16); - if (val == nullptr) - { - if (nothrow) - { - OPENVPN_LOG("Missing mssfix value, mssfix functionality disabled"); - return; - } - else - throw option_error("mssfix must have a value"); - } - - const bool status = parse_number_validate<decltype(mssfix)>(*val, - 16, - 576, - 65535, - &mssfix); - if (!status) - { - if (nothrow) - { - // no need to warn if mssfix is actually 0 - if (*val != "0") - { - OPENVPN_LOG("Invalid mssfix value " << *val << ", mssfix functionality disabled"); - } - } - else - throw option_error("mssfix: parse/range issue"); - } - mtu = (o->get_optional(2, 16) == "mtu"); - } - } - - unsigned int mssfix; // standard OpenVPN mssfix parm - bool mtu; // consider transport packet overhead in MSS adjustment - }; - - struct MSSCtrlParms - { - MSSCtrlParms(const OptionList& opt) - { - mssfix_ctrl = opt.get_num<decltype(mssfix_ctrl)>("mssfix-ctrl", 1, 1250, - 256, 65535); - } - - unsigned int mssfix_ctrl; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/nscert.hpp b/Sources/OpenVPN3/openvpn/ssl/nscert.hpp deleted file mode 100644 index fc6d643..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/nscert.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// 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-2020 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/>. - -// Parse the ns-cert-type option. - -#ifndef OPENVPN_SSL_NSCERT_H -#define OPENVPN_SSL_NSCERT_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - namespace NSCert { - enum Type { - NONE, - CLIENT, - SERVER - }; - - inline Type ns_cert_type(const std::string& ct) - { - if (ct == "server") - return SERVER; - else if (ct == "client") - return CLIENT; - else - throw option_error("ns-cert-type must be 'client' or 'server'"); - } - - inline Type ns_cert_type(const OptionList& opt, const std::string& relay_prefix) - { - const Option* o = opt.get_ptr(relay_prefix + "ns-cert-type"); - if (o) - { - const std::string ct = o->get_optional(1, 16); - return ns_cert_type(ct); - } - return NONE; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/peerinfo.hpp b/Sources/OpenVPN3/openvpn/ssl/peerinfo.hpp deleted file mode 100644 index 1223585..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/peerinfo.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// 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-2020 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/>. - -// These objects are primary concerned with generating the Peer Info on the -// client side before transmission to server. For the reverse case (parsing -// the Peer Info on the server) we normally use an OptionList. - -#ifndef OPENVPN_SSL_PEERINFO_H -#define OPENVPN_SSL_PEERINFO_H - -#include <string> -#include <vector> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/jsonlib.hpp> - -#ifdef HAVE_JSON -#include <openvpn/common/jsonhelper.hpp> -#endif - -namespace openvpn { - namespace PeerInfo { - - OPENVPN_EXCEPTION(peer_info_error); - - struct KeyValue - { - KeyValue(const std::string& key_arg, const std::string& value_arg) - : key(key_arg), - value(value_arg) - { - } - - std::string key; - std::string value; - - std::string to_string() const - { - return key + '=' + value; - } - }; - - struct Set : public std::vector<KeyValue>, public RCCopyable<thread_unsafe_refcount> - { - typedef RCPtr<Set> Ptr; - - template <typename SET> - static Ptr new_from_foreign_set(const SET& other) - { - Ptr sp = new Set(); - for (const auto &kv : other) - sp->emplace_back(kv.key, kv.value); - return sp; - } - - template <typename SET> - void append_foreign_set_ptr(const SET* other) - { - if (other) - for (const auto &kv : *other) - emplace_back(kv.key, kv.value); - } - - template <typename SET> - void append_foreign_set_ref(const SET& other) - { - for (const auto &kv : other) - emplace_back(kv.key, kv.value); - } - - Ptr copy() const - { - return new Set(*this); - } - - // src may be comma-separated key=value pairs or @filename, where - // filename contains a JSON dictionary of key/value pairs. - template <typename SET> - static void parse_flexible(const std::string& src, SET& dest) - { - if (src.length() >= 1 && src[0] == '@') - { - const std::string fn = src.substr(1); -#ifdef OPENVPN_JSON_INTERNAL - const Json::Value root = json::parse_from_file(fn); - parse_json(root, dest, fn); -#else - OPENVPN_THROW(peer_info_error, fn << ": JSON library not available"); -#endif - } - else - parse_csv(src, dest); - } - - // Parse src in the form K1=V1,K2=V2,... - template <typename SET> - static void parse_csv(const std::string& src, SET& dest) - { - if (!string::is_empty(src)) - { - if (string::is_multiline(src)) - OPENVPN_THROW(peer_info_error, "key/value list must be a single line: " << Unicode::utf8_printable(src, 256)); - const auto list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(src, ',', Split::TRIM_LEADING_SPACES|Split::TRIM_SPECIAL); - for (const auto &kvstr : list) - { - const auto kv = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(kvstr, '=', 0, 1); - if (kv.size() == 2) - dest.emplace_back(kv[0], kv[1]); - else - OPENVPN_THROW(peer_info_error, "key/value must be in the form K=V, not: " << Unicode::utf8_printable(kvstr, 256)); - } - } - } - -#ifdef OPENVPN_JSON_INTERNAL - template <typename SET> - static void parse_json(const Json::Value& src, SET& dest, const std::string& title) - { - if (!src.isObject()) - OPENVPN_THROW(peer_info_error, title << ": top level JSON object must be a dictionary"); - auto m = src.map(); - for (auto &e : m) - { - if (e.second.isString()) - dest.emplace_back(e.first, e.second.asStringRef()); - else - dest.emplace_back(e.first, e.second.toCompactString()); - } - } -#endif - - std::string to_string() const - { - std::string ret; - ret.reserve(256); - for (const auto &kv : *this) - { - ret += kv.to_string(); - ret += '\n'; - } - return ret; - } - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/proto.hpp b/Sources/OpenVPN3/openvpn/ssl/proto.hpp deleted file mode 100644 index 46a7dfe..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/proto.hpp +++ /dev/null @@ -1,3947 +0,0 @@ -// 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-2020 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/>. - -// ProtoContext, the fundamental OpenVPN protocol implementation. -// It can be used by OpenVPN clients, servers, or unit tests. - -#ifndef OPENVPN_SSL_PROTO_H -#define OPENVPN_SSL_PROTO_H - -#include <cstring> -#include <string> -#include <sstream> -#include <algorithm> // for std::min -#include <cstdint> // for std::uint32_t, etc. -#include <memory> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/version.hpp> -#include <openvpn/common/platform_name.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/mode.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/safestr.hpp> -#include <openvpn/buffer/bufcomposed.hpp> -#include <openvpn/ip/ip4.hpp> -#include <openvpn/ip/ip6.hpp> -#include <openvpn/ip/udp.hpp> -#include <openvpn/ip/tcp.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/time/durhelper.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/crypto/cipher.hpp> -#include <openvpn/crypto/ovpnhmac.hpp> -#include <openvpn/crypto/tls_crypt.hpp> -#include <openvpn/crypto/tls_crypt_v2.hpp> -#include <openvpn/crypto/packet_id.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/bs64_data_limit.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/ssl/protostack.hpp> -#include <openvpn/ssl/psid.hpp> -#include <openvpn/ssl/tlsprf.hpp> -#include <openvpn/ssl/datalimit.hpp> -#include <openvpn/ssl/mssparms.hpp> -#include <openvpn/transport/mssfix.hpp> -#include <openvpn/transport/protocol.hpp> -#include <openvpn/tun/layer.hpp> -#include <openvpn/tun/tunmtu.hpp> -#include <openvpn/compress/compress.hpp> -#include <openvpn/ssl/proto_context_options.hpp> -#include <openvpn/ssl/peerinfo.hpp> -#include <openvpn/ssl/ssllog.hpp> -#include <openvpn/crypto/crypto_aead.hpp> - - -#if OPENVPN_DEBUG_PROTO >= 1 -#define OPENVPN_LOG_PROTO(x) OPENVPN_LOG(x) -#define OPENVPN_LOG_STRING_PROTO(x) OPENVPN_LOG_STRING(x) -#else -#define OPENVPN_LOG_PROTO(x) -#define OPENVPN_LOG_STRING_PROTO(x) -#endif - -#if OPENVPN_DEBUG_PROTO >= 2 -#define OPENVPN_LOG_PROTO_VERBOSE(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_PROTO_VERBOSE(x) -#endif - -/* - -ProtoContext -- OpenVPN protocol implementation - -Protocol negotiation states: - -Client: - -1. send client reset to server -2. wait for server reset from server AND ack from 1 (C_WAIT_RESET, C_WAIT_RESET_ACK) -3. start SSL handshake -4. send auth message to server -5. wait for server auth message AND ack from 4 (C_WAIT_AUTH, C_WAIT_AUTH_ACK) -6. go active (ACTIVE) - -Server: - -1. wait for client reset (S_WAIT_RESET) -2. send server reset to client -3. wait for ACK from 2 (S_WAIT_RESET_ACK) -4. start SSL handshake -5. wait for auth message from client (S_WAIT_AUTH) -6. send auth message to client -7. wait for ACK from 6 (S_WAIT_AUTH_ACK) -8. go active (ACTIVE) - -*/ - -namespace openvpn { - - // utility namespace for ProtoContext - namespace proto_context_private { - namespace { - const unsigned char auth_prefix[] = { 0, 0, 0, 0, 2 }; // CONST GLOBAL - - const unsigned char keepalive_message[] = { // CONST GLOBAL - 0x2a, 0x18, 0x7b, 0xf3, 0x64, 0x1e, 0xb4, 0xcb, - 0x07, 0xed, 0x2d, 0x0a, 0x98, 0x1f, 0xc7, 0x48 - }; - - enum { - KEEPALIVE_FIRST_BYTE = 0x2a // first byte of keepalive message - }; - - inline bool is_keepalive(const Buffer& buf) - { - return buf.size() >= sizeof(keepalive_message) - && buf[0] == KEEPALIVE_FIRST_BYTE - && !std::memcmp(keepalive_message, buf.c_data(), sizeof(keepalive_message)); - } - - const unsigned char explicit_exit_notify_message[] = { // CONST GLOBAL - 0x28, 0x7f, 0x34, 0x6b, 0xd4, 0xef, 0x7a, 0x81, - 0x2d, 0x56, 0xb8, 0xd3, 0xaf, 0xc5, 0x45, 0x9c, - 6 // OCC_EXIT - }; - - enum { - EXPLICIT_EXIT_NOTIFY_FIRST_BYTE = 0x28 // first byte of exit message - }; - } - } - - class ProtoContext - { - protected: - static constexpr size_t APP_MSG_MAX = 65536; - - enum { - // packet opcode (high 5 bits) and key-id (low 3 bits) are combined in one byte - KEY_ID_MASK = 0x07, - OPCODE_SHIFT = 3, - - // packet opcodes -- the V1 is intended to allow protocol changes in the future - //CONTROL_HARD_RESET_CLIENT_V1 = 1, // (obsolete) initial key from client, forget previous state - //CONTROL_HARD_RESET_SERVER_V1 = 2, // (obsolete) initial key from server, forget previous state - CONTROL_SOFT_RESET_V1 = 3, // new key, graceful transition from old to new key - CONTROL_V1 = 4, // control channel packet (usually TLS ciphertext) - ACK_V1 = 5, // acknowledgement for packets received - DATA_V1 = 6, // data channel packet with 1-byte header - DATA_V2 = 9, // data channel packet with 4-byte header - - // indicates key_method >= 2 - CONTROL_HARD_RESET_CLIENT_V2 = 7, // initial key from client, forget previous state - CONTROL_HARD_RESET_CLIENT_V3 = 10, // initial key from client, forget previous state - CONTROL_HARD_RESET_SERVER_V2 = 8, // initial key from server, forget previous state - - // define the range of legal opcodes - FIRST_OPCODE = 3, - LAST_OPCODE = 9, - INVALID_OPCODE = 0, - - // DATA_V2 constants - OP_SIZE_V2 = 4, // size of initial packet opcode - OP_PEER_ID_UNDEF = 0x00FFFFFF, // indicates that Peer ID is undefined - - // states - // C_x : client states - // S_x : server states - - // ACK states -- must be first before other states - STATE_UNDEF=-1, - C_WAIT_RESET_ACK=0, - C_WAIT_AUTH_ACK=1, - S_WAIT_RESET_ACK=2, - S_WAIT_AUTH_ACK=3, - LAST_ACK_STATE=3, // all ACK states must be <= this value - - // key negotiation states (client) - C_INITIAL=4, - C_WAIT_RESET=5, // must be C_INITIAL+1 - C_WAIT_AUTH=6, - - // key negotiation states (server) - S_INITIAL=7, - S_WAIT_RESET=8, // must be S_INITIAL+1 - S_WAIT_AUTH=9, - - // key negotiation states (client and server) - ACTIVE=10, - }; - - enum iv_proto_flag: unsigned int - { - // See ssl.h in openvpn2 for detailed documentation of IV_PROTO - IV_PROTO_DATA_V2=(1<<1), - IV_PROTO_REQUEST_PUSH=(1<<2), - IV_PROTO_TLS_KEY_EXPORT=(1<<3), - IV_PROTO_AUTH_PENDING_KW=(1<<4) - }; - static unsigned int opcode_extract(const unsigned int op) - { - return op >> OPCODE_SHIFT; - } - - static unsigned int key_id_extract(const unsigned int op) - { - return op & KEY_ID_MASK; - } - - static size_t op_head_size(const unsigned int op) - { - return opcode_extract(op) == DATA_V2 ? OP_SIZE_V2 : 1; - } - - static unsigned int op_compose(const unsigned int opcode, const unsigned int key_id) - { - return (opcode << OPCODE_SHIFT) | key_id; - } - - static unsigned int op32_compose(const unsigned int opcode, - const unsigned int key_id, - const int op_peer_id) - { - return (op_compose(opcode, key_id) << 24) | (op_peer_id & 0x00FFFFFF); - } - - public: - OPENVPN_EXCEPTION(proto_error); - OPENVPN_EXCEPTION(process_server_push_error); - OPENVPN_EXCEPTION_INHERIT(option_error, proto_option_error); - - // configuration data passed to ProtoContext constructor - class Config : public RCCopyable<thread_unsafe_refcount> - { - public: - typedef RCPtr<Config> Ptr; - - // master SSL context factory - SSLFactoryAPI::Ptr ssl_factory; - - // data channel - CryptoDCSettings dc; - - // TLSPRF factory - TLSPRFFactory::Ptr tlsprf_factory; - - // master Frame object - Frame::Ptr frame; - - // (non-smart) pointer to current time - TimePtr now; - - // Random number generator. - // Use-cases demand highest cryptographic strength - // such as key generation. - RandomAPI::Ptr rng; - - // Pseudo-random number generator. - // Use-cases demand cryptographic strength - // combined with high performance. Used for - // IV and ProtoSessionID generation. - RandomAPI::Ptr prng; - - // If relay mode is enabled, connect to a special OpenVPN - // server that acts as a relay/proxy to a second server. - bool relay_mode = false; - - // defer data channel initialization until after client options pull - bool dc_deferred = false; - - // transmit username/password creds to server (client-only) - bool xmit_creds = true; - - // Transport protocol, i.e. UDPv4, etc. - Protocol protocol; // set with set_protocol() - - // OSI layer - Layer layer; - - // compressor - CompressContext comp_ctx; - - // tls_auth/crypt parms - OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt - bool tls_crypt_v2 = false; // needed to distinguish between tls-crypt and tls-crypt-v2 server mode - BufferAllocated wkc; // leave this undefined to disable tls-crypt-v2 on client - - OvpnHMACFactory::Ptr tls_auth_factory; - OvpnHMACContext::Ptr tls_auth_context; - int key_direction = -1; // 0, 1, or -1 for bidirectional - - TLSCryptFactory::Ptr tls_crypt_factory; - TLSCryptContext::Ptr tls_crypt_context; - - TLSCryptMetadataFactory::Ptr tls_crypt_metadata_factory; - - // reliability layer parms - reliable::id_t reliable_window = 0; - size_t max_ack_list = 0; - - // packet_id parms for both data and control channels - int pid_mode = 0; // PacketIDReceive::UDP_MODE or PacketIDReceive::TCP_MODE - - // timeout parameters, relative to construction of KeyContext object - Time::Duration handshake_window; // SSL/TLS negotiation must complete by this time - Time::Duration become_primary; // KeyContext (that is ACTIVE) becomes primary at this time - Time::Duration renegotiate; // start SSL/TLS renegotiation at this time - Time::Duration expire; // KeyContext expires at this time - Time::Duration tls_timeout; // Packet retransmit timeout on TLS control channel - - // keepalive parameters - Time::Duration keepalive_ping; - Time::Duration keepalive_timeout; - - // extra peer info key/value pairs generated by client app - PeerInfo::Set::Ptr extra_peer_info; - - // op header - bool enable_op32 = false; - int remote_peer_id = -1; // -1 to disable - int local_peer_id = -1; // -1 to disable - - // MTU - unsigned int tun_mtu = 1500; - MSSParms mss_parms; - unsigned int mss_inter = 0; - - // Debugging - int debug_level = 1; - - // For compatibility with openvpn2 we send initial options on rekeying, - // instead of possible modifications caused by NCP - std::string initial_options; - - void load(const OptionList& opt, const ProtoContextOptions& pco, - const int default_key_direction, const bool server) - { - // first set defaults - reliable_window = 4; - max_ack_list = 4; - handshake_window = Time::Duration::seconds(60); - renegotiate = Time::Duration::seconds(3600); - tls_timeout = Time::Duration::seconds(1); - keepalive_ping = Time::Duration::seconds(8); - keepalive_timeout = Time::Duration::seconds(40); - comp_ctx = CompressContext(CompressContext::NONE, false); - protocol = Protocol(); - pid_mode = PacketIDReceive::UDP_MODE; - key_direction = default_key_direction; - - // layer - { - const Option* dev = opt.get_ptr("dev-type"); - if (!dev) - dev = opt.get_ptr("dev"); - if (!dev) - throw proto_option_error("missing dev-type or dev option"); - const std::string& dev_type = dev->get(1, 64); - if (string::starts_with(dev_type, "tun")) - layer = Layer(Layer::OSI_LAYER_3); - else if (string::starts_with(dev_type, "tap")) - throw proto_option_error("TAP mode is not supported"); - else - throw proto_option_error("bad dev-type"); - } - - // cipher/digest/tls-auth/tls-crypt - { - CryptoAlgs::Type cipher = CryptoAlgs::NONE; - CryptoAlgs::Type digest = CryptoAlgs::NONE; - - // data channel cipher - { - const Option *o = opt.get_ptr("cipher"); - if (o) - { - const std::string& cipher_name = o->get(1, 128); - if (cipher_name != "none") - cipher = CryptoAlgs::lookup(cipher_name); - } - else - cipher = CryptoAlgs::lookup("BF-CBC"); - } - - // data channel HMAC - { - const Option *o = opt.get_ptr("auth"); - if (o) - { - const std::string& auth_name = o->get(1, 128); - if (auth_name != "none") - digest = CryptoAlgs::lookup(auth_name); - } - else - digest = CryptoAlgs::lookup("SHA1"); - } - dc.set_cipher(cipher); - dc.set_digest(digest); - - // tls-auth - { - const Option *o = opt.get_ptr(relay_prefix("tls-auth")); - if (o) - { - if (tls_crypt_context) - throw proto_option_error("tls-auth and tls-crypt are mutually exclusive"); - - tls_key.parse(o->get(1, 0)); - - const Option *tad = opt.get_ptr(relay_prefix("tls-auth-digest")); - if (tad) - digest = CryptoAlgs::lookup(tad->get(1, 128)); - if (digest != CryptoAlgs::NONE) - set_tls_auth_digest(digest); - } - } - - // tls-crypt - { - const Option *o = opt.get_ptr(relay_prefix("tls-crypt")); - if (o) - { - if (tls_auth_context) - throw proto_option_error("tls-auth and tls-crypt are mutually exclusive"); - if (tls_crypt_context) - throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive"); - - tls_key.parse(o->get(1, 0)); - - 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 algorithms"); - - 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 - { - if (key_direction >= -1 && key_direction <= 1) - { - const Option *o = opt.get_ptr(relay_prefix("key-direction")); - if (o) - { - const std::string& dir = o->get(1, 16); - if (dir == "0") - key_direction = 0; - else if (dir == "1") - key_direction = 1; - else if (dir == "bidirectional" || dir == "bi") - key_direction = -1; - else - throw proto_option_error("bad key-direction parameter"); - } - } - else - throw proto_option_error("bad key-direction default"); - } - - // compression - { - const Option *o = opt.get_ptr("compress"); - if (o) - { - if (o->size() >= 2) - { - const std::string meth_name = o->get(1, 128); - CompressContext::Type meth = CompressContext::parse_method(meth_name); - if (meth == CompressContext::NONE) - OPENVPN_THROW(proto_option_error, "Unknown compressor: '" << meth_name << '\''); - comp_ctx = CompressContext(pco.is_comp() ? meth : CompressContext::stub(meth), pco.is_comp_asym()); - } - else - comp_ctx = CompressContext(pco.is_comp() ? CompressContext::ANY : CompressContext::COMP_STUB, pco.is_comp_asym()); - } - else - { - o = opt.get_ptr("comp-lzo"); - if (o) - { - if (o->size() == 2 && o->ref(1) == "no") - { - // On the client, by using ANY instead of ANY_LZO, we are telling the server - // that it's okay to use any of our supported compression methods. - comp_ctx = CompressContext(pco.is_comp() ? CompressContext::ANY : CompressContext::LZO_STUB, pco.is_comp_asym()); - } - else - { - comp_ctx = CompressContext(pco.is_comp() ? CompressContext::LZO : CompressContext::LZO_STUB, pco.is_comp_asym()); - } - } - } - } - - // tun-mtu - tun_mtu = parse_tun_mtu(opt, tun_mtu); - - // mssfix - mss_parms.parse(opt, true); - - // 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 options string pushed by server - void process_push(const OptionList& opt, const ProtoContextOptions& pco) - { - // data channel - { - // cipher - std::string new_cipher; - try { - const Option *o = opt.get_ptr("cipher"); - if (o) - { - new_cipher = o->get(1, 128); - if (new_cipher != "none") - dc.set_cipher(CryptoAlgs::lookup(new_cipher)); - } - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed cipher '" << new_cipher << "': " << e.what()); - } - - // digest - std::string new_digest; - try { - const Option *o = opt.get_ptr("auth"); - if (o) - { - new_digest = o->get(1, 128); - if (new_digest != "none") - dc.set_digest(CryptoAlgs::lookup(new_digest)); - } - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed digest '" << new_digest << "': " << e.what()); - } - - - // tls key-derivation method - std::string key_method; - try { - const Option *o = opt.get_ptr("key-derivation"); - if (o) - { - key_method = o->get(1, 128); - if (key_method == "tls-ekm") - dc.set_key_derivation(CryptoAlgs::KeyDerivation::TLS_EKM); - else - OPENVPN_THROW(process_server_push_error, "Problem accepting key-derivation method '" << key_method << "'"); - } - else - dc.set_key_derivation(CryptoAlgs::KeyDerivation::OPENVPN_PRF); - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting key-derivation method '" << key_method << "': " << e.what()); - } - } - // compression - std::string new_comp; - try { - const Option *o; - o = opt.get_ptr("compress"); - if (o) - { - new_comp = o->get(1, 128); - CompressContext::Type meth = CompressContext::parse_method(new_comp); - if (meth != CompressContext::NONE) - { - // if compression is not availabe, CompressContext ctor throws an exception - if (pco.is_comp()) - comp_ctx = CompressContext(meth, pco.is_comp_asym()); - else - { - // server pushes compression but client has compression disabled - // degrade to asymmetric compression (downlink only) - comp_ctx = CompressContext(meth, true); - if (!comp_ctx.is_any_stub(meth)) - { - OPENVPN_LOG("Server has pushed compressor " - << comp_ctx.str() - << ", but client has disabled compression, switching to asymmetric"); - } - } - } - } - else - { - o = opt.get_ptr("comp-lzo"); - if (o) - { - if (o->size() == 2 && o->ref(1) == "no") - { - comp_ctx = CompressContext(CompressContext::LZO_STUB, false); - } - else - { - comp_ctx = CompressContext(pco.is_comp() ? CompressContext::LZO : CompressContext::LZO_STUB, pco.is_comp_asym()); - } - } - } - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed compressor '" << new_comp << "': " << e.what()); - } - - // peer ID - try { - const Option *o = opt.get_ptr("peer-id"); - if (o) - { - bool status = parse_number_validate<int>(o->get(1, 16), - 16, - -1, - 0xFFFFFE, - &remote_peer_id); - if (!status) - throw Exception("parse/range issue"); - enable_op32 = true; - } - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed peer-id: " << e.what()); - } - - try { - // load parameters that can be present in both config file or pushed options - load_common(opt, pco, LOAD_COMMON_CLIENT_PUSHED); - } - catch (const std::exception& e) - { - OPENVPN_THROW(process_server_push_error, "Problem accepting server-pushed parameter: " << e.what()); - } - - // show negotiated options - OPENVPN_LOG_STRING_PROTO(show_options()); - } - - std::string show_options() const - { - std::ostringstream os; - os << "PROTOCOL OPTIONS:" << std::endl; - os << " cipher: " << CryptoAlgs::name(dc.cipher()) << std::endl; - os << " digest: " << CryptoAlgs::name(dc.digest()) << std::endl; - os << " key-derivation: " << CryptoAlgs::name(dc.key_derivation()) << std::endl; - os << " compress: " << comp_ctx.str() << std::endl; - os << " peer ID: " << remote_peer_id << std::endl; - if (tls_auth_enabled()) - { - os << " control channel: tls-auth enabled" << std::endl; - } - else if (tls_crypt_v2_enabled()) - { - os << " control channel: tls-crypt v2 enabled" << std::endl; - } - else if (tls_crypt_enabled()) - { - os << " control channel: tls-crypt enabled" << std::endl; - } - return os.str(); - } - - void set_pid_mode(const bool tcp_linear) - { - if (protocol.is_udp() || !tcp_linear) - pid_mode = PacketIDReceive::UDP_MODE; - else if (protocol.is_tcp()) - pid_mode = PacketIDReceive::TCP_MODE; - else - throw proto_option_error("transport protocol undefined"); - } - - void set_protocol(const Protocol& p) - { - // adjust options for new transport protocol - protocol = p; - set_pid_mode(false); - } - - void set_tls_auth_digest(const CryptoAlgs::Type digest) - { - tls_auth_context = tls_auth_factory->new_obj(digest); - } - - void set_tls_crypt_algs(const CryptoAlgs::Type digest, - const CryptoAlgs::Type cipher) - { - tls_crypt_context = tls_crypt_factory->new_obj(digest, cipher); - } - - void set_xmit_creds(const bool xmit_creds_arg) - { - xmit_creds = xmit_creds_arg; - } - - bool tls_auth_enabled() const - { - return tls_key.defined() && tls_auth_context; - } - - bool tls_crypt_enabled() const - { - return tls_key.defined() && tls_crypt_context; - } - - bool tls_crypt_v2_enabled() const - { - return tls_crypt_enabled() && tls_crypt_v2; - } - - // generate a string summarizing options that will be - // transmitted to peer for options consistency check - std::string options_string() - { - if (!initial_options.empty()) - return initial_options; - - std::ostringstream out; - - const bool server = ssl_factory->mode().is_server(); - const unsigned int l2extra = (layer() == Layer::OSI_LAYER_2 ? 32 : 0); - - out << "V4"; - - out << ",dev-type " << layer.dev_type(); - out << ",link-mtu " << tun_mtu + link_mtu_adjust() + l2extra; - out << ",tun-mtu " << tun_mtu + l2extra; - out << ",proto " << protocol.str_client(true); - - { - const char *compstr = comp_ctx.options_string(); - if (compstr) - out << ',' << compstr; - } - - if (tls_auth_context && (key_direction >= 0)) - out << ",keydir " << key_direction; - - out << ",cipher " << CryptoAlgs::name(dc.cipher(), "[null-cipher]"); - out << ",auth " << CryptoAlgs::name(dc.digest(), "[null-digest]"); - out << ",keysize " << (CryptoAlgs::key_length(dc.cipher()) * 8); - - if (tls_auth_context) - out << ",tls-auth"; - - // sending tls-crypt does not make sense. If we got to this point it - // means that tls-crypt was already there and it worked fine. - // tls-auth has to be kept for backward compatibility as it is there - // since a bit. - - out << ",key-method 2"; - - if (server) - out << ",tls-server"; - else - out << ",tls-client"; - - initial_options = out.str(); - - return initial_options; - } - - // generate a string summarizing information about the client - // including capabilities - std::string peer_info_string() const - { - std::ostringstream out; - const char *compstr = nullptr; - - // supports op32 and P_DATA_V2 and expects a push reply - - unsigned int iv_proto = IV_PROTO_DATA_V2 - | IV_PROTO_REQUEST_PUSH - | IV_PROTO_AUTH_PENDING_KW; - - if (SSLLib::SSLAPI::support_key_material_export()) - { - iv_proto |= IV_PROTO_TLS_KEY_EXPORT; - } - - out << "IV_VER=" << OPENVPN_VERSION << '\n'; - out << "IV_PLAT=" << platform_name() << '\n'; - out << "IV_NCP=2\n"; // negotiable crypto parameters V2 - out << "IV_TCPNL=1\n"; // supports TCP non-linear packet ID - out << "IV_PROTO=" << std::to_string(iv_proto) << '\n'; - /* - * OpenVPN3 allows to be pushed any cipher that it supports as it - * only implements secure ones and BF-CBC for backwards - * compatibility and generally adopts the concept of the server being - * responsible for sensible choices. Include the cipher here since - * OpenVPN 2.5 will otherwise ignore it and break on conrer cases - * like --cipher AES-128-CBC on client and --data-ciphers "AES-128-CBC" - * on server. - * - */ - out << "IV_CIPHERS=AES-256-GCM:AES-128-GCM"; - if (openvpn::AEAD::is_algorithm_supported<SSLLib::CryptoAPI>(CryptoAlgs::CHACHA20_POLY1305)) - { - out << ":CHACHA20-POLY1305"; - } - - if (openvpn::CryptoAlgs::defined(dc.cipher()) && - dc.cipher() != CryptoAlgs::AES_128_GCM && - dc.cipher() != CryptoAlgs::AES_256_GCM && - dc.cipher() != CryptoAlgs::CHACHA20_POLY1305) - { - out << ":" << openvpn::CryptoAlgs::name(dc.cipher()); - } - out << "\n"; - - compstr = comp_ctx.peer_info_string(); - - if (compstr) - out << compstr; - if (extra_peer_info) - out << extra_peer_info->to_string(); - if (is_bs64_cipher(dc.cipher())) - out << "IV_BS64DL=1\n"; // indicate support for data limits when using 64-bit block-size ciphers, version 1 (CVE-2016-6329) - if (relay_mode) - out << "IV_RELAY=1\n"; - const std::string ret = out.str(); - OPENVPN_LOG_PROTO("Peer Info:" << std::endl << ret); - return ret; - } - - // Used to generate link_mtu option sent to peer. - // Not const because dc.context() caches the DC context. - unsigned int link_mtu_adjust() - { - const size_t adj = protocol.extra_transport_bytes() + // extra 2 bytes for TCP-streamed packet length - (enable_op32 ? 4 : 1) + // leading op - comp_ctx.extra_payload_bytes() + // compression header - PacketID::size(PacketID::SHORT_FORM) + // sequence number - dc.context().encap_overhead(); // data channel crypto layer overhead - return (unsigned int)adj; - } - - private: - enum LoadCommonType { - LOAD_COMMON_SERVER, - LOAD_COMMON_CLIENT, - LOAD_COMMON_CLIENT_PUSHED, - }; - - // load parameters that can be present in both config file or pushed options - void load_common(const OptionList& opt, const ProtoContextOptions& pco, - const LoadCommonType type) - { - // duration parms - load_duration_parm(renegotiate, "reneg-sec", opt, 10, false, false); - expire = renegotiate; - load_duration_parm(expire, "tran-window", opt, 10, false, false); - expire += renegotiate; - load_duration_parm(handshake_window, "hand-window", opt, 10, false, false); - if (is_bs64_cipher(dc.cipher())) // special data limits for 64-bit block-size ciphers (CVE-2016-6329) - { - become_primary = Time::Duration::seconds(5); - tls_timeout = Time::Duration::milliseconds(1000); - } - else - become_primary = Time::Duration::seconds(std::min(handshake_window.to_seconds(), - renegotiate.to_seconds() / 2)); - load_duration_parm(become_primary, "become-primary", opt, 0, false, false); - load_duration_parm(tls_timeout, "tls-timeout", opt, 100, false, true); - - if (type == LOAD_COMMON_SERVER) - renegotiate += handshake_window; // avoid renegotiation collision with client - - // keepalive, ping, ping-restart - { - const Option *o = opt.get_ptr("keepalive"); - if (o) - { - set_duration_parm(keepalive_ping, "keepalive ping", o->get(1, 16), 1, false, false); - set_duration_parm(keepalive_timeout, "keepalive timeout", o->get(2, 16), 1, type == LOAD_COMMON_SERVER, false); - } - else - { - load_duration_parm(keepalive_ping, "ping", opt, 1, false, false); - load_duration_parm(keepalive_timeout, "ping-restart", opt, 1, false, false); - } - } - } - - std::string relay_prefix(const char *optname) const - { - std::string ret; - if (relay_mode) - ret = "relay-"; - ret += optname; - return ret; - } - }; - - // Used to describe an incoming network packet - class PacketType - { - friend class ProtoContext; - - enum { - DEFINED=1<<0, // packet is valid (otherwise invalid) - CONTROL=1<<1, // packet for control channel (otherwise for data channel) - SECONDARY=1<<2, // packet is associated with secondary KeyContext (otherwise primary) - SOFT_RESET=1<<3, // packet is a CONTROL_SOFT_RESET_V1 msg indicating a request for SSL/TLS renegotiate - }; - - public: - bool is_defined() const { return flags & DEFINED; } - bool is_control() const { return (flags & (CONTROL|DEFINED)) == (CONTROL|DEFINED); } - bool is_data() const { return (flags & (CONTROL|DEFINED)) == DEFINED; } - bool is_soft_reset() const { return (flags & (CONTROL|DEFINED|SECONDARY|SOFT_RESET)) - == (CONTROL|DEFINED|SECONDARY|SOFT_RESET); } - int peer_id() const { return peer_id_; } - - private: - PacketType(const Buffer& buf, class ProtoContext& proto) - : flags(0), opcode(INVALID_OPCODE), peer_id_(-1) - { - if (likely(buf.size())) - { - // get packet header byte - const unsigned int op = buf[0]; - - // examine opcode - { - const unsigned int opc = opcode_extract(op); - switch (opc) - { - case CONTROL_SOFT_RESET_V1: - case CONTROL_V1: - case ACK_V1: - { - flags |= CONTROL; - opcode = opc; - break; - } - case DATA_V2: - { - if (unlikely(buf.size() < 4)) - return; - const int opi = ntohl(*(const std::uint32_t *)buf.c_data()) & 0x00FFFFFF; - if (opi != OP_PEER_ID_UNDEF) - peer_id_ = opi; - opcode = opc; - break; - } - case DATA_V1: - { - opcode = opc; - break; - } - case CONTROL_HARD_RESET_CLIENT_V2: - case CONTROL_HARD_RESET_CLIENT_V3: - { - if (!proto.is_server()) - return; - flags |= CONTROL; - opcode = opc; - break; - } - case CONTROL_HARD_RESET_SERVER_V2: - { - if (proto.is_server()) - return; - flags |= CONTROL; - opcode = opc; - break; - } - default: - return; - } - } - - // examine key ID - { - const unsigned int kid = key_id_extract(op); - if (proto.primary && kid == proto.primary->key_id()) - flags |= DEFINED; - else if (proto.secondary && kid == proto.secondary->key_id()) - flags |= (DEFINED | SECONDARY); - else if (opcode == CONTROL_SOFT_RESET_V1 && kid == proto.upcoming_key_id) - flags |= (DEFINED | SECONDARY | SOFT_RESET); - } - } - } - - unsigned int flags; - unsigned int opcode; - int peer_id_; - }; - - static const char *opcode_name(const unsigned int opcode) - { - switch (opcode) - { - case CONTROL_SOFT_RESET_V1: - return "CONTROL_SOFT_RESET_V1"; - case CONTROL_V1: - return "CONTROL_V1"; - case ACK_V1: - return "ACK_V1"; - case DATA_V1: - return "DATA_V1"; - case DATA_V2: - return "DATA_V2"; - case CONTROL_HARD_RESET_CLIENT_V2: - return "CONTROL_HARD_RESET_CLIENT_V2"; - case CONTROL_HARD_RESET_CLIENT_V3: - return "CONTROL_HARD_RESET_CLIENT_V3"; - case CONTROL_HARD_RESET_SERVER_V2: - return "CONTROL_HARD_RESET_SERVER_V2"; - } - return nullptr; - } - - std::string dump_packet(const Buffer& buf) - { - std::ostringstream out; - try { - Buffer b(buf); - const size_t orig_size = b.size(); - const unsigned int op = b.pop_front(); - - const unsigned int opcode = opcode_extract(op); - const char *op_name = opcode_name(opcode); - if (op_name) - out << op_name << '/' << key_id_extract(op); - else - return "BAD_PACKET"; - - if (opcode == DATA_V1 || opcode == DATA_V2) - { - if (opcode == DATA_V2) - { - const unsigned int p1 = b.pop_front(); - const unsigned int p2 = b.pop_front(); - const unsigned int p3 = b.pop_front(); - const unsigned int peer_id = (p1<<16) + (p2<<8) + p3; - if (peer_id != 0xFFFFFF) - out << " PEER_ID=" << peer_id; - } - out << " SIZE=" << b.size() << '/' << orig_size; - } - else - { - { - ProtoSessionID src_psid(b); - out << " SRC_PSID=" << src_psid.str(); - } - - if (tls_wrap_mode == TLS_CRYPT) - { - PacketID pid; - pid.read(b, PacketID::LONG_FORM); - out << " PID=" << pid.str(); - - const unsigned char *hmac = b.read_alloc(hmac_size); - out << " HMAC=" << render_hex(hmac, hmac_size); - - // nothing else to print as the content is encrypted beyond this point - out << " TLS-CRYPT ENCRYPTED"; - } - else - { - if (tls_wrap_mode == TLS_AUTH) - { - const unsigned char *hmac = b.read_alloc(hmac_size); - out << " HMAC=" << render_hex(hmac, hmac_size); - - PacketID pid; - pid.read(b, PacketID::LONG_FORM); - out << " PID=" << pid.str(); - } - - ReliableAck ack(0); - ack.read(b); - const bool dest_psid_defined = !ack.empty(); - out << " ACK=["; - while (!ack.empty()) - { - out << " " << ack.front(); - ack.pop_front(); - } - out << " ]"; - - if (dest_psid_defined) - { - ProtoSessionID dest_psid(b); - out << " DEST_PSID=" << dest_psid.str(); - } - - if (opcode != ACK_V1) - out << " MSG_ID=" << ReliableAck::read_id(b); - } - if (opcode != ACK_V1) - out << " SIZE=" << b.size() << '/' << orig_size; - } -#ifdef OPENVPN_DEBUG_PROTO_DUMP - out << '\n' << string::trim_crlf_copy(dump_hex(buf)); -#endif - } - catch (const std::exception& e) - { - out << " EXCEPTION: " << e.what(); - } - return out.str(); - } - - protected: - - // used for reading/writing authentication strings (username, password, etc.) - - static void write_string_length(const size_t size, Buffer& buf) - { - if (size > 0xFFFF) - throw proto_error("auth_string_overflow"); - const std::uint16_t net_size = htons(size); - buf.write((const unsigned char *)&net_size, sizeof(net_size)); - } - - static size_t read_string_length(Buffer& buf) - { - if (buf.size()) - { - std::uint16_t net_size; - buf.read((unsigned char *)&net_size, sizeof(net_size)); - return ntohs(net_size); - } - else - return 0; - } - - template <typename S> - static void write_auth_string(const S& str, Buffer& buf) - { - const size_t len = str.length(); - if (len) - { - write_string_length(len+1, buf); - buf.write((const unsigned char *)str.c_str(), len); - buf.null_terminate(); - } - else - write_string_length(0, buf); - } - - template <typename S> - static S read_auth_string(Buffer& buf) - { - const size_t len = read_string_length(buf); - if (len) - { - const char *data = (const char *) buf.read_alloc(len); - if (len > 1) - return S(data, len-1); - } - return S(); - } - - template <typename S> - static void write_control_string(const S& str, Buffer& buf) - { - const size_t len = str.length(); - buf.write((const unsigned char *)str.c_str(), len); - buf.null_terminate(); - } - - template <typename S> - static S read_control_string(const Buffer& buf) - { - size_t size = buf.size(); - if (size) - { - if (buf[size-1] == 0) - --size; - if (size) - return S((const char *)buf.c_data(), size); - } - return S(); - } - - template <typename S> - void write_control_string(const S& str) - { - const size_t len = str.length(); - BufferPtr bp = new BufferAllocated(len+1, 0); - write_control_string(str, *bp); - control_send(std::move(bp)); - } - - static unsigned char *skip_string(Buffer& buf) - { - const size_t len = read_string_length(buf); - return buf.read_alloc(len); - } - - static void write_empty_string(Buffer& buf) - { - write_string_length(0, buf); - } - - // Packet structure for managing network packets, passed as a template - // parameter to ProtoStackBase - class Packet - { - friend class ProtoContext; - - public: - Packet() - { - reset_non_buf(); - } - - Packet(BufferPtr&& buf_arg, const unsigned int opcode_arg = CONTROL_V1) - : opcode(opcode_arg), buf(std::move(buf_arg)) - { - } - - void reset() - { - reset_non_buf(); - buf.reset(); - } - - void frame_prepare(const Frame& frame, const unsigned int context) - { - if (!buf) - buf.reset(new BufferAllocated()); - frame.prepare(context, *buf); - } - - bool is_raw() const { return opcode != CONTROL_V1; } - operator bool() const { return bool(buf); } - const BufferPtr& buffer_ptr() { return buf; } - const Buffer& buffer() const { return *buf; } - - private: - void reset_non_buf() - { - opcode = INVALID_OPCODE; - } - - unsigned int opcode; - BufferPtr buf; - }; - - // KeyContext encapsulates a single SSL/TLS session. - // ProtoStackBase uses CRTP-based static polymorphism for method callbacks. - class KeyContext : ProtoStackBase<Packet, KeyContext>, public RC<thread_unsafe_refcount> - { - typedef ProtoStackBase<Packet, KeyContext> Base; - friend Base; - typedef Base::ReliableSend ReliableSend; - typedef Base::ReliableRecv ReliableRecv; - - // ProtoStackBase protected vars - using Base::now; - using Base::rel_recv; - using Base::rel_send; - using Base::xmit_acks; - - // ProtoStackBase member functions - using Base::start_handshake; - using Base::raw_send; - using Base::send_pending_acks; - - // Helper for handling deferred data channel setup, - // for example if cipher/digest are pushed. - struct DataChannelKey - { - DataChannelKey() : rekey_defined(false) {} - - OpenVPNStaticKey key; - bool rekey_defined; - CryptoDCInstance::RekeyType rekey_type; - }; - - public: - typedef RCPtr<KeyContext> Ptr; - - OPENVPN_SIMPLE_EXCEPTION(tls_crypt_unwrap_wkc_error); - - // KeyContext events occur on two basic key types: - // Primary Key -- the key we transmit/encrypt on. - // Secondary Key -- new keys and retiring keys. - // - // The very first key created (key_id == 0) is a - // primary key. Subsequently created keys are always, - // at least initially, secondary keys. Secondary keys - // promote to primary via the KEV_BECOME_PRIMARY event - // (actually KEV_BECOME_PRIMARY swaps the primary and - // secondary keys, so the old primary is demoted - // to secondary and marked for expiration). - // - // Secondary keys are created by: - // 1. locally-generated soft renegotiation requests, and - // 2. peer-requested soft renegotiation requests. - // In each case, any previous secondary key will be - // wiped (including a secondary key that exists due to - // demotion of a previous primary key that has been marked - // for expiration). - enum EventType { - KEV_NONE, - - // KeyContext has reached the ACTIVE state, occurs on both - // primary and secondary. - KEV_ACTIVE, - - // SSL/TLS negotiation must complete by this time. If this - // event is hit on the first primary (i.e. first KeyContext - // with key_id == 0), it is fatal to the session and will - // trigger a disconnect/reconnect. If it's hit on the - // secondary, it will trigger a soft renegotiation. - KEV_NEGOTIATE, - - // When a KeyContext (normally the secondary) is scheduled - // to transition to the primary state. - KEV_BECOME_PRIMARY, - - // Waiting for condition on secondary (usually - // dataflow-based) to trigger KEV_BECOME_PRIMARY. - KEV_PRIMARY_PENDING, - - // Start renegotiating a new KeyContext on secondary - // (ignored unless originating on primary). - KEV_RENEGOTIATE, - - // Trigger a renegotiation originating from either - // primary or secondary. - KEV_RENEGOTIATE_FORCE, - - // Queue delayed renegotiation request from secondary - // to take effect after KEV_BECOME_PRIMARY. - KEV_RENEGOTIATE_QUEUE, - - // Expiration of KeyContext. - KEV_EXPIRE, - }; - - // for debugging - static const char *event_type_string(const EventType et) - { - switch (et) - { - case KEV_NONE: - return "KEV_NONE"; - case KEV_ACTIVE: - return "KEV_ACTIVE"; - case KEV_NEGOTIATE: - return "KEV_NEGOTIATE"; - case KEV_BECOME_PRIMARY: - return "KEV_BECOME_PRIMARY"; - case KEV_PRIMARY_PENDING: - return "KEV_PRIMARY_PENDING"; - case KEV_RENEGOTIATE: - return "KEV_RENEGOTIATE"; - case KEV_RENEGOTIATE_FORCE: - return "KEV_RENEGOTIATE_FORCE"; - case KEV_RENEGOTIATE_QUEUE: - return "KEV_RENEGOTIATE_QUEUE"; - case KEV_EXPIRE: - return "KEV_EXPIRE"; - default: - return "KEV_?"; - } - } - - KeyContext(ProtoContext& p, const bool initiator) - : Base(*p.config->ssl_factory, - p.config->now, p.config->tls_timeout, - p.config->frame, p.stats, - p.config->reliable_window, p.config->max_ack_list), - proto(p), - state(STATE_UNDEF), - crypto_flags(0), - dirty(0), - key_limit_renegotiation_fired(false), - tlsprf(p.config->tlsprf_factory->new_obj(p.is_server())) - { - // reliable protocol? - set_protocol(proto.config->protocol); - - // get key_id from parent - key_id_ = proto.next_key_id(); - - // set initial state - set_state((proto.is_server() ? S_INITIAL : C_INITIAL) + (initiator ? 0 : 1)); - - // cache stuff that we need to access in hot path - cache_op32(); - - // remember when we were constructed - construct_time = *now; - - // set must-negotiate-by time - set_event(KEV_NONE, KEV_NEGOTIATE, construct_time + proto.config->handshake_window); - } - - void set_protocol(const Protocol& p) - { - is_reliable = p.is_reliable(); // cache is_reliable state locally - } - - uint32_t get_tls_warnings() const - { - return Base::get_tls_warnings(); - } - - // need to call only on the initiator side of the connection - void start() - { - if (state == C_INITIAL || state == S_INITIAL) - { - send_reset(); - set_state(state+1); - dirty = true; - } - } - - // control channel flush - void flush() - { - if (dirty) - { - post_ack_action(); - Base::flush(); - send_pending_acks(); - dirty = false; - } - } - - void invalidate(const Error::Type reason) - { - Base::invalidate(reason); - } - - // retransmit packets as part of reliability layer - void retransmit() - { - // note that we don't set dirty here - Base::retransmit(); - } - - // when should we next call retransmit method - Time next_retransmit() const - { - const Time t = Base::next_retransmit(); - if (t <= next_event_time) - return t; - else - return next_event_time; - } - - void app_send_validate(BufferPtr&& bp) - { - if (bp->size() > APP_MSG_MAX) - throw proto_error("app_send: sent control message is too large"); - Base::app_send(std::move(bp)); - } - - // send app-level cleartext data to peer via SSL - void app_send(BufferPtr&& bp) - { - if (state >= ACTIVE) - { - app_send_validate(std::move(bp)); - dirty = true; - } - else - app_pre_write_queue.push_back(bp); - } - - // pass received ciphertext packets on network to SSL/reliability layers - bool net_recv(Packet&& pkt) - { - const bool ret = Base::net_recv(std::move(pkt)); - dirty = true; - return ret; - } - - // data channel encrypt - void encrypt(BufferAllocated& buf) - { - if (state >= ACTIVE - && (crypto_flags & CryptoDCInstance::CRYPTO_DEFINED) - && !invalidated()) - { - // compress and encrypt packet and prepend op header - const bool pid_wrap = do_encrypt(buf, true); - - // Trigger a new SSL/TLS negotiation if packet ID (a 32-bit unsigned int) - // is getting close to wrapping around. If it wraps back to 0 without - // a renegotiation, it would cause the replay protection logic to wrongly - // think that all further packets are replays. - if (pid_wrap) - schedule_key_limit_renegotiation(); - } - else - buf.reset_size(); // no crypto context available - } - - // data channel decrypt - void decrypt(BufferAllocated& buf) - { - try { - if (state >= ACTIVE - && (crypto_flags & CryptoDCInstance::CRYPTO_DEFINED) - && !invalidated()) - { - // Knock off leading op from buffer, but pass the 32-bit version to - // decrypt so it can be used as Additional Data for packet authentication. - const size_t head_size = op_head_size(buf[0]); - const unsigned char *op32 = (head_size == OP_SIZE_V2) ? buf.c_data() : nullptr; - buf.advance(head_size); - - // decrypt packet - const Error::Type err = crypto->decrypt(buf, now->seconds_since_epoch(), op32); - if (err) - { - proto.stats->error(err); - if (proto.is_tcp() && (err == Error::DECRYPT_ERROR || err == Error::HMAC_ERROR)) - invalidate(err); - } - - // trigger renegotiation if we hit decrypt data limit - if (data_limit) - data_limit_add(DataLimit::Decrypt, buf.size()); - - // decompress packet - if (compress) - compress->decompress(buf); - - // set MSS for segments server can receive - if (proto.config->mss_inter > 0) - MSSFix::mssfix(buf, proto.config->mss_inter); - } - else - buf.reset_size(); // no crypto context available - } - catch (BufferException&) - { - proto.stats->error(Error::BUFFER_ERROR); - buf.reset_size(); - if (proto.is_tcp()) - invalidate(Error::BUFFER_ERROR); - } - } - - // usually called by parent ProtoContext object when this KeyContext - // has been retired. - void prepare_expire(const EventType current_ev = KeyContext::KEV_NONE) - { - set_event(current_ev, - KEV_EXPIRE, - key_limit_renegotiation_fired ? data_limit_expire() : construct_time + proto.config->expire); - } - - // set a default next event, if unspecified - void set_next_event_if_unspecified() - { - if (next_event == KEV_NONE && !invalidated()) - prepare_expire(); - } - - // set a key limit renegotiation event at time t - void key_limit_reneg(const EventType ev, const Time& t) - { - if (t.defined()) - set_event(KEV_NONE, ev, t + Time::Duration::seconds(proto.is_server() ? 2 : 1)); - } - - // return time of upcoming KEV_BECOME_PRIMARY event - Time become_primary_time() - { - if (next_event == KEV_BECOME_PRIMARY) - return next_event_time; - else - return Time(); - } - - // is an KEV_x event pending? - bool event_pending() - { - if (current_event == KEV_NONE && *now >= next_event_time) - process_next_event(); - return current_event != KEV_NONE; - } - - // get KEV_x event - EventType get_event() const { return current_event; } - - // clear KEV_x event - void reset_event() { current_event = KEV_NONE; } - - // was session invalidated by an exception? - bool invalidated() const { return Base::invalidated(); } - - // Reason for invalidation - Error::Type invalidation_reason() const { return Base::invalidation_reason(); } - - // our Key ID in the OpenVPN protocol - unsigned int key_id() const { return key_id_; } - - // indicates that data channel is keyed and ready to encrypt/decrypt packets - bool data_channel_ready() const { return state >= ACTIVE; } - - bool is_dirty() const { return dirty; } - - // notification from parent of rekey operation - void rekey(const CryptoDCInstance::RekeyType type) - { - if (crypto) - crypto->rekey(type); - else if (data_channel_key) - { - // save for deferred processing - data_channel_key->rekey_type = type; - data_channel_key->rekey_defined = true; - } - } - - // time that our state transitioned to ACTIVE - Time reached_active() const { return reached_active_time_; } - - // transmit a keepalive message to peer - void send_keepalive() - { - send_data_channel_message(proto_context_private::keepalive_message, - sizeof(proto_context_private::keepalive_message)); - } - - // send explicit-exit-notify message to peer - void send_explicit_exit_notify() - { -#ifndef OPENVPN_DISABLE_EXPLICIT_EXIT // explicit exit should always be enabled in production - if (crypto_flags & CryptoDCInstance::EXPLICIT_EXIT_NOTIFY_DEFINED) - crypto->explicit_exit_notify(); - else - send_data_channel_message(proto_context_private::explicit_exit_notify_message, - sizeof(proto_context_private::explicit_exit_notify_message)); -#endif - } - - // general purpose method for sending constant string messages - // to peer via data channel - void send_data_channel_message(const unsigned char *data, const size_t size) - { - if (state >= ACTIVE - && (crypto_flags & CryptoDCInstance::CRYPTO_DEFINED) - && !invalidated()) - { - // allocate packet - Packet pkt; - pkt.frame_prepare(*proto.config->frame, Frame::WRITE_DC_MSG); - - // write keepalive message - pkt.buf->write(data, size); - - // process packet for transmission - do_encrypt(*pkt.buf, false); // set compress hint to "no" - - // send it - proto.net_send(key_id_, pkt); - } - } - - // validate the integrity of a packet - static bool validate(const Buffer& net_buf, ProtoContext& proto, TimePtr now) - { - try { - Buffer recv(net_buf); - - switch (proto.tls_wrap_mode) - { - case TLS_AUTH: - return validate_tls_auth(recv, proto, now); - case TLS_CRYPT_V2: - if (opcode_extract(recv[0]) == CONTROL_HARD_RESET_CLIENT_V3) - { - // skip validation of HARD_RESET_V3 because the tls-crypt - // engine has not been initialized yet - OPENVPN_LOG_PROTO_VERBOSE("SKIPPING VALIDATION OF HARD_RESET_V3"); - return true; - } - /* no break */ - case TLS_CRYPT: - return validate_tls_crypt(recv, proto, now); - case TLS_PLAIN: - return validate_tls_plain(recv, proto, now); - } - } - catch (BufferException& e) - { - OPENVPN_LOG_PROTO_VERBOSE("validate() exception: " << e.what()); - } - return false; - } - - void generate_datachannel_keys() - { - std::unique_ptr<DataChannelKey> dck(new DataChannelKey()); - - - if(proto.config->dc.key_derivation() == CryptoAlgs::KeyDerivation::TLS_EKM) - { - // USE RFC 5705 key material export - export_key_material(dck->key); - } - else - { - // use the TLS PRF construction to exchange session keys for building - // the data channel crypto context - tlsprf->generate_key_expansion(dck->key, proto.psid_self, proto.psid_peer); - } - tlsprf->erase(); - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " KEY " << CryptoAlgs::name(proto.config->dc.key_derivation()) - << " " << proto.mode().str() << ' ' << dck->key.render()); - - if (data_channel_key) - { - dck->rekey_defined = data_channel_key->rekey_defined; - dck->rekey_type = data_channel_key->rekey_type; - } - dck.swap(data_channel_key); - } - - // Initialize the components of the OpenVPN data channel protocol - void init_data_channel() - { - // set up crypto for data channel - if (!data_channel_key || !data_channel_key->key.defined()) - { - generate_datachannel_keys(); - } - bool enable_compress = true; - Config& c = *proto.config; - const unsigned int key_dir = proto.is_server() ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - const OpenVPNStaticKey& key = data_channel_key->key; - - // special data limits for 64-bit block-size ciphers (CVE-2016-6329) - if (is_bs64_cipher(c.dc.cipher())) - { - DataLimit::Parameters dp; - dp.encrypt_red_limit = OPENVPN_BS64_DATA_LIMIT; - dp.decrypt_red_limit = OPENVPN_BS64_DATA_LIMIT; - OPENVPN_LOG_PROTO("Per-Key Data Limit: " << dp.encrypt_red_limit << '/' << dp.decrypt_red_limit); - data_limit.reset(new DataLimit(dp)); - } - - // build crypto context for data channel encryption/decryption - crypto = c.dc.context().new_obj(key_id_); - crypto_flags = crypto->defined(); - - if (crypto_flags & CryptoDCInstance::CIPHER_DEFINED) - crypto->init_cipher(key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir), - key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); - - if (crypto_flags & CryptoDCInstance::HMAC_DEFINED) - crypto->init_hmac(key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir), - key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); - - crypto->init_pid(PacketID::SHORT_FORM, - c.pid_mode, - PacketID::SHORT_FORM, - "DATA", int(key_id_), - proto.stats); - - crypto->init_remote_peer_id(c.remote_peer_id); - - enable_compress = crypto->consider_compression(proto.config->comp_ctx); - - if (data_channel_key->rekey_defined) - crypto->rekey(data_channel_key->rekey_type); - data_channel_key.reset(); - - // set up compression for data channel - if (enable_compress) - compress = proto.config->comp_ctx.new_compressor(proto.config->frame, proto.stats); - else - compress.reset(); - - // cache op32 for hot path in do_encrypt - cache_op32(); - - int crypto_encap = (enable_op32 ? OP_SIZE_V2 : 1) + - c.comp_ctx.extra_payload_bytes() + - PacketID::size(PacketID::SHORT_FORM) + - c.dc.context().encap_overhead(); - - int transport_encap = 0; - if (c.mss_parms.mtu) - { - if (proto.is_tcp()) - transport_encap += sizeof(struct TCPHeader); - else - transport_encap += sizeof(struct UDPHeader); - - if (c.protocol.is_ipv6()) - transport_encap += sizeof(struct IPv6Header); - else - transport_encap += sizeof(struct IPv4Header); - - transport_encap += c.protocol.extra_transport_bytes(); - } - - if (c.mss_parms.mssfix != 0) - { - OPENVPN_LOG_PROTO("MTU mssfix=" << c.mss_parms.mssfix << - " crypto_encap=" << crypto_encap << - " transport_encap=" << transport_encap); - c.mss_inter = c.mss_parms.mssfix - (crypto_encap + transport_encap); - } - } - - void data_limit_notify(const DataLimit::Mode cdl_mode, - const DataLimit::State cdl_status) - { - if (data_limit) - data_limit_event(cdl_mode, data_limit->update_state(cdl_mode, cdl_status)); - } - - private: - static bool validate_tls_auth(Buffer &recv, ProtoContext& proto, TimePtr now) - { - const unsigned char *orig_data = recv.data(); - const size_t orig_size = recv.size(); - - // advance buffer past initial op byte - recv.advance(1); - - // get source PSID - ProtoSessionID src_psid(recv); - - // verify HMAC - { - recv.advance(proto.hmac_size); - if (!proto.ta_hmac_recv->ovpn_hmac_cmp(orig_data, orig_size, - 1 + ProtoSessionID::SIZE, - proto.hmac_size, - PacketID::size(PacketID::LONG_FORM))) - return false; - } - - // verify source PSID - if (!proto.psid_peer.match(src_psid)) - return false; - - // read tls_auth packet ID - const PacketID pid = proto.ta_pid_recv.read_next(recv); - - // get current time_t - const PacketID::time_t t = now->seconds_since_epoch(); - - // verify tls_auth packet ID - const bool pid_ok = proto.ta_pid_recv.test_add(pid, t, false); - - // make sure that our own PSID is contained in packet received from peer - if (ReliableAck::ack_skip(recv)) - { - ProtoSessionID dest_psid(recv); - if (!proto.psid_self.match(dest_psid)) - return false; - } - - return pid_ok; - } - - static bool validate_tls_crypt(Buffer& recv, ProtoContext& proto, TimePtr now) - { - const unsigned char *orig_data = recv.data(); - const size_t orig_size = recv.size(); - - // advance buffer past initial op byte - recv.advance(1); - // get source PSID - ProtoSessionID src_psid(recv); - // read tls_auth packet ID - const PacketID pid = proto.ta_pid_recv.read_next(recv); - - recv.advance(proto.hmac_size); - - const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM); - const size_t data_offset = head_size + proto.hmac_size; - if (orig_size < data_offset) - return false; - - // we need a buffer to perform the payload decryption and being this a static - // function we can't use the instance member like in decapsulate_tls_crypt() - BufferAllocated work; - proto.config->frame->prepare(Frame::DECRYPT_WORK, work); - - // decrypt payload from 'recv' into 'work' - const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + head_size, - work.data(), work.max_size(), - recv.c_data(), recv.size()); - if (!decrypt_bytes) - return false; - - work.inc_size(decrypt_bytes); - - // verify HMAC - if (!proto.tls_crypt_recv->hmac_cmp(orig_data, - TLSCryptContext::hmac_offset, - work.c_data(), work.size())) - return false; - - // verify source PSID - if (proto.psid_peer.defined()) - { - if (!proto.psid_peer.match(src_psid)) - return false; - } - else - { - proto.psid_peer = src_psid; - } - - // get current time_t - const PacketID::time_t t = now->seconds_since_epoch(); - - // verify tls_auth packet ID - const bool pid_ok = proto.ta_pid_recv.test_add(pid, t, false); - // make sure that our own PSID is contained in packet received from peer - if (ReliableAck::ack_skip(work)) - { - ProtoSessionID dest_psid(work); - if (!proto.psid_self.match(dest_psid)) - return false; - } - - return pid_ok; - } - - static bool validate_tls_plain(Buffer& recv, ProtoContext& proto, TimePtr now) - { - // advance buffer past initial op byte - recv.advance(1); - - // verify source PSID - ProtoSessionID src_psid(recv); - if (!proto.psid_peer.match(src_psid)) - return false; - - // make sure that our own PSID is contained in packet received from peer - if (ReliableAck::ack_skip(recv)) - { - ProtoSessionID dest_psid(recv); - if (!proto.psid_self.match(dest_psid)) - return false; - } - return true; - } - - bool do_encrypt(BufferAllocated& buf, const bool compress_hint) - { - bool pid_wrap; - - // set MSS for segments client can receive - if (proto.config->mss_inter > 0) - MSSFix::mssfix(buf, proto.config->mss_inter); - - // compress packet - if (compress) - compress->compress(buf, compress_hint); - - // trigger renegotiation if we hit encrypt data limit - if (data_limit) - data_limit_add(DataLimit::Encrypt, buf.size()); - - if (enable_op32) - { - const std::uint32_t op32 = htonl(op32_compose(DATA_V2, key_id_, remote_peer_id)); - - static_assert(sizeof(op32) == OP_SIZE_V2, "OP_SIZE_V2 inconsistency"); - - // encrypt packet - pid_wrap = crypto->encrypt(buf, now->seconds_since_epoch(), (const unsigned char *)&op32); - - // prepend op - buf.prepend((const unsigned char *)&op32, sizeof(op32)); - } - else - { - // encrypt packet - pid_wrap = crypto->encrypt(buf, now->seconds_since_epoch(), nullptr); - - // prepend op - buf.push_front(op_compose(DATA_V1, key_id_)); - } - return pid_wrap; - } - - // cache op32 and remote_peer_id - void cache_op32() - { - enable_op32 = proto.config->enable_op32; - remote_peer_id = proto.config->remote_peer_id; - } - - void set_state(const int newstate) - { - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " KeyContext[" << key_id_ << "] " << state_string(state) << " -> " << state_string(newstate)); - state = newstate; - } - - void set_event(const EventType current) - { - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " KeyContext[" << key_id_ << "] " << event_type_string(current)); - current_event = current; - } - - void set_event(const EventType current, const EventType next, const Time& next_time) - { - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " KeyContext[" << key_id_ << "] " << event_type_string(current) << " -> " << event_type_string(next) << '(' << seconds_until(next_time) << ')'); - current_event = current; - next_event = next; - next_event_time = next_time; - } - - void invalidate_callback() // called by ProtoStackBase when session is invalidated - { - reached_active_time_ = Time(); - next_event = KEV_NONE; - next_event_time = Time::infinite(); - } - - // Trigger a renegotiation based on data flow condition such - // as per-key data limit or packet ID approaching wraparound. - void schedule_key_limit_renegotiation() - { - if (!key_limit_renegotiation_fired && state >= ACTIVE && !invalidated()) - { - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " SCHEDULE KEY LIMIT RENEGOTIATION"); - - key_limit_renegotiation_fired = true; - proto.stats->error(Error::N_KEY_LIMIT_RENEG); - - // If primary, renegotiate now (within a second or two). - // If secondary, queue the renegotiation request until - // key reaches primary. - if (next_event == KEV_BECOME_PRIMARY) // secondary key before transition to primary? - set_event(KEV_RENEGOTIATE_QUEUE); // reneg request crosses over to primary, doesn't wipe next_event (KEV_BECOME_PRIMARY) - else - key_limit_reneg(KEV_RENEGOTIATE, *now); - } - } - - // Handle data-limited keys such as Blowfish and other 64-bit block-size ciphers. - void data_limit_add(const DataLimit::Mode mode, const size_t size) - { - const DataLimit::State state = data_limit->add(mode, size); - if (state > DataLimit::None) - data_limit_event(mode, state); - } - - // Handle a DataLimit event. - void data_limit_event(const DataLimit::Mode mode, const DataLimit::State state) - { - OPENVPN_LOG_PROTO_VERBOSE(proto.debug_prefix() << " DATA LIMIT " << DataLimit::mode_str(mode) << ' ' << DataLimit::state_str(state) << " key_id=" << key_id_); - - // State values: - // DataLimit::Green -- first packet received and decrypted. - // DataLimit::Red -- data limit has been exceeded, so trigger a renegotiation. - if (state == DataLimit::Red) - schedule_key_limit_renegotiation(); - - // When we are in KEV_PRIMARY_PENDING state, we must receive at least - // one packet from the peer on this key before we transition to - // KEV_BECOME_PRIMARY so we can transmit on it. - if (next_event == KEV_PRIMARY_PENDING && data_limit->is_decrypt_green()) - set_event(KEV_NONE, KEV_BECOME_PRIMARY, *now + Time::Duration::seconds(1)); - } - - // Should we enter KEV_PRIMARY_PENDING state? Do it if: - // 1. we are a client, - // 2. data limit is enabled, - // 3. this is a renegotiated key in secondary context, i.e. not the first key, and - // 4. no data received yet from peer on this key. - bool data_limit_defer() const - { - return !proto.is_server() && data_limit && key_id_ && !data_limit->is_decrypt_green(); - } - - // General expiration set when key hits data limit threshold. - Time data_limit_expire() const - { - return *now + (proto.config->handshake_window * 2); - } - - void active_event() - { - set_event(KEV_ACTIVE, KEV_BECOME_PRIMARY, reached_active() + proto.config->become_primary); - } - - void process_next_event() - { - if (*now >= next_event_time) - { - switch (next_event) - { - case KEV_BECOME_PRIMARY: - if (data_limit_defer()) - set_event(KEV_NONE, KEV_PRIMARY_PENDING, data_limit_expire()); - else - set_event(KEV_BECOME_PRIMARY, KEV_RENEGOTIATE, construct_time + proto.config->renegotiate); - break; - case KEV_RENEGOTIATE: - case KEV_RENEGOTIATE_FORCE: - prepare_expire(next_event); - break; - case KEV_NEGOTIATE: - kev_error(KEV_NEGOTIATE, Error::KEV_NEGOTIATE_ERROR); - break; - case KEV_PRIMARY_PENDING: - kev_error(KEV_PRIMARY_PENDING, Error::KEV_PENDING_ERROR); - break; - case KEV_EXPIRE: - kev_error(KEV_EXPIRE, Error::N_KEV_EXPIRE); - break; - default: - break; - } - } - } - - void kev_error(const EventType ev, const Error::Type reason) - { - proto.stats->error(reason); - invalidate(reason); - set_event(ev); - } - - unsigned int initial_op(const bool sender, const bool tls_crypt_v2) const - { - if (key_id_) - { - return CONTROL_SOFT_RESET_V1; - } - else - { - if (proto.is_server() == sender) - return CONTROL_HARD_RESET_SERVER_V2; - - if (!tls_crypt_v2) - return CONTROL_HARD_RESET_CLIENT_V2; - else - return CONTROL_HARD_RESET_CLIENT_V3; - } - } - - void send_reset() - { - Packet pkt; - pkt.opcode = initial_op(true, proto.tls_wrap_mode == TLS_CRYPT_V2); - pkt.frame_prepare(*proto.config->frame, Frame::WRITE_SSL_INIT); - raw_send(std::move(pkt)); - } - - void raw_recv(Packet&& raw_pkt) // called by ProtoStackBase - { - if (raw_pkt.buf->empty() && - raw_pkt.opcode == initial_op(false, proto.tls_wrap_mode == TLS_CRYPT_V2)) - { - switch (state) - { - case C_WAIT_RESET: - //send_reset(); // fixme -- possibly not needed - set_state(C_WAIT_RESET_ACK); - break; - case S_WAIT_RESET: - send_reset(); - set_state(S_WAIT_RESET_ACK); - break; - } - } - } - - void app_recv(BufferPtr&& to_app_buf) // called by ProtoStackBase - { - app_recv_buf.put(std::move(to_app_buf)); - if (app_recv_buf.size() > APP_MSG_MAX) - throw proto_error("app_recv: received control message is too large"); - BufferComposed::Complete bcc = app_recv_buf.complete(); - switch (state) - { - case C_WAIT_AUTH: - if (recv_auth_complete(bcc)) - { - recv_auth(bcc.get()); - set_state(C_WAIT_AUTH_ACK); - } - break; - case S_WAIT_AUTH: - if (recv_auth_complete(bcc)) - { - recv_auth(bcc.get()); - send_auth(); - set_state(S_WAIT_AUTH_ACK); - } - break; - case S_WAIT_AUTH_ACK: // rare case where client receives auth, goes ACTIVE, but the ACK response is dropped - case ACTIVE: - if (bcc.advance_to_null()) // does composed buffer contain terminating null char? - proto.app_recv(key_id_, bcc.get()); - break; - } - } - - void net_send(const Packet& net_pkt, const Base::NetSendType nstype) // called by ProtoStackBase - { - if (!is_reliable || nstype != Base::NET_SEND_RETRANSMIT) // retransmit packets on UDP only, not TCP - proto.net_send(key_id_, net_pkt); - } - - void post_ack_action() - { - if (state <= LAST_ACK_STATE && !rel_send.n_unacked()) - { - switch (state) - { - case C_WAIT_RESET_ACK: - start_handshake(); - send_auth(); - set_state(C_WAIT_AUTH); - break; - case S_WAIT_RESET_ACK: - start_handshake(); - set_state(S_WAIT_AUTH); - break; - case C_WAIT_AUTH_ACK: - active(); - set_state(ACTIVE); - break; - case S_WAIT_AUTH_ACK: - active(); - set_state(ACTIVE); - break; - } - } - } - - void send_auth() - { - BufferPtr buf = new BufferAllocated(); - proto.config->frame->prepare(Frame::WRITE_SSL_CLEARTEXT, *buf); - buf->write(proto_context_private::auth_prefix, sizeof(proto_context_private::auth_prefix)); - tlsprf->self_randomize(*proto.config->rng); - tlsprf->self_write(*buf); - const std::string options = proto.config->options_string(); - write_auth_string(options, *buf); - if (!proto.is_server()) - { - OPENVPN_LOG_PROTO("Tunnel Options:" << options); - buf->or_flags(BufferAllocated::DESTRUCT_ZERO); - if (proto.config->xmit_creds) - proto.client_auth(*buf); - else - { - write_empty_string(*buf); // username - write_empty_string(*buf); // password - } - const std::string peer_info = proto.config->peer_info_string(); - write_auth_string(peer_info, *buf); - } - app_send_validate(std::move(buf)); - dirty = true; - } - - void recv_auth(BufferPtr buf) - { - const unsigned char *buf_pre = buf->read_alloc(sizeof(proto_context_private::auth_prefix)); - if (std::memcmp(buf_pre, proto_context_private::auth_prefix, sizeof(proto_context_private::auth_prefix))) - throw proto_error("bad_auth_prefix"); - tlsprf->peer_read(*buf); - const std::string options = read_auth_string<std::string>(*buf); - if (proto.is_server()) - { - const std::string username = read_auth_string<std::string>(*buf); - const SafeString password = read_auth_string<SafeString>(*buf); - const std::string peer_info = read_auth_string<std::string>(*buf); - proto.server_auth(username, password, peer_info, Base::auth_cert()); - } - } - - // return true if complete recv_auth message is contained in buffer - bool recv_auth_complete(BufferComplete& bc) const - { - if (!bc.advance(sizeof(proto_context_private::auth_prefix))) - return false; - if (!tlsprf->peer_read_complete(bc)) - return false; - if (!bc.advance_string()) // options - return false; - if (proto.is_server()) - { - if (!bc.advance_string()) // username - return false; - if (!bc.advance_string()) // password - return false; - if (!bc.advance_string()) // peer_info - return false; - } - return true; - } - - void active() - { - if (proto.config->debug_level >= 1) - OPENVPN_LOG_SSL("SSL Handshake: " << Base::ssl_handshake_details()); - /* Our internal state machine only decides after push request what protocol - * options we want to use. Therefore we also have to postpone data key - * generation until this happens, create a empty DataChannelKey as - * placeholder */ - data_channel_key.reset(new DataChannelKey()); - - if (!proto.dc_deferred) - { - init_data_channel(); - } - - while (!app_pre_write_queue.empty()) - { - app_send_validate(std::move(app_pre_write_queue.front())); - app_pre_write_queue.pop_front(); - dirty = true; - } - reached_active_time_ = *now; - proto.slowest_handshake_.max(reached_active_time_ - construct_time); - active_event(); - } - - void prepend_dest_psid_and_acks(Buffer& buf) - { - // if sending ACKs, prepend dest PSID - if (!xmit_acks.empty()) - { - if (proto.psid_peer.defined()) - proto.psid_peer.prepend(buf); - else - { - proto.stats->error(Error::CC_ERROR); - throw proto_error("peer_psid_undef"); - } - } - - // prepend ACKs for messages received from peer - xmit_acks.prepend(buf); - } - - bool verify_src_psid(const ProtoSessionID& src_psid) - { - if (proto.psid_peer.defined()) - { - if (!proto.psid_peer.match(src_psid)) - { - proto.stats->error(Error::CC_ERROR); - if (proto.is_tcp()) - invalidate(Error::CC_ERROR); - return false; - } - } - else - { - proto.psid_peer = src_psid; - } - return true; - } - - bool verify_dest_psid(Buffer& buf) - { - ProtoSessionID dest_psid(buf); - if (!proto.psid_self.match(dest_psid)) - { - proto.stats->error(Error::CC_ERROR); - if (proto.is_tcp()) - invalidate(Error::CC_ERROR); - return false; - } - return true; - } - - void gen_head_tls_auth(const unsigned int opcode, Buffer& buf) - { - // write tls-auth packet ID - proto.ta_pid_send.write_next(buf, true, now->seconds_since_epoch()); - - // make space for tls-auth HMAC - buf.prepend_alloc(proto.hmac_size); - - // write source PSID - proto.psid_self.prepend(buf); - - // write opcode - buf.push_front(op_compose(opcode, key_id_)); - - // write hmac - proto.ta_hmac_send->ovpn_hmac_gen(buf.data(), buf.size(), - 1 + ProtoSessionID::SIZE, - proto.hmac_size, - PacketID::size(PacketID::LONG_FORM)); - } - - void gen_head_tls_crypt(const unsigned int opcode, BufferAllocated& buf) - { - // in 'work' we store all the fields that are not supposed to be encrypted - proto.config->frame->prepare(Frame::ENCRYPT_WORK, work); - // make space for HMAC - work.prepend_alloc(proto.hmac_size); - // write tls-crypt packet ID - proto.ta_pid_send.write_next(work, true, now->seconds_since_epoch()); - // write source PSID - proto.psid_self.prepend(work); - // write opcode - work.push_front(op_compose(opcode, key_id_)); - - // compute HMAC using header fields (from 'work') and plaintext - // payload (from 'buf') - proto.tls_crypt_send->hmac_gen(work.data(), TLSCryptContext::hmac_offset, - buf.c_data(), buf.size()); - - const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size; - - // encrypt the content of 'buf' (packet payload) into 'work' - const size_t decrypt_bytes = proto.tls_crypt_send->encrypt(work.c_data() + TLSCryptContext::hmac_offset, - work.data() + data_offset, - work.max_size() - data_offset, - buf.c_data(), buf.size()); - if (!decrypt_bytes) - { - buf.reset_size(); - return; - } - work.inc_size(decrypt_bytes); - - // append WKc to wrapped packet for tls-crypt-v2 - if ((opcode == CONTROL_HARD_RESET_CLIENT_V3) - && (proto.tls_wrap_mode == TLS_CRYPT_V2)) - proto.tls_crypt_append_wkc(work); - - // 'work' now contains the complete packet ready to go. swap it with 'buf' - buf.swap(work); - } - - void gen_head_tls_plain(const unsigned int opcode, Buffer& buf) - { - // write source PSID - proto.psid_self.prepend(buf); - // write opcode - buf.push_front(op_compose(opcode, key_id_)); - } - - void gen_head(const unsigned int opcode, BufferAllocated& buf) - { - switch (proto.tls_wrap_mode) - { - case TLS_AUTH: - gen_head_tls_auth(opcode, buf); - break; - case TLS_CRYPT: - case TLS_CRYPT_V2: - gen_head_tls_crypt(opcode, buf); - break; - case TLS_PLAIN: - gen_head_tls_plain(opcode, buf); - break; - } - } - - void encapsulate(id_t id, Packet& pkt) // called by ProtoStackBase - { - BufferAllocated& buf = *pkt.buf; - - // prepend message sequence number - ReliableAck::prepend_id(buf, id); - - // prepend dest PSID and ACKs to reply to peer - prepend_dest_psid_and_acks(buf); - - // generate message head - gen_head(pkt.opcode, buf); - } - - void generate_ack(Packet& pkt) // called by ProtoStackBase - { - BufferAllocated& buf = *pkt.buf; - - // prepend dest PSID and ACKs to reply to peer - prepend_dest_psid_and_acks(buf); - - gen_head(ACK_V1, buf); - } - - bool decapsulate_post_process(Packet& pkt, ProtoSessionID& src_psid, const PacketID pid) - { - Buffer& recv = *pkt.buf; - - // update our last-packet-received time - proto.update_last_received(); - - // verify source PSID - if (!verify_src_psid(src_psid)) - return false; - - // get current time_t - const PacketID::time_t t = now->seconds_since_epoch(); - // verify tls_auth/crypt packet ID - const bool pid_ok = proto.ta_pid_recv.test_add(pid, t, false); - - // process ACKs sent by peer (if packet ID check failed, - // read the ACK IDs, but don't modify the rel_send object). - if (ReliableAck::ack(rel_send, recv, pid_ok)) - { - // make sure that our own PSID is contained in packet received from peer - if (!verify_dest_psid (recv)) - return false; - } - - // for CONTROL packets only, not ACK - if (pkt.opcode != ACK_V1) - { - // get message sequence number - const id_t id = ReliableAck::read_id (recv); - - if (pid_ok) - { - // try to push message into reliable receive object - const unsigned int rflags = rel_recv.receive (pkt, id); - - // should we ACK packet back to sender? - if (rflags & ReliableRecv::ACK_TO_SENDER) - xmit_acks.push_back (id); // ACK packet to sender - - // was packet accepted by reliable receive object? - if (rflags & ReliableRecv::IN_WINDOW) - { - proto.ta_pid_recv.test_add (pid, t, true); // remember tls_auth packet ID so that it can't be replayed - return true; - } - } - else // treat as replay - { - proto.stats->error (Error::REPLAY_ERROR); - if (pid.is_valid ()) - xmit_acks.push_back (id); // even replayed packets must be ACKed or protocol could deadlock - } - } - else - { - if (pid_ok) - proto.ta_pid_recv.test_add (pid, t, true); // remember tls_auth packet ID of ACK packet to prevent replay - else - proto.stats->error (Error::REPLAY_ERROR); - } - return false; - - } - - bool decapsulate_tls_auth(Packet &pkt) - { - Buffer& recv = *pkt.buf; - const unsigned char *orig_data = recv.data (); - const size_t orig_size = recv.size (); - - // advance buffer past initial op byte - recv.advance (1); - - // get source PSID - ProtoSessionID src_psid (recv); - - // verify HMAC - { - recv.advance (proto.hmac_size); - if (!proto.ta_hmac_recv->ovpn_hmac_cmp(orig_data, orig_size, - 1 + ProtoSessionID::SIZE, - proto.hmac_size, - PacketID::size (PacketID::LONG_FORM))) - { - proto.stats->error(Error::HMAC_ERROR); - if (proto.is_tcp()) - invalidate(Error::HMAC_ERROR); - return false; - } - } - - // read tls_auth packet ID - const PacketID pid = proto.ta_pid_recv.read_next(recv); - - return decapsulate_post_process(pkt, src_psid, pid); - } - - bool decapsulate_tls_crypt(Packet &pkt) - { - BufferAllocated& recv = *pkt.buf; - const unsigned char *orig_data = recv.data(); - const size_t orig_size = recv.size(); - - // advance buffer past initial op byte - recv.advance(1); - // get source PSID - ProtoSessionID src_psid(recv); - // get tls-crypt packet ID - const PacketID pid = proto.ta_pid_recv.read_next(recv); - // skip the hmac - recv.advance(proto.hmac_size); - - const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size; - if (orig_size < data_offset) - return false; - - // decrypt payload - proto.config->frame->prepare(Frame::DECRYPT_WORK, work); - - const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + TLSCryptContext::hmac_offset, - work.data(), work.max_size(), - recv.c_data(), recv.size()); - if (!decrypt_bytes) - { - proto.stats->error(Error::DECRYPT_ERROR); - if (proto.is_tcp()) - invalidate(Error::DECRYPT_ERROR); - return false; - } - - work.inc_size(decrypt_bytes); - - // verify HMAC - if (!proto.tls_crypt_recv->hmac_cmp(orig_data, TLSCryptContext::hmac_offset, - work.c_data(), work.size())) - { - proto.stats->error(Error::HMAC_ERROR); - if (proto.is_tcp()) - invalidate(Error::HMAC_ERROR); - return false; - } - - // move the decrypted payload to 'recv', so that the processing of the - // packet can continue - recv.swap(work); - - return decapsulate_post_process(pkt, src_psid, pid); - } - - bool decapsulate_tls_plain(Packet &pkt) - { - Buffer& recv = *pkt.buf; - - // update our last-packet-received time - proto.update_last_received(); - - // advance buffer past initial op byte - recv.advance(1); - - // verify source PSID - ProtoSessionID src_psid(recv); - if (!verify_src_psid(src_psid)) - return false; - - // process ACKs sent by peer - if (ReliableAck::ack(rel_send, recv, true)) - { - // make sure that our own PSID is in packet received from peer - if (!verify_dest_psid(recv)) - return false; - } - - // for CONTROL packets only, not ACK - if (pkt.opcode != ACK_V1) - { - // get message sequence number - const id_t id = ReliableAck::read_id(recv); - - // try to push message into reliable receive object - const unsigned int rflags = rel_recv.receive(pkt, id); - - // should we ACK packet back to sender? - if (rflags & ReliableRecv::ACK_TO_SENDER) - xmit_acks.push_back(id); // ACK packet to sender - - // was packet accepted by reliable receive object? - if (rflags & ReliableRecv::IN_WINDOW) - return true; - } - return false; - } - - bool unwrap_tls_crypt_wkc(Buffer &recv) - { - // the ``WKc`` is located at the end of the packet, after the tls-crypt - // payload. - // Format is as follows (as documented by Steffan Krager): - // - // ``len = len(WKc)`` (16 bit, network byte order) - // ``T = HMAC-SHA256(Ka, len || Kc || metadata)`` - // ``IV = 128 most significant bits of T`` - // ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len`` - - const unsigned char *orig_data = recv.data(); - const size_t orig_size = recv.size(); - const size_t hmac_size = proto.config->tls_crypt_context->digest_size(); - const size_t tls_frame_size = 1 + ProtoSessionID::SIZE + - PacketID::size(PacketID::LONG_FORM) + - hmac_size + - // the following is the tls-crypt payload - sizeof(char) + // length of ACK array - sizeof(id_t); // reliable ID - - // check that at least the authentication tag ``T`` is present - if (orig_size < (tls_frame_size + hmac_size)) - return false; - - // the ``WKc`` is just appended after the standard tls-crypt frame - const unsigned char *wkc_raw = orig_data + tls_frame_size; - const size_t wkc_raw_size = orig_size - tls_frame_size - sizeof(uint16_t); - // retrieve the ``WKc`` len from the bottom of the packet and convert it to Host Order - uint16_t wkc_len = ntohs(*(uint16_t *)(wkc_raw + wkc_raw_size)); - // length sanity check (the size of the ``len`` field is included in the value) - if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size) - return false; - - BufferAllocated plaintext(wkc_len, BufferAllocated::CONSTRUCT_ZERO); - // plaintext will be used to compute the Auth Tag, therefore start by prepnding - // the WKc length in network order - wkc_len = htons(wkc_len); - plaintext.write(&wkc_len, sizeof(wkc_len)); - const size_t decrypt_bytes = proto.tls_crypt_server->decrypt(wkc_raw, - plaintext.data() + 2, - plaintext.max_size() - 2, - wkc_raw + hmac_size, - wkc_raw_size - hmac_size); - plaintext.inc_size(decrypt_bytes); - // decrypted data must at least contain a full 2048bits client key - // (metadata is optional) - if (plaintext.size() < OpenVPNStaticKey::KEY_SIZE) - { - proto.stats->error(Error::DECRYPT_ERROR); - if (proto.is_tcp()) - invalidate(Error::DECRYPT_ERROR); - return false; - } - - if (!proto.tls_crypt_server->hmac_cmp(wkc_raw, 0, - plaintext.c_data(), - plaintext.size())) - { - proto.stats->error(Error::HMAC_ERROR); - if (proto.is_tcp()) - invalidate(Error::HMAC_ERROR); - return false; - } - - // we can now remove the WKc length from the plaintext, as it is not - // really part of the key material - plaintext.advance(sizeof(wkc_len)); - - // WKc has been authenticated: it contains the client key followed - // by the optional metadata. Let's initialize the tls-crypt context - // with the client key - - OpenVPNStaticKey client_key; - plaintext.read(client_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE); - proto.reset_tls_crypt(*proto.config, client_key); - - // verify metadata - int metadata_type = -1; - if (!plaintext.empty()) - metadata_type = plaintext.pop_front(); - - if (!proto.tls_crypt_metadata->verify(metadata_type, plaintext)) - { - proto.stats->error(Error::TLS_CRYPT_META_FAIL); - return false; - } - - // virtually remove the WKc from the packet - recv.set_size(tls_frame_size); - - return true; - } - - bool decapsulate(Packet& pkt) // called by ProtoStackBase - { - try { - switch (proto.tls_wrap_mode) - { - case TLS_AUTH: - return decapsulate_tls_auth(pkt); - case TLS_CRYPT_V2: - if (pkt.opcode == CONTROL_HARD_RESET_CLIENT_V3) - { - // unwrap WKc and extract Kc (client key) from packet. - // This way we can initialize the tls-crypt per-client contexts - // (this happens on the server side only) - if (!unwrap_tls_crypt_wkc(*pkt.buf)) - { - return false; - } - } - // now that the tls-crypt contexts have been initialized it is - // possible to proceed with the standard tls-crypt decapsulation - /* no break */ - case TLS_CRYPT: - return decapsulate_tls_crypt(pkt); - case TLS_PLAIN: - return decapsulate_tls_plain(pkt); - } - } - catch (BufferException&) - { - proto.stats->error(Error::BUFFER_ERROR); - if (proto.is_tcp()) - invalidate(Error::BUFFER_ERROR); - } - return false; - } - - // for debugging - static const char *state_string(const int s) - { - switch (s) - { - case C_WAIT_RESET_ACK: - return "C_WAIT_RESET_ACK"; - case C_WAIT_AUTH_ACK: - return "C_WAIT_AUTH_ACK"; - case S_WAIT_RESET_ACK: - return "S_WAIT_RESET_ACK"; - case S_WAIT_AUTH_ACK: - return "S_WAIT_AUTH_ACK"; - case C_INITIAL: - return "C_INITIAL"; - case C_WAIT_RESET: - return "C_WAIT_RESET"; - case C_WAIT_AUTH: - return "C_WAIT_AUTH"; - case S_INITIAL: - return "S_INITIAL"; - case S_WAIT_RESET: - return "S_WAIT_RESET"; - case S_WAIT_AUTH: - return "S_WAIT_AUTH"; - case ACTIVE: - return "ACTIVE"; - default: - return "STATE_UNDEF"; - } - } - - // for debugging - int seconds_until(const Time& next_time) - { - Time::Duration d = next_time - *now; - if (d.is_infinite()) - return -1; - else - return d.to_seconds(); - } - - // BEGIN KeyContext data members - - ProtoContext& proto; // parent - int state; - unsigned int key_id_; - unsigned int crypto_flags; - int remote_peer_id; // -1 to disable - bool enable_op32; - bool dirty; - bool key_limit_renegotiation_fired; - bool is_reliable; - Compress::Ptr compress; - CryptoDCInstance::Ptr crypto; - TLSPRFInstance::Ptr tlsprf; - Time construct_time; - Time reached_active_time_; - Time next_event_time; - EventType current_event; - EventType next_event; - std::deque<BufferPtr> app_pre_write_queue; - std::unique_ptr<DataChannelKey> data_channel_key; - BufferComposed app_recv_buf; - std::unique_ptr<DataLimit> data_limit; - BufferAllocated work; - - // static member used by validate_tls_crypt() - static BufferAllocated static_work; - }; - - public: - class TLSWrapPreValidate : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSWrapPreValidate> Ptr; - - virtual bool validate(const BufferAllocated& net_buf) = 0; - }; - - // Validate the integrity of a packet, only considering tls-auth HMAC. - class TLSAuthPreValidate : public TLSWrapPreValidate - { - public: - OPENVPN_SIMPLE_EXCEPTION(tls_auth_pre_validate); - - TLSAuthPreValidate(const Config& c, const bool server) - { - if (!c.tls_auth_enabled()) - throw tls_auth_pre_validate(); - - // save hard reset op we expect to receive from peer - reset_op = server ? CONTROL_HARD_RESET_CLIENT_V2 : CONTROL_HARD_RESET_SERVER_V2; - - // init OvpnHMACInstance - ta_hmac_recv = c.tls_auth_context->new_obj(); - - // init tls_auth hmac - if (c.key_direction >= 0) - { - // key-direction is 0 or 1 - const unsigned int key_dir = c.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); - } - else - { - // key-direction bidirectional mode - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); - } - } - - bool validate(const BufferAllocated& net_buf) - { - try - { - if (!net_buf.size()) - return false; - - const unsigned int op = net_buf[0]; - if (opcode_extract(op) != reset_op || key_id_extract(op) != 0) - return false; - - return ta_hmac_recv->ovpn_hmac_cmp(net_buf.c_data(), net_buf.size(), - 1 + ProtoSessionID::SIZE, - ta_hmac_recv->output_size(), - PacketID::size(PacketID::LONG_FORM)); - } - catch (BufferException&) - { - } - - return false; - } - - private: - OvpnHMACInstance::Ptr ta_hmac_recv; - unsigned int reset_op; - }; - - class TLSCryptPreValidate : public TLSWrapPreValidate - { - public: - OPENVPN_SIMPLE_EXCEPTION(tls_crypt_pre_validate); - - TLSCryptPreValidate(const Config& c, const bool server) - { - if (!c.tls_crypt_enabled()) - throw tls_crypt_pre_validate(); - - // save hard reset op we expect to receive from peer - reset_op = server ? CONTROL_HARD_RESET_CLIENT_V2 : CONTROL_HARD_RESET_SERVER_V2; - - tls_crypt_recv = c.tls_crypt_context->new_obj_recv(); - - // static direction assignment - not user configurable - const unsigned int key_dir = server ? OpenVPNStaticKey::NORMAL : OpenVPNStaticKey::INVERSE; - tls_crypt_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir), - c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir)); - - // needed to create the decrypt buffer during validation - frame = c.frame; - } - - bool validate(const BufferAllocated& net_buf) - { - try - { - if (!net_buf.size()) - return false; - - const unsigned int op = net_buf[0]; - if (opcode_extract(op) != reset_op || key_id_extract(op) != 0) - return false; - - const size_t data_offset = TLSCryptContext::hmac_offset + tls_crypt_recv->output_hmac_size(); - if (net_buf.size() < data_offset) - return false; - - frame->prepare(Frame::DECRYPT_WORK, work); - - // decrypt payload from 'net_buf' into 'work' - const size_t decrypt_bytes = tls_crypt_recv->decrypt(net_buf.c_data() + TLSCryptContext::hmac_offset, - work.data(), work.max_size(), - net_buf.c_data() + data_offset, - net_buf.size() - data_offset); - if (!decrypt_bytes) - return false; - - work.inc_size(decrypt_bytes); - - // verify HMAC - return tls_crypt_recv->hmac_cmp(net_buf.c_data(), - TLSCryptContext::hmac_offset, - work.data(), work.size()); - } - catch (BufferException&) - { - } - return false; - } - - protected: - unsigned int reset_op; - - private: - TLSCryptInstance::Ptr tls_crypt_recv; - Frame::Ptr frame; - BufferAllocated work; - }; - - 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); - - ProtoContext(const Config::Ptr& config_arg, // configuration - const SessionStats::Ptr& stats_arg) // error stats - : config(config_arg), - stats(stats_arg), - mode_(config_arg->ssl_factory->mode()), - n_key_ids(0), - now_(config_arg->now) - { - const Config& c = *config; - - // tls-auth setup - if (c.tls_crypt_v2_enabled()) - { - tls_wrap_mode = TLS_CRYPT_V2; - - // get HMAC size from Digest object - hmac_size = c.tls_crypt_context->digest_size(); - } - else if (c.tls_crypt_enabled()) - { - tls_wrap_mode = TLS_CRYPT; - - // get HMAC size from Digest object - hmac_size = c.tls_crypt_context->digest_size(); - } - else if (c.tls_auth_enabled()) - { - tls_wrap_mode = TLS_AUTH; - - // get HMAC size from Digest object - hmac_size = c.tls_auth_context->size(); - } - else - { - tls_wrap_mode = TLS_PLAIN; - hmac_size = 0; - } - } - - uint32_t get_tls_warnings() const - { - if (primary) - return primary->get_tls_warnings(); - - OPENVPN_LOG("TLS: primary key context uninitialized. Can't retrieve TLS warnings"); - return 0; - } - - bool uses_bs64_cipher() const - { - return is_bs64_cipher(conf().dc.cipher()); - } - - void reset_tls_crypt(const Config& c, const OpenVPNStaticKey& key) - { - tls_crypt_send = c.tls_crypt_context->new_obj_send(); - tls_crypt_recv = c.tls_crypt_context->new_obj_recv(); - - // static direction assignment - not user configurable - unsigned int key_dir = is_server() ? - OpenVPNStaticKey::NORMAL : - OpenVPNStaticKey::INVERSE; - - tls_crypt_send->init(key.slice(OpenVPNStaticKey::HMAC | - OpenVPNStaticKey::ENCRYPT | key_dir), - key.slice(OpenVPNStaticKey::CIPHER | - OpenVPNStaticKey::ENCRYPT | key_dir)); - tls_crypt_recv->init(key.slice(OpenVPNStaticKey::HMAC | - OpenVPNStaticKey::DECRYPT | key_dir), - key.slice(OpenVPNStaticKey::CIPHER | - OpenVPNStaticKey::DECRYPT | key_dir)); - } - - void reset_tls_crypt_server(const Config& c) - { - //tls-crypt session key is derived later from WKc received from the client - tls_crypt_send.reset(); - tls_crypt_recv.reset(); - - //server context is used only to process incoming WKc's - tls_crypt_server = c.tls_crypt_context->new_obj_recv(); - - //the server key is composed by one key set only, therefore direction and - //mode should not be specified when slicing - tls_crypt_server->init(c.tls_key.slice(OpenVPNStaticKey::HMAC), - c.tls_key.slice(OpenVPNStaticKey::CIPHER)); - - tls_crypt_metadata = c.tls_crypt_metadata_factory->new_obj(); - } - - void reset() - { - const Config& c = *config; - - // defer data channel initialization until after client options pull? - dc_deferred = c.dc_deferred; - - // clear key contexts - reset_all(); - - // start with key ID 0 - upcoming_key_id = 0; - - unsigned int key_dir; - - // tls-auth initialization - switch (tls_wrap_mode) - { - case TLS_CRYPT: - reset_tls_crypt(c, c.tls_key); - // init tls_crypt packet ID - ta_pid_send.init(PacketID::LONG_FORM); - ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats); - break; - case TLS_CRYPT_V2: - if (is_server()) - // setup key to be used to unwrap WKc upon client connection. - // tls-crypt session key setup is postponed to reception of WKc - // from client - reset_tls_crypt_server(c); - else - reset_tls_crypt(c, c.tls_key); - // init tls_crypt packet ID - ta_pid_send.init(PacketID::LONG_FORM); - ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats); - break; - case TLS_AUTH: - // init OvpnHMACInstance - ta_hmac_send = c.tls_auth_context->new_obj(); - ta_hmac_recv = c.tls_auth_context->new_obj(); - - // init tls_auth hmac - if (c.key_direction >= 0) - { - // key-direction is 0 or 1 - key_dir = c.key_direction ? OpenVPNStaticKey::INVERSE : OpenVPNStaticKey::NORMAL; - ta_hmac_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir)); - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir)); - } - else - { - // key-direction bidirectional mode - ta_hmac_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); - ta_hmac_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC)); - } - - // init tls_auth packet ID - ta_pid_send.init(PacketID::LONG_FORM); - ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats); - break; - case TLS_PLAIN: - break; - } - - // initialize proto session ID - psid_self.randomize(*c.prng); - psid_peer.reset(); - - // initialize key contexts - primary.reset(new KeyContext(*this, is_client())); - OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " New KeyContext PRIMARY id=" << primary->key_id()); - - // initialize keepalive timers - keepalive_expire = Time::infinite(); // initially disabled - update_last_sent(); // set timer for initial keepalive send - } - - void set_protocol(const Protocol& p) - { - config->set_protocol(p); - if (primary) - primary->set_protocol(p); - if (secondary) - secondary->set_protocol(p); - } - - // Free up space when parent object has been halted but - // object destruction is not immediately scheduled. - void pre_destroy() - { - reset_all(); - } - - // Is primary key defined - bool primary_defined() - { - return bool(primary); - } - - virtual ~ProtoContext() {} - - // return the PacketType of an incoming network packet - PacketType packet_type(const Buffer& buf) - { - return PacketType(buf, *this); - } - - // start protocol negotiation - void start() - { - if (!primary) - throw proto_error("start: no primary key"); - primary->start(); - update_last_received(); // set an upper bound on when we expect a response - } - - // trigger a protocol renegotiation - void renegotiate() - { - // initialize secondary key context - new_secondary_key(true); - secondary->start(); - } - - // Should be called at the end of sequence of send/recv - // operations on underlying protocol object. - // If control_channel is true, do a full flush. - // If control_channel is false, optimize flush for data - // channel only. - void flush(const bool control_channel) - { - if (control_channel || process_events()) - { - do { - if (primary) - primary->flush(); - if (secondary) - secondary->flush(); - } while (process_events()); - } - } - - // Perform various time-based housekeeping tasks such as retransmiting - // unacknowleged packets as part of the reliability layer and testing - // for keepalive timouts. - // Should be called at the time returned by next_housekeeping. - void housekeeping() - { - // handle control channel retransmissions on primary - if (primary) - primary->retransmit(); - - // handle control channel retransmissions on secondary - if (secondary) - secondary->retransmit(); - - // handle possible events - flush(false); - - // handle keepalive/expiration - keepalive_housekeeping(); - } - - // When should we next call housekeeping? - // Will return a time value for immediate execution - // if session has been invalidated. - Time next_housekeeping() const - { - if (!invalidated()) - { - Time ret = Time::infinite(); - if (primary) - ret.min(primary->next_retransmit()); - if (secondary) - ret.min(secondary->next_retransmit()); - ret.min(keepalive_xmit); - ret.min(keepalive_expire); - return ret; - } - else - return Time(); - } - - // send app-level cleartext to remote peer - - void control_send(BufferPtr&& app_bp) - { - select_control_send_context().app_send(std::move(app_bp)); - } - - void control_send(BufferAllocated&& app_buf) - { - control_send(app_buf.move_to_ptr()); - } - - // validate a control channel network packet - bool control_net_validate(const PacketType& type, const Buffer& net_buf) - { - return type.is_defined() && KeyContext::validate(net_buf, *this, now_); - } - - // pass received control channel network packets (ciphertext) into protocol object - - bool control_net_recv(const PacketType& type, BufferAllocated&& net_buf) - { - Packet pkt(net_buf.move_to_ptr(), type.opcode); - if (type.is_soft_reset() && !renegotiate_request(pkt)) - return false; - return select_key_context(type, true).net_recv(std::move(pkt)); - } - - bool control_net_recv(const PacketType& type, BufferPtr&& net_bp) - { - Packet pkt(std::move(net_bp), type.opcode); - if (type.is_soft_reset() && !renegotiate_request(pkt)) - return false; - return select_key_context(type, true).net_recv(std::move(pkt)); - } - - // encrypt a data channel packet using primary KeyContext - void data_encrypt(BufferAllocated& in_out) - { - //OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " DATA ENCRYPT size=" << in_out.size()); - if (!primary) - throw proto_error("data_encrypt: no primary key"); - primary->encrypt(in_out); - } - - // decrypt a data channel packet (automatically select primary - // or secondary KeyContext based on packet content) - bool data_decrypt(const PacketType& type, BufferAllocated& in_out) - { - bool ret = false; - - //OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " DATA DECRYPT key_id=" << select_key_context(type, false).key_id() << " size=" << in_out.size()); - - select_key_context(type, false).decrypt(in_out); - - // update time of most recent packet received - if (in_out.size()) - { - update_last_received(); - ret = true; - } - - // discard keepalive packets - if (proto_context_private::is_keepalive(in_out)) - { - in_out.reset_size(); - } - - return ret; - } - - // enter disconnected state - void disconnect(const Error::Type reason) - { - if (primary) - primary->invalidate(reason); - if (secondary) - secondary->invalidate(reason); - } - - // normally used by UDP clients to tell the server that - // they are disconnecting - void send_explicit_exit_notify() - { - if (is_client() && is_udp() && primary) - primary->send_explicit_exit_notify(); - } - - // should be called after a successful network packet transmit - void update_last_sent() - { - keepalive_xmit = *now_ + config->keepalive_ping; - } - - // can we call data_encrypt or data_decrypt yet? - bool data_channel_ready() const { return primary && primary->data_channel_ready(); } - - // total number of SSL/TLS negotiations during lifetime of ProtoContext object - unsigned int negotiations() const { return n_key_ids; } - - // worst-case handshake time - const Time::Duration& slowest_handshake() { return slowest_handshake_; } - - // was primary context invalidated by an exception? - bool invalidated() const { return primary && primary->invalidated(); } - - // reason for invalidation if invalidated() above returns true - Error::Type invalidation_reason() const { return primary->invalidation_reason(); } - - // Do late initialization of data channel, for example - // on client after server push, or on server after client - // capabilities are known. - void init_data_channel() - { - dc_deferred = false; - - // initialize data channel (crypto & compression) - if (primary) - primary->init_data_channel(); - if (secondary) - secondary->init_data_channel(); - } - - // Call on client with server-pushed options - void process_push(const OptionList& opt, const ProtoContextOptions& pco) - { - // modify config with pushed options - config->process_push(opt, pco); - - // in case keepalive parms were modified by push - keepalive_parms_modified(); - } - - // Return the current transport alignment adjustment - size_t align_adjust_hint() const - { - return config->enable_op32 ? 0 : 1; - } - - // Return true if keepalive parameter(s) are enabled - bool is_keepalive_enabled() const - { - return config->keepalive_ping.enabled() - || config->keepalive_timeout.enabled(); - } - - // Disable keepalive for rest of session, - // but return the previous keepalive parameters. - void disable_keepalive(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) - { - keepalive_ping = config->keepalive_ping.enabled() ? config->keepalive_ping.to_seconds() : 0; - keepalive_timeout = config->keepalive_timeout.enabled() ? config->keepalive_timeout.to_seconds() : 0; - config->keepalive_ping = Time::Duration::infinite(); - config->keepalive_timeout = Time::Duration::infinite(); - keepalive_parms_modified(); - } - - // Notify our component KeyContext when per-key Data Limits have been reached - void data_limit_notify(const unsigned int key_id, - const DataLimit::Mode cdl_mode, - const DataLimit::State cdl_status) - { - if (primary && key_id == primary->key_id()) - primary->data_limit_notify(cdl_mode, cdl_status); - else if (secondary && key_id == secondary->key_id()) - secondary->data_limit_notify(cdl_mode, cdl_status); - } - - // access the data channel settings - CryptoDCSettings& dc_settings() - { - return config->dc; - } - - // reset the data channel factory - void reset_dc_factory() - { - config->dc.reset(); - } - - // set the local peer ID (or -1 to disable) - void set_local_peer_id(const int local_peer_id) - { - config->local_peer_id = local_peer_id; - } - - // current time - const Time& now() const { return *now_; } - void update_now() { now_->update(); } - - // frame - const Frame& frame() const { return *config->frame; } - const Frame::Ptr& frameptr() const { return config->frame; } - - // client or server? - const Mode& mode() const { return mode_; } - bool is_server() const { return mode_.is_server(); } - bool is_client() const { return mode_.is_client(); } - - // tcp/udp mode - bool is_tcp() { return config->protocol.is_tcp(); } - bool is_udp() { return config->protocol.is_udp(); } - - // configuration - const Config& conf() const { return *config; } - Config& conf() { return *config; } - Config::Ptr conf_ptr() const { return config; } - - // stats - SessionStats& stat() const { return *stats; } - - private: - - // TLS wrapping mode for the control channel - enum TLSWrapMode { - TLS_PLAIN, - TLS_AUTH, - TLS_CRYPT, - TLS_CRYPT_V2 - }; - - void reset_all() - { - if (primary) - primary->rekey(CryptoDCInstance::DEACTIVATE_ALL); - primary.reset(); - secondary.reset(); - } - - virtual void control_net_send(const Buffer& net_buf) = 0; - - // app may take ownership of app_bp via std::move - virtual void control_recv(BufferPtr&& app_bp) = 0; - - // Called on client to request username/password credentials. - // Should be overriden by derived class if credentials are required. - // username and password should be written into buf with write_auth_string(). - virtual void client_auth(Buffer& buf) - { - write_empty_string(buf); // username - write_empty_string(buf); // password - } - - // Called on server with credentials and peer info provided by client. - // Should be overriden by derived class if credentials are required. - virtual void server_auth(const std::string& username, - const SafeString& password, - const std::string& peer_info, - const AuthCert::Ptr& auth_cert) - { - } - - // Called when initial KeyContext transitions to ACTIVE state - virtual void active() - { - } - - void update_last_received() - { - keepalive_expire = *now_ + config->keepalive_timeout; - } - - void net_send(const unsigned int key_id, const Packet& net_pkt) - { - control_net_send(net_pkt.buffer()); - } - - void app_recv(const unsigned int key_id, BufferPtr&& to_app_buf) - { - control_recv(std::move(to_app_buf)); - } - - // we're getting a request from peer to renegotiate. - bool renegotiate_request(Packet& pkt) - { - if (KeyContext::validate(pkt.buffer(), *this, now_)) - { - new_secondary_key(false); - return true; - } - else - return false; - } - - // select a KeyContext (primary or secondary) for received network packets - KeyContext& select_key_context(const PacketType& type, const bool control) - { - const unsigned int flags = type.flags & (PacketType::DEFINED|PacketType::SECONDARY|PacketType::CONTROL); - if (!control) - { - if (flags == (PacketType::DEFINED) && primary) - return *primary; - else if (flags == (PacketType::DEFINED|PacketType::SECONDARY) && secondary) - return *secondary; - } - else - { - if (flags == (PacketType::DEFINED|PacketType::CONTROL) && primary) - return *primary; - else if (flags == (PacketType::DEFINED|PacketType::SECONDARY|PacketType::CONTROL) && secondary) - return *secondary; - } - throw select_key_context_error(); - } - - // Select a KeyContext (primary or secondary) for control channel sends. - // Even after new key context goes active, we still wait for - // KEV_BECOME_PRIMARY event (controlled by the become_primary duration - // in Config) before we use it for app-level control-channel - // transmissions. Simulations have found this method to be more reliable - // than the immediate rollover practiced by OpenVPN 2.x. - KeyContext& select_control_send_context() - { - OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " CONTROL SEND"); - if (!primary) - throw proto_error("select_control_send_context: no primary key"); - return *primary; - } - - // Possibly send a keepalive message, and check for expiration - // of session due to lack of received packets from peer. - void keepalive_housekeeping() - { - const Time now = *now_; - - // check for keepalive timeouts - if (now >= keepalive_xmit && primary) - { - primary->send_keepalive(); - update_last_sent(); - } - if (now >= keepalive_expire) - { - // no contact with peer, disconnect - stats->error(Error::KEEPALIVE_TIMEOUT); - disconnect(Error::KEEPALIVE_TIMEOUT); - } - } - - // Process KEV_x events - // Return true if any events were processed. - bool process_events() - { - bool did_work = false; - - // primary - if (primary && primary->event_pending()) - { - process_primary_event(); - did_work = true; - } - - // secondary - if (secondary && secondary->event_pending()) - { - process_secondary_event(); - did_work = true; - } - - return did_work; - } - - // Create a new secondary key. - // initiator -- - // false : remote renegotiation request - // true : local renegotiation request - void new_secondary_key(const bool initiator) - { - // Create the secondary - secondary.reset(new KeyContext(*this, initiator)); - OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " New KeyContext SECONDARY id=" << secondary->key_id() << (initiator ? " local-triggered" : " remote-triggered")); - } - - // Promote a newly renegotiated KeyContext to primary status. - // This is usually triggered by become_primary variable (Time::Duration) - // in Config. - void promote_secondary_to_primary() - { - primary.swap(secondary); - if (primary) - primary->rekey(CryptoDCInstance::PRIMARY_SECONDARY_SWAP); - if (secondary) - secondary->prepare_expire(); - OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " PRIMARY_SECONDARY_SWAP"); - } - - void process_primary_event() - { - const KeyContext::EventType ev = primary->get_event(); - if (ev != KeyContext::KEV_NONE) - { - primary->reset_event(); - switch (ev) - { - case KeyContext::KEV_ACTIVE: - OPENVPN_LOG_PROTO_VERBOSE(debug_prefix() << " SESSION_ACTIVE"); - primary->rekey(CryptoDCInstance::ACTIVATE_PRIMARY); - active(); - break; - case KeyContext::KEV_RENEGOTIATE: - case KeyContext::KEV_RENEGOTIATE_FORCE: - renegotiate(); - break; - case KeyContext::KEV_EXPIRE: - if (secondary && !secondary->invalidated()) - promote_secondary_to_primary(); - else - { - stats->error(Error::PRIMARY_EXPIRE); - disconnect(Error::PRIMARY_EXPIRE); // primary context expired and no secondary context available - } - break; - case KeyContext::KEV_NEGOTIATE: - stats->error(Error::HANDSHAKE_TIMEOUT); - disconnect(Error::HANDSHAKE_TIMEOUT); // primary negotiation failed - break; - default: - break; - } - } - primary->set_next_event_if_unspecified(); - } - - void process_secondary_event() - { - const KeyContext::EventType ev = secondary->get_event(); - if (ev != KeyContext::KEV_NONE) - { - secondary->reset_event(); - switch (ev) - { - case KeyContext::KEV_ACTIVE: - secondary->rekey(CryptoDCInstance::NEW_SECONDARY); - if (primary) - primary->prepare_expire(); - break; - case KeyContext::KEV_BECOME_PRIMARY: - if (!secondary->invalidated()) - promote_secondary_to_primary(); - break; - case KeyContext::KEV_EXPIRE: - secondary->rekey(CryptoDCInstance::DEACTIVATE_SECONDARY); - secondary.reset(); - break; - case KeyContext::KEV_RENEGOTIATE_QUEUE: - if (primary) - primary->key_limit_reneg(KeyContext::KEV_RENEGOTIATE_FORCE, secondary->become_primary_time()); - break; - case KeyContext::KEV_NEGOTIATE: - stats->error(Error::HANDSHAKE_TIMEOUT); - case KeyContext::KEV_PRIMARY_PENDING: - case KeyContext::KEV_RENEGOTIATE_FORCE: - renegotiate(); - break; - default: - break; - } - } - if (secondary) - secondary->set_next_event_if_unspecified(); - } - - std::string debug_prefix() - { - std::string ret = openvpn::to_string(now_->raw()); - ret += is_server() ? " SERVER[" : " CLIENT["; - if (primary) - ret += openvpn::to_string(primary->key_id()); - if (secondary) - { - ret += '/'; - ret += openvpn::to_string(secondary->key_id()); - } - ret += ']'; - return ret; - } - - // key_id starts at 0, increments to KEY_ID_MASK, then recycles back to 1. - // Therefore, if key_id is 0, it is the first key. - unsigned int next_key_id() - { - ++n_key_ids; - unsigned int ret = upcoming_key_id; - if ((upcoming_key_id = (upcoming_key_id + 1) & KEY_ID_MASK) == 0) - upcoming_key_id = 1; - return ret; - } - - // call whenever keepalive parms are modified, - // to reset timers - void keepalive_parms_modified() - { - update_last_received(); - - // For keepalive_xmit timer, don't reschedule current cycle - // unless it would fire earlier. Subsequent cycles will - // time according to new keepalive_ping value. - const Time kx = *now_ + config->keepalive_ping; - if (kx < keepalive_xmit) - keepalive_xmit = kx; - } - - void tls_crypt_append_wkc(BufferAllocated& dst) - { - if (!config->wkc.defined()) - throw proto_error("Client Key Wrapper undefined"); - dst.append(config->wkc); - } - - // BEGIN ProtoContext data members - - Config::Ptr config; - SessionStats::Ptr stats; - - size_t hmac_size; - TLSWrapMode tls_wrap_mode; - Mode mode_; // client or server - unsigned int upcoming_key_id; - unsigned int n_key_ids; - - TimePtr now_; // pointer to current time (a clone of config->now) - Time keepalive_xmit; // time in future when we will transmit a keepalive (subject to continuous change) - Time keepalive_expire; // time in future when we must have received a packet from peer or we will timeout session - - Time::Duration slowest_handshake_; // longest time to reach a successful handshake - - OvpnHMACInstance::Ptr ta_hmac_send; - OvpnHMACInstance::Ptr ta_hmac_recv; - - TLSCryptInstance::Ptr tls_crypt_send; - TLSCryptInstance::Ptr tls_crypt_recv; - - TLSCryptInstance::Ptr tls_crypt_server; - TLSCryptMetadata::Ptr tls_crypt_metadata; - - PacketIDSend ta_pid_send; - PacketIDReceive ta_pid_recv; - - ProtoSessionID psid_self; - ProtoSessionID psid_peer; - - KeyContext::Ptr primary; - KeyContext::Ptr secondary; - bool dc_deferred; - - // END ProtoContext data members - }; - -} // namespace openvpn - -#endif //OPENVPN_SSL_PROTO_H diff --git a/Sources/OpenVPN3/openvpn/ssl/proto_context_options.hpp b/Sources/OpenVPN3/openvpn/ssl/proto_context_options.hpp deleted file mode 100644 index 3030174..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/proto_context_options.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// 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-2020 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/>. - -// Helper class to parse certain options needed by ProtoContext. - -#ifndef OPENVPN_SSL_PROTO_CONTEXT_OPTIONS_H -#define OPENVPN_SSL_PROTO_CONTEXT_OPTIONS_H - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - struct ProtoContextOptions : public RC<thread_safe_refcount> - { - typedef RCPtr<ProtoContextOptions> Ptr; - - enum CompressionMode { - COMPRESS_NO, - COMPRESS_YES, - COMPRESS_ASYM - }; - - ProtoContextOptions() : compression_mode(COMPRESS_NO) {} - - bool is_comp() const { return compression_mode != COMPRESS_NO; } - bool is_comp_asym() const { return compression_mode == COMPRESS_ASYM; } - - void parse_compression_mode(const std::string& mode) - { - if (mode == "no") - compression_mode = COMPRESS_NO; - else if (mode == "yes") - compression_mode = COMPRESS_YES; - else if (mode == "asym") - compression_mode = COMPRESS_ASYM; - else - OPENVPN_THROW(option_error, "error parsing compression mode: " << mode); - } - - CompressionMode compression_mode; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/protostack.hpp b/Sources/OpenVPN3/openvpn/ssl/protostack.hpp deleted file mode 100644 index e617a2a..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/protostack.hpp +++ /dev/null @@ -1,493 +0,0 @@ -// 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-2020 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_SSL_PROTOSTACK_H -#define OPENVPN_SSL_PROTOSTACK_H - -#include <deque> -#include <utility> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/usecount.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/reliable/relrecv.hpp> -#include <openvpn/reliable/relsend.hpp> -#include <openvpn/reliable/relack.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/error/excode.hpp> -#include <openvpn/ssl/sslconsts.hpp> -#include <openvpn/ssl/sslapi.hpp> - -// ProtoStackBase is designed to allow general-purpose protocols (including -// but not limited to OpenVPN) to run over SSL, where the underlying transport -// layer is unreliable, such as UDP. The OpenVPN protocol implementation in -// proto.hpp (ProtoContext) layers on top of ProtoStackBase. -// ProtoStackBase is independent of any particular SSL implementation, and -// accepts the SSL object type as a template parameter. - -namespace openvpn { - - // PACKET type must define the following methods: - // - // Default constructor: - // PACKET() - // - // Constructor for BufferPtr: - // explicit PACKET(const BufferPtr& buf) - // - // Test if defined: - // operator bool() const - // - // Return true if packet is raw, or false if packet is SSL ciphertext: - // bool is_raw() const - // - // Reset back to post-default-constructor state: - // void reset() - // - // Return internal BufferPtr: - // const BufferPtr& buffer_ptr() const - // - // Call frame.prepare on internal buffer: - // void frame_prepare(const Frame& frame, const unsigned int context) - - template <typename PACKET, typename PARENT> - class ProtoStackBase - { - public: - typedef reliable::id_t id_t; - typedef ReliableSendTemplate<PACKET> ReliableSend; - typedef ReliableRecvTemplate<PACKET> ReliableRecv; - - OPENVPN_SIMPLE_EXCEPTION(proto_stack_invalidated); - OPENVPN_SIMPLE_EXCEPTION(unknown_status_from_ssl_layer); - - enum NetSendType { - NET_SEND_SSL, - NET_SEND_RAW, - NET_SEND_ACK, - NET_SEND_RETRANSMIT, - }; - - ProtoStackBase(SSLFactoryAPI& ssl_factory, // SSL factory object that can be used to generate new SSL sessions - TimePtr now_arg, // pointer to current time - const Time::Duration& tls_timeout_arg, // packet retransmit timeout - const Frame::Ptr& frame, // contains info on how to allocate and align buffers - const SessionStats::Ptr& stats_arg, // error statistics - const id_t span, // basically the window size for our reliability layer - const size_t max_ack_list) // maximum number of ACK messages to bundle in one packet - : tls_timeout(tls_timeout_arg), - ssl_(ssl_factory.ssl()), - frame_(frame), - up_stack_reentry_level(0), - invalidated_(false), - invalidation_reason_(Error::SUCCESS), - ssl_started_(false), - next_retransmit_(Time::infinite()), - stats(stats_arg), - now(now_arg), - rel_recv(span), - rel_send(span), - xmit_acks(max_ack_list) - { - } - - // Start SSL handshake on underlying SSL connection object. - void start_handshake() - { - if (!invalidated()) - { - ssl_->start_handshake(); - ssl_started_ = true; - up_sequenced(); - } - } - - uint32_t get_tls_warnings() const - { - return ssl_->get_tls_warnings(); - } - - // Incoming ciphertext packet arriving from network, - // we will take ownership of pkt. - bool net_recv(PACKET&& pkt) - { - if (!invalidated()) - return up_stack(pkt); - return false; - } - - // Outgoing application-level cleartext packet ready to send - // (will be encrypted via SSL), we will take ownership - // of buf. - void app_send(BufferPtr&& buf) - { - if (!invalidated()) - app_write_queue.push_back(std::move(buf)); - } - - // Outgoing raw packet ready to send (will NOT be encrypted - // via SSL, but will still be encapsulated, sequentialized, - // and tracked via reliability layer). - void raw_send(PACKET&& pkt) - { - if (!invalidated()) - raw_write_queue.push_back(std::move(pkt)); - } - - // Write any pending data to network and update retransmit - // timer. Should be called as a final step after one or more - // net_recv, app_send, raw_send, or start_handshake calls. - void flush() - { - if (!invalidated() && !up_stack_reentry_level) - { - down_stack_raw(); - down_stack_app(); - update_retransmit(); - } - } - - // Send pending ACKs back to sender for packets already received - void send_pending_acks() - { - if (!invalidated()) - { - while (!xmit_acks.empty()) - { - ack_send_buf.frame_prepare(*frame_, Frame::WRITE_ACK_STANDALONE); - - // encapsulate standalone ACK - parent().generate_ack(ack_send_buf); - - // transmit it - parent().net_send(ack_send_buf, NET_SEND_ACK); - } - } - } - - // Send any pending retransmissions - void retransmit() - { - if (!invalidated() && *now >= next_retransmit_) - { - for (id_t i = rel_send.head_id(); i < rel_send.tail_id(); ++i) - { - typename ReliableSend::Message& m = rel_send.ref_by_id(i); - if (m.ready_retransmit(*now)) - { - parent().net_send(m.packet, NET_SEND_RETRANSMIT); - m.reset_retransmit(*now, tls_timeout); - } - } - update_retransmit(); - } - } - - // When should we next call retransmit() - Time next_retransmit() const - { - if (!invalidated()) - return next_retransmit_; - else - return Time::infinite(); - } - - // Has SSL handshake been started yet? - bool ssl_started() const { return ssl_started_; } - - // Was session invalidated by an exception? - bool invalidated() const { return invalidated_; } - - // Reason for invalidation - Error::Type invalidation_reason() const { return invalidation_reason_; } - - // Invalidate session - void invalidate(const Error::Type reason) - { - if (!invalidated_) - { - invalidated_ = true; - invalidation_reason_ = reason; - parent().invalidate_callback(); - } - } - - std::string ssl_handshake_details() const - { - return ssl_->ssl_handshake_details(); - } - - void export_key_material(OpenVPNStaticKey& key) const - { - if (!ssl_->export_keying_material("EXPORTER-OpenVPN-datakeys", key.raw_alloc(), - OpenVPNStaticKey::KEY_SIZE)) - throw ErrorCode(Error::KEY_EXPANSION_ERROR, true, "TLS Keying material export error"); - } - - const AuthCert::Ptr& auth_cert() const - { - return ssl_->auth_cert(); - } - - private: - // Parent methods -- derived class must define these methods - - // Encapsulate packet, use id as sequence number. If xmit_acks is non-empty, - // try to piggy-back ACK replies from xmit_acks to sender in encapsulated - // packet. Any exceptions thrown will invalidate session, i.e. this object - // can no longer be used. - // - // void encapsulate(id_t id, PACKET& pkt) = 0; - - // Perform integrity check on packet. If packet is good, unencapsulate it and - // pass it into the rel_recv object. Any ACKs received for messages previously - // sent should be marked in rel_send. Message sequence number should be recorded - // in xmit_acks. Exceptions may be thrown here and they will be passed up to - // caller of net_recv and will not invalidate the session. - // Method should return true if packet was placed into rel_recv. - // - // bool decapsulate(PACKET& pkt) = 0; - - // Generate a standalone ACK message in buf based on ACKs in xmit_acks - // (PACKET will be already be initialized by frame_prepare()). - // - // void generate_ack(PACKET& pkt) = 0; - - // Transmit encapsulated ciphertext packet to peer. Method may not modify - // or take ownership of net_pkt or underlying data unless it copies it. - // - // void net_send(const PACKET& net_pkt, const NetSendType nstype) = 0; - - // Pass cleartext data up to application, which make take - // ownership of to_app_buf via std::move. - // - // void app_recv(BufferPtr&& to_app_buf) = 0; - - // Pass raw data up to application. A packet is considered to be raw - // if is_raw() method returns true. Method may take ownership - // of raw_pkt via std::move. - // - // void raw_recv(PACKET&& raw_pkt) = 0; - - // called if session is invalidated by an error (optional) - // - // void invalidate_callback() {} - - // END of parent methods - - // get reference to parent for CRTP - PARENT& parent() - { - return *static_cast<PARENT*>(this); - } - - // app data -> SSL -> protocol encapsulation -> reliability layer -> network - void down_stack_app() - { - if (ssl_started_) - { - // push app-layer cleartext through SSL object - while (!app_write_queue.empty()) - { - BufferPtr& buf = app_write_queue.front(); - ssize_t size; - try { - size = ssl_->write_cleartext_unbuffered(buf->data(), buf->size()); - } - catch (...) - { - error(Error::SSL_ERROR); - throw; - } - if (size == static_cast<ssize_t>(buf->size())) - app_write_queue.pop_front(); - else if (size == SSLConst::SHOULD_RETRY) - break; - else if (size >= 0) - { - // partial write - app_write_queue.front()->advance(size); - break; - } - else - { - error(Error::SSL_ERROR); - throw unknown_status_from_ssl_layer(); - } - } - - // encapsulate SSL ciphertext packets - while (ssl_->read_ciphertext_ready() && rel_send.ready()) - { - typename ReliableSend::Message& m = rel_send.send(*now, tls_timeout); - m.packet = PACKET(ssl_->read_ciphertext()); - - // encapsulate packet - try { - parent().encapsulate(m.id(), m.packet); - } - catch (...) - { - error(Error::ENCAPSULATION_ERROR); - throw; - } - - // transmit it - parent().net_send(m.packet, NET_SEND_SSL); - } - } - } - - // raw app data -> protocol encapsulation -> reliability layer -> network - void down_stack_raw() - { - while (!raw_write_queue.empty() && rel_send.ready()) - { - typename ReliableSend::Message& m = rel_send.send(*now, tls_timeout); - m.packet = raw_write_queue.front(); - raw_write_queue.pop_front(); - - // encapsulate packet - try { - parent().encapsulate(m.id(), m.packet); - } - catch (...) - { - error(Error::ENCAPSULATION_ERROR); - throw; - } - - // transmit it - parent().net_send(m.packet, NET_SEND_RAW); - } - } - - // network -> reliability layer -> protocol decapsulation -> SSL -> app - bool up_stack(PACKET& recv) - { - UseCount use_count(up_stack_reentry_level); - if (parent().decapsulate(recv)) - { - up_sequenced(); - return true; - } - else - return false; - } - - // if a sequenced packet is available from reliability layer, - // move it up the stack - void up_sequenced() - { - // is sequenced receive packet available? - while (rel_recv.ready()) - { - typename ReliableRecv::Message& m = rel_recv.next_sequenced(); - if (m.packet.is_raw()) - parent().raw_recv(std::move(m.packet)); - else // SSL packet - { - if (ssl_started_) - ssl_->write_ciphertext(m.packet.buffer_ptr()); - else - break; - } - rel_recv.advance(); - } - - // read cleartext data from SSL object - if (ssl_started_) - while (ssl_->read_cleartext_ready()) - { - ssize_t size; - to_app_buf.reset(new BufferAllocated()); - frame_->prepare(Frame::READ_SSL_CLEARTEXT, *to_app_buf); - try { - size = ssl_->read_cleartext(to_app_buf->data(), to_app_buf->max_size()); - } - catch (...) - { - // SSL fatal errors will invalidate the session - error(Error::SSL_ERROR); - throw; - } - if (size >= 0) - { - to_app_buf->set_size(size); - - // pass cleartext data to app - parent().app_recv(std::move(to_app_buf)); - } - else if (size == SSLConst::SHOULD_RETRY) - break; - else if (size == SSLConst::PEER_CLOSE_NOTIFY) - { - error(Error::SSL_ERROR); - throw ErrorCode(Error::CLIENT_HALT, true, "SSL Close Notify received"); - } - else - { - error(Error::SSL_ERROR); - throw unknown_status_from_ssl_layer(); - } - } - } - - void update_retransmit() - { - next_retransmit_ = *now + rel_send.until_retransmit(*now); - } - - void error(const Error::Type reason) - { - if (stats) - stats->error(reason); - invalidate(reason); - } - - private: - const Time::Duration tls_timeout; - typename SSLAPI::Ptr ssl_; - Frame::Ptr frame_; - int up_stack_reentry_level; - bool invalidated_; - Error::Type invalidation_reason_; - bool ssl_started_; - Time next_retransmit_; - BufferPtr to_app_buf; // cleartext data decrypted by SSL that is to be passed to app via app_recv method - PACKET ack_send_buf; // only used for standalone ACKs to be sent to peer - std::deque<BufferPtr> app_write_queue; - std::deque<PACKET> raw_write_queue; - SessionStats::Ptr stats; - - protected: - TimePtr now; - ReliableRecv rel_recv; - ReliableSend rel_send; - ReliableAck xmit_acks; - }; - -} // namespace openvpn - -#endif // OPENVPN_SSL_PROTOSTACK_H diff --git a/Sources/OpenVPN3/openvpn/ssl/psid.hpp b/Sources/OpenVPN3/openvpn/ssl/psid.hpp deleted file mode 100644 index 1b18377..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/psid.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// 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-2020 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/>. - -// A 64-bit session ID, used by ProtoContext. - -#ifndef OPENVPN_SSL_PSID_H -#define OPENVPN_SSL_PSID_H - -#include <string> -#include <cstring> - -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/memneq.hpp> - -namespace openvpn { - - class ProtoSessionID - { - public: - enum { - SIZE=8 - }; - - ProtoSessionID() - { - reset(); - } - - void reset() - { - defined_ = false; - std::memset(id_, 0, SIZE); - } - - explicit ProtoSessionID(Buffer& buf) - { - buf.read(id_, SIZE); - defined_ = true; - } - - template <typename PRNG_TYPE> - void randomize(PRNG_TYPE& prng) - { - prng.assert_crypto(); - prng.rand_bytes(id_, SIZE); - defined_ = true; - } - - void read(Buffer& buf) - { - buf.read(id_, SIZE); - defined_ = true; - } - - void write(Buffer& buf) const - { - buf.write(id_, SIZE); - } - - void prepend(Buffer& buf) const - { - buf.prepend(id_, SIZE); - } - - bool defined() const { return defined_; } - - bool match(const ProtoSessionID& other) const - { - return defined_ && other.defined_ && !crypto::memneq(id_, other.id_, SIZE); - } - - std::string str() const - { - return render_hex(id_, SIZE); - } - - protected: - ProtoSessionID(const unsigned char *data) - { - std::memcpy(id_, data, SIZE); - } - - private: - bool defined_; - unsigned char id_[SIZE]; - }; -} // namespace openvpn - -#endif // OPENVPN_SSL_PSID_H diff --git a/Sources/OpenVPN3/openvpn/ssl/sess_ticket.hpp b/Sources/OpenVPN3/openvpn/ssl/sess_ticket.hpp deleted file mode 100644 index cf60345..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sess_ticket.hpp +++ /dev/null @@ -1,242 +0,0 @@ -// 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-2020 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 <cstring> -#include <memory> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hash.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - class OpenSSLContext; - class MbedTLSContext; - - // Abstract base class used to provide an interface for TLS - // Session Ticket keying originally described by RFC 5077. - class TLSSessionTicketBase - { - public: - typedef std::unique_ptr<TLSSessionTicketBase> UPtr; - - OPENVPN_EXCEPTION(sess_ticket_error); - - enum Status { - NO_TICKET, - TICKET_AVAILABLE, - TICKET_EXPIRING, - }; - - class Name - { - public: - static constexpr size_t SIZE = 16; - - explicit Name(RandomAPI& rng) - { - rng.rand_bytes(value_, SIZE); - } - - explicit Name(const std::string& name_b64) - { - b64_to_key(name_b64, "key name", value_, SIZE); - } - - explicit Name(const unsigned char name[SIZE]) - { - std::memcpy(value_, name, SIZE); - } - - bool operator==(const Name& rhs) const - { - return std::memcmp(value_, rhs.value_, SIZE) == 0; - } - - bool operator!=(const Name& rhs) const - { - return std::memcmp(value_, rhs.value_, SIZE) != 0; - } - - bool operator<(const Name& rhs) const - { - return std::memcmp(value_, rhs.value_, SIZE) < 0; - } - - std::string to_string() const - { - return "TLSTicketName[" + b64() + ']'; - } - - std::string b64() const - { - return base64->encode(value_, SIZE); - } - - template <typename HASH> - void hash(HASH& h) const - { - h(value_, SIZE); - } - -#ifdef HAVE_CITYHASH - std::size_t hashval() const - { - HashSizeT h; - hash(h); - return h.value(); - } -#endif - - private: - // we need to friend SSL implementation classes - friend class OpenSSLContext; - friend class MbedTLSContext; - - Name() {} // note that default constructor leaves object in an undefined state - - unsigned char value_[SIZE]; - }; - - class Key - { - public: - static constexpr size_t CIPHER_KEY_SIZE = 32; - static constexpr size_t HMAC_KEY_SIZE = 16; - - explicit Key(RandomAPI& rng) - { - rng.assert_crypto(); - rng.rand_bytes(cipher_value_, CIPHER_KEY_SIZE); - rng.rand_bytes(hmac_value_, HMAC_KEY_SIZE); - } - - explicit Key(const std::string& cipher_key_b64, const std::string& hmac_key_b64) - { - b64_to_key(cipher_key_b64, "cipher key", cipher_value_, CIPHER_KEY_SIZE); - b64_to_key(hmac_key_b64, "hmac key", hmac_value_, HMAC_KEY_SIZE); - } - - ~Key() - { - // wipe keys - std::memset(cipher_value_, 0, CIPHER_KEY_SIZE); - std::memset(hmac_value_, 0, HMAC_KEY_SIZE); - } - - std::string to_string() const - { - return "TLSTicketKey[cipher=" + cipher_b64() + " hmac=" + hmac_b64() + ']'; - } - - std::string cipher_b64() const - { - return base64->encode(cipher_value_, CIPHER_KEY_SIZE); - } - - std::string hmac_b64() const - { - return base64->encode(hmac_value_, HMAC_KEY_SIZE); - } - - bool operator==(const Key& rhs) const - { - return std::memcmp(cipher_value_, rhs.cipher_value_, CIPHER_KEY_SIZE) == 0 && std::memcmp(hmac_value_, rhs.hmac_value_, HMAC_KEY_SIZE) == 0; - } - - bool operator!=(const Key& rhs) const - { - return !operator==(rhs); - } - - template <typename KEY_TRANSFORM> - void key_transform(KEY_TRANSFORM& t) - { - unsigned char out[KEY_TRANSFORM::MAX_HMAC_SIZE]; - - // cipher - { - t.cipher_transform.reset(); - t.cipher_transform.update(cipher_value_, CIPHER_KEY_SIZE); - const size_t size = t.cipher_transform.final(out); - if (size < CIPHER_KEY_SIZE) - throw sess_ticket_error("insufficient key material for cipher transform"); - std::memcpy(cipher_value_, out, CIPHER_KEY_SIZE); - } - - // hmac - { - t.hmac_transform.reset(); - t.hmac_transform.update(hmac_value_, HMAC_KEY_SIZE); - const size_t size = t.hmac_transform.final(out); - if (size < HMAC_KEY_SIZE) - throw sess_ticket_error("insufficient key material for hmac transform"); - std::memcpy(hmac_value_, out, HMAC_KEY_SIZE); - } - } - - private: - // we need to friend SSL implementation classes - friend class OpenSSLContext; - friend class MbedTLSContext; - - Key() {} // note that default constructor leaves object in an undefined state - - unsigned char cipher_value_[CIPHER_KEY_SIZE]; - unsigned char hmac_value_[HMAC_KEY_SIZE]; - }; - - // method returns name and key - virtual Status create_session_ticket_key(Name& name, Key& key) const = 0; - - // method is given name and returns key - virtual Status lookup_session_ticket_key(const Name& name, Key& key) const = 0; - - // return string that identifies the app - virtual std::string session_id_context() const = 0; - - virtual ~TLSSessionTicketBase() {} - - private: - static void b64_to_key(const std::string& b64, const char *title, unsigned char *out, const size_t outlen) - { - Buffer srcbuf(out, outlen, false); - try { - base64->decode(srcbuf, b64); - } - catch (const std::exception& e) - { - throw sess_ticket_error(std::string("base64 decode for ") + title + ": " + std::string(e.what())); - } - if (srcbuf.size() != outlen) - throw sess_ticket_error(std::string("wrong input size for ") + title + ", actual=" + std::to_string(srcbuf.size()) + " expected=" + std::to_string(outlen)); - } - }; -} - -#ifdef HAVE_CITYHASH -OPENVPN_HASH_METHOD(openvpn::TLSSessionTicketBase::Name, hashval); -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/sni_handler.hpp b/Sources/OpenVPN3/openvpn/ssl/sni_handler.hpp deleted file mode 100644 index 6a2567d..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sni_handler.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// 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-2020 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 <memory> - -#include <openvpn/ssl/sslapi.hpp> -#include <openvpn/ssl/sni_metadata.hpp> - -namespace openvpn { - namespace SNI { - - // Abstract base class used to provide an SNI handler - class HandlerBase - { - public: - typedef std::unique_ptr<HandlerBase> UPtr; - - // Return a new SSLFactoryAPI for this SNI name. - // Implementation may also set sni_metadata. - // Return SSLFactoryAPI::Ptr() if sni_name is not recognized. - // The caller guarantees that sni_name is valid UTF-8 and - // doesn't contain any control characters. - virtual SSLFactoryAPI::Ptr sni_hello(const std::string& sni_name, - SNI::Metadata::UPtr& sni_metadata, - SSLConfigAPI::Ptr default_factory) const = 0; - - virtual ~HandlerBase() {} - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/ssl/sni_metadata.hpp b/Sources/OpenVPN3/openvpn/ssl/sni_metadata.hpp deleted file mode 100644 index 8c8dbb5..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sni_metadata.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// 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-2020 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 <memory> - -namespace openvpn { - - class AuthCert; - - namespace SNI { - - class Metadata - { - public: - typedef std::unique_ptr<Metadata> UPtr; - - virtual std::string sni_client_name(const AuthCert& ac) const = 0; - - virtual ~Metadata() = default; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/ssl/sslapi.hpp b/Sources/OpenVPN3/openvpn/ssl/sslapi.hpp deleted file mode 100644 index 856da9e..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sslapi.hpp +++ /dev/null @@ -1,202 +0,0 @@ -// 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-2020 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/>. - -// API for SSL implementations - -#ifndef OPENVPN_SSL_SSLAPI_H -#define OPENVPN_SSL_SSLAPI_H - -#include <string> -#include <cstdint> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/mode.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/auth/authcert.hpp> -#include <openvpn/pki/epkibase.hpp> -#include <openvpn/pki/pktype.hpp> -#include <openvpn/ssl/kuparse.hpp> -#include <openvpn/ssl/nscert.hpp> -#include <openvpn/ssl/tlsver.hpp> -#include <openvpn/ssl/tls_remote.hpp> -#include <openvpn/ssl/tls_cert_profile.hpp> -#include <openvpn/ssl/sess_ticket.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - namespace SNI { - class HandlerBase; - } - - class SSLAPI : public RC<thread_unsafe_refcount> - { - public: - - enum TLSWarnings { - TLS_WARN_NONE = 0, - TLS_WARN_SIG_MD5 = (1 << 0), - TLS_WARN_SIG_SHA1 = (1 << 1) - }; - - typedef RCPtr<SSLAPI> Ptr; - - virtual void start_handshake() = 0; - virtual ssize_t write_cleartext_unbuffered(const void *data, const size_t size) = 0; - virtual ssize_t read_cleartext(void *data, const size_t capacity) = 0; - virtual bool read_cleartext_ready() const = 0; - virtual void write_ciphertext(const BufferPtr& buf) = 0; - virtual void write_ciphertext_unbuffered(const unsigned char *data, const size_t size) = 0; - virtual bool read_ciphertext_ready() const = 0; - virtual BufferPtr read_ciphertext() = 0; - virtual std::string ssl_handshake_details() const = 0; - virtual bool export_keying_material(const std::string& label, unsigned char* dest, size_t size) = 0; - virtual bool did_full_handshake() = 0; - virtual const AuthCert::Ptr& auth_cert() const = 0; - virtual void mark_no_cache() = 0; // prevent caching of client-side session (only meaningful when client_session_tickets is enabled) - uint32_t get_tls_warnings() const - { - return tls_warnings; - } - protected: - uint32_t tls_warnings = 0; // bitfield of SSLAPI::TLSWarnings - }; - - class SSLFactoryAPI : public RC<thread_unsafe_refcount> - { - public: - OPENVPN_EXCEPTION(ssl_options_error); - OPENVPN_EXCEPTION(ssl_context_error); - OPENVPN_EXCEPTION(ssl_external_pki); - OPENVPN_SIMPLE_EXCEPTION(ssl_ciphertext_in_overflow); - - typedef RCPtr<SSLFactoryAPI> Ptr; - - // create a new SSLAPI instance - virtual SSLAPI::Ptr ssl() = 0; - - // like ssl() above but optionally verify hostname against cert CommonName and/or - // SubjectAltName, and optionally set/lookup a cache key for this session. - virtual SSLAPI::Ptr ssl(const std::string* hostname, const std::string* cache_key) = 0; - - // client or server? - virtual const Mode& mode() const = 0; - }; - - class SSLConfigAPI : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<SSLConfigAPI> Ptr; - - enum LoadFlags { - LF_PARSE_MODE = (1<<0), - LF_ALLOW_CLIENT_CERT_NOT_REQUIRED = (1<<1), - LF_RELAY_MODE = (1<<2), // look for "relay-ca" instead of "ca" directive - }; - - std::string private_key_type_string() const - { - PKType::Type type = private_key_type(); - - switch (type) - { - case PKType::PK_NONE: - return "None"; - case PKType::PK_DSA: - return "DSA"; - case PKType::PK_RSA: - return "RSA"; - case PKType::PK_EC: - return "EC"; - case PKType::PK_ECDSA: - return "ECDSA"; - case PKType::PK_UNKNOWN: - default: - return "Unknown"; - } - } - - virtual void set_mode(const Mode& mode_arg) = 0; - virtual const Mode& get_mode() const = 0; - virtual void set_external_pki_callback(ExternalPKIBase* external_pki_arg) = 0; // private key alternative - virtual void set_session_ticket_handler(TLSSessionTicketBase* session_ticket_handler) = 0; // server side - virtual void set_client_session_tickets(const bool v) = 0; // client side - virtual void set_sni_handler(SNI::HandlerBase* sni_handler) = 0; // server side - virtual void set_sni_name(const std::string& sni_name_arg) = 0; // client side - virtual void set_private_key_password(const std::string& pwd) = 0; - virtual void load_ca(const std::string& ca_txt, bool strict) = 0; - virtual void load_crl(const std::string& crl_txt) = 0; - virtual void load_cert(const std::string& cert_txt) = 0; - virtual void load_cert(const std::string& cert_txt, const std::string& extra_certs_txt) = 0; - virtual void load_private_key(const std::string& key_txt) = 0; - virtual void load_dh(const std::string& dh_txt) = 0; - virtual std::string extract_ca() const = 0; - virtual std::string extract_crl() const = 0; - virtual std::string extract_cert() const = 0; - virtual std::vector<std::string> extract_extra_certs() const = 0; - virtual std::string extract_private_key() const = 0; - virtual std::string extract_dh() const = 0; - virtual PKType::Type private_key_type() const = 0; - virtual size_t private_key_length() const = 0; - virtual void set_frame(const Frame::Ptr& frame_arg) = 0; - virtual void set_debug_level(const int debug_level) = 0; - virtual void set_flags(const unsigned int flags_arg) = 0; - virtual void set_ns_cert_type(const NSCert::Type ns_cert_type_arg) = 0; - virtual void set_remote_cert_tls(const KUParse::TLSWebType wt) = 0; - virtual void set_tls_remote(const std::string& tls_remote_arg) = 0; - virtual void set_tls_version_min(const TLSVersion::Type tvm) = 0; - virtual void set_tls_version_min_override(const std::string& override) = 0; - virtual void set_tls_cert_profile(const TLSCertProfile::Type type) = 0; - virtual void set_tls_cert_profile_override(const std::string& override) = 0; - virtual void set_local_cert_enabled(const bool v) = 0; - virtual void set_x509_track(X509Track::ConfigSet x509_track_config_arg) = 0; - virtual void set_rng(const RandomAPI::Ptr& rng_arg) = 0; - virtual void load(const OptionList& opt, const unsigned int lflags) = 0; - -#ifdef OPENVPN_JSON_INTERNAL - virtual SSLConfigAPI::Ptr json_override(const Json::Value& root, const bool load_cert_key) const = 0; -#endif - - virtual std::string validate_cert(const std::string& cert_txt) const = 0; - virtual std::string validate_cert_list(const std::string& certs_txt) const = 0; - virtual std::string validate_crl(const std::string& crl_txt) const = 0; - virtual std::string validate_private_key(const std::string& key_txt) const = 0; - virtual std::string validate_dh(const std::string& dh_txt) const = 0; - - virtual SSLFactoryAPI::Ptr new_factory() = 0; - }; - - /** - * Reports a human readable string of the SSL library in use and its version. - * E.g. mbed TLS 1.2.4 - * - * @return a human readable SSL library version string - */ - inline const std::string get_ssl_library_version(); - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/sslchoose.hpp b/Sources/OpenVPN3/openvpn/ssl/sslchoose.hpp deleted file mode 100644 index 3bfd878..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sslchoose.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// 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-2020 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_SSL_SSLCHOOSE_H -#define OPENVPN_SSL_SSLCHOOSE_H - -#ifdef USE_OPENSSL -#include <openvpn/openssl/crypto/api.hpp> -#include <openvpn/openssl/ssl/sslctx.hpp> -#include <openvpn/openssl/util/rand.hpp> -#include <openvpn/openssl/util/pem.hpp> -#endif - -#ifdef USE_APPLE_SSL -#include <openvpn/applecrypto/crypto/api.hpp> -#include <openvpn/applecrypto/ssl/sslctx.hpp> -#include <openvpn/applecrypto/util/rand.hpp> -#endif - -#ifdef USE_MBEDTLS -#include <mbedtls/platform.h> -#include <mbedtls/debug.h> // for debug_set_threshold -#include <openvpn/mbedtls/crypto/api.hpp> -#include <openvpn/mbedtls/ssl/sslctx.hpp> -#include <openvpn/mbedtls/util/rand.hpp> -#ifdef OPENVPN_PLATFORM_UWP -#include <openvpn/mbedtls/util/uwprand.hpp> -#endif -#include <openvpn/mbedtls/util/pem.hpp> -#endif - -#ifdef USE_MBEDTLS_APPLE_HYBRID -#include <openvpn/applecrypto/crypto/api.hpp> -#include <openvpn/mbedtls/ssl/sslctx.hpp> -#include <openvpn/mbedtls/util/rand.hpp> -#endif - -namespace openvpn { - namespace SSLLib { -#if defined(USE_MBEDTLS) -#define SSL_LIB_NAME "MbedTLS" - typedef MbedTLSCryptoAPI CryptoAPI; - typedef MbedTLSContext SSLAPI; -#if defined OPENVPN_PLATFORM_UWP - typedef MbedTLSRandomWithUWPEntropy RandomAPI; -#else - typedef MbedTLSRandom RandomAPI; -#endif - typedef MbedTLSPEM PEMAPI; -#elif defined(USE_MBEDTLS_APPLE_HYBRID) - // Uses Apple framework for CryptoAPI and MbedTLS for SSLAPI and RandomAPI -#define SSL_LIB_NAME "MbedTLSAppleHybrid" - typedef AppleCryptoAPI CryptoAPI; - typedef MbedTLSContext SSLAPI; - typedef MbedTLSRandom RandomAPI; -#elif defined(USE_APPLE_SSL) -#define SSL_LIB_NAME "AppleSSL" - typedef AppleCryptoAPI CryptoAPI; - typedef AppleSSLContext SSLAPI; - typedef AppleRandom RandomAPI; -#elif defined(USE_OPENSSL) -#define SSL_LIB_NAME "OpenSSL" - typedef OpenSSLCryptoAPI CryptoAPI; - typedef OpenSSLContext SSLAPI; - typedef OpenSSLRandom RandomAPI; - typedef OpenSSLPEM PEMAPI; -#else -#error no SSL library defined -#endif - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/sslconsts.hpp b/Sources/OpenVPN3/openvpn/ssl/sslconsts.hpp deleted file mode 100644 index 8df60b9..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/sslconsts.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// 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-2020 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_SSL_SSLCONSTS_H -#define OPENVPN_SSL_SSLCONSTS_H - -namespace openvpn { - namespace SSLConst { - - // Special return values from SSL read/write methods - enum { - // Indicates that no cleartext data is available now (until - // more ciphertext is pushed into the SSL engine). - SHOULD_RETRY = -1, - - // Return value from read_cleartext indicating that peer - // has sent a Close Notify message. - PEER_CLOSE_NOTIFY = -2, - }; - - // SSL config flags - enum { - // Show SSL status and cert chain in verify method - LOG_VERIFY_STATUS=(1<<0), - - // Disable peer verification - NO_VERIFY_PEER=(1<<1), - - // [client only] Enable client-side SNI (Server Name Indication) - // when hostname is provided - ENABLE_CLIENT_SNI=(1<<2), - - // [client only] Don't require that the hostname matches - // the common name in the certificate. - NO_VERIFY_HOSTNAME=(1<<3), - - // [server only] Don't automatically fail connections on - // bad peer cert. Succeed the connection, but pass the - // fail status data via AuthCert so the higher layers - // can handle it. - DEFERRED_CERT_VERIFY=(1<<4), - - // [server only] When running as a server, require that - // clients that connect to us have their certificate - // purpose set to server. - SERVER_TO_SERVER=(1<<5), - - // Peer certificate is optional - PEER_CERT_OPTIONAL=(1<<6), - - // [server only] Send a list of client CAs to the client - SEND_CLIENT_CA_LIST=(1<<7), - - // last flag marker - LAST=(1<<8) - }; - - // filter all but SSL flags - inline unsigned int ssl_flags(const unsigned int flags) - { - return flags & (LAST-1); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/ssllog.hpp b/Sources/OpenVPN3/openvpn/ssl/ssllog.hpp deleted file mode 100644 index 26f8236..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/ssllog.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// 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-2020 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_SSL_SSLLOG_H -#define OPENVPN_SSL_SSLLOG_H - -#ifndef OPENVPN_LOG_SSL -#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x) -#endif - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/tls_cert_profile.hpp b/Sources/OpenVPN3/openvpn/ssl/tls_cert_profile.hpp deleted file mode 100644 index 0cc11a1..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/tls_cert_profile.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// 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-2020 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/>. - -// Parse the tls-cert-profile option. - -#ifndef OPENVPN_SSL_TLS_CERT_PROFILE_H -#define OPENVPN_SSL_TLS_CERT_PROFILE_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - namespace TLSCertProfile { - enum Type { - UNDEF=0, -#ifdef OPENVPN_USE_TLS_MD5 - INSECURE, -#endif - LEGACY, - PREFERRED, - SUITEB, - }; - - inline Type default_if_undef(const Type type) - { - if (type == UNDEF) - return LEGACY; // this is the default if unspecified - else - return type; - } - - inline const std::string to_string(const Type type) - { - switch (type) - { - case UNDEF: - return "UNDEF"; -#ifdef OPENVPN_USE_TLS_MD5 - case INSECURE: - return "INSECURE"; -#endif - case LEGACY: - return "LEGACY"; - case PREFERRED: - return "PREFERRED"; - case SUITEB: - return "SUITEB"; - default: - return "???"; - } - } - - inline Type parse_tls_cert_profile(const std::string& profile_name) - { -#ifdef OPENVPN_USE_TLS_MD5 - if (profile_name == "insecure") - return INSECURE; - else -#endif - if (profile_name == "legacy") - return LEGACY; - else if (profile_name == "preferred") - return PREFERRED; - else if (profile_name == "suiteb") - return SUITEB; - else - throw option_error("tls-cert-profile: unrecognized profile name"); - } - - inline Type parse_tls_cert_profile(const OptionList& opt, - const std::string& relay_prefix) - { - const Option* o = opt.get_ptr(relay_prefix + "tls-cert-profile"); - if (o) - { - const std::string profile_name = o->get_optional(1, 16); - return parse_tls_cert_profile(profile_name); - } - return UNDEF; - } - - // If the override ends with "default", it is only applied - // if the config doesn't specify tls-cert-profile. - // Otherwise, the override has priority over the config. - inline void apply_override(Type& type, const std::string& override) - { - const Type orig = type; - if (override.empty() || override == "default") - ; -#ifdef OPENVPN_USE_TLS_MD5 - else if (override == "insecure-default") - { - if (orig == UNDEF) - type = INSECURE; - } -#endif - else if (override == "legacy-default") - { - if (orig == UNDEF) - type = LEGACY; - } - else if (override == "preferred-default") - { - if (orig == UNDEF) - type = PREFERRED; - } -#ifdef OPENVPN_USE_TLS_MD5 - else if (override == "insecure") - type = INSECURE; -#endif - else if (override == "legacy") - type = LEGACY; - else if (override == "preferred") - type = PREFERRED; - else if (override == "suiteb") - type = SUITEB; - else - throw option_error("tls-cert-profile: unrecognized override string"); - //OPENVPN_LOG("*** tls-cert-profile before=" << to_string(orig) << " override=" << override << " after=" << to_string(type)); - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/tls_remote.hpp b/Sources/OpenVPN3/openvpn/ssl/tls_remote.hpp deleted file mode 100644 index 7aa480f..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/tls_remote.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// 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-2020 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/>. - -// test certificate subject and common name against tls_remote parameter - -#ifndef OPENVPN_SSL_TLS_REMOTE_H -#define OPENVPN_SSL_TLS_REMOTE_H - -#include <cstring> -#include <string> - -#include <openvpn/common/string.hpp> - -namespace openvpn { - namespace TLSRemote { - inline bool test(const std::string& tls_remote, const std::string& subject, const std::string& common_name) - { - return tls_remote == subject || string::starts_with(common_name, tls_remote); - } - - inline void log(const std::string& tls_remote, const std::string& subject, const std::string& common_name) - { - OPENVPN_LOG("tls-remote validation" << std::endl << " tls-remote: '" << tls_remote << '\'' << std::endl << " Subj: '" << subject << '\'' << std::endl << " CN: '" << common_name << '\''); - } - - // modifies x509 name in a way that is compatible with - // name remapping behavior on OpenVPN 2.x - inline std::string sanitize_x509_name(const std::string& str) - { - std::string ret; - bool leading_dash = true; - ret.reserve(str.length()); - for (size_t i = 0; i < str.length(); ++i) - { - const char c = str[i]; - if (c == '-' && leading_dash) - { - ret += '_'; - continue; - } - leading_dash = false; - if ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '_' || c == '-' || c == '.' - || c == '@' || c == ':' || c == '/' - || c == '=') - ret += c; - else - ret += '_'; - } - return ret; - } - - // modifies common name in a way that is compatible with - // name remapping behavior on OpenVPN 2.x - inline std::string sanitize_common_name(const std::string& str) - { - std::string ret; - ret.reserve(str.length()); - for (size_t i = 0; i < str.length(); ++i) - { - const char c = str[i]; - if ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '_' || c == '-' || c == '.' - || c == '@' || c == '/') - ret += c; - else - ret += '_'; - } - return ret; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/ssl/tlsprf.hpp b/Sources/OpenVPN3/openvpn/ssl/tlsprf.hpp deleted file mode 100644 index 71d654c..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/tlsprf.hpp +++ /dev/null @@ -1,395 +0,0 @@ -// 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-2020 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/>. - -// Implement the TLS-PRF function, used by ProtoContext. - -#ifndef OPENVPN_SSL_TLSPRF_H -#define OPENVPN_SSL_TLSPRF_H - -#include <cstring> // for std::strlen and others - -#include <string> -#include <sstream> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/bufcomplete.hpp> -#include <openvpn/crypto/static_key.hpp> -#include <openvpn/crypto/cryptoalgs.hpp> -#include <openvpn/ssl/psid.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - template <typename CRYPTO_API> - class TLSPRF - { - public: - OPENVPN_SIMPLE_EXCEPTION(tlsprf_uninitialized); - OPENVPN_SIMPLE_EXCEPTION(tlsprf_client_server_mismatch); - - TLSPRF(const bool server) - : initialized_(false), server_(server) {} - - void randomize(RandomAPI& rng) - { - rng.assert_crypto(); - if (!server_) - rng.rand_bytes(pre_master, sizeof(pre_master)); - rng.rand_bytes(random1, sizeof(random1)); - rng.rand_bytes(random2, sizeof(random2)); - initialized_ = true; - } - - void read(Buffer& buf) - { - if (!server_) - buf.read(pre_master, sizeof(pre_master)); - buf.read(random1, sizeof(random1)); - buf.read(random2, sizeof(random2)); - initialized_ = true; - } - - bool read_complete(BufferComplete& bc) - { - size_t need = sizeof(random1) + sizeof(random2); - if (!server_) - need += sizeof(pre_master); - if (!bc.advance(need)) - return false; - return true; - } - - void write(Buffer& buf) - { - verify_initialized(); - if (!server_) - buf.write(pre_master, sizeof(pre_master)); - buf.write(random1, sizeof(random1)); - buf.write(random2, sizeof(random2)); - } - - void generate_key_expansion(OpenVPNStaticKey& dest, const TLSPRF& peer, - const ProtoSessionID& psid_self, const ProtoSessionID& psid_peer) const - { - if (server_ == peer.server_) - throw tlsprf_client_server_mismatch(); - if (server_) - gen_exp(dest, peer, psid_peer, *this, psid_self); - else - gen_exp(dest, *this, psid_self, peer, psid_peer); - } - - void erase() - { - if (initialized_) - { - if (!server_) - std::memset(pre_master, 0, sizeof(pre_master)); - std::memset(random1, 0, sizeof(random1)); - std::memset(random2, 0, sizeof(random2)); - initialized_ = false; - } - } - - std::string dump(const char *title) - { - std::ostringstream out; - out << "*** TLSPRF " << title << " pre_master: " << render_hex(pre_master, sizeof(pre_master)) << std::endl; - out << "*** TLSPRF " << title << " random1: " << render_hex(random1, sizeof(random1)) << std::endl; - out << "*** TLSPRF " << title << " random2: " << render_hex(random2, sizeof(random2)) << std::endl; - return out.str(); - } - - ~TLSPRF() - { - erase(); - } - - static void openvpn_PRF (const unsigned char *secret, - const size_t secret_len, - const char *label, - const unsigned char *client_seed, - const size_t client_seed_len, - const unsigned char *server_seed, - const size_t server_seed_len, - const ProtoSessionID* client_sid, - const ProtoSessionID* server_sid, - unsigned char *output, - const size_t output_len) - { - const size_t label_len = std::strlen(label); - BufferAllocated seed(label_len - + client_seed_len - + server_seed_len - + ProtoSessionID::SIZE * 2, - BufferAllocated::DESTRUCT_ZERO); - seed.write((unsigned char *)label, label_len); - seed.write(client_seed, client_seed_len); - seed.write(server_seed, server_seed_len); - if (client_sid) - client_sid->write(seed); - if (server_sid) - server_sid->write(seed); - - // compute PRF - PRF(seed.data(), seed.size(), secret, secret_len, output, output_len); - } - - private: - /* - * Use the TLS PRF function for generating data channel keys. - * This code is adapted from the OpenSSL library. - * - * TLS generates keys as such: - * - * master_secret[48] = PRF(pre_master_secret[48], "master secret", - * ClientHello.random[32] + ServerHello.random[32]) - * - * key_block[] = PRF(SecurityParameters.master_secret[48], - * "key expansion", - * SecurityParameters.server_random[32] + - * SecurityParameters.client_random[32]); - * - * Notes: - * - * (1) key_block contains a full set of 4 keys. - * (2) The pre-master secret is generated by the client. - */ - - static void hash (const CryptoAlgs::Type md, - const unsigned char *sec, - const size_t sec_len, - const unsigned char *seed, - const size_t seed_len, - unsigned char *out, - size_t olen) - { - size_t j; - unsigned char A1[CRYPTO_API::HMACContext::MAX_HMAC_SIZE]; - size_t A1_len; - typename CRYPTO_API::HMACContext ctx; - typename CRYPTO_API::HMACContext ctx_tmp; - const size_t chunk = CryptoAlgs::size(md); - - ctx.init(md, sec, sec_len); - ctx_tmp.init(md, sec, sec_len); - ctx.update(seed, seed_len); - A1_len = ctx.final(A1); - - for (;;) - { - ctx.reset(); - ctx_tmp.reset(); - ctx.update(A1, A1_len); - ctx_tmp.update(A1, A1_len); - ctx.update(seed, seed_len); - - if (olen > chunk) - { - j = ctx.final(out); - out+=j; - olen-=j; - A1_len = ctx_tmp.final(A1); /* calc the next A1 value */ - } - else /* last one */ - { - A1_len = ctx.final(A1); - memcpy(out,A1,olen); - break; - } - } - std::memset(A1, 0, sizeof(A1)); - } - - static void PRF (unsigned char *label, - const size_t label_len, - const unsigned char *sec, - const size_t slen, - unsigned char *out1, - const size_t olen) - { - size_t len, i; - const unsigned char *S1, *S2; - unsigned char *out2; - - out2 = new unsigned char[olen]; - - len = slen / 2; - S1 = sec; - S2 = &(sec[len]); - len += (slen & 1); /* add for odd, make longer */ - - hash(CryptoAlgs::MD5,S1,len,label,label_len,out1,olen); - hash(CryptoAlgs::SHA1,S2,len,label,label_len,out2,olen); - - for (i=0; i<olen; i++) - out1[i]^=out2[i]; - - std::memset(out2, 0, olen); - delete [] out2; - } - - static void gen_exp(OpenVPNStaticKey& dest, const TLSPRF& client, const ProtoSessionID& psid_client, - const TLSPRF& server, const ProtoSessionID& psid_server) - { - static const char master_secret_id[] = "OpenVPN master secret"; - static const char key_expansion_id[] = "OpenVPN key expansion"; - - unsigned char master[48]; - - client.verify_initialized(); - server.verify_initialized(); - - // compute master secret - openvpn_PRF (client.pre_master, - sizeof(client.pre_master), - master_secret_id, - client.random1, - sizeof(client.random1), - server.random1, - sizeof(server.random1), - nullptr, - nullptr, - master, - sizeof(master)); - - // compute key expansion */ - openvpn_PRF (master, - sizeof(master), - key_expansion_id, - client.random2, - sizeof(client.random2), - server.random2, - sizeof(server.random2), - &psid_client, - &psid_server, - dest.raw_alloc(), - OpenVPNStaticKey::KEY_SIZE); - - std::memset(master, 0, sizeof(master)); - } - - void verify_initialized() const - { - if (!initialized_) - throw tlsprf_uninitialized(); - } - - bool initialized_; - bool server_; - unsigned char pre_master[48]; // client generated - unsigned char random1[32]; // generated by both client and server - unsigned char random2[32]; // generated by both client and server - }; - - // TLSPRF wrapper API using dynamic polymorphism - - class TLSPRFInstance : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSPRFInstance> Ptr; - - virtual void self_randomize(RandomAPI& rng) = 0; - virtual void self_write(Buffer& buf) = 0; - virtual void peer_read(Buffer& buf) = 0; - virtual bool peer_read_complete(BufferComplete& bc) = 0; - virtual void erase() = 0; - - virtual void generate_key_expansion(OpenVPNStaticKey& dest, - const ProtoSessionID& psid_self, - const ProtoSessionID& psid_peer) const = 0; - }; - - class TLSPRFFactory : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TLSPRFFactory> Ptr; - - virtual TLSPRFInstance::Ptr new_obj(const bool self_is_server) = 0; - }; - - // TLSPRF wrapper implementation using dynamic polymorphism - - template <typename CRYPTO_API> - class CryptoTLSPRFInstance : public TLSPRFInstance - { - public: - CryptoTLSPRFInstance(const bool self_is_server) - : self(self_is_server), - peer(!self_is_server) - { - } - - virtual void self_randomize(RandomAPI& rng) - { - self.randomize(rng); - } - - virtual void self_write(Buffer& buf) - { - self.write(buf); - } - - virtual void peer_read(Buffer& buf) - { - peer.read(buf); - } - - virtual bool peer_read_complete(BufferComplete& bc) - { - return peer.read_complete(bc); - } - - virtual void erase() - { - self.erase(); - peer.erase(); - } - - virtual void generate_key_expansion(OpenVPNStaticKey& dest, - const ProtoSessionID& psid_self, - const ProtoSessionID& psid_peer) const - { - self.generate_key_expansion(dest, peer, psid_self, psid_peer); - } - - private: - TLSPRF<CRYPTO_API> self; - TLSPRF<CRYPTO_API> peer; - }; - - template <typename CRYPTO_API> - class CryptoTLSPRFFactory : public TLSPRFFactory - { - public: - virtual TLSPRFInstance::Ptr new_obj(const bool self_is_server) - { - return new CryptoTLSPRFInstance<CRYPTO_API>(self_is_server); - } - }; - -} // namespace openvpn - -#endif // OPENVPN_SSL_TLSPRF_H diff --git a/Sources/OpenVPN3/openvpn/ssl/tlsver.hpp b/Sources/OpenVPN3/openvpn/ssl/tlsver.hpp deleted file mode 100644 index 98c574e..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/tlsver.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// 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-2020 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/>. - -// Parse the tls-version-min option. - -#pragma once - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/options.hpp> - -namespace openvpn { - namespace TLSVersion { - enum Type { - UNDEF=0, - V1_0, - V1_1, - V1_2, - V1_3 - }; - - inline const std::string to_string(const Type version) - { - switch (version) - { - case UNDEF: - return "UNDEF"; - case V1_0: - return "V1_0"; - case V1_1: - return "V1_1"; - case V1_2: - return "V1_2"; - case V1_3: - return "V1_3"; - default: - return "???"; - } - } - - inline Type parse_tls_version_min(const std::string& ver, - const bool or_highest, - const Type max_version) - { - if (ver == "1.0" && V1_0 <= max_version) - return V1_0; - else if (ver == "1.1" && V1_1 <= max_version) - return V1_1; - else if (ver == "1.2" && V1_2 <= max_version) - return V1_2; - else if (ver == "1.3" && V1_3 <= max_version) - return V1_2; - else if (or_highest) - return max_version; - else - throw option_error("tls-version-min: unrecognized TLS version"); - } - - inline Type parse_tls_version_min(const OptionList& opt, - const std::string& relay_prefix, - const Type max_version) - { - const Option* o = opt.get_ptr(relay_prefix + "tls-version-min"); - if (o) - { - const std::string ver = o->get_optional(1, 16); - const bool or_highest = (o->get_optional(2, 16) == "or-highest"); - return parse_tls_version_min(ver, or_highest, max_version); - } - return UNDEF; - } - - inline void apply_override(Type& tvm, const std::string& override) - { - //const Type orig = tvm; - if (override.empty() || override == "default") - ; - else if (override == "disabled") - tvm = UNDEF; - else if (override == "tls_1_0") - tvm = V1_0; - else if (override == "tls_1_1") - tvm = V1_1; - else if (override == "tls_1_2") - tvm = V1_2; - else if (override == "tls_1_3") - tvm = V1_3; - else - throw option_error("tls-version-min: unrecognized override string"); - - //OPENVPN_LOG("*** TLS-version-min before=" << to_string(orig) << " override=" << override << " after=" << to_string(tvm)); // fixme - } - } -} diff --git a/Sources/OpenVPN3/openvpn/ssl/verify_x509_name.hpp b/Sources/OpenVPN3/openvpn/ssl/verify_x509_name.hpp deleted file mode 100644 index d529755..0000000 --- a/Sources/OpenVPN3/openvpn/ssl/verify_x509_name.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// 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-2020 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/options.hpp> - -namespace openvpn { - -/** - * Parses the --verify-x509-name configuration option - * and provides the logic to validate an X.509 certificate subject - * against such an option. - */ -class VerifyX509Name { - public: - enum Mode { - VERIFY_X509_NONE = 0, - VERIFY_X509_SUBJECT_DN = 1, - VERIFY_X509_SUBJECT_RDN = 2, - VERIFY_X509_SUBJECT_RDN_PREFIX = 3 - }; - - VerifyX509Name() = default; - - VerifyX509Name(const OptionList& opt, const std::string& relay_prefix = "") { - init(opt, relay_prefix); - } - - ~VerifyX509Name() = default; - - void init(const OptionList& opt, const std::string& relay_prefix) { - const Option* o = opt.get_ptr(relay_prefix + "verify-x509-name"); - if (o) { - o->min_args(1); - verify_value = o->get(1, 256); - // If the mode flag is not present, we default to subject. - // For details, see openvpn(8) man page. - mode = parse_x509_verify_mode(o->get_default(2, 256, "subject")); - } - } - - std::string get_mode_str() const { - switch (mode) { - case VERIFY_X509_NONE: - return "VERIFY_X509_NONE"; - case VERIFY_X509_SUBJECT_DN: - return "VERIFY_X509_SUBJECT_DN"; - case VERIFY_X509_SUBJECT_RDN: - return "VERIFY_X509_SUBJECT_RDN"; - case VERIFY_X509_SUBJECT_RDN_PREFIX: - return "VERIFY_X509_SUBJECT_RDN_PREFIX"; - default: - return "VERIFY_X509_NONE"; - } - } - - Mode get_mode() const { return mode; } - - bool verify(const std::string& value) const { - switch (mode) { - case VERIFY_X509_NONE: - // If no verification is configured, it is always a pass - return true; - - case VERIFY_X509_SUBJECT_DN: - // The input value is expected to be a full subject DN - // where a perfect match is expected - return verify_value == value; - - case VERIFY_X509_SUBJECT_RDN: - // The input value is expected to be the certificate - // Common Name (CN), and a perfect patch is expected - return verify_value == value; - - case VERIFY_X509_SUBJECT_RDN_PREFIX: - // The input value contains a prefix of the certificate - // Common Name (CN), where we only require a perfect match - // only on the matching prefix - return value.compare(0, verify_value.length(), verify_value) == 0; - } - return false; - } - - private: - Mode mode = VERIFY_X509_NONE; - std::string verify_value; - - static Mode parse_x509_verify_mode(const std::string& type) { - if (type == "subject") { - return VERIFY_X509_SUBJECT_DN; - } else if (type == "name") { - return VERIFY_X509_SUBJECT_RDN; - } else if (type == "name-prefix") { - return VERIFY_X509_SUBJECT_RDN_PREFIX; - } - throw option_error("Invalid verify-x509-name type: " + type); - } - -}; // class VerifyX509Name -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/time/asiotimer.hpp b/Sources/OpenVPN3/openvpn/time/asiotimer.hpp deleted file mode 100644 index 5432320..0000000 --- a/Sources/OpenVPN3/openvpn/time/asiotimer.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// 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-2020 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/>. - -// Create an Asio time_traits class to allow Asio to natively handle -// our Time and Time::Duration classes. - -#ifndef OPENVPN_TIME_ASIOTIMER_H -#define OPENVPN_TIME_ASIOTIMER_H - -#include <chrono> - -#include <openvpn/io/io.hpp> // was: #include <asio/basic_waitable_timer.hpp> - -#include <openvpn/common/olong.hpp> -#include <openvpn/time/time.hpp> - -namespace openvpn { - struct AsioClock - { - typedef olong rep; - typedef std::ratio<1, 1024> period; // time resolution of openvpn::Time - typedef std::chrono::duration<rep, period> duration; - typedef std::chrono::time_point<AsioClock> time_point; - - static constexpr bool is_steady() - { - return false; - } - - static time_point now() - { - return to_time_point(Time::now()); - } - - static time_point to_time_point(const Time& t) - { - return time_point(duration(t.raw())); - } - - static duration to_duration(const Time::Duration& d) - { - return duration(d.raw()); - } - }; - - class AsioTimer : public openvpn_io::basic_waitable_timer<AsioClock> - { - public: - AsioTimer(openvpn_io::io_context& io_context) - : openvpn_io::basic_waitable_timer<AsioClock>(io_context) - { - } - - std::size_t expires_at(const Time& t) - { - return openvpn_io::basic_waitable_timer<AsioClock>::expires_at(AsioClock::to_time_point(t)); - } - - std::size_t expires_after(const Time::Duration& d) - { - return openvpn_io::basic_waitable_timer<AsioClock>::expires_after(AsioClock::to_duration(d)); - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/time/asiotimersafe.hpp b/Sources/OpenVPN3/openvpn/time/asiotimersafe.hpp deleted file mode 100644 index a5c2277..0000000 --- a/Sources/OpenVPN3/openvpn/time/asiotimersafe.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// 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-2020 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/rc.hpp> -#include <openvpn/time/asiotimer.hpp> - -// AsioTimerSafe is like AsioTimer but with strict cancellation -// semantics that guarantees that a handler will never be called -// with a non-error status after the timer is cancelled. - -namespace openvpn { - class AsioTimerSafe - { - public: - AsioTimerSafe(openvpn_io::io_context& io_context) - : timer_(io_context), - epoch_(new Epoch) - { - } - - std::size_t expires_at(const Time& t) - { - inc_epoch(); - return timer_.expires_at(t); - } - - std::size_t expires_after(const Time::Duration& d) - { - inc_epoch(); - return timer_.expires_after(d); - } - - std::size_t cancel() - { - inc_epoch(); - return timer_.cancel(); - } - - template <typename F> - void async_wait(F&& func) - { - inc_epoch(); - timer_.async_wait([func=std::move(func), epoch=epoch(), eptr=epoch_](const openvpn_io::error_code& error) - { - func(epoch == eptr->epoch ? error : openvpn_io::error::operation_aborted); - }); - } - - private: - typedef std::size_t epoch_t; - - struct Epoch : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Epoch> Ptr; - epoch_t epoch = 0; - }; - - epoch_t epoch() const - { - return epoch_->epoch; - } - - void inc_epoch() - { - ++epoch_->epoch; - } - - AsioTimer timer_; - Epoch::Ptr epoch_; - }; -} diff --git a/Sources/OpenVPN3/openvpn/time/coarsetime.hpp b/Sources/OpenVPN3/openvpn/time/coarsetime.hpp deleted file mode 100644 index e38b29e..0000000 --- a/Sources/OpenVPN3/openvpn/time/coarsetime.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// 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-2020 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_TIME_COARSETIME_H -#define OPENVPN_TIME_COARSETIME_H - -#include <openvpn/time/time.hpp> - -namespace openvpn { - - // Used to compare two time objects within the accuracy limits - // defined by pre and post. - - class CoarseTime - { - public: - CoarseTime() {} - - CoarseTime(const Time::Duration& pre, const Time::Duration& post) - : pre_(pre), post_(post) {} - - void init(const Time::Duration& pre, const Time::Duration& post) - { - pre_ = pre; - post_ = post; - } - - void reset(const Time& t) { time_ = t; } - void reset() { time_.reset(); } - - bool similar(const Time& t) const - { - if (time_.defined()) - { - if (t >= time_) - return (t - time_) <= post_; - else - return (time_ - t) <= pre_; - } - else - return false; - } - - private: - Time time_; - Time::Duration pre_; - Time::Duration post_; - }; - -} // namespace openvpn - -#endif // OPENVPN_TIME_COARSETIME_H diff --git a/Sources/OpenVPN3/openvpn/time/cputime.hpp b/Sources/OpenVPN3/openvpn/time/cputime.hpp deleted file mode 100644 index 08f0795..0000000 --- a/Sources/OpenVPN3/openvpn/time/cputime.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// 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-2020 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 <errno.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/resource.h> -#include <unistd.h> - -#include <string> - -#include <openvpn/common/file.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/exception.hpp> - -#if defined(__APPLE__) -#include <mach/mach.h> - - /** - * Wrapper around the mach thread_info call that emulates the Linux - * getrusage with Thread specific call. - */ - static int getrusage_thread(struct rusage& rusage) - { - int ret = -1; - thread_basic_info_data_t info{}; - mach_msg_type_number_t info_count = THREAD_BASIC_INFO_COUNT; - kern_return_t kern_err; - - kern_err = thread_info(mach_thread_self(), - THREAD_BASIC_INFO, - (thread_info_t)&info, - &info_count); - if (kern_err == KERN_SUCCESS) { - rusage.ru_utime.tv_sec = info.user_time.seconds; - rusage.ru_utime.tv_usec = info.user_time.microseconds; - rusage.ru_stime.tv_sec = info.system_time.seconds; - rusage.ru_stime.tv_usec = info.system_time.microseconds; - ret = 0; - } else { - errno = EINVAL; - } - return ret; - } - -#endif - -namespace openvpn { - /** - * Retrieve the time (in seconds) the current process or thread - * has been running. Runing time includes both system and user - * times. - * - * @param thread Boolean flag controlling if process or thread - * runtime should be returned - * - * @return Returns a double containing number of seconds the - * current process (PID) or thread has been running. - * On errors -1.0 is returned. - * - */ - inline double cpu_time(const bool thread=false) - { - try - { - struct rusage usage{}; - - int ret = 0; -#if defined(__APPLE__) - if (thread) - ret = getrusage_thread(usage); - else - ret = getrusage(RUSAGE_SELF, &usage); -#else - ret = getrusage((thread ? RUSAGE_THREAD : RUSAGE_SELF), &usage); -#endif - if (ret != 0) - { - throw Exception("getrusage() call failed: " + std::string(strerror(errno))); - } - double utime = usage.ru_utime.tv_sec + ((double)usage.ru_utime.tv_usec / 1000000); - double stime = usage.ru_stime.tv_sec + ((double)usage.ru_stime.tv_usec / 1000000); - - return utime + stime; - } - catch (const std::exception& e) - { - //OPENVPN_LOG("cpu_time exception: " << e.what()); - return -1.0; - } - } - - -} diff --git a/Sources/OpenVPN3/openvpn/time/durhelper.hpp b/Sources/OpenVPN3/openvpn/time/durhelper.hpp deleted file mode 100644 index c57c23e..0000000 --- a/Sources/OpenVPN3/openvpn/time/durhelper.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// 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-2020 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_TIME_DURHELPER_H -#define OPENVPN_TIME_DURHELPER_H - -#include <openvpn/common/options.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - inline void set_duration_parm(Time::Duration& dur, - const std::string& name, - const std::string& valstr, - const unsigned int min_value, - const bool x2, // multiply result by 2 - const bool ms) // values are in milliseconds rather than seconds - { - const unsigned int maxdur = ms ? 1000*60*60*24 : 60*60*24*7; // maximum duration -- milliseconds: 1 day, seconds: 7 days - unsigned int value = 0; - const bool status = parse_number<unsigned int>(valstr, value); - if (!status) - OPENVPN_THROW(option_error, name << ": error parsing number of " << (ms ? "milliseconds" : "seconds")); - if (x2) - value *= 2; - if (value == 0 || value > maxdur) - value = maxdur; - if (value < min_value) - value = min_value; - dur = ms ? Time::Duration::milliseconds(value) : Time::Duration::seconds(value); - } - - inline const Option* load_duration_parm(Time::Duration& dur, - const std::string& name, - const OptionList& opt, - const unsigned int min_value, - const bool x2, - const bool allow_ms) - { - // look for milliseconds given as <name>-ms - if (allow_ms) - { - const Option *o = opt.get_ptr(name + "-ms"); - if (o) - { - set_duration_parm(dur, name, o->get(1, 16), min_value, x2, true); - return o; - } - } - - // look for seconds given as <name> - { - const Option *o = opt.get_ptr(name); - if (o) - set_duration_parm(dur, name, o->get(1, 16), allow_ms ? 1 : min_value, x2, false); - return o; - } - } - - inline Time::Duration load_duration_default(const std::string& name, - const OptionList& opt, - const Time::Duration& default_duration, - const unsigned int min_value, - const bool x2, - const bool allow_ms) - { - Time::Duration ret(default_duration); - load_duration_parm(ret, name, opt, min_value, x2, allow_ms); - return ret; - } - - inline Time::Duration skew_duration(const Time::Duration& dur, - const Time::Duration& min, - const unsigned int flux_order, - RandomAPI& rng) - { - const unsigned int range = 1 << flux_order; - const int delta = int(rng.rand_get<unsigned int>() & (range-1)) - int(range>>1); - const Time::Duration ret = dur + delta; - if (ret >= min) - return ret; - else - return min; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/time/epoch.hpp b/Sources/OpenVPN3/openvpn/time/epoch.hpp deleted file mode 100644 index 7abc686..0000000 --- a/Sources/OpenVPN3/openvpn/time/epoch.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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/timespec.hpp> - -namespace openvpn { - - typedef std::uint64_t nanotime_t; - - inline std::uint64_t milliseconds_since_epoch() - { - struct timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - return 0; - return TimeSpec::milliseconds_since_epoch(ts); - } - - inline nanotime_t nanoseconds_since_epoch() - { - struct timespec ts; - if (::clock_gettime(CLOCK_REALTIME, &ts)) - return 0; - return TimeSpec::nanoseconds_since_epoch(ts); - } - -} diff --git a/Sources/OpenVPN3/openvpn/time/skew.hpp b/Sources/OpenVPN3/openvpn/time/skew.hpp deleted file mode 100644 index 8528ce9..0000000 --- a/Sources/OpenVPN3/openvpn/time/skew.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// 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-2020 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 <algorithm> - -#include <openvpn/time/time.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - - struct TimeSkew - { - // Skew factors (+/- %). - // Pass these to skew() via factor parameter. - enum { - PCT_50 = 0, - PCT_25 = 1, - PCT_12_5 = 2, - PCT_6_25 = 3, - PCT_3_125 = 4, - PCT_1_5625 = 5, - }; - - // Skew a duration by some random flux. - static Time::Duration skew(const Time::Duration& dur, const unsigned int factor, RandomAPI& prng) - { - const std::uint32_t bms = std::min(dur.to_binary_ms() >> factor, oulong(0x40000000)); // avoid 32-bit overflow in next step - const int flux = int(prng.randrange32(bms)) - int(bms/2); - return dur + flux; - } - }; - -} diff --git a/Sources/OpenVPN3/openvpn/time/time.hpp b/Sources/OpenVPN3/openvpn/time/time.hpp deleted file mode 100644 index 1e8ba5e..0000000 --- a/Sources/OpenVPN3/openvpn/time/time.hpp +++ /dev/null @@ -1,405 +0,0 @@ -// 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-2020 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/>. - -// These are our fundamental Time and Time Duration classes. -// We normally deal with time in units of 1/1024 of a second. -// This allows us to use 32-bit values to represent most time -// and time duration values, but still gives us reasonable -// accuracy. Using units of 1/1024 of a second vs. straight -// milliseconds gives us an advantage of not needing to do -// very much integer multiplication and division which can -// help us on platforms such as ARM that lack integer division -// instructions. Note that the data type used to store the time -// is an oulong, so it will automatically expand to 64 bits on -// 64-bit machines (see olong.hpp). Using a 32-bit -// data type for time durations is normally fine for clients, -// but imposes a wraparound limit of ~ 48 days. Servers -// should always use a 64-bit data type to avoid this -// limitation. - -// This code was originally designed to be efficient on 32-bit -// processors. On 64-bit processors, define OPENVPN_TIME_NO_BASE -// to optimize out the base_ variable. This also has the benefit -// of allowing Time to represent any arbitrary time_t value. - -#ifndef OPENVPN_TIME_TIME_H -#define OPENVPN_TIME_TIME_H - -#include <limits> -#include <cstdint> // for std::uint32_t, uint64_t - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/olong.hpp> -#include <openvpn/common/to_string.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#include <time.h> // for ::time() on Windows -#include <windows.h> // for GetTickCount -#else -#include <sys/time.h> // for ::time() and ::gettimeofday() -#endif - -namespace openvpn { - OPENVPN_SIMPLE_EXCEPTION(get_time_error); - - template <typename T> - class TimeType - { - public: - enum { prec=1024 }; - typedef ::time_t base_type; - typedef T type; - - class Duration - { - friend class TimeType; - - public: - static Duration seconds(const T v) { return Duration(v * prec); } - static Duration binary_ms(const T v) { return Duration(v); } - static Duration infinite() { return Duration(std::numeric_limits<T>::max()); } - - static Duration milliseconds(const T v) - { - // NOTE: assumes that prec == 1024 - // Also note that this might wrap if v is larger than 1/3 of max size of T - return Duration(v + (v * T(3) / T(128))); - } - - Duration() noexcept : duration_(T(0)) {} - - bool defined() const { return duration_ != T(0); } - bool operator!() const { return duration_ == T(0); } - bool is_infinite() const { return duration_ == std::numeric_limits<T>::max(); } - bool enabled() const { return defined() && !is_infinite(); } - void set_infinite() { duration_ = std::numeric_limits<T>::max(); } - void set_zero() { duration_ = T(0); } - - Duration operator+(const Duration& d) const - { - if (is_infinite() || d.is_infinite()) - return infinite(); - else - return Duration(duration_ + d.duration_); - } - - Duration operator+(const int delta) const - { - T duration = duration_; - if (delta >= 0) - duration += delta; - else - { - const unsigned int ndelta = -delta; - if (duration_ >= ndelta) - duration -= ndelta; - else - duration = 0; - } - return Duration(duration); - } - - Duration operator*(const unsigned int mult) const - { - return Duration(duration_ * mult); - } - - Duration& operator+=(const Duration& d) - { - if (is_infinite() || d.is_infinite()) - set_infinite(); - else - duration_ += d.duration_; - return *this; - } - - void min(const Duration& d) - { - if (d.duration_ < duration_) - duration_ = d.duration_; - } - - void max(const Duration& d) - { - if (d.duration_ > duration_) - duration_ = d.duration_; - } - - Duration operator-(const Duration& d) const - { - if (d.duration_ >= duration_) - return Duration(0); - else if (is_infinite()) - return Duration::infinite(); - else - return Duration(duration_ - d.duration_); - } - - Duration& operator-=(const Duration& d) - { - if (d.duration_ >= duration_) - set_zero(); - else if (!is_infinite()) - duration_ -= d.duration_; - return *this; - } - - T to_seconds() const { return duration_ / prec; } - T to_binary_ms() const { return duration_; } - - T to_milliseconds() const - { - // NOTE: assumes that prec == 1024 - // Also note that this might wrap if duration_ is larger than 1/3 of max size of T - return duration_ - (duration_ * T(3) / T(128)); - } - - double to_double() const - { - return double(duration_) / double(prec); - } - - T raw() const { return duration_; } - -# define OPENVPN_DURATION_REL(OP) bool operator OP(const Duration& d) const { return duration_ OP d.duration_; } - OPENVPN_DURATION_REL(==) - OPENVPN_DURATION_REL(!=) - OPENVPN_DURATION_REL(>) - OPENVPN_DURATION_REL(<) - OPENVPN_DURATION_REL(>=) - OPENVPN_DURATION_REL(<=) -# undef OPENVPN_DURATION_REL - - private: - explicit Duration(const T duration) : duration_(duration) {} - - T duration_; - }; - - TimeType() noexcept : time_(T(0)) {} - - static TimeType zero() { return TimeType(T(0)); } - static TimeType infinite() { return TimeType(std::numeric_limits<T>::max()); } - - static TimeType from_seconds_since_epoch(const time_t t) - { - if (t <= base_) - return TimeType(T(1)); - else - return TimeType(T((t - base_) * prec)); - } - - bool is_infinite() const { return time_ == std::numeric_limits<T>::max(); } - - void reset() { time_ = 0; } - void set_infinite() { time_ = std::numeric_limits<T>::max(); } - - bool defined() const { return time_ != 0; } - bool operator!() const { return time_ == 0; } - - base_type seconds_since_epoch() const { return base_ + time_ / prec; } - T fractional_binary_ms() const { return time_ % prec; } - - static TimeType now() { return TimeType(now_()); } - - void update() { time_ = now_(); } - - TimeType operator+(const Duration& d) const - { - if (is_infinite() || d.is_infinite()) - return infinite(); - else - return TimeType(time_ + d.duration_); - } - - TimeType& operator+=(const Duration& d) - { - if (is_infinite() || d.is_infinite()) - set_infinite(); - else - time_ += d.duration_; - return *this; - } - - Duration operator-(const TimeType& t) const - { - if (t.time_ >= time_) - return Duration(0); - else if (is_infinite()) - return Duration::infinite(); - else - return Duration(time_ - t.time_); - } - - void min(const TimeType& t) - { - if (t.time_ < time_) - time_ = t.time_; - } - - void max(const TimeType& t) - { - if (t.time_ > time_) - time_ = t.time_; - } - - long delta_prec(const TimeType& t) const - { - return long(time_) - long(t.time_); - } - - long delta(const TimeType& t) const - { - return delta_prec(t) / long(prec); - } - - double delta_float(const TimeType& t) const - { - return (double(time_) - double(t.time_)) / double(prec); - } - - // Return a human-readable number of seconds that *this is ahead of t. - // t is usually now(). - std::string delta_str(const TimeType& t) const - { - if (!defined()) - return "UNDEF-TIME"; - if (is_infinite()) - return "INF"; - const double df = delta_float(t); - std::string ret; - if (df >= 0.0) - ret += '+'; - ret += openvpn::to_string(df); - return ret; - } - -# define OPENVPN_TIME_REL(OP) bool operator OP(const TimeType& t) const { return time_ OP t.time_; } - OPENVPN_TIME_REL(==) - OPENVPN_TIME_REL(!=) - OPENVPN_TIME_REL(>) - OPENVPN_TIME_REL(<) - OPENVPN_TIME_REL(>=) - OPENVPN_TIME_REL(<=) -# undef OPENVPN_TIME_REL - - T raw() const { return time_; } - - static void reset_base_conditional() - { - // on 32-bit systems, reset time base after 30 days - if (sizeof(T) == 4) - { - const base_type newbase = ::time(0); - if (newbase - base_ >= (60*60*24*30)) - reset_base(); - } - } - - static void reset_base() - { -#ifdef OPENVPN_TIME_NO_BASE - static_assert(sizeof(base_type) >= 8, "OPENVPN_TIME_NO_BASE requires time_t to be 64 bits"); -#else - base_ = ::time(0); -#ifdef OPENVPN_PLATFORM_WIN -#if (_WIN32_WINNT >= 0x0600) - win_recalibrate((DWORD)::GetTickCount64()); -#else - win_recalibrate(::GetTickCount()); -#endif -#endif -#endif - } - - // number of tenths of a microsecond since January 1, 1601. - static uint64_t win_time() - { - // NOTE: assumes that prec == 1024 - return ((11644473600ULL * uint64_t(prec)) + (uint64_t(base_) * uint64_t(prec)) + uint64_t(now_())) * 78125ULL / 8ULL; - } - - private: - explicit TimeType(const T time) : time_(time) {} - -#ifdef OPENVPN_PLATFORM_WIN - - static void win_recalibrate(const DWORD gtc) - { - gtc_last = gtc; - gtc_base = ::time(0) - gtc_last/1000; - } - - static T now_() - { -#if (_WIN32_WINNT >= 0x0600) - const DWORD gtc = (DWORD)::GetTickCount64(); -#else - const DWORD gtc = ::GetTickCount(); -#endif - if (gtc < gtc_last) - win_recalibrate(gtc); - const time_t sec = gtc_base + gtc / 1000; - const unsigned int msec = gtc % 1000; - return T((sec - base_) * prec + msec * prec / 1000); - } - - static DWORD gtc_last; - static time_t gtc_base; - -#else - - static T now_() - { - ::timeval tv; - if (::gettimeofday(&tv, nullptr) != 0) - throw get_time_error(); - return T((tv.tv_sec - base_) * prec + tv.tv_usec * prec / 1000000); - } - -#endif - -#ifdef OPENVPN_TIME_NO_BASE - static constexpr base_type base_ = 0; -#else - static base_type base_; -#endif - - T time_; - }; - -#ifdef OPENVPN_PLATFORM_WIN - template <typename T> DWORD TimeType<T>::gtc_last; - template <typename T> time_t TimeType<T>::gtc_base; -#endif - -#ifndef OPENVPN_TIME_NO_BASE - template <typename T> typename TimeType<T>::base_type TimeType<T>::base_; -#endif - - typedef TimeType<oulong> Time; - - typedef Time* TimePtr; - -} // namespace openvpn - -#endif // OPENVPN_TIME_TIME_H diff --git a/Sources/OpenVPN3/openvpn/time/timespec.hpp b/Sources/OpenVPN3/openvpn/time/timespec.hpp deleted file mode 100644 index 0a2f7cd..0000000 --- a/Sources/OpenVPN3/openvpn/time/timespec.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// 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-2020 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 <time.h> -#include <cstdint> // for std::uint64_t - -namespace openvpn { - - typedef std::uint64_t nanotime_t; - - namespace TimeSpec { - - inline std::uint64_t milliseconds_since_epoch(const struct timespec& ts) - { - return std::uint64_t(ts.tv_sec) * std::uint64_t(1000) - + std::uint64_t(ts.tv_nsec) / std::uint64_t(1000000); - } - - inline nanotime_t nanoseconds_since_epoch(const struct timespec& ts) - { - return std::uint64_t(ts.tv_sec) * std::uint64_t(1000000000) - + std::uint64_t(ts.tv_nsec); - } - - } -} diff --git a/Sources/OpenVPN3/openvpn/time/timestr.hpp b/Sources/OpenVPN3/openvpn/time/timestr.hpp deleted file mode 100644 index 64196b4..0000000 --- a/Sources/OpenVPN3/openvpn/time/timestr.hpp +++ /dev/null @@ -1,206 +0,0 @@ -// 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-2020 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/>. - -// Function to return the current date/time as a string. - -#ifndef OPENVPN_TIME_TIMESTR_H -#define OPENVPN_TIME_TIMESTR_H - -#include <string> -#include <cstring> // for std::strlen and std::memset -#include <time.h> -#include <stdio.h> -#include <ctype.h> -#include <cstdint> // for std::uint64_t - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/string.hpp> - -#if defined(OPENVPN_PLATFORM_WIN) -#include <windows.h> -#else -#include <sys/time.h> -#endif - -namespace openvpn { - -#if defined(OPENVPN_PLATFORM_WIN) - - inline std::string date_time(const time_t now) - { - struct tm *lt = localtime(&now); - char *ret = asctime(lt); - const size_t len = std::strlen(ret); - if (len > 0 && ret[len-1] == '\n') - ret[len-1] = '\0'; - return ret; - } - - inline std::string date_time() - { - const time_t now = time(NULL); - return date_time(now); - } - - inline std::string date_time_store_time_t(time_t& save) - { - save = time(NULL); - return date_time(save); - } - -#else - - inline std::string date_time(const time_t t) - { - struct tm lt; - char buf[64]; - - std::memset(<, 0, sizeof(lt)); - if (!localtime_r(&t, <)) - return "LOCALTIME_ERROR"; - if (!asctime_r(<, buf)) - return "ASCTIME_ERROR"; - const size_t len = std::strlen(buf); - if (len > 0 && buf[len-1] == '\n') - buf[len-1] = '\0'; - return std::string(buf); - } - - inline std::string date_time_utc(const time_t t) - { - struct tm lt; - char buf[64]; - - std::memset(<, 0, sizeof(lt)); - if (!gmtime_r(&t, <)) - return "GMTIME_ERROR"; - if (!asctime_r(<, buf)) - return "ASCTIME_ERROR"; - const size_t len = std::strlen(buf); - if (len > 0 && buf[len-1] == '\n') - buf[len-1] = '\0'; - return std::string(buf); - } - - // msecs == false : Tue Feb 17 01:24:30 2015 - // msecs == true : Tue Feb 17 01:24:30.123 2015 - inline std::string date_time(const struct timeval *tv, const bool msecs) - { - const std::string dt = date_time(tv->tv_sec); - if (msecs) - { - // find correct position in string to insert milliseconds - const size_t pos = dt.find_last_of(':'); - if (pos != std::string::npos - && pos + 3 < dt.length() - && string::is_digit(dt[pos+1]) - && string::is_digit(dt[pos+2]) - && string::is_space(dt[pos+3])) - { - char ms[5]; - ::snprintf(ms, sizeof(ms), ".%03u", static_cast<unsigned int>(tv->tv_usec / 1000)); - return dt.substr(0, pos+3) + ms + dt.substr(pos+3); - } - } - return dt; - } - - inline std::string nanosec_time_to_string(const std::uint64_t ns_time) - { - const std::uint64_t sec = ns_time / std::uint64_t(1000000000); - const std::uint64_t ns = ns_time % std::uint64_t(1000000000); - - const std::string dt = date_time_utc(sec); - - // find correct position in string to insert nanoseconds - const size_t pos = dt.find_last_of(':'); - if (pos != std::string::npos - && pos + 3 < dt.length() - && string::is_digit(dt[pos+1]) - && string::is_digit(dt[pos+2]) - && string::is_space(dt[pos+3])) - { - char ms[11]; - ::snprintf(ms, sizeof(ms), ".%09u", (unsigned int)ns); - return dt.substr(0, pos+3) + ms + dt.substr(pos+3); - } - return dt; - } - - inline std::string date_time() - { - struct timeval tv; - if (::gettimeofday(&tv, nullptr) < 0) - { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - return date_time(&tv, true); - } - - inline std::string date_time_store_time_t(time_t& save) - { - struct timeval tv; - if (::gettimeofday(&tv, nullptr) < 0) - { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - save = tv.tv_sec; - return date_time(&tv, true); - } - -#endif - - inline std::string date_time_rfc822(const time_t t) - { - struct tm lt; - char buf[64]; - -#if defined(OPENVPN_PLATFORM_WIN) - if (gmtime_s(<, &t)) - return ""; - // MinGW doesn't yet support %T, so use %H:%M:%S - // https://sourceforge.net/p/mingw-w64/bugs/793/ - if (!strftime(buf, sizeof(buf), - "%a, %d %b %Y %H:%M:%S GMT", - <)) - return ""; -#else - if (!gmtime_r(&t, <)) - return ""; - if (!strftime(buf, sizeof(buf), - "%a, %d %b %Y %T %Z", - <)) - return ""; -#endif - return std::string(buf); - } - - inline std::string date_time_rfc822() - { - return date_time_rfc822(::time(nullptr)); - } - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/altproxy.hpp b/Sources/OpenVPN3/openvpn/transport/altproxy.hpp deleted file mode 100644 index 58c7a69..0000000 --- a/Sources/OpenVPN3/openvpn/transport/altproxy.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// 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-2020 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_TRANSPORT_ALTPROXY_H -#define OPENVPN_TRANSPORT_ALTPROXY_H - -#include <string> - -#include <openvpn/common/rc.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/crypto/digestapi.hpp> - -namespace openvpn { - struct AltProxy : public RC<thread_unsafe_refcount> - { - struct Config - { - Config() - : free_list_max_size(8), - socket_protect(nullptr) - {} - - RemoteList::Ptr remote_list; - size_t free_list_max_size; - Frame::Ptr frame; - SessionStats::Ptr stats; - - RandomAPI::Ptr rng; - DigestFactory::Ptr digest_factory; - - SocketProtect* socket_protect; - }; - - typedef RCPtr<AltProxy> Ptr; - - // return proxy name - virtual std::string name() const = 0; - - // called to indicate whether or not remote_list should be cached - virtual void set_enable_cache(const bool enable_cache) = 0; - - // return a RemoteList::Ptr (optional) to precache it - virtual void precache(RemoteList::Ptr& r) = 0; - - // iterate to next host in proxy-specific remote_list, return true - // to prevent next() from being called on global remote_list - virtual bool next() = 0; - - // return true if this proxy method only supports TCP transport - virtual bool requires_tcp() const = 0; - - // return a new TransportClientFactory for this proxy - virtual TransportClientFactory::Ptr new_transport_client_factory(const Config&) = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/extern/config.hpp b/Sources/OpenVPN3/openvpn/transport/client/extern/config.hpp deleted file mode 100644 index 739df26..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/extern/config.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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-2020 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_TRANSPORT_CLIENT_EXTERN_CONFIG_H -#define OPENVPN_TRANSPORT_CLIENT_EXTERN_CONFIG_H - -#include <sstream> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/client/remotelist.hpp> - -namespace openvpn -{ - namespace ExternalTransport - { - struct Config - { - Protocol protocol; - RemoteList::Ptr remote_list; - bool server_addr_float = false; - bool synchronous_dns_lookup = false; - Frame::Ptr frame; - SessionStats::Ptr stats; - SocketProtect* socket_protect = nullptr; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/extern/fw.hpp b/Sources/OpenVPN3/openvpn/transport/client/extern/fw.hpp deleted file mode 100644 index 5b3ce15..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/extern/fw.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// 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-2020 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_TRANSPORT_CLIENT_EXTERN_FW_H -#define OPENVPN_TRANSPORT_CLIENT_EXTERN_FW_H - -#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY -#include <openvpn/transport/client/transbase.hpp> -#endif - -namespace openvpn { - namespace ExternalTransport { -#ifdef OPENVPN_EXTERNAL_TRANSPORT_FACTORY - struct Config; - struct Factory - { - virtual TransportClientFactory* new_transport_factory(const Config& conf) = 0; - virtual ~Factory() {} - }; -#else - struct Factory {}; -#endif - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/httpcli.hpp b/Sources/OpenVPN3/openvpn/transport/client/httpcli.hpp deleted file mode 100644 index 2e1d926..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/httpcli.hpp +++ /dev/null @@ -1,1037 +0,0 @@ -// 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-2020 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/>. - -// HTTP proxy transport object. - -#ifndef OPENVPN_TRANSPORT_CLIENT_HTTPCLI_H -#define OPENVPN_TRANSPORT_CLIENT_HTTPCLI_H - -#include <vector> -#include <string> -#include <sstream> -#include <algorithm> // for std::min -#include <memory> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/userpass.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/buffer/buflimit.hpp> -#include <openvpn/transport/tcplink.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/transport/protocol.hpp> -#include <openvpn/http/reply.hpp> -#include <openvpn/http/status.hpp> -#include <openvpn/http/htmlskip.hpp> -#include <openvpn/proxy/proxyauth.hpp> -#include <openvpn/proxy/httpdigest.hpp> -#include <openvpn/proxy/ntlm.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/crypto/digestapi.hpp> - -namespace openvpn { - namespace HTTPProxyTransport { - - class Options : public RC<thread_safe_refcount> - { - public: - struct CustomHeader : public RC<thread_unsafe_refcount> - { - typedef RCPtr<CustomHeader> Ptr; - - std::string p1; - std::string p2; - }; - - struct CustomHeaderList : public std::vector<CustomHeader::Ptr> - { - }; - - typedef RCPtr<Options> Ptr; - - Options() : allow_cleartext_auth(false) {} - - RemoteList::Ptr proxy_server; - std::string username; - std::string password; - bool allow_cleartext_auth; - - std::string http_version; - std::string user_agent; - - CustomHeaderList headers; - - void set_proxy_server(const std::string& host, const std::string& port) - { - proxy_server.reset(new RemoteList(host, port, Protocol(Protocol::TCP), "http proxy port")); - } - - void proxy_server_set_enable_cache(const bool enable_cache) - { - proxy_server->set_enable_cache(enable_cache); - } - - void proxy_server_precache(RemoteList::Ptr& r) - { - if (proxy_server->get_enable_cache()) - r = proxy_server; - } - - static Ptr parse(const OptionList& opt) - { - if (opt.exists("http-proxy")) - { - Ptr obj(new Options); - if (obj->parse_options(opt)) - return obj; - } - return Ptr(); - } - - private: - bool parse_options(const OptionList& opt) - { - const Option* hp = opt.get_ptr("http-proxy"); - if (hp) - { - // get server/port - set_proxy_server(hp->get(1, 256), hp->get(2, 16)); - - // get creds - { - std::vector<std::string> user_pass; - if (UserPass::parse(opt, "http-proxy-user-pass", 0, &user_pass)) - { - if (user_pass.size() >= 1) - username = user_pass[0]; - if (user_pass.size() >= 2) - password = user_pass[1]; - } - } - - // allow cleartext auth? - allow_cleartext_auth = (hp->get_optional(3, 16) != "auto-nct"); - - // get options - const OptionList::IndexList* hpo = opt.get_index_ptr("http-proxy-option"); - if (hpo) - { - for (OptionList::IndexList::const_iterator i = hpo->begin(); i != hpo->end(); ++i) - { - const Option& o = opt[*i]; - const std::string& type = o.get(1, 64); - if (type == "VERSION") - { - http_version = o.get(2, 16); - o.touch(); - } - else if (type == "AGENT") - { - user_agent = o.get(2, 256); - o.touch(); - } - else if (type == "EXT1" || type == "EXT2" || type == "CUSTOM-HEADER") - { - CustomHeader::Ptr h(new CustomHeader()); - h->p1 = o.get(2, 512); - h->p2 = o.get_optional(3, 512); - headers.push_back(h); - o.touch(); - } - } - } - return true; - } - else - return false; - } - }; - - class ClientConfig : public TransportClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - RemoteList::Ptr remote_list; - size_t free_list_max_size; - Frame::Ptr frame; - SessionStats::Ptr stats; - - Options::Ptr http_proxy_options; - - RandomAPI::Ptr rng; // random data source - - DigestFactory::Ptr digest_factory; // needed by proxy auth methods - - SocketProtect* socket_protect; - - bool skip_html; - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent); - - private: - ClientConfig() - : free_list_max_size(8), - socket_protect(nullptr), - skip_html(false) - {} - }; - - class Client : public TransportClient, AsyncResolvableTCP - { - typedef RCPtr<Client> Ptr; - - typedef TCPTransport::Link<openvpn_io::ip::tcp, Client*, false> LinkImpl; - - friend class ClientConfig; // calls constructor - friend LinkImpl::Base; // calls tcp_read_handler - - public: - void transport_start() override - { - if (!impl) - { - if (!config->http_proxy_options) - { - parent->proxy_error(Error::PROXY_ERROR, "http_proxy_options not defined"); - return; - } - - halt = false; - - // Get target server host:port. We don't care about resolving it - // since proxy server will do that for us. - remote_list().endpoint_available(&server_host, &server_port, nullptr); - - // Get proxy server host:port, and resolve it if not already cached - if (proxy_remote_list().endpoint_available(&proxy_host, &proxy_port, nullptr)) - { - // already cached - start_connect_(); - } - else - { - // resolve it - parent->transport_pre_resolve(); - - async_resolve_lock(); - async_resolve_name(proxy_host, proxy_port); - } - } - } - - bool transport_send_const(const Buffer& buf) override - { - return send_const(buf); - } - - bool transport_send(BufferAllocated& buf) override - { - return send(buf); - } - - bool transport_send_queue_empty() override - { - if (impl) - return impl->send_queue_empty(); - else - return false; - } - - bool transport_has_send_queue() override - { - return true; - } - - void transport_stop_requeueing() override { } - - unsigned int transport_send_queue_size() override - { - if (impl) - return impl->send_queue_size(); - else - return 0; - } - - void reset_align_adjust(const size_t align_adjust) override - { - if (impl) - impl->reset_align_adjust(align_adjust); - } - - void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const override - { - host = server_host; - port = server_port; - const IP::Addr addr = server_endpoint_addr(); - proto = "TCP"; - proto += addr.version_string(); - proto += "-via-HTTP"; - ip_addr = addr.to_string(); - } - - IP::Addr server_endpoint_addr() const override - { - return IP::Addr::from_asio(server_endpoint.address()); - } - - Protocol transport_protocol() const override - { - if (server_endpoint.address().is_v4()) - return Protocol(Protocol::TCPv4); - else if (server_endpoint.address().is_v6()) - return Protocol(Protocol::TCPv6); - else - return Protocol(); - } - - void stop() override { stop_(); } - virtual ~Client() { stop_(); } - - private: - struct ProxyResponseLimit : public BufferLimit<size_t> - { - ProxyResponseLimit() : BufferLimit(1024, 65536) {} - - virtual void bytes_exceeded() { - OPENVPN_THROW_EXCEPTION("HTTP proxy response too large (> " << max_bytes << " bytes)"); - } - - virtual void lines_exceeded() { - OPENVPN_THROW_EXCEPTION("HTTP proxy response too large (> " << max_lines << " lines)"); - } - }; - - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TransportClientParent* parent_arg) - : AsyncResolvableTCP(io_context_arg), - socket(io_context_arg), - config(config_arg), - parent(parent_arg), - halt(false), - n_transactions(0), - proxy_established(false), - http_reply_status(HTTP::ReplyParser::pending), - ntlm_phase_2_response_pending(false), - drain_content_length(0) - { - } - - void transport_reparent(TransportClientParent* parent_arg) override - { - parent = parent_arg; - } - - bool send_const(const Buffer& cbuf) - { - if (impl) - { - BufferAllocated buf(cbuf, 0); - return impl->send(buf); - } - else - return false; - } - - bool send(BufferAllocated& buf) - { - if (impl) - return impl->send(buf); - else - return false; - } - - void tcp_error_handler(const char *error) // called by LinkImpl and internally - { - std::ostringstream os; - os << "Transport error on '" << server_host << "' via HTTP proxy " << proxy_host << ':' << proxy_port << " : " << error; - stop(); - parent->transport_error(Error::TRANSPORT_ERROR, os.str()); - } - - void proxy_error(const Error::Type fatal_err, const std::string& what) - { - std::ostringstream os; - os << "on " << proxy_host << ':' << proxy_port << ": " << what; - stop(); - parent->proxy_error(fatal_err, os.str()); - } - - bool tcp_read_handler(BufferAllocated& buf) // called by LinkImpl - { - if (proxy_established) - { - if (!html_skip) - parent->transport_recv(buf); - else - drain_html(buf); // skip extraneous HTML after header - } - else - { - try { - proxy_read_handler(buf); - } - catch (const std::exception& e) - { - proxy_error(Error::PROXY_ERROR, e.what()); - } - } - return true; - } - - void tcp_write_queue_needs_send() // called by LinkImpl - { - if (proxy_established) - parent->transport_needs_send(); - } - - void tcp_eof_handler() // called by LinkImpl - { - if (proxy_established) - { - config->stats->error(Error::NETWORK_EOF_ERROR); - tcp_error_handler("NETWORK_EOF_ERROR"); - } - else - { - try { - proxy_eof_handler(); - } - catch (const std::exception& e) - { - proxy_error(Error::PROXY_ERROR, e.what()); - } - } - } - - void proxy_read_handler(BufferAllocated& buf) - { - // for anti-DoS, only allow a maximum number of chars in HTTP response - proxy_response_limit.add(buf); - - if (http_reply_status == HTTP::ReplyParser::pending) - { - OPENVPN_LOG_NTNL("FROM PROXY: " << buf_to_string(buf)); - for (size_t i = 0; i < buf.size(); ++i) - { - http_reply_status = http_parser.consume(http_reply, (char)buf[i]); - if (http_reply_status != HTTP::ReplyParser::pending) - { - buf.advance(i+1); - if (http_reply_status == HTTP::ReplyParser::success) - { - //OPENVPN_LOG("*** HTTP header parse complete, resid_size=" << buf.size()); - //OPENVPN_LOG(http_reply.to_string()); - - // we are connected, switch socket to tunnel mode - if (http_reply.status_code == HTTP::Status::Connected) - { - if (config->skip_html) - { - proxy_half_connected(); - html_skip.reset(new HTTP::HTMLSkip()); - drain_html(buf); - } - else - proxy_connected(buf, true); - } - else if (ntlm_phase_2_response_pending) - ntlm_auth_phase_2_pre(); - } - else - { - throw Exception("HTTP proxy header parse error"); - } - break; - } - } - } - - // handle draining of content controlled by Content-length header - if (drain_content_length) - { - const size_t drain = std::min(drain_content_length, buf.size()); - buf.advance(drain); - drain_content_length -= drain; - if (!drain_content_length) - { - if (ntlm_phase_2_response_pending) - ntlm_auth_phase_2(); - } - } - } - - void proxy_connected(BufferAllocated& buf, const bool notify_parent) - { - proxy_established = true; - if (parent->transport_is_openvpn_protocol()) - { - // switch socket from HTTP proxy handshake mode to OpenVPN protocol mode - impl->set_raw_mode(false); - if (notify_parent) - parent->transport_connecting(); - try { - impl->inject(buf); - } - catch (const std::exception& e) - { - proxy_error(Error::PROXY_ERROR, std::string("post-header inject error: ") + e.what()); - return; - } - } - else - { - if (notify_parent) - parent->transport_connecting(); - parent->transport_recv(buf); - } - } - - // Called after header received but before possible extraneous HTML - // is drained. At this point, we are in a state where output data - // (if OpenVPN protocol) is packetized, but input data is still in - // raw mode as we search the input stream for the end of the - // extraneous HTML. When we reach the beginning of payload data, - // proxy_connected() should be called with notify_parent == false. - void proxy_half_connected() - { - proxy_established = true; - if (parent->transport_is_openvpn_protocol()) - impl->set_raw_mode_write(false); - parent->transport_connecting(); - } - - void drain_html(BufferAllocated& buf) - { - while (!buf.empty()) - { - switch (html_skip->add(buf.pop_front())) - { - case HTTP::HTMLSkip::MATCH: - case HTTP::HTMLSkip::NOMATCH: - { - OPENVPN_LOG("Proxy: Skipped " << html_skip->n_bytes() << " byte(s) of HTML"); - html_skip->get_residual(buf); - html_skip.reset(); - proxy_connected(buf, false); - return; - } - case HTTP::HTMLSkip::PENDING: - break; - } - } - } - - HTTPProxy::ProxyAuthenticate::Ptr get_proxy_authenticate_header(const char *type) - { - for (HTTP::HeaderList::const_iterator i = http_reply.headers.begin(); i != http_reply.headers.end(); ++i) - { - const HTTP::Header& h = *i; - if (string::strcasecmp(h.name, "proxy-authenticate") == 0) - { - HTTPProxy::ProxyAuthenticate::Ptr pa = new HTTPProxy::ProxyAuthenticate(h.value); - if (string::strcasecmp(type, pa->method) == 0) - return pa; - } - } - return HTTPProxy::ProxyAuthenticate::Ptr(); - } - - void proxy_eof_handler() - { - if (http_reply_status == HTTP::ReplyParser::success) - { - if (http_reply.status_code == HTTP::Status::ProxyAuthenticationRequired) - { - if (n_transactions <= 1) - { - //OPENVPN_LOG("*** PROXY AUTHENTICATION REQUIRED"); - - if (config->http_proxy_options->username.empty()) - { - proxy_error(Error::PROXY_NEED_CREDS, "HTTP proxy requires credentials"); - return; - } - - HTTPProxy::ProxyAuthenticate::Ptr pa; - - // NTLM - pa = get_proxy_authenticate_header("ntlm"); - if (pa) - { - ntlm_auth_phase_1(*pa); - return; - } - - // Digest - pa = get_proxy_authenticate_header("digest"); - if (pa) - { - digest_auth(*pa); - return; - } - - // Basic - pa = get_proxy_authenticate_header("basic"); - if (pa) - { - if (config->http_proxy_options->allow_cleartext_auth) - { - basic_auth(*pa); - return; - } - else - throw Exception("HTTP proxy Basic authentication not allowed by user preference"); - } - throw Exception("HTTP proxy-authenticate method must be Basic, Digest, or NTLM"); - } - else - { - proxy_error(Error::PROXY_NEED_CREDS, "HTTP proxy credentials were not accepted"); - return; - } - } - else if (http_reply.status_code == HTTP::Status::ProxyError - || http_reply.status_code == HTTP::Status::NotFound - || http_reply.status_code == HTTP::Status::ServiceUnavailable) - { - // this is a nonfatal error, so we pass Error::UNDEF to tell the upper layer to - // retry the connection - proxy_error(Error::UNDEF, "HTTP proxy server could not connect to OpenVPN server"); - return; - } - else if (http_reply.status_code == HTTP::Status::Forbidden) - OPENVPN_THROW_EXCEPTION("HTTP proxy returned Forbidden status code"); - else - OPENVPN_THROW_EXCEPTION("HTTP proxy status code: " << http_reply.status_code); - } - else if (http_reply_status == HTTP::ReplyParser::pending) - throw Exception("HTTP proxy unexpected EOF: reply incomplete"); - else - throw Exception("HTTP proxy general error"); - } - - void basic_auth(HTTPProxy::ProxyAuthenticate& pa) - { - OPENVPN_LOG("Proxy method: Basic" << std::endl << pa.to_string()); - - std::ostringstream os; - gen_headers(os); - os << "Proxy-Authorization: Basic " - << base64->encode(config->http_proxy_options->username + ':' + config->http_proxy_options->password) - << "\r\n"; - http_request = os.str(); - reset(); - start_connect_(); - } - - void digest_auth(HTTPProxy::ProxyAuthenticate& pa) - { - try { - OPENVPN_LOG("Proxy method: Digest" << std::endl << pa.to_string()); - - // constants - const std::string http_method = "CONNECT"; - const std::string nonce_count = "00000001"; - const std::string qop = "auth"; - - // get values from Proxy-Authenticate header - const std::string realm = pa.parms.get_value("realm"); - const std::string nonce = pa.parms.get_value("nonce"); - const std::string algorithm = pa.parms.get_value("algorithm"); - const std::string opaque = pa.parms.get_value("opaque"); - - // generate a client nonce - unsigned char cnonce_raw[8]; - config->rng->assert_crypto(); - config->rng->rand_bytes(cnonce_raw, sizeof(cnonce_raw)); - const std::string cnonce = render_hex(cnonce_raw, sizeof(cnonce_raw)); - - // build URI - const std::string uri = server_host + ":" + server_port; - - // calculate session key - const std::string session_key = HTTPProxy::Digest::calcHA1( - *config->digest_factory, - algorithm, - config->http_proxy_options->username, - realm, - config->http_proxy_options->password, - nonce, - cnonce); - - // calculate response - const std::string response = HTTPProxy::Digest::calcResponse( - *config->digest_factory, - session_key, - nonce, - nonce_count, - cnonce, - qop, - http_method, - uri, - ""); - - // generate proxy request - std::ostringstream os; - gen_headers(os); - os << "Proxy-Authorization: Digest username=\"" << config->http_proxy_options->username << "\", realm=\"" << realm << "\", nonce=\"" << nonce << "\", uri=\"" << uri << "\", qop=" << qop << ", nc=" << nonce_count << ", cnonce=\"" << cnonce << "\", response=\"" << response << "\""; - if (!opaque.empty()) - os << ", opaque=\"" + opaque + "\""; - os << "\r\n"; - - http_request = os.str(); - reset(); - start_connect_(); - } - catch (const std::exception& e) - { - proxy_error(Error::PROXY_NEED_CREDS, std::string("Digest Auth: ") + e.what()); - } - } - - std::string get_ntlm_phase_2_response() - { - for (HTTP::HeaderList::const_iterator i = http_reply.headers.begin(); i != http_reply.headers.end(); ++i) - { - const HTTP::Header& h = *i; - if (string::strcasecmp(h.name, "proxy-authenticate") == 0) - { - std::vector<std::string> v = Split::by_space<std::vector<std::string>, StandardLex, SpaceMatch, Split::NullLimit>(h.value); - if (v.size() >= 2 && string::strcasecmp("ntlm", v[0]) == 0) - return v[1]; - } - } - return ""; - } - - void ntlm_auth_phase_1(HTTPProxy::ProxyAuthenticate& pa) - { - OPENVPN_LOG("Proxy method: NTLM" << std::endl << pa.to_string()); - - const std::string phase_1_reply = HTTPProxy::NTLM::phase_1(); - - std::ostringstream os; - gen_headers(os); - os << "Proxy-Connection: Keep-Alive\r\n"; - os << "Proxy-Authorization: NTLM " << phase_1_reply << "\r\n"; - - http_request = os.str(); - reset(); - ntlm_phase_2_response_pending = true; - start_connect_(); - } - - void ntlm_auth_phase_2_pre() - { - // if content exists, drain it first, then progress to ntlm_auth_phase_2 - const std::string content_length_str = http_reply.headers.get_value_trim("content-length"); - const unsigned int content_length = parse_number_throw<unsigned int>(content_length_str, "content-length"); - if (content_length) - drain_content_length = content_length; - else - ntlm_auth_phase_2(); - } - - void ntlm_auth_phase_2() - { - ntlm_phase_2_response_pending = false; - - if (http_reply.status_code != HTTP::Status::ProxyAuthenticationRequired) - throw Exception("NTLM phase-2 status is not ProxyAuthenticationRequired"); - - const std::string phase_2_response = get_ntlm_phase_2_response(); - if (!phase_2_response.empty()) - ntlm_auth_phase_3(phase_2_response); - else - throw Exception("NTLM phase-2 response missing"); - } - - void ntlm_auth_phase_3(const std::string& phase_2_response) - { - // do the NTLMv2 handshake - try { - //OPENVPN_LOG("NTLM phase 3: " << phase_2_response); - - const std::string phase_3_reply = HTTPProxy::NTLM::phase_3( - *config->digest_factory, - phase_2_response, - config->http_proxy_options->username, - config->http_proxy_options->password, - *config->rng); - - std::ostringstream os; - gen_headers(os); - os << "Proxy-Connection: Keep-Alive\r\n"; - os << "Proxy-Authorization: NTLM " << phase_3_reply << "\r\n"; - - http_request = os.str(); - reset_partial(); - http_proxy_send(); - } - catch (const std::exception& e) - { - proxy_error(Error::PROXY_NEED_CREDS, std::string("NTLM Auth: ") + e.what()); - } - } - - void gen_headers(std::ostringstream& os) - { - bool host_header_sent = false; - - // emit custom headers - { - const Options::CustomHeaderList& headers = config->http_proxy_options->headers; - for (Options::CustomHeaderList::const_iterator i = headers.begin(); i != headers.end(); ++i) - { - const Options::CustomHeader& h = **i; - if (!h.p2.empty()) - { - os << h.p1 << ": " << h.p2 << "\r\n"; - if (!string::strcasecmp(h.p1, "host")) - host_header_sent = true; - } - else - { - os << h.p1 << "\r\n"; - const std::string h5 = h.p1.substr(0, 5); - if (!string::strcasecmp(h5, "host:")) - host_header_sent = true; - } - } - } - - // emit user-agent header - { - const std::string& user_agent = config->http_proxy_options->user_agent; - if (!user_agent.empty()) - os << "User-Agent: " << user_agent << "\r\n"; - } - - // emit host header - if (!host_header_sent) - os << "Host: " << server_host << "\r\n"; - } - - void stop_() - { - if (!halt) - { - halt = true; - if (impl) - impl->stop(); - - socket.close(); - async_resolve_cancel(); - } - } - - // do DNS resolve - void resolve_callback(const openvpn_io::error_code& error, - openvpn_io::ip::tcp::resolver::results_type results) override - { - // release resolver allocated resources - async_resolve_cancel(); - - if (!halt) - { - if (!error) - { - // save resolved endpoint list in proxy remote_list - proxy_remote_list().set_endpoint_range(results); - start_connect_(); - } - else - { - std::ostringstream os; - os << "DNS resolve error on '" << proxy_host << "' for TCP (HTTP proxy): " << error.message(); - config->stats->error(Error::RESOLVE_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - void reset() - { - stop(); - halt = false; - proxy_response_limit.reset(); - proxy_established = false; - reset_partial(); - } - - void reset_partial() - { - http_reply_status = HTTP::ReplyParser::pending; - http_reply.reset(); - http_parser.reset(); - ntlm_phase_2_response_pending = false; - drain_content_length = 0; - html_skip.reset(); - } - - // do TCP connect - void start_connect_() - { - proxy_remote_list().get_endpoint(server_endpoint); - OPENVPN_LOG("Contacting " << server_endpoint << " via HTTP Proxy"); - parent->transport_wait_proxy(); - socket.open(server_endpoint.protocol()); - - if (config->socket_protect) - { - if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) - { - config->stats->error(Error::SOCKET_PROTECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, "socket_protect error (HTTP Proxy)"); - return; - } - } - - socket.set_option(openvpn_io::ip::tcp::no_delay(true)); - socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->start_impl_(error); - }); - } - - // start I/O on TCP socket - void start_impl_(const openvpn_io::error_code& error) - { - if (!halt) - { - if (!error) - { - parent->transport_wait(); - impl.reset(new LinkImpl(this, - socket, - 0, // send_queue_max_size is unlimited because we regulate size in cliproto.hpp - config->free_list_max_size, - (*config->frame)[Frame::READ_LINK_TCP], - config->stats)); - impl->set_raw_mode(true); - impl->start(); - ++n_transactions; - - // tell proxy to connect through to OpenVPN server - http_proxy_send(); - } - else - { - proxy_remote_list().next(); - - std::ostringstream os; - os << "TCP connect error on '" << proxy_host << ':' << proxy_port << "' (" << server_endpoint << ") for TCP-via-HTTP-proxy session: " << error.message(); - config->stats->error(Error::TCP_CONNECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - void http_proxy_send() - { - BufferAllocated buf; - create_http_connect_msg(buf); - send(buf); - } - - // create HTTP CONNECT message - void create_http_connect_msg(BufferAllocated& buf) - { - std::ostringstream os; - const std::string& http_version = config->http_proxy_options->http_version; - os << "CONNECT " << server_host << ':' << server_port << " HTTP/"; - if (!http_version.empty()) - os << http_version; - else - os << "1.0"; - os << "\r\n"; - if (!http_request.empty()) - os << http_request; - else - gen_headers(os); - os << "\r\n"; - const std::string str = os.str(); - http_request = ""; - - OPENVPN_LOG_NTNL("TO PROXY: " << str); - - config->frame->prepare(Frame::WRITE_HTTP, buf); - buf_write_string(buf, str); - } - - RemoteList& remote_list() const { return *config->remote_list; } - RemoteList& proxy_remote_list() const { return *config->http_proxy_options->proxy_server; } - - std::string proxy_host; - std::string proxy_port; - - std::string server_host; - std::string server_port; - - openvpn_io::ip::tcp::socket socket; - ClientConfig::Ptr config; - TransportClientParent* parent; - LinkImpl::Ptr impl; - LinkImpl::protocol::endpoint server_endpoint; - bool halt; - - unsigned int n_transactions; - ProxyResponseLimit proxy_response_limit; - bool proxy_established; - HTTP::ReplyParser::status http_reply_status; - HTTP::Reply http_reply; - HTTP::ReplyParser http_parser; - std::string http_request; - - bool ntlm_phase_2_response_pending; - size_t drain_content_length; - - std::unique_ptr<HTTP::HTMLSkip> html_skip; - }; - - inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, TransportClientParent* parent) - { - return TransportClient::Ptr(new Client(io_context, this, parent)); - } - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/relay.hpp b/Sources/OpenVPN3/openvpn/transport/client/relay.hpp deleted file mode 100644 index 7f6d18e..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/relay.hpp +++ /dev/null @@ -1,165 +0,0 @@ -// 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-2020 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/>. - -// Create a special transport factory that persists an existing -// transport client. This is used to preserve the transport -// socket when other client components are restarted after -// a RELAY message is received from the server. - -#ifndef OPENVPN_TRANSPORT_CLIENT_RELAY_H -#define OPENVPN_TRANSPORT_CLIENT_RELAY_H - -#include <memory> - -#include <openvpn/transport/client/transbase.hpp> - -namespace openvpn { - class TransportRelayFactory : public TransportClientFactory - { - public: - TransportRelayFactory(openvpn_io::io_context& io_context, - TransportClient::Ptr transport, - TransportClientParent* old_parent) - : io_context_(io_context), - transport_(std::move(transport)), - null_parent_(new NullParent(old_parent)) - { - // Temporarily point transport to our null parent - transport_->transport_reparent(null_parent_.get()); - } - - class TransportClientNull : public TransportClient - { - public: - TransportClientNull(TransportClient* old) - : endpoint_(old->server_endpoint_addr()), - protocol_(old->transport_protocol()) - { - old->server_endpoint_info(host_, port_, proto_, ip_addr_); - } - - private: - virtual void transport_start() {} - virtual void stop() {} - virtual bool transport_send_const(const Buffer& buf) { return false; } - virtual bool transport_send(BufferAllocated& buf) { return false; } - virtual bool transport_send_queue_empty() { return false; } - virtual bool transport_has_send_queue() { return false; } - virtual unsigned int transport_send_queue_size() { return 0; } - virtual void transport_stop_requeueing() { } - virtual void reset_align_adjust(const size_t align_adjust) {} - virtual void transport_reparent(TransportClientParent* parent) {} - - virtual IP::Addr server_endpoint_addr() const - { - return endpoint_; - } - - virtual Protocol transport_protocol() const - { - return protocol_; - } - - virtual void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const - { - host = host_; - port = port_; - proto = proto_; - ip_addr = ip_addr_; - } - - IP::Addr endpoint_; - Protocol protocol_; - std::string host_; - std::string port_; - std::string proto_; - std::string ip_addr_; - }; - - private: - class NullParent : public TransportClientParent - { - public: - NullParent(TransportClientParent* old_parent) - : is_openvpn_protocol(old_parent->transport_is_openvpn_protocol()) - { - } - - private: - virtual void transport_recv(BufferAllocated& buf) {} - virtual void transport_needs_send() {} - - virtual void transport_error(const Error::Type fatal_err, const std::string& err_text) - { - OPENVPN_LOG("TransportRelayFactory: Transport Error in null parent: " << Error::name(fatal_err) << " : " << err_text); - } - - virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text) - { - OPENVPN_LOG("TransportRelayFactory: Proxy Error in null parent: " << Error::name(fatal_err) << " : " << err_text); - } - - // Return true if we are transporting OpenVPN protocol - virtual bool transport_is_openvpn_protocol() { return is_openvpn_protocol; } - - // progress notifications - virtual void transport_pre_resolve() {} - virtual void transport_wait_proxy() {} - virtual void transport_wait() {} - virtual void transport_connecting() {} - - // Return true if keepalive parameter(s) are enabled. - virtual bool is_keepalive_enabled() const { return false; } - - // Disable keepalive for rest of session, but fetch - // the keepalive parameters (in seconds). - virtual void disable_keepalive(unsigned int& keepalive_ping, unsigned int& keepalive_timeout) - { - keepalive_ping = 0; - keepalive_timeout = 0; - } - - bool is_openvpn_protocol; - }; - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) override - { - // io_context MUST stay consistent - if (&io_context != &io_context_) - throw Exception("TransportRelayFactory: inconsistent io_context"); - - transport_->transport_reparent(parent); - return transport_; - } - - virtual bool is_relay() override - { - return true; - } - - openvpn_io::io_context& io_context_; // only used to verify consistency - TransportClient::Ptr transport_; // the persisted transport - std::unique_ptr<TransportClientParent> null_parent_; // placeholder for TransportClient parent before reparenting - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/tcpcli.hpp b/Sources/OpenVPN3/openvpn/transport/client/tcpcli.hpp deleted file mode 100644 index cd178bd..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/tcpcli.hpp +++ /dev/null @@ -1,399 +0,0 @@ -// 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-2020 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/>. - -// TCP transport object specialized for client. - -#ifndef OPENVPN_TRANSPORT_CLIENT_TCPCLI_H -#define OPENVPN_TRANSPORT_CLIENT_TCPCLI_H - -#include <sstream> - -#include <openvpn/io/io.hpp> - -#include <openvpn/transport/tcplink.hpp> -#ifdef OPENVPN_TLS_LINK -#include <openvpn/transport/tlslink.hpp> -#endif -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/client/remotelist.hpp> - -namespace openvpn { - namespace TCPTransport { - - class ClientConfig : public TransportClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - RemoteList::Ptr remote_list; - size_t free_list_max_size; - Frame::Ptr frame; - SessionStats::Ptr stats; - - SocketProtect* socket_protect; - -#ifdef OPENVPN_TLS_LINK - bool use_tls = false; - std::string tls_ca; -#endif - -#ifdef OPENVPN_GREMLIN - Gremlin::Config::Ptr gremlin_config; -#endif - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent); - - private: - ClientConfig() - : free_list_max_size(8), - socket_protect(nullptr) - {} - }; - - class Client : public TransportClient, AsyncResolvableTCP - { - typedef RCPtr<Client> Ptr; - - typedef Link<openvpn_io::ip::tcp, Client*, false> LinkImpl; -#ifdef OPENVPN_TLS_LINK - typedef TLSLink<openvpn_io::ip::tcp, Client*, false> LinkImplTLS; -#endif - - friend class ClientConfig; // calls constructor - friend LinkImpl::Base; // calls tcp_read_handler - - public: - void transport_start() override - { - if (!impl) - { - halt = false; - stop_requeueing = false; - if (config->remote_list->endpoint_available(&server_host, - &server_port, - &server_protocol)) - { - start_connect_(); - } - else - { - parent->transport_pre_resolve(); - - async_resolve_name(server_host, server_port); - } - } - } - - bool transport_send_const(const Buffer& buf) override - { - return send_const(buf); - } - - bool transport_send(BufferAllocated& buf) override - { - return send(buf); - } - - bool transport_send_queue_empty() override - { - if (impl) - return impl->send_queue_empty(); - else - return false; - } - - bool transport_has_send_queue() override - { - return true; - } - - unsigned int transport_send_queue_size() override - { - if (impl) - return impl->send_queue_size(); - else - return 0; - } - - void reset_align_adjust(const size_t align_adjust) override - { - if (impl) - impl->reset_align_adjust(align_adjust); - } - - void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const override - { - host = server_host; - port = server_port; - const IP::Addr addr = server_endpoint_addr(); - proto = server_protocol.str(); - ip_addr = addr.to_string(); - } - - IP::Addr server_endpoint_addr() const override - { - return IP::Addr::from_asio(server_endpoint.address()); - } - - Protocol transport_protocol() const override - { - return server_protocol; - } - - void stop() override { stop_(); } - ~Client() override { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TransportClientParent* parent_arg) - : AsyncResolvableTCP(io_context_arg), - io_context(io_context_arg), - socket(io_context_arg), - config(config_arg), - parent(parent_arg), - resolver(io_context_arg), - halt(false), - stop_requeueing(false) - { - } - - void transport_reparent(TransportClientParent* parent_arg) override - { - parent = parent_arg; - } - - void transport_stop_requeueing() override - { - stop_requeueing = true; - } - - bool send_const(const Buffer& cbuf) - { - if (impl) - { - BufferAllocated buf(cbuf, 0); - return impl->send(buf); - } - else - return false; - } - - bool send(BufferAllocated& buf) - { - if (impl) - return impl->send(buf); - else - return false; - } - - void tcp_eof_handler() // called by LinkImpl::Base - { - config->stats->error(Error::NETWORK_EOF_ERROR); - tcp_error_handler("NETWORK_EOF_ERROR"); - } - - bool tcp_read_handler(BufferAllocated& buf) // called by LinkImpl::Base - { - parent->transport_recv(buf); - return !stop_requeueing; - } - - void tcp_write_queue_needs_send() // called by LinkImpl::Base - { - parent->transport_needs_send(); - } - - void tcp_error_handler(const char *error) // called by LinkImpl::Base - { - std::ostringstream os; - os << "Transport error on '" << server_host << ": " << error; - stop(); - parent->transport_error(Error::TRANSPORT_ERROR, os.str()); - } - - void stop_() - { - if (!halt) - { - halt = true; - if (impl) - impl->stop(); - - socket.close(); - resolver.cancel(); - async_resolve_cancel(); - } - } - - // do DNS resolve - void resolve_callback(const openvpn_io::error_code& error, - openvpn_io::ip::tcp::resolver::results_type results) override - { - if (!halt) - { - if (!error) - { - // save resolved endpoint list in remote_list - config->remote_list->set_endpoint_range(results); - start_connect_(); - } - else - { - std::ostringstream os; - os << "DNS resolve error on '" << server_host << "' for " << server_protocol.str() << " session: " << error.message(); - config->stats->error(Error::RESOLVE_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - // do TCP connect - void start_connect_() - { - config->remote_list->get_endpoint(server_endpoint); - OPENVPN_LOG("Contacting " << server_endpoint << " via " - << server_protocol.str()); - parent->transport_wait(); - socket.open(server_endpoint.protocol()); - - if (config->socket_protect) - { - if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) - { - config->stats->error(Error::SOCKET_PROTECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, "socket_protect error (" + std::string(server_protocol.str()) + ")"); - return; - } - } - - socket.set_option(openvpn_io::ip::tcp::no_delay(true)); - socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->start_impl_(error); - }); - } - - // start I/O on TCP socket - void start_impl_(const openvpn_io::error_code& error) - { - if (!halt) - { - if (!error) - { -#ifdef OPENVPN_TLS_LINK - if (config->use_tls) - { - int flags = SSLConst::LOG_VERIFY_STATUS|SSLConst::ENABLE_CLIENT_SNI; - SSLLib::SSLAPI::Config::Ptr ssl_conf; - ssl_conf.reset(new SSLLib::SSLAPI::Config()); - ssl_conf->set_mode(Mode(Mode::CLIENT)); - ssl_conf->set_local_cert_enabled(false); - ssl_conf->set_frame(config->frame); - ssl_conf->set_rng(new SSLLib::RandomAPI(false)); - - if (!config->tls_ca.empty()) - { - ssl_conf->load_ca(config->tls_ca, true); - } - else - { - flags |= SSLConst::NO_VERIFY_PEER; - } - - ssl_conf->set_flags(flags); - ssl_factory = ssl_conf->new_factory(); - - impl.reset(new LinkImplTLS(this, - io_context, - socket, - 0, - config->free_list_max_size, - config->frame, - config->stats, - ssl_factory)); - } - else -#endif - impl.reset(new LinkImpl(this, - socket, - 0, // send_queue_max_size is unlimited because we regulate size in cliproto.hpp - config->free_list_max_size, - (*config->frame)[Frame::READ_LINK_TCP], - config->stats)); - -#ifdef OPENVPN_GREMLIN - impl->gremlin_config(config->gremlin_config); -#endif - impl->start(); - if (!parent->transport_is_openvpn_protocol()) - impl->set_raw_mode(true); - parent->transport_connecting(); - } - else - { - std::ostringstream os; - os << server_protocol.str() << " connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message(); - config->stats->error(Error::TCP_CONNECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - std::string server_host; - std::string server_port; - Protocol server_protocol; - - openvpn_io::io_context& io_context; - openvpn_io::ip::tcp::socket socket; - ClientConfig::Ptr config; - TransportClientParent* parent; - LinkBase::Ptr impl; - openvpn_io::ip::tcp::resolver resolver; - LinkImpl::Base::protocol::endpoint server_endpoint; - bool halt; - bool stop_requeueing; - -#ifdef OPENVPN_TLS_LINK - SSLFactoryAPI::Ptr ssl_factory; -#endif - }; - - inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) - { - return TransportClient::Ptr(new Client(io_context, this, parent)); - } - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/client/transbase.hpp b/Sources/OpenVPN3/openvpn/transport/client/transbase.hpp deleted file mode 100644 index 32d1d76..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/transbase.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// 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-2020 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/>. - -// Abstract base classes for client transport objects that implement UDP, TCP, -// HTTP Proxy, etc. - -#ifndef OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H -#define OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H - -#include <string> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/transport/protocol.hpp> - -namespace openvpn { - struct TransportClientParent; - - // Base class for client transport object. - struct TransportClient : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<TransportClient> Ptr; - - virtual void transport_start() = 0; - virtual void stop() = 0; - virtual bool transport_send_const(const Buffer& buf) = 0; - virtual bool transport_send(BufferAllocated& buf) = 0; - virtual bool transport_send_queue_empty() = 0; - virtual bool transport_has_send_queue() = 0; - virtual void transport_stop_requeueing() = 0; - virtual unsigned int transport_send_queue_size() = 0; - virtual void reset_align_adjust(const size_t align_adjust) = 0; - virtual IP::Addr server_endpoint_addr() const = 0; - virtual void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const = 0; - virtual Protocol transport_protocol() const = 0; - virtual void transport_reparent(TransportClientParent* parent) = 0; - }; - - // Base class for parent of client transport object, used by client transport - // objects to communicate received data packets, exceptions, and progress - // notifications. - struct TransportClientParent - { - virtual void transport_recv(BufferAllocated& buf) = 0; - virtual void transport_needs_send() = 0; // notification that send queue is empty - virtual void transport_error(const Error::Type fatal_err, const std::string& err_text) = 0; - virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text) = 0; - - // Return true if we are transporting OpenVPN protocol - virtual bool transport_is_openvpn_protocol() = 0; - - // progress notifications - virtual void transport_pre_resolve() = 0; - virtual void transport_wait_proxy() = 0; - virtual void transport_wait() = 0; - virtual void transport_connecting() = 0; - - // Return true if keepalive parameter(s) are enabled. - virtual bool is_keepalive_enabled() const = 0; - - // Disable keepalive for rest of session, but fetch - // the keepalive parameters (in seconds). - virtual void disable_keepalive(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) = 0; - - virtual ~TransportClientParent() {} - }; - - // Factory for client transport object. - struct TransportClientFactory : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<TransportClientFactory> Ptr; - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) = 0; - virtual bool is_relay() { return false; } - }; - -} // namespace openvpn - -#endif // OPENVPN_TRANSPORT_CLIENT_TRANSBASE_H diff --git a/Sources/OpenVPN3/openvpn/transport/client/udpcli.hpp b/Sources/OpenVPN3/openvpn/transport/client/udpcli.hpp deleted file mode 100644 index c54ce09..0000000 --- a/Sources/OpenVPN3/openvpn/transport/client/udpcli.hpp +++ /dev/null @@ -1,336 +0,0 @@ -// 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-2020 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/>. - -// UDP transport object specialized for client. - -#ifndef OPENVPN_TRANSPORT_CLIENT_UDPCLI_H -#define OPENVPN_TRANSPORT_CLIENT_UDPCLI_H - -#include <sstream> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/bigmutex.hpp> -#include <openvpn/common/likely.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/transport/udplink.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/transport/socket_protect.hpp> -#include <openvpn/client/remotelist.hpp> - -namespace openvpn { - namespace UDPTransport { - - class ClientConfig : public TransportClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - RemoteList::Ptr remote_list; - bool server_addr_float; - bool synchronous_dns_lookup; - int n_parallel; - Frame::Ptr frame; - SessionStats::Ptr stats; - - SocketProtect* socket_protect; - -#ifdef OPENVPN_GREMLIN - Gremlin::Config::Ptr gremlin_config; -#endif - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent); - - private: - ClientConfig() - : server_addr_float(false), - synchronous_dns_lookup(false), - n_parallel(8), - socket_protect(nullptr) - {} - }; - - class Client : public TransportClient, AsyncResolvableUDP - { - typedef RCPtr<Client> Ptr; - - friend class ClientConfig; // calls constructor - friend class Link<Client*>; // calls udp_read_handler - - typedef Link<Client*> LinkImpl; - - public: - void transport_start() override - { - if (!impl) - { - halt = false; - if (config->remote_list->endpoint_available(&server_host, &server_port, nullptr)) - { - start_connect_(); - } - else - { - parent->transport_pre_resolve(); - - if (config->synchronous_dns_lookup) - { - openvpn_io::error_code error; - openvpn_io::ip::udp::resolver::results_type results = resolver.resolve(server_host, server_port, error); - resolve_callback(error, results); - } - else - { - async_resolve_name(server_host, server_port); - } - } - } - } - - bool transport_send_const(const Buffer& buf) override - { - return send(buf); - } - - bool transport_send(BufferAllocated& buf) override - { - return send(buf); - } - - bool transport_send_queue_empty() override // really only has meaning for TCP - { - return false; - } - - bool transport_has_send_queue() override - { - return false; - } - - void transport_stop_requeueing() override { } - - unsigned int transport_send_queue_size() override - { - return 0; - } - - void reset_align_adjust(const size_t align_adjust) override - { - if (impl) - impl->reset_align_adjust(align_adjust); - } - - void server_endpoint_info(std::string& host, std::string& port, std::string& proto, std::string& ip_addr) const override - { - host = server_host; - port = server_port; - const IP::Addr addr = server_endpoint_addr(); - proto = "UDP"; - proto += addr.version_string(); - ip_addr = addr.to_string(); - } - - IP::Addr server_endpoint_addr() const override - { - return IP::Addr::from_asio(server_endpoint.address()); - } - - Protocol transport_protocol() const override - { - if (server_endpoint.address().is_v4()) - return Protocol(Protocol::UDPv4); - else if (server_endpoint.address().is_v6()) - return Protocol(Protocol::UDPv6); - else - return Protocol(); - } - - void stop() override { stop_(); } - ~Client() override { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TransportClientParent* parent_arg) - : AsyncResolvableUDP(io_context_arg), - socket(io_context_arg), - config(config_arg), - parent(parent_arg), - resolver(io_context_arg), - halt(false) - { - } - - void transport_reparent(TransportClientParent* parent_arg) override - { - parent = parent_arg; - } - - bool send(const Buffer& buf) - { - if (impl) - { - const int err = impl->send(buf, nullptr); - if (unlikely(err)) - { - // While UDP errors are generally ignored, certain - // errors should be forwarded up to the higher levels. -#ifdef OPENVPN_PLATFORM_IPHONE - if (err == EADDRNOTAVAIL) - { - stop(); - parent->transport_error(Error::TRANSPORT_ERROR, "EADDRNOTAVAIL: Can't assign requested address"); - } -#endif - return false; - } - else - return true; - } - else - return false; - } - - void udp_read_handler(PacketFrom::SPtr& pfp) // called by LinkImpl - { - if (config->server_addr_float || pfp->sender_endpoint == server_endpoint) - parent->transport_recv(pfp->buf); - else - config->stats->error(Error::BAD_SRC_ADDR); - } - - void stop_() - { - if (!halt) - { - halt = true; - if (impl) - impl->stop(); - socket.close(); - resolver.cancel(); - async_resolve_cancel(); - } - } - - // called after DNS resolution has succeeded or failed - void resolve_callback(const openvpn_io::error_code& error, - openvpn_io::ip::udp::resolver::results_type results) override - { - if (!halt) - { - if (!error) - { - // save resolved endpoint list in remote_list - config->remote_list->set_endpoint_range(results); - start_connect_(); - } - else - { - std::ostringstream os; - os << "DNS resolve error on '" << server_host << "' for UDP session: " << error.message(); - config->stats->error(Error::RESOLVE_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - // do UDP connect - void start_connect_() - { - config->remote_list->get_endpoint(server_endpoint); - OPENVPN_LOG("Contacting " << server_endpoint << " via UDP"); - parent->transport_wait(); - socket.open(server_endpoint.protocol()); - - if (config->socket_protect) - { - if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr())) - { - config->stats->error(Error::SOCKET_PROTECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, "socket_protect error (UDP)"); - return; - } - } - - socket.async_connect(server_endpoint, [self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - self->start_impl_(error); - }); - } - - // start I/O on UDP socket - void start_impl_(const openvpn_io::error_code& error) - { - if (!halt) - { - if (!error) - { - impl.reset(new LinkImpl(this, - socket, - (*config->frame)[Frame::READ_LINK_UDP], - config->stats)); -#ifdef OPENVPN_GREMLIN - impl->gremlin_config(config->gremlin_config); -#endif - impl->start(config->n_parallel); - parent->transport_connecting(); - } - else - { - std::ostringstream os; - os << "UDP connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message(); - config->stats->error(Error::UDP_CONNECT_ERROR); - stop(); - parent->transport_error(Error::UNDEF, os.str()); - } - } - } - - std::string server_host; - std::string server_port; - - openvpn_io::ip::udp::socket socket; - ClientConfig::Ptr config; - TransportClientParent* parent; - LinkImpl::Ptr impl; - openvpn_io::ip::udp::resolver resolver; - UDPTransport::AsioEndpoint server_endpoint; - bool halt; - }; - - inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context& io_context, - TransportClientParent* parent) - { - return TransportClient::Ptr(new Client(io_context, this, parent)); - } - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/dco.hpp b/Sources/OpenVPN3/openvpn/transport/dco.hpp deleted file mode 100644 index 88ced97..0000000 --- a/Sources/OpenVPN3/openvpn/transport/dco.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// 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-2020 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_TRANSPORT_DCO_H -#define OPENVPN_TRANSPORT_DCO_H - -#include <string> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/transport/protocol.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/tun/layer.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> - -namespace openvpn { - struct DCO : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<DCO> Ptr; - - struct TransportConfig - { - TransportConfig() - : server_addr_float(false) - { - } - - Protocol protocol; - RemoteList::Ptr remote_list; - bool server_addr_float; - Frame::Ptr frame; - SessionStats::Ptr stats; - SocketProtect* socket_protect = nullptr; - }; - - struct TunConfig - { - TunConfig() = default; - - TunProp::Config tun_prop; - Stop* stop = nullptr; - }; - - - virtual TunClientFactory::Ptr new_tun_factory(const TunConfig& conf, const OptionList& opt) = 0; - virtual TransportClientFactory::Ptr new_transport_factory(const TransportConfig& conf) = 0; - - TunBuilderBase* builder = nullptr; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/gremlin.hpp b/Sources/OpenVPN3/openvpn/transport/gremlin.hpp deleted file mode 100644 index cb75680..0000000 --- a/Sources/OpenVPN3/openvpn/transport/gremlin.hpp +++ /dev/null @@ -1,224 +0,0 @@ -// 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-2020 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_TRANSPORT_GREMLIN_H -#define OPENVPN_TRANSPORT_GREMLIN_H - -#include <memory> -#include <deque> -#include <vector> -#include <utility> -#include <sstream> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/random/mtrandapi.hpp> - -namespace openvpn { - namespace Gremlin { - - OPENVPN_EXCEPTION(gremlin_error); - - struct DelayedQueue : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<DelayedQueue> Ptr; - - DelayedQueue(openvpn_io::io_context& io_context, - const unsigned int delay_ms) - : dur(Time::Duration::milliseconds(delay_ms)), - next_event(io_context) - { - } - - template <class F> - void queue(F&& func_arg) - { - const bool empty = events.empty(); - events.emplace_back(new Event<F>(Time::now() + dur, std::move(func_arg))); - if (empty) - set_timer(); - } - - size_t size() const - { - return events.size(); - } - - void stop() - { - next_event.cancel(); - } - - private: - struct EventBase - { - virtual void call() = 0; - virtual const Time& fire_time() = 0; - virtual ~EventBase() {} - }; - - template <class F> - struct Event : public EventBase - { - public: - Event(Time fire_arg, F&& func_arg) - : fire(fire_arg), - func(std::move(func_arg)) - { - } - - virtual void call() - { - func(); - } - - virtual const Time& fire_time() - { - return fire; - } - - private: - Time fire; - F func; - }; - - void set_timer() - { - if (events.empty()) - return; - EventBase& ev = *events.front(); - next_event.expires_at(ev.fire_time()); - next_event.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - { - EventBase& ev = *self->events.front(); - ev.call(); - self->events.pop_front(); - self->set_timer(); - } - }); - } - - Time::Duration dur; - AsioTimer next_event; - std::deque<std::unique_ptr<EventBase>> events; - }; - - class Config : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Config> Ptr; - - Config(const std::string& config_str) - { - const std::vector<std::string> parms = string::split(config_str, ','); - if (parms.size() < 4) - throw gremlin_error("need 4 comma-separated values for send_delay_ms, recv_delay_ms, send_drop_prob, recv_drop_prob"); - if (!parse_number(string::trim_copy(parms[0]), send_delay_ms)) - throw gremlin_error("send_delay_ms"); - if (!parse_number(string::trim_copy(parms[1]), recv_delay_ms)) - throw gremlin_error("recv_delay_ms"); - if (!parse_number(string::trim_copy(parms[2]), send_drop_probability)) - throw gremlin_error("send_drop_probability"); - if (!parse_number(string::trim_copy(parms[3]), recv_drop_probability)) - throw gremlin_error("recv_drop_probability"); - } - - std::string to_string() const - { - std::ostringstream os; - os << '[' << send_delay_ms << ',' << recv_delay_ms << ',' << send_drop_probability << ',' << recv_drop_probability << ']'; - return os.str(); - } - - unsigned int send_delay_ms = 0; - unsigned int recv_delay_ms = 0; - unsigned int send_drop_probability = 0; - unsigned int recv_drop_probability = 0; - }; - - class SendRecvQueue - { - public: - SendRecvQueue(openvpn_io::io_context& io_context, - const Config::Ptr& conf_arg, - const bool tcp_arg) - : conf(conf_arg), - send(new DelayedQueue(io_context, conf->send_delay_ms)), - recv(new DelayedQueue(io_context, conf->recv_delay_ms)), - tcp(tcp_arg) - { - } - - template <class F> - void send_queue(F&& func_arg) - { - if (tcp || flip(conf->send_drop_probability)) - send->queue(std::move(func_arg)); - } - - template <class F> - void recv_queue(F&& func_arg) - { - if (tcp || flip(conf->recv_drop_probability)) - recv->queue(std::move(func_arg)); - } - - size_t send_size() const - { - return send->size(); - } - - size_t recv_size() const - { - return recv->size(); - } - - void stop() - { - send->stop(); - recv->stop(); - } - - private: - bool flip(const unsigned int prob) - { - if (prob) - return ri.randrange(prob) != 0; - else - return true; - } - - Config::Ptr conf; - MTRand ri; - DelayedQueue::Ptr send; - DelayedQueue::Ptr recv; - bool tcp; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/mssfix.hpp b/Sources/OpenVPN3/openvpn/transport/mssfix.hpp deleted file mode 100644 index e275f6e..0000000 --- a/Sources/OpenVPN3/openvpn/transport/mssfix.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// 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-2020 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); - } - } - } - } - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/transport/mutate.hpp b/Sources/OpenVPN3/openvpn/transport/mutate.hpp deleted file mode 100644 index d45ba61..0000000 --- a/Sources/OpenVPN3/openvpn/transport/mutate.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// 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-2020 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_TRANSPORT_MUTATE_H -#define OPENVPN_TRANSPORT_MUTATE_H - -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/buffer.hpp> - -namespace openvpn { - - class TransportMutateStream : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TransportMutateStream> Ptr; - - virtual void pre_send(BufferAllocated& buf) = 0; - virtual void post_recv(BufferAllocated& buf) = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/pktstream.hpp b/Sources/OpenVPN3/openvpn/transport/pktstream.hpp deleted file mode 100644 index e0a51b5..0000000 --- a/Sources/OpenVPN3/openvpn/transport/pktstream.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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-2020 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_TRANSPORT_PKTSTREAM_H -#define OPENVPN_TRANSPORT_PKTSTREAM_H - -#include <algorithm> // for std::min -#include <cstdint> // for std::uint16_t, etc. - -#include <openvpn/common/exception.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> - -namespace openvpn { - - // Used to encapsulate OpenVPN packets onto a stream transport such as TCP, - // or extract them from the stream. - class PacketStream - { - public: - OPENVPN_SIMPLE_EXCEPTION(embedded_packet_size_error); - OPENVPN_SIMPLE_EXCEPTION(packet_not_fully_formed); - - PacketStream() : declared_size_defined(false) {} - - // Add stream fragment to packet that we are building up. - // Data will be read from buf. On return buf may still contain - // residual data. If function is able to use all of buf, it may - // grab ownership of it, replacing buf as returned to caller with - // an empty (but possibly pre-allocated) BufferAllocated object. - void put(BufferAllocated& buf, const Frame::Context& frame_context) - { - if (buf.defined()) - { - if (!declared_size_defined && !buffer.defined()) - { - if (size_defined(buf)) - { - extract_size(buf, frame_context); - if (buf.size() == declared_size) // packet is correctly sized - buffer.swap(buf); - else if (buf.size() < declared_size) // packet is undersized - { - if (buf.offset() + declared_size + frame_context.tailroom() <= buf.capacity()) - buffer.swap(buf); - else - { - buffer.swap(buf); - frame_context.realign(buffer); - } - } - else // packet is oversized - { - frame_context.prepare(buffer); - const unsigned char *data = buf.read_alloc(declared_size); - buffer.write(data, declared_size); - } - } - else // rare case where packet fragment is too small to contain embedded size - { - buffer.swap(buf); - frame_context.realign(buffer); - } - } - else - { - while (!declared_size_defined) - { - if (buf.empty()) - return; - buffer.push_back(buf.pop_front()); - if (size_defined(buffer)) - extract_size(buffer, frame_context); - } - if (buffer.size() < declared_size) - { - const size_t needed = std::min(declared_size - buffer.size(), buf.size()); - const unsigned char *data = buf.read_alloc(needed); - buffer.write(data, needed); - } - } - } - } - - // returns true if get() may be called to return fully formed packet - bool ready() const - { - return declared_size_defined && buffer.size() >= declared_size; - } - - // return fully formed packet as ret. ret, as passed to method, will - // be grabbed, reset, and subsequently used internally. - void get(BufferAllocated& ret) - { - if (declared_size_defined && buffer.size() == declared_size) - { - ret.swap(buffer); - buffer.reset_content(); - declared_size_defined = false; - } - else - throw packet_not_fully_formed(); - } - - // prepend uint16_t size to buffer - static void prepend_size(Buffer& buf) - { - const std::uint16_t net_len = htons(buf.size()); - buf.prepend((const unsigned char *)&net_len, sizeof(net_len)); - } - - private: - void extract_size(Buffer& buf, const Frame::Context& frame_context) - { - const size_t size = read_size(buf); - validate_size(size, frame_context); - declared_size = size; - declared_size_defined = true; - } - - static bool size_defined(const Buffer& buf) - { - return buf.size() >= sizeof(std::uint16_t); - } - - static size_t read_size(Buffer& buf) - { - std::uint16_t net_len; - buf.read((unsigned char *)&net_len, sizeof(net_len)); - return ntohs(net_len); - } - - static void validate_size(const size_t size, const Frame::Context& frame_context) - { - if (!size || size > frame_context.payload()) - throw embedded_packet_size_error(); - } - - size_t declared_size; // declared size of packet in leading uint16_t prefix - bool declared_size_defined; // true if declared_size is defined - BufferAllocated buffer; // accumulated packet data - }; -} // namespace openvpn - -#endif // OPENVPN_TRANSPORT_PKTSTREAM_H diff --git a/Sources/OpenVPN3/openvpn/transport/protocol.hpp b/Sources/OpenVPN3/openvpn/transport/protocol.hpp deleted file mode 100644 index 78df59a..0000000 --- a/Sources/OpenVPN3/openvpn/transport/protocol.hpp +++ /dev/null @@ -1,314 +0,0 @@ -// 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-2020 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_TRANSPORT_PROTOCOL_H -#define OPENVPN_TRANSPORT_PROTOCOL_H - -#include <string> -#include <cstdint> // for std::uint32_t, etc. - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/option_error.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { -// A class that encapsulates a transport protocol. - class Protocol - { - public: - enum Type { - NONE, - UDPv4, - TCPv4, - UDPv6, - TCPv6, - TLSv4, // TLS over IPv4 - TLSv6, // TLS over IPv6 - UnixStream, // unix domain socket (stream) - UnixDGram, // unix domain socket (datagram) - NamedPipe, // named pipe (Windows only) - UDP=UDPv4, - TCP=TCPv4, - TLS=TLSv4, - }; - - enum AllowSuffix { - NO_SUFFIX, - CLIENT_SUFFIX, - SERVER_SUFFIX, - }; - - Protocol() : type_(NONE) {} - explicit Protocol(const Type t) : type_(t) {} - Type operator()() const { return type_; } - - bool defined() const { return type_ != NONE; } - - void reset() { type_ = NONE; } - - bool is_udp() const { return type_ == UDPv4 || type_ == UDPv6; } - bool is_tcp() const { return type_ == TCPv4 || type_ == TCPv6; } - bool is_tls() const { return type_ == TLSv4 || type_ == TLSv6; } - bool is_reliable() const { return is_tcp() || is_tls(); } - bool is_ipv6() const { return type_ == UDPv6 || type_ == TCPv6 || type_ == TLSv6; } - bool is_unix() const { return type_ == UnixStream || type_ == UnixDGram; } - bool is_named_pipe() const { return type_ == NamedPipe; } - bool is_local() const { return is_unix() || is_named_pipe(); } - - bool operator==(const Protocol& other) const - { - return type_ == other.type_; - } - - bool operator!=(const Protocol& other) const - { - return type_ != other.type_; - } - - bool transport_match(const Protocol& other) const - { - return transport_proto() == other.transport_proto(); - } - - unsigned int extra_transport_bytes() const - { - return (is_tcp() || is_tls()) ? sizeof(std::uint16_t) : 0; - } - - void mod_addr_version(const IP::Addr& addr) - { - switch (addr.version()) - { - case IP::Addr::UNSPEC: - break; - case IP::Addr::V4: - if (is_udp()) - type_ = UDPv4; - else if (is_tcp()) - type_ = TCPv4; - else if (is_tls()) - type_ = TLSv4; - break; - case IP::Addr::V6: - if (is_udp()) - type_ = UDPv6; - else if (is_tcp()) - type_ = TCPv6; - else if (is_tls()) - type_ = TLSv6; - break; - } - } - - static Protocol parse(const std::string& str, - const AllowSuffix allow_suffix, - const char *title = nullptr) - { - Protocol ret; - if (string::strcasecmp(str, "adaptive") == 0) - return ret; - ret.type_ = parse_type(str, allow_suffix); - if (ret.type_ == NONE) - { - if (!title) - title = "protocol"; - OPENVPN_THROW(option_error, "error parsing " << title << ": " << str); - } - return ret; - } - - static bool is_local_type(const std::string& str) - { - if (str.empty()) - return false; - if (str[0] != 'u' && str[0] != 'U' // unix fast path - && str[0] != 'n' && str[0] != 'N') // named pipe fast path - return false; - const Type type = parse_type(str, NO_SUFFIX); - return type == UnixStream || type == UnixDGram || type == NamedPipe; - } - - int transport_proto() const - { - switch (type_) - { - case UDPv4: - return 0; - case TCPv4: - return 1; - case UDPv6: - return 0; - case TCPv6: - return 1; - case UnixDGram: - return 2; - case UnixStream: - return 3; - case NamedPipe: - return 4; - case TLSv4: - case TLSv6: - return 5; - default: - return -1; - } - } - - const char *str() const - { - switch (type_) - { - case UDPv4: - return "UDPv4"; - case TCPv4: - return "TCPv4"; - case UDPv6: - return "UDPv6"; - case TCPv6: - return "TCPv6"; - case TLSv4: - return "TLS/TCPv4"; - case TLSv6: - return "TLS/TCPv6"; - case UnixStream: - return "UnixStream"; - case UnixDGram: - return "UnixDGram"; - case NamedPipe: - return "NamedPipe"; - default: - return "UNDEF_PROTO"; - } - } - - /* This function returns a parseable string representation of the used - * transport protocol. NOTE: returns nullptr if there is no mapping */ - const char *protocol_to_string() const - { - switch (type_) - { - case UDPv4: - return "udp4"; - case TCPv4: - return "tcp4"; - case UDPv6: - return "udp6"; - case TCPv6: - return "tcp6"; - case TLSv4: - return "tls4"; - case TLSv6: - return "tls6"; - case UnixStream: - return "unix-stream"; - case UnixDGram: - return "unix-dgram"; - case NamedPipe: - return "named-pipe"; - case NONE: - return "adaptive"; - default: - return nullptr; - } - } - - const char *str_client(const bool force_ipv4) const - { - switch (type_) - { - case UDPv4: - return "UDPv4"; - case TCPv4: - return "TCPv4_CLIENT"; - case UDPv6: - return force_ipv4 ? "UDPv4" : "UDPv6"; - case TCPv6: - return force_ipv4 ? "TCPv4_CLIENT" : "TCPv6_CLIENT"; - case TLSv4: - return "TLSv4"; - case TLSv6: - return force_ipv4 ? "TLSv4" : "TLSv6"; - default: - return "UNDEF_PROTO"; - } - } - - private: - static Type parse_type(const std::string& str, - const AllowSuffix allow_suffix) - { - Type ret = NONE; - std::string s = str; - string::to_lower(s); - switch (allow_suffix) - { - case NO_SUFFIX: - break; - case CLIENT_SUFFIX: - if (string::ends_with(s, "-client")) - s = s.substr(0, s.length()-7); - break; - case SERVER_SUFFIX: - if (string::ends_with(s, "-server")) - s = s.substr(0, s.length()-7); - break; - } - if (string::starts_with(s, "unix")) // unix domain socket - { - if (s == "unix-stream") - ret = UnixStream; - else if (s == "unix-dgram") - ret = UnixDGram; - } - else if (s == "named-pipe") // Windows named pipe - ret = NamedPipe; - else if (s.length() >= 3) // udp/tcp - { - const std::string s1 = s.substr(0, 3); - const std::string s2 = s.substr(3); - if (s2 == "" || s2 == "4" || s2 == "v4") - { - if (s1 == "udp") - ret = UDPv4; - else if (s1 == "tcp") - ret = TCPv4; - else if (s1 == "tls") - ret = TLSv4; - } - else if (s2 == "6" || s2 == "v6") - { - if (s1 == "udp") - ret = UDPv6; - else if (s1 == "tcp") - ret = TCPv6; - else if (s1 == "tls") - ret = TLSv6; - } - } - return ret; - } - - Type type_; - }; -} // namespace openvpn - -#endif // OPENVPN_TRANSPORT_PROTOCOL_H diff --git a/Sources/OpenVPN3/openvpn/transport/reconnect_notify.hpp b/Sources/OpenVPN3/openvpn/transport/reconnect_notify.hpp deleted file mode 100644 index 2e899d0..0000000 --- a/Sources/OpenVPN3/openvpn/transport/reconnect_notify.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// 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-2020 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_TRANSPORT_RECONNECT_NOTIFY_H -#define OPENVPN_TRANSPORT_RECONNECT_NOTIFY_H - -namespace openvpn { - class ReconnectNotify { - public: - // When a connection is close to timeout, the core will call this - // method. If it returns false, the core will disconnect with a - // CONNECTION_TIMEOUT event. If true, the core will enter a PAUSE - // state. - virtual bool pause_on_connection_timeout() = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/server/transbase.hpp b/Sources/OpenVPN3/openvpn/transport/server/transbase.hpp deleted file mode 100644 index d1ecc0c..0000000 --- a/Sources/OpenVPN3/openvpn/transport/server/transbase.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// 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-2020 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/>. - -// Abstract base classes for server transport objects that implement UDP, TCP, -// HTTP Proxy, etc. - -#ifndef OPENVPN_TRANSPORT_SERVER_TRANSBASE_H -#define OPENVPN_TRANSPORT_SERVER_TRANSBASE_H - -#include <string> -#include <vector> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/crypto/cryptodc.hpp> -#include <openvpn/tun/server/tunbase.hpp> -#include <openvpn/server/servhalt.hpp> -#include <openvpn/server/peerstats.hpp> -#include <openvpn/server/peeraddr.hpp> -#include <openvpn/ssl/datalimit.hpp> - -namespace openvpn { - - // Base class for server transport object. - struct TransportServer : public RC<thread_unsafe_refcount> - { - typedef RCPtr<TransportServer> Ptr; - - virtual void start() = 0; - virtual void stop() = 0; - virtual std::string local_endpoint_info() const = 0; - virtual IP::Addr local_endpoint_addr() const = 0; - }; - - // Factory for server transport object. - struct TransportServerFactory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<TransportServerFactory> Ptr; - - virtual TransportServer::Ptr new_server_obj(openvpn_io::io_context& io_context) = 0; - }; - - namespace TransportClientInstance { - - // Base class for the per-client-instance state of the TransportServer. - // Each client instance uses this class to send data to the transport layer. - struct Send : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Send> Ptr; - - virtual bool defined() const = 0; - virtual void stop() = 0; - - virtual bool transport_send_const(const Buffer& buf) = 0; - virtual bool transport_send(BufferAllocated& buf) = 0; - - virtual const std::string& transport_info() const = 0; - - // bandwidth stats polling - virtual bool stats_pending() const = 0; - virtual PeerStats stats_poll() = 0; - }; - - // Base class for the client instance receiver. Note that all - // client instance receivers (transport, routing, management, - // etc.) must inherit virtually from RC because the client instance - // object will inherit from multiple receivers. - struct Recv : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Recv> Ptr; - - virtual bool defined() const = 0; - virtual void stop() = 0; - - virtual void start(const Send::Ptr& parent, - const PeerAddr::Ptr& addr, - const int local_peer_id) = 0; - - // Called with OpenVPN-encapsulated packets from transport layer. - // Returns true if packet successfully validated. - virtual bool transport_recv(BufferAllocated& buf) = 0; - - // Return true if keepalive parameter(s) are enabled. - virtual bool is_keepalive_enabled() const = 0; - - // Disable keepalive for rest of session, but fetch - // the keepalive parameters (in seconds). - virtual void disable_keepalive(unsigned int &keepalive_ping, - unsigned int &keepalive_timeout) = 0; - - // override the data channel factory - virtual void override_dc_factory(const CryptoDCFactory::Ptr& dc_factory) = 0; - - // override the tun provider - virtual TunClientInstance::Recv* override_tun(TunClientInstance::Send* tun) = 0; - - // bandwidth stats notification - virtual void stats_notify(const PeerStats& ps, const bool final) = 0; - - // client float notification - virtual void float_notify(const PeerAddr::Ptr& addr) = 0; - - // Data limit notification -- trigger a renegotiation - // when cdl_status == DataLimit::Red. - virtual void data_limit_notify(const int key_id, - const DataLimit::Mode cdl_mode, - const DataLimit::State cdl_status) = 0; - - // push a halt or restart message to client - virtual void push_halt_restart_msg(const HaltRestart::Type type, - const std::string& reason, - const bool tell_client) = 0; - - }; - - // Base class for factory used to create Recv objects. - struct Factory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Factory> Ptr; - - virtual Recv::Ptr new_client_instance() = 0; - virtual bool validate_initial_packet(const BufferAllocated& net_buf) = 0; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/socket_protect.hpp b/Sources/OpenVPN3/openvpn/transport/socket_protect.hpp deleted file mode 100644 index 76113db..0000000 --- a/Sources/OpenVPN3/openvpn/transport/socket_protect.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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-2020 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_TRANSPORT_SOCKET_PROTECT_H -#define OPENVPN_TRANSPORT_SOCKET_PROTECT_H - -#include <openvpn/addr/ip.hpp> -#ifdef OPENVPN_PLATFORM_UWP -#include <openvpn/transport/uwp_socket_protect.hpp> -#endif - -namespace openvpn { - // Used as an interface in cases where the high-level controlling app - // needs early access to newly created transport sockets for making - // property changes. For example, on Android, we need to "protect" - // the socket from being routed into the VPN tunnel. - class BaseSocketProtect { - public: - virtual bool socket_protect(int socket, IP::Addr endpoint) = 0; - }; - -#ifdef OPENVPN_PLATFORM_UWP - typedef UWPSocketProtect SocketProtect; -#else - typedef BaseSocketProtect SocketProtect; -#endif -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/tcplink.hpp b/Sources/OpenVPN3/openvpn/transport/tcplink.hpp deleted file mode 100644 index 76fabb3..0000000 --- a/Sources/OpenVPN3/openvpn/transport/tcplink.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// 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-2020 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/>. - -// Low-level TCP transport object. - -#ifndef OPENVPN_TRANSPORT_TCPLINK_H -#define OPENVPN_TRANSPORT_TCPLINK_H - -#include <deque> -#include <utility> // for std::move -#include <memory> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/bigmutex.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/transport/pktstream.hpp> -#include <openvpn/transport/mutate.hpp> -#include <openvpn/transport/tcplinkcommon.hpp> - -#ifdef OPENVPN_GREMLIN -#include <openvpn/transport/gremlin.hpp> -#endif - -namespace openvpn { - namespace TCPTransport { - - template <typename Protocol, typename ReadHandler, bool RAW_MODE_ONLY> - class Link : public LinkCommon<Protocol, - ReadHandler, - RAW_MODE_ONLY> - { - typedef std::deque<BufferPtr> Queue; - - public: - typedef LinkCommon<Protocol, - ReadHandler, - RAW_MODE_ONLY> Base; - typedef RCPtr<Link> Ptr; - - typedef Protocol protocol; - - friend Base; - - Link(ReadHandler read_handler_arg, - typename Protocol::socket& socket_arg, - const size_t send_queue_max_size_arg, // 0 to disable - const size_t free_list_max_size_arg, - const Frame::Context& frame_context_arg, - const SessionStats::Ptr& stats_arg) - : Base(read_handler_arg, socket_arg, send_queue_max_size_arg, - free_list_max_size_arg, frame_context_arg, stats_arg) - { } - - private: - // Called by LinkCommon - virtual void from_app_send_buffer(BufferPtr& buf) override - { - Base::queue_send_buffer(buf); - } - - virtual void recv_buffer(PacketFrom::SPtr& pfp, const size_t bytes_recvd) override - { - bool requeue = true; - OPENVPN_LOG_TCPLINK_VERBOSE("TCP recv raw=" << Base::raw_mode_read << " size=" << bytes_recvd); - - pfp->buf.set_size(bytes_recvd); - requeue = Base::process_recv_buffer(pfp->buf); - if (!Base::halt && requeue) - Base::queue_recv(pfp.release()); // reuse PacketFrom object - } - }; - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/tcplinkbase.hpp b/Sources/OpenVPN3/openvpn/transport/tcplinkbase.hpp deleted file mode 100644 index 5ab64d3..0000000 --- a/Sources/OpenVPN3/openvpn/transport/tcplinkbase.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2012-2020 OpenVPN Inc. - -// Base class for generic link objects. - -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/common/rc.hpp> - -#pragma once - -namespace openvpn -{ - namespace TCPTransport - { - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - - class LinkBase : public RC<thread_unsafe_refcount> - { - protected: - virtual void recv_buffer(PacketFrom::SPtr& pfp, - const size_t bytes_recvd) = 0; - virtual void from_app_send_buffer(BufferPtr& buf) = 0; - - public: - typedef RCPtr<LinkBase> Ptr; - - virtual bool send_queue_empty() const = 0; - virtual unsigned int send_queue_size() const = 0; - virtual void reset_align_adjust(const size_t align_adjust) = 0; - virtual bool send(BufferAllocated& b) = 0; - virtual void set_raw_mode(const bool mode) = 0; - virtual void start() = 0; - virtual void stop() = 0; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/transport/tcplinkcommon.hpp b/Sources/OpenVPN3/openvpn/transport/tcplinkcommon.hpp deleted file mode 100644 index 91adf01..0000000 --- a/Sources/OpenVPN3/openvpn/transport/tcplinkcommon.hpp +++ /dev/null @@ -1,457 +0,0 @@ -// Copyright (C) 2012-2020 OpenVPN Inc. - -// Base class for TCP link objects. - -#ifndef OPENVPN_TRANSPORT_COMMONLINK_H -#define OPENVPN_TRANSPORT_COMMONLINK_H - -#include <deque> -#include <utility> // for std::move -#include <memory> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/error/excode.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/transport/tcplinkbase.hpp> -#include <openvpn/transport/pktstream.hpp> -#include <openvpn/transport/mutate.hpp> - -#ifdef OPENVPN_GREMLIN -#include <openvpn/transport/gremlin.hpp> -#endif - -#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 1 -#define OPENVPN_LOG_TCPLINK_ERROR(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_TCPLINK_ERROR(x) -#endif - -#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 3 -#define OPENVPN_LOG_TCPLINK_VERBOSE(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_TCPLINK_VERBOSE(x) -#endif - -namespace openvpn { - namespace TCPTransport { - - template <typename Protocol, - typename ReadHandler, - bool RAW_MODE_ONLY> - class LinkCommon : public LinkBase - { - typedef std::deque<BufferPtr> Queue; - - public: - typedef RCPtr<LinkCommon<Protocol, ReadHandler, RAW_MODE_ONLY>> Ptr; - typedef Protocol protocol; - - // In raw mode, data is sent and received without any special encapsulation. - // In non-raw mode, data is packetized by prepending a 16-bit length word - // onto each packet. The OpenVPN protocol runs in non-raw mode, while other - // TCP protocols such as HTTP or HTTPS would run in raw mode. - // This method is a no-op if RAW_MODE_ONLY is true. - void set_raw_mode(const bool mode) - { - set_raw_mode_read(mode); - set_raw_mode_write(mode); - } - - void set_raw_mode_read(const bool mode) - { - if (RAW_MODE_ONLY) - raw_mode_read = true; - else - raw_mode_read = mode; - } - - void set_raw_mode_write(const bool mode) - { - if (RAW_MODE_ONLY) - raw_mode_write = true; - else - raw_mode_write = mode; - } - - void set_mutate(const TransportMutateStream::Ptr& mutate_arg) - { - mutate = mutate_arg; - } - - bool send_queue_empty() const - { - return send_queue_size() == 0; - } - - void inject(const Buffer& src) - { - const size_t size = src.size(); - OPENVPN_LOG_TCPLINK_VERBOSE("TCP inject size=" << size); - if (size && !RAW_MODE_ONLY) - { - BufferAllocated buf; - frame_context.prepare(buf); - buf.write(src.c_data(), size); - BufferAllocated pkt; - put_pktstream(buf, pkt); - } - } - - void start() - { - if (!halt) - queue_recv(nullptr); - } - - void stop() - { - halt = true; -#ifdef OPENVPN_GREMLIN - if (gremlin) - gremlin->stop(); -#endif - } - - void reset_align_adjust(const size_t align_adjust) - { - frame_context.reset_align_adjust(align_adjust + (is_raw_mode() ? 0 : 2)); - } - - unsigned int send_queue_size() const - { - return queue.size() -#ifdef OPENVPN_GREMLIN - + (gremlin ? gremlin->send_size() : 0) -#endif - ; - } - - bool send(BufferAllocated& b) - { - if (halt) - return false; - - if (send_queue_max_size && send_queue_size() >= send_queue_max_size) - { - stats->error(Error::TCP_OVERFLOW); - read_handler->tcp_error_handler("TCP_OVERFLOW"); - stop(); - return false; - } - - BufferPtr buf; - if (!free_list.empty()) - { - buf = free_list.front(); - free_list.pop_front(); - } - else - buf.reset(new BufferAllocated()); - buf->swap(b); - if (!is_raw_mode_write()) - PacketStream::prepend_size(*buf); - if (mutate) - mutate->pre_send(*buf); -#ifdef OPENVPN_GREMLIN - if (gremlin) - gremlin_queue_send_buffer(buf); - else -#endif - from_app_send_buffer(buf); - return true; - } - - void queue_recv(PacketFrom *tcpfrom) - { - OPENVPN_LOG_TCPLINK_VERBOSE("TLSLink::queue_recv"); - if (!tcpfrom) - tcpfrom = new PacketFrom(); - frame_context.prepare(tcpfrom->buf); - - socket.async_receive(frame_context.mutable_buffer_clamp(tcpfrom->buf), - [self=Ptr(this), tcpfrom=PacketFrom::SPtr(tcpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable - { - OPENVPN_ASYNC_HANDLER; - try - { - self->handle_recv(std::move(tcpfrom), error, bytes_recvd); - } - catch (const std::exception& e) - { - Error::Type err = Error::TCP_SIZE_ERROR; - const char *msg = "TCP_SIZE_ERROR"; - // if exception is an ExceptionCode, translate the code - // to return status string - { - const ExceptionCode *ec = dynamic_cast<const ExceptionCode *>(&e); - if (ec && ec->code_defined()) - { - err = ec->code(); - msg = ec->what(); - } - } - - OPENVPN_LOG_TCPLINK_ERROR("TCP packet extract exception: " << e.what()); - self->stats->error(err); - self->read_handler->tcp_error_handler(msg); - self->stop(); - } - }); - } - - protected: - LinkCommon(ReadHandler read_handler_arg, - typename Protocol::socket& socket_arg, - const size_t send_queue_max_size_arg, // 0 to disable - const size_t free_list_max_size_arg, - const Frame::Context& frame_context_arg, - const SessionStats::Ptr& stats_arg) - : socket(socket_arg), - halt(false), - read_handler(read_handler_arg), - frame_context(frame_context_arg), - stats(stats_arg), - send_queue_max_size(send_queue_max_size_arg), - free_list_max_size(free_list_max_size_arg) - { - set_raw_mode(false); - } - -#ifdef OPENVPN_GREMLIN - void gremlin_config(const Gremlin::Config::Ptr& config) - { - if (config) - gremlin.reset(new Gremlin::SendRecvQueue(socket.get_executor().context(), config, true)); - } -#endif - - bool is_raw_mode() const { - return is_raw_mode_read() && is_raw_mode_write(); - } - - bool is_raw_mode_read() const { - if (RAW_MODE_ONLY) - return true; - else - return raw_mode_read; - } - - bool is_raw_mode_write() const { - if (RAW_MODE_ONLY) - return true; - else - return raw_mode_write; - } - - LinkCommon() { stop(); } - - void queue_send_buffer(BufferPtr& buf) - { - queue.push_back(std::move(buf)); - if (queue.size() == 1) // send operation not currently active? - queue_send(); - } - - void queue_send() - { - BufferAllocated& buf = *queue.front(); - socket.async_send(buf.const_buffer_clamp(), - [self=Ptr(this)](const openvpn_io::error_code& error, const size_t bytes_sent) - { - OPENVPN_ASYNC_HANDLER; - self->handle_send(error, bytes_sent); - }); - } - - void handle_send(const openvpn_io::error_code& error, const size_t bytes_sent) - { - if (!halt) - { - if (!error) - { - OPENVPN_LOG_TCPLINK_VERBOSE("TLS-TCP send raw=" << raw_mode_write << " size=" << bytes_sent); - stats->inc_stat(SessionStats::BYTES_OUT, bytes_sent); - stats->inc_stat(SessionStats::PACKETS_OUT, 1); - - BufferPtr buf = queue.front(); - if (bytes_sent == buf->size()) - { - queue.pop_front(); - if (free_list.size() < free_list_max_size) - { - buf->reset_content(); - free_list.push_back(std::move(buf)); // recycle the buffer for later use - } - } - else if (bytes_sent < buf->size()) - buf->advance(bytes_sent); - else - { - stats->error(Error::TCP_OVERFLOW); - read_handler->tcp_error_handler("TCP_INTERNAL_ERROR"); // error sent more bytes than we asked for - stop(); - return; - } - } - else - { - OPENVPN_LOG_TCPLINK_ERROR("TLS-TCP send error: " << error.message()); - stats->error(Error::NETWORK_SEND_ERROR); - read_handler->tcp_error_handler("NETWORK_SEND_ERROR"); - stop(); - return; - } - if (!queue.empty()) - queue_send(); - else - tcp_write_queue_needs_send(); - } - } - - bool process_recv_buffer(BufferAllocated& buf) - { - bool requeue = true; - - OPENVPN_LOG_TCPLINK_VERBOSE("TLSLink::process_recv_buffer: size=" << buf.size()); - - if (!is_raw_mode_read()) - { - try { - BufferAllocated pkt; - requeue = put_pktstream(buf, pkt); - if (!buf.allocated() && pkt.allocated()) // recycle pkt allocated buffer - buf.move(pkt); - } - catch (const std::exception& e) - { - OPENVPN_LOG_TCPLINK_ERROR("TLS-TCP packet extract error: " << e.what()); - stats->error(Error::TCP_SIZE_ERROR); - read_handler->tcp_error_handler("TCP_SIZE_ERROR"); - stop(); - return false; - } - } - else - { - if (mutate) - mutate->post_recv(buf); -#ifdef OPENVPN_GREMLIN - if (gremlin) - requeue = gremlin_recv(buf); - else -#endif - requeue = read_handler->tcp_read_handler(buf); - } - - return requeue; - } - - void handle_recv(PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd) - { - OPENVPN_LOG_TCPLINK_VERBOSE("Link::handle_recv: " << error.message()); - if (!halt) - { - if (!error) - { - recv_buffer(pfp, bytes_recvd); - } - else if (error == openvpn_io::error::eof) - { - OPENVPN_LOG_TCPLINK_ERROR("TCP recv EOF"); - read_handler->tcp_eof_handler(); - } - else - { - OPENVPN_LOG_TCPLINK_ERROR("TCP recv error: " << error.message()); - stats->error(Error::NETWORK_RECV_ERROR); - read_handler->tcp_error_handler("NETWORK_RECV_ERROR"); - stop(); - } - } - } - - bool put_pktstream(BufferAllocated& buf, BufferAllocated& pkt) - { - bool requeue = true; - stats->inc_stat(SessionStats::BYTES_IN, buf.size()); - stats->inc_stat(SessionStats::PACKETS_IN, 1); - if (mutate) - mutate->post_recv(buf); - while (buf.size()) - { - pktstream.put(buf, frame_context); - if (pktstream.ready()) - { - pktstream.get(pkt); -#ifdef OPENVPN_GREMLIN - if (gremlin) - requeue = gremlin_recv(pkt); - else -#endif - requeue = read_handler->tcp_read_handler(pkt); - } - } - return requeue; - } - -#ifdef OPENVPN_GREMLIN - void gremlin_queue_send_buffer(BufferPtr& buf) - { - gremlin->send_queue([self=Ptr(this), buf=std::move(buf)]() mutable { - if (!self->halt) - { - self->queue_send_buffer(buf); - } - }); - } - - bool gremlin_recv(BufferAllocated& buf) - { - gremlin->recv_queue([self=Ptr(this), buf=std::move(buf)]() mutable { - if (!self->halt) - { - const bool requeue = self->read_handler->tcp_read_handler(buf); - if (requeue) - self->queue_recv(nullptr); - } - }); - return false; - } -#endif - - void tcp_write_queue_needs_send() - { - read_handler->tcp_write_queue_needs_send(); - } - - typename Protocol::socket& socket; - bool halt; - ReadHandler read_handler; - Frame::Context frame_context; - SessionStats::Ptr stats; - const size_t send_queue_max_size; - const size_t free_list_max_size; - Queue queue; // send queue - Queue free_list; // recycled free buffers for send queue - PacketStream pktstream; - TransportMutateStream::Ptr mutate; - bool raw_mode_read; - bool raw_mode_write; - -#ifdef OPENVPN_GREMLIN - std::unique_ptr<Gremlin::SendRecvQueue> gremlin; -#endif - - private: - virtual void recv_buffer(PacketFrom::SPtr& pfp, const size_t bytes_recvd) = 0; - virtual void from_app_send_buffer(BufferPtr& buf) = 0; - }; - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/transport/udplink.hpp b/Sources/OpenVPN3/openvpn/transport/udplink.hpp deleted file mode 100644 index 6cff819..0000000 --- a/Sources/OpenVPN3/openvpn/transport/udplink.hpp +++ /dev/null @@ -1,246 +0,0 @@ -// 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-2020 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/>. - -// Low-level UDP transport object. - -#ifndef OPENVPN_TRANSPORT_UDPLINK_H -#define OPENVPN_TRANSPORT_UDPLINK_H - -#include <memory> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> - -#ifdef OPENVPN_GREMLIN -#include <openvpn/transport/gremlin.hpp> -#endif - -#if defined(OPENVPN_DEBUG_UDPLINK) && OPENVPN_DEBUG_UDPLINK >= 1 -#define OPENVPN_LOG_UDPLINK_ERROR(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_UDPLINK_ERROR(x) -#endif - -#if defined(OPENVPN_DEBUG_UDPLINK) && OPENVPN_DEBUG_UDPLINK >= 3 -#define OPENVPN_LOG_UDPLINK_VERBOSE(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_UDPLINK_VERBOSE(x) -#endif - -namespace openvpn { - namespace UDPTransport { - - typedef openvpn_io::ip::udp::endpoint AsioEndpoint; - - enum { - SEND_SOCKET_HALTED=-1, - SEND_PARTIAL=-2, - }; - - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - AsioEndpoint sender_endpoint; - }; - - template <typename ReadHandler> - class Link : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Link> Ptr; - - Link(ReadHandler read_handler_arg, - openvpn_io::ip::udp::socket& socket_arg, - const Frame::Context& frame_context_arg, - const SessionStats::Ptr& stats_arg) - : socket(socket_arg), - halt(false), - read_handler(read_handler_arg), - frame_context(frame_context_arg), - stats(stats_arg) - { - } - -#ifdef OPENVPN_GREMLIN - void gremlin_config(const Gremlin::Config::Ptr& config) - { - if (config) - gremlin.reset(new Gremlin::SendRecvQueue(socket.get_executor().context(), config, false)); - } -#endif - - // Returns 0 on success, or a system error code on error. - // May also return SEND_PARTIAL or SEND_SOCKET_HALTED. - int send(const Buffer& buf, const AsioEndpoint* endpoint) - { -#ifdef OPENVPN_GREMLIN - if (gremlin) - { - gremlin_send(buf, endpoint); - return 0; - } - else -#endif - return do_send(buf, endpoint); - } - - void start(const int n_parallel) - { - if (!halt) - { - for (int i = 0; i < n_parallel; i++) - queue_read(nullptr); - } - } - - void stop() - { - halt = true; -#ifdef OPENVPN_GREMLIN - if (gremlin) - gremlin->stop(); -#endif - } - - void reset_align_adjust(const size_t align_adjust) - { - frame_context.reset_align_adjust(align_adjust); - } - - ~Link() { stop(); } - - private: - void queue_read(PacketFrom *udpfrom) - { - OPENVPN_LOG_UDPLINK_VERBOSE("UDPLink::queue_read"); - if (!udpfrom) - udpfrom = new PacketFrom(); - frame_context.prepare(udpfrom->buf); - socket.async_receive_from(frame_context.mutable_buffer(udpfrom->buf), - udpfrom->sender_endpoint, - [self=Ptr(this), udpfrom=PacketFrom::SPtr(udpfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable - { - OPENVPN_ASYNC_HANDLER; - self->handle_read(std::move(udpfrom), error, bytes_recvd); - }); - } - - void handle_read(PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd) - { - OPENVPN_LOG_UDPLINK_VERBOSE("UDPLink::handle_read: " << error.message()); - if (!halt) - { - if (bytes_recvd) - { - if (!error) - { - OPENVPN_LOG_UDPLINK_VERBOSE("UDP[" << bytes_recvd << "] from " << pfp->sender_endpoint); - pfp->buf.set_size(bytes_recvd); - stats->inc_stat(SessionStats::BYTES_IN, bytes_recvd); - stats->inc_stat(SessionStats::PACKETS_IN, 1); -#ifdef OPENVPN_GREMLIN - if (gremlin) - gremlin_recv(pfp); - else -#endif - read_handler->udp_read_handler(pfp); - } - else - { - OPENVPN_LOG_UDPLINK_ERROR("UDP recv error: " << error.message()); - stats->error(Error::NETWORK_RECV_ERROR); - } - } - if (!halt) - queue_read(pfp.release()); // reuse PacketFrom object if still available - } - } - - int do_send(const Buffer& buf, const AsioEndpoint* endpoint) - { - if (!halt) - { - try { - const size_t wrote = endpoint - ? socket.send_to(buf.const_buffer(), *endpoint) - : socket.send(buf.const_buffer()); - stats->inc_stat(SessionStats::BYTES_OUT, wrote); - stats->inc_stat(SessionStats::PACKETS_OUT, 1); - if (wrote == buf.size()) - return 0; - else - { - OPENVPN_LOG_UDPLINK_ERROR("UDP partial send error"); - stats->error(Error::NETWORK_SEND_ERROR); - return SEND_PARTIAL; - } - } - catch (openvpn_io::system_error& e) - { - OPENVPN_LOG_UDPLINK_ERROR("UDP send exception: " << e.what()); - stats->error(Error::NETWORK_SEND_ERROR); - return e.code().value(); - } - } - else - return SEND_SOCKET_HALTED; - } - -#ifdef OPENVPN_GREMLIN - void gremlin_send(const Buffer& buf, const AsioEndpoint* endpoint) - { - std::unique_ptr<AsioEndpoint> ep; - if (endpoint) - ep.reset(new AsioEndpoint(*endpoint)); - gremlin->send_queue([self=Ptr(this), buf=BufferAllocated(buf, 0), ep=std::move(ep)]() mutable { - if (!self->halt) - self->do_send(buf, ep.get()); - }); - } - - void gremlin_recv(PacketFrom::SPtr& pfp) - { - gremlin->recv_queue([self=Ptr(this), pfp=std::move(pfp)]() mutable { - if (!self->halt) - self->read_handler->udp_read_handler(pfp); - }); - } -#endif - - openvpn_io::ip::udp::socket& socket; - bool halt; - ReadHandler read_handler; - Frame::Context frame_context; - SessionStats::Ptr stats; - -#ifdef OPENVPN_GREMLIN - std::unique_ptr<Gremlin::SendRecvQueue> gremlin; -#endif - }; - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/builder/base.hpp b/Sources/OpenVPN3/openvpn/tun/builder/base.hpp deleted file mode 100644 index 1ac548f..0000000 --- a/Sources/OpenVPN3/openvpn/tun/builder/base.hpp +++ /dev/null @@ -1,333 +0,0 @@ -// 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-2020 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_TUN_BUILDER_BASE_H -#define OPENVPN_TUN_BUILDER_BASE_H - -#include <string> - -#ifdef ENABLE_OVPNDCO -#include <openvpn/dco/key.hpp> -#endif - -namespace openvpn { - class TunBuilderBase - { - public: - // Tun builder methods, loosely based on the Android VpnService.Builder - // abstraction. These methods comprise an abstraction layer that - // allows the OpenVPN C++ core to call out to external methods for - // establishing the tunnel, adding routes, etc. - - // All methods returning bool use the return - // value to indicate success (true) or fail (false). - // tun_builder_new() should be called first, then arbitrary setter methods, - // and finally tun_builder_establish to return the socket descriptor - // for the session. IP addresses are pre-validated before being passed to - // these methods. - // This interface is based on Android's VpnService.Builder. - - // Callback to construct a new tun builder - // Should be called first. - virtual bool tun_builder_new() - { - return false; - } - - // Optional callback that indicates OSI layer, should be 2 or 3. - // Defaults to 3. - virtual bool tun_builder_set_layer(int layer) - { - return true; - } - - // Callback to set address of remote server - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_remote_address(const std::string& address, bool ipv6) - { - return false; - } - - // Callback to add network address to VPN interface - // May be called more than once per tun_builder session - virtual bool tun_builder_add_address(const std::string& address, - int prefix_length, - const std::string& gateway, // optional - bool ipv6, - bool net30) - { - return false; - } - - // Optional callback to set default value for route metric. - // Guaranteed to be called before other methods that deal - // with routes such as tun_builder_add_route and - // tun_builder_reroute_gw. Route metric is ignored - // if < 0. - virtual bool tun_builder_set_route_metric_default(int metric) - { - return true; - } - - // Callback to reroute default gateway to VPN interface. - // ipv4 is true if the default route to be added should be IPv4. - // ipv6 is true if the default route to be added should be IPv6. - // flags are defined in RGWFlags (rgwflags.hpp). - // Never called more than once per tun_builder session. - virtual bool tun_builder_reroute_gw(bool ipv4, - bool ipv6, - unsigned int flags) - { - return false; - } - - // Callback to add route to VPN interface - // May be called more than once per tun_builder session - // metric is optional and should be ignored if < 0 - virtual bool tun_builder_add_route(const std::string& address, - int prefix_length, - int metric, - bool ipv6) - { - return false; - } - - // Callback to exclude route from VPN interface - // May be called more than once per tun_builder session - // metric is optional and should be ignored if < 0 - virtual bool tun_builder_exclude_route(const std::string& address, - int prefix_length, - int metric, - bool ipv6) - { - return false; - } - - // Callback to add DNS server to VPN interface - // May be called more than once per tun_builder session - // If reroute_dns is true, all DNS traffic should be routed over the - // tunnel, while if false, only DNS traffic that matches an added search - // domain should be routed. - // Guaranteed to be called after tun_builder_reroute_gw. - virtual bool tun_builder_add_dns_server(const std::string& address, bool ipv6) - { - return false; - } - - // Callback to add search domain to DNS resolver - // May be called more than once per tun_builder session - // See tun_builder_add_dns_server above for description of - // reroute_dns parameter. - // Guaranteed to be called after tun_builder_reroute_gw. - virtual bool tun_builder_add_search_domain(const std::string& domain) - { - return false; - } - - // Callback to set MTU of the VPN interface - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_mtu(int mtu) - { - return false; - } - - // Callback to set the session name - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_session_name(const std::string& name) - { - return false; - } - - // Callback to add a host which should bypass the proxy - // May be called more than once per tun_builder session - virtual bool tun_builder_add_proxy_bypass(const std::string& bypass_host) - { - return false; - } - - // Callback to set the proxy "Auto Config URL" - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_proxy_auto_config_url(const std::string& url) - { - return false; - } - - // Callback to set the HTTP proxy - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_proxy_http(const std::string& host, int port) - { - return false; - } - - // Callback to set the HTTPS proxy - // Never called more than once per tun_builder session. - virtual bool tun_builder_set_proxy_https(const std::string& host, int port) - { - return false; - } - - // Callback to add Windows WINS server to VPN interface. - // WINS server addresses are always IPv4. - // May be called more than once per tun_builder session. - // Guaranteed to be called after tun_builder_reroute_gw. - virtual bool tun_builder_add_wins_server(const std::string& address) - { - return false; - } - - // Optional callback that indicates whether IPv6 traffic should be - // blocked, to prevent unencrypted IPv6 packet leakage when the - // tunnel is IPv4-only, but the local machine has IPv6 connectivity - // to the internet. Enabled by "block-ipv6" config var. - virtual bool tun_builder_set_block_ipv6(bool block_ipv6) - { - return true; - } - - // Optional callback to set a DNS suffix on tun/tap adapter. - // Currently only implemented on Windows, where it will - // set the "Connection-specific DNS Suffix" property on - // the TAP driver. - virtual bool tun_builder_set_adapter_domain_suffix(const std::string& name) - { - return true; - } - - // Callback to establish the VPN tunnel, returning a file descriptor - // to the tunnel, which the caller will henceforth own. Returns -1 - // if the tunnel could not be established. - // Always called last after tun_builder session has been configured. - virtual int tun_builder_establish() - { - return -1; - } - - // Return true if tun interface may be persisted, i.e. rolled - // into a new session with properties untouched. This method - // is only called after all other tests of persistence - // allowability succeed, therefore it can veto persistence. - // If persistence is ultimately enabled, - // tun_builder_establish_lite() will be called. Otherwise, - // tun_builder_establish() will be called. - virtual bool tun_builder_persist() - { - return true; - } - - // When the exclude local network option is enabled this - // function is called to get a list of local networks so routes - // to exclude them from the VPN network are generated - // This should be a list of CIDR networks (e.g. 192.168.0.0/24) - virtual const std::vector<std::string> tun_builder_get_local_networks(bool ipv6) - { - return {}; - } - - // Indicates a reconnection with persisted tun state. - virtual void tun_builder_establish_lite() - { - } - - // Indicates that tunnel is being torn down. - // If disconnect == true, then the teardown is occurring - // prior to final disconnect. - virtual void tun_builder_teardown(bool disconnect) {} - - virtual ~TunBuilderBase() {} - -#ifdef ENABLE_OVPNDCO - /** - * Enable ovpn-dco support - * - * @param transport_fd file descriptor of client-created transport socket - * @param dev_name name of ovpn-dco net device, which should be created by client - * @return int file descriptor of socket used to direct communication with ovpn-dco kernel module - */ - virtual int tun_builder_dco_enable(int transport_fd, const std::string& dev_name) - { - return -1; - } - - /** - * Add peer information to kernel module - * - * @param local_ip local ip - * @param local_port local port - * @param remote_ip remote ip - * @param remote_port remote port - */ - virtual void tun_builder_dco_new_peer(const std::string& local_ip, unsigned int local_port, - const std::string& remote_ip, unsigned int remote_port) - { - } - - /** - * Set peer properties. Currently used for keepalive settings. - * - * @param keepalive_interval how often to send ping packet in absence of traffic - * @param keepalive_timeout when to trigger keepalive_timeout in absence of traffic - */ - virtual void tun_builder_dco_set_peer(int keepalive_interval, int keepalive_timeout) - { - } - - /** - * Inject new key into kernel module - * - * @param key_slot \c OVPN_KEY_SLOT_PRIMARY or \c OVPN_KEY_SLOT_SECONDARY - * @param kc pointer to \c KeyConfig struct which contains key data - */ - virtual void tun_builder_dco_new_key(unsigned int key_slot, const KoRekey::KeyConfig* kc) - { - } - - /** - * Swap keys between primary and secondary slot. Called - * by client as part of rekeying logic to promote and demote keys. - * - */ - virtual void tun_builder_dco_swap_keys() - { - } - - /** - * Remove key from key slot. - * - * @param key_slot OVPN_KEY_SLOT_PRIMARY or OVPN_KEY_SLOT_SECONDARY - */ - virtual void tun_builder_dco_del_key(unsigned int key_slot) - { - } - - /** - * Establishes VPN tunnel. Should be called last after tun_builder - * session has been configured. - * - */ - virtual void tun_builder_dco_establish() - { - } -#endif // ENABLE_DCO - - }; -} - -#endif \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/tun/builder/capture.hpp b/Sources/OpenVPN3/openvpn/tun/builder/capture.hpp deleted file mode 100644 index cecc267..0000000 --- a/Sources/OpenVPN3/openvpn/tun/builder/capture.hpp +++ /dev/null @@ -1,821 +0,0 @@ -// 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-2020 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/>. - -// An artificial TunBuilder object, used to log the tun builder settings, -// but doesn't actually configure anything. - -#ifndef OPENVPN_TUN_BUILDER_CAPTURE_H -#define OPENVPN_TUN_BUILDER_CAPTURE_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/tun/builder/base.hpp> -#include <openvpn/client/rgopt.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/http/urlparse.hpp> -#include <openvpn/tun/layer.hpp> - -#ifdef HAVE_JSON -#include <openvpn/common/jsonhelper.hpp> -#endif - -namespace openvpn { - class TunBuilderCapture : public TunBuilderBase, public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TunBuilderCapture> Ptr; - - // builder data classes - - class RemoteAddress - { - public: - std::string address; - bool ipv6 = false; - - std::string to_string() const - { - std::string ret = address; - if (ipv6) - ret += " [IPv6]"; - return ret; - } - - bool defined() const - { - return !address.empty(); - } - - void validate(const std::string& title) const - { - IP::Addr(address, title, ipv6 ? IP::Addr::V6 : IP::Addr::V4); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["address"] = Json::Value(address); - root["ipv6"] = Json::Value(ipv6); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - if (!json::is_dict(root, title)) - return; - json::to_string(root, address, "address", title); - json::to_bool(root, ipv6, "ipv6", title); - } -#endif - }; - - class RerouteGW - { - public: - bool ipv4 = false; - bool ipv6 = false; - unsigned int flags = 0; - - std::string to_string() const - { - std::ostringstream os; - const RedirectGatewayFlags rgf(flags); - os << "IPv4=" << ipv4 << " IPv6=" << ipv6 << " flags=" << rgf.to_string(); - return os.str(); - } - - void validate(const std::string& title) const - { - // nothing to validate - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["ipv4"] = Json::Value(ipv4); - root["ipv6"] = Json::Value(ipv6); - root["flags"] = Json::Value((Json::UInt)flags); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_bool(root, ipv4, "ipv4", title); - json::to_bool(root, ipv6, "ipv6", title); - json::to_uint(root, flags, "flags", title); - } -#endif - }; - - class RouteBase - { - public: - std::string address; - int prefix_length = 0; - int metric = -1; // optional - std::string gateway; // optional - bool ipv6 = false; - bool net30 = false; - - std::string to_string() const - { - std::ostringstream os; - os << address << '/' << prefix_length; - if (!gateway.empty()) - os << " -> " << gateway; - if (metric >= 0) - os << " [METRIC=" << metric << ']'; - if (ipv6) - os << " [IPv6]"; - if (net30) - os << " [net30]"; - return os.str(); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["address"] = Json::Value(address); - root["prefix_length"] = Json::Value(prefix_length); - root["metric"] = Json::Value(metric); - root["gateway"] = Json::Value(gateway); - root["ipv6"] = Json::Value(ipv6); - root["net30"] = Json::Value(net30); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_string(root, address, "address", title); - json::to_int(root, prefix_length, "prefix_length", title); - json::to_int(root, metric, "metric", title); - json::to_string(root, gateway, "gateway", title); - json::to_bool(root, ipv6, "ipv6", title); - json::to_bool(root, net30, "net30", title); - } -#endif - - protected: - void validate_(const std::string& title, const bool require_canonical) const - { - const IP::Addr::Version ver = ipv6 ? IP::Addr::V6 : IP::Addr::V4; - const IP::Route route = IP::route_from_string_prefix(address, prefix_length, title, ver); - if (require_canonical && !route.is_canonical()) - OPENVPN_THROW_EXCEPTION(title << " : not a canonical route: " << route); - if (!gateway.empty()) - IP::Addr(gateway, title + ".gateway", ver); - if (net30 && route.prefix_len != 30) - OPENVPN_THROW_EXCEPTION(title << " : not a net30 route: " << route); - } - }; - - class RouteAddress : public RouteBase // may be non-canonical - { - public: - void validate(const std::string& title) const - { - validate_(title, false); - } - }; - - class Route : public RouteBase // must be canonical - { - public: - void validate(const std::string& title) const - { - validate_(title, true); - } - }; - - class DNSServer - { - public: - std::string address; - bool ipv6 = false; - - std::string to_string() const - { - std::string ret = address; - if (ipv6) - ret += " [IPv6]"; - return ret; - } - - void validate(const std::string& title) const - { - IP::Addr(address, title, ipv6 ? IP::Addr::V6 : IP::Addr::V4); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["address"] = Json::Value(address); - root["ipv6"] = Json::Value(ipv6); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_string(root, address, "address", title); - json::to_bool(root, ipv6, "ipv6", title); - } -#endif - }; - - class SearchDomain - { - public: - std::string domain; - - std::string to_string() const - { - return domain; - } - - void validate(const std::string& title) const - { - HostPort::validate_host(domain, title); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["domain"] = Json::Value(domain); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_string(root, domain, "domain", title); - } -#endif - }; - - class ProxyBypass - { - public: - std::string bypass_host; - - std::string to_string() const - { - return bypass_host; - } - - bool defined() const - { - return !bypass_host.empty(); - } - - void validate(const std::string& title) const - { - if (defined()) - HostPort::validate_host(bypass_host, title); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["bypass_host"] = Json::Value(bypass_host); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_string(root, bypass_host, "bypass_host", title); - } -#endif - }; - - class ProxyAutoConfigURL - { - public: - std::string url; - - std::string to_string() const - { - return url; - } - - bool defined() const { - return !url.empty(); - } - - void validate(const std::string& title) const - { - try { - if (defined()) - (URL::Parse(url)); - } - catch (const std::exception& e) - { - OPENVPN_THROW_EXCEPTION(title << " : error parsing ProxyAutoConfigURL: " << e.what()); - } - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["url"] = Json::Value(url); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - if (!json::is_dict(root, title)) - return; - json::to_string(root, url, "url", title); - } -#endif - }; - - class ProxyHostPort - { - public: - std::string host; - int port = 0; - - std::string to_string() const - { - std::ostringstream os; - os << host << ' ' << port; - return os.str(); - } - - bool defined() const { - return !host.empty(); - } - - void validate(const std::string& title) const - { - if (defined()) - { - HostPort::validate_host(host, title); - HostPort::validate_port(port, title); - } - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["host"] = Json::Value(host); - root["port"] = Json::Value(port); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - if (!json::is_dict(root, title)) - return; - json::to_string(root, host, "host", title); - json::to_int(root, port, "port", title); - } -#endif - }; - - class WINSServer - { - public: - std::string address; - - std::string to_string() const - { - std::string ret = address; - return ret; - } - - void validate(const std::string& title) const - { - IP::Addr(address, title, IP::Addr::V4); - } - -#ifdef HAVE_JSON - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["address"] = Json::Value(address); - return root; - } - - void from_json(const Json::Value& root, const std::string& title) - { - json::assert_dict(root, title); - json::to_string(root, address, "address", title); - } -#endif - }; - - virtual bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override - { - remote_address.address = address; - remote_address.ipv6 = ipv6; - return true; - } - - virtual bool tun_builder_add_address(const std::string& address, int prefix_length, const std::string& gateway, bool ipv6, bool net30) override - { - RouteAddress r; - r.address = address; - r.prefix_length = prefix_length; - r.gateway = gateway; - r.ipv6 = ipv6; - r.net30 = net30; - if (ipv6) - tunnel_address_index_ipv6 = (int)tunnel_addresses.size(); - else - tunnel_address_index_ipv4 = (int)tunnel_addresses.size(); - tunnel_addresses.push_back(r); - return true; - } - - virtual bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override - { - reroute_gw.ipv4 = ipv4; - reroute_gw.ipv6 = ipv6; - reroute_gw.flags = flags; - return true; - } - - virtual bool tun_builder_set_route_metric_default(int metric) override - { - route_metric_default = metric; - return true; - } - - virtual bool tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) override - { - Route r; - r.address = address; - r.prefix_length = prefix_length; - r.metric = metric; - r.ipv6 = ipv6; - add_routes.push_back(r); - return true; - } - - virtual bool tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) override - { - Route r; - r.address = address; - r.prefix_length = prefix_length; - r.metric = metric; - r.ipv6 = ipv6; - exclude_routes.push_back(r); - return true; - } - - virtual bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override - { - DNSServer dns; - dns.address = address; - dns.ipv6 = ipv6; - dns_servers.push_back(dns); - return true; - } - - virtual bool tun_builder_add_search_domain(const std::string& domain) override - { - SearchDomain dom; - dom.domain = domain; - search_domains.push_back(dom); - return true; - } - - virtual bool tun_builder_set_adapter_domain_suffix(const std::string& name) override - { - adapter_domain_suffix = name; - return true; - } - - virtual bool tun_builder_set_layer(int layer) override - { - this->layer = Layer::from_value(layer); - return true; - } - - virtual bool tun_builder_set_mtu(int mtu) override - { - this->mtu = mtu; - return true; - } - - virtual bool tun_builder_set_session_name(const std::string& name) override - { - session_name = name; - return true; - } - - virtual bool tun_builder_add_proxy_bypass(const std::string& bypass_host) override - { - ProxyBypass b; - b.bypass_host = bypass_host; - proxy_bypass.push_back(b); - return true; - } - - virtual bool tun_builder_set_proxy_auto_config_url(const std::string& url) override - { - proxy_auto_config_url.url = url; - return true; - } - - virtual bool tun_builder_set_proxy_http(const std::string& host, int port) override - { - http_proxy.host = host; - http_proxy.port = port; - return true; - } - - virtual bool tun_builder_set_proxy_https(const std::string& host, int port) override - { - https_proxy.host = host; - https_proxy.port = port; - return true; - } - - virtual bool tun_builder_add_wins_server(const std::string& address) override - { - WINSServer wins; - wins.address = address; - wins_servers.push_back(wins); - return true; - } - - virtual bool tun_builder_set_block_ipv6(bool value) override - { - block_ipv6 = value; - return true; - } - - void reset_tunnel_addresses() - { - tunnel_addresses.clear(); - tunnel_address_index_ipv4 = -1; - tunnel_address_index_ipv6 = -1; - } - - void reset_dns_servers() - { - dns_servers.clear(); - } - - const RouteAddress* vpn_ipv4() const - { - if (tunnel_address_index_ipv4 >= 0) - return &tunnel_addresses[tunnel_address_index_ipv4]; - else - return nullptr; - } - - const RouteAddress* vpn_ipv6() const - { - if (tunnel_address_index_ipv6 >= 0) - return &tunnel_addresses[tunnel_address_index_ipv6]; - else - return nullptr; - } - - const RouteAddress* vpn_ip(const IP::Addr::Version v) const - { - switch (v) - { - case IP::Addr::V4: - return vpn_ipv4(); - case IP::Addr::V6: - return vpn_ipv6(); - default: - return nullptr; - } - } - - void validate() const - { - validate_layer("root"); - validate_mtu("root"); - remote_address.validate("remote_address"); - validate_list(tunnel_addresses, "tunnel_addresses"); - validate_tunnel_address_indices("root"); - reroute_gw.validate("reroute_gw"); - validate_list(add_routes, "add_routes"); - validate_list(exclude_routes, "exclude_routes"); - validate_list(dns_servers, "dns_servers"); - validate_list(search_domains, "search_domains"); - validate_list(proxy_bypass, "proxy_bypass"); - proxy_auto_config_url.validate("proxy_auto_config_url"); - http_proxy.validate("http_proxy"); - https_proxy.validate("https_proxy"); - } - - std::string to_string() const - { - std::ostringstream os; - os << "Session Name: " << session_name << std::endl; - os << "Layer: " << layer.str() << std::endl; - if (mtu) - os << "MTU: " << mtu << std::endl; - os << "Remote Address: " << remote_address.to_string() << std::endl; - render_list(os, "Tunnel Addresses", tunnel_addresses); - os << "Reroute Gateway: " << reroute_gw.to_string() << std::endl; - os << "Block IPv6: " << (block_ipv6 ? "yes" : "no") << std::endl; - if (route_metric_default >= 0) - os << "Route Metric Default: " << route_metric_default << std::endl; - render_list(os, "Add Routes", add_routes); - render_list(os, "Exclude Routes", exclude_routes); - render_list(os, "DNS Servers", dns_servers); - render_list(os, "Search Domains", search_domains); - if (!adapter_domain_suffix.empty()) - os << "Adapter Domain Suffix: " << adapter_domain_suffix << std::endl; - if (!proxy_bypass.empty()) - render_list(os, "Proxy Bypass", proxy_bypass); - if (proxy_auto_config_url.defined()) - os << "Proxy Auto Config URL: " << proxy_auto_config_url.to_string() << std::endl; - if (http_proxy.defined()) - os << "HTTP Proxy: " << http_proxy.to_string() << std::endl; - if (https_proxy.defined()) - os << "HTTPS Proxy: " << https_proxy.to_string() << std::endl; - if (!wins_servers.empty()) - render_list(os, "WINS Servers", wins_servers); - return os.str(); - } - -#ifdef HAVE_JSON - - Json::Value to_json() const - { - Json::Value root(Json::objectValue); - root["session_name"] = Json::Value(session_name); - root["mtu"] = Json::Value(mtu); - root["layer"] = Json::Value(layer.value()); - if (remote_address.defined()) - root["remote_address"] = remote_address.to_json(); - json::from_vector(root, tunnel_addresses, "tunnel_addresses"); - root["tunnel_address_index_ipv4"] = Json::Value(tunnel_address_index_ipv4); - root["tunnel_address_index_ipv6"] = Json::Value(tunnel_address_index_ipv6); - root["reroute_gw"] = reroute_gw.to_json(); - root["block_ipv6"] = Json::Value(block_ipv6); - root["route_metric_default"] = Json::Value(route_metric_default); - json::from_vector(root, add_routes, "add_routes"); - json::from_vector(root, exclude_routes, "exclude_routes"); - json::from_vector(root, dns_servers, "dns_servers"); - json::from_vector(root, wins_servers, "wins_servers"); - json::from_vector(root, search_domains, "search_domains"); - root["adapter_domain_suffix"] = Json::Value(adapter_domain_suffix); - json::from_vector(root, proxy_bypass, "proxy_bypass"); - if (proxy_auto_config_url.defined()) - root["proxy_auto_config_url"] = proxy_auto_config_url.to_json(); - if (http_proxy.defined()) - root["http_proxy"] = http_proxy.to_json(); - if (https_proxy.defined()) - root["https_proxy"] = https_proxy.to_json(); - return root; - } - - static TunBuilderCapture::Ptr from_json(const Json::Value& root) - { - const std::string title = "root"; - TunBuilderCapture::Ptr tbc(new TunBuilderCapture); - json::assert_dict(root, title); - json::to_string(root, tbc->session_name, "session_name", title); - tbc->layer = Layer::from_value(json::get_int(root, "layer", title)); - json::to_int(root, tbc->mtu, "mtu", title); - tbc->remote_address.from_json(root["remote_address"], "remote_address"); - json::to_vector(root, tbc->tunnel_addresses, "tunnel_addresses", title); - json::to_int(root, tbc->tunnel_address_index_ipv4, "tunnel_address_index_ipv4", title); - json::to_int(root, tbc->tunnel_address_index_ipv6, "tunnel_address_index_ipv6", title); - tbc->reroute_gw.from_json(root["reroute_gw"], "reroute_gw"); - json::to_bool(root, tbc->block_ipv6, "block_ipv6", title); - json::to_int(root, tbc->route_metric_default, "route_metric_default", title); - json::to_vector(root, tbc->add_routes, "add_routes", title); - json::to_vector(root, tbc->exclude_routes, "exclude_routes", title); - json::to_vector(root, tbc->dns_servers, "dns_servers", title); - json::to_vector(root, tbc->wins_servers, "wins_servers", title); - json::to_vector(root, tbc->search_domains, "search_domains", title); - json::to_string(root, tbc->adapter_domain_suffix, "adapter_domain_suffix", title); - json::to_vector(root, tbc->proxy_bypass, "proxy_bypass", title); - tbc->proxy_auto_config_url.from_json(root["proxy_auto_config_url"], "proxy_auto_config_url"); - tbc->http_proxy.from_json(root["http_proxy"], "http_proxy"); - tbc->https_proxy.from_json(root["https_proxy"], "https_proxy"); - return tbc; - } - -#endif // HAVE_JSON - - // builder data - std::string session_name; - int mtu = 0; - Layer layer{Layer::OSI_LAYER_3}; // OSI layer - RemoteAddress remote_address; // real address of server - std::vector<RouteAddress> tunnel_addresses; // local tunnel addresses - int tunnel_address_index_ipv4 = -1; // index into tunnel_addresses for IPv4 entry (or -1 if undef) - int tunnel_address_index_ipv6 = -1; // index into tunnel_addresses for IPv6 entry (or -1 if undef) - RerouteGW reroute_gw; // redirect-gateway info - bool block_ipv6 = false; // block IPv6 traffic while VPN is active - int route_metric_default = -1; // route-metric directive - std::vector<Route> add_routes; // routes that should be added to tunnel - std::vector<Route> exclude_routes; // routes that should be excluded from tunnel - std::vector<DNSServer> dns_servers; // VPN DNS servers - std::vector<SearchDomain> search_domains; // domain suffixes whose DNS requests should be tunnel-routed - std::string adapter_domain_suffix; // domain suffix on tun/tap adapter (currently Windows only) - - std::vector<ProxyBypass> proxy_bypass; // hosts that should bypass proxy - ProxyAutoConfigURL proxy_auto_config_url; - ProxyHostPort http_proxy; - ProxyHostPort https_proxy; - - std::vector<WINSServer> wins_servers; // Windows WINS servers - - private: - template <typename LIST> - static void render_list(std::ostream& os, const std::string& title, const LIST& list) - { - os << title << ':' << std::endl; - for (auto &e : list) - os << " " << e.to_string() << std::endl; - } - - template <typename LIST> - static void validate_list(const LIST& list, const std::string& title) - { - int i = 0; - for (auto &e : list) - { - e.validate(title + '[' + openvpn::to_string(i) + ']'); - ++i; - } - } - - bool validate_tunnel_index(const int index) const - { - if (index == -1) - return true; - return index >= 0 && static_cast<unsigned int>(index) <= tunnel_addresses.size(); - } - - void validate_tunnel_address_indices(const std::string& title) const - { - if (!validate_tunnel_index(tunnel_address_index_ipv4)) - OPENVPN_THROW_EXCEPTION(title << ".tunnel_address_index_ipv4 : IPv4 tunnel address index out of range: " << tunnel_address_index_ipv4); - if (!validate_tunnel_index(tunnel_address_index_ipv6)) - OPENVPN_THROW_EXCEPTION(title << ".tunnel_address_index_ipv6 : IPv6 tunnel address index out of range: " << tunnel_address_index_ipv6); - const RouteAddress* r4 = vpn_ipv4(); - if (r4 && r4->ipv6) - OPENVPN_THROW_EXCEPTION(title << ".tunnel_address_index_ipv4 : IPv4 tunnel address index points to wrong address type: " << r4->to_string()); - const RouteAddress* r6 = vpn_ipv6(); - if (r6 && !r6->ipv6) - OPENVPN_THROW_EXCEPTION(title << ".tunnel_address_index_ipv6 : IPv6 tunnel address index points to wrong address type: " << r6->to_string()); - } - - void validate_mtu(const std::string& title) const - { - if (mtu < 0 || mtu > 65536) - OPENVPN_THROW_EXCEPTION(title << ".mtu : MTU out of range: " << mtu); - } - - void validate_layer(const std::string& title) const - { - if (!layer.defined()) - OPENVPN_THROW_EXCEPTION(title << ": layer undefined"); - } - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/builder/client.hpp b/Sources/OpenVPN3/openvpn/tun/builder/client.hpp deleted file mode 100644 index 5330e20..0000000 --- a/Sources/OpenVPN3/openvpn/tun/builder/client.hpp +++ /dev/null @@ -1,317 +0,0 @@ -// 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-2020 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/>. - -// Generic, cross-platform tun interface that drives a TunBuilderBase API. -// Fully supports IPv6. To make this work on a given platform, define -// a TunBuilderBase for the platform. - -#ifndef OPENVPN_TUN_BUILDER_CLIENT_H -#define OPENVPN_TUN_BUILDER_CLIENT_H - -#include <memory> - -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/tun/tunio.hpp> - -namespace openvpn { - namespace TunBuilderClient { - - OPENVPN_EXCEPTION(tun_builder_error); - - // struct used to pass received tun packets - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - - // our TunPersist class, specialized for Unix file descriptors - typedef TunPersistTemplate<ScopedFD> TunPersist; - - // A simplified tun interface where pre-existing - // socket is provided. - template <typename ReadHandler> - class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> - { - typedef TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> Base; - - public: - typedef RCPtr<Tun> Ptr; - - Tun(openvpn_io::io_context& io_context, - const int socket, - const bool retain_sd_arg, - const bool tun_prefix_arg, - ReadHandler read_handler_arg, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg) - : Base(read_handler_arg, frame_arg, stats_arg) - { - Base::stream = new openvpn_io::posix::stream_descriptor(io_context, socket); - Base::name_ = "tun"; - Base::retain_stream = retain_sd_arg; - Base::tun_prefix = tun_prefix_arg; - } - - ~Tun() { Base::stop(); } - }; - - // A factory for the Client class - class ClientConfig : public TunClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - TunProp::Config tun_prop; - int n_parallel; // number of parallel async reads on tun socket - bool retain_sd; - bool tun_prefix; - Frame::Ptr frame; - SessionStats::Ptr stats; - EmulateExcludeRouteFactory::Ptr eer_factory; - TunPersist::Ptr tun_persist; - TunBuilderBase* builder; - - static Ptr new_obj() - { - return new ClientConfig; - } - - TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) override; - - void finalize(const bool disconnected) override - { - if (disconnected) - tun_persist.reset(); - } - - private: - ClientConfig() - : n_parallel(8), retain_sd(false), tun_prefix(false), builder(nullptr) {} - }; - - // The tun interface - class Client : public TunClient - { - friend class ClientConfig; // calls constructor - friend class TunIO<Client*, PacketFrom, openvpn_io::posix::stream_descriptor>; // calls tun_read_handler - - typedef Tun<Client*> TunImpl; - - public: - virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { - if (!impl) - { - halt = false; - if (config->tun_persist) - tun_persist = config->tun_persist; // long-term persistent - else - tun_persist.reset(new TunPersist(false, config->retain_sd, config->builder)); // short-term - - try { - int sd = -1; - const IP::Addr server_addr = transcli.server_endpoint_addr(); - - // Check if persisted tun session matches properties of to-be-created session - if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) - { - sd = tun_persist->obj(); - state = tun_persist->state(); - OPENVPN_LOG("TunPersist: reused tun context"); - - // indicate reconnection with persisted state - config->builder->tun_builder_establish_lite(); - } - else - { - TunBuilderBase* tb = config->builder; - - // reset target tun builder object - if (!tb->tun_builder_new()) - throw tun_builder_error("tun_builder_new failed"); - - // notify parent - parent.tun_pre_tun_config(); - - // configure the tun builder - TunProp::configure_builder(tb, state.get(), config->stats.get(), server_addr, - config->tun_prop, opt, config->eer_factory.get(), false); - - // start tun - sd = tb->tun_builder_establish(); - } - - if (sd == -1) - { - parent.tun_error(Error::TUN_IFACE_CREATE, "cannot acquire tun interface socket"); - return; - } - - // persist state - if (tun_persist->persist_tun_state(sd, state)) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); - - impl.reset(new TunImpl(io_context, - sd, - true, - config->tun_prefix, - this, - config->frame, - config->stats - )); - impl->start(config->n_parallel); - - // signal that we are connected - parent.tun_connected(); - } - catch (const std::exception& e) - { - if (tun_persist) - tun_persist->close(); - stop(); - parent.tun_error(Error::TUN_SETUP_FAILED, e.what()); - } - } - } - - virtual bool tun_send(BufferAllocated& buf) override - { - return send(buf); - } - - virtual std::string tun_name() const override - { - if (impl) - return impl->name(); - else - return "UNDEF_TUN"; - } - - virtual std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - virtual std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - virtual void set_disconnect() override - { - if (tun_persist) - tun_persist->set_disconnect(); - } - - virtual void stop() override { stop_(); } - virtual ~Client() { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : io_context(io_context_arg), - config(config_arg), - parent(parent_arg), - halt(false), - state(new TunProp::State()) - { - } - - bool send(Buffer& buf) - { - if (impl) - return impl->write(buf); - else - return false; - } - - void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl - { - parent.tun_recv(pfp->buf); - } - - void tun_error_handler(const Error::Type errtype, // called by TunImpl - const openvpn_io::error_code* error) - { - } - - void stop_() - { - if (!halt) - { - halt = true; - - // stop tun - if (impl) - impl->stop(); - tun_persist.reset(); - } - } - - - openvpn_io::io_context& io_context; - TunPersist::Ptr tun_persist; // owns the tun socket descriptor - ClientConfig::Ptr config; - TunClientParent& parent; - TunImpl::Ptr impl; - bool halt; - TunProp::State::Ptr state; - }; - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - return TunClient::Ptr(new Client(io_context, this, parent)); - } - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/builder/rgwflags.hpp b/Sources/OpenVPN3/openvpn/tun/builder/rgwflags.hpp deleted file mode 100644 index e4655c5..0000000 --- a/Sources/OpenVPN3/openvpn/tun/builder/rgwflags.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// 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-2020 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_TUN_BUILDER_RGWFLAGS_H -#define OPENVPN_TUN_BUILDER_RGWFLAGS_H - -namespace openvpn { - namespace RGWFlags { - // These flags are passed as the flags argument to TunBuilderBase::tun_builder_reroute_gw - // NOTE: must not collide with RG_x flags in rgopt.hpp. - enum { - EmulateExcludeRoutes=(1<<16), - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/builder/setup.hpp b/Sources/OpenVPN3/openvpn/tun/builder/setup.hpp deleted file mode 100644 index e46ab93..0000000 --- a/Sources/OpenVPN3/openvpn/tun/builder/setup.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// 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-2020 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/>. - -// Client tun setup base class for unix - -#ifndef OPENVPN_TUN_BUILDER_SETUP_H -#define OPENVPN_TUN_BUILDER_SETUP_H - -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/common/destruct.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/tun/builder/capture.hpp> - -namespace openvpn { - namespace TunBuilderSetup { - struct Config - { -#ifdef HAVE_JSON - virtual Json::Value to_json() = 0; - virtual void from_json(const Json::Value& root, const std::string& title) = 0; -#endif - virtual ~Config() {} - }; - - struct Base : public DestructorBase - { - typedef RCPtr<Base> Ptr; - - virtual int establish(const TunBuilderCapture& pull, - Config* config, - Stop* stop, - std::ostream& os) = 0; - }; - - struct Factory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Factory> Ptr; - - virtual Base::Ptr new_setup_obj() = 0; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/client/dhcp_capture.hpp b/Sources/OpenVPN3/openvpn/tun/client/dhcp_capture.hpp deleted file mode 100644 index b75db5e..0000000 --- a/Sources/OpenVPN3/openvpn/tun/client/dhcp_capture.hpp +++ /dev/null @@ -1,320 +0,0 @@ -// 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-2020 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_TUN_CLIENT_DHCP_CAPTURE_H -#define OPENVPN_TUN_CLIENT_DHCP_CAPTURE_H - -#include <cstring> - -#include <openvpn/common/socktypes.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/ip/ipcommon.hpp> -#include <openvpn/ip/dhcp.hpp> -#include <openvpn/tun/builder/capture.hpp> - -namespace openvpn { - class DHCPCapture - { - public: - // We take a TunBuilderCapture object with previously pushed - // options and augment it with additional options sniffed - // from the DHCP reply. - DHCPCapture(const TunBuilderCapture::Ptr& props_arg) - : props(props_arg) - { - if (props->vpn_ipv4() || props->vpn_ipv4()) - OPENVPN_LOG("NOTE: pushed ifconfig directive is ignored in layer 2 mode"); - if (!props->dns_servers.empty()) - OPENVPN_LOG("NOTE: pushed DNS servers are ignored in layer 2 mode"); - reset(); - } - - // returns true when router addr and DNS servers are captured - bool mod_reply(Buffer& buf) - { - if (buf.size() < sizeof(DHCPPacket)) - return false; - - DHCPPacket* dhcp = (DHCPPacket*)buf.data(); - if (dhcp->ip.protocol == IPCommon::UDP - && dhcp->udp.source == htons(DHCP::BOOTPS_PORT) - && dhcp->udp.dest == htons(DHCP::BOOTPC_PORT) - && dhcp->dhcp.op == DHCP::BOOTREPLY) - { - const unsigned int optlen = buf.size() - sizeof(DHCPPacket); - const int message_type = dhcp_message_type(dhcp, optlen); - if (message_type == DHCP::DHCPACK || message_type == DHCP::DHCPOFFER) - { - /* get host IP address/netmask */ - const IPv4::Addr host = IPv4::Addr::from_uint32_net(dhcp->dhcp.yiaddr); - const IPv4::Addr netmask = get_netmask(dhcp, optlen); - const int prefix_len = netmask.prefix_len_nothrow(); - - /* get the router IP address while padding out all DHCP router options */ - const IPv4::Addr router = extract_router(dhcp, optlen); - - /* get DNS server addresses */ - const std::vector<IPv4::Addr> dns_servers = get_dns(dhcp, optlen); - - /* recompute the UDP checksum */ - dhcp->udp.check = 0; - dhcp->udp.check = htons(udp_checksum((uint8_t *)&dhcp->udp, - sizeof(UDPHeader) + sizeof(DHCP) + optlen, - (uint8_t *)&dhcp->ip.saddr, - (uint8_t *)&dhcp->ip.daddr)); - - /* only capture the extracted Router address if DHCPACK */ - if (message_type == DHCP::DHCPACK && !configured) - { - bool complete = true; - if (host.unspecified()) - { - OPENVPN_LOG("NOTE: failed to obtain host address via DHCP"); - complete = false; - } - if (netmask.unspecified()) - { - OPENVPN_LOG("NOTE: failed to obtain netmask via DHCP"); - complete = false; - } - if (prefix_len < 0) - { - OPENVPN_LOG("NOTE: bad netmask obtained via DHCP: " << netmask); - complete = false; - } - if (router.unspecified()) - { - OPENVPN_LOG("NOTE: failed to obtain router via DHCP"); - complete = false; - } - if (complete) - { - reset(); - props->tun_builder_add_address(host.to_string(), prefix_len, router.to_string(), false, false); - if (dns_servers.empty()) - OPENVPN_LOG("NOTE: failed to obtain DNS servers via DHCP"); - else - { - for (const auto &a : dns_servers) - props->tun_builder_add_dns_server(a.to_string(), false); - } - } - return configured = complete; - } - } - } - return false; - } - - const TunBuilderCapture& get_props() const - { - return *props; - } - - private: - void reset() - { - props->reset_tunnel_addresses(); - props->reset_dns_servers(); - } - - static int dhcp_message_type(const DHCPPacket* dhcp, const unsigned int optlen) - { - const std::uint8_t* p = dhcp->options; - for (unsigned int i = 0; i < optlen; ++i) - { - const std::uint8_t type = p[i]; - const unsigned int room = optlen - i; - - if (type == DHCP::DHCP_END) /* didn't find what we were looking for */ - return -1; - else if (type == DHCP::DHCP_PAD) /* no-operation */ - ; - else if (type == DHCP::DHCP_MSG_TYPE) /* what we are looking for */ - { - if (room >= 3) - { - if (p[i+1] == 1) /* option length should be 1 */ - return p[i+2]; /* return message type */ - } - return -1; - } - else /* some other option */ - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - i += (len + 1); /* advance to next option */ - } - } - } - return -1; - } - - static IPv4::Addr extract_router(DHCPPacket* dhcp, const unsigned int optlen) - { - std::uint8_t* p = dhcp->options; - IPv4::Addr ret = IPv4::Addr::from_zero(); - - for (unsigned int i = 0; i < optlen; ) - { - const std::uint8_t type = p[i]; - const unsigned int room = optlen - i; - - if (type == DHCP::DHCP_END) - break; - else if (type == DHCP::DHCP_PAD) - ++i; - else if (type == DHCP::DHCP_ROUTER) - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - if (len <= (room-2)) - { - /* get router IP address */ - if (ret.unspecified() && len >= 4 && (len & 3) == 0) - ret = IPv4::Addr::from_bytes_net(p + i + 2); - - /* delete the router option */ - std::uint8_t *dest = p + i; - const unsigned int owlen = len + 2; /* len of data to overwrite */ - std::uint8_t *src = dest + owlen; - std::uint8_t *end = p + optlen; - const int movlen = end - src; - if (movlen > 0) - std::memmove(dest, src, movlen); /* overwrite router option */ - std::memset(end - owlen, DHCP::DHCP_PAD, owlen); /* pad tail */ - } - else - break; - } - else - break; - } - else /* some other option */ - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - i += (len + 2); /* advance to next option */ - } - else - break; - } - } - return ret; - } - - static IPv4::Addr get_netmask(const DHCPPacket* dhcp, const unsigned int optlen) - { - const std::uint8_t* p = dhcp->options; - IPv4::Addr ret = IPv4::Addr::from_zero(); - - for (unsigned int i = 0; i < optlen; ) - { - const std::uint8_t type = p[i]; - const unsigned int room = optlen - i; - - if (type == DHCP::DHCP_END) - break; - else if (type == DHCP::DHCP_PAD) - ++i; - else if (type == DHCP::DHCP_NETMASK) - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - if (len <= (room-2) && len == 4) - return IPv4::Addr::from_bytes_net(p + i + 2); - else - break; - } - else - break; - } - else /* some other option */ - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - i += (len + 2); /* advance to next option */ - } - else - break; - } - } - return ret; - } - - static std::vector<IPv4::Addr> get_dns(const DHCPPacket* dhcp, const unsigned int optlen) - { - const std::uint8_t* p = dhcp->options; - std::vector<IPv4::Addr> ret; - - for (unsigned int i = 0; i < optlen; ) - { - const std::uint8_t type = p[i]; - const unsigned int room = optlen - i; - - if (type == DHCP::DHCP_END) - break; - else if (type == DHCP::DHCP_PAD) - ++i; - else if (type == DHCP::DHCP_DNS) - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - if (len <= (room-2) && (len & 3) == 0) - { - /* get DNS addresses */ - for (unsigned int j = 0; j < len; j += 4) - ret.push_back(IPv4::Addr::from_bytes_net(p + i + j + 2)); - - i += (len + 2); /* advance to next option */ - } - else - break; - } - else - break; - } - else /* some other option */ - { - if (room >= 2) - { - const unsigned int len = p[i+1]; /* get option length */ - i += (len + 2); /* advance to next option */ - } - else - break; - } - } - return ret; - } - - TunBuilderCapture::Ptr props; - bool configured = false; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/client/emuexr.hpp b/Sources/OpenVPN3/openvpn/tun/client/emuexr.hpp deleted file mode 100644 index c3c8d06..0000000 --- a/Sources/OpenVPN3/openvpn/tun/client/emuexr.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// 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-2020 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/>. - -// Base classes for Emulate Excluded Routes - -#ifndef OPENVPN_TUN_CLIENT_EMUEXR_H -#define OPENVPN_TUN_CLIENT_EMUEXR_H - -#include <openvpn/common/rc.hpp> -#include <openvpn/client/ipverflags.hpp> -#include <openvpn/tun/builder/base.hpp> - -namespace openvpn { - struct EmulateExcludeRoute : public RC<thread_unsafe_refcount> - { - typedef RCPtr<EmulateExcludeRoute> Ptr; - - virtual void add_route(const bool add, const IP::Addr& addr, const int prefix_len) = 0; - virtual bool enabled(const IPVerFlags& ipv) const = 0; - virtual void emulate(TunBuilderBase* tb, IPVerFlags& ipv, const IP::Addr& server_addr) const = 0; - virtual void add_default_routes(bool ipv4, bool ipv6) = 0; - }; - - struct EmulateExcludeRouteFactory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<EmulateExcludeRouteFactory> Ptr; - - virtual EmulateExcludeRoute::Ptr new_obj() const = 0; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/client/tunbase.hpp b/Sources/OpenVPN3/openvpn/tun/client/tunbase.hpp deleted file mode 100644 index e9b96f4..0000000 --- a/Sources/OpenVPN3/openvpn/tun/client/tunbase.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// 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-2020 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/>. - -// Abstract base classes for client tun interface objects. - -#ifndef OPENVPN_TUN_CLIENT_TUNBASE_H -#define OPENVPN_TUN_CLIENT_TUNBASE_H - -#include <string> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/transport/client/transbase.hpp> - -namespace openvpn { - - // Base class for objects that implement a client tun interface. - struct TunClient : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<TunClient> Ptr; - - virtual void tun_start(const OptionList&, TransportClient&, CryptoDCSettings&) = 0; - virtual void stop() = 0; - virtual void set_disconnect() = 0; - virtual bool tun_send(BufferAllocated& buf) = 0; // return true if send succeeded - - virtual std::string tun_name() const = 0; - - virtual std::string vpn_ip4() const = 0; // VPN IP addresses - virtual std::string vpn_ip6() const = 0; - - virtual std::string vpn_gw4() const { return std::string(); } // VPN gateways - virtual std::string vpn_gw6() const { return std::string(); } - }; - - // Base class for parent of tun interface object, used to - // communicate received data packets, exceptions, and progress - // notifications. - struct TunClientParent - { - virtual void tun_recv(BufferAllocated& buf) = 0; - virtual void tun_error(const Error::Type fatal_err, const std::string& err_text) = 0; - - // progress notifications - virtual void tun_pre_tun_config() = 0; - virtual void tun_pre_route_config() = 0; - virtual void tun_connected() = 0; - }; - - // Factory for tun interface objects. - struct TunClientFactory : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<TunClientFactory> Ptr; - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) = 0; - - // return true if layer 2 tunnels are supported - virtual bool layer_2_supported() const { return false; } - - // Called on TunClient close, after TunClient::stop has been called. - // disconnected -> - // true: this is the final disconnect, or - // false: we are in a pause/reconnecting state. - virtual void finalize(const bool disconnected) {} - }; - -} // namespace openvpn - -#endif // OPENVPN_TUN_CLIENT_TUNBASE_H diff --git a/Sources/OpenVPN3/openvpn/tun/client/tunnull.hpp b/Sources/OpenVPN3/openvpn/tun/client/tunnull.hpp deleted file mode 100644 index ef2fa99..0000000 --- a/Sources/OpenVPN3/openvpn/tun/client/tunnull.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// 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-2020 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/>. - -// Null tun interface object, intended for testing. - -#ifndef OPENVPN_TUN_CLIENT_TUNNULL_H -#define OPENVPN_TUN_CLIENT_TUNNULL_H - -#include <openvpn/tun/client/tunbase.hpp> - -namespace openvpn { - namespace TunNull { - - class ClientConfig : public TunClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - Frame::Ptr frame; - SessionStats::Ptr stats; - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli); - private: - ClientConfig() {} - }; - - class Client : public TunClient - { - friend class ClientConfig; // calls constructor - - public: - virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { -#ifdef TUN_NULL_EXIT - throw ErrorCode(Error::TUN_SETUP_FAILED, true, "TUN_NULL_EXIT"); -#else - // signal that we are "connected" - parent.tun_connected(); -#endif - } - - virtual bool tun_send(BufferAllocated& buf) override - { - config->stats->inc_stat(SessionStats::TUN_BYTES_OUT, buf.size()); - config->stats->inc_stat(SessionStats::TUN_PACKETS_OUT, 1); - return true; - } - - virtual std::string tun_name() const override - { - return "TUN_NULL"; - } - - virtual std::string vpn_ip4() const override - { - return ""; - } - - virtual std::string vpn_ip6() const override - { - return ""; - } - - virtual void set_disconnect() override - { - } - - virtual void stop() override {} - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : config(config_arg), - parent(parent_arg) - { - } - - ClientConfig::Ptr config; - TunClientParent& parent; - }; - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - return TunClient::Ptr(new Client(io_context, this, parent)); - } - - } -} // namespace openvpn - -#endif // OPENVPN_TUN_CLIENT_TUNNULL_H diff --git a/Sources/OpenVPN3/openvpn/tun/client/tunprop.hpp b/Sources/OpenVPN3/openvpn/tun/client/tunprop.hpp deleted file mode 100644 index d9f20f8..0000000 --- a/Sources/OpenVPN3/openvpn/tun/client/tunprop.hpp +++ /dev/null @@ -1,654 +0,0 @@ -// 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-2020 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/>. - -// Process tun interface properties. - -#ifndef OPENVPN_TUN_CLIENT_TUNPROP_H -#define OPENVPN_TUN_CLIENT_TUNPROP_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/tun/builder/base.hpp> -#include <openvpn/addr/addrpair.hpp> -#include <openvpn/client/remotelist.hpp> -#include <openvpn/client/ipverflags.hpp> -#include <openvpn/tun/client/emuexr.hpp> -#include <openvpn/tun/layer.hpp> - -namespace openvpn { - class TunProp { - // add_dns flags - enum { - F_ADD_DNS=(1<<0), - }; - - // render option flags - enum { - OPT_RENDER_FLAGS = Option::RENDER_TRUNC_64 | Option::RENDER_BRACKET - }; - - // maximum route metric - static constexpr int MAX_ROUTE_METRIC = 1000000; - - public: - OPENVPN_EXCEPTION(tun_prop_error); - OPENVPN_EXCEPTION(tun_prop_route_error); - OPENVPN_EXCEPTION(tun_prop_dhcp_option_error); - - struct Config - { - std::string session_name; - int mtu = 0; - bool google_dns_fallback = false; - bool allow_local_lan_access = false; - Layer layer{Layer::OSI_LAYER_3}; - - // If remote_bypass is true, obtain cached remote IPs from - // remote_list, and preconfigure exclude route rules for them. - // Note that the primary remote IP is not included in the - // exclusion list because existing pathways already exist - // (i.e. redirect-gateway) for routing this particular address. - // This feature is intended to work with tun_persist, so that - // the client is not locked out of contacting subsequent - // servers in the remote list after the routing configuration - // for the initial connection has taken effect. - RemoteList::Ptr remote_list; - bool remote_bypass = false; - }; - - struct State : public RC<thread_unsafe_refcount> - { - typedef RCPtr<State> Ptr; - - std::string iface_name; - IP::Addr vpn_ip4_addr; - IP::Addr vpn_ip6_addr; - IP::Addr vpn_ip4_gw; - IP::Addr vpn_ip6_gw; - bool tun_prefix = false; - }; - - static void configure_builder(TunBuilderBase* tb, - State* state, - SessionStats* stats, - const IP::Addr& server_addr, - const Config& config, - const OptionList& opt, - const EmulateExcludeRouteFactory* eer_factory, - const bool quiet) - { - // if eer_factory is defined, we must emulate exclude routes - EmulateExcludeRoute::Ptr eer; - if (eer_factory) - eer = eer_factory->new_obj(); - - // do ifconfig - IP::Addr::VersionMask ip_ver_flags = tun_ifconfig(tb, state, opt); - - // with layer 2, either IPv4 or IPv6 might be supported - if (config.layer() == Layer::OSI_LAYER_2) - ip_ver_flags |= (IP::Addr::V4_MASK|IP::Addr::V6_MASK); - - // verify IPv4/IPv6 - if (!ip_ver_flags) - throw tun_prop_error("one of ifconfig or ifconfig-ipv6 must be specified"); - - // get IP version and redirect-gateway flags - IPVerFlags ipv(opt, ip_ver_flags); - - // add default route-metric - add_route_metric_default(tb, opt, quiet); - - // add remote bypass routes - if (config.remote_list && config.remote_bypass) - add_remote_bypass_routes(tb, *config.remote_list, server_addr, eer.get(), quiet); - - // add routes - if (config.allow_local_lan_access) - { - // query local lan exclude routes and then - // copy option list to construct a copy with the excluded routes as route options - OptionList excludedRoutesOptions = opt; - for (const std::string& exRoute: tb->tun_builder_get_local_networks(false)) - { - excludedRoutesOptions.add_item(Option{"route", exRoute, "", "net_gateway"}); - } - - for (const std::string& exRoute: tb->tun_builder_get_local_networks(true)) - { - excludedRoutesOptions.add_item(Option{"route-ipv6", exRoute, "", "net_gateway"}); - } - - add_routes(tb, excludedRoutesOptions, ipv, eer.get(), quiet); - } - else - { - add_routes(tb, opt, ipv, eer.get(), quiet); - } - - - if (eer) - { - // Route emulation needs to know if default routes are included - // from redirect-gateway - eer->add_default_routes(ipv.rgv4(), ipv.rgv6()); - // emulate exclude routes - eer->emulate(tb, ipv, server_addr); - } - else - { - // configure redirect-gateway - if (!tb->tun_builder_reroute_gw(ipv.rgv4(), ipv.rgv6(), ipv.api_flags())) - throw tun_prop_route_error("tun_builder_reroute_gw for redirect-gateway failed"); - } - - // add DNS servers and domain prefixes - const unsigned int dhcp_option_flags = add_dhcp_options(tb, opt, quiet); - - // Block IPv6? - tb->tun_builder_set_block_ipv6(opt.exists("block-ipv6")); - - // DNS fallback - if (ipv.rgv4() && !(dhcp_option_flags & F_ADD_DNS)) - { - if (config.google_dns_fallback) - { - if (!quiet) - OPENVPN_LOG("Google DNS fallback enabled"); - add_google_dns(tb); - } - else if (stats && (config.layer() != Layer::OSI_LAYER_2)) - stats->error(Error::REROUTE_GW_NO_DNS); - } - - // set remote server address - if (!tb->tun_builder_set_remote_address(server_addr.to_string(), - server_addr.version() == IP::Addr::V6)) - throw tun_prop_error("tun_builder_set_remote_address failed"); - - // set layer - if (!tb->tun_builder_set_layer(config.layer.value())) - throw tun_prop_error("tun_builder_set_layer failed"); - - // set MTU - if (config.mtu) - { - if (!tb->tun_builder_set_mtu(config.mtu)) - throw tun_prop_error("tun_builder_set_mtu failed"); - } - - // set session name - if (!config.session_name.empty()) - { - if (!tb->tun_builder_set_session_name(config.session_name)) - throw tun_prop_error("tun_builder_set_session_name failed"); - } - } - - private: - - static void add_route_metric_default(TunBuilderBase* tb, - const OptionList& opt, - const bool quiet) - { - try { - const Option* o = opt.get_ptr("route-metric"); // DIRECTIVE - if (o) - { - const int metric = o->get_num<int>(1); - if (metric < 0 || metric > MAX_ROUTE_METRIC) - throw tun_prop_error("route-metric is out of range"); - if (!tb->tun_builder_set_route_metric_default(metric)) - throw tun_prop_error("tun_builder_set_route_metric_default failed"); - } - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception processing route-metric: " << e.what()); - } - } - - static IP::Addr route_gateway(const OptionList& opt) - { - IP::Addr gateway; - const Option* o = opt.get_ptr("route-gateway"); // DIRECTIVE - if (o) - { - gateway = IP::Addr::from_string(o->get(1, 256), "route-gateway"); - if (gateway.version() != IP::Addr::V4) - throw tun_prop_error("route-gateway is not IPv4 (IPv6 route-gateway is passed with ifconfig-ipv6 directive)"); - } - return gateway; - } - - static IP::Addr::VersionMask tun_ifconfig(TunBuilderBase* tb, - State* state, - const OptionList& opt) - { - enum Topology { - NET30, - SUBNET, - }; - - IP::Addr::VersionMask ip_ver_flags = 0; - - // get topology - Topology top = NET30; - { - const Option* o = opt.get_ptr("topology"); // DIRECTIVE - if (o) - { - const std::string& topstr = o->get(1, 16); - if (topstr == "subnet") - top = SUBNET; - else if (topstr == "net30") - top = NET30; - else - throw option_error("only topology 'subnet' and 'net30' supported"); - } - } - - // configure tun interface - { - const Option* o; - o = opt.get_ptr("ifconfig"); // DIRECTIVE - if (o) - { - if (top == SUBNET) - { - const IP::AddrMaskPair pair = IP::AddrMaskPair::from_string(o->get(1, 256), o->get_optional(2, 256), "ifconfig"); - const IP::Addr gateway = route_gateway(opt); - if (pair.version() != IP::Addr::V4) - throw tun_prop_error("ifconfig address is not IPv4 (topology subnet)"); - if (!tb->tun_builder_add_address(pair.addr.to_string(), - pair.netmask.prefix_len(), - gateway.to_string(), - false, // IPv6 - false)) // net30 - throw tun_prop_error("tun_builder_add_address IPv4 failed (topology subnet)"); - if (state) - { - state->vpn_ip4_addr = pair.addr; - state->vpn_ip4_gw = gateway; - } - ip_ver_flags |= IP::Addr::V4_MASK; - } - else if (top == NET30) - { - const IP::Addr remote = IP::Addr::from_string(o->get(2, 256)); - const IP::Addr local = IP::Addr::from_string(o->get(1, 256)); - const IP::Addr netmask = IP::Addr::from_string("255.255.255.252"); - if (local.version() != IP::Addr::V4 || remote.version() != IP::Addr::V4) - throw tun_prop_error("ifconfig address is not IPv4 (topology net30)"); - if ((local & netmask) != (remote & netmask)) - throw tun_prop_error("ifconfig addresses are not in the same /30 subnet (topology net30)"); - if (!tb->tun_builder_add_address(local.to_string(), - netmask.prefix_len(), - remote.to_string(), - false, // IPv6 - true)) // net30 - throw tun_prop_error("tun_builder_add_address IPv4 failed (topology net30)"); - if (state) - { - state->vpn_ip4_addr = local; - state->vpn_ip4_gw = remote; - } - ip_ver_flags |= IP::Addr::V4_MASK; - } - else - throw option_error("internal topology error"); - } - - o = opt.get_ptr("ifconfig-ipv6"); // DIRECTIVE - if (o) - { - // We don't check topology setting here since it doesn't really affect IPv6 - const IP::AddrMaskPair pair = IP::AddrMaskPair::from_string(o->get(1, 256), "ifconfig-ipv6"); - if (pair.version() != IP::Addr::V6) - throw tun_prop_error("ifconfig-ipv6 address is not IPv6"); - std::string gateway_str; - if (o->size() >= 3) - { - const IP::Addr gateway = IP::Addr::from_string(o->get(2, 256), "ifconfig-ipv6"); - if (gateway.version() != IP::Addr::V6) - throw tun_prop_error("ifconfig-ipv6 gateway is not IPv6"); - gateway_str = gateway.to_string(); - if (state) - state->vpn_ip6_gw = gateway; - } - if (!tb->tun_builder_add_address(pair.addr.to_string(), - pair.netmask.prefix_len(), - gateway_str, - true, // IPv6 - false)) // net30 - throw tun_prop_error("tun_builder_add_address IPv6 failed"); - if (state) - state->vpn_ip6_addr = pair.addr; - ip_ver_flags |= IP::Addr::V6_MASK; - } - - return ip_ver_flags; - } - } - - static void add_route_tunbuilder(TunBuilderBase* tb, - bool add, - const IP::Addr& addr, - int prefix_length, - int metric, - bool ipv6, - EmulateExcludeRoute* eer) - { - const std::string addr_str = addr.to_string(); - if (eer) - eer->add_route(add, addr, prefix_length); - else if (add) - { - if (!tb->tun_builder_add_route(addr_str, prefix_length, metric, ipv6)) - throw tun_prop_route_error("tun_builder_add_route failed"); - } - else if (!eer) - { - if (!tb->tun_builder_exclude_route(addr_str, prefix_length, metric, ipv6)) - throw tun_prop_route_error("tun_builder_exclude_route failed"); - } - - } - - // Check the target of a route. - // Return true if route should be added or false if route should be excluded. - static bool route_target(const Option& o, const size_t target_index) - { - if (o.size() >= (target_index+1)) - { - const std::string& target = o.ref(target_index); - if (target == "vpn_gateway") - return true; - else if (target == "net_gateway") - return false; - else - throw tun_prop_route_error("route destinations other than vpn_gateway or net_gateway are not supported"); - } - else - return true; - } - - static void add_routes(TunBuilderBase* tb, - const OptionList& opt, - const IPVerFlags& ipv, - EmulateExcludeRoute* eer, - const bool quiet) - { - // add IPv4 routes - if (ipv.v4()) - { - OptionList::IndexMap::const_iterator dopt = opt.map().find("route"); // DIRECTIVE - if (dopt != opt.map().end()) - { - for (OptionList::IndexList::const_iterator i = dopt->second.begin(); i != dopt->second.end(); ++i) - { - const Option& o = opt[*i]; - try { - const IP::AddrMaskPair pair = IP::AddrMaskPair::from_string(o.get(1, 256), o.get_optional(2, 256), "route"); - const int metric = o.get_num<int>(4, -1, 0, MAX_ROUTE_METRIC); - if (!pair.is_canonical()) - throw tun_prop_error("route is not canonical"); - if (pair.version() != IP::Addr::V4) - throw tun_prop_error("route is not IPv4"); - const bool add = route_target(o, 3); - add_route_tunbuilder(tb, add, pair.addr, pair.netmask.prefix_len(), metric, false, eer); - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception parsing IPv4 route: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what()); - } - } - } - } - - // add IPv6 routes - if (ipv.v6()) - { - OptionList::IndexMap::const_iterator dopt = opt.map().find("route-ipv6"); // DIRECTIVE - if (dopt != opt.map().end()) - { - for (OptionList::IndexList::const_iterator i = dopt->second.begin(); i != dopt->second.end(); ++i) - { - const Option& o = opt[*i]; - try { - const IP::AddrMaskPair pair = IP::AddrMaskPair::from_string(o.get(1, 256), "route-ipv6"); - const int metric = o.get_num<int>(3, -1, 0, MAX_ROUTE_METRIC); - if (!pair.is_canonical()) - throw tun_prop_error("route is not canonical"); - if (pair.version() != IP::Addr::V6) - throw tun_prop_error("route is not IPv6"); - const bool add = route_target(o, 2); - add_route_tunbuilder(tb, add, pair.addr, pair.netmask.prefix_len(), metric, true, eer); - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception parsing IPv6 route: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what()); - } - } - } - } - } - - static void add_remote_bypass_routes(TunBuilderBase* tb, - const RemoteList& remote_list, - const IP::Addr& server_addr, - EmulateExcludeRoute* eer, - const bool quiet) - { - IP::AddrList addrlist; - remote_list.cached_ip_address_list(addrlist); - for (IP::AddrList::const_iterator i = addrlist.begin(); i != addrlist.end(); ++i) - { - const IP::Addr& addr = *i; - if (addr != server_addr) - { - try { - const IP::Addr::Version ver = addr.version(); - add_route_tunbuilder(tb, false, addr, IP::Addr::version_size(ver), -1, ver == IP::Addr::V6, eer); - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception adding remote bypass route: " << addr.to_string() << " : " << e.what()); - } - } - } - } - - static unsigned int add_dhcp_options(TunBuilderBase* tb, const OptionList& opt, const bool quiet) - { - // Example: - // [dhcp-option] [DNS] [172.16.0.23] - // [dhcp-option] [WINS] [172.16.0.23] - // [dhcp-option] [DOMAIN] [openvpn.net] - // [dhcp-option] [DOMAIN] [example.com] - // [dhcp-option] [DOMAIN] [foo1.com foo2.com foo3.com ...] - // [dhcp-option] [DOMAIN] [bar1.com] [bar2.com] [bar3.com] ... - // [dhcp-option] [ADAPTER_DOMAIN_SUFFIX] [mycompany.com] - // [dhcp-option] [PROXY_HTTP] [foo.bar.gov] [1234] - // [dhcp-option] [PROXY_HTTPS] [foo.bar.gov] [1234] - // [dhcp-option] [PROXY_BYPASS] [server1] [server2] ... - // [dhcp-option] [PROXY_AUTO_CONFIG_URL] [http://...] - unsigned int flags = 0; - OptionList::IndexMap::const_iterator dopt = opt.map().find("dhcp-option"); // DIRECTIVE - if (dopt != opt.map().end()) - { - std::string auto_config_url; - std::string http_host; - unsigned int http_port = 0; - std::string https_host; - unsigned int https_port = 0; - for (OptionList::IndexList::const_iterator i = dopt->second.begin(); i != dopt->second.end(); ++i) - { - const Option& o = opt[*i]; - try { - const std::string& type = o.get(1, 64); - if (type == "DNS" || type == "DNS6") - { - o.exact_args(3); - const IP::Addr ip = IP::Addr::from_string(o.get(2, 256), "dns-server-ip"); - if (!tb->tun_builder_add_dns_server(ip.to_string(), - ip.version() == IP::Addr::V6)) - throw tun_prop_dhcp_option_error("tun_builder_add_dns_server failed"); - flags |= F_ADD_DNS; - } - else if (type == "DOMAIN") - { - o.min_args(3); - for (size_t j = 2; j < o.size(); ++j) - { - typedef std::vector<std::string> strvec; - strvec v = Split::by_space<strvec, StandardLex, SpaceMatch, Split::NullLimit>(o.get(j, 256)); - for (size_t k = 0; k < v.size(); ++k) - { - if (!tb->tun_builder_add_search_domain(v[k])) - throw tun_prop_dhcp_option_error("tun_builder_add_search_domain failed"); - } - } - } - else if (type == "ADAPTER_DOMAIN_SUFFIX") - { - o.exact_args(3); - const std::string& adapter_domain_suffix = o.get(2, 256); - if (!tb->tun_builder_set_adapter_domain_suffix(adapter_domain_suffix)) - throw tun_prop_dhcp_option_error("tun_builder_set_adapter_domain_suffix"); - } - else if (type == "PROXY_BYPASS") - { - o.min_args(3); - for (size_t j = 2; j < o.size(); ++j) - { - typedef std::vector<std::string> strvec; - strvec v = Split::by_space<strvec, StandardLex, SpaceMatch, Split::NullLimit>(o.get(j, 256)); - for (size_t k = 0; k < v.size(); ++k) - { - if (!tb->tun_builder_add_proxy_bypass(v[k])) - throw tun_prop_dhcp_option_error("tun_builder_add_proxy_bypass"); - } - } - } - else if (type == "PROXY_AUTO_CONFIG_URL") - { - o.exact_args(3); - auto_config_url = o.get(2, 256); - } - else if (type == "PROXY_HTTP") - { - o.exact_args(4); - http_host = o.get(2, 256); - HostPort::validate_port(o.get(3, 256), "PROXY_HTTP", &http_port); - } - else if (type == "PROXY_HTTPS") - { - o.exact_args(4); - https_host = o.get(2, 256); - HostPort::validate_port(o.get(3, 256), "PROXY_HTTPS", &https_port); - } - else if (type == "WINS") - { - o.exact_args(3); - const IP::Addr ip = IP::Addr::from_string(o.get(2, 256), "wins-server-ip"); - if (ip.version() != IP::Addr::V4) - throw tun_prop_dhcp_option_error("WINS addresses must be IPv4"); - if (!tb->tun_builder_add_wins_server(ip.to_string())) - throw tun_prop_dhcp_option_error("tun_builder_add_wins_server failed"); - } - else if (!quiet) - OPENVPN_LOG("Unknown pushed DHCP option: " << o.render(OPT_RENDER_FLAGS)); - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception parsing dhcp-option: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what()); - } - } - try { - if (!http_host.empty()) - { - if (!tb->tun_builder_set_proxy_http(http_host, http_port)) - throw tun_prop_dhcp_option_error("tun_builder_set_proxy_http"); - } - if (!https_host.empty()) - { - if (!tb->tun_builder_set_proxy_https(https_host, https_port)) - throw tun_prop_dhcp_option_error("tun_builder_set_proxy_https"); - } - if (!auto_config_url.empty()) - { - if (!tb->tun_builder_set_proxy_auto_config_url(auto_config_url)) - throw tun_prop_dhcp_option_error("tun_builder_set_proxy_auto_config_url"); - } - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception setting dhcp-option for proxy: " << e.what()); - } - } - return flags; - } - - static bool search_domains_exist(const OptionList& opt, const bool quiet) - { - OptionList::IndexMap::const_iterator dopt = opt.map().find("dhcp-option"); // DIRECTIVE - if (dopt != opt.map().end()) - { - for (OptionList::IndexList::const_iterator i = dopt->second.begin(); i != dopt->second.end(); ++i) - { - const Option& o = opt[*i]; - try { - const std::string& type = o.get(1, 64); - if (type == "DOMAIN") - return true; - } - catch (const std::exception& e) - { - if (!quiet) - OPENVPN_LOG("exception parsing dhcp-option: " << o.render(OPT_RENDER_FLAGS) << " : " << e.what()); - } - } - } - return false; - } - - static void add_google_dns(TunBuilderBase* tb) - { - if (!tb->tun_builder_add_dns_server("8.8.8.8", false) - || !tb->tun_builder_add_dns_server("8.8.4.4", false)) - throw tun_prop_dhcp_option_error("tun_builder_add_dns_server failed for Google DNS"); - } - }; -} // namespace openvpn - -#endif // OPENVPN_TUN_CLIENT_TUNPROP_H diff --git a/Sources/OpenVPN3/openvpn/tun/extern/config.hpp b/Sources/OpenVPN3/openvpn/tun/extern/config.hpp deleted file mode 100644 index c3f08ed..0000000 --- a/Sources/OpenVPN3/openvpn/tun/extern/config.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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_TUN_EXTERN_CONFIG_H -#define OPENVPN_TUN_EXTERN_CONFIG_H - -// These includes are also intended to resolve forward references in fw.hpp -#include <openvpn/common/options.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/common/stop.hpp> - -namespace openvpn { - namespace ExternalTun { - struct Config - { - TunProp::Config tun_prop; - Frame::Ptr frame; - SessionStats::Ptr stats; - Stop* stop = nullptr; - bool tun_persist = false; - }; - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/extern/fw.hpp b/Sources/OpenVPN3/openvpn/tun/extern/fw.hpp deleted file mode 100644 index 90373f3..0000000 --- a/Sources/OpenVPN3/openvpn/tun/extern/fw.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// 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-2020 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_TUN_EXTERN_FW_H -#define OPENVPN_TUN_EXTERN_FW_H - -namespace openvpn { - -#if defined(OPENVPN_EXTERNAL_TUN_FACTORY) - - struct TunClientFactory; - class OptionList; - - namespace ExternalTun { - struct Config; // defined in config.hpp - struct Factory - { - virtual TunClientFactory* new_tun_factory(const Config& conf, const OptionList& opt) = 0; - virtual ~Factory() {} - }; - } - -#else - - namespace ExternalTun { - struct Factory {}; - } - -#endif -} -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/ipv6_setting.hpp b/Sources/OpenVPN3/openvpn/tun/ipv6_setting.hpp deleted file mode 100644 index 4aeb21e..0000000 --- a/Sources/OpenVPN3/openvpn/tun/ipv6_setting.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// 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-2020 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_TUN_IPv6_SETTING_H -#define OPENVPN_TUN_IPv6_SETTING_H - -#include <openvpn/common/exception.hpp> - -namespace openvpn { - class IPv6Setting - { - public: - enum Type { - No, - Yes, - Default, - }; - - IPv6Setting() - { - } - - explicit IPv6Setting(const Type t) - : type_(t) - { - } - - Type operator()() const { return type_; } - - std::string to_string() const - { - switch (type_) - { - case No: - return "no"; - case Yes: - return "yes"; - case Default: - default: - return "default"; - } - } - - static IPv6Setting parse(const std::string& str) - { - if (str == "no") - return IPv6Setting(No); - else if (str == "yes") - return IPv6Setting(Yes); - else if (str == "default") - return IPv6Setting(Default); - else - throw Exception("IPv6Setting: unrecognized setting: '" + str + '\''); - } - - bool operator==(const IPv6Setting& other) const - { - return type_ == other.type_; - } - - bool operator!=(const IPv6Setting& other) const - { - return type_ != other.type_; - } - - private: - Type type_ = Default; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/layer.hpp b/Sources/OpenVPN3/openvpn/tun/layer.hpp deleted file mode 100644 index 085cc06..0000000 --- a/Sources/OpenVPN3/openvpn/tun/layer.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// 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-2020 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/>. - -// Class that encapsulates the definition of an OSI layer. - -#ifndef OPENVPN_TUN_LAYER_H -#define OPENVPN_TUN_LAYER_H - -#include <openvpn/common/exception.hpp> - -namespace openvpn { - class Layer - { - public: - enum Type { - NONE, - OSI_LAYER_2, - OSI_LAYER_3, - }; - - Layer() : type_(NONE) {} - explicit Layer(const Type t) : type_(t) {} - Type operator()() const { return type_; } - - bool defined() const - { - return type_ != NONE; - } - - const char *dev_type() const - { - switch (type_) - { - case OSI_LAYER_2: - return "tap"; - case OSI_LAYER_3: - return "tun"; - default: - return "null"; - } - } - - const char *str() const - { - switch (type_) - { - case NONE: - return "UNDEF_LAYER"; - case OSI_LAYER_2: - return "OSI_LAYER_2"; - case OSI_LAYER_3: - return "OSI_LAYER_3"; - default: - throw Exception("Layer: unrecognized layer type"); - } - } - - int value() const - { - switch (type_) - { - case NONE: - return 0; - case OSI_LAYER_2: - return 2; - case OSI_LAYER_3: - return 3; - default: - throw Exception("Layer: unrecognized layer type"); - } - } - - static Layer from_str(const std::string& str) - { - if (str == "OSI_LAYER_3") - return Layer(OSI_LAYER_3); - else if (str == "OSI_LAYER_2") - return Layer(OSI_LAYER_2); - else if (str == "UNDEF_LAYER") - return Layer(NONE); - else - throw Exception("Layer: unrecognized layer string"); - } - - static Layer from_value(const int value) - { - if (value == 3) - return Layer(OSI_LAYER_3); - else if (value == 2) - return Layer(OSI_LAYER_2); - else if (value == 0) - return Layer(NONE); - else - throw Exception("Layer: unrecognized layer value"); - } - - bool operator==(const Layer& other) const - { - return type_ == other.type_; - } - - bool operator!=(const Layer& other) const - { - return type_ != other.type_; - } - - private: - Type type_; - }; -} // namespace openvpn - -#endif // OPENVPN_TUN_LAYER_H diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/genl.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/genl.hpp deleted file mode 100644 index 1e7dc4f..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/genl.hpp +++ /dev/null @@ -1,642 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2020-2020 Lev Stipakov <lev@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 <openvpn/buffer/buffer.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/dco/key.hpp> - -#include <linux/ovpn_dco.h> -#include <netlink/genl/ctrl.h> -#include <netlink/genl/family.h> -#include <netlink/genl/genl.h> -#include <netlink/netlink.h> -#include <netlink/socket.h> - -#include <memory> - -namespace openvpn { - -#define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED) - -typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg); - -/** - * Implements asynchronous communication with ovpn-dco kernel module - * via generic netlink protocol. - * - * Before using this class, caller should create ovpn-dco network device. - * - * @tparam ReadHandler class which implements - * <tt>tun_read_handler(BufferAllocated &buf)</tt> method. \n - * - * buf has following layout: - * \li first byte - command type ( \p OVPN_CMD_PACKET, \p OVPN_CMD_DEL_PEER or - * -1 for error) - * \li following bytes - command-specific payload - */ -template <typename ReadHandler> class GeNL : public RC<thread_unsafe_refcount> { - OPENVPN_EXCEPTION(netlink_error); - - typedef std::unique_ptr<nl_msg, decltype(&nlmsg_free)> NlMsgPtr; - typedef std::unique_ptr<nl_sock, decltype(&nl_socket_free)> NlSockPtr; - typedef std::unique_ptr<nl_cb, decltype(&nl_cb_put)> NlCbPtr; - -public: - typedef RCPtr<GeNL> Ptr; - - /** - * Construct a new GeNL object - * - * @param io_context reference to io_context - * @param ifindex_arg index of ovpn-dco network device - * @param read_handler_arg instance of \p ReadHandler - * @throws netlink_error thrown if error occurs during initialization - */ - explicit GeNL(openvpn_io::io_context &io_context, unsigned int ifindex_arg, - ReadHandler read_handler_arg) - : sock_ptr(nl_socket_alloc(), nl_socket_free), - cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put), sock(sock_ptr.get()), - cb(cb_ptr.get()), ifindex(ifindex_arg), read_handler(read_handler_arg), - halt(false) { - nl_socket_set_buffer_size(sock, 8192, 8192); - - int ret = genl_connect(sock); - if (ret != 0) - OPENVPN_THROW(netlink_error, - " cannot connect to generic netlink: " << nl_geterror(ret)); - - int mcast_id = get_mcast_id(); - if (mcast_id < 0) - OPENVPN_THROW(netlink_error, - " cannot get multicast group: " << nl_geterror(mcast_id)); - - ret = nl_socket_add_membership(sock, mcast_id); - if (ret) - OPENVPN_THROW(netlink_error, "failed to join mcast group: " << ret); - - ovpn_dco_id = genl_ctrl_resolve(sock, OVPN_NL_NAME); - if (ovpn_dco_id < 0) - OPENVPN_THROW(netlink_error, - " cannot find ovpn_dco netlink component: " << ovpn_dco_id); - - // set callback to handle control channel messages - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, message_received, this); - - nl_cb_set( - cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, - [](struct nl_msg *, void *) { return (int)NL_OK; }, NULL); - nl_socket_set_cb(sock, cb); - - register_packet(); - - // wrap netlink socket into ASIO primitive for async read - stream.reset(new openvpn_io::posix::stream_descriptor( - io_context, nl_socket_get_fd(sock))); - - nl_socket_set_nonblocking(sock); - - queue_genl_read(); - } - - /** - * Start VPN connection - * - * At the moment, only client mode and ipv4/udp transport is supported. - * - * Note: this and many other methods have \p nla_put_failure label, which - * must be defined when using NLA_PUT_XXX macros. - * - * @param socket file descriptor of transport socket, created by client - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void start_vpn(int socket) { - auto msg_ptr = create_msg(OVPN_CMD_START_VPN); - auto* msg = msg_ptr.get(); - - NLA_PUT_U32(msg, OVPN_ATTR_SOCKET, socket); - NLA_PUT_U8(msg, OVPN_ATTR_PROTO, OVPN_PROTO_UDP4); - NLA_PUT_U8(msg, OVPN_ATTR_MODE, OVPN_MODE_CLIENT); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " start_vpn() nla_put_failure"); - } - - /** - * Add peer information to kernel module - * - * @tparam T ASIO's transport socket endpoint type - * @param local_endpoint local endpoint - * @param remote_endpoint remote endpoiont - * @throws netlink_error thrown if error occurs during sending netlink message - */ - template <typename T> void new_peer(T local_endpoint, T remote_endpoint) { - auto msg_ptr = create_msg(OVPN_CMD_NEW_PEER); - auto* msg = msg_ptr.get(); - - struct in_addr laddr; - std::memcpy(&laddr.s_addr, - local_endpoint.address().to_v4().to_bytes().data(), 4); - struct in_addr raddr; - std::memcpy(&raddr.s_addr, - remote_endpoint.address().to_v4().to_bytes().data(), 4); - - struct nlattr *addr = nla_nest_start(msg, OVPN_ATTR_SOCKADDR_REMOTE); - NLA_PUT(msg, OVPN_SOCKADDR_ATTR_ADDRESS, 4, &raddr); - NLA_PUT_U16(msg, OVPN_SOCKADDR_ATTR_PORT, remote_endpoint.port()); - nla_nest_end(msg, addr); - - addr = nla_nest_start(msg, OVPN_ATTR_SOCKADDR_LOCAL); - NLA_PUT(msg, OVPN_SOCKADDR_ATTR_ADDRESS, 4, &laddr); - NLA_PUT_U16(msg, OVPN_SOCKADDR_ATTR_PORT, local_endpoint.port()); - nla_nest_end(msg, addr); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " new_peer() nla_put_failure"); - } - - /** - * Send data to kernel module, which is then sent to remote. - * Used for sending control channel packets. - * - * @param data binary blob - * @param len length of binary blob - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void send_data(const void *data, size_t len) { - auto msg_ptr = create_msg(OVPN_CMD_PACKET); - auto* msg = msg_ptr.get(); - - NLA_PUT(msg, OVPN_ATTR_PACKET, len, data); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " send_data() nla_put_failure"); - } - - /** - * Inject new key into kernel module - * - * @param key_slot OVPN_KEY_SLOT_PRIMARY or OVPN_KEY_SLOT_SECONDARY - * @param kc pointer to KeyConfig struct which contains key data - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc) { - auto msg_ptr = create_msg(OVPN_CMD_NEW_KEY); - auto* msg = msg_ptr.get(); - - const int NONCE_LEN = 12; - - struct nlattr *key_dir; - - NLA_PUT_U32(msg, OVPN_ATTR_REMOTE_PEER_ID, kc->remote_peer_id); - NLA_PUT_U8(msg, OVPN_ATTR_KEY_SLOT, key_slot); - NLA_PUT_U16(msg, OVPN_ATTR_KEY_ID, kc->key_id); - NLA_PUT_U16(msg, OVPN_ATTR_CIPHER_ALG, kc->cipher_alg); - if ((kc->cipher_alg == OVPN_CIPHER_ALG_AES_CBC) || - (kc->cipher_alg == OVPN_CIPHER_ALG_NONE)) { - NLA_PUT_U16(msg, OVPN_ATTR_HMAC_ALG, kc->hmac_alg); - } - - key_dir = nla_nest_start(msg, OVPN_ATTR_ENCRYPT_KEY); - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->encrypt.cipher_key_size, - kc->encrypt.cipher_key); - if (kc->cipher_alg == OVPN_CIPHER_ALG_AES_GCM) { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_LEN, - kc->encrypt.nonce_tail); - } else { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_HMAC_KEY, kc->encrypt.hmac_key_size, - kc->encrypt.hmac_key); - } - nla_nest_end(msg, key_dir); - - key_dir = nla_nest_start(msg, OVPN_ATTR_DECRYPT_KEY); - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->decrypt.cipher_key_size, - kc->decrypt.cipher_key); - if (kc->cipher_alg == OVPN_CIPHER_ALG_AES_GCM) { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_LEN, - kc->decrypt.nonce_tail); - } else { - NLA_PUT(msg, OVPN_KEY_DIR_ATTR_HMAC_KEY, kc->decrypt.hmac_key_size, - kc->decrypt.hmac_key); - } - nla_nest_end(msg, key_dir); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " set_keys() nla_put_failure"); - } - - /** - * Swap keys between primary and secondary slots. Called - * by client as part of rekeying logic to promote and demote keys. - * - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void swap_keys() { - auto msg_ptr = create_msg(OVPN_CMD_SWAP_KEYS); - auto* msg = msg_ptr.get(); - - send_netlink_message(msg); - } - - /** - * Remove key from key slot. - * - * @param key_slot OVPN_KEY_SLOT_PRIMARY or OVPN_KEY_SLOT_SECONDARY - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void del_key(unsigned int key_slot) { - auto msg_ptr = create_msg(OVPN_CMD_DEL_KEY); - auto* msg = msg_ptr.get(); - - NLA_PUT_U8(msg, OVPN_ATTR_KEY_SLOT, key_slot); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " del_key() nla_put_failure"); - } - - /** - * Set peer properties. Currently used for keepalive settings. - * - * @param keepalive_interval how often to send ping packet in absence of - * traffic - * @param keepalive_timeout when to trigger keepalive_timeout in absence of - * traffic - * @throws netlink_error thrown if error occurs during sending netlink message - */ - void set_peer(unsigned int keepalive_interval, - unsigned int keepalive_timeout) { - auto msg_ptr = create_msg(OVPN_CMD_SET_PEER); - auto* msg = msg_ptr.get(); - - NLA_PUT_U32(msg, OVPN_ATTR_KEEPALIVE_INTERVAL, keepalive_interval); - NLA_PUT_U32(msg, OVPN_ATTR_KEEPALIVE_TIMEOUT, keepalive_timeout); - - send_netlink_message(msg); - return; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " set_peer() nla_put_failure"); - } - - void stop() { - if (!halt) { - halt = true; - - try { - stream->cancel(); - stream->close(); - } catch (...) { - // ASIO might throw transport exceptions which I found is safe to ignore - } - - // contrary to what ASIO doc says, stream->close() doesn't - // cancel async read on netlink socket, explicitly close it here - sock_ptr.reset(); - cb_ptr.reset(); - } - } - -private: - void register_packet() { - auto msg_ptr = create_msg(OVPN_CMD_REGISTER_PACKET); - auto* msg = msg_ptr.get(); - - send_netlink_message(msg); - } - - struct mcast_handler_args { - const char *group; - int id; - }; - - /** - * This callback is called by libnl. Here we enumerate netlink - * multicast groups and find id of the one which name matches - * ovpn-dco multicast group. - * - * @param msg netlink message to be processed - * @param arg arguments passed by nl_cb_set() call - * @return int id of ovpn-dco multicast group - */ - static int mcast_family_handler(struct nl_msg *msg, void *arg) { - struct mcast_handler_args *grp = static_cast<mcast_handler_args *>(arg); - struct nlattr *tb[CTRL_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = static_cast<genlmsghdr *>( - nlmsg_data(reinterpret_cast<const nlmsghdr *>(nlmsg_hdr(msg)))); - struct nlattr *mcgrp; - int rem_mcgrp; - - nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb[CTRL_ATTR_MCAST_GROUPS]) - return NL_SKIP; - - nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) { - struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1]; - - nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, - static_cast<nlattr *>(nla_data(mcgrp)), nla_len(mcgrp), NULL); - - if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || - !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]) - continue; - if (strncmp((const char *)nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), - grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))) - continue; - grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]); - break; - } - - return NL_SKIP; - } - - /** - * Return id of multicast group which ovpn-dco uses to - * broadcast OVPN_CMD_DEL_PEER message - * - * @return int multicast group id - */ - int get_mcast_id() { - int ret = 1; - struct mcast_handler_args grp = { - .group = OVPN_NL_MULTICAST_GROUP_PEERS, - .id = -ENOENT, - }; - NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free); - auto* msg = msg_ptr.get(); - - NlCbPtr mcast_cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put); - auto* mcast_cb = mcast_cb_ptr.get(); - - int ctrlid = genl_ctrl_resolve(sock, "nlctrl"); - - genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0); - NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME); - - send_netlink_message(msg); - - nl_cb_err( - mcast_cb, NL_CB_CUSTOM, - [](struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) { - int *ret = static_cast<int *>(arg); - *ret = err->error; - return (int)NL_STOP; - }, - &ret); - nl_cb_set( - mcast_cb, NL_CB_ACK, NL_CB_CUSTOM, - [](struct nl_msg *msg, void *arg) { - int *ret = static_cast<int *>(arg); - *ret = 0; - return (int)NL_STOP; - }, - &ret); - - nl_cb_set(mcast_cb, NL_CB_VALID, NL_CB_CUSTOM, mcast_family_handler, &grp); - - while (ret > 0) - nl_recvmsgs(sock, mcast_cb); - - if (ret == 0) - ret = grp.id; - - return ret; - - nla_put_failure: - OPENVPN_THROW(netlink_error, "get_mcast_id() nla_put_failure"); - } - - void handle_read(const openvpn_io::error_code &error) { - if (halt) - return; - - std::ostringstream os; - if (error) { - os << "error reading netlink message: " << error.message() << ", " - << error; - reset_buffer(); - int8_t cmd = -1; - buf.write(&cmd, sizeof(cmd)); - buf_write_string(buf, os.str()); - read_handler->tun_read_handler(buf); - } - - try { - read_netlink_message(); - queue_genl_read(); - } catch (const netlink_error &e) { - reset_buffer(); - int8_t cmd = -1; - buf.write(&cmd, sizeof(cmd)); - buf_write_string(buf, e.what()); - read_handler->tun_read_handler(buf); - } - } - - void queue_genl_read() { - stream->async_wait(openvpn_io::posix::stream_descriptor::wait_read, - [self = Ptr(this)](const openvpn_io::error_code &error) { - self->handle_read(error); - }); - } - - NlMsgPtr create_msg(enum ovpn_nl_commands cmd) { - NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free); - genlmsg_put(msg_ptr.get(), 0, 0, ovpn_dco_id, 0, 0, cmd, 0); - NLA_PUT_U32(msg_ptr.get(), OVPN_ATTR_IFINDEX, ifindex); - return msg_ptr; - - nla_put_failure: - OPENVPN_THROW(netlink_error, " start_vpn() nla_put_failure"); - } - - void read_netlink_message() { - // this is standard error code returned from kernel - // and assigned inside ovpn_nl_cb_error() - int ovpn_dco_err = 0; - nl_cb_err(cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &ovpn_dco_err); - - // this triggers reading callback, GeNL::message_received(), - // and, if neccessary, ovpn_nl_cb_error() and returns netlink error code - int netlink_err = nl_recvmsgs(sock, cb); - - if (ovpn_dco_err != 0) - OPENVPN_THROW(netlink_error, "ovpn-dco error on receiving message: " - << strerror(-ovpn_dco_err) << ", " - << ovpn_dco_err); - - if (netlink_err < 0) - OPENVPN_THROW(netlink_error, "netlink error on receiving message: " - << nl_geterror(netlink_err) << ", " - << netlink_err); - } - - /** - * This is called inside libnl's \c nl_recvmsgs() call - * to process incoming netlink message. - * - * @param msg netlink message to be processed - * @param arg argument passed by \c nl_cb_set() - * @return int callback action - */ - static int message_received(struct nl_msg *msg, void *arg) { - GeNL *self = static_cast<GeNL *>(arg); - - struct genlmsghdr *gnlh = static_cast<genlmsghdr *>( - nlmsg_data(reinterpret_cast<const nlmsghdr *>(nlmsg_hdr(msg)))); - struct nlattr *attrs[OVPN_ATTR_MAX + 1]; - - nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - switch (gnlh->cmd) { - case OVPN_CMD_PACKET: - if (!attrs[OVPN_ATTR_PACKET]) - OPENVPN_THROW( - netlink_error, - "missing OVPN_ATTR_PACKET attribute in OVPN_CMD_PACKET command"); - - { - self->reset_buffer(); - self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd)); - self->buf.write(nla_data(attrs[OVPN_ATTR_PACKET]), - nla_len(attrs[OVPN_ATTR_PACKET])); - // pass control channel message to upper layer - self->read_handler->tun_read_handler(self->buf); - } - break; - - case OVPN_CMD_DEL_PEER: - if (!attrs[OVPN_ATTR_DEL_PEER_REASON]) - OPENVPN_THROW(netlink_error, "missing OVPN_ATTR_DEL_PEER_REASON " - "attribute in OVPN_CMD_DEL_PEER command"); - - { - self->reset_buffer(); - self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd)); - uint8_t reason = nla_get_u8(attrs[OVPN_ATTR_DEL_PEER_REASON]); - self->buf.write(&reason, sizeof(reason)); - self->read_handler->tun_read_handler(self->buf); - } - break; - - default: - OPENVPN_LOG(__func__ << " unknown netlink command: " << (int)gnlh->cmd); - } - - return NL_SKIP; - } - - void reset_buffer() { - // good enough values to handle control packets - buf.reset(512, 3072, - BufferAllocated::GROW | BufferAllocated::CONSTRUCT_ZERO | - BufferAllocated::DESTRUCT_ZERO); - } - - /** - * This is an error callback called by netlink for - * error message processing customization. - * - * @param nla netlink address of the peer (value not needed here) - * @param err netlink error message being processed - * @param arg argument passed by \c nl_cb_err() - * @return int callback action - */ - static int ovpn_nl_cb_error(struct sockaddr_nl* /*nla*/, - struct nlmsgerr *err, void *arg) { - struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1; - struct nlattr *tb_msg[NLMSGERR_ATTR_MAX + 1]; - int len = nlh->nlmsg_len; - struct nlattr *attrs; - int *ret = static_cast<int *>(arg); - int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh); - - *ret = err->error; - - if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) - return NL_STOP; - - if (!(nlh->nlmsg_flags & NLM_F_CAPPED)) - ack_len += err->msg.nlmsg_len - sizeof(*nlh); - - if (len <= ack_len) - return NL_STOP; - - attrs = reinterpret_cast<nlattr *>((unsigned char *)nlh + ack_len); - len -= ack_len; - - nla_parse(tb_msg, NLMSGERR_ATTR_MAX, attrs, len, NULL); - if (tb_msg[NLMSGERR_ATTR_MSG]) { - len = strnlen((char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]), - nla_len(tb_msg[NLMSGERR_ATTR_MSG])); - OPENVPN_LOG(__func__ << " kernel error " - << (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG])); - } - - return NL_STOP; - } - - void send_netlink_message(struct nl_msg *msg) { - int netlink_err = nl_send_auto(sock, msg); - - if (netlink_err < 0) - OPENVPN_THROW(netlink_error, "netlink error on sending message: " - << nl_geterror(netlink_err) << ", " - << netlink_err); - } - - NlSockPtr sock_ptr; - NlCbPtr cb_ptr; - - struct nl_sock *sock; - struct nl_cb *cb; - - int ovpn_dco_id; - unsigned int ifindex; - - ReadHandler read_handler; - - bool halt; - BufferAllocated buf; - - std::unique_ptr<openvpn_io::posix::stream_descriptor> stream; -}; -} // namespace openvpn \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/sitnl.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/sitnl.hpp deleted file mode 100644 index ff6e432..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/sitnl.hpp +++ /dev/null @@ -1,1090 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2018-2020 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_DONE) - { - 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); - if (ret < 0) - goto out; - } - } - else - { - OPENVPN_LOG(__func__ << ": rtnl: generic error: " - << strerror(-err->error) - << " (" << err->error << ")"); - ret = err->error; - } - } - goto out; - } - - if (cb) - { - ret = cb(h, arg_cb); - } - 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; - } - - // continue reading multipart message - if (!(h->nlmsg_flags & NLM_F_MULTI)) - 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; - std::string iface_to_ignore; - int metric; - IP::Route dst; - int prefix_len; - } 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; - int metric = 0; - - IP::Addr gw; - - IP::Route route; - switch (res->family) - { - case AF_INET: - route = IP::Route("0.0.0.0/0"); - break; - case AF_INET6: - route = IP::Route("::/0"); - break; - } - - 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 */ - { - const unsigned char *bytestr = (unsigned char *)RTA_DATA(rta); - switch (res->family) - { - case AF_INET: - route = IP::Route(IPv4::Addr::from_bytes_net(bytestr).to_string() + "/" + std::to_string(r->rtm_dst_len)); - break; - case AF_INET6: - route = IP::Route(IPv6::Addr::from_byte_string(bytestr).to_string() + "/" + std::to_string(r->rtm_dst_len)); - break; - } - } - break; - case RTA_PRIORITY: - metric = *(unsigned int *)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: - gw = IP::Addr::from_ipv4(IPv4::Addr::from_bytes_net(bytestr)); - break; - case AF_INET6: - gw = IP::Addr::from_ipv6(IPv6::Addr::from_byte_string(bytestr)); - break; - } - } - break; - } - - rta = RTA_NEXT(rta, len); - } - - if (!gw.defined() || ifindex <= 0) - { - return 0; - } - else - { - OPENVPN_LOG_RTNL(__func__ << ": RTA_GATEWAY " << gw.to_string()); - } - - if (!route.contains(res->dst)) - { - OPENVPN_LOG_RTNL(__func__ << ": Ignore gw for unmatched route " << route.to_string()); - return 0; - } - - char iface[IFNAMSIZ]; - if (!if_indextoname(ifindex, iface)) - { - OPENVPN_LOG(__func__ << ": rtnl: can't get ifname for index " - << ifindex); - return -1; - } - - if (res->iface_to_ignore == iface) - { - OPENVPN_LOG_RTNL(__func__ << ": Ignore gw " << gw.to_string() << " on " << iface); - return 0; - } - - // skip if gw's route prefix is shorter - if (r->rtm_dst_len < res->prefix_len) - { - OPENVPN_LOG_RTNL(__func__ << ": Ignore gw " << gw.to_string() << " with shorter route prefix " << route.to_string()); - return 0; - } - - // skip if gw's route metric is higher - if ((metric > res->metric) && (res->metric != -1)) - { - OPENVPN_LOG_RTNL(__func__ << ": Ignore gw " << gw.to_string() << " with higher metrics " << metric); - return 0; - } - - res->iface = iface; - res->gw = gw; - res->metric = metric; - res->prefix_len = res->prefix_len; - - OPENVPN_LOG_RTNL(__func__ << ": Use gw " << gw.to_string() << " route " << route.to_string() << " metric " << metric); - - return 0; - } - - /** - * Searches for best gateway for a given route - * @param iface_to_ignore this allows to exclude certain interface - * from discovered gateways. Used when we want to exclude VPN interface - * when there is active VPN connection with redirected default gateway - * @param route route for which we search gw - * @param [out] best_gw found gw - * @param [out] best_iface network interface on which gw was found - * @return - */ - static int - sitnl_route_best_gw(const std::string& iface_to_ignore, - const IP::Route& route, - IP::Addr& best_gw, - std::string& best_iface) - { - struct sitnl_route_req req = { }; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r)); - req.n.nlmsg_type = RTM_GETROUTE; - req.n.nlmsg_flags = NLM_F_REQUEST; - - route_res_t res; - res.metric = -1; - res.prefix_len = -1; - - int ret = -EINVAL; - - 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; - } - - res.iface_to_ignore = iface_to_ignore; - res.dst = route; - - { - 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, 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, const std::string& iface_to_ignore = "") - { - IP::Addr best_gw; - int ret; - - OPENVPN_LOG(__func__ << " query IPv6: " << route); - - ret = sitnl_route_best_gw(iface_to_ignore, 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, const std::string& iface_to_ignore = "") - { - IP::Addr best_gw; - int ret; - - OPENVPN_LOG(__func__ << " query IPv4: " << route); - - ret = sitnl_route_best_gw(iface_to_ignore, 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; - } - - /** - * @brief Add new interface (similar to ip link add) - * - * @param iface interface name - * @param type interface link type (for example "ovpn-dco") - * @return int 0 on success, negative error code on error - */ - static int - net_iface_new(const std::string& iface, const std::string& type) - { - struct sitnl_link_req req = { }; - struct rtattr *tail = NULL; - int ret = -1; - - if (iface.empty()) - { - OPENVPN_LOG(__func__ << ": passed empty interface"); - return -EINVAL; - } - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - req.n.nlmsg_type = RTM_NEWLINK; - - SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface.c_str(), - iface.length() + 1); - tail = NLMSG_TAIL(&req.n); - SITNL_ADDATTR(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); - SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, type.c_str(), - type.length() + 1); - tail->rta_len = (uint8_t *)NLMSG_TAIL(&req.n) - (uint8_t *)tail; - - req.i.ifi_family = AF_PACKET; - req.i.ifi_index = 0; - - OPENVPN_LOG(__func__ << ": add " << iface << " type " << type); - - ret = sitnl_send(&req.n, 0, 0, NULL, NULL); -err: - return ret; - } - - static int - net_iface_del(const std::string& iface) - { - 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_DELLINK; - - req.i.ifi_family = AF_PACKET; - req.i.ifi_index = ifindex; - - OPENVPN_LOG(__func__ << ": idel " << iface); - - return sitnl_send(&req.n, 0, 0, NULL, NULL); - } - - static int - net_iface_up(std::string& iface, bool up) - { - struct sitnl_link_req req = { }; - int ifindex; - - if (iface.empty()) - { - OPENVPN_LOG(__func__ << ": passed empty interface"); - return -EINVAL; - } - - ifindex = if_nametoindex(iface.c_str()); - if (ifindex == 0) - { - OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface - << ": " << strerror(errno)); - return -ENOENT; - } - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_NEWLINK; - - req.i.ifi_family = AF_PACKET; - req.i.ifi_index = ifindex; - req.i.ifi_change |= IFF_UP; - if (up) - { - req.i.ifi_flags |= IFF_UP; - } - else - { - req.i.ifi_flags &= ~IFF_UP; - } - - OPENVPN_LOG(__func__ << ": set " << iface << " " << (up ? "up" : "down")); - - return sitnl_send(&req.n, 0, 0, NULL, NULL); - } - - static int - net_iface_mtu_set(std::string& iface, uint32_t mtu) - { - struct sitnl_link_req req = { }; - int ifindex; - - if (iface.empty()) - { - OPENVPN_LOG(__func__ << ": passed empty interface"); - return -EINVAL; - } - - ifindex = if_nametoindex(iface.c_str()); - if (ifindex == 0) - { - OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface); - return -1; - } - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_NEWLINK; - - req.i.ifi_family = AF_PACKET; - req.i.ifi_index = ifindex; - - SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4); - - OPENVPN_LOG(__func__ << ": mtu " << mtu << " for " << iface); - -err: - return sitnl_send(&req.n, 0, 0, NULL, NULL); - } - - static int - net_addr_add(const std::string& iface, const IPv4::Addr& addr, - const int prefixlen, const IPv4::Addr& broadcast) - { - OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " brd " - << broadcast << " dev " << iface); - - return sitnl_addr_add(iface, IP::Addr::from_ipv4(addr), prefixlen, - IP::Addr::from_ipv4(broadcast)); - } - - static int - net_addr_add(const std::string& iface, const IPv6::Addr& addr, - const int prefixlen) - { - OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface); - - return sitnl_addr_add(iface, IP::Addr::from_ipv6(addr), prefixlen, - IP::Addr::from_zero(IP::Addr::V6)); - } - - static int - net_addr_del(const std::string& iface, const IPv4::Addr& addr, - const int prefixlen) - { - OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface); - - return sitnl_addr_del(iface, IP::Addr::from_ipv4(addr), prefixlen); - } - - static int - net_addr_del(const std::string& iface, const IPv6::Addr& addr, - const int prefixlen) - { - OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface); - - return sitnl_addr_del(iface, IP::Addr::from_ipv6(addr), prefixlen); - } - - static int - net_addr_ptp_add(const std::string& iface, const IPv4::Addr& local, - const IPv4::Addr& remote) - { - OPENVPN_LOG(__func__ << ": " << local << " peer " << remote << " dev " << iface); - - return sitnl_addr_ptp_add(iface, IP::Addr::from_ipv4(local), - IP::Addr::from_ipv4(remote)); - } - - static int - net_addr_ptp_del(const std::string& iface, const IPv4::Addr& local, - const IPv4::Addr& remote) - { - OPENVPN_LOG(__func__ << ": " << local << " dev " << iface); - - return sitnl_addr_ptp_del(iface, IP::Addr::from_ipv4(local)); - } - - static int - net_route_add(const IP::Route4& route, const IPv4::Addr& gw, - const std::string& iface, const uint32_t table, - const int metric) - { - OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface - << " table " << table << " metric " << metric); - - return sitnl_route_add(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len), - IP::Addr::from_ipv4(gw), iface, table, metric); - } - - static int - net_route_add(const IP::Route6& route, const IPv6::Addr& gw, - const std::string& iface, const uint32_t table, - const int metric) - { - OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface - << " table " << table << " metric " << metric); - - return sitnl_route_add(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len), - IP::Addr::from_ipv6(gw), iface, table, metric); - } - - static int - net_route_del(const IP::Route4& route, const IPv4::Addr& gw, - const std::string& iface, const uint32_t table, - const int metric) - { - OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface - << " table " << table << " metric " << metric); - - return sitnl_route_del(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len), - IP::Addr::from_ipv4(gw), iface, table, metric); - } - - static int - net_route_del(const IP::Route6& route, const IPv6::Addr& gw, - const std::string& iface, const uint32_t table, - const int metric) - { - OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface - << " table " << table << " metric " << metric); - - return sitnl_route_del(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len), - IP::Addr::from_ipv6(gw), iface, table, metric); - } - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/tuncli.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/tuncli.hpp deleted file mode 100644 index accfd93..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/tuncli.hpp +++ /dev/null @@ -1,348 +0,0 @@ -// 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-2020 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/>. - -// Client tun interface for Linux. - -#ifndef OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H -#define OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H - -#include <openvpn/asio/asioerr.hpp> -#include <openvpn/common/cleanup.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/tun/builder/setup.hpp> -#include <openvpn/tun/tunio.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/linux/client/tunmethods.hpp> - -namespace openvpn { - namespace TunLinux { - - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - - template <typename ReadHandler> - class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> - { - typedef TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor> Base; - - public: - typedef RCPtr<Tun> Ptr; - - Tun(openvpn_io::io_context& io_context, - ReadHandler read_handler_arg, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg, - const int socket, - const std::string& name) - : Base(read_handler_arg, frame_arg, stats_arg) - { - Base::name_ = name; - Base::retain_stream = true; - Base::stream = new openvpn_io::posix::stream_descriptor(io_context, socket); - OPENVPN_LOG_TUN(Base::name_ << " opened"); - } - - ~Tun() { Base::stop(); } - }; - - typedef TunPersistTemplate<ScopedFD> TunPersist; - - class ClientConfig : public TunClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - std::string dev_name; - int txqueuelen = 200; - - TunProp::Config tun_prop; - - int n_parallel = 8; - Frame::Ptr frame; - SessionStats::Ptr stats; - - TunBuilderSetup::Factory::Ptr tun_setup_factory; - TunPersist::Ptr tun_persist; - - void load(const OptionList& opt) - { - // set a default MTU - if (!tun_prop.mtu) - tun_prop.mtu = 1500; - - // parse "dev" option - if (dev_name.empty()) - { - const Option* dev = opt.get_ptr("dev"); - if (dev) - dev_name = dev->get(1, 64); - } - } - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli); - - TunBuilderSetup::Base::Ptr new_setup_obj() - { - if (tun_setup_factory) - return tun_setup_factory->new_setup_obj(); - else - return new TunLinuxSetup::Setup<TUN_LINUX>(); - } - - private: - ClientConfig() {} - }; - - class Client : public TunClient - { - friend class ClientConfig; // calls constructor - friend class TunIO<Client*, PacketFrom, openvpn_io::posix::stream_descriptor>; // calls tun_read_handler - - typedef Tun<Client*> TunImpl; - - public: - virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { - if (!impl) - { - halt = false; - - if (config->tun_persist) - { - OPENVPN_LOG("TunPersist: long-term session scope"); - tun_persist = config->tun_persist; // long-term persistent - } - else - { - OPENVPN_LOG("TunPersist: short-term connection scope"); - tun_persist.reset(new TunPersist(true, false, nullptr)); // short-term - } - - try { - const IP::Addr server_addr = transcli.server_endpoint_addr(); - - int sd = -1; - - // Check if persisted tun session matches properties of to-be-created session - if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) - { - state = tun_persist->state(); - sd = tun_persist->obj(); - state = tun_persist->state(); - OPENVPN_LOG("TunPersist: reused tun context"); - } - else - { - // notify parent - parent.tun_pre_tun_config(); - - // close old tun handle if persisted - tun_persist->close(); - - // parse pushed options - TunBuilderCapture::Ptr po(new TunBuilderCapture()); - TunProp::configure_builder(po.get(), - state.get(), - config->stats.get(), - server_addr, - config->tun_prop, - opt, - nullptr, - false); - - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - - // create new tun setup object - tun_setup = config->new_setup_obj(); - - // create config object for tun setup layer - TunLinuxSetup::Setup<TUN_LINUX>::Config tsconf; - tsconf.layer = config->tun_prop.layer; - tsconf.dev_name = config->dev_name; - tsconf.txqueuelen = config->txqueuelen; - tsconf.add_bypass_routes_on_establish = true; - - // open/config tun - { - std::ostringstream os; - auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - sd = tun_setup->establish(*po, &tsconf, nullptr, os); - } - - // persist tun settings state - state->iface_name = tsconf.iface_name; - tun_persist->persist_tun_state(sd, state); - - // enable tun_setup destructor - tun_persist->add_destructor(tun_setup); - } - - // start tun - impl.reset(new TunImpl(io_context, - this, - config->frame, - config->stats, - sd, - state->iface_name - )); - impl->start(config->n_parallel); - - // signal that we are connected - parent.tun_connected(); - } - catch (const std::exception& e) - { - if (tun_persist) - tun_persist->close(); - - stop(); - parent.tun_error(Error::TUN_SETUP_FAILED, e.what()); - } - } - } - - virtual bool tun_send(BufferAllocated& buf) override - { - return send(buf); - } - - virtual std::string tun_name() const override - { - if (impl) - return impl->name(); - else - return "UNDEF_TUN"; - } - - virtual std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - virtual std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - virtual void set_disconnect() override - { - } - - virtual void stop() override { stop_(); } - virtual ~Client() { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : io_context(io_context_arg), - config(config_arg), - parent(parent_arg), - state(new TunProp::State()), - halt(false) - { - } - - bool send(Buffer& buf) - { - if (impl) - return impl->write(buf); - else - return false; - } - - void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl - { - parent.tun_recv(pfp->buf); - } - - void tun_error_handler(const Error::Type errtype, // called by TunImpl - const openvpn_io::error_code* error) - { - } - - void stop_() - { - if (!halt) - { - halt = true; - - // stop tun - if (impl) - impl->stop(); - - tun_persist.reset(); - } - } - - openvpn_io::io_context& io_context; - TunPersist::Ptr tun_persist; - ClientConfig::Ptr config; - TunClientParent& parent; - TunImpl::Ptr impl; - TunProp::State::Ptr state; - TunBuilderSetup::Base::Ptr tun_setup; - bool halt; - }; - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - return TunClient::Ptr(new Client(io_context, this, parent)); - } - - } -} // namespace openvpn - -#endif // OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/tuniproute.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/tuniproute.hpp deleted file mode 100644 index 7382aab..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/tuniproute.hpp +++ /dev/null @@ -1,351 +0,0 @@ -// 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-2020 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/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/tun/builder/setup.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/linux/client/tunsetup.hpp> -#include <openvpn/netconf/linux/gw.hpp> - -namespace openvpn { - namespace TunIPRoute { - - using namespace openvpn::TunLinuxSetup; - - 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 IP::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 - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-6"); - add->argv.push_back("route"); - add->argv.push_back("prepend"); - add->argv.push_back(net.to_string() + '/' + openvpn::to_string(prefix_len)); - add->argv.push_back("via"); - add->argv.push_back(gateway_str); - if (!dev.empty()) - { - add->argv.push_back("dev"); - add->argv.push_back(dev); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - 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 - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-4"); - add->argv.push_back("route"); - add->argv.push_back("prepend"); - add->argv.push_back(net.to_string() + '/' + openvpn::to_string(prefix_len)); - add->argv.push_back("via"); - add->argv.push_back(gateway_str); - if (!dev.empty()) - { - add->argv.push_back("dev"); - add->argv.push_back(dev); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - 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) - { - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("link"); - add->argv.push_back("set"); - add->argv.push_back(iface_name); - add->argv.push_back("up"); - if (mtu > 0) - { - add->argv.push_back("mtu"); - add->argv.push_back(openvpn::to_string(mtu)); - } - create.add(add); - - // for the destroy command, copy the add command but replace "up" with "down" - Command::Ptr del(add->copy()); - del->argv[4] = "down"; - 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) - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-4"); - add->argv.push_back("addr"); - add->argv.push_back("add"); - add->argv.push_back(local4->address + '/' + openvpn::to_string(local4->prefix_length)); - add->argv.push_back("broadcast"); - add->argv.push_back((IPv4::Addr::from_string(local4->address) | ~IPv4::Addr::netmask_from_prefix_len(local4->prefix_length)).to_string()); - add->argv.push_back("dev"); - add->argv.push_back(iface_name); - 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" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - 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) - { - Command::Ptr add(new Command); - add->argv.push_back("/sbin/ip"); - add->argv.push_back("-6"); - add->argv.push_back("addr"); - add->argv.push_back("add"); - add->argv.push_back(local6->address + '/' + openvpn::to_string(local6->prefix_length)); - add->argv.push_back("dev"); - add->argv.push_back(iface_name); - create.add(add); - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[3] = "del"; - 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); - } - } - - struct TunMethods - { - static inline void tun_config(const std::string& iface_name, - const TunBuilderCapture& pull, - std::vector<IP::Route>* rtvec, - ActionList& create, - ActionList& destroy, - bool add_bypass_routes = true) - { - const LinuxGW46 gw(true); - - // 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 (local6 && !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 (add_bypass_routes && !pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL) && gw.v4.defined()) - 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 (add_bypass_routes && pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL) && gw.v4.defined()) - 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 - } - - static inline void add_bypass_route(const std::string& tun_iface_name, - const std::string& address, - bool ipv6, - std::vector<IP::Route>* rtvec, - ActionList& create, - ActionList& destroy) - { - LinuxGW46 gw(true); - - if (!ipv6 && gw.v4.defined()) - add_del_route(address, 32, gw.v4.addr().to_string(), gw.dev(), R_ADD_SYS, rtvec, create, destroy); - - if (ipv6 && gw.v6.defined()) - add_del_route(address, 128, gw.v6.addr().to_string(), gw.dev(), R_ADD_SYS, rtvec, create, destroy); - } - }; - } -} // namespace openvpn - diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/tunmethods.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/tunmethods.hpp deleted file mode 100644 index c9a902a..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/tunmethods.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// 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-2020 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 -// check if Netlink has been selected at compile time -#ifdef OPENVPN_USE_SITNL -#include <openvpn/tun/linux/client/tunnetlink.hpp> -#define TUN_LINUX openvpn::TunNetlink::TunMethods -#else -#include <openvpn/tun/linux/client/tuniproute.hpp> -#define TUN_LINUX openvpn::TunIPRoute::TunMethods -#endif \ No newline at end of file diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/tunnetlink.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/tunnetlink.hpp deleted file mode 100644 index 20b9f3d..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/tunnetlink.hpp +++ /dev/null @@ -1,752 +0,0 @@ -// 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-2020 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/asio/asioerr.hpp> -#include <openvpn/netconf/linux/gwnetlink.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/tun/builder/setup.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/linux/client/sitnl.hpp> -#include <openvpn/tun/linux/client/tunsetup.hpp> - -namespace openvpn { - namespace TunNetlink { - - using namespace openvpn::TunLinuxSetup; - - 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, - }; - - /** - * @brief Add new interface - * - * @param os output stream to where error message is written - * @param dev interface name - * @param type interface link type (such as "ovpn-dco") - * @return int 0 on success, negative error code on error - */ - inline int iface_new(std::ostringstream& os, const std::string& dev, const std::string& type) - { - int ret = -1; - - if (dev.empty()) - { - os << "Error: can't call NetlinkLinkNew with no interface" << std::endl; - return ret; - } - - if (type.empty()) - { - os << "Error: can't call NetlinkLinkNew with no interfacei type" << std::endl; - return ret; - } - - ret = SITNL::net_iface_new(dev, type); - if (ret) - { - os << "Error while executing NetlinkLinkNew " << dev << ": " << ret << std::endl; - } - - return ret; - } - - inline int iface_del(std::ostringstream& os, const std::string& dev) - { - int ret = -1; - - if (dev.empty()) - { - os << "Error: can't call NetlinkLinkDel with no interface" << std::endl; - return ret; - } - - ret = SITNL::net_iface_del(dev); - if (ret) - { - os << "Error while executing NetlinkLinkDel " << dev << ": " << ret << std::endl; - } - - return ret; - } - - /*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); - } - } - - struct TunMethods - { - static inline void tun_config(const std::string& iface_name, - const TunBuilderCapture& pull, - std::vector<IP::Route>* rtvec, - ActionList& create, - ActionList& destroy, - bool add_bypass_routes) - { - // 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 (local6 && !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 - if (!pull.exclude_routes.empty()) - { - LinuxGW46Netlink gw(iface_name); - - 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 (add_bypass_routes && !pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL)) - add_bypass_route(iface_name, pull.remote_address.address, false, 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 (add_bypass_routes && pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL)) - add_bypass_route(iface_name, pull.remote_address.address, true, 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 - } - - static inline void add_bypass_route(const std::string& tun_iface_name, - const std::string& address, - bool ipv6, - std::vector<IP::Route>* rtvec, - ActionList& create, - ActionList& destroy) - { - LinuxGW46Netlink gw(tun_iface_name, address); - - if (!ipv6 && gw.v4.defined()) - add_del_route(address, 32, gw.v4.addr().to_string(), gw.dev(), R_ADD_SYS, rtvec, create, destroy); - - if (ipv6 && gw.v6.defined()) - add_del_route(address, 128, gw.v6.addr().to_string(), gw.dev(), R_IPv6|R_ADD_SYS, rtvec, create, destroy); - } - }; - } -} // namespace openvpn diff --git a/Sources/OpenVPN3/openvpn/tun/linux/client/tunsetup.hpp b/Sources/OpenVPN3/openvpn/tun/linux/client/tunsetup.hpp deleted file mode 100644 index 449b590..0000000 --- a/Sources/OpenVPN3/openvpn/tun/linux/client/tunsetup.hpp +++ /dev/null @@ -1,262 +0,0 @@ -// 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-2020 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/>. - -// Client tun interface for Linux. - -#ifndef OPENVPN_TUN_LINUX_CLIENT_TUNSETUP_H -#define OPENVPN_TUN_LINUX_CLIENT_TUNSETUP_H - -#include <sys/ioctl.h> -#include <fcntl.h> -#include <errno.h> -#include <net/if.h> -#include <linux/if_tun.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/split.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/addr/route.hpp> -#include <openvpn/asio/asioerr.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/tun/builder/setup.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/netconf/linux/gw.hpp> - -namespace openvpn { - namespace TunLinuxSetup { - - 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); - - template <class TUNMETHODS> - class Setup : public TunBuilderSetup::Base - { - public: - typedef RCPtr<Setup> Ptr; - - // This empty constructor shouldn't be needed, but due to a - // plausible compiler bug in GCC 4.8.5 (RHEL 7), this empty - // constructor is required to be able to build. This is - // related to the member initialization of the private - // remove_cmds_bypass_gw and remove_cmds class members. - Setup() {} - - struct Config : public TunBuilderSetup::Config - { - std::string iface_name; - Layer layer; // OSI layer - std::string dev_name; - int txqueuelen; - bool add_bypass_routes_on_establish; // required when not using tunbuilder - bool dco = false; - -#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); - root["dco"] = Json::Value(dco); - 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); - json::to_bool(root, dco, "dco", title); - } -#endif - }; - - void destroy(std::ostream &os) override - { - // remove added routes - remove_cmds->execute(os); - - // remove bypass route - remove_cmds_bypass_gw->execute(os); - } - - bool add_bypass_route(const std::string& address, - bool ipv6, - std::ostream& os) - { - // nothing to do if we reconnect to the same gateway - if (connected_gw == address) - return true; - - // remove previous bypass route - remove_cmds_bypass_gw->execute(os); - remove_cmds_bypass_gw->clear(); - - ActionList::Ptr add_cmds = new ActionList(); - TUNMETHODS::add_bypass_route(tun_iface_name, address, ipv6, nullptr, *add_cmds, *remove_cmds_bypass_gw); - - // add gateway bypass route - add_cmds->execute(os); - return true; - } - - 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"); - - int fd = -1; - if (!conf->dco) - { - fd = open_tun(conf); - } - else - { - // in DCO case device is already opened - tun_iface_name = conf->iface_name; - } - - ActionList::Ptr add_cmds = new ActionList(); - ActionList::Ptr remove_cmds_new = new ActionListReversed(); - - // configure tun properties - TUNMETHODS::tun_config(tun_iface_name, pull, nullptr, *add_cmds, *remove_cmds_new, conf->add_bypass_routes_on_establish); - - // execute commands to bring up interface - add_cmds->execute(os); - - // tear down old routes - remove_cmds->execute(os); - std::swap(remove_cmds, remove_cmds_new); - - connected_gw = pull.remote_address.to_string(); - - return fd; - } - - private: - int open_tun(Config* conf) - { - 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; - tun_iface_name = ifr.ifr_name; - - return fd.release(); - } - - 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)); - } - } - } - - ActionList::Ptr remove_cmds_bypass_gw = new ActionList(); - ActionListReversed::Ptr remove_cmds = new ActionListReversed(); - - std::string connected_gw; - - std::string tun_iface_name; // used to skip tun-based default gw when add bypass route - }; - } -} // namespace openvpn - -#endif // OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H diff --git a/Sources/OpenVPN3/openvpn/tun/mac/client/tuncli.hpp b/Sources/OpenVPN3/openvpn/tun/mac/client/tuncli.hpp deleted file mode 100644 index c6dbfae..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/client/tuncli.hpp +++ /dev/null @@ -1,379 +0,0 @@ -// 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-2020 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/>. - -// Client tun interface for Mac OS X - -#ifndef OPENVPN_TUN_MAC_CLIENT_TUNCLI_H -#define OPENVPN_TUN_MAC_CLIENT_TUNCLI_H - -#include <string> -#include <sstream> -#include <memory> - -#include <openvpn/common/to_string.hpp> -#include <openvpn/asio/scoped_asio_stream.hpp> -#include <openvpn/common/cleanup.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/persist/tunwrapasio.hpp> -#include <openvpn/tun/tunio.hpp> -#include <openvpn/tun/mac/client/tunsetup.hpp> - -#ifdef TEST_EER // test emulated exclude routes -#include <openvpn/client/cliemuexr.hpp> -#endif - -namespace openvpn { - namespace TunMac { - - OPENVPN_EXCEPTION(tun_mac_error); - - // struct used to pass received tun packets - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - - // tun interface wrapper for Mac OS X - template <typename ReadHandler, typename TunPersist> - class Tun : public TunIO<ReadHandler, PacketFrom, TunWrapAsioStream<TunPersist> > - { - typedef TunIO<ReadHandler, PacketFrom, TunWrapAsioStream<TunPersist> > Base; - - public: - typedef RCPtr<Tun> Ptr; - - Tun(const typename TunPersist::Ptr& tun_persist, - const std::string& name, - const bool retain_stream, - const bool tun_prefix, - ReadHandler read_handler, - const Frame::Ptr& frame, - const SessionStats::Ptr& stats) - : Base(read_handler, frame, stats) - { - Base::name_ = name; - Base::retain_stream = retain_stream; - Base::tun_prefix = tun_prefix; - Base::stream = new TunWrapAsioStream<TunPersist>(tun_persist); - } - }; - - // These types manage the underlying tun driver fd - typedef openvpn_io::posix::stream_descriptor TUNStream; - typedef ScopedAsioStream<TUNStream> ScopedTUNStream; - typedef TunPersistTemplate<ScopedTUNStream> TunPersist; - - class Client; - - class ClientConfig : public TunClientFactory - { - public: - typedef RCPtr<ClientConfig> Ptr; - - TunProp::Config tun_prop; - int n_parallel = 8; // number of parallel async reads on tun socket - - Frame::Ptr frame; - SessionStats::Ptr stats; - - TunPersist::Ptr tun_persist; - - Stop* stop = nullptr; - - TunBuilderSetup::Factory::Ptr tun_setup_factory; - - TunBuilderSetup::Base::Ptr new_setup_obj() - { - if (tun_setup_factory) - return tun_setup_factory->new_setup_obj(); - else - return new TunMac::Setup(); - } - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli); - - // return true if layer 2 tunnels are supported - virtual bool layer_2_supported() const - { -# if defined(MAC_TUNTAP_FALLBACK) - return false; // change to true after TAP support is added -# else - return false; // utun device doesn't support TAP -# endif - } - - // called just prior to transmission of Disconnect event - virtual void finalize(const bool disconnected) - { - if (disconnected) - tun_persist.reset(); - } - }; - - class Client : public TunClient - { - friend class ClientConfig; // calls constructor - friend class TunIO<Client*, PacketFrom, TunWrapAsioStream<TunPersist> >; // calls tun_read_handler - - typedef Tun<Client*, TunPersist> TunImpl; - - public: - virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { - if (!impl) - { - halt = false; - if (config->tun_persist) - { - OPENVPN_LOG("TunPersist: long-term session scope"); - tun_persist = config->tun_persist; - } - else - { - OPENVPN_LOG("TunPersist: short-term connection scope"); - tun_persist.reset(new TunPersist(false, false, NULL)); - } - - try { - const IP::Addr server_addr = transcli.server_endpoint_addr(); - - // Check if persisted tun session matches properties of to-be-created session - if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) - { - state = tun_persist->state(); - OPENVPN_LOG("TunPersist: reused tun context"); - } - else - { - OPENVPN_LOG("TunPersist: new tun context"); - - // notify parent - parent.tun_pre_tun_config(); - - // close old tun handle if persisted - tun_persist->close(); - - // emulated exclude routes - EmulateExcludeRouteFactory::Ptr eer_factory; -#ifdef TEST_EER - eer_factory.reset(new EmulateExcludeRouteFactoryImpl(true)); -#endif - // parse pushed options - TunBuilderCapture::Ptr po(new TunBuilderCapture()); - TunProp::configure_builder(po.get(), - state.get(), - config->stats.get(), - server_addr, - config->tun_prop, - opt, - eer_factory.get(), - false); - - // handle MTU default - if (!po->mtu) - po->mtu = 1500; - - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - - // create new tun setup object - tun_setup = config->new_setup_obj(); - - // create config object for tun setup layer - Setup::Config tsconf; - tsconf.iface_name = state->iface_name; - tsconf.layer = config->tun_prop.layer; - - // open/config tun - int fd = -1; - { - std::ostringstream os; - auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - fd = tun_setup->establish(*po, &tsconf, config->stop, os); - } - - // create ASIO wrapper for tun fd - TUNStream* ts = new TUNStream(io_context, fd); - - // persist tun settings state - state->iface_name = tsconf.iface_name; - state->tun_prefix = tsconf.tun_prefix; - if (tun_persist->persist_tun_state(ts, state)) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); - - // enable tun_setup destructor - tun_persist->add_destructor(tun_setup); - } - - // configure tun interface packet forwarding - impl.reset(new TunImpl(tun_persist, - state->iface_name, - true, - state->tun_prefix, - this, - config->frame, - config->stats - )); - impl->start(config->n_parallel); - - // signal that we are connected - parent.tun_connected(); - } - catch (const std::exception& e) - { - if (tun_persist) - tun_persist->close(); - stop(); - Error::Type err = Error::TUN_SETUP_FAILED; - const ExceptionCode *ec = dynamic_cast<const ExceptionCode *>(&e); - if (ec && ec->code_defined()) - err = ec->code(); - parent.tun_error(err, e.what()); - } - } - } - - virtual bool tun_send(BufferAllocated& buf) override - { - return send(buf); - } - - virtual std::string tun_name() const override - { - if (impl) - return impl->name(); - else - return "UNDEF_TUN"; - } - - virtual std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - virtual std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - virtual void set_disconnect() override - { - } - - virtual void stop() override { stop_(); } - virtual ~Client() { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : io_context(io_context_arg), - config(config_arg), - parent(parent_arg), - halt(false), - state(new TunProp::State()) - { - } - - bool send(Buffer& buf) - { - if (impl) - return impl->write(buf); - else - return false; - } - - void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl - { - parent.tun_recv(pfp->buf); - } - - void tun_error_handler(const Error::Type errtype, // called by TunImpl - const openvpn_io::error_code* error) - { - parent.tun_error(Error::TUN_ERROR, "TUN I/O error"); - } - - void stop_() - { - if (!halt) - { - halt = true; - - // stop tun - if (impl) - impl->stop(); - tun_persist.reset(); - } - } - - openvpn_io::io_context& io_context; - TunPersist::Ptr tun_persist; // contains the tun device fd - ClientConfig::Ptr config; - TunClientParent& parent; - TunImpl::Ptr impl; - bool halt; - TunProp::State::Ptr state; - TunBuilderSetup::Base::Ptr tun_setup; - }; - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - return TunClient::Ptr(new Client(io_context, this, parent)); - } - - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/client/tunsetup.hpp b/Sources/OpenVPN3/openvpn/tun/mac/client/tunsetup.hpp deleted file mode 100644 index e64b471..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/client/tunsetup.hpp +++ /dev/null @@ -1,507 +0,0 @@ -// 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-2020 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/>. - -// Client tun setup for Mac - -#ifndef OPENVPN_TUN_MAC_CLIENT_TUNSETUP_H -#define OPENVPN_TUN_MAC_CLIENT_TUNSETUP_H - -#include <string> -#include <sstream> -#include <ostream> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/common/jsonlib.hpp> -#include <openvpn/error/excode.hpp> -#include <openvpn/tun/layer.hpp> -#include <openvpn/tun/mac/tunutil.hpp> -#include <openvpn/tun/mac/utun.hpp> -#include <openvpn/tun/mac/macgw.hpp> -#include <openvpn/tun/mac/macdns_watchdog.hpp> -#include <openvpn/tun/proxy.hpp> -#include <openvpn/tun/mac/macproxy.hpp> -#include <openvpn/tun/builder/rgwflags.hpp> -#include <openvpn/tun/builder/setup.hpp> - -#ifdef HAVE_JSON -#include <openvpn/common/jsonhelper.hpp> -#endif - -namespace openvpn { - namespace TunMac { - class Setup : public TunBuilderSetup::Base - { - public: - typedef RCPtr<Setup> Ptr; - - OPENVPN_EXCEPTION(tun_mac_setup); - - struct Config : public TunBuilderSetup::Config - { - std::string iface_name; - Layer layer; // OSI layer - bool tun_prefix = false; - bool add_bypass_routes_on_establish = false; - -#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["tun_prefix"] = Json::Value(tun_prefix); - 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_bool(root, tun_prefix, "tun_prefix", title); - } -#endif - }; - - bool add_bypass_route(const std::string& address, - bool ipv6, - std::ostream& os) - { - // not yet implemented - return true; - } - - 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_mac_setup("missing config"); - - // close out old remove cmds, if they exist - destroy(os); - - // Open tun device. Try Mac OS X integrated utun device first - // (layer 3 only). If utun fails and MAC_TUNTAP_FALLBACK is defined, - // then fall back to TunTap third-party device. - // If successful, conf->iface_name will be set to tun iface name. - int fd = -1; - conf->tun_prefix = false; - try { -# if defined(MAC_TUNTAP_FALLBACK) -# if !defined(ASIO_DISABLE_KQUEUE) -# error Mac OS X TunTap adapter is incompatible with kqueue; rebuild with ASIO_DISABLE_KQUEUE -# endif - if (conf->layer() == Layer::OSI_LAYER_3) - { - try { - fd = UTun::utun_open(conf->iface_name); - conf->tun_prefix = true; - } - catch (const std::exception& e) - { - os << e.what() << std::endl; - } - } - if (fd == -1) - fd = Util::tuntap_open(conf->layer, conf->iface_name); -# else - fd = UTun::utun_open(conf->iface_name); - conf->tun_prefix = true; -# endif - } - catch (const std::exception& e) - { - throw ErrorCode(Error::TUN_IFACE_CREATE, true, e.what()); - } - - // create ActionLists for setting up and removing adapter properties - ActionList::Ptr add_cmds(new ActionList()); - remove_cmds.reset(new ActionList()); - - // populate add/remove lists with actions - tun_config(conf->iface_name, pull, *add_cmds, *remove_cmds, os); - - // execute the add actions - add_cmds->execute(os); - - // now that the add actions have succeeded, - // enable the remove actions - remove_cmds->enable_destroy(true); - - os << "open " << conf->iface_name << " SUCCEEDED" << std::endl; - return fd; - } - - virtual void destroy(std::ostream& os) override // defined by DestructorBase - { - if (remove_cmds) - { - remove_cmds->destroy(os); - remove_cmds.reset(); - } - } - - virtual ~Setup() - { - std::ostringstream os; - destroy(os); - } - - private: - enum { // add_del_route flags - R_IPv6=(1<<0), - R_IFACE=(1<<1), - R_IFACE_HINT=(1<<2), - R_ONLINK=(1<<3), - R_REJECT=(1<<4), - R_BLACKHOLE=(1<<5), - }; - - static void add_del_route(const std::string& addr_str, - const int prefix_len, - const std::string& gateway_str, - const std::string& iface, - const unsigned int flags, - 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; - - Command::Ptr add(new Command); - add->argv.push_back("/sbin/route"); - add->argv.push_back("add"); - add->argv.push_back("-net"); - add->argv.push_back("-inet6"); - add->argv.push_back(net.to_string()); - add->argv.push_back("-prefixlen"); - add->argv.push_back(to_string(prefix_len)); - if (flags & R_REJECT) - add->argv.push_back("-reject"); - if (flags & R_BLACKHOLE) - add->argv.push_back("-blackhole"); - if (!iface.empty()) - { - if (flags & R_IFACE) - { - add->argv.push_back("-iface"); - add->argv.push_back(iface); - } - } - if (!gateway_str.empty() && !(flags & R_IFACE)) - { - std::string g = gateway_str; - if (flags & R_IFACE_HINT) - g += '%' + iface; - add->argv.push_back(g); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[1] = "delete"; - destroy = del; - } - 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; - - Command::Ptr add(new Command); - add->argv.push_back("/sbin/route"); - add->argv.push_back("add"); - if (flags & R_ONLINK) - { - add->argv.push_back("-cloning"); - add->argv.push_back("-net"); - add->argv.push_back(net.to_string()); - add->argv.push_back("-netmask"); - add->argv.push_back(netmask.to_string()); - add->argv.push_back("-interface"); - add->argv.push_back(iface); - } - else - { - add->argv.push_back("-net"); - add->argv.push_back(net.to_string()); - add->argv.push_back("-netmask"); - add->argv.push_back(netmask.to_string()); - if (flags & R_REJECT) - add->argv.push_back("-reject"); - if (flags & R_BLACKHOLE) - add->argv.push_back("-blackhole"); - if (!iface.empty()) - { - if (flags & R_IFACE) - { - add->argv.push_back("-iface"); - add->argv.push_back(iface); - } - } - add->argv.push_back(gateway_str); - } - create = add; - - // for the destroy command, copy the add command but replace "add" with "delete" - Command::Ptr del(add->copy()); - del->argv[1] = "delete"; - destroy = del; - } - } - - static void add_del_route(const std::string& addr_str, - const int prefix_len, - const std::string& gateway_str, - const std::string& iface, - const unsigned int flags, - ActionList& create, - ActionList& destroy) - { - Action::Ptr c, d; - add_del_route(addr_str, prefix_len, gateway_str, iface, flags, c, d); - create.add(c); - destroy.add(d); - } - - static void tun_config(const std::string& iface_name, - const TunBuilderCapture& pull, - ActionList& create, - ActionList& destroy, - std::ostream& os) - { - // get default gateway - MacGWInfo gw; - - // set local4 and local6 to point to IPv4/6 route configurations - const TunBuilderCapture::RouteAddress* local4 = nullptr; - const TunBuilderCapture::RouteAddress* local6 = nullptr; - if (pull.tunnel_address_index_ipv4 >= 0) - local4 = &pull.tunnel_addresses[pull.tunnel_address_index_ipv4]; - if (pull.tunnel_address_index_ipv6 >= 0) - local6 = &pull.tunnel_addresses[pull.tunnel_address_index_ipv6]; - - // Interface down - Command::Ptr iface_down(new Command); - iface_down->argv.push_back("/sbin/ifconfig"); - iface_down->argv.push_back(iface_name); - iface_down->argv.push_back("down"); - create.add(iface_down); - - // Set IPv4 Interface - if (local4) - { - // Process ifconfig - const IPv4::Addr netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length); - { - Command::Ptr cmd(new Command); - cmd->argv.push_back("/sbin/ifconfig"); - cmd->argv.push_back(iface_name); - cmd->argv.push_back(local4->address); - cmd->argv.push_back(local4->gateway); - cmd->argv.push_back("netmask"); - cmd->argv.push_back(netmask.to_string()); - cmd->argv.push_back("mtu"); - cmd->argv.push_back(to_string(pull.mtu)); - cmd->argv.push_back("up"); - create.add(cmd); - } - add_del_route(local4->address, local4->prefix_length, local4->address, iface_name, 0, create, destroy); - } - - // Set IPv6 Interface - if (local6 && !pull.block_ipv6) - { - { - Command::Ptr cmd(new Command); - cmd->argv.push_back("/sbin/ifconfig"); - cmd->argv.push_back(iface_name); - cmd->argv.push_back("inet6"); - cmd->argv.push_back(local6->address + '/' + to_string(local6->prefix_length)); - cmd->argv.push_back("up"); - create.add(cmd); - } - add_del_route(local6->address, local6->prefix_length, "", iface_name, R_IPv6|R_IFACE, create, destroy); - } - - // Process Routes - { - for (std::vector<TunBuilderCapture::Route>::const_iterator i = pull.add_routes.begin(); i != pull.add_routes.end(); ++i) - { - const TunBuilderCapture::Route& route = *i; - if (route.ipv6) - { - if (!pull.block_ipv6) - add_del_route(route.address, route.prefix_length, local6->gateway, iface_name, R_IPv6|R_IFACE, create, destroy); - } - else - { - if (local4 && !local4->gateway.empty()) - add_del_route(route.address, route.prefix_length, local4->gateway, iface_name, 0, create, destroy); - else - os << "ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway" << std::endl; - } - } - } - - // Process exclude routes - if (!pull.exclude_routes.empty()) - { - for (std::vector<TunBuilderCapture::Route>::const_iterator i = pull.exclude_routes.begin(); i != pull.exclude_routes.end(); ++i) - { - const TunBuilderCapture::Route& route = *i; - if (route.ipv6) - { - if (!pull.block_ipv6) - { - if (gw.v6.defined()) - add_del_route(route.address, route.prefix_length, gw.v6.router.to_string(), gw.v6.iface, R_IPv6|R_IFACE_HINT, create, destroy); - else - os << "NOTE: cannot determine gateway for exclude IPv6 routes" << std::endl; - } - } - else - { - if (gw.v4.defined()) - add_del_route(route.address, route.prefix_length, gw.v4.router.to_string(), gw.v4.iface, 0, create, destroy); - else - os << "NOTE: cannot determine gateway for exclude IPv4 routes" << std::endl; - } - } - } - - // Process IPv4 redirect-gateway - if (pull.reroute_gw.ipv4) - { - // add server bypass route - if (gw.v4.defined()) - { - if (!pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL)) - { - Action::Ptr c, d; - add_del_route(pull.remote_address.address, 32, gw.v4.router.to_string(), gw.v4.iface, 0, c, d); - create.add(c); - destroy.add(d); - //add_del_route(gw.v4.router.to_string(), 32, "", gw.v4.iface, R_ONLINK, create, destroy); // fixme -- needed for block-local - } - } - else - os << "ERROR: cannot detect IPv4 default gateway" << std::endl; - - if (!(pull.reroute_gw.flags & RGWFlags::EmulateExcludeRoutes)) - { - add_del_route("0.0.0.0", 1, local4->gateway, iface_name, 0, create, destroy); - add_del_route("128.0.0.0", 1, local4->gateway, iface_name, 0, create, destroy); - } - } - - // Process IPv6 redirect-gateway - if (pull.reroute_gw.ipv6 && !pull.block_ipv6) - { - // add server bypass route - if (gw.v6.defined()) - { - if (pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL)) - { - Action::Ptr c, d; - add_del_route(pull.remote_address.address, 128, gw.v6.router.to_string(), gw.v6.iface, R_IPv6|R_IFACE_HINT, c, d); - create.add(c); - destroy.add(d); - //add_del_route(gw.v6.router.to_string(), 128, "", gw.v6.iface, R_IPv6|R_ONLINK, create, destroy); // fixme -- needed for block-local - } - } - else - os << "ERROR: cannot detect IPv6 default gateway" << std::endl; - - if (!(pull.reroute_gw.flags & RGWFlags::EmulateExcludeRoutes)) - { - add_del_route("0000::", 1, local6->gateway, iface_name, R_IPv6|R_IFACE, create, destroy); - add_del_route("8000::", 1, local6->gateway, iface_name, R_IPv6|R_IFACE, create, destroy); - } - } - - // Process block-ipv6 - if (pull.block_ipv6) - { - add_del_route("2000::", 4, "::1", "lo0", R_IPv6|R_REJECT|R_IFACE_HINT, create, destroy); - add_del_route("3000::", 4, "::1", "lo0", R_IPv6|R_REJECT|R_IFACE_HINT, create, destroy); - add_del_route("fc00::", 7, "::1", "lo0", R_IPv6|R_REJECT|R_IFACE_HINT, create, destroy); - } - - // Interface down - destroy.add(iface_down); - - // configure DNS - { - MacDNS::Config::Ptr dns(new MacDNS::Config(pull)); - MacDNSWatchdog::add_actions(dns, - MacDNSWatchdog::FLUSH_RECONFIG -#ifdef ENABLE_DNS_WATCHDOG - | MacDNSWatchdog::SYNCHRONOUS - | MacDNSWatchdog::ENABLE_WATCHDOG -#endif - , - create, - destroy); - } - - if (pull.proxy_auto_config_url.defined()) - ProxySettings::add_actions<MacProxySettings>(pull, create, destroy); - } - - ActionList::Ptr remove_cmds; - - public: - static void add_bypass_route(const std::string& route, - bool ipv6, - ActionList& add_cmds, - ActionList& remove_cmds_bypass_gw) - { - MacGWInfo gw; - - if (!ipv6) - { - if (gw.v4.defined()) - add_del_route(route, 32, gw.v4.router.to_string(), gw.v4.iface, 0, add_cmds, remove_cmds_bypass_gw); - } - else - { - if (gw.v6.defined()) - add_del_route(route, 128, gw.v6.router.to_string(), gw.v6.iface, R_IPv6|R_IFACE_HINT, add_cmds, remove_cmds_bypass_gw); - } - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/dsdict.hpp b/Sources/OpenVPN3/openvpn/tun/mac/dsdict.hpp deleted file mode 100644 index dbfb5a5..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/dsdict.hpp +++ /dev/null @@ -1,184 +0,0 @@ -// 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-2020 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 - -namespace openvpn { - class DSDict { - public: - OPENVPN_EXCEPTION(dsdict_error); - - DSDict(CF::DynamicStore& sc_arg, const std::string& sname_arg, const std::string& dskey_arg) - : sc(sc_arg), - sname(sname_arg), - dskey(dskey_arg), - dict(CF::DynamicStoreCopyDict(sc_arg, dskey)) { } - - bool dirty() const - { - return mod.defined() ? !CFEqual(dict(), mod()) : false; - } - - bool push_to_store() - { - if (dirty()) - { - const CF::String keystr = CF::string(dskey); - if (SCDynamicStoreSetValue(sc(), keystr(), mod())) - { - OPENVPN_LOG("DSDict: updated " << dskey); - return true; - } - else - OPENVPN_LOG("DSDict: ERROR updating " << dskey); - } - return false; - } - - bool remove_from_store() - { - if (dirty()) - throw dsdict_error("internal error: remove_from_store called on modified dict"); - const CF::String keystr = CF::string(dskey); - if (SCDynamicStoreRemoveValue(sc(), keystr())) - { - OPENVPN_LOG("DSDict: removed " << dskey); - return true; - } - else - { - OPENVPN_LOG("DSDict: ERROR removing " << dskey); - return false; - } - } - - void will_modify() - { - if (!mod.defined()) - mod = CF::mutable_dict_copy(dict); - } - - void mod_reset() - { - mod = CF::mutable_dict(); - } - - void backup_orig(const std::string& key, const bool wipe_orig=true) - { - const CF::String k = CF::string(key); - const CF::String orig = orig_key(key); - if (!CFDictionaryContainsKey(dict(), orig())) - { - const CF::String delval = delete_value(); - CFTypeRef v = CFDictionaryGetValue(dict(), k()); - if (!v) - v = delval(); - will_modify(); - CFDictionarySetValue(mod(), orig(), v); - } - if (wipe_orig) - { - will_modify(); - CFDictionaryRemoveValue(mod(), k()); - } - } - - void restore_orig() - { - const CFIndex size = CFDictionaryGetCount(dict()); - std::unique_ptr<const void *[]> keys(new const void *[size]); - std::unique_ptr<const void *[]> values(new const void *[size]); - CFDictionaryGetKeysAndValues(dict(), keys.get(), values.get()); - const CF::String orig_prefix = orig_key(""); - const CFIndex orig_prefix_len = CFStringGetLength(orig_prefix()); - const CF::String delval = delete_value(); - for (CFIndex i = 0; i < size; ++i) - { - const CF::String key = CF::string_cast(keys[i]); - if (CFStringHasPrefix(key(), orig_prefix())) - { - const CFIndex key_len = CFStringGetLength(key()); - if (key_len > orig_prefix_len) - { - const CFRange r = CFRangeMake(orig_prefix_len, key_len - orig_prefix_len); - const CF::String k(CFStringCreateWithSubstring(kCFAllocatorDefault, key(), r)); - const CFTypeRef v = values[i]; - const CF::String vstr = CF::string_cast(v); - will_modify(); - if (vstr.defined() && CFStringCompare(vstr(), delval(), 0) == kCFCompareEqualTo) - CFDictionaryRemoveValue(mod(), k()); - else - CFDictionaryReplaceValue(mod(), k(), v); - CFDictionaryRemoveValue(mod(), key()); - } - } - } - } - - std::string to_string() const - { - std::ostringstream os; - os << "*** DSDict " << dskey << std::endl; - std::string orig = CF::description(dict()); - string::trim_crlf(orig); - os << "ORIG " << orig << std::endl; - if (dirty()) - { - std::string modstr = CF::description(mod()); - string::trim_crlf(modstr); - os << "MODIFIED " << modstr << std::endl; - } - return os.str(); - } - - static CF::DynamicStore ds_create(const std::string& sname) - { - CF::String sn = CF::string(sname); - return CF::DynamicStore(SCDynamicStoreCreate(kCFAllocatorDefault, sn(), nullptr, nullptr)); - } - - static bool signal_network_reconfiguration(const std::string& sname) - { - const char *key = "Setup:/Network/Global/IPv4"; - CF::DynamicStore sc = ds_create(sname); - const CF::String cfkey = CF::string(key); - OPENVPN_LOG("DSDict: SCDynamicStoreNotifyValue " << key); - return bool(SCDynamicStoreNotifyValue(sc(), cfkey())); - } - - CF::DynamicStore sc; - const std::string sname; - const std::string dskey; - const CF::Dict dict; - CF::MutableDict mod; - - private: - CF::String orig_key(const std::string& key) const - { - return CF::string(sname + "Orig" + key); - } - - CF::String delete_value() const - { - return CF::string(sname + "DeleteValue"); - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/tun/mac/gwv4.hpp b/Sources/OpenVPN3/openvpn/tun/mac/gwv4.hpp deleted file mode 100644 index c8be0cc..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/gwv4.hpp +++ /dev/null @@ -1,282 +0,0 @@ -// 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-2020 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/>. - -// Get IPv4 gateway info on Mac OS X. - -#ifndef OPENVPN_TUN_MAC_GWV4_H -#define OPENVPN_TUN_MAC_GWV4_H - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include <net/route.h> -#include <net/if.h> -#include <net/if_dl.h> - -#include <cstring> -#include <string> -#include <sstream> -#include <algorithm> // for std::max -#include <cstdint> // for std::uint32_t -#include <memory> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/addr/addrpair.hpp> -#include <openvpn/addr/macaddr.hpp> - -namespace openvpn { - class MacGatewayInfoV4 - { - struct rtmsg { - struct rt_msghdr m_rtm; - char m_space[512]; - }; - -# define OPENVPN_ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(std::uint32_t) - 1))) : sizeof(std::uint32_t)) - -# define OPENVPN_NEXTADDR(w, u) \ - if (rtm_addrs & (w)) { \ - l = OPENVPN_ROUNDUP(u.sa_len); \ - std::memmove(cp, &(u), l); \ - cp += l; \ - } - -# define OPENVPN_ADVANCE(x, n) \ - (x += OPENVPN_ROUNDUP((n)->sa_len)) - - public: - OPENVPN_EXCEPTION(route_gateway_error); - - enum { - ADDR_DEFINED = (1<<0), /* set if gateway.addr defined */ - NETMASK_DEFINED = (1<<1), /* set if gateway.netmask defined */ - HWADDR_DEFINED = (1<<2), /* set if hwaddr is defined */ - IFACE_DEFINED = (1<<3), /* set if iface is defined */ - }; - - MacGatewayInfoV4() - : flags_(0) - { - struct rtmsg m_rtmsg; - ScopedFD sockfd; - int seq, l, pid, rtm_addrs, i; - struct sockaddr so_dst, so_mask; - char *cp = m_rtmsg.m_space; - struct sockaddr *gate = nullptr, *ifp = nullptr, *sa; - struct rt_msghdr *rtm_aux; - - /* setup data to send to routing socket */ - pid = ::getpid(); - seq = 0; - rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP; - - std::memset(&m_rtmsg, 0, sizeof(m_rtmsg)); - std::memset(&so_dst, 0, sizeof(so_dst)); - std::memset(&so_mask, 0, sizeof(so_mask)); - std::memset(&m_rtmsg.m_rtm, 0, sizeof(struct rt_msghdr)); - - m_rtmsg.m_rtm.rtm_type = RTM_GET; - m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; - m_rtmsg.m_rtm.rtm_version = RTM_VERSION; - m_rtmsg.m_rtm.rtm_seq = ++seq; - m_rtmsg.m_rtm.rtm_addrs = rtm_addrs; - - so_dst.sa_family = AF_INET; - so_dst.sa_len = sizeof(struct sockaddr_in); - so_mask.sa_family = AF_INET; - so_mask.sa_len = sizeof(struct sockaddr_in); - - OPENVPN_NEXTADDR(RTA_DST, so_dst); - OPENVPN_NEXTADDR(RTA_NETMASK, so_mask); - - m_rtmsg.m_rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; - - /* transact with routing socket */ - sockfd.reset(socket(PF_ROUTE, SOCK_RAW, 0)); - if (!sockfd.defined()) - throw route_gateway_error("GDG: socket #1 failed"); - if (::write(sockfd(), (char *)&m_rtmsg, l) < 0) - throw route_gateway_error("GDG: problem writing to routing socket"); - do { - l = ::read(sockfd(), (char *)&m_rtmsg, sizeof(m_rtmsg)); - } while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid)); - sockfd.close(); - - /* extract return data from routing socket */ - rtm_aux = &m_rtmsg.m_rtm; - cp = ((char *)(rtm_aux + 1)); - if (rtm_aux->rtm_addrs) - { - for (i = 1; i; i <<= 1) - { - if (i & rtm_aux->rtm_addrs) - { - sa = (struct sockaddr *)cp; - if (i == RTA_GATEWAY ) - gate = sa; - else if (i == RTA_IFP) - ifp = sa; - OPENVPN_ADVANCE(cp, sa); - } - } - } - else - return; - - /* get gateway addr and interface name */ - if (gate != nullptr ) - { - /* get default gateway addr */ - gateway_.addr.reset_ipv4_from_uint32(ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr)); - if (!gateway_.addr.unspecified()) - flags_ |= ADDR_DEFINED; - - if (ifp) - { - /* get interface name */ - const struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp; - const size_t len = adl->sdl_nlen; - if (len && len < sizeof(iface_)) - { - std::memcpy (iface_, adl->sdl_data, len); - iface_[len] = '\0'; - flags_ |= IFACE_DEFINED; - } - } - } - - /* get netmask of interface that owns default gateway */ - if (flags_ & IFACE_DEFINED) { - struct ifreq ifr; - - sockfd.reset(socket(AF_INET, SOCK_DGRAM, 0)); - if (!sockfd.defined()) - throw route_gateway_error("GDG: socket #2 failed"); - - std::memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_addr.sa_family = AF_INET; - string::strncpynt(ifr.ifr_name, iface_, IFNAMSIZ); - - if (::ioctl(sockfd(), SIOCGIFNETMASK, (char *)&ifr) < 0) - throw route_gateway_error("GDG: ioctl #1 failed"); - sockfd.close(); - - gateway_.netmask.reset_ipv4_from_uint32(ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr)); - flags_ |= NETMASK_DEFINED; - } - - /* try to read MAC addr associated with interface that owns default gateway */ - if (flags_ & IFACE_DEFINED) - { - struct ifconf ifc; - struct ifreq *ifr; - const int bufsize = 4096; - - std::unique_ptr<char[]> buffer(new char[bufsize]); - std::memset(buffer.get(), 0, bufsize); - sockfd.reset(socket(AF_INET, SOCK_DGRAM, 0)); - if (!sockfd.defined()) - throw route_gateway_error("GDG: socket #3 failed"); - - ifc.ifc_len = bufsize; - ifc.ifc_buf = buffer.get(); - - if (::ioctl(sockfd(), SIOCGIFCONF, (char *)&ifc) < 0) - throw route_gateway_error("GDG: ioctl #2 failed"); - sockfd.close(); - - for (cp = buffer.get(); cp <= buffer.get() + ifc.ifc_len - sizeof(struct ifreq); ) - { - ifr = (struct ifreq *)cp; - const size_t len = sizeof(ifr->ifr_name) + std::max(sizeof(ifr->ifr_addr), size_t(ifr->ifr_addr.sa_len)); - if (!ifr->ifr_addr.sa_family) - break; - if (!::strncmp(ifr->ifr_name, iface_, IFNAMSIZ)) - { - if (ifr->ifr_addr.sa_family == AF_LINK) - { - struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr; - hwaddr_.reset((const unsigned char *)LLADDR(sdl)); - flags_ |= HWADDR_DEFINED; - } - } - cp += len; - } - } - } -# undef OPENVPN_ROUNDUP -# undef OPENVPN_NEXTADDR -# undef OPENVPN_ADVANCE - - std::string info() const - { - std::ostringstream os; - os << "GATEWAY"; - if (flags_ & ADDR_DEFINED) - { - os << " ADDR=" << gateway_.addr; - if (flags_ & NETMASK_DEFINED) - { - os << '/' << gateway_.netmask; - } - } - if (flags_ & IFACE_DEFINED) - os << " IFACE=" << iface_; - if (flags_ & HWADDR_DEFINED) - os << " HWADDR=" << hwaddr_; - return os.str(); - } - - unsigned int flags() const { return flags_; } - const IP::Addr& gateway_addr() const { return gateway_.addr; } - std::string gateway_addr_str() const { return gateway_addr().to_string(); } - const IP::Addr& gateway_netmask() const { return gateway_.netmask; } - std::string gateway_netmask_str() const { return gateway_netmask().to_string(); } - std::string iface() const { return iface_; } - const MACAddr& hwaddr() const { return hwaddr_; } - - bool iface_addr_defined() const - { - return (flags_ & (ADDR_DEFINED|IFACE_DEFINED)) == (ADDR_DEFINED|IFACE_DEFINED); - } - - bool hwaddr_defined() const - { - return flags_ & HWADDR_DEFINED; - } - - private: - unsigned int flags_; - IP::AddrMaskPair gateway_; - char iface_[16]; - MACAddr hwaddr_; - }; - -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/macdns.hpp b/Sources/OpenVPN3/openvpn/tun/mac/macdns.hpp deleted file mode 100644 index 8b26789..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/macdns.hpp +++ /dev/null @@ -1,374 +0,0 @@ -// 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-2020 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/>. - -// DNS utilities for Mac OS X. - -#ifndef OPENVPN_TUN_MAC_MACDNS_H -#define OPENVPN_TUN_MAC_MACDNS_H - -#include <string> -#include <sstream> -#include <memory> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/process.hpp> -#include <openvpn/apple/macver.hpp> -#include <openvpn/apple/scdynstore.hpp> -#include <openvpn/apple/cf/cfhelper.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/tun/mac/dsdict.hpp> - -namespace openvpn { - class MacDNS : public RC<thread_unsafe_refcount> - { - class Info; - - public: - typedef RCPtr<MacDNS> Ptr; - - OPENVPN_EXCEPTION(macdns_error); - - class Config : public RC<thread_safe_refcount> - { - public: - typedef RCPtr<Config> Ptr; - - Config() - { - } - - Config(const TunBuilderCapture& settings) - : dns_servers(get_dns_servers(settings)), - search_domains(get_search_domains(settings)), - adapter_domain_suffix(settings.adapter_domain_suffix) - { - // We redirect DNS if either of the following is true: - // 1. redirect-gateway (IPv4) is pushed, or - // 2. DNS servers are pushed but no search domains are pushed - redirect_dns = settings.reroute_gw.ipv4 || (CF::array_len(dns_servers) && !CF::array_len(search_domains)); - } - - std::string to_string() const - { - std::ostringstream os; - os << "RD=" << redirect_dns; - os << " SO=" << search_order; - os << " DNS=" << CF::array_to_string(dns_servers); - os << " DOM=" << CF::array_to_string(search_domains); - os << " ADS=" << adapter_domain_suffix; - return os.str(); - } - - bool redirect_dns = false; - int search_order = 5000; - CF::Array dns_servers; - CF::Array search_domains; - std::string adapter_domain_suffix; - - private: - static CF::Array get_dns_servers(const TunBuilderCapture& settings) - { - CF::MutableArray ret(CF::mutable_array()); - for (std::vector<TunBuilderCapture::DNSServer>::const_iterator i = settings.dns_servers.begin(); - i != settings.dns_servers.end(); ++i) - { - const TunBuilderCapture::DNSServer& ds = *i; - CF::array_append_str(ret, ds.address); - } - return CF::const_array(ret); - } - - static CF::Array get_search_domains(const TunBuilderCapture& settings) - { - CF::MutableArray ret(CF::mutable_array()); - for (std::vector<TunBuilderCapture::SearchDomain>::const_iterator i = settings.search_domains.begin(); - i != settings.search_domains.end(); ++i) - { - const TunBuilderCapture::SearchDomain& sd = *i; - CF::array_append_str(ret, sd.domain); - } - return CF::const_array(ret); - } - }; - - MacDNS(const std::string& sname_arg) - : sname(sname_arg) - { - } - - void flush_cache() - { - const int v = ver.major(); - if (v < Mac::Version::OSX_10_6) - OPENVPN_LOG("MacDNS: Error: No support for Mac OS X versions earlier than 10.6"); - if (v == Mac::Version::OSX_10_6 || v >= Mac::Version::OSX_10_9) - { - Argv args; - args.push_back("/usr/bin/dscacheutil"); - args.push_back("-flushcache"); - OPENVPN_LOG(args.to_string()); - system_cmd(args); - } - if (v >= Mac::Version::OSX_10_7) - { - Argv args; - args.push_back("/usr/bin/killall"); - args.push_back("-HUP"); - args.push_back("mDNSResponder"); - OPENVPN_LOG(args.to_string()); - system_cmd(args); - } - } - - bool signal_network_reconfiguration() - { - return DSDict::signal_network_reconfiguration(sname); - } - - bool setdns(const Config& config) - { - bool mod = false; - - try { - CF::DynamicStore sc = ds_create(); - Info::Ptr info(new Info(sc, sname)); - - // cleanup settings applied to previous interface - interface_change_cleanup(info.get()); - - if (config.redirect_dns) - { - // redirect all DNS - info->dns.will_modify(); - - // set DNS servers - if (CF::array_len(config.dns_servers)) - { - info->dns.backup_orig("ServerAddresses"); - CF::dict_set_obj(info->dns.mod, "ServerAddresses", config.dns_servers()); - } - - // set search domains - info->dns.backup_orig("SearchDomains"); - CF::MutableArray search_domains(CF::mutable_array()); - - // add adapter_domain_suffix to SearchDomains for domain autocompletion - if (config.adapter_domain_suffix.length() > 0) - CF::array_append_str(search_domains, config.adapter_domain_suffix); - - if (CF::array_len(search_domains)) - CF::dict_set_obj(info->dns.mod, "SearchDomains", search_domains()); - - // set search order - info->dns.backup_orig("SearchOrder"); - CF::dict_set_int(info->dns.mod, "SearchOrder", config.search_order); - - // push it - mod |= info->dns.push_to_store(); - } - else - { - // split-DNS - resolve only specific domains - info->ovpn.mod_reset(); - if (CF::array_len(config.dns_servers) && CF::array_len(config.search_domains)) - { - // set DNS servers - CF::dict_set_obj(info->ovpn.mod, "ServerAddresses", config.dns_servers()); - - // DNS will be used only for those domains - CF::dict_set_obj(info->ovpn.mod, "SupplementalMatchDomains", config.search_domains()); - - // do not use those domains in autocompletion - CF::dict_set_int(info->ovpn.mod, "SupplementalMatchDomainsNoSearch", 1); - } - - // in case of split-DNS macOS uses domain suffix of network adapter, - // not the one provided by VPN (which we put to SearchDomains) - - // push it - mod |= info->ovpn.push_to_store(); - } - - if (mod) - { - // As a backup, save PrimaryService in private dict (if network goes down while - // we are set, we can lose info about PrimaryService in State:/Network/Global/IPv4 - // and be unable to reset ourselves). - const CFTypeRef ps = CF::dict_get_obj(info->ipv4.dict, "PrimaryService"); - if (ps) - { - info->info.mod_reset(); - CF::dict_set_obj(info->info.mod, "PrimaryService", ps); - info->info.push_to_store(); - } - } - - prev = info; - if (mod) - OPENVPN_LOG("MacDNS: SETDNS " << ver.to_string() << std::endl << info->to_string()); - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacDNS: setdns exception: " << e.what()); - } - return mod; - } - - bool resetdns() - { - bool mod = false; - try { - CF::DynamicStore sc = ds_create(); - Info::Ptr info(new Info(sc, sname)); - - // cleanup settings applied to previous interface - interface_change_cleanup(info.get()); - - // undo primary dns changes - mod |= reset_primary_dns(info.get()); - - // undo non-redirect-gateway changes - if (CF::dict_len(info->ovpn.dict)) - mod |= info->ovpn.remove_from_store(); - - // remove private info dict - if (CF::dict_len(info->info.dict)) - mod |= info->info.remove_from_store(); - - if (mod) - OPENVPN_LOG("MacDNS: RESETDNS " << ver.to_string() << std::endl << info->to_string()); - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacDNS: resetdns exception: " << e.what()); - } - return mod; - } - - std::string to_string() const - { - CF::DynamicStore sc = ds_create(); - Info::Ptr info(new Info(sc, sname)); - return info->to_string(); - } - - CF::Array dskey_array() const - { - CF::DynamicStore sc = ds_create(); - Info::Ptr info(new Info(sc, sname)); - CF::MutableArray ret(CF::mutable_array()); - CF::array_append_str(ret, info->ipv4.dskey); - CF::array_append_str(ret, info->info.dskey); - CF::array_append_str(ret, info->ovpn.dskey); - CF::array_append_str(ret, info->dns.dskey); - return CF::const_array(ret); - } - - private: - void interface_change_cleanup(Info* info) - { - if (info->interface_change(prev.get())) - { - reset_primary_dns(prev.get()); - prev.reset(); - } - } - - bool reset_primary_dns(Info* info) - { - bool mod = false; - if (info) - { -#if 1 - // Restore previous DNS settings. - // Recommended for production. - info->dns.will_modify(); - info->dns.restore_orig(); - mod |= info->dns.push_to_store(); -#else - // Wipe DNS settings without restore. - // This can potentially wipe static IP/DNS settings. - info->dns.mod_reset(); - mod |= info->dns.push_to_store(); -#endif - } - return mod; - } - - class Info : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Info> Ptr; - - Info(CF::DynamicStore& sc, const std::string& sname) - : ipv4(sc, sname, "State:/Network/Global/IPv4"), - info(sc, sname, "State:/Network/Service/" + sname + "/Info"), - ovpn(sc, sname, "State:/Network/Service/" + sname + "/DNS"), - dns(sc, sname, primary_dns(ipv4.dict, info.dict)) - { - } - - std::string to_string() const - { - std::ostringstream os; - os << ipv4.to_string(); - os << info.to_string(); - os << ovpn.to_string(); - os << dns.to_string(); - return os.str(); - } - - bool interface_change(Info* other) const - { - return other && dns.dskey != other->dns.dskey; - } - - DSDict ipv4; - DSDict info; // we may modify - DSDict ovpn; // we may modify - DSDict dns; // we may modify - - private: - static std::string primary_dns(const CF::Dict& ipv4, const CF::Dict& info) - { - std::string serv = CF::dict_get_str(ipv4, "PrimaryService"); - if (serv.empty()) - serv = CF::dict_get_str(info, "PrimaryService"); - if (serv.empty()) - throw macdns_error("no primary service"); - return "Setup:/Network/Service/" + serv + "/DNS"; - } - }; - - CF::DynamicStore ds_create() const - { - return DSDict::ds_create(sname); - } - - const std::string sname; - Mac::Version ver; - Info::Ptr prev; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/macdns_watchdog.hpp b/Sources/OpenVPN3/openvpn/tun/mac/macdns_watchdog.hpp deleted file mode 100644 index 38b150d..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/macdns_watchdog.hpp +++ /dev/null @@ -1,291 +0,0 @@ -// 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-2020 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/>. - -// DNS utilities for Mac - -#ifndef OPENVPN_TUN_MAC_MACDNS_WATCHDOG_H -#define OPENVPN_TUN_MAC_MACDNS_WATCHDOG_H - -#include <thread> -#include <mutex> - -#include <openvpn/log/logthread.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/apple/cf/cftimer.hpp> -#include <openvpn/apple/cf/cfrunloop.hpp> -#include <openvpn/tun/mac/macdns.hpp> - -namespace openvpn { - OPENVPN_EXCEPTION(macdns_watchdog_error); - - class MacDNSWatchdog : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<MacDNSWatchdog> Ptr; - - // flags - enum { - ENABLE_WATCHDOG = (1<<0), - SYNCHRONOUS = (1<<1), - FLUSH_RECONFIG = (1<<2), - }; - - class DNSAction : public Action - { - public: - typedef RCPtr<DNSAction> Ptr; - - DNSAction(const MacDNSWatchdog::Ptr& parent_arg, - const MacDNS::Config::Ptr& config_arg, - const unsigned int flags_arg) - : parent(parent_arg), - config(config_arg), - flags(flags_arg) - { - } - - virtual void execute(std::ostream& os) - { - os << to_string() << std::endl; - if (parent) - parent->setdns(config, flags); - } - - virtual std::string to_string() const - { - std::ostringstream os; - os << "MacDNSAction: FLAGS="; - if (flags & ENABLE_WATCHDOG) - os << 'E'; - if (flags & SYNCHRONOUS) - os << 'S'; - if (flags & FLUSH_RECONFIG) - os << 'F'; - if (config) - os << ' ' << config->to_string(); - return os.str(); - } - - private: - const MacDNSWatchdog::Ptr parent; - const MacDNS::Config::Ptr config; - const unsigned int flags; - }; - - MacDNSWatchdog() - : macdns(new MacDNS("OpenVPNConnect")), - thread(nullptr) - { - } - - virtual ~MacDNSWatchdog() - { - stop_thread(); - } - - static void add_actions(const MacDNS::Config::Ptr& dns, - const unsigned int flags, - ActionList& create, - ActionList& destroy) - { - MacDNSWatchdog::Ptr watchdog(new MacDNSWatchdog); - MacDNS::Config::Ptr dns_remove; - DNSAction::Ptr create_action(new DNSAction(watchdog, dns, flags)); - DNSAction::Ptr destroy_action(new DNSAction(watchdog, dns_remove, flags)); - create.add(create_action); - destroy.add(destroy_action); - } - - private: - bool setdns(const MacDNS::Config::Ptr& config, const unsigned int flags) - { - bool mod = false; - if (config) - { - if ((flags & SYNCHRONOUS) || !(flags & ENABLE_WATCHDOG)) - stop_thread(); - config_ = config; - if (flags & ENABLE_WATCHDOG) - { - if (!thread) - { - mod = macdns->setdns(*config_); - thread = new std::thread(&MacDNSWatchdog::thread_func, this); - } - else - { - if (runloop.defined()) - schedule_push_timer(0); - else - OPENVPN_LOG("MacDNSWatchdog::setdns: runloop undefined"); - } - } - else - { - mod = macdns->setdns(*config_); - } - } - else - { - stop_thread(); - config_.reset(); - mod = macdns->resetdns(); - } - if (mod && (flags & FLUSH_RECONFIG)) - { - macdns->flush_cache(); - macdns->signal_network_reconfiguration(); - } - return mod; - } - - std::string to_string() const - { - const MacDNS::Config::Ptr config(config_); - if (config) - return config->to_string(); - else - return std::string("UNDEF"); - } - - void stop_thread() - { - if (thread) - { - if (runloop.defined()) - CFRunLoopStop(runloop()); - thread->join(); - delete thread; - thread = nullptr; - } - } - - // All methods below this point called in the context of watchdog thread - // except for schedule_push_timer which may be called from parent thread - // as well. - void thread_func() - { - runloop.reset(CFRunLoopGetCurrent(), CF::GET); - Log::Context logctx(logwrap); - - try { - SCDynamicStoreContext context = {0, this, nullptr, nullptr, nullptr}; - CF::DynamicStore ds(SCDynamicStoreCreate(kCFAllocatorDefault, - CFSTR("OpenVPN_MacDNSWatchdog"), - callback_static, - &context)); - if (!ds.defined()) - throw macdns_watchdog_error("SCDynamicStoreCreate"); - const CF::Array watched_keys(macdns->dskey_array()); - if (!watched_keys.defined()) - throw macdns_watchdog_error("watched_keys is undefined"); - if (!SCDynamicStoreSetNotificationKeys(ds(), - watched_keys(), - nullptr)) - throw macdns_watchdog_error("SCDynamicStoreSetNotificationKeys failed"); - CF::RunLoopSource rls(SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, ds(), 0)); - if (!rls.defined()) - throw macdns_watchdog_error("SCDynamicStoreCreateRunLoopSource failed"); - CFRunLoopAddSource(CFRunLoopGetCurrent(), rls(), kCFRunLoopDefaultMode); - - // process event loop until CFRunLoopStop is called from parent thread - CFRunLoopRun(); - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacDNSWatchdog::thread_func exception: " << e.what()); - } - cancel_push_timer(); - } - - static void callback_static(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg) - { - MacDNSWatchdog *self = (MacDNSWatchdog *)arg; - self->callback(store, changedKeys); - } - - void callback(SCDynamicStoreRef store, CFArrayRef changedKeys) - { - // DNS Watchdog delay from the time that change is detected - // to when we forcibly revert it (seconds). - schedule_push_timer(1); - } - - void schedule_push_timer(const int seconds) - { - std::lock_guard<std::mutex> lock(push_timer_lock); - CFRunLoopTimerContext context = { 0, this, nullptr, nullptr, nullptr }; - cancel_push_timer_nolock(); - push_timer.reset(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + seconds, 0, 0, 0, push_timer_callback_static, &context)); - if (push_timer.defined()) - CFRunLoopAddTimer(runloop(), push_timer(), kCFRunLoopCommonModes); - else - OPENVPN_LOG("MacDNSWatchdog::schedule_push_timer: failed to create timer"); - } - - void cancel_push_timer_nolock() - { - if (push_timer.defined()) - { - CFRunLoopTimerInvalidate(push_timer()); - push_timer.reset(nullptr); - } - } - - void cancel_push_timer() - { - std::lock_guard<std::mutex> lock(push_timer_lock); - cancel_push_timer_nolock(); - } - - static void push_timer_callback_static(CFRunLoopTimerRef timer, void *info) - { - MacDNSWatchdog* self = (MacDNSWatchdog*)info; - self->push_timer_callback(timer); - } - - void push_timer_callback(CFRunLoopTimerRef timer) - { - try { - // reset DNS settings after watcher detected modifications by third party - const MacDNS::Config::Ptr config(config_); - if (macdns->setdns(*config)) - OPENVPN_LOG("MacDNSWatchdog: updated DNS settings"); - } - catch (const std::exception& e) - { - OPENVPN_LOG("MacDNSWatchdog::push_timer_callback exception: " << e.what()); - } - } - - - MacDNS::Config::Ptr config_; - MacDNS::Ptr macdns; - - std::thread* thread; // watcher thread - CF::RunLoop runloop; // run loop in watcher thread - CF::Timer push_timer; // watcher thread timer - std::mutex push_timer_lock; - Log::Context::Wrapper logwrap; // used to carry forward the log context from parent thread - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/macgw.hpp b/Sources/OpenVPN3/openvpn/tun/mac/macgw.hpp deleted file mode 100644 index f9c5287..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/macgw.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// 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-2020 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_TUN_MAC_MACGW_H -#define OPENVPN_TUN_MAC_MACGW_H - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/apple/scdynstore.hpp> -#include <openvpn/apple/cf/cfhelper.hpp> - -namespace openvpn { - struct MacGWInfo - { - struct Variant - { - friend struct MacGWInfo; - public: - bool defined() const { - return !iface.empty() && router.defined(); - } - - std::string to_string() const - { - return iface + '/' + router.to_string(); - } - - std::string iface; - IP::Addr router; - - private: - Variant() {} - - Variant(const IP::Addr::Version v, const CF::DynamicStore& dstore) - { - const std::string key = std::string("State:/Network/Global/IP") + IP::Addr::version_string_static(v); - const CF::Dict d(CF::DynamicStoreCopyDict(dstore, key)); - iface = CF::dict_get_str(d, "PrimaryInterface"); - const std::string addr = CF::dict_get_str(d, "Router"); - if (!addr.empty()) - router = IP::Addr::from_string(addr, "MacGWInfo::Variant", v); - else - router.reset(); - } - }; - - MacGWInfo() - { - const CF::DynamicStore ds(SCDynamicStoreCreate(kCFAllocatorDefault, - CFSTR("MacGWInfo"), - nullptr, - nullptr)); - v4 = Variant(IP::Addr::V4, ds); - v6 = Variant(IP::Addr::V6, ds); - } - - std::string to_string() const - { - return "IPv4=" + v4.to_string() + " IPv6=" + v6.to_string(); - } - - Variant v4; - Variant v6; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/macproxy.hpp b/Sources/OpenVPN3/openvpn/tun/mac/macproxy.hpp deleted file mode 100644 index 1e64f68..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/macproxy.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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-2020 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/tun/proxy.hpp> -#include <openvpn/tun/mac/dsdict.hpp> - -namespace openvpn { - class MacProxySettings : public ProxySettings - { - public: - OPENVPN_EXCEPTION(macproxy_error); - - typedef RCPtr<MacProxySettings> Ptr; - - class Info : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<Info> Ptr; - - Info(CF::DynamicStore& sc, const std::string& sname) - : ipv4(sc, sname, "State:/Network/Global/IPv4"), - info(sc, sname, "State:/Network/Service/" + sname + "/Info"), - proxy(sc, sname, proxies(ipv4.dict, info.dict)) { } - - std::string to_string() const - { - std::ostringstream os; - os << ipv4.to_string(); - os << info.to_string(); - os << proxy.to_string(); - return os.str(); - } - - DSDict ipv4; - DSDict info; - DSDict proxy; - - private: - static std::string proxies(const CF::Dict& ipv4, const CF::Dict& info) - { - std::string serv = CF::dict_get_str(ipv4, "PrimaryService"); - if (serv.empty()) - serv = CF::dict_get_str(info, "PrimaryService"); - if (serv.empty()) - throw macproxy_error("no primary service"); - return "Setup:/Network/Service/" + serv + "/Proxies"; - } - }; - - MacProxySettings(const TunBuilderCapture::ProxyAutoConfigURL& config_arg) - : ProxySettings(config_arg) { } - - void set_proxy(bool del) override - { - if (!config.defined()) - return; - - CF::DynamicStore sc = DSDict::ds_create(sname); - Info::Ptr info(new Info(sc, sname)); - - info->proxy.will_modify(); - - if (!del) - { - info->proxy.backup_orig("ProxyAutoConfigEnable"); - CF::dict_set_int(info->proxy.mod, "ProxyAutoConfigEnable", 1); - - info->proxy.backup_orig("ProxyAutoConfigURLString"); - CF::dict_set_str(info->proxy.mod, "ProxyAutoConfigURLString", config.to_string()); - } - else - info->proxy.restore_orig(); - - info->proxy.push_to_store(); - - OPENVPN_LOG("MacProxy: set_proxy " << info->to_string()); - } - }; -} diff --git a/Sources/OpenVPN3/openvpn/tun/mac/tunutil.hpp b/Sources/OpenVPN3/openvpn/tun/mac/tunutil.hpp deleted file mode 100644 index 700f7a0..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/tunutil.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// 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-2020 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/>. - -// Tun interface utilities for Mac OS X. - -#ifndef OPENVPN_TUN_MAC_TUNUTIL_H -#define OPENVPN_TUN_MAC_TUNUTIL_H - -#include <fcntl.h> -#include <errno.h> - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/asio/asioerr.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/scoped_fd.hpp> -#include <openvpn/tun/layer.hpp> - -namespace openvpn { - namespace TunMac { - namespace Util { - OPENVPN_EXCEPTION(tun_mac_util); - - inline int tuntap_open(const Layer& layer, std::string& name) - { - for (int i = 0; i < 256; ++i) - { - const char *tuntap; - if (layer() == Layer::OSI_LAYER_3) - tuntap = "tun"; - else if (layer() == Layer::OSI_LAYER_2) - tuntap = "tap"; - else - throw tun_mac_util("unknown OSI layer"); - const std::string node_str = tuntap + to_string(i); - const std::string node_fn = "/dev/" + node_str; - - ScopedFD fd(open(node_fn.c_str(), O_RDWR)); - if (fd.defined()) - { - // got it - if (fcntl(fd(), F_SETFL, O_NONBLOCK) < 0) - throw tun_mac_util("fcntl error on " + node_fn + " : " + errinfo(errno)); - - name = node_str; - return fd.release(); - } - } - throw tun_mac_util(std::string("error opening Mac ") + layer.dev_type() + " device"); - } - - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/mac/utun.hpp b/Sources/OpenVPN3/openvpn/tun/mac/utun.hpp deleted file mode 100644 index 8d4f63d..0000000 --- a/Sources/OpenVPN3/openvpn/tun/mac/utun.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// 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-2020 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/>. -// - -// Thanks to Jonathan Levin for proof-of-concept utun code for Mac OS X. -// http://newosxbook.com/src.jl?tree=listings&file=17-15-utun.c - -// Open a utun device on Mac OS X. - -#ifndef OPENVPN_TUN_MAC_UTUN_H -#define OPENVPN_TUN_MAC_UTUN_H - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/sys_domain.h> -#include <sys/kern_control.h> -#include <net/if_utun.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <stdlib.h> - -#include <string> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/scoped_fd.hpp> - -namespace openvpn { - namespace TunMac { - namespace UTun { - OPENVPN_EXCEPTION(utun_error); - - // Open specific utun device unit and return fd. - // If the unit number is already in use, return -1. - // Throw exceptions for all other errors. - // Return the iface name in name. - inline int utun_open(std::string& name, const int unit) - { - struct sockaddr_ctl sc; - struct ctl_info ctlInfo; - - memset(&ctlInfo, 0, sizeof(ctlInfo)); - if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) - >= sizeof(ctlInfo.ctl_name)) - throw utun_error("UTUN_CONTROL_NAME too long"); - - ScopedFD fd(socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL)); - if (!fd.defined()) - throw utun_error("socket(SYSPROTO_CONTROL)"); - - if (ioctl(fd(), CTLIOCGINFO, &ctlInfo) == -1) - throw utun_error("ioctl(CTLIOCGINFO)"); - - sc.sc_id = ctlInfo.ctl_id; - sc.sc_len = sizeof(sc); - sc.sc_family = AF_SYSTEM; - sc.ss_sysaddr = AF_SYS_CONTROL; - sc.sc_unit = unit + 1; - - // If the connect is successful, a utunX device will be created, where X - // is our unit number - 1. - if (connect(fd(), (struct sockaddr *)&sc, sizeof(sc)) == -1) - return -1; - - // Get iface name of newly created utun dev. - char utunname[20]; - socklen_t utunname_len = sizeof(utunname); - if (getsockopt(fd(), SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len)) - throw utun_error("getsockopt(SYSPROTO_CONTROL)"); - name = utunname; - - return fd.release(); - } - - // Try to open an available utun device unit. - // Return the iface name in name. - inline int utun_open(std::string& name) - { - for (int unit = 0; unit < 256; ++unit) - { - const int fd = utun_open(name, unit); - if (fd >= 0) - return fd; - } - throw utun_error("cannot open available utun device"); - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/persist/tunpersist.hpp b/Sources/OpenVPN3/openvpn/tun/persist/tunpersist.hpp deleted file mode 100644 index 83d0969..0000000 --- a/Sources/OpenVPN3/openvpn/tun/persist/tunpersist.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// 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-2020 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_TUN_PERSIST_TUNPERSIST_H -#define OPENVPN_TUN_PERSIST_TUNPERSIST_H - -#include <openvpn/common/size.hpp> -#include <openvpn/tun/persist/tunwrap.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/builder/capture.hpp> - -namespace openvpn { - - // TunPersistTemplate adds persistence capabilities onto TunWrapTemplate, - // in order to implement logic for the persist-tun directive. - template <typename SCOPED_OBJ, typename STATE=TunProp::State::Ptr> - class TunPersistTemplate : public TunWrapTemplate<SCOPED_OBJ> - { - public: - typedef RCPtr<TunPersistTemplate> Ptr; - - TunPersistTemplate(const bool enable_persistence, const bool retain_obj, TunBuilderBase* tb) - : TunWrapTemplate<SCOPED_OBJ>(retain_obj), - enable_persistence_(enable_persistence), - tb_(tb), - use_persisted_tun_(false), - disconnect(false) - { - } - - // Current persisted state - const STATE& state() const - { - return state_; - } - - virtual ~TunPersistTemplate() - { - close_local(); - } - - void invalidate() - { - options_.clear(); - } - - void close() - { - close_local(); - TunWrapTemplate<SCOPED_OBJ>::close(); - } - - void set_disconnect() - { - disconnect = true; - } - - // Current persisted options - const std::string& options() - { - return options_; - } - - // Return true if we should use previously persisted - // tun socket descriptor/handle - bool use_persisted_tun(const IP::Addr server_addr, - const TunProp::Config& tun_prop, - const OptionList& opt) - { -#if OPENVPN_DEBUG_TUN_BUILDER > 0 - { - TunBuilderCapture::Ptr capture = new TunBuilderCapture(); - try { - TunProp::configure_builder(capture.get(), nullptr, nullptr, server_addr, tun_prop, opt, nullptr, true); - OPENVPN_LOG("*** TUN BUILDER CAPTURE" << std::endl << capture->to_string()); - } - catch (const std::exception& e) - { - OPENVPN_LOG("*** TUN BUILDER CAPTURE exception: " << e.what()); - } - } -#endif - - // In tun_persist mode, capture tun builder settings so we can - // compare them to previous persisted settings. - if (enable_persistence_) - { - copt_.reset(new TunBuilderCapture()); - try { - TunProp::configure_builder(copt_.get(), nullptr, nullptr, server_addr, tun_prop, opt, nullptr, true); - } - catch (const std::exception&) - { - copt_.reset(); - } - } - - // Check if previous tun session matches properties of to-be-created session - use_persisted_tun_ = (TunWrapTemplate<SCOPED_OBJ>::obj_defined() - && copt_ - && !options_.empty() - && options_ == copt_->to_string() - && (tb_ ? tb_->tun_builder_persist() : true)); - return use_persisted_tun_; - } - - // Possibly save tunnel fd/handle, state, and options. - bool persist_tun_state(const typename SCOPED_OBJ::base_type obj, - const STATE& state) - { - if (!enable_persistence_ || !use_persisted_tun_) - { - TunWrapTemplate<SCOPED_OBJ>::save_replace_sock(obj); - } - if (enable_persistence_ && copt_ && !use_persisted_tun_) - { - state_ = state; - options_ = copt_->to_string(); - return true; - } - else - return false; - } - - private: - void close_local() - { - if (tb_) - tb_->tun_builder_teardown(disconnect); - state_.reset(); - options_ = ""; - } - - const bool enable_persistence_; - TunBuilderBase * const tb_; - STATE state_; - std::string options_; - - TunBuilderCapture::Ptr copt_; - bool use_persisted_tun_; - - bool disconnect; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/persist/tunwrap.hpp b/Sources/OpenVPN3/openvpn/tun/persist/tunwrap.hpp deleted file mode 100644 index 4dba72c..0000000 --- a/Sources/OpenVPN3/openvpn/tun/persist/tunwrap.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// 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-2020 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_TUN_PERSIST_TUNWRAP_H -#define OPENVPN_TUN_PERSIST_TUNWRAP_H - -#include <openvpn/common/size.hpp> -#include <openvpn/common/destruct.hpp> - -namespace openvpn { - - // TunWrapTemplate is used client-side to store the underlying tun - // interface fd/handle. SCOPED_OBJ is generally a ScopedFD (unix) or a - // ScopedHANDLE (Windows). It can also be a ScopedAsioStream. - template <typename SCOPED_OBJ> - class TunWrapTemplate : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TunWrapTemplate> Ptr; - - TunWrapTemplate(const bool retain_obj) - : retain_obj_(retain_obj) - { - } - - virtual ~TunWrapTemplate() - { - close(); - } - - bool obj_defined() const - { - return obj_.defined(); - } - - // Current persisted tun fd/handle - typename SCOPED_OBJ::base_type obj() const - { - return obj_(); - } - - bool destructor_defined() const - { - return bool(destruct_); - } - - // destruct object performs cleanup prior to TAP device - // HANDLE close, such as removing added routes. - void add_destructor(const DestructorBase::Ptr& destruct) - { - close_destructor(); - destruct_ = destruct; - } - - void close_destructor() - { - try { - if (destruct_) - { - std::ostringstream os; - destruct_->destroy(os); - OPENVPN_LOG_STRING(os.str()); - destruct_.reset(); - } - } - catch (const std::exception& e) - { - OPENVPN_LOG("TunWrap destructor exception: " << e.what()); - } - } - - void close() - { - if (retain_obj_) - obj_.release(); - else - { - close_destructor(); - obj_.close(); - } - } - - void save_replace_sock(const typename SCOPED_OBJ::base_type obj) - { - if (retain_obj_) - obj_.replace(obj); - else - obj_.reset(obj); - } - - private: - const bool retain_obj_; - DestructorBase::Ptr destruct_; - SCOPED_OBJ obj_; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/persist/tunwrapasio.hpp b/Sources/OpenVPN3/openvpn/tun/persist/tunwrapasio.hpp deleted file mode 100644 index b5e79f4..0000000 --- a/Sources/OpenVPN3/openvpn/tun/persist/tunwrapasio.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// 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-2020 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_TUN_PERSIST_TUNWRAPASIO_H -#define OPENVPN_TUN_PERSIST_TUNWRAPASIO_H - -#include <utility> - -namespace openvpn { - - // This object supports that subset of the Asio stream - // interface required by TunIO, and is intended to wrap - // a ScopedAsioStream embedded in a TunWrap object. - // It is used primarily on Windows to wrap the TAP - // interface HANDLE in way that plays well with Windows - // I/O completion ports (once a HANDLE is bound to an - // I/O completion port it cannot be unbound). - template <typename TunWrap> - class TunWrapAsioStream - { - public: - TunWrapAsioStream(const typename TunWrap::Ptr& tun_wrap_arg) - : tun_wrap(tun_wrap_arg) {} - - - void release() - { - tun_wrap.reset(); - } - - // Delegate STREAM methods (only need to support the - // subset of methods used by TunIO). - // Prototypes from asio/windows/basic_stream_handle.hpp - - template <typename MUTABLE_BUFFER, typename HANDLER> - void async_read_some(const MUTABLE_BUFFER& buffers, HANDLER&& handler) - { - return tun_wrap->obj()->async_read_some(buffers, std::move(handler)); - } - - template <typename CONST_BUFFER> - std::size_t write_some(const CONST_BUFFER& buffers) - { - return tun_wrap->obj()->write_some(buffers); - } - - void cancel() - { - tun_wrap->obj()->cancel(); - } - - void close() - { - tun_wrap->obj()->close(); - } - - private: - typename TunWrap::Ptr tun_wrap; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/proxy.hpp b/Sources/OpenVPN3/openvpn/tun/proxy.hpp deleted file mode 100644 index 07b3f3c..0000000 --- a/Sources/OpenVPN3/openvpn/tun/proxy.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// 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-2020 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/action.hpp> -#include <openvpn/tun/builder/capture.hpp> - -namespace openvpn { - class ProxySettings : public RC<thread_unsafe_refcount> - { - public: - OPENVPN_EXCEPTION(proxy_error); - - typedef RCPtr<ProxySettings> Ptr; - - class ProxyAction : public Action - { - public: - typedef RCPtr<ProxyAction> Ptr; - - ProxyAction(ProxySettings::Ptr parent_arg, bool del_arg) - : parent(parent_arg), del(del_arg) { } - - virtual void execute(std::ostream& os) override - { - os << to_string() << std::endl; - if (parent) - parent->set_proxy(del); - } - - virtual std::string to_string() const override - { - std::ostringstream os; - if (parent && parent->config.defined()) - os << "ProxyAction: auto config: " << parent->config.to_string(); - return os.str(); - } - - private: - const ProxySettings::Ptr parent; - bool del; - }; - - ProxySettings(const TunBuilderCapture::ProxyAutoConfigURL& config_arg) - : config(config_arg) { } - - virtual void set_proxy(bool del) = 0; - - template<class T> - static void add_actions(const TunBuilderCapture& settings, - ActionList& create, - ActionList& destroy) - { - ProxySettings::Ptr proxy(new T(settings.proxy_auto_config_url)); - ProxyAction::Ptr create_action(new ProxyAction(proxy, false)); - ProxyAction::Ptr destroy_action(new ProxyAction(proxy, true)); - create.add(create_action); - destroy.add(destroy_action); - } - - const std::string sname = "OpenVPNConnect"; - - TunBuilderCapture::ProxyAutoConfigURL config; - }; -} diff --git a/Sources/OpenVPN3/openvpn/tun/server/tunbase.hpp b/Sources/OpenVPN3/openvpn/tun/server/tunbase.hpp deleted file mode 100644 index 74007bf..0000000 --- a/Sources/OpenVPN3/openvpn/tun/server/tunbase.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// 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-2020 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/>. - -// Abstract base classes for server tun objects - -#ifndef OPENVPN_TUN_SERVER_TUNBASE_H -#define OPENVPN_TUN_SERVER_TUNBASE_H - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/function.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/server/servhalt.hpp> - -namespace openvpn { - namespace TunClientInstance { - - typedef Function<void(int fd)> PostCloseFunc; - - // A native reference to a client instance - struct NativeHandle - { - NativeHandle() {} - - NativeHandle(const int fd_arg, const int peer_id_arg) - : fd(fd_arg), - peer_id(peer_id_arg) - { - } - - bool fd_defined() const - { - return fd >= 0; - } - - bool defined() const - { - return fd >= 0 && peer_id >= 0; - } - - int fd = -1; - int peer_id = -1; - }; - - // Base class for the client instance receiver. Note that all - // client instance receivers (transport, routing, management, - // etc.) must inherit virtually from RC because the client instance - // object will inherit from multiple receivers. - struct Recv : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Recv> Ptr; - - //virtual bool defined() const = 0; - virtual void stop() = 0; - - // Called with IP packets from tun layer. - virtual void tun_recv(BufferAllocated& buf) = 0; - - // push a halt or restart message to client - virtual void push_halt_restart_msg(const HaltRestart::Type type, - const std::string& reason, - const bool tell_client) = 0; - }; - - // Base class for the per-client-instance state of the TunServer. - // Each client instance uses this class to send data to the tun layer. - struct Send : public virtual RC<thread_unsafe_refcount> - { - typedef RCPtr<Send> Ptr; - - //virtual bool defined() const = 0; - virtual void stop() = 0; - - virtual bool tun_send_const(const Buffer& buf) = 0; - virtual bool tun_send(BufferAllocated& buf) = 0; - - // get the native handle for tun/peer - virtual NativeHandle tun_native_handle() = 0; - - // set up relay to target - virtual void relay(const IP::Addr& target, const int port) = 0; - - virtual const std::string& tun_info() const = 0; - }; - - // Factory for server tun object. - struct Factory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Factory> Ptr; - - virtual Send::Ptr new_obj(Recv* parent) = 0; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/tunio.hpp b/Sources/OpenVPN3/openvpn/tun/tunio.hpp deleted file mode 100644 index f915228..0000000 --- a/Sources/OpenVPN3/openvpn/tun/tunio.hpp +++ /dev/null @@ -1,280 +0,0 @@ -// 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-2020 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/>. - -// Low level tun device I/O class for all platforms (Unix and Windows) - -#ifndef OPENVPN_TUN_TUNIO_H -#define OPENVPN_TUN_TUNIO_H - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/bigmutex.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/ip/ipcommon.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/tun/tunlog.hpp> - -namespace openvpn { - - template <typename ReadHandler, typename PacketFrom, typename STREAM> - class TunIO : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<TunIO> Ptr; - - TunIO(ReadHandler read_handler_arg, - const Frame::Ptr& frame_arg, - const SessionStats::Ptr& stats_arg, - const size_t frame_context_type=Frame::READ_TUN) - : stream(nullptr), - retain_stream(false), - tun_prefix(false), - halt(false), - read_handler(read_handler_arg), - frame(frame_arg), - frame_context((*frame_arg)[frame_context_type]), - stats(stats_arg) - { - } - - virtual ~TunIO() - { - //OPENVPN_LOG("**** TUNIO destruct"); - stop(); - delete stream; - } - - bool write(Buffer& buf) - { - if (!halt) - { - try { - // handle tun packet prefix, if enabled - if (tun_prefix) - { - if (buf.offset() >= 4 && buf.size() >= 1) - { - switch (IPCommon::version(buf[0])) - { - case 4: - prepend_pf_inet(buf, PF_INET); - break; - case 6: - prepend_pf_inet(buf, PF_INET6); - break; - default: - OPENVPN_LOG_TUN_ERROR("TUN write error: cannot identify IP version for prefix"); - tun_error(Error::TUN_FRAMING_ERROR, nullptr); - return false; - } - } - else - { - OPENVPN_LOG_TUN_ERROR("TUN write error: cannot write prefix"); - tun_error(Error::TUN_FRAMING_ERROR, nullptr); - return false; - } - } - - // write data to tun device - const size_t wrote = stream->write_some(buf.const_buffer()); - if (stats) - { - stats->inc_stat(SessionStats::TUN_BYTES_OUT, wrote); - stats->inc_stat(SessionStats::TUN_PACKETS_OUT, 1); - } - if (wrote == buf.size()) - return true; - else - { - OPENVPN_LOG_TUN_ERROR("TUN partial write error"); - tun_error(Error::TUN_WRITE_ERROR, nullptr); - return false; - } - } - catch (openvpn_io::system_error& e) - { - OPENVPN_LOG_TUN_ERROR("TUN write exception: " << e.what()); - const openvpn_io::error_code code(e.code()); - tun_error(Error::TUN_WRITE_ERROR, &code); - return false; - } - } - else - return false; - } - - template <class BUFSEQ> - bool write_seq(const BUFSEQ& bs) - { - if (!halt) - { - try { - // write data to tun device - const size_t wrote = stream->write_some(bs); - if (stats) - { - stats->inc_stat(SessionStats::TUN_BYTES_OUT, wrote); - stats->inc_stat(SessionStats::TUN_PACKETS_OUT, 1); - } - if (wrote == bs.size()) - return true; - else - { - OPENVPN_LOG_TUN_ERROR("TUN partial write error"); - tun_error(Error::TUN_WRITE_ERROR, nullptr); - return false; - } - } - catch (openvpn_io::system_error& e) - { - OPENVPN_LOG_TUN_ERROR("TUN write exception: " << e.what()); - const openvpn_io::error_code code(e.code()); - tun_error(Error::TUN_WRITE_ERROR, &code); - return false; - } - } - else - return false; - } - - void start(const int n_parallel) - { - if (!halt) - { - for (int i = 0; i < n_parallel; i++) - queue_read(nullptr); - } - } - - // must be called by derived class destructor - void stop() - { - if (!halt) - { - halt = true; - if (stream) - { - stream->cancel(); - if (!retain_stream) - { - //OPENVPN_LOG("**** TUNIO close"); - stream->close(); - } - else - stream->release(); - } - } - } - - std::string name() const - { - return name_; - } - - private: - void prepend_pf_inet(Buffer& buf, const std::uint32_t value) - { - const std::uint32_t net_value = htonl(value); - buf.prepend((unsigned char *)&net_value, sizeof(net_value)); - } - - protected: - void queue_read(PacketFrom *tunfrom) - { - OPENVPN_LOG_TUN_VERBOSE("TunIO::queue_read"); - if (!tunfrom) - tunfrom = new PacketFrom(); - frame_context.prepare(tunfrom->buf); - - // queue read on tun device - stream->async_read_some(frame_context.mutable_buffer(tunfrom->buf), - [self=Ptr(this), tunfrom=typename PacketFrom::SPtr(tunfrom)](const openvpn_io::error_code& error, const size_t bytes_recvd) mutable - { - OPENVPN_ASYNC_HANDLER; - self->handle_read(std::move(tunfrom), error, bytes_recvd); - }); - } - - void handle_read(typename PacketFrom::SPtr pfp, const openvpn_io::error_code& error, const size_t bytes_recvd) - { - OPENVPN_LOG_TUN_VERBOSE("TunIO::handle_read: " << error.message()); - if (!halt) - { - if (!error) - { - pfp->buf.set_size(bytes_recvd); - if (stats) - { - stats->inc_stat(SessionStats::TUN_BYTES_IN, bytes_recvd); - stats->inc_stat(SessionStats::TUN_PACKETS_IN, 1); - } - if (!tun_prefix) - { - read_handler->tun_read_handler(pfp); - } - else if (pfp->buf.size() >= 4) - { - // handle tun packet prefix, if enabled - pfp->buf.advance(4); - read_handler->tun_read_handler(pfp); - } - else - { - OPENVPN_LOG_TUN_ERROR("TUN Read Error: cannot read prefix"); - tun_error(Error::TUN_READ_ERROR, nullptr); - } - } - else - { - OPENVPN_LOG_TUN_ERROR("TUN Read Error: " << error.message()); - tun_error(Error::TUN_READ_ERROR, &error); - } - if (!halt) - queue_read(pfp.release()); // reuse buffer if still available - } - } - - void tun_error(const Error::Type errtype, const openvpn_io::error_code* error) - { - if (stats) - stats->error(errtype); - read_handler->tun_error_handler(errtype, error); - } - - // should be set by derived class constructor - std::string name_; - STREAM *stream; - bool retain_stream; // don't close tun stream - bool tun_prefix; - - bool halt; - ReadHandler read_handler; - const Frame::Ptr frame; - const Frame::Context& frame_context; - SessionStats::Ptr stats; - }; -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/tunlog.hpp b/Sources/OpenVPN3/openvpn/tun/tunlog.hpp deleted file mode 100644 index 78ebda6..0000000 --- a/Sources/OpenVPN3/openvpn/tun/tunlog.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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/>. - -// Define tun logging macros using OPENVPN_DEBUG_TUN as a verbosity level. - -#ifndef OPENVPN_TUN_TUNLOG_H -#define OPENVPN_TUN_TUNLOG_H - -#if defined(OPENVPN_DEBUG_TUN) && OPENVPN_DEBUG_TUN >= 1 -#define OPENVPN_LOG_TUN_ERROR(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_TUN_ERROR(x) -#endif - -#if defined(OPENVPN_DEBUG_TUN) && OPENVPN_DEBUG_TUN >= 2 -#define OPENVPN_LOG_TUN(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_TUN(x) -#endif - -#if defined(OPENVPN_DEBUG_TUN) && OPENVPN_DEBUG_TUN >= 3 -#define OPENVPN_LOG_TUN_VERBOSE(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_TUN_VERBOSE(x) -#endif - -#endif // OPENVPN_TUN_TUNLOG_H diff --git a/Sources/OpenVPN3/openvpn/tun/tunmtu.hpp b/Sources/OpenVPN3/openvpn/tun/tunmtu.hpp deleted file mode 100644 index 7b1181c..0000000 --- a/Sources/OpenVPN3/openvpn/tun/tunmtu.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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-2020 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_TUN_TUNMTU_H -#define OPENVPN_TUN_TUNMTU_H - -#include <openvpn/common/options.hpp> - -namespace openvpn { - inline unsigned int parse_tun_mtu(const OptionList& opt, unsigned int default_value) - { - return opt.get_num<unsigned int>("tun-mtu", 1, default_value, 576, 65535); - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/tunspec.hpp b/Sources/OpenVPN3/openvpn/tun/tunspec.hpp deleted file mode 100644 index dcbc17c..0000000 --- a/Sources/OpenVPN3/openvpn/tun/tunspec.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// 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-2020 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/>. - -// Parse the argument of a "tun" or "tap" directive. Also parse an optional -// "/v4" or "/v6" after the tun name to denote IPv4 or IPv6 usage. - -#ifndef OPENVPN_TUN_TUNSPEC_H -#define OPENVPN_TUN_TUNSPEC_H - -#include <string> - -#include <openvpn/common/split.hpp> - -namespace openvpn { - - struct ParseTunSpec - { - OPENVPN_EXCEPTION(bad_tun_spec); - - ParseTunSpec(const std::string& tun_spec) - : ipv6(false) - { - std::vector<std::string> s = Split::by_char<std::vector<std::string>, NullLex, Split::NullLimit>(tun_spec, '/'); - if (s.size() == 1) - { - tun_name = s[0]; - } - else if (s.size() == 2) - { - tun_name = s[0]; - if (s[1] == "v4") - ipv6 = false; - else if (s[1] == "v6") - ipv6 = true; - else - throw bad_tun_spec(); - } - else - throw bad_tun_spec(); - } - bool ipv6; - std::string tun_name; - }; - -} // namespace openvpn - -#endif // OPENVPN_TUN_TUNSPEC_H diff --git a/Sources/OpenVPN3/openvpn/tun/win/client/clientconfig.hpp b/Sources/OpenVPN3/openvpn/tun/win/client/clientconfig.hpp deleted file mode 100644 index 702f762..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/client/clientconfig.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// 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-2020 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/asio/scoped_asio_stream.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/win/client/tunsetup.hpp> - -namespace openvpn { - namespace TunWin { - - // These types manage the underlying TAP driver HANDLE - typedef openvpn_io::windows::stream_handle TAPStream; - typedef ScopedAsioStream<TAPStream> ScopedTAPStream; - struct TunPersistState { - TunProp::State::Ptr state; - RingBuffer::Ptr ring_buffer; - - void reset() - { - state.reset(); - ring_buffer.reset(); - } - }; - typedef TunPersistTemplate<ScopedTAPStream, TunPersistState> TunPersist; - - class ClientConfig : public TunClientFactory - { - friend class Client; // accesses wfp - - public: - typedef RCPtr<ClientConfig> Ptr; - - TunProp::Config tun_prop; - int n_parallel = 8; // number of parallel async reads on tun socket - bool wintun = false; - - Frame::Ptr frame; - SessionStats::Ptr stats; - - Stop* stop = nullptr; - - TunPersist::Ptr tun_persist; - - TunWin::SetupFactory::Ptr tun_setup_factory; - - TunWin::SetupBase::Ptr new_setup_obj(openvpn_io::io_context& io_context) - { - if (tun_setup_factory) - return tun_setup_factory->new_setup_obj(io_context, wintun); - else - return new TunWin::Setup(io_context, wintun); - } - - static Ptr new_obj() - { - return new ClientConfig; - } - - virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) override; - - virtual void finalize(const bool disconnected) override - { - if (disconnected) - tun_persist.reset(); - } - - virtual bool layer_2_supported() const override - { - return true; - } - }; - } -} - diff --git a/Sources/OpenVPN3/openvpn/tun/win/client/setupbase.hpp b/Sources/OpenVPN3/openvpn/tun/win/client/setupbase.hpp deleted file mode 100644 index 84519ba..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/client/setupbase.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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-2020 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/>. -// - -// Client tun setup base class for Windows - -#ifndef OPENVPN_TUN_WIN_CLIENT_SETUPBASE_H -#define OPENVPN_TUN_WIN_CLIENT_SETUPBASE_H - -#include <windows.h> // for HANDLE - -#include <functional> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/destruct.hpp> -#include <openvpn/common/stop.hpp> -#include <openvpn/tun/builder/capture.hpp> - -#include <openvpn/tun/win/ringbuffer.hpp> - -namespace openvpn { - namespace TunWin { - struct SetupBase : public DestructorBase - { - typedef RCPtr<SetupBase> Ptr; - - OPENVPN_EXCEPTION(tun_win_setup); - - virtual HANDLE establish(const TunBuilderCapture& pull, - const std::wstring& openvpn_app_path, - Stop* stop, - std::ostream& os, - RingBuffer::Ptr rings) = 0; - - virtual bool l2_ready(const TunBuilderCapture& pull) = 0; - - virtual void l2_finish(const TunBuilderCapture& pull, - Stop* stop, - std::ostream& os) = 0; - - virtual void confirm() - { - } - - virtual void set_service_fail_handler(std::function<void()>&& handler) - { - } - }; - - struct SetupFactory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<SetupFactory> Ptr; - - virtual SetupBase::Ptr new_setup_obj(openvpn_io::io_context& io_context, bool wintun) = 0; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/client/tuncli.hpp b/Sources/OpenVPN3/openvpn/tun/win/client/tuncli.hpp deleted file mode 100644 index 38d7890..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/client/tuncli.hpp +++ /dev/null @@ -1,410 +0,0 @@ -// 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-2020 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/>. - -// Client tun interface for Windows - -#ifndef OPENVPN_TUN_WIN_CLIENT_TUNCLI_H -#define OPENVPN_TUN_WIN_CLIENT_TUNCLI_H - -#include <string> -#include <sstream> -#include <memory> - -#include <openvpn/common/to_string.hpp> -#include <openvpn/asio/scoped_asio_stream.hpp> -#include <openvpn/common/cleanup.hpp> -#include <openvpn/time/asiotimer.hpp> -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/client/tunprop.hpp> -#include <openvpn/tun/client/dhcp_capture.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/persist/tunwrapasio.hpp> -#include <openvpn/tun/tunio.hpp> -#include <openvpn/tun/win/client/clientconfig.hpp> -#include <openvpn/tun/win/client/tunsetup.hpp> -#include <openvpn/win/modname.hpp> -#include <openvpn/tun/win/client/wintun.hpp> - -namespace openvpn { - namespace TunWin { - - OPENVPN_EXCEPTION(tun_win_error); - - // struct used to pass received tun packets - struct PacketFrom - { - typedef std::unique_ptr<PacketFrom> SPtr; - BufferAllocated buf; - }; - - // tun interface wrapper for Windows - template <typename ReadHandler, typename TunPersist> - class Tun : public TunIO<ReadHandler, PacketFrom, TunWrapAsioStream<TunPersist> > - { - typedef TunIO<ReadHandler, PacketFrom, TunWrapAsioStream<TunPersist> > Base; - - public: - typedef RCPtr<Tun> Ptr; - - Tun(const typename TunPersist::Ptr& tun_persist, - const std::string& name, - const bool retain_stream, - ReadHandler read_handler, - const Frame::Ptr& frame, - const SessionStats::Ptr& stats) - : Base(read_handler, frame, stats, Frame::READ_TUN) - { - Base::name_ = name; - Base::retain_stream = retain_stream; - Base::stream = new TunWrapAsioStream<TunPersist>(tun_persist); - } - }; - - class Client : public TunClient - { - friend class ClientConfig; // calls constructor - friend class TunIO<Client*, PacketFrom, TunWrapAsioStream<TunPersist> >; // calls tun_read_handler - - typedef Tun<Client*, TunPersist> TunImpl; - - public: - typedef RCPtr<Client> Ptr; - - virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { - if (!impl) - { - halt = false; - if (config->tun_persist) - tun_persist = config->tun_persist; // long-term persistent - else - tun_persist.reset(new TunPersist(false, false, nullptr)); // short-term - - try { - const IP::Addr server_addr = transcli.server_endpoint_addr(); - - // Check if persisted tun session matches properties of to-be-created session - if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) - { - state = tun_persist->state().state; - OPENVPN_LOG("TunPersist: reused tun context"); - } - else - { - // notify parent - parent.tun_pre_tun_config(); - - // close old TAP handle if persisted - tun_persist->close(); - - // parse pushed options - TunBuilderCapture::Ptr po(new TunBuilderCapture()); - TunProp::configure_builder(po.get(), - state.get(), - config->stats.get(), - server_addr, - config->tun_prop, - opt, - nullptr, - false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - - // create new tun setup object - tun_setup = config->new_setup_obj(io_context); - - // open/config TAP - HANDLE th; - { - std::ostringstream os; - auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - th = tun_setup->establish(*po, Win::module_name(), config->stop, os, NULL); - } - - // create ASIO wrapper for HANDLE - TAPStream* ts = new TAPStream(io_context, th); - - // persist tun settings state - if (tun_persist->persist_tun_state(ts, { state, nullptr })) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); - - // setup handler for external tun close - tun_setup->set_service_fail_handler([self=Ptr(this)]() { - if (!self->halt) - self->parent.tun_error(Error::TUN_IFACE_DISABLED, "service failure"); - }); - - // enable tun_setup destructor - tun_persist->add_destructor(tun_setup); - - // assert ownership over TAP device handle - tun_setup->confirm(); - - // if layer 2, set up to capture DHCP messages over the tunnel - if (config->tun_prop.layer() == Layer::OSI_LAYER_2) - dhcp_capture.reset(new DHCPCapture(po)); - } - - // configure tun interface packet forwarding - impl.reset(new TunImpl(tun_persist, - "TUN_WIN", - true, - this, - config->frame, - config->stats)); - impl->start(config->n_parallel); - - if (!dhcp_capture) - parent.tun_connected(); // signal that we are connected - } - catch (const std::exception& e) - { - if (tun_persist) - tun_persist->close(); - stop(); - Error::Type err = Error::TUN_SETUP_FAILED; - const ExceptionCode *ec = dynamic_cast<const ExceptionCode *>(&e); - if (ec && ec->code_defined()) - err = ec->code(); - parent.tun_error(err, e.what()); - } - } - } - - virtual bool tun_send(BufferAllocated& buf) override - { - return send(buf); - } - - virtual std::string tun_name() const override - { - if (impl) - return impl->name(); - else - return "UNDEF_TUN"; - } - - virtual std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - virtual std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - virtual std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - virtual void set_disconnect() override - { - } - - virtual void stop() override { stop_(); } - virtual ~Client() { stop_(); } - - private: - Client(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : io_context(io_context_arg), - config(config_arg), - parent(parent_arg), - state(new TunProp::State()), - l2_timer(io_context_arg), - frame_context((*config_arg->frame)[Frame::READ_TUN]), - halt(false) - { - } - - bool send(Buffer& buf) - { - if (impl) - { - if (dhcp_capture) - dhcp_inspect(buf); - - return impl->write(buf); - } - else - return false; -#ifdef OPENVPN_DEBUG_TAPWIN - tap_process_logging(); -#endif - } - - void tun_read_handler(PacketFrom::SPtr& pfp) // called by TunImpl - { - parent.tun_recv(pfp->buf); - -#ifdef OPENVPN_DEBUG_TAPWIN - tap_process_logging(); -#endif - } - - void tun_error_handler(const Error::Type errtype, // called by TunImpl - const openvpn_io::error_code* error) - { - if (errtype == Error::TUN_READ_ERROR && error && error->value() == 995) - parent.tun_error(Error::TUN_IFACE_DISABLED, "TAP adapter is disabled"); - else - parent.tun_error(Error::TUN_ERROR, "TUN I/O error"); - } - - void stop_() - { - if (!halt) - { - halt = true; - - l2_timer.cancel(); - - // stop tun - if (impl) - impl->stop(); - tun_persist.reset(); - } - } - - HANDLE tap_handle() - { - if (tun_persist) - { - TAPStream* stream = tun_persist->obj(); - if (stream) - return stream->native_handle(); - } - return Win::Handle::undefined(); - } - - void tap_process_logging() - { - HANDLE h = tap_handle(); - if (Win::Handle::defined(h)) - Util::tap_process_logging(h); - } - - void dhcp_inspect(Buffer& buf) - { - try { - if (dhcp_capture->mod_reply(buf)) - { - OPENVPN_LOG("DHCP PROPS:" << std::endl << dhcp_capture->get_props().to_string()); - layer_2_schedule_timer(1); - } - } - catch (const std::exception& e) - { - stop(); - parent.tun_error(Error::TUN_SETUP_FAILED, std::string("L2 exception: ") + e.what()); - } - } - - void layer_2_schedule_timer(const unsigned int seconds) - { - l2_timer.expires_after(Time::Duration::seconds(seconds)); - l2_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - OPENVPN_ASYNC_HANDLER; - if (!error && !self->halt) - self->layer_2_timer_callback(); - }); - } - - // Normally called once per second by l2_timer while we are waiting - // for layer 2 DHCP handshake to complete. - void layer_2_timer_callback() - { - try { - if (dhcp_capture && tun_setup) - { - if (tun_setup->l2_ready(dhcp_capture->get_props())) - { - std::ostringstream os; - tun_setup->l2_finish(dhcp_capture->get_props(), config->stop, os); - OPENVPN_LOG_STRING(os.str()); - parent.tun_connected(); - dhcp_capture.reset(); - } - else - { - OPENVPN_LOG("L2: Waiting for DHCP handshake..."); - layer_2_schedule_timer(1); - } - } - } - catch (const std::exception& e) - { - stop(); - parent.tun_error(Error::TUN_SETUP_FAILED, std::string("L2 exception: ") + e.what()); - } - } - - openvpn_io::io_context& io_context; - TunPersist::Ptr tun_persist; // contains the TAP device HANDLE - ClientConfig::Ptr config; - TunClientParent& parent; - TunImpl::Ptr impl; - TunProp::State::Ptr state; - TunWin::SetupBase::Ptr tun_setup; - - // Layer 2 DHCP stuff - std::unique_ptr<DHCPCapture> dhcp_capture; - AsioTimer l2_timer; - - Frame::Context& frame_context; - - bool halt; - }; - - inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context& io_context, - TunClientParent& parent, - TransportClient* transcli) - { - if (wintun) - return TunClient::Ptr(new WintunClient(io_context, this, parent)); - else - return TunClient::Ptr(new Client(io_context, this, parent)); - } - - } -} // namespace openvpn - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/client/tunsetup.hpp b/Sources/OpenVPN3/openvpn/tun/win/client/tunsetup.hpp deleted file mode 100644 index 9440bb3..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/client/tunsetup.hpp +++ /dev/null @@ -1,952 +0,0 @@ -// 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-2020 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/>. -// - -// Client tun setup for Windows - -#ifndef OPENVPN_TUN_WIN_CLIENT_TUNSETUP_H -#define OPENVPN_TUN_WIN_CLIENT_TUNSETUP_H - -#include <string> -#include <sstream> -#include <ostream> -#include <memory> -#include <utility> -#include <thread> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/error/excode.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/tun/proxy.hpp> -#include <openvpn/tun/win/tunutil.hpp> -#include <openvpn/tun/win/winproxy.hpp> -#include <openvpn/tun/win/tunutil.hpp> -#include <openvpn/tun/win/client/setupbase.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/cmd.hpp> - -#if _WIN32_WINNT >= 0x0600 // Vista+ -#include <openvpn/tun/win/nrpt.hpp> -#include <openvpn/tun/win/wfp.hpp> -#endif - -#include <versionhelpers.h> - -// use IP Helper on Windows by default -#ifdef OPENVPN_USE_NETSH -#define TUNWINDOWS Util::TunNETSH -#else -#define TUNWINDOWS Util::TunIPHELPER -#endif - -namespace openvpn { - namespace TunWin { - class Setup : public SetupBase - { - public: - typedef RCPtr<Setup> Ptr; - - Setup(openvpn_io::io_context& io_context_arg, bool wintun_arg=false) - : delete_route_timer(io_context_arg), - wintun(wintun_arg) {} - - // Set up the TAP device - virtual HANDLE establish(const TunBuilderCapture& pull, - const std::wstring& openvpn_app_path, - Stop* stop, - std::ostream& os, - RingBuffer::Ptr ring_buffer) override // defined by SetupBase - { - // close out old remove cmds, if they exist - destroy(os); - - // enumerate available TAP adapters - Util::TapNameGuidPairList guids(wintun); - os << "TAP ADAPTERS:" << std::endl << guids.to_string() << std::endl; - - // open TAP device handle - std::string path_opened; - Util::TapNameGuidPair tap; - Win::ScopedHANDLE th(Util::tap_open(guids, path_opened, tap, wintun)); - const std::string msg = "Open TAP device \"" + tap.name + "\" PATH=\"" + path_opened + '\"'; - vpn_interface_index_ = tap.index; - - if (!th.defined()) - { - os << msg << " FAILED" << std::endl; - throw ErrorCode(Error::TUN_IFACE_CREATE, true, "cannot acquire TAP handle"); - } - - os << msg << " SUCCEEDED" << std::endl; - if (!wintun) - { - Util::TAPDriverVersion version(th()); - os << version.to_string() << std::endl; - } - - // create ActionLists for setting up and removing adapter properties - ActionList::Ptr add_cmds(new ActionList()); - remove_cmds.reset(new ActionList()); - - // populate add/remove lists with actions - switch (pull.layer()) - { - case Layer::OSI_LAYER_3: - adapter_config(th(), openvpn_app_path, tap, pull, false, *add_cmds, *remove_cmds, os); - break; - case Layer::OSI_LAYER_2: - adapter_config_l2(th(), openvpn_app_path, tap, pull, *add_cmds, *remove_cmds, os); - break; - default: - throw tun_win_setup("layer undefined"); - } - // execute the add actions - add_cmds->execute(os); - - // now that the add actions have succeeded, - // enable the remove actions - remove_cmds->enable_destroy(true); - - // if layer 2, save state - if (pull.layer() == Layer::OSI_LAYER_2) - l2_state.reset(new L2State(tap, openvpn_app_path)); - - if (ring_buffer) - register_rings(th(), ring_buffer); - - if (!wintun && tap.index_defined()) - Util::flush_arp(tap.index, os); - - return th.release(); - } - - // In layer 2 mode, return true route_delay seconds after - // the adapter properties matches the data given in pull. - // This method is usually called once per second until it - // returns true. - virtual bool l2_ready(const TunBuilderCapture& pull) override - { - const unsigned int route_delay = 5; - if (l2_state) - { - if (l2_state->props_ready.defined()) - { - if (Time::now() >= l2_state->props_ready) - return true; - } - else - { - const Util::IPNetmask4 vpn_addr(pull, "VPN IP"); - const Util::IPAdaptersInfo ai; - if (ai.is_up(l2_state->tap.index, vpn_addr)) - l2_state->props_ready = Time::now() + Time::Duration::seconds(route_delay); - } - } - return false; - } - - // Finish the layer 2 configuration, should be called - // after l2_ready() returns true. - virtual void l2_finish(const TunBuilderCapture& pull, - Stop* stop, - std::ostream& os) override - { - std::unique_ptr<L2State> l2s(std::move(l2_state)); - if (l2s) - { - Win::ScopedHANDLE nh; - ActionList::Ptr add_cmds(new ActionList()); - adapter_config(nh(), l2s->openvpn_app_path, l2s->tap, pull, true, *add_cmds, *remove_cmds, os); - add_cmds->execute(os); - } - } - - virtual void destroy(std::ostream& os) override // defined by DestructorBase - { - // l2_state - l2_state.reset(); - - // l2_thread - if (l2_thread) - { - try { - l2_thread->join(); - } - catch (...) - { - } - l2_thread.reset(); - } - - // remove_cmds - if (remove_cmds) - { - remove_cmds->destroy(os); - remove_cmds.reset(); - } - - delete_route_timer.cancel(); - - vpn_interface_index_ = DWORD(-1); - } - - virtual ~Setup() - { - std::ostringstream os; - destroy(os); - } - - DWORD vpn_interface_index() const - { - return vpn_interface_index_; - } - - static void add_bypass_route(const Util::BestGateway& gw, - const std::string& route, - bool ipv6, - ActionList& add_cmds, - ActionList& remove_cmds_bypass_gw) - { - if (!ipv6) - { - if (!gw.local_route()) - { - add_cmds.add(new WinCmd("netsh interface ip add route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active")); - remove_cmds_bypass_gw.add(new WinCmd("netsh interface ip delete route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active")); - } - else - { - OPENVPN_LOG("Skip bypass route to " << route << ", route is local"); - } - } - } - - private: - struct L2State - { - L2State(const Util::TapNameGuidPair& tap_arg, - const std::wstring& openvpn_app_path_arg) - : tap(tap_arg), - openvpn_app_path(openvpn_app_path_arg) - { - } - - Util::TapNameGuidPair tap; - std::wstring openvpn_app_path; - Time props_ready; - }; - - class UseDNS - { - public: - UseDNS() {} - - UseDNS(const TunBuilderCapture& pull) - { - for (auto &ds : pull.dns_servers) - add(ds, pull); - } - - static bool enabled(const TunBuilderCapture::DNSServer& ds, - const TunBuilderCapture& pull) - { - if (ds.ipv6 && pull.block_ipv6) - return false; - return true; - } - - int add(const TunBuilderCapture::DNSServer& ds, - const TunBuilderCapture& pull) - { - if (enabled(ds, pull)) - return indices[ds.ipv6 ? 1 : 0]++; - else - return -1; - } - - int ipv4() const { return indices[0]; } - int ipv6() const { return indices[1]; } - - private: - int indices[2] = {0, 0}; - }; - - void register_rings(HANDLE handle, RingBuffer::Ptr ring_buffer) - { - TUN_REGISTER_RINGS rings; - - ZeroMemory(&rings, sizeof(rings)); - - rings.receive.ring = ring_buffer->receive_ring(); - rings.receive.tail_moved = ring_buffer->receive_ring_tail_moved(); - rings.receive.ring_size = sizeof(rings.receive.ring->data); - - rings.send.ring = ring_buffer->send_ring(); - rings.send.tail_moved = ring_buffer->send_ring_tail_moved(); - rings.send.ring_size = sizeof(rings.send.ring->data); - - { - Win::Impersonate imp(true); - - DWORD len; - if (!DeviceIoControl(handle, TUN_IOCTL_REGISTER_RINGS, &rings, sizeof(rings), NULL, 0, &len, NULL)) - { - const Win::LastError err; - throw ErrorCode(Error::TUN_REGISTER_RINGS_ERROR, true, "Error registering ring buffers: " + err.message()); - } - } - } - -#if _WIN32_WINNT >= 0x0600 - // Configure TAP adapter on Vista and higher - void adapter_config(HANDLE th, - const std::wstring& openvpn_app_path, - const Util::TapNameGuidPair& tap, - const TunBuilderCapture& pull, - const bool l2_post, - ActionList& create, - ActionList& destroy, - std::ostream& os) - { - // Windows interface index - const std::string tap_index_name = tap.index_or_name(); - - // special IPv6 next-hop recognized by TAP driver (magic) - const std::string ipv6_next_hop = "fe80::8"; - - // 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(); - - if (!l2_post) - { - // set TAP media status to CONNECTED - if (!wintun) - Util::tap_set_media_status(th, true); - - // try to delete any stale routes on interface left over from previous session - create.add(new Util::ActionDeleteAllRoutesOnInterface(tap.index)); - } - - // Set IPv4 Interface - // - // Usage: set address [name=]<string> - // [[source=]dhcp|static] - // [[address=]<IPv4 address>[/<integer>] [[mask=]<IPv4 mask>] - // [[gateway=]<IPv4 address>|none [gwmetric=]<integer>] - // [[type=]unicast|anycast] - // [[subinterface=]<string>] - // [[store=]active|persistent] - // Usage: delete address [name=]<string> [[address=]<IPv4 address>] - // [[gateway=]<IPv4 address>|all] - // [[store=]active|persistent] - if (local4) - { - // Process ifconfig and topology - if (!l2_post) - { - // set lowest interface metric to make Windows use pushed DNS search domain - create.add(new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=1")); - - const std::string metric = route_metric_opt(pull, *local4, MT_IFACE); - const std::string netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length).to_string(); - const IP::Addr localaddr = IP::Addr::from_string(local4->address); - const IP::Addr remoteaddr = IP::Addr::from_string(local4->gateway); - if (!wintun) - { - if (local4->net30) - Util::tap_configure_topology_net30(th, localaddr, remoteaddr); - else - Util::tap_configure_topology_subnet(th, localaddr, local4->prefix_length); - } - create.add(new WinCmd("netsh interface ip set address " + tap_index_name + " static " + local4->address + ' ' + netmask + " gateway=" + local4->gateway + metric + " store=active")); - destroy.add(new WinCmd("netsh interface ip delete address " + tap_index_name + ' ' + local4->address + " gateway=all store=active")); - - // specifying 'gateway' when setting ip address makes Windows add unnecessary route 0.0.0.0/0, - // which might cause routing conflicts, so we have to delete it after a small delay. - // If route is deleted before profile is created, then profile won't be created at all (OVPN-135) - WinCmd::Ptr cmd = new WinCmd("netsh interface ip delete route 0.0.0.0/0 " + tap_index_name + ' ' + local4->gateway + " store=active"); - delete_route_timer.expires_after(Time::Duration::seconds(5)); - delete_route_timer.async_wait([self=Ptr(this), cmd=std::move(cmd)](const openvpn_io::error_code& error) - { - if (!error) - { - std::ostringstream os; - cmd->execute(os); - } - }); - } - } - - // Should we block IPv6? - if (pull.block_ipv6) - { - static const char *const block_ipv6_net[] = { - "2000::/4", - "3000::/4", - "fc00::/7", - }; - for (size_t i = 0; i < array_size(block_ipv6_net); ++i) - { - create.add(new WinCmd("netsh interface ipv6 add route " + std::string(block_ipv6_net[i]) + " interface=1 store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete route " + std::string(block_ipv6_net[i]) + " interface=1 store=active")); - } - } - - // Set IPv6 Interface - // - // Usage: set address [interface=]<string> [address=]<IPv6 address> - // [[type=]unicast|anycast] - // [[validlifetime=]<integer>|infinite] - // [[preferredlifetime=]<integer>|infinite] - // [[store=]active|persistent] - //Usage: delete address [interface=]<string> [address=]<IPv6 address> - // [[store=]active|persistent] - if (local6 && !pull.block_ipv6 && !l2_post) - { - create.add(new WinCmd("netsh interface ipv6 set address " + tap_index_name + ' ' + local6->address + " store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete address " + tap_index_name + ' ' + local6->address + " store=active")); - - create.add(new WinCmd("netsh interface ipv6 add route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - } - - // Process Routes - // - // Usage: add route [prefix=]<IPv4 address>/<integer> [interface=]<string> - // [[nexthop=]<IPv4 address>] [[siteprefixlength=]<integer>] - // [[metric=]<integer>] [[publish=]no|age|yes] - // [[validlifetime=]<integer>|infinite] - // [[preferredlifetime=]<integer>|infinite] - // [[store=]active|persistent] - // Usage: delete route [prefix=]<IPv4 address>/<integer> [interface=]<string> - // [[nexthop=]<IPv4 address>] - // [[store=]active|persistent] - // - // Usage: add route [prefix=]<IPv6 address>/<integer> [interface=]<string> - // [[nexthop=]<IPv6 address>] [[siteprefixlength=]<integer>] - // [[metric=]<integer>] [[publish=]no|age|yes] - // [[validlifetime=]<integer>|infinite] - // [[preferredlifetime=]<integer>|infinite] - // [[store=]active|persistent] - // Usage: delete route [prefix=]<IPv6 address>/<integer> [interface=]<string> - // [[nexthop=]<IPv6 address>] - // [[store=]active|persistent] - { - for (auto &route : pull.add_routes) - { - if (route.ipv6) - { - if (!pull.block_ipv6) - { - const std::string metric = route_metric_opt(pull, route, MT_NETSH); - create.add(new WinCmd("netsh interface ipv6 add route " + route.address + '/' + to_string(route.prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + metric + " store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete route " + route.address + '/' + to_string(route.prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - } - } - else - { - if (local4) - { - int metric = pull.route_metric_default; - if (route.metric >= 0) - metric = route.metric; - create.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap, local4->gateway, metric, true)); - destroy.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap, local4->gateway, metric, false)); - } - else - throw tun_win_setup("IPv4 routes pushed without IPv4 ifconfig"); - } - } - } - - // Process exclude routes - if (!pull.exclude_routes.empty()) - { - const Util::BestGateway gw; - if (gw.defined()) - { - bool ipv6_error = false; - for (auto &route : pull.exclude_routes) - { - const std::string metric = route_metric_opt(pull, route, MT_NETSH); - if (route.ipv6) - { - ipv6_error = true; - } - else - { - create.add(new WinCmd("netsh interface ip add route " + route.address + '/' + to_string(route.prefix_length) + ' ' + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + metric + " store=active")); - destroy.add(new WinCmd("netsh interface ip delete route " + route.address + '/' + to_string(route.prefix_length) + ' ' + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active")); - } - } - if (ipv6_error) - os << "NOTE: exclude IPv6 routes not currently supported" << std::endl; - } - else - os << "NOTE: exclude routes error: cannot detect default gateway" << std::endl; - } - - // Process IPv4 redirect-gateway - if (pull.reroute_gw.ipv4) - { - // get default gateway - const Util::BestGateway gw{ pull.remote_address.address, tap.index }; - - if (!gw.local_route()) - { - // add server bypass route - if (gw.defined()) - { - if (!pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL)) - add_bypass_route(gw, pull.remote_address.address, false, create, destroy); - } - else - throw tun_win_setup("redirect-gateway error: cannot find gateway for bypass route"); - } - - create.add(new WinCmd("netsh interface ip add route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active")); - create.add(new WinCmd("netsh interface ip add route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active")); - destroy.add(new WinCmd("netsh interface ip delete route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active")); - destroy.add(new WinCmd("netsh interface ip delete route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active")); - } - - // Process IPv6 redirect-gateway - if (pull.reroute_gw.ipv6 && !pull.block_ipv6) - { - create.add(new WinCmd("netsh interface ipv6 add route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - create.add(new WinCmd("netsh interface ipv6 add route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - destroy.add(new WinCmd("netsh interface ipv6 delete route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active")); - } - - // Process DNS Servers - // - // Usage: set dnsservers [name=]<string> [source=]dhcp|static - // [[address=]<IP address>|none] - // [[register=]none|primary|both] - // [[validate=]yes|no] - // Usage: add dnsservers [name=]<string> [address=]<IPv4 address> - // [[index=]<integer>] [[validate=]yes|no] - // Usage: delete dnsservers [name=]<string> [[address=]<IP address>|all] [[validate=]yes|no] - // - // Usage: set dnsservers [name=]<string> [source=]dhcp|static - // [[address=]<IPv6 address>|none] - // [[register=]none|primary|both] - // [[validate=]yes|no] - // Usage: add dnsservers [name=]<string> [address=]<IPv6 address> - // [[index=]<integer>] [[validate=]yes|no] - // Usage: delete dnsservers [name=]<string> [[address=]<IPv6 address>|all] [[validate=]yes|no] - { - // fix for vista and dnsserver vs win7+ dnsservers - std::string dns_servers_cmd = "dnsservers"; - std::string validate_cmd = " validate=no"; - if (IsWindowsVistaOrGreater() && !IsWindows7OrGreater()) { - dns_servers_cmd = "dnsserver"; - validate_cmd = ""; - } - -#if 1 - // normal production setting - const bool use_nrpt = IsWindows8OrGreater(); - const bool use_wfp = IsWindows8OrGreater(); - const bool add_netsh_rules = true; -#else - // test NRPT registry settings on pre-Win8 - const bool use_nrpt = true; - const bool use_wfp = true; - const bool add_netsh_rules = true; -#endif - // determine IPv4/IPv6 DNS redirection - const UseDNS dns(pull); - - // will DNS requests be split between VPN DNS server and local? - const bool split_dns = (!pull.search_domains.empty() - && !(pull.reroute_gw.ipv4 && dns.ipv4()) - && !(pull.reroute_gw.ipv6 && dns.ipv6())); - - // add DNS servers via netsh - if (add_netsh_rules && !(use_nrpt && split_dns) && !l2_post) - { - UseDNS dc; - for (auto &ds : pull.dns_servers) - { - // 0-based index for specific IPv4/IPv6 protocol, or -1 if disabled - const int count = dc.add(ds, pull); - if (count >= 0) - { - const std::string proto = ds.ipv6 ? "ipv6" : "ip"; - if (count) - create.add(new WinCmd("netsh interface " + proto + " add " + dns_servers_cmd + " " + tap_index_name + ' ' + ds.address + " " + to_string(count+1) + validate_cmd)); - else - { - create.add(new WinCmd("netsh interface " + proto + " set " + dns_servers_cmd + " " + tap_index_name + " static " + ds.address + " register=primary" + validate_cmd)); - destroy.add(new WinCmd("netsh interface " + proto + " delete " + dns_servers_cmd + " " + tap_index_name + " all" + validate_cmd)); - } - } - } - } - - // If NRPT enabled and at least one IPv4 or IPv6 DNS - // server was added, add NRPT registry entries to - // route DNS through the tunnel. - // Also consider selective DNS routing using domain - // suffix list from pull.search_domains as set by - // "dhcp-option DOMAIN ..." directives. - if (use_nrpt && (dns.ipv4() || dns.ipv6())) - { - // domain suffix list - std::vector<std::string> dsfx; - - // Only add DNS routing suffixes if not rerouting gateway. - // Otherwise, route all DNS requests with wildcard ("."). - if (split_dns) - { - for (const auto &sd : pull.search_domains) - { - std::string dom = sd.domain; - if (!dom.empty()) - { - // each DNS suffix must begin with '.' - if (dom[0] != '.') - dom = "." + dom; - dsfx.push_back(std::move(dom)); - } - } - } - if (dsfx.empty()) - dsfx.emplace_back("."); - - // DNS server list - std::vector<std::string> dserv; - for (const auto &ds : pull.dns_servers) - dserv.push_back(ds.address); - - create.add(new NRPT::ActionCreate(dsfx, dserv)); - destroy.add(new NRPT::ActionDelete); - } - - // Use WFP for DNS leak protection. - // If we added DNS servers, block DNS on all interfaces except - // the TAP adapter. - if (use_wfp && !split_dns && !openvpn_app_path.empty() && (dns.ipv4() || dns.ipv6())) - { - create.add(new ActionWFP(openvpn_app_path, tap.index, true, wfp)); - destroy.add(new ActionWFP(openvpn_app_path, tap.index, false, wfp)); - } - } - - // Set a default TAP-adapter domain suffix using - // "dhcp-option ADAPTER_DOMAIN_SUFFIX mycompany.com" directive. - if (!pull.adapter_domain_suffix.empty()) - { - // Only the first search domain is used - create.add(new Util::ActionSetAdapterDomainSuffix(pull.adapter_domain_suffix, tap.guid)); - destroy.add(new Util::ActionSetAdapterDomainSuffix("", tap.guid)); - } - - // Process WINS Servers - // - // Usage: set winsservers [name=]<string> [source=]dhcp|static - // [[address=]<IP address>|none] - // Usage: add winsservers [name=]<string> [address=]<IP address> [[index=]<integer>] - // Usage: delete winsservers [name=]<string> [[address=]<IP address>|all] - { - for (size_t i = 0; i < pull.wins_servers.size(); ++i) - { - const TunBuilderCapture::WINSServer& ws = pull.wins_servers[i]; - if (i) - create.add(new WinCmd("netsh interface ip add winsservers " + tap_index_name + ' ' + ws.address + ' ' + to_string(i+1))); - else - { - create.add(new WinCmd("netsh interface ip set winsservers " + tap_index_name + " static " + ws.address)); - destroy.add(new WinCmd("netsh interface ip delete winsservers " + tap_index_name + " all")); - } - } - } - - OPENVPN_LOG("proxy_auto_config_url " << pull.proxy_auto_config_url.url); - if (pull.proxy_auto_config_url.defined()) - ProxySettings::add_actions<WinProxySettings>(pull, create, destroy); - - // flush DNS cache - create.add(new WinCmd("ipconfig /flushdns")); - destroy.add(new WinCmd("ipconfig /flushdns")); - } -#else - // Configure TAP adapter for pre-Vista - // Currently we don't support IPv6 on pre-Vista - void adapter_config(HANDLE th, - const std::wstring& openvpn_app_path, - const Util::TapNameGuidPair& tap, - const TunBuilderCapture& pull, - const bool l2_post, - ActionList& create, - ActionList& destroy, - std::ostream& os) - { - // Windows interface index - const std::string tap_index_name = tap.index_or_name(); - - // get default gateway - const Util::DefaultGateway gw; - - // set local4 to point to IPv4 route configurations - const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4(); - - // This section skipped on layer 2 post-config - if (!l2_post) - { - // Make sure the TAP adapter is set for DHCP - { - const Util::IPAdaptersInfo ai; - if (!ai.is_dhcp_enabled(tap.index)) - { - os << "TAP: DHCP is disabled, attempting to enable" << std::endl; - ActionList::Ptr cmds(new ActionList()); - cmds->add(new Util::ActionEnableDHCP(tap)); - cmds->execute(os); - } - } - - // Set IPv4 Interface - if (local4) - { - // Process ifconfig and topology - const std::string netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length).to_string(); - const IP::Addr localaddr = IP::Addr::from_string(local4->address); - if (local4->net30) - Util::tap_configure_topology_net30(th, localaddr, local4->prefix_length); - else - Util::tap_configure_topology_subnet(th, localaddr, local4->prefix_length); - } - - // On pre-Vista, set up TAP adapter DHCP masquerade for - // configuring adapter properties. - { - os << "TAP: configure DHCP masquerade" << std::endl; - Util::TAPDHCPMasquerade dhmasq; - dhmasq.init_from_capture(pull); - dhmasq.ioctl(th); - } - - // set TAP media status to CONNECTED - if (!wintun) - Util::tap_set_media_status(th, true); - - // ARP - Util::flush_arp(tap.index, os); - - // DHCP release/renew - { - const Util::InterfaceInfoList ii; - Util::dhcp_release(ii, tap.index, os); - Util::dhcp_renew(ii, tap.index, os); - } - - // Wait for TAP adapter to come up - { - bool succeed = false; - const Util::IPNetmask4 vpn_addr(pull, "VPN IP"); - for (int i = 1; i <= 30; ++i) - { - os << '[' << i << "] waiting for TAP adapter to receive DHCP settings..." << std::endl; - const Util::IPAdaptersInfo ai; - if (ai.is_up(tap.index, vpn_addr)) - { - succeed = true; - break; - } - ::Sleep(1000); - } - if (!succeed) - throw tun_win_setup("TAP adapter DHCP handshake failed"); - } - - // Pre route-add sleep - os << "Sleeping 5 seconds prior to adding routes..." << std::endl; - ::Sleep(5000); - } - - // Process routes - for (auto &route : pull.add_routes) - { - const std::string metric = route_metric_opt(pull, route, MT_ROUTE); - if (!route.ipv6) - { - if (local4) - { - const std::string netmask = IPv4::Addr::netmask_from_prefix_len(route.prefix_length).to_string(); - create.add(new WinCmd("route ADD " + route.address + " MASK " + netmask + ' ' + local4->gateway + metric)); - destroy.add(new WinCmd("route DELETE " + route.address + " MASK " + netmask + ' ' + local4->gateway)); - } - else - throw tun_win_setup("IPv4 routes pushed without IPv4 ifconfig"); - } - } - - // Process exclude routes - if (!pull.exclude_routes.empty()) - { - if (gw.defined()) - { - for (auto &route : pull.exclude_routes) - { - const std::string metric = route_metric_opt(pull, route, MT_ROUTE); - if (!route.ipv6) - { - const std::string netmask = IPv4::Addr::netmask_from_prefix_len(route.prefix_length).to_string(); - create.add(new WinCmd("route ADD " + route.address + " MASK " + netmask + ' ' + gw.gateway_address() + metric)); - destroy.add(new WinCmd("route DELETE " + route.address + " MASK " + netmask + ' ' + gw.gateway_address())); - } - } - } - else - os << "NOTE: exclude routes error: cannot detect default gateway" << std::endl; - } - - // Process IPv4 redirect-gateway - if (pull.reroute_gw.ipv4) - { - // add server bypass route - if (gw.defined()) - { - if (!pull.remote_address.ipv6) - { - create.add(new WinCmd("route ADD " + pull.remote_address.address + " MASK 255.255.255.255 " + gw.gateway_address())); - destroy.add(new WinCmd("route DELETE " + pull.remote_address.address + " MASK 255.255.255.255 " + gw.gateway_address())); - } - } - else - throw tun_win_setup("redirect-gateway error: cannot detect default gateway"); - - create.add(new WinCmd("route ADD 0.0.0.0 MASK 128.0.0.0 " + local4->gateway)); - create.add(new WinCmd("route ADD 128.0.0.0 MASK 128.0.0.0 " + local4->gateway)); - destroy.add(new WinCmd("route DELETE 0.0.0.0 MASK 128.0.0.0 " + local4->gateway)); - destroy.add(new WinCmd("route DELETE 128.0.0.0 MASK 128.0.0.0 " + local4->gateway)); - } - - // flush DNS cache - //create.add(new WinCmd("net stop dnscache")); - //create.add(new WinCmd("net start dnscache")); - create.add(new WinCmd("ipconfig /flushdns")); - //create.add(new WinCmd("ipconfig /registerdns")); - destroy.add(new WinCmd("ipconfig /flushdns")); - } -#endif - - void adapter_config_l2(HANDLE th, - const std::wstring& openvpn_app_path, - const Util::TapNameGuidPair& tap, - const TunBuilderCapture& pull, - ActionList& create, - ActionList& destroy, - std::ostream& os) - { - // Make sure the TAP adapter is set for DHCP - { - const Util::IPAdaptersInfo ai; - if (!ai.is_dhcp_enabled(tap.index)) - { - os << "TAP: DHCP is disabled, attempting to enable" << std::endl; - ActionList::Ptr cmds(new ActionList()); - cmds->add(new Util::ActionEnableDHCP(tap)); - cmds->execute(os); - } - } - - // set TAP media status to CONNECTED - Util::tap_set_media_status(th, true); - - // ARP - Util::flush_arp(tap.index, os); - - // We must do DHCP release/renew in a background thread - // so the foreground can forward the DHCP negotiation packets - // over the tunnel. - l2_thread.reset(new std::thread([tap, logwrap=Log::Context::Wrapper()]() { - Log::Context logctx(logwrap); - ::Sleep(250); - const Util::InterfaceInfoList ii; - { - std::ostringstream os; - Util::dhcp_release(ii, tap.index, os); - OPENVPN_LOG_STRING(os.str()); - } - ::Sleep(250); - { - std::ostringstream os; - Util::dhcp_renew(ii, tap.index, os); - OPENVPN_LOG_STRING(os.str()); - } - })); - } - - enum MetricType { - MT_ROUTE, - MT_NETSH, - MT_IFACE, - }; - - static std::string route_metric_opt(const TunBuilderCapture& pull, - const TunBuilderCapture::RouteBase& route, - const MetricType mt) - { - int metric = pull.route_metric_default; - if (route.metric >= 0) - metric = route.metric; - if (metric >= 0) - { - switch (mt) - { - case MT_ROUTE: - return " METRIC " + std::to_string(metric); // route command form - case MT_NETSH: - return " metric=" + std::to_string(metric); // "netsh interface ip[v6] add route" form - case MT_IFACE: - return " gwmetric=" + std::to_string(metric); // "netsh interface ip set address" form - } - } - return ""; - } - -#if _WIN32_WINNT >= 0x0600 // Vista+ - TunWin::WFPContext::Ptr wfp{new TunWin::WFPContext}; -#endif - - std::unique_ptr<std::thread> l2_thread; - std::unique_ptr<L2State> l2_state; - - DWORD vpn_interface_index_ = DWORD(-1); - ActionList::Ptr remove_cmds; - - AsioTimer delete_route_timer; - - bool wintun = false; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/client/wintun.hpp b/Sources/OpenVPN3/openvpn/tun/win/client/wintun.hpp deleted file mode 100644 index 6bcc0db..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/client/wintun.hpp +++ /dev/null @@ -1,315 +0,0 @@ -#pragma once - -#include <openvpn/tun/client/tunbase.hpp> -#include <openvpn/tun/persist/tunpersist.hpp> -#include <openvpn/tun/win/client/setupbase.hpp> -#include <openvpn/tun/win/client/clientconfig.hpp> -#include <openvpn/win/modname.hpp> - -namespace openvpn { - namespace TunWin { - - class WintunClient : public TunClient - { - typedef RCPtr<WintunClient> Ptr; - - public: - WintunClient(openvpn_io::io_context& io_context_arg, - ClientConfig* config_arg, - TunClientParent& parent_arg) - : io_context(io_context_arg), - config(config_arg), - parent(parent_arg), - state(new TunProp::State()), - frame(config_arg->frame) - { - } - - // Inherited via TunClient - void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override - { - halt = false; - if (config->tun_persist) - tun_persist = config->tun_persist; // long-term persistent - else - tun_persist.reset(new TunPersist(false, false, nullptr)); // short-term - - try { - - const IP::Addr server_addr = transcli.server_endpoint_addr(); - - // Check if persisted tun session matches properties of to-be-created session - if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt)) - { - state = tun_persist->state().state; - ring_buffer = tun_persist->state().ring_buffer; - OPENVPN_LOG("TunPersist: reused tun context"); - } - else - { - // notify parent - parent.tun_pre_tun_config(); - - // close old TAP handle if persisted - tun_persist->close(); - - // parse pushed options - TunBuilderCapture::Ptr po(new TunBuilderCapture()); - TunProp::configure_builder(po.get(), - state.get(), - config->stats.get(), - server_addr, - config->tun_prop, - opt, - nullptr, - false); - OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl << po->to_string()); - - // create new tun setup object - tun_setup = config->new_setup_obj(io_context); - - ring_buffer.reset(new RingBuffer(io_context)); - - // open/config TAP - HANDLE th; - { - std::ostringstream os; - auto os_print = Cleanup([&os]() { OPENVPN_LOG_STRING(os.str()); }); - th = tun_setup->establish(*po, Win::module_name(), config->stop, os, ring_buffer); - } - - // create ASIO wrapper for HANDLE - TAPStream* ts = new TAPStream(io_context, th); - - // persist tun settings state - if (tun_persist->persist_tun_state(ts, { state, ring_buffer })) - OPENVPN_LOG("TunPersist: saving tun context:" << std::endl << tun_persist->options()); - - // enable tun_setup destructor - tun_persist->add_destructor(tun_setup); - - // assert ownership over TAP device handle - tun_setup->confirm(); - } - - openvpn_io::post(io_context, [self=Ptr(this)](){ - self->read(); - }); - - parent.tun_connected(); // signal that we are connected - } - catch (const std::exception& e) - { - stop(); - Error::Type err = Error::TUN_SETUP_FAILED; - const ExceptionCode* ec = dynamic_cast<const ExceptionCode*>(&e); - if (ec && ec->code_defined()) - err = ec->code(); - parent.tun_error(err, e.what()); - } - } - - void stop() override - { - if (!halt) - { - halt = true; - - tun_persist.reset(); - } - } - - void set_disconnect() override - { - - } - - bool tun_send(BufferAllocated& buf) override - { - TUN_RING* receive_ring = ring_buffer->receive_ring(); - - ULONG head = receive_ring->head.load(std::memory_order_acquire); - if (head > WINTUN_RING_CAPACITY) - { - if (head == 0xFFFFFFFF) - parent.tun_error(Error::TUN_WRITE_ERROR, "invalid ring head/tail or bogus packet received"); - return false; - } - - ULONG tail = receive_ring->tail.load(std::memory_order_acquire); - if (tail >= WINTUN_RING_CAPACITY) - return false; - - ULONG aligned_packet_size = packet_align(sizeof(TUN_PACKET_HEADER) + buf.size()); - ULONG buf_space = wrap(head - tail - WINTUN_PACKET_ALIGN); - if (aligned_packet_size > buf_space) - { - OPENVPN_LOG("ring is full"); - return false; - } - - // copy packet size and data into ring - TUN_PACKET* packet = (TUN_PACKET*)& receive_ring->data[tail]; - packet->size = buf.size(); - std::memcpy(packet->data, buf.data(), buf.size()); - - // move ring tail - receive_ring->tail.store(wrap(tail + aligned_packet_size), std::memory_order_release); - if (receive_ring->alertable.load(std::memory_order_acquire) != 0) - SetEvent(ring_buffer->receive_ring_tail_moved()); - - return true; - } - - std::string tun_name() const override - { - return "wintun"; - } - - std::string vpn_ip4() const override - { - if (state->vpn_ip4_addr.specified()) - return state->vpn_ip4_addr.to_string(); - else - return ""; - } - - std::string vpn_ip6() const override - { - if (state->vpn_ip6_addr.specified()) - return state->vpn_ip6_addr.to_string(); - else - return ""; - } - - std::string vpn_gw4() const override - { - if (state->vpn_ip4_gw.specified()) - return state->vpn_ip4_gw.to_string(); - else - return ""; - } - - std::string vpn_gw6() const override - { - if (state->vpn_ip6_gw.specified()) - return state->vpn_ip6_gw.to_string(); - else - return ""; - } - - private: - void read() - { - TUN_RING* send_ring = ring_buffer->send_ring(); - - if (halt) - return; - - ULONG head = send_ring->head.load(std::memory_order_acquire); - if (head >= WINTUN_RING_CAPACITY) - { - parent.tun_error(Error::TUN_ERROR, "ring head exceeds ring capacity"); - return; - } - - ULONG tail = send_ring->tail.load(std::memory_order_acquire); - if (tail >= WINTUN_RING_CAPACITY) - { - parent.tun_error(Error::TUN_ERROR, "ring tail exceeds ring capacity"); - return; - } - - while (true) - { - // tail has moved? - if (head == tail) - { - ring_buffer->send_tail_moved_asio_event().async_wait([self = Ptr(this)](const openvpn_io::error_code& error) { - if (!error) - self->read(); - else - { - if (!self->halt) - self->parent.tun_error(Error::TUN_ERROR, "error waiting on ring send tail moved"); - } - }); - return; - } - - // read buffer content - ULONG content_len = wrap(tail - head); - if (content_len < sizeof(TUN_PACKET_HEADER)) - { - parent.tun_error(Error::TUN_ERROR, "incomplete packet header in send ring"); - return; - } - - TUN_PACKET* packet = (TUN_PACKET *)&send_ring->data[head]; - if (packet->size > WINTUN_MAX_PACKET_SIZE) - { - parent.tun_error(Error::TUN_ERROR, "packet too big in send ring"); - return; - } - - ULONG aligned_packet_size = packet_align(sizeof(TUN_PACKET_HEADER) + packet->size); - if (aligned_packet_size > content_len) - { - parent.tun_error(Error::TUN_ERROR, "incomplete packet in send ring"); - return; - } - - frame->prepare(Frame::READ_TUN, buf); - - buf.write(packet->data, packet->size); - - head = wrap(head + aligned_packet_size); - send_ring->head.store(head, std::memory_order_release); - - parent.tun_recv(buf); - - if (halt) - return; - } - } - - struct TUN_PACKET_HEADER - { - uint32_t size; - }; - - struct TUN_PACKET - { - uint32_t size; - UCHAR data[WINTUN_MAX_PACKET_SIZE]; - }; - - ULONG packet_align(ULONG size) - { - return (size + (WINTUN_PACKET_ALIGN - 1)) & ~(WINTUN_PACKET_ALIGN - 1); - } - - ULONG wrap(ULONG value) - { - return value & (WINTUN_RING_CAPACITY - 1); - } - - openvpn_io::io_context& io_context; - TunPersist::Ptr tun_persist; // contains the TAP device HANDLE - ClientConfig::Ptr config; - TunClientParent& parent; - TunProp::State::Ptr state; - TunWin::SetupBase::Ptr tun_setup; - - BufferAllocated buf; - - Frame::Ptr frame; - - bool halt = false; - - ScopedHANDLE driver_handle; - - RingBuffer::Ptr ring_buffer; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/tun/win/nrpt.hpp b/Sources/OpenVPN3/openvpn/tun/win/nrpt.hpp deleted file mode 100644 index 0bcd5cb..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/nrpt.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// 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-2020 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/>. -// - -// Name Resolution Policy Table (NRPT) utilities for Windows - -#ifndef OPENVPN_TUN_WIN_NRPT_H -#define OPENVPN_TUN_WIN_NRPT_H - -#include <string> -#include <sstream> -#include <vector> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/win/reg.hpp> -#include <openvpn/win/winerr.hpp> - -namespace openvpn { - namespace TunWin { - - // NRPT rules described here: https://msdn.microsoft.com/en-us/library/ff957356.aspx - class NRPT - { - public: - OPENVPN_EXCEPTION(nrpt_error); - - static void create_rule(const std::vector<std::string> names, const std::vector<std::string> dns_servers) - { - Win::RegKey key; - - for (size_t i = 0; i < names.size(); ++ i) - { - // open/create the key - { - std::ostringstream ss; - ss << dnsPolicyConfig() << "\\" << policyPrefix() << "-" << i; - auto key_name = ss.str(); - - const LONG status = ::RegCreateKeyA(HKEY_LOCAL_MACHINE, key_name.c_str(), key.ref()); - check_reg_error<nrpt_error>(status, key_name); - } - - // Name - { - std::wstring name(wstring::from_utf8(names[i])); - name += L'\0'; - const LONG status = ::RegSetValueExW(key(), - L"Name", - 0, - REG_MULTI_SZ, - (const BYTE *)name.c_str(), - (name.length()+1)*2); - check_reg_error<nrpt_error>(status, "Name"); - } - - // GenericDNSServers - { - const std::wstring dns_servers_joined = wstring::from_utf8(string::join(dns_servers, ";")); - const LONG status = ::RegSetValueExW(key(), - L"GenericDNSServers", - 0, - REG_SZ, - (const BYTE *)dns_servers_joined.c_str(), - (dns_servers_joined.length()+1)*2); - check_reg_error<nrpt_error>(status, "GenericDNSServers"); - } - - // ConfigOptions - { - const DWORD value = 0x8; // Only the Generic DNS server option (that is, the option defined in section 2.2.2.13) is specified. - const LONG status = ::RegSetValueExW(key(), - L"ConfigOptions", - 0, - REG_DWORD, - (const BYTE *)&value, - sizeof(value)); - check_reg_error<nrpt_error>(status, "ConfigOptions"); - } - - // Version - { - const DWORD value = 0x2; - const LONG status = ::RegSetValueExW(key(), - L"Version", - 0, - REG_DWORD, - (const BYTE *)&value, - sizeof(value)); - check_reg_error<nrpt_error>(status, "Version"); - } - } - } - - static bool delete_rule() - { - Win::RegKeyEnumerator keys(HKEY_LOCAL_MACHINE, dnsPolicyConfig()); - - for (const auto& key : keys) - { - // remove only own policies - if (key.find(policyPrefix()) == std::string::npos) - continue; - - std::ostringstream ss; - ss << dnsPolicyConfig() << "\\" << key; - auto path = ss.str(); - ::RegDeleteTreeA(HKEY_LOCAL_MACHINE, path.c_str()); - } - - return true; - } - - private: - static const char *dnsPolicyConfig() - { - static const char subkey[] = "SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\DnsPolicyConfig"; - return subkey; - } - - static const char *policyPrefix() - { - static const char prefix[] = "OpenVPNDNSRouting"; - return prefix; - } - - public: - class ActionCreate : public Action - { - public: - ActionCreate(const std::vector<std::string>& names_arg, - const std::vector<std::string>& dns_servers_arg) - : names(names_arg), - dns_servers(dns_servers_arg) - { - } - - virtual void execute(std::ostream& log) override - { - log << to_string() << std::endl; - create_rule(names, dns_servers); - } - - virtual std::string to_string() const override - { - std::ostringstream os; - os << "NRPT::ActionCreate" - << " names=[" << string::join(names, ",") << "]" - << " dns_servers=[" << string::join(dns_servers, ",") << "]"; - return os.str(); - } - - private: - const std::vector<std::string> names; - const std::vector<std::string> dns_servers; - }; - - class ActionDelete : public Action - { - public: - virtual void execute(std::ostream& log) override - { - log << to_string() << std::endl; - delete_rule(); - } - - virtual std::string to_string() const override - { - return "NRPT::ActionDelete"; - } - }; - - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/ringbuffer.hpp b/Sources/OpenVPN3/openvpn/tun/win/ringbuffer.hpp deleted file mode 100644 index 9bb7e60..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/ringbuffer.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// 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-2020 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 <windows.h> - -#include <string> -#include <type_traits> - -#include <openvpn/buffer/bufhex.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/event.hpp> - -#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) -#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) - -#define WINTUN_RING_CAPACITY 0x800000 -#define WINTUN_RING_TRAILING_BYTES 0x10000 -#define WINTUN_RING_FRAMING_SIZE 12 -#define WINTUN_MAX_PACKET_SIZE 0xffff -#define WINTUN_PACKET_ALIGN 4 - -namespace openvpn -{ - namespace TunWin - { - struct TUN_RING { - std::atomic_ulong head; - std::atomic_ulong tail; - std::atomic_long alertable; - UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES + WINTUN_RING_FRAMING_SIZE]; - }; - - struct TUN_REGISTER_RINGS - { - struct - { - ULONG ring_size; - TUN_RING* ring; - HANDLE tail_moved; - } send, receive; - }; - - typedef openvpn_io::windows::object_handle AsioEvent; - - class RingBuffer : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<RingBuffer> Ptr; - - RingBuffer(openvpn_io::io_context& io_context) - : send_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)), - receive_ring_hmem(CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TUN_RING), NULL)), - send_tail_moved_asio_event_(io_context) - { - // sanity checks - static_assert((sizeof(TUN_RING) - sizeof(TUN_RING::data)) == 12, "sizeof(TUN_RING) is expected to be 12"); -#if !defined(ATOMIC_LONG_LOCK_FREE) || (ATOMIC_LONG_LOCK_FREE != 2) -#error Atomic long is expected to be always lock-free -#endif - - send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); - receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); - - HANDLE handle; - DuplicateHandle(GetCurrentProcess(), send_ring_tail_moved_(), - GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - send_tail_moved_asio_event_.assign(handle); - } - - RingBuffer(openvpn_io::io_context& io_context, - HANDLE client_process, - const std::string& send_ring_hmem_hex, - const std::string& receive_ring_hmem_hex, - const std::string& send_ring_tail_moved_hex, - const std::string& receive_ring_tail_moved_hex) - : send_tail_moved_asio_event_(io_context) - { - HANDLE remote_handle = BufHex::parse<HANDLE>(send_ring_hmem_hex, "send_ring_hmem"); - HANDLE handle; - DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - send_ring_hmem.reset(handle); - - remote_handle = BufHex::parse<HANDLE>(receive_ring_hmem_hex, "receive_ring_hmem"); - DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - receive_ring_hmem.reset(handle); - - remote_handle = BufHex::parse<HANDLE>(send_ring_tail_moved_hex, "send_ring_tail_moved"); - DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - send_ring_tail_moved_.reset(handle); - - remote_handle = BufHex::parse<HANDLE>(receive_ring_tail_moved_hex, "receive_ring_tail_moved"); - DuplicateHandle(client_process, remote_handle, GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - receive_ring_tail_moved_.reset(handle); - - send_ring_ = (TUN_RING*)MapViewOfFile(send_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); - receive_ring_ = (TUN_RING*)MapViewOfFile(receive_ring_hmem(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(TUN_RING)); - } - - RingBuffer(RingBuffer const&) = delete; - RingBuffer& operator=(RingBuffer const&) = delete; - - ~RingBuffer() - { - UnmapViewOfFile(send_ring_); - UnmapViewOfFile(receive_ring_); - } - - HANDLE send_ring_tail_moved() - { - return send_ring_tail_moved_(); - } - - HANDLE receive_ring_tail_moved() - { - return receive_ring_tail_moved_(); - } - - TUN_RING* send_ring() - { - return send_ring_; - } - - TUN_RING* receive_ring() - { - return receive_ring_; - } - - AsioEvent& send_tail_moved_asio_event() - { - return send_tail_moved_asio_event_; - } - -#ifdef HAVE_JSON - void serialize(Json::Value& json) - { - json["send_ring_hmem"] = BufHex::render(send_ring_hmem()); - json["receive_ring_hmem"] = BufHex::render(receive_ring_hmem()); - json["send_ring_tail_moved"] = BufHex::render(send_ring_tail_moved()); - json["receive_ring_tail_moved"] = BufHex::render(receive_ring_tail_moved()); - } -#endif - - protected: - Win::ScopedHANDLE send_ring_hmem; - Win::ScopedHANDLE receive_ring_hmem; - Win::Event send_ring_tail_moved_{FALSE}; - Win::Event receive_ring_tail_moved_{FALSE}; - AsioEvent send_tail_moved_asio_event_; - - TUN_RING* send_ring_ = nullptr; - TUN_RING* receive_ring_ = nullptr; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/tun/win/tunutil.hpp b/Sources/OpenVPN3/openvpn/tun/win/tunutil.hpp deleted file mode 100644 index 73c238e..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/tunutil.hpp +++ /dev/null @@ -1,1443 +0,0 @@ -// 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-2020 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/>. - -// tun interface utilities for Windows - -#ifndef OPENVPN_TUN_WIN_TUNUTIL_H -#define OPENVPN_TUN_WIN_TUNUTIL_H - -#include <openvpn/common/socktypes.hpp> // prevent winsock multiple def errors - -#include <windows.h> -#include <winsock2.h> // for IPv6 -#include <winioctl.h> -#include <iphlpapi.h> -#include <ntddndis.h> -#include <wininet.h> -#include <ws2tcpip.h> // for IPv6 -#include <tlhelp32.h> // for impersonating as LocalSystem - - -#include <setupapi.h> -#include <devguid.h> -#include <cfgmgr32.h> - -#ifdef __MINGW32__ -#include <ddk/ndisguid.h> -#else -#include <ndisguid.h> -#endif - -#include <string> -#include <vector> -#include <sstream> -#include <cstdint> // for std::uint32_t -#include <memory> - -#include <tap-windows.h> - -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/stringize.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/common/uniqueptr.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/tun/builder/capture.hpp> -#include <openvpn/win/reg.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/unicode.hpp> -#include <openvpn/win/cmd.hpp> -#include <openvpn/win/winerr.hpp> - -namespace openvpn { - namespace TunWin { - namespace Util { - OPENVPN_EXCEPTION(tun_win_util); - - namespace { - // from tap-windows.h - const char ADAPTER[] = ADAPTER_KEY; // CONST GLOBAL - const char NETWORK_CONNECTIONS[] = NETWORK_CONNECTIONS_KEY; // CONST GLOBAL - - // generally defined on cl command line - const char COMPONENT_ID[] = OPENVPN_STRINGIZE(TAP_WIN_COMPONENT_ID); // CONST GLOBAL - const char WINTUN_COMPONENT_ID[] = "wintun"; // CONST GLOBAL - - const char ROOT_COMPONENT_ID[] = "root\\" OPENVPN_STRINGIZE(TAP_WIN_COMPONENT_ID); - const char ROOT_WINTUN_COMPONENT_ID[] = "root\\wintun"; - } - - using TapGuidLuid = std::pair<std::string, DWORD>; - - // Return a list of TAP device GUIDs installed on the system, - // filtered by TAP_WIN_COMPONENT_ID. - inline std::vector<TapGuidLuid> tap_guids(bool wintun) - { - LONG status; - DWORD len; - DWORD data_type; - - std::vector<TapGuidLuid> ret; - - Win::RegKey adapter_key; - status = ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, - ADAPTER, - 0, - KEY_READ, - adapter_key.ref()); - if (status != ERROR_SUCCESS) - { - const Win::Error err(status); - OPENVPN_THROW(tun_win_util, "tap_guids: error opening adapter registry key: " << ADAPTER << " : " << err.message()); - } - - for (int i = 0;; ++i) - { - char strbuf[256]; - Win::RegKey unit_key; - - len = sizeof(strbuf); - status = ::RegEnumKeyExA(adapter_key(), - i, - strbuf, - &len, - nullptr, - nullptr, - nullptr, - nullptr); - if (status == ERROR_NO_MORE_ITEMS) - break; - else if (status != ERROR_SUCCESS) - OPENVPN_THROW(tun_win_util, "tap_guids: error enumerating registry subkeys of key: " << ADAPTER); - strbuf[len] = '\0'; - - const std::string unit_string = std::string(ADAPTER) - + std::string("\\") - + std::string(strbuf); - - status = ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, - unit_string.c_str(), - 0, - KEY_READ, - unit_key.ref()); - - if (status != ERROR_SUCCESS) - continue; - - len = sizeof(strbuf); - status = ::RegQueryValueExA(unit_key(), - "ComponentId", - nullptr, - &data_type, - (LPBYTE)strbuf, - &len); - - if (status != ERROR_SUCCESS || data_type != REG_SZ) - continue; - strbuf[len] = '\0'; - if (string::strcasecmp(strbuf, wintun ? WINTUN_COMPONENT_ID : COMPONENT_ID) && - string::strcasecmp(strbuf, wintun ? ROOT_WINTUN_COMPONENT_ID : ROOT_COMPONENT_ID)) - continue; - - TapGuidLuid tgl; - - len = sizeof(strbuf); - status = ::RegQueryValueExA(unit_key(), - "NetCfgInstanceId", - nullptr, - &data_type, - (LPBYTE)strbuf, - &len); - - if (status == ERROR_SUCCESS && data_type == REG_SZ) - { - strbuf[len] = '\0'; - tgl.first = std::string(strbuf); - } - - DWORD luid; - len = sizeof(luid); - status = ::RegQueryValueExA(unit_key(), - "NetLuidIndex", - nullptr, - &data_type, - (LPBYTE)&luid, - &len); - - if (status == ERROR_SUCCESS && data_type == REG_DWORD) - { - tgl.second = luid; - } - - ret.push_back(tgl); - } - return ret; - } - - struct TapNameGuidPair - { - TapNameGuidPair() : index(DWORD(-1)) {} - - bool index_defined() const { return index != DWORD(-1); } - - std::string index_or_name() const - { - if (index_defined()) - return to_string(index); - else if (!name.empty()) - return '"' + name + '"'; - else - OPENVPN_THROW(tun_win_util, "TapNameGuidPair: TAP interface " << guid << " has no name or interface index"); - } - - std::string name; - std::string guid; - DWORD net_luid_index; - DWORD index; - }; - - struct TapNameGuidPairList : public std::vector<TapNameGuidPair> - { - TapNameGuidPairList(bool wintun) - { - // first get the TAP guids - { - std::vector<TapGuidLuid> guids = tap_guids(wintun); - for (auto i = guids.begin(); i != guids.end(); i++) - { - TapNameGuidPair pair; - pair.guid = i->first; - pair.net_luid_index = i->second; - - // lookup adapter index - { - ULONG aindex; - const size_t len = 128; - wchar_t wbuf[len]; - _snwprintf(wbuf, len, L"\\DEVICE\\TCPIP_%S", pair.guid.c_str()); - wbuf[len-1] = 0; - if (::GetAdapterIndex(wbuf, &aindex) == NO_ERROR) - pair.index = aindex; - } - - push_back(pair); - } - } - - // next, match up control panel interface names with GUIDs - { - LONG status; - DWORD len; - DWORD data_type; - - Win::RegKey network_connections_key; - status = ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, - NETWORK_CONNECTIONS, - 0, - KEY_READ, - network_connections_key.ref()); - if (status != ERROR_SUCCESS) - { - const Win::Error err(status); - OPENVPN_THROW(tun_win_util, "TapNameGuidPairList: error opening network connections registry key: " << NETWORK_CONNECTIONS << " : " << err.message()); - } - - for (int i = 0;; ++i) - { - char strbuf[256]; - Win::RegKey connection_key; - - len = sizeof(strbuf); - status = ::RegEnumKeyExA(network_connections_key(), - i, - strbuf, - &len, - nullptr, - nullptr, - nullptr, - nullptr); - if (status == ERROR_NO_MORE_ITEMS) - break; - else if (status != ERROR_SUCCESS) - OPENVPN_THROW(tun_win_util, "TapNameGuidPairList: error enumerating registry subkeys of key: " << NETWORK_CONNECTIONS); - strbuf[len] = '\0'; - - const std::string guid = std::string(strbuf); - const std::string connection_string = std::string(NETWORK_CONNECTIONS) + std::string("\\") + guid + std::string("\\Connection"); - - status = ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, - connection_string.c_str(), - 0, - KEY_READ, - connection_key.ref()); - if (status != ERROR_SUCCESS) - continue; - - wchar_t wbuf[256] = L""; - DWORD cbwbuf = sizeof(wbuf); - status = ::RegQueryValueExW(connection_key(), - L"Name", - nullptr, - &data_type, - (LPBYTE)wbuf, - &cbwbuf); - if (status != ERROR_SUCCESS || data_type != REG_SZ) - continue; - wbuf[(cbwbuf / sizeof(wchar_t)) - 1] = L'\0'; - - // iterate through self and try to patch the name - { - for (iterator j = begin(); j != end(); j++) - { - TapNameGuidPair& pair = *j; - if (pair.guid == guid) - pair.name = wstring::to_utf8(wbuf); - } - } - } - } - } - - std::string to_string() const - { - std::ostringstream os; - for (const_iterator i = begin(); i != end(); i++) - { - const TapNameGuidPair& pair = *i; - os << "guid='" << pair.guid << '\''; - if (pair.index_defined()) - os << " index=" << pair.index; - if (!pair.name.empty()) - os << " name='" << pair.name << '\''; - os << std::endl; - } - return os.str(); - } - - std::string name_from_guid(const std::string& guid) const - { - for (const_iterator i = begin(); i != end(); i++) - { - const TapNameGuidPair& pair = *i; - if (pair.guid == guid) - return pair.name; - } - } - - std::string guid_from_name(const std::string& name) const - { - for (const_iterator i = begin(); i != end(); i++) - { - const TapNameGuidPair& pair = *i; - if (pair.name == name) - return pair.guid; - } - } - }; - - struct DeviceInstanceIdInterfacePair - { - std::string net_cfg_instance_id; - std::string device_interface_list; - }; - - class DevInfoSetHelper - { - public: - DevInfoSetHelper() - { - handle = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); - } - - bool is_valid() - { - return handle != INVALID_HANDLE_VALUE; - } - - operator HDEVINFO() - { - return handle; - } - - ~DevInfoSetHelper() - { - if (is_valid()) - { - SetupDiDestroyDeviceInfoList(handle); - } - } - - private: - HDEVINFO handle; - }; - - struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterfacePair> - { - DeviceInstanceIdInterfaceList() - { - DevInfoSetHelper device_info_set; - if (!device_info_set.is_valid()) - return; - - for (DWORD i = 0;; ++i) - { - SP_DEVINFO_DATA dev_info_data; - ZeroMemory(&dev_info_data, sizeof(SP_DEVINFO_DATA)); - dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); - BOOL res = SetupDiEnumDeviceInfo(device_info_set, i, &dev_info_data); - if (!res) - { - if (GetLastError() == ERROR_NO_MORE_ITEMS) - break; - else - continue; - } - - Win::RegKey regkey; - *regkey.ref() = SetupDiOpenDevRegKey(device_info_set, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE); - if (!regkey.defined()) - continue; - - std::string str_net_cfg_instance_id; - - DWORD size; - LONG status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, NULL, &size); - if (status != ERROR_SUCCESS) - continue; - BufferAllocatedType<char, thread_unsafe_refcount> buf_net_cfg_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); - - status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, (LPBYTE)buf_net_cfg_inst_id.data(), &size); - if (status == ERROR_SUCCESS) - { - buf_net_cfg_inst_id.data()[size - 1] = '\0'; - str_net_cfg_instance_id = std::string(buf_net_cfg_inst_id.data()); - } - else - continue; - - res = SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, NULL, 0, &size); - if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - continue; - - BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); - if (!SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, buf_dev_inst_id.data(), size, &size)) - continue; - buf_dev_inst_id.set_size(size); - - ULONG dev_interface_list_size = 0; - CONFIGRET cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size, - (LPGUID)& GUID_DEVINTERFACE_NET, - buf_dev_inst_id.data(), - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - - if (cr != CR_SUCCESS) - continue; - - BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_iface_list(dev_interface_list_size, BufferAllocated::CONSTRUCT_ZERO); - cr = CM_Get_Device_Interface_List((LPGUID)& GUID_DEVINTERFACE_NET, buf_dev_inst_id.data(), - buf_dev_iface_list.data(), - dev_interface_list_size, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (cr != CR_SUCCESS) - continue; - - DeviceInstanceIdInterfacePair pair; - pair.net_cfg_instance_id = str_net_cfg_instance_id; - pair.device_interface_list = std::string(buf_dev_iface_list.data()); - push_back(pair); - } - } - }; - - // given a TAP GUID, form the pathname of the TAP device node - inline std::string tap_path(const TapNameGuidPair& tap) - { - return std::string(USERMODEDEVICEDIR) + tap.guid + std::string(TAP_WIN_SUFFIX); - } - - // open an available TAP adapter - inline HANDLE tap_open(const TapNameGuidPairList& guids, - std::string& path_opened, - TapNameGuidPair& used, - bool wintun) - { - Win::ScopedHANDLE hand; - - std::unique_ptr<DeviceInstanceIdInterfaceList> inst_id_interface_list; - if (wintun) - inst_id_interface_list.reset(new DeviceInstanceIdInterfaceList()); - - // iterate over list of TAP adapters on system - for (TapNameGuidPairList::const_iterator i = guids.begin(); i != guids.end(); i++) - { - const TapNameGuidPair& tap = *i; - - std::string path; - - if (wintun) - { - for (const auto& inst_id_interface : *inst_id_interface_list) - { - if (inst_id_interface.net_cfg_instance_id != tap.guid) - continue; - - path = inst_id_interface.device_interface_list; - break; - } - } - else - { - path = tap_path(tap); - } - - if (path.length() > 0) - { - hand.reset(::CreateFileA(path.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, /* was: FILE_SHARE_READ */ - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, - 0)); - - if (hand.defined()) - { - used = tap; - path_opened = path; - break; - } - } - } - return hand.release(); - } - - // set TAP adapter to topology subnet - inline void tap_configure_topology_subnet(HANDLE th, const IP::Addr& local, const unsigned int prefix_len) - { - const IPv4::Addr netmask = IPv4::Addr::netmask_from_prefix_len(prefix_len); - const IPv4::Addr network = local.to_ipv4() & netmask; - - std::uint32_t ep[3]; - ep[0] = htonl(local.to_ipv4().to_uint32()); - ep[1] = htonl(network.to_uint32()); - ep[2] = htonl(netmask.to_uint32()); - - DWORD len; - if (!::DeviceIoControl(th, TAP_WIN_IOCTL_CONFIG_TUN, - ep, sizeof (ep), - ep, sizeof (ep), &len, nullptr)) - throw tun_win_util("DeviceIoControl TAP_WIN_IOCTL_CONFIG_TUN failed"); - } - - // set TAP adapter to topology net30 - inline void tap_configure_topology_net30(HANDLE th, const IP::Addr& local_addr, const IP::Addr& remote_addr) - { - const IPv4::Addr local = local_addr.to_ipv4(); - const IPv4::Addr remote = remote_addr.to_ipv4(); - - std::uint32_t ep[2]; - ep[0] = htonl(local.to_uint32()); - ep[1] = htonl(remote.to_uint32()); - - DWORD len; - if (!::DeviceIoControl(th, TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT, - ep, sizeof (ep), - ep, sizeof (ep), &len, nullptr)) - throw tun_win_util("DeviceIoControl TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT failed"); - } - - // set driver media status to 'connected' - inline void tap_set_media_status(HANDLE th, bool media_status) - { - DWORD len; - ULONG status = media_status ? TRUE : FALSE; - if (!::DeviceIoControl(th, TAP_WIN_IOCTL_SET_MEDIA_STATUS, - &status, sizeof (status), - &status, sizeof (status), &len, nullptr)) - throw tun_win_util("DeviceIoControl TAP_WIN_IOCTL_SET_MEDIA_STATUS failed"); - } - - // get debug logging from TAP driver (requires that - // TAP driver was built with logging enabled) - inline void tap_process_logging(HANDLE th) - { - const size_t size = 1024; - std::unique_ptr<char[]> line(new char[size]); - DWORD len; - - while (::DeviceIoControl(th, TAP_WIN_IOCTL_GET_LOG_LINE, - line.get(), size, - line.get(), size, - &len, nullptr)) - { - OPENVPN_LOG("TAP-Windows: " << line.get()); - } - } - - struct InterfaceInfoList - { - public: - InterfaceInfoList() - { - DWORD size = 0; - if (::GetInterfaceInfo(nullptr, &size) != ERROR_INSUFFICIENT_BUFFER) - OPENVPN_THROW(tun_win_util, "InterfaceInfoList: GetInterfaceInfo #1"); - list.reset((IP_INTERFACE_INFO*)new unsigned char[size]); - if (::GetInterfaceInfo(list.get(), &size) != NO_ERROR) - OPENVPN_THROW(tun_win_util, "InterfaceInfoList: GetInterfaceInfo #2"); - } - - IP_ADAPTER_INDEX_MAP* iface(const DWORD index) const - { - if (list) - { - for (LONG i = 0; i < list->NumAdapters; ++i) - { - IP_ADAPTER_INDEX_MAP* inter = &list->Adapter[i]; - if (index == inter->Index) - return inter; - } - } - return nullptr; - } - - std::unique_ptr<IP_INTERFACE_INFO> list; - }; - - inline void dhcp_release(const InterfaceInfoList& ii, - const DWORD adapter_index, - std::ostream& os) - { - IP_ADAPTER_INDEX_MAP* iface = ii.iface(adapter_index); - if (iface) - { - const DWORD status = ::IpReleaseAddress(iface); - if (status == NO_ERROR) - os << "TAP: DHCP release succeeded" << std::endl; - else - os << "TAP: DHCP release failed" << std::endl; - } - } - - inline void dhcp_renew(const InterfaceInfoList& ii, - const DWORD adapter_index, - std::ostream& os) - { - IP_ADAPTER_INDEX_MAP* iface = ii.iface(adapter_index); - if (iface) - { - const DWORD status = ::IpRenewAddress(iface); - if (status == NO_ERROR) - os << "TAP: DHCP renew succeeded" << std::endl; - else - os << "TAP: DHCP renew failed" << std::endl; - } - } - - inline void flush_arp(const DWORD adapter_index, - std::ostream& os) - { - const DWORD status = ::FlushIpNetTable2(AF_INET, adapter_index); - if (status == NO_ERROR) - os << "TAP: ARP flush succeeded" << std::endl; - else - os << "TAP: ARP flush failed" << std::endl; - } - - struct IPNetmask4 - { - IPNetmask4() {} - - IPNetmask4(const TunBuilderCapture& pull, const char *title) - { - const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4(); - if (local4) - { - ip = IPv4::Addr::from_string(local4->address, title); - netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length); - } - } - - IPNetmask4(const IP_ADDR_STRING *ias) - { - if (ias) - { - try { - if (ias->IpAddress.String) - ip = IPv4::Addr::from_string(ias->IpAddress.String); - } - catch (const std::exception&) - { - } - try { - if (ias->IpMask.String) - netmask = IPv4::Addr::from_string(ias->IpMask.String); - } - catch (const std::exception&) - { - } - } - } - - bool operator==(const IPNetmask4& rhs) const - { - return ip == rhs.ip && netmask == rhs.netmask; - } - - bool operator!=(const IPNetmask4& rhs) const - { - return !operator==(rhs); - } - - IPv4::Addr ip = IPv4::Addr::from_zero(); - IPv4::Addr netmask = IPv4::Addr::from_zero(); - }; - - struct IPAdaptersInfo - { - IPAdaptersInfo() - { - ULONG size = 0; - if (::GetAdaptersInfo(nullptr, &size) != ERROR_BUFFER_OVERFLOW) - OPENVPN_THROW(tun_win_util, "IPAdaptersInfo: GetAdaptersInfo #1"); - list.reset((IP_ADAPTER_INFO*)new unsigned char[size]); - if (::GetAdaptersInfo(list.get(), &size) != NO_ERROR) - OPENVPN_THROW(tun_win_util, "IPAdaptersInfo: GetAdaptersInfo #2"); - } - - const IP_ADAPTER_INFO* adapter(const DWORD index) const - { - if (list) - { - for (const IP_ADAPTER_INFO* a = list.get(); a != nullptr; a = a->Next) - { - if (index == a->Index) - return a; - } - } - return nullptr; - } - - bool is_up(const DWORD index, const IPNetmask4& vpn_addr) const - { - const IP_ADAPTER_INFO* ai = adapter(index); - if (ai) - { - for (const IP_ADDR_STRING *iplist = &ai->IpAddressList; iplist != nullptr; iplist = iplist->Next) - { - if (vpn_addr == IPNetmask4(iplist)) - return true; - } - } - return false; - } - - bool is_dhcp_enabled(const DWORD index) const - { - const IP_ADAPTER_INFO* ai = adapter(index); - return ai && ai->DhcpEnabled; - } - - std::unique_ptr<IP_ADAPTER_INFO> list; - }; - - struct IPPerAdapterInfo - { - IPPerAdapterInfo(const DWORD index) - { - ULONG size = 0; - if (::GetPerAdapterInfo(index, nullptr, &size) != ERROR_BUFFER_OVERFLOW) - return; - adapt.reset((IP_PER_ADAPTER_INFO*)new unsigned char[size]); - if (::GetPerAdapterInfo(index, adapt.get(), &size) != ERROR_SUCCESS) - adapt.reset(); - } - - std::unique_ptr<IP_PER_ADAPTER_INFO> adapt; - }; - - // Use the TAP DHCP masquerade capability to set TAP adapter properties. - // Generally only used on pre-Vista. - class TAPDHCPMasquerade - { - public: - OPENVPN_EXCEPTION(dhcp_masq); - - // VPN IP/netmask - IPNetmask4 vpn; - - // IP address of fake DHCP server in TAP adapter - IPv4::Addr dhcp_serv_addr = IPv4::Addr::from_zero(); - - // DHCP lease for one year - unsigned int lease_time = 31536000; - - // DHCP options - std::string domain; // DOMAIN (15) - std::string netbios_scope; // NBS (47) - int netbios_node_type = 0; // NBT 1,2,4,8 (46) - bool disable_nbt = false; // DISABLE_NBT (43, Vendor option 001) - std::vector<IPv4::Addr> dns; // DNS (6) - std::vector<IPv4::Addr> wins; // WINS (44) - std::vector<IPv4::Addr> ntp; // NTP (42) - std::vector<IPv4::Addr> nbdd; // NBDD (45) - - void init_from_capture(const TunBuilderCapture& pull) - { - // VPN IP/netmask - vpn = IPNetmask4(pull, "VPN IP"); - - // DHCP server address - { - const IPv4::Addr network_addr = vpn.ip & vpn.netmask; - const std::uint32_t extent = vpn.netmask.extent_from_netmask_uint32(); - if (extent >= 16) - dhcp_serv_addr = network_addr + (extent - 2); - else - dhcp_serv_addr = network_addr; - } - - // DNS - for (auto &ds : pull.dns_servers) - { - if (!ds.ipv6) - dns.push_back(IPv4::Addr::from_string(ds.address, "DNS Server")); - } - - // WINS - for (auto &ws : pull.wins_servers) - wins.push_back(IPv4::Addr::from_string(ws.address, "WINS Server")); - - // DOMAIN - if (!pull.search_domains.empty()) - domain = pull.search_domains[0].domain; - } - - void ioctl(HANDLE th) const - { - // TAP_WIN_IOCTL_CONFIG_DHCP_MASQ - { - std::uint32_t ep[4]; - ep[0] = vpn.ip.to_uint32_net(); - ep[1] = vpn.netmask.to_uint32_net(); - ep[2] = dhcp_serv_addr.to_uint32_net(); - ep[3] = lease_time; - - DWORD len; - if (!::DeviceIoControl(th, TAP_WIN_IOCTL_CONFIG_DHCP_MASQ, - ep, sizeof (ep), - ep, sizeof (ep), &len, nullptr)) - throw dhcp_masq("DeviceIoControl TAP_WIN_IOCTL_CONFIG_DHCP_MASQ failed"); - } - - // TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT - { - BufferAllocated buf(256, BufferAllocated::GROW); - write_options(buf); - - DWORD len; - if (!::DeviceIoControl(th, TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT, - buf.data(), buf.size(), - buf.data(), buf.size(), &len, nullptr)) - throw dhcp_masq("DeviceIoControl TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT failed"); - } - } - - private: - void write_options(Buffer& buf) const - { - // DOMAIN - write_dhcp_str(buf, 15, domain); - - // NBS - write_dhcp_str(buf, 47, netbios_scope); - - // NBT - if (netbios_node_type) - write_dhcp_u8(buf, 46, netbios_node_type); - - // DNS - write_dhcp_addr_list(buf, 6, dns); - - // WINS - write_dhcp_addr_list(buf, 44, wins); - - // NTP - write_dhcp_addr_list(buf, 42, ntp); - - // NBDD - write_dhcp_addr_list(buf, 45, nbdd); - - // DISABLE_NBT - // - // The MS DHCP server option 'Disable Netbios-over-TCP/IP - // is implemented as vendor option 001, value 002. - // A value of 001 means 'leave NBT alone' which is the default. - if (disable_nbt) - { - buf.push_back(43); - buf.push_back(6); // total length field - buf.push_back(0x001); - buf.push_back(4); // length of the vendor-specified field - { - const std::uint32_t raw = 0x002; - buf.write((const unsigned char *)&raw, sizeof(raw)); - } - } - } - - static void write_dhcp_u8(Buffer& buf, - const unsigned char type, - const unsigned char data) - { - buf.push_back(type); - buf.push_back(1); - buf.push_back(data); - } - - static void write_dhcp_str(Buffer& buf, - const unsigned char type, - const std::string& str) - { - const size_t len = str.length(); - if (len) - { - if (len > 255) - OPENVPN_THROW(dhcp_masq, "string '" << str << "' must be > 0 bytes and <= 255 bytes"); - buf.push_back(type); - buf.push_back((unsigned char)len); - buf.write((const unsigned char *)str.c_str(), len); - } - } - - static void write_dhcp_addr_list(Buffer& buf, - const unsigned char type, - const std::vector<IPv4::Addr>& addr_list) - { - if (!addr_list.empty()) - { - const size_t size = addr_list.size() * sizeof(std::uint32_t); - if (size < 1 || size > 255) - OPENVPN_THROW(dhcp_masq, "array size=" << size << " must be > 0 bytes and <= 255 bytes"); - buf.push_back(type); - buf.push_back((unsigned char)size); - for (auto &a : addr_list) - { - const std::uint32_t rawaddr = a.to_uint32_net(); - buf.write((const unsigned char *)&rawaddr, sizeof(std::uint32_t)); - } - } - } - }; - - class TAPDriverVersion - { - public: - TAPDriverVersion(HANDLE th) - : defined(false) - { - DWORD len; - info[0] = info[1] = info[2] = 0; - if (::DeviceIoControl(th, TAP_WIN_IOCTL_GET_VERSION, - &info, sizeof (info), - &info, sizeof (info), &len, nullptr)) - defined = true; - } - - std::string to_string() - { - std::ostringstream os; - os << "TAP-Windows Driver Version "; - if (defined) - { - os << info[0] << '.' << info[1]; - if (info[2]) - os << " (DEBUG)"; - } - else - os << "UNDEFINED"; - return os.str(); - } - - private: - bool defined; - ULONG info[3]; - }; - - // An action to set the DNS "Connection-specific DNS Suffix" - class ActionSetAdapterDomainSuffix : public Action - { - public: - ActionSetAdapterDomainSuffix(const std::string& search_domain_arg, - const std::string& tap_guid_arg) - : search_domain(search_domain_arg), - tap_guid(tap_guid_arg) - { - } - - virtual void execute(std::ostream& os) override - { - os << to_string() << std::endl; - - LONG status; - Win::RegKey key; - const std::string reg_key_name = "SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\" + tap_guid; - status = ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, - reg_key_name.c_str(), - 0, - KEY_READ|KEY_WRITE, - key.ref()); - if (status != ERROR_SUCCESS) - { - const Win::Error err(status); - OPENVPN_THROW(tun_win_util, "ActionSetAdapterDomainSuffix: error opening registry key: " << reg_key_name << " : " << err.message()); - } - - Win::UTF16 dom(Win::utf16(search_domain)); - status = ::RegSetValueExW(key(), - L"Domain", - 0, - REG_SZ, - (const BYTE *)dom.get(), - (Win::utf16_strlen(dom.get())+1)*2); - if (status != ERROR_SUCCESS) - OPENVPN_THROW(tun_win_util, "ActionSetAdapterDomainSuffix: error writing Domain registry key: " << reg_key_name); - } - - virtual std::string to_string() const override - { - return "Set adapter domain suffix: '" + search_domain + "' " + tap_guid; - } - - private: - const std::string search_domain; - const std::string tap_guid; - }; - - // get the Windows IPv4 routing table - inline const MIB_IPFORWARDTABLE* windows_routing_table() - { - ULONG size = 0; - DWORD status; - std::unique_ptr<MIB_IPFORWARDTABLE> rt; - - status = ::GetIpForwardTable(nullptr, &size, TRUE); - if (status == ERROR_INSUFFICIENT_BUFFER) - { - rt.reset((MIB_IPFORWARDTABLE*)new unsigned char[size]); - status = ::GetIpForwardTable(rt.get(), &size, TRUE); - if (status != NO_ERROR) - { - OPENVPN_LOG("windows_routing_table: GetIpForwardTable failed"); - return nullptr; - } - } - return rt.release(); - } - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - // Get the Windows IPv4/IPv6 routing table. - // Note that returned pointer must be freed with FreeMibTable. - inline const MIB_IPFORWARD_TABLE2* windows_routing_table2(ADDRESS_FAMILY af) - { - MIB_IPFORWARD_TABLE2* routes = nullptr; - int res = ::GetIpForwardTable2(af, &routes); - if (res == NO_ERROR) - return routes; - else - return nullptr; - } -#endif - - class BestGateway - { - public: - /** - * Construct object which represents default gateway - */ - BestGateway() - { - std::unique_ptr<const MIB_IPFORWARDTABLE> rt(windows_routing_table()); - if (rt) - { - const MIB_IPFORWARDROW* gw = nullptr; - for (size_t i = 0; i < rt->dwNumEntries; ++i) - { - const MIB_IPFORWARDROW* row = &rt->table[i]; - if (!row->dwForwardDest && !row->dwForwardMask - && (!gw || row->dwForwardMetric1 < gw->dwForwardMetric1)) - gw = row; - } - if (gw) - { - index = gw->dwForwardIfIndex; - addr = IPv4::Addr::from_uint32(ntohl(gw->dwForwardNextHop)).to_string(); - } - } - } - - /** - * Construct object which represents best gateway to given - * destination, excluding gateway on VPN interface. Gateway is chosen - * first by the longest prefix match and then by metric. If destination - * is in local network, no gateway is selected and "local_route" flag is set. - * - * @param dest destination IPv4 address - * @param vpn_interface_index index of VPN interface which is excluded from gateway selection - */ - BestGateway(const std::string& dest, DWORD vpn_interface_index) - { - DWORD dest_addr; - auto res = inet_pton(AF_INET, dest.c_str(), &dest_addr); - switch (res) - { - case -1: - OPENVPN_THROW(tun_win_util, "GetBestGateway: error converting IPv4 address " << dest << " to int: " << ::WSAGetLastError()); - - case 0: - OPENVPN_THROW(tun_win_util, "GetBestGateway: " << dest << " is not a valid IPv4 address"); - } - - { - MIB_IPFORWARDROW row; - DWORD res2 = GetBestRoute(dest_addr, 0, &row); - if (res2 != NO_ERROR) - { - OPENVPN_THROW(tun_win_util, "GetBestGateway: error retrieving the best route for " << dest << ": " << res2); - } - - if (row.dwForwardType == MIB_IPROUTE_TYPE_DIRECT) - { - local_route_ = true; - return; - } - } - - std::unique_ptr<const MIB_IPFORWARDTABLE> rt(windows_routing_table()); - if (rt) - { - const MIB_IPFORWARDROW* gw = nullptr; - for (size_t i = 0; i < rt->dwNumEntries; ++i) - { - const MIB_IPFORWARDROW* row = &rt->table[i]; - // does route match? - if ((dest_addr & row->dwForwardMask) == (row->dwForwardDest & row->dwForwardMask)) - { - // skip gateway on VPN interface - if ((vpn_interface_index != DWORD(-1)) && (row->dwForwardIfIndex == vpn_interface_index)) - { - OPENVPN_LOG("GetBestGateway: skip gateway " << - IPv4::Addr::from_uint32(ntohl(row->dwForwardNextHop)).to_string() << - " on VPN interface " << vpn_interface_index); - continue; - } - - if (!gw) - { - gw = row; - continue; - } - - auto cur_prefix = IPv4::Addr::prefix_len_32(ntohl(gw->dwForwardMask)); - auto new_prefix = IPv4::Addr::prefix_len_32(ntohl(row->dwForwardMask)); - auto new_metric_is_higher = row->dwForwardMetric1 > gw->dwForwardMetric1; - - if ((new_prefix > cur_prefix) || ((new_prefix == cur_prefix) && (new_metric_is_higher))) - gw = row; - } - } - if (gw) - { - index = gw->dwForwardIfIndex; - addr = IPv4::Addr::from_uint32(ntohl(gw->dwForwardNextHop)).to_string(); - OPENVPN_LOG("GetBestGateway: selected gateway " << addr << " on adapter " << index << " for destination " << dest); - } - } - } - - bool defined() const - { - return index != DWORD(-1) && !addr.empty(); - } - - DWORD interface_index() const - { - return index; - } - - const std::string& gateway_address() const - { - return addr; - } - - /** - * Return true if destination, provided to constructor, - * doesn't require gateway, false otherwise. - */ - bool local_route() const - { - return local_route_; - } - - private: - DWORD index = -1; - std::string addr; - bool local_route_ = false; - }; - - // An action to delete all routes on an interface - class ActionDeleteAllRoutesOnInterface : public Action - { - public: - ActionDeleteAllRoutesOnInterface(const DWORD iface_index_arg) - : iface_index(iface_index_arg) - { - } - - virtual void execute(std::ostream& os) override - { - os << to_string() << std::endl; - - ActionList::Ptr actions = new ActionList(); - remove_all_ipv4_routes_on_iface(iface_index, *actions); -#if _WIN32_WINNT >= 0x0600 // Vista and higher - remove_all_ipv6_routes_on_iface(iface_index, *actions); -#endif - actions->execute(os); - } - - virtual std::string to_string() const override - { - return "ActionDeleteAllRoutesOnInterface iface_index=" + std::to_string(iface_index); - } - - private: - static void remove_all_ipv4_routes_on_iface(DWORD index, ActionList& actions) - { - std::unique_ptr<const MIB_IPFORWARDTABLE> rt(windows_routing_table()); - if (rt) - { - for (size_t i = 0; i < rt->dwNumEntries; ++i) - { - const MIB_IPFORWARDROW* row = &rt->table[i]; - if (row->dwForwardIfIndex == index) - { - const IPv4::Addr net = IPv4::Addr::from_uint32(ntohl(row->dwForwardDest)); - const IPv4::Addr mask = IPv4::Addr::from_uint32(ntohl(row->dwForwardMask)); - const std::string net_str = net.to_string(); - const unsigned int pl = mask.prefix_len(); - - // don't remove multicast route or other Windows-assigned routes - if (net_str == "224.0.0.0" && pl == 4) - continue; - if (net_str == "255.255.255.255" && pl == 32) - continue; - - actions.add(new WinCmd("netsh interface ip delete route " + net_str + '/' + openvpn::to_string(pl) + ' ' + openvpn::to_string(index) + " store=active")); - } - } - } - } - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - static void remove_all_ipv6_routes_on_iface(DWORD index, ActionList& actions) - { - unique_ptr_del<const MIB_IPFORWARD_TABLE2> rt2(windows_routing_table2(AF_INET6), - [](const MIB_IPFORWARD_TABLE2* p) { FreeMibTable((PVOID)p); }); - if (rt2) - { - const IPv6::Addr ll_net = IPv6::Addr::from_string("fe80::"); - const IPv6::Addr ll_mask = IPv6::Addr::netmask_from_prefix_len(64); - for (size_t i = 0; i < rt2->NumEntries; ++i) - { - const MIB_IPFORWARD_ROW2* row = &rt2->Table[i]; - if (row->InterfaceIndex == index) - { - const unsigned int pl = row->DestinationPrefix.PrefixLength; - if (row->DestinationPrefix.Prefix.si_family == AF_INET6) - { - const IPv6::Addr net = IPv6::Addr::from_byte_string(row->DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte); - const std::string net_str = net.to_string(); - - // don't remove multicast route or other Windows-assigned routes - if (net_str == "ff00::" && pl == 8) - continue; - if ((net & ll_mask) == ll_net && pl >= 64) - continue; - actions.add(new WinCmd("netsh interface ipv6 delete route " + net_str + '/' + openvpn::to_string(pl) + ' ' + openvpn::to_string(index) + " store=active")); - } - } - } - } - } -#endif - - const DWORD iface_index; - }; - - class ActionEnableDHCP : public WinCmd - { - public: - ActionEnableDHCP(const TapNameGuidPair& tap) - : WinCmd(cmd(tap)) - { - } - - private: - static std::string cmd(const TapNameGuidPair& tap) - { - return "netsh interface ip set address " + tap.index_or_name() + " dhcp"; - } - }; - - namespace TunNETSH - { - class AddRoute4Cmd : public Action - { - public: - typedef RCPtr<AddRoute4Cmd> Ptr; - - AddRoute4Cmd(const std::string& route_address, - int prefix_length, - const TunWin::Util::TapNameGuidPair& tap, - const std::string& gw_address, - int metric, - bool add) - { - std::ostringstream os; - os << "netsh interface ip "; - if (add) - os << "add "; - else - os << "delete "; - os << "route " << route_address << "/" << std::to_string(prefix_length) << " " << tap.index_or_name() << " " << gw_address << " "; - if (add && metric >= 0) - os << "metric=" << std::to_string(metric) << " "; - os << "store=active"; - cmd.reset(new WinCmd(os.str())); - }; - - void execute(std::ostream& os) override - { - cmd->execute(os); - } - - std::string to_string() const override - { - return cmd->to_string(); - } - - private: - WinCmd::Ptr cmd; - }; - } - - namespace TunIPHELPER - { - static SOCKADDR_INET sockaddr_inet(short family, const std::string& addr) - { - SOCKADDR_INET sa; - ZeroMemory(&sa, sizeof(sa)); - sa.si_family = family; - inet_pton(family, addr.c_str(), family == AF_INET ? &(sa.Ipv4.sin_addr) : (PVOID) & (sa.Ipv6.sin6_addr)); - return sa; - } - - static DWORD InterfaceLuid(const std::string& iface_name, PNET_LUID luid) - { - auto wide_name = wstring::from_utf8(iface_name); - return ConvertInterfaceAliasToLuid(wide_name.c_str(), luid); - } - - class AddRoute4Cmd : public Action - { - public: - typedef RCPtr<AddRoute4Cmd> Ptr; - - AddRoute4Cmd(const std::string& route_address, - int prefix_length, - const TunWin::Util::TapNameGuidPair& tap, - const std::string& gw_address, - int metric, - bool add) : add(add) - { - os_ << "IPHelper: "; - if (add) - os_ << "add "; - else - os_ << "delete "; - os_ << "route " << route_address << "/" << std::to_string(prefix_length) << " " << tap.index_or_name() << " " << gw_address << " "; - os_ << "metric=" << std::to_string(metric); - - ZeroMemory(&fwd_row, sizeof(fwd_row)); - fwd_row.ValidLifetime = 0xffffffff; - fwd_row.PreferredLifetime = 0xffffffff; - fwd_row.Protocol = (NL_ROUTE_PROTOCOL)MIB_IPPROTO_NETMGMT; - fwd_row.Metric = metric; - fwd_row.DestinationPrefix.Prefix = sockaddr_inet(AF_INET, route_address); - fwd_row.DestinationPrefix.PrefixLength = prefix_length; - fwd_row.NextHop = sockaddr_inet(AF_INET, gw_address); - - if (tap.index_defined()) - fwd_row.InterfaceIndex = tap.index; - else if (!tap.name.empty()) - { - NET_LUID luid; - auto err = InterfaceLuid(tap.name, &luid); - if (err) - OPENVPN_THROW(tun_win_util, "Cannot convert interface name " << tap.name << " to LUID"); - fwd_row.InterfaceLuid = luid; - } - }; - - void execute(std::ostream& os) override - { - os << os_.str() << std::endl; - DWORD res; - if (add) - res = CreateIpForwardEntry2(&fwd_row); - else - res = DeleteIpForwardEntry2(&fwd_row); - if (res) - os << "cannot modify route: error " << res << std::endl; - } - - std::string to_string() const override - { - return os_.str(); - } - - private: - MIB_IPFORWARD_ROW2 fwd_row; - bool add; - std::ostringstream os_; - }; - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/wfp.hpp b/Sources/OpenVPN3/openvpn/tun/win/wfp.hpp deleted file mode 100644 index 5026969..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/wfp.hpp +++ /dev/null @@ -1,385 +0,0 @@ -// 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-2020 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_TUN_WIN_WFP_H -#define OPENVPN_TUN_WIN_WFP_H - -#include <ostream> - -#include <openvpn/common/rc.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/tun/win/tunutil.hpp> -#include <openvpn/win/winerr.hpp> - -#include <fwpmu.h> -#include <fwpmtypes.h> -#include <iphlpapi.h> -#include <wchar.h> - -#ifdef __MINGW32__ - -#include <initguid.h> - -// WFP-related defines and GUIDs not in mingw32 - -#ifndef FWPM_SESSION_FLAG_DYNAMIC -#define FWPM_SESSION_FLAG_DYNAMIC 0x00000001 -#endif - -// defines below are taken from openvpn2 code (https://github.com/OpenVPN/openvpn/blob/master/src/openvpn/block_dns.c) -// which likely borrowed them from Windows SDK header fwpmu.h - -/* c38d57d1-05a7-4c33-904f-7fbceee60e82 */ -DEFINE_GUID( - FWPM_LAYER_ALE_AUTH_CONNECT_V4, - 0xc38d57d1, - 0x05a7, - 0x4c33, - 0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82 -); - -/* 4a72393b-319f-44bc-84c3-ba54dcb3b6b4 */ -DEFINE_GUID( - FWPM_LAYER_ALE_AUTH_CONNECT_V6, - 0x4a72393b, - 0x319f, - 0x44bc, - 0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4 -); - -/* d78e1e87-8644-4ea5-9437-d809ecefc971 */ -DEFINE_GUID( - FWPM_CONDITION_ALE_APP_ID, - 0xd78e1e87, - 0x8644, - 0x4ea5, - 0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71 -); - -/* c35a604d-d22b-4e1a-91b4-68f674ee674b */ -DEFINE_GUID( - FWPM_CONDITION_IP_REMOTE_PORT, - 0xc35a604d, - 0xd22b, - 0x4e1a, - 0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b -); - -/* 4cd62a49-59c3-4969-b7f3-bda5d32890a4 */ -DEFINE_GUID( - FWPM_CONDITION_IP_LOCAL_INTERFACE, - 0x4cd62a49, - 0x59c3, - 0x4969, - 0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4 -); - -/* UUID of WFP sublayer used by all instances of openvpn - * 2f660d7e-6a37-11e6-a181-001e8c6e04a2 */ -DEFINE_GUID( - OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER, - 0x2f660d7e, - 0x6a37, - 0x11e6, - 0xa1, 0x81, 0x00, 0x1e, 0x8c, 0x6e, 0x04, 0xa2 -); - -#endif - -namespace openvpn { - namespace TunWin { - - class WFP : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<WFP> Ptr; - - OPENVPN_EXCEPTION(wfp_error); - - // Block DNS from all apps except openvpn_app_path and - // from all interfaces except tap_index. - // Derived from https://github.com/ValdikSS/openvpn-with-patches/commit/3bd4d503d21aa34636e4f97b3e32ae0acca407f0 - void block_dns(const std::wstring& openvpn_app_path, - const NET_IFINDEX tap_index, - std::ostream& log) - { - // WFP filter/conditions - FWPM_FILTER0 filter = {0}; - FWPM_FILTER_CONDITION0 condition[2] = {0}; - UINT64 filterid = 0; - - // Get NET_LUID object for adapter - NET_LUID tap_luid = adapter_index_to_luid(tap_index); - - // Get app ID - unique_ptr_del<FWP_BYTE_BLOB> openvpn_app_id_blob = get_app_id_blob(openvpn_app_path); - - // Populate packet filter layer information - { - FWPM_SUBLAYER0 subLayer = {0}; - subLayer.subLayerKey = subLayerGUID; - subLayer.displayData.name = const_cast<wchar_t*>(L"OpenVPN"); - subLayer.displayData.description = const_cast<wchar_t*>(L"OpenVPN"); - subLayer.flags = 0; - subLayer.weight = 0x100; - - // Add packet filter to interface - const DWORD status = ::FwpmSubLayerAdd0(engineHandle(), &subLayer, NULL); - if (status != ERROR_SUCCESS) - OPENVPN_THROW(wfp_error, "FwpmSubLayerAdd0 failed with status=0x" << std::hex << status); - } - - // Prepare filter - filter.subLayerKey = subLayerGUID; - filter.displayData.name = const_cast<wchar_t*>(L"OpenVPN"); - filter.weight.type = FWP_UINT8; - filter.weight.uint8 = 0xF; - filter.filterCondition = condition; - - // Filter #1 -- permit IPv4 DNS requests from OpenVPN app - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; - filter.action.type = FWP_ACTION_PERMIT; - filter.numFilterConditions = 2; - - condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; - condition[0].matchType = FWP_MATCH_EQUAL; - condition[0].conditionValue.type = FWP_UINT16; - condition[0].conditionValue.uint16 = 53; - - condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID; - condition[1].matchType = FWP_MATCH_EQUAL; - condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE; - condition[1].conditionValue.byteBlob = openvpn_app_id_blob.get(); - - add_filter(&filter, NULL, &filterid); - log << "permit IPv4 DNS requests from OpenVPN app" << std::endl; - - // Filter #2 -- permit IPv6 DNS requests from OpenVPN app - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; - - add_filter(&filter, NULL, &filterid); - log << "permit IPv6 DNS requests from OpenVPN app" << std::endl; - - // Filter #3 -- block IPv4 DNS requests from other apps - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; - filter.action.type = FWP_ACTION_BLOCK; - filter.weight.type = FWP_EMPTY; - filter.numFilterConditions = 1; - - add_filter(&filter, NULL, &filterid); - log << "block IPv4 DNS requests from other apps" << std::endl; - - // Filter #4 -- block IPv6 DNS requests from other apps - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; - - add_filter(&filter, NULL, &filterid); - log << "block IPv6 DNS requests from other apps" << std::endl; - - // Filter #5 -- allow IPv4 traffic from TAP - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; - filter.action.type = FWP_ACTION_PERMIT; - filter.numFilterConditions = 2; - - condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE; - condition[1].matchType = FWP_MATCH_EQUAL; - condition[1].conditionValue.type = FWP_UINT64; - condition[1].conditionValue.uint64 = &tap_luid.Value; - - add_filter(&filter, NULL, &filterid); - log << "allow IPv4 traffic from TAP" << std::endl; - - // Filter #6 -- allow IPv6 traffic from TAP - filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; - - add_filter(&filter, NULL, &filterid); - log << "allow IPv6 traffic from TAP" << std::endl; - } - - void reset(std::ostream& log) - { - engineHandle.reset(&log); - } - - private: - class WFPEngine - { - public: - WFPEngine() - { - FWPM_SESSION0 session = {0}; - - // delete all filters when engine handle is closed - session.flags = FWPM_SESSION_FLAG_DYNAMIC; - - const DWORD status = ::FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &handle); - if (status != ERROR_SUCCESS) - OPENVPN_THROW(wfp_error, "FwpmEngineOpen0 failed with status=0x" << std::hex << status); - } - - void reset(std::ostream* log) - { - if (defined()) - { - const DWORD status = ::FwpmEngineClose0(handle); - handle = NULL; - if (log) - { - if (status != ERROR_SUCCESS) - *log << "FwpmEngineClose0 failed, status=" << status << std::endl; - else - *log << "WFPEngine closed" << std::endl; - } - } - } - - ~WFPEngine() - { - reset(nullptr); - } - - bool defined() const - { - return Win::Handle::defined(handle); - } - - HANDLE operator()() const - { - return handle; - } - - private: - WFPEngine(const WFPEngine&) = delete; - WFPEngine& operator=(const WFPEngine&) = delete; - - HANDLE handle = NULL; - }; - - static GUID new_guid() - { - UUID ret; - const RPC_STATUS status = ::UuidCreate(&ret); - if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) - throw wfp_error("UuidCreate failed"); - return ret; - } - - static NET_LUID adapter_index_to_luid(const NET_IFINDEX index) - { - NET_LUID tap_luid; - const NETIO_STATUS ret = ::ConvertInterfaceIndexToLuid(index, &tap_luid); - if (ret != NO_ERROR) - throw wfp_error("ConvertInterfaceIndexToLuid failed"); - return tap_luid; - } - - static unique_ptr_del<FWP_BYTE_BLOB> get_app_id_blob(const std::wstring& app_path) - { - FWP_BYTE_BLOB *blob; - const DWORD status = ::FwpmGetAppIdFromFileName0(app_path.c_str(), &blob); - if (status != ERROR_SUCCESS) - OPENVPN_THROW(wfp_error, "FwpmGetAppIdFromFileName0 failed, status=0x" << std::hex << status); - return unique_ptr_del<FWP_BYTE_BLOB>(blob, [](FWP_BYTE_BLOB* blob) { - ::FwpmFreeMemory0((void**)&blob); - }); - } - - void add_filter(const FWPM_FILTER0 *filter, - PSECURITY_DESCRIPTOR sd, - UINT64 *id) - { - const DWORD status = ::FwpmFilterAdd0(engineHandle(), filter, sd, id); - if (status != ERROR_SUCCESS) - OPENVPN_THROW(wfp_error, "FwpmFilterAdd0 failed, status=0x" << std::hex << status); - } - - const GUID subLayerGUID{new_guid()}; - WFPEngine engineHandle; - }; - - class WFPContext : public RC<thread_unsafe_refcount> - { - public: - typedef RCPtr<WFPContext> Ptr; - - private: - friend class ActionWFP; - - void block(const std::wstring& openvpn_app_path, - const NET_IFINDEX tap_index, - std::ostream& log) - { - unblock(log); - wfp.reset(new WFP()); - wfp->block_dns(openvpn_app_path, tap_index, log); - } - - void unblock(std::ostream& log) - { - if (wfp) - { - wfp->reset(log); - wfp.reset(); - } - } - - WFP::Ptr wfp; - }; - - class ActionWFP : public Action - { - public: - ActionWFP(const std::wstring& openvpn_app_path_arg, - const NET_IFINDEX tap_index_arg, - const bool enable_arg, - const WFPContext::Ptr& wfp_arg) - : openvpn_app_path(openvpn_app_path_arg), - tap_index(tap_index_arg), - enable(enable_arg), - wfp(wfp_arg) - { - } - - virtual void execute(std::ostream& log) override - { - log << to_string() << std::endl; - if (enable) - wfp->block(openvpn_app_path, tap_index, log); - else - wfp->unblock(log); - } - - virtual std::string to_string() const override - { - return "ActionWFP openvpn_app_path=" + wstring::to_utf8(openvpn_app_path) + " tap_index=" + std::to_string(tap_index) + " enable=" + std::to_string(enable); - } - - private: - const std::wstring openvpn_app_path; - const NET_IFINDEX tap_index; - const bool enable; - WFPContext::Ptr wfp; - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/tun/win/winproxy.hpp b/Sources/OpenVPN3/openvpn/tun/win/winproxy.hpp deleted file mode 100644 index 281301f..0000000 --- a/Sources/OpenVPN3/openvpn/tun/win/winproxy.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// 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-2020 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/>. -// - -// proxy settings for Windows - -#pragma once - -#include <wininet.h> - -#include <openvpn/win/impersonate.hpp> -#include <openvpn/tun/proxy.hpp> -#include <openvpn/win/reg.hpp> - -using namespace openvpn::Win; - -namespace openvpn { - namespace TunWin { - class WinProxySettings : public ProxySettings { - public: - typedef RCPtr<WinProxySettings> Ptr; - - WinProxySettings(const TunBuilderCapture::ProxyAutoConfigURL& config_arg) - : ProxySettings(config_arg) { } - - void set_proxy(bool del) override - { - Impersonate imp{false}; - - LONG status; - RegKey hkcu; - RegKey key; - - status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref()); - check_reg_error<proxy_error>(status, "RegOpenCurrentUser"); - - status = ::RegCreateKeyExA(hkcu(), key_name, 0, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, key.ref(), NULL); - check_reg_error<proxy_error>(status, key_name); - - if (!del) - { - save_key(key, "AutoConfigURL", config.url, true); - save_key(key, "ProxyEnable", "0", false); - } - else - { - restore_key(key, "AutoConfigURL", true); - restore_key(key, "ProxyEnable", false); - } - - // WinInet API cannot be called from service, even via impersonation - if (!imp.is_local_system()) - { - OPENVPN_LOG("Refresh proxy settings"); - - InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0); - InternetSetOptionA(NULL, INTERNET_OPTION_REFRESH, NULL, 0); - } - } - - private: - void restore_key(Win::RegKey& regkey, const std::string& key, bool str) - { - LONG status; - char prev_val_str[1024] = { 0 }; // should be enough to fit proxy URL - DWORD prev_val_dword; - DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword); - bool del = false; - Win::RegKey hkcu; - - status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref()); - check_reg_error<proxy_error>(status, "RegOpenCurrentUser"); - - // get previous value - std::string prev_key_name = sname + key; - status = ::RegGetValueA(hkcu(), - key_name, - prev_key_name.c_str(), - str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD, - NULL, - str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword, - &prev_buf_size); - check_reg_error<proxy_error>(status, prev_key_name); - - RegDeleteValueA(regkey(), prev_key_name.c_str()); - - // check if previous value needs to be deleted - if (str) - del = strcmp(delete_value_str, prev_val_str) == 0; - else - del = prev_val_dword == delete_value_dword; - - if (del) - ::RegDeleteValueA(regkey(), key.c_str()); - else - ::RegSetValueExA(regkey(), - key.c_str(), - 0, - str ? REG_SZ : REG_DWORD, - str ? (const BYTE *)prev_val_str : (CONST BYTE *)&prev_val_dword, - str ? strlen(prev_val_str) + 1 : sizeof(prev_val_dword)); - } - - void save_key(Win::RegKey& regkey, const std::string& key, const std::string& value, bool str) - { - LONG status; - char prev_val_str[1024] = { 0 }; // should be enought to fit proxy URL - DWORD prev_val_dword; - DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword); - Win::RegKey hkcu; - - status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref()); - check_reg_error<proxy_error>(status, "RegOpenCurrentUser"); - - // get original value - status = ::RegGetValueA(hkcu(), - key_name, - key.c_str(), - str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD, - NULL, - str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword, - &prev_buf_size); - switch (status) - { - case ERROR_FILE_NOT_FOUND: - // mark that original value doesn't exist - strcpy(prev_val_str, delete_value_str); - prev_val_dword = delete_value_dword; - case ERROR_SUCCESS: - break; - default: - check_reg_error<proxy_error>(status, key); - break; - } - - // save original value - std::string prev_key_name = sname + key; - status = ::RegSetValueExA(regkey(), - prev_key_name.c_str(), - 0, - str ? REG_SZ : REG_DWORD, - str ? (const BYTE *)prev_val_str : (CONST BYTE *)&prev_val_dword, - str ? strlen(prev_val_str) + 1 : sizeof(DWORD)); - check_reg_error<proxy_error>(status, prev_key_name); - - // save new value - DWORD val_dword = 0; - if (!str) - val_dword = std::atol(value.c_str()); - status = ::RegSetValueExA(regkey(), - key.c_str(), - 0, - str ? REG_SZ : REG_DWORD, - str ? (const BYTE *)value.c_str() : (CONST BYTE *)&val_dword, - str ? value.length() + 1 : sizeof(val_dword)); - check_reg_error<proxy_error>(status, key); - } - - const char* key_name = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; - const char* delete_value_str = "DeleteValue"; - const DWORD delete_value_dword = 0xCAFEBABE; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/win/call.hpp b/Sources/OpenVPN3/openvpn/win/call.hpp deleted file mode 100644 index a54e36e..0000000 --- a/Sources/OpenVPN3/openvpn/win/call.hpp +++ /dev/null @@ -1,167 +0,0 @@ -// 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-2020 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/>. - -// execute a Windows command, capture the output - -#ifndef OPENVPN_WIN_CALL_H -#define OPENVPN_WIN_CALL_H - -#include <windows.h> -#include <shlobj.h> -#include <knownfolders.h> - -#include <cstring> - -#include <openvpn/common/uniqueptr.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/unicode.hpp> - -namespace openvpn { - namespace Win { - - OPENVPN_EXCEPTION(win_call); - - inline std::string call(const std::string& cmd) - { - // split command name from args - std::string name; - std::string args; - const size_t spcidx = cmd.find_first_of(" "); - if (spcidx != std::string::npos) - { - name = cmd.substr(0, spcidx); - if (spcidx+1 < cmd.length()) - args = cmd.substr(spcidx+1); - } - else - name = cmd; - -#if _WIN32_WINNT >= 0x0600 - // get system path (Vista and higher) - wchar_t *syspath_ptr = nullptr; - if (::SHGetKnownFolderPath(FOLDERID_System, 0, nullptr, &syspath_ptr) != S_OK) - throw win_call("cannot get system path using SHGetKnownFolderPath"); - unique_ptr_del<wchar_t> syspath(syspath_ptr, [](wchar_t* p) { ::CoTaskMemFree(p); }); -# define SYSPATH_FMT_CHAR L"s" -# define SYSPATH_LEN_METH(x) ::wcslen(x) -#else - // get system path (XP and higher) - std::unique_ptr<wchar_t[]> syspath(new wchar_t[MAX_PATH]); - if (::SHGetFolderPathW(nullptr, CSIDL_SYSTEM, nullptr, 0, syspath.get()) != S_OK) - throw win_call("cannot get system path using SHGetFolderPathW"); -# define SYSPATH_FMT_CHAR L"s" -# define SYSPATH_LEN_METH(x) ::wcslen(x) -#endif - - // build command line - const size_t wcmdlen = SYSPATH_LEN_METH(syspath.get()) + name.length() + args.length() + 64; - std::unique_ptr<wchar_t[]> wcmd(new wchar_t[wcmdlen]); - const char *spc = ""; - if (!args.empty()) - spc = " "; - ::_snwprintf(wcmd.get(), wcmdlen, L"\"%" SYSPATH_FMT_CHAR L"\\%S.exe\"%S%S", syspath.get(), name.c_str(), spc, args.c_str()); - wcmd.get()[wcmdlen-1] = 0; - //::wprintf(L"CMD[%d]: %s\n", (int)::wcslen(wcmd.get()), wcmd.get()); -# undef SYSPATH_FMT_CHAR -# undef SYSPATH_LEN_METH - - // Set the bInheritHandle flag so pipe handles are inherited. - SECURITY_ATTRIBUTES saAttr; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = nullptr; - - // Create a pipe for the child process's STDOUT. - ScopedHANDLE cstdout_r; // child write side - ScopedHANDLE cstdout_w; // parent read side - if (!::CreatePipe(cstdout_r.ref(), cstdout_w.ref(), &saAttr, 0)) - throw win_call("cannot create pipe for child stdout"); - - // Ensure the read handle to the pipe for STDOUT is not inherited. - if (!::SetHandleInformation(cstdout_r(), HANDLE_FLAG_INHERIT, 0)) - throw win_call("SetHandleInformation failed for child stdout pipe"); - - // Set up members of the PROCESS_INFORMATION structure. - PROCESS_INFORMATION piProcInfo; - ::ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); - - // Set up members of the STARTUPINFO structure. - // This structure specifies the STDIN and STDOUT handles for redirection. - STARTUPINFOW siStartInfo; - ::ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); - siStartInfo.cb = sizeof(STARTUPINFO); - siStartInfo.hStdError = cstdout_w(); - siStartInfo.hStdOutput = cstdout_w(); - siStartInfo.hStdInput = nullptr; - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - - // Create the child process. - if (!::CreateProcessW(nullptr, - wcmd.get(), // command line - nullptr, // process security attributes - nullptr, // primary thread security attributes - TRUE, // handles are inherited - 0, // creation flags - nullptr, // use parent's environment - nullptr, // use parent's current directory - &siStartInfo, // STARTUPINFO pointer - &piProcInfo)) // receives PROCESS_INFORMATION - throw win_call("cannot create process"); - - // wrap handles to child process and its primary thread. - ScopedHANDLE process_hand(piProcInfo.hProcess); - ScopedHANDLE thread_hand(piProcInfo.hThread); - - // close child's end of stdout/stderr pipe - cstdout_w.close(); - - // read child's stdout - const size_t outbuf_size = 512; - std::unique_ptr<char[]> outbuf(new char[outbuf_size]); - std::string out; - while (true) - { - DWORD dwRead; - if (!::ReadFile(cstdout_r(), outbuf.get(), outbuf_size, &dwRead, nullptr)) - break; - if (dwRead == 0) - break; - out += std::string(outbuf.get(), 0, dwRead); - } - - // decode output using console codepage, convert to utf16 - // console codepage, used to decode output - UTF16 utf16output(Win::utf16(out, ::GetOEMCP())); - - // re-encode utf16 to utf8 - UTF8 utf8output(Win::utf8(utf16output.get())); - out.assign(utf8output.get()); - - // wait for child to exit - if (::WaitForSingleObject(process_hand(), INFINITE) == WAIT_FAILED) - throw win_call("WaitForSingleObject failed on child process handle"); - - return out; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/cmd.hpp b/Sources/OpenVPN3/openvpn/win/cmd.hpp deleted file mode 100644 index 7e0d914..0000000 --- a/Sources/OpenVPN3/openvpn/win/cmd.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// 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-2020 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_WIN_CMD_H -#define OPENVPN_WIN_CMD_H - -#include <windows.h> - -#include <string> -#include <regex> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/action.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/win/call.hpp> - -namespace openvpn { - - class WinCmd : public Action - { - public: - typedef RCPtr<WinCmd> Ptr; - - WinCmd(const std::string& command) - : cmd(command) - { - } - - virtual void execute(std::ostream& os) override - { - os << cmd << std::endl; - std::string out = Win::call(cmd); - os << out; - } - - virtual std::string to_string() const override - { - return cmd; - } - - private: - std::string cmd; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/win/console.hpp b/Sources/OpenVPN3/openvpn/win/console.hpp deleted file mode 100644 index 6401d74..0000000 --- a/Sources/OpenVPN3/openvpn/win/console.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// 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-2020 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/>. - -// console utilities for Windows - -#ifndef OPENVPN_WIN_CONSOLE_H -#define OPENVPN_WIN_CONSOLE_H - -#include <windows.h> -#include <string> -#include <openvpn/win/handle.hpp> - -namespace openvpn { - namespace Win { - namespace Console { - - class Input - { - Input(const Input&) = delete; - Input& operator=(const Input&) = delete; - - public: - Input() - : std_input(Handle::undefined()), - console_mode_save(0) - { - // disable control-C - ::SetConsoleCtrlHandler(nullptr, TRUE); - - HANDLE in = ::GetStdHandle(STD_INPUT_HANDLE); - DWORD mode = 0; - if (Handle::defined(in) && ::GetConsoleMode(in, &mode)) - { - // running on a console - const DWORD newmode = mode - & ~(ENABLE_WINDOW_INPUT - | ENABLE_PROCESSED_INPUT - | ENABLE_LINE_INPUT - | ENABLE_ECHO_INPUT - | ENABLE_MOUSE_INPUT); - - if (newmode == mode || ::SetConsoleMode(in, newmode)) - { - std_input = in; - console_mode_save = mode; - } - } - } - - ~Input() - { - if (Handle::defined(std_input)) - ::SetConsoleMode(std_input, console_mode_save); - } - - bool available() - { - if (Handle::defined(std_input)) - { - DWORD n; - if (::GetNumberOfConsoleInputEvents(std_input, &n)) - return n > 0; - } - return false; - } - - unsigned int get() - { - if (Handle::defined(std_input)) - { - INPUT_RECORD ir; - do { - DWORD n; - if (!available()) - return 0; - if (!::ReadConsoleInputA(std_input, &ir, 1, &n)) - return 0; - } while (ir.EventType != KEY_EVENT || ir.Event.KeyEvent.bKeyDown != TRUE); - return keyboard_ir_to_key(&ir); - } - else - return 0; - } - - private: - unsigned int keyboard_ir_to_key(INPUT_RECORD *ir) - { - if (ir->Event.KeyEvent.uChar.AsciiChar == 0) - return ir->Event.KeyEvent.wVirtualScanCode; - - if ((ir->Event.KeyEvent.dwControlKeyState - & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - && (ir->Event.KeyEvent.wVirtualKeyCode != 18)) - return ir->Event.KeyEvent.wVirtualScanCode * 256; - - return ir->Event.KeyEvent.uChar.AsciiChar; - } - - HANDLE std_input; - DWORD console_mode_save; - }; - - class Title - { - Title(const Title&) = delete; - Title& operator=(const Title&) = delete; - - public: - Title(const std::string& new_title) - : old_title_defined(false) - { - char title[256]; - if (::GetConsoleTitleA(title, sizeof(title))) - { - old_title = title; - old_title_defined = true; - } - ::SetConsoleTitleA(new_title.c_str()); - } - - ~Title() - { - if (old_title_defined) - ::SetConsoleTitleA(old_title.c_str()); - } - private: - bool old_title_defined; - std::string old_title; - }; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/event.hpp b/Sources/OpenVPN3/openvpn/win/event.hpp deleted file mode 100644 index 9657a49..0000000 --- a/Sources/OpenVPN3/openvpn/win/event.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// 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-2020 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_WIN_EVENT_H -#define OPENVPN_WIN_EVENT_H - -#include <windows.h> - -#include <string> - -#include <openvpn/buffer/bufhex.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/win/scoped_handle.hpp> - -namespace openvpn { - namespace Win { - - // Wrap a standard Windows Event object - class Event - { - public: - explicit Event(BOOL manual_reset=TRUE) - { - event.reset(::CreateEvent(NULL, manual_reset, FALSE, NULL)); - if (!event.defined()) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("Win::Event: cannot create Windows event: " << err.message()); - } - } - - std::string duplicate_local() - { - HANDLE new_handle; - if (!::DuplicateHandle(GetCurrentProcess(), - event(), - GetCurrentProcess(), - &new_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("Win::Event: DuplicateHandle failed: " << err.message()); - } - return BufHex::render(new_handle); - } - - void signal_event() - { - if (event.defined()) - { - ::SetEvent(event()); - event.close(); - } - } - - void release_event() - { - event.close(); - } - - HANDLE operator()() const - { - return event(); - } - - void reset(HANDLE h) - { - event.reset(h); - } - - private: - ScopedHANDLE event; - }; - - // Windows event object that automatically signals in the destructor - struct DestroyEvent : public Event - { - ~DestroyEvent() - { - signal_event(); - } - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/handle.hpp b/Sources/OpenVPN3/openvpn/win/handle.hpp deleted file mode 100644 index 071fdd5..0000000 --- a/Sources/OpenVPN3/openvpn/win/handle.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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-2020 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/>. - -// windows HANDLE utilities - -#ifndef OPENVPN_WIN_HANDLE_H -#define OPENVPN_WIN_HANDLE_H - -#include <windows.h> - -namespace openvpn { - namespace Win { - namespace Handle { - inline HANDLE undefined() - { - return INVALID_HANDLE_VALUE; - } - - inline bool defined(HANDLE handle) - { - return handle != nullptr && handle != INVALID_HANDLE_VALUE; - } - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/handlecomm.hpp b/Sources/OpenVPN3/openvpn/win/handlecomm.hpp deleted file mode 100644 index e46204f..0000000 --- a/Sources/OpenVPN3/openvpn/win/handlecomm.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// 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-2020 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 <windows.h> - -#include <openvpn/buffer/bufhex.hpp> -#include <openvpn/win/winerr.hpp> - -namespace openvpn { - namespace Win { - namespace HandleComm { - - OPENVPN_EXCEPTION(handle_comm); - - // Duplicate a local handle into the address space of a - // remote process and return as a hex string that can be - // communicated across a process boundary. - inline std::string send_handle(const HANDLE handle, - const HANDLE remote_process) - { - HANDLE remote_handle; - if (!::DuplicateHandle(GetCurrentProcess(), - handle, - remote_process, - &remote_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) - { - const Win::LastError err; - OPENVPN_THROW(handle_comm, "send_handle: DuplicateHandle failed: " << err.message()); - } - return BufHex::render(remote_handle); - } - - // Duplicate a remote handle (specified as a hex string) into - // the address space of the local process. - inline HANDLE receive_handle(const std::string& remote_handle_hex, - const HANDLE remote_process) - { - const HANDLE remote_handle = BufHex::parse<HANDLE>(remote_handle_hex, "receive_handle"); - HANDLE local_handle; - if (!::DuplicateHandle(remote_process, - remote_handle, - GetCurrentProcess(), - &local_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) - { - const Win::LastError err; - OPENVPN_THROW(handle_comm, "receive_handle: DuplicateHandle failed: " << err.message()); - } - return local_handle; - } - - } - } -} diff --git a/Sources/OpenVPN3/openvpn/win/impersonate.hpp b/Sources/OpenVPN3/openvpn/win/impersonate.hpp deleted file mode 100644 index 95543f6..0000000 --- a/Sources/OpenVPN3/openvpn/win/impersonate.hpp +++ /dev/null @@ -1,220 +0,0 @@ -// 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-2020 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 <windows.h> -#include <lmcons.h> -#include <wtsapi32.h> - -#include <openvpn/win/winerr.hpp> - -namespace openvpn { - namespace Win { - - class Impersonate - { - public: - explicit Impersonate(bool as_local_system) - : local_system_(is_local_system_()) - { - if (as_local_system) - { - if (local_system_) - OPENVPN_LOG("ImpersonateAsSystem: running under SYSTEM account, no need to impersonate"); - else - impersonate_as_local_system(); - } - else - { - if (local_system_) - impersonate_as_user(); - else - OPENVPN_LOG("ImpersonateAsUser: running under user account, no need to impersonate"); - } - } - - ~Impersonate() - { - if (impersonated) - { - if (!RevertToSelf()) - { - const Win::LastError err; - OPENVPN_LOG("Impersonate: RevertToSelf() failed: " << err.message()); - } - } - } - - bool is_local_system() const - { - return local_system_; - } - - private: - void impersonate_as_local_system() - { - HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token; - PROCESSENTRY32 entry = {}; - entry.dwSize = sizeof(PROCESSENTRY32); - BOOL ret; - DWORD pid = 0; - TOKEN_PRIVILEGES privileges = {}; - privileges.PrivilegeCount = 1; - privileges.Privileges->Attributes = SE_PRIVILEGE_ENABLED; - - if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid)) - return; - - if (!ImpersonateSelf(SecurityImpersonation)) - return; - - impersonated = true; - - if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token)) - return; - if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) - { - CloseHandle(thread_token); - return; - } - CloseHandle(thread_token); - - process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (process_snapshot == INVALID_HANDLE_VALUE) - return; - - for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) - { - if (!_stricmp(entry.szExeFile, "winlogon.exe")) - { - pid = entry.th32ProcessID; - break; - } - } - CloseHandle(process_snapshot); - if (!pid) - return; - - winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!winlogon_process) - return; - - if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token)) - { - CloseHandle(winlogon_process); - return; - } - CloseHandle(winlogon_process); - - if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) - { - CloseHandle(winlogon_token); - return; - } - CloseHandle(winlogon_token); - - if (!SetThreadToken(NULL, duplicated_token)) - { - CloseHandle(duplicated_token); - return; - } - CloseHandle(duplicated_token); - } - - void impersonate_as_user() - { - DWORD sessId = WTSGetActiveConsoleSessionId(); - if (sessId == 0xFFFFFFFF) - { - const Win::LastError err; - OPENVPN_LOG("ImpersonateAsUser: WTSGetActiveConsoleSessionId() failed: " << err.message()); - return; - } - - HANDLE hToken; - if (!WTSQueryUserToken(sessId, &hToken)) - { - const Win::LastError err; - OPENVPN_LOG("ImpersonateAsUser: WTSQueryUserToken() failed: " << err.message()); - return; - } - - if (!ImpersonateLoggedOnUser(hToken)) - { - CloseHandle(hToken); - - const Win::LastError err; - OPENVPN_LOG("ImpersonateAsUser: ImpersonateLoggedOnUser() failed: " << err.message()); - return; - } - - CloseHandle(hToken); - - impersonated = true; - - char uname[UNLEN + 1]; - DWORD len = UNLEN + 1; - GetUserNameA(uname, &len); - OPENVPN_LOG("ImpersonateAsUser: impersonated as " << uname); - } - - // https://stackoverflow.com/a/4024388/227024 - BOOL is_local_system_() const - { - HANDLE hToken; - UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES]; - PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser; - ULONG cbTokenUser; - SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; - PSID pSystemSid; - BOOL bSystem; - - // open process token - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - return FALSE; - - // retrieve user SID - if (!GetTokenInformation(hToken, TokenUser, pTokenUser, sizeof(bTokenUser), &cbTokenUser)) - { - CloseHandle(hToken); - return FALSE; - } - - CloseHandle(hToken); - - // allocate LocalSystem well-known SID - if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID, - 0, 0, 0, 0, 0, 0, 0, &pSystemSid)) return FALSE; - - // compare the user SID from the token with the LocalSystem SID - bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid); - - FreeSid(pSystemSid); - - return bSystem; - } - - bool local_system_ = false; - bool impersonated = false; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/win/logfile.hpp b/Sources/OpenVPN3/openvpn/win/logfile.hpp deleted file mode 100644 index 0e8538a..0000000 --- a/Sources/OpenVPN3/openvpn/win/logfile.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// 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-2020 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/log/logbase.hpp> -#include <openvpn/win/logutil.hpp> - -namespace openvpn { - namespace Win { - - class LogFile : public LogBase - { - public: - typedef RCPtr<LogFile> Ptr; - - LogFile(const std::string& fn, - const std::string& sddl_string, - bool append) - : log_handle(LogUtil::create_file(fn, sddl_string, append)), - log_context(this) - { - } - - virtual void log(const std::string& str) override - { - LogUtil::log(log_handle(), str); - } - - private: - ScopedHANDLE log_handle; - Log::Context log_context; // must be initialized last - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/win/logutil.hpp b/Sources/OpenVPN3/openvpn/win/logutil.hpp deleted file mode 100644 index e3785ac..0000000 --- a/Sources/OpenVPN3/openvpn/win/logutil.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// 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-2020 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 <windows.h> - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/time/timestr.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/win/secattr.hpp> -#include <openvpn/win/scoped_handle.hpp> - -namespace openvpn { - namespace Win { - namespace LogUtil { - - inline void log(const HANDLE file, const std::string& str) - { - DWORD n_written; - const std::string line = date_time() + ' ' + str; - ::WriteFile(file, line.c_str(), line.length(), &n_written, NULL); - } - - inline ScopedHANDLE create_file(const std::string& fn, - const std::string& sddl_string, - bool append) - { - SecurityAttributes sa(sddl_string, true, fn); // fn passed as title only - const std::wstring wfn = wstring::from_utf8(fn); - ScopedHANDLE file(::CreateFileW( - wfn.c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - &sa.sa, - append ? OPEN_ALWAYS : CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL)); - if (!file.defined()) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("Win::LogFile: failed to open " << fn << " : " << err.message()); - } - - // append to logfile? - if (append) - { - if (::SetFilePointer(file(), 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("Win::LogFile: cannot append to " << fn << " : " << err.message()); - } - } - return file; - } - - } - } -} diff --git a/Sources/OpenVPN3/openvpn/win/modname.hpp b/Sources/OpenVPN3/openvpn/win/modname.hpp deleted file mode 100644 index 1647b36..0000000 --- a/Sources/OpenVPN3/openvpn/win/modname.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// 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-2020 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/>. - -// windows SECURITY_ATTRIBUTES utilities - -#ifndef OPENVPN_WIN_MODNAME_H -#define OPENVPN_WIN_MODNAME_H - -#include <windows.h> - -#include <string> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/win/reg.hpp> - -namespace openvpn { - namespace Win { - - inline std::wstring module_name() - { - // get path to our binary - wchar_t path[MAX_PATH]; - if (!::GetModuleFileNameW(NULL, path, MAX_PATH)) - { - const Win::LastError err; - OPENVPN_THROW_EXCEPTION("GetModuleFileNameW failed: " << err.message()); - } - return std::wstring(path); - } - - inline std::string module_name_utf8() - { - return wstring::to_utf8(module_name()); - } - - inline std::string omiclient_path() - { - char strbuf[256] = {0}; - DWORD len = sizeof(strbuf); - DWORD data_type; - auto status = ::RegGetValueA(HKEY_LOCAL_MACHINE, - "SOFTWARE\\OpenVPN", - "omi_exe_path", - RRF_RT_REG_SZ, - &data_type, - (LPBYTE)strbuf, - &len); - - if (status != ERROR_SUCCESS) - { - const Win::Error err(status); - OPENVPN_THROW_EXCEPTION("Cannot read HKLM\\SOFTWARE\\OpenVPN\\omi_exe_path: " << err.message()); - } - - return strbuf; - } - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/npinfo.hpp b/Sources/OpenVPN3/openvpn/win/npinfo.hpp deleted file mode 100644 index 2621122..0000000 --- a/Sources/OpenVPN3/openvpn/win/npinfo.hpp +++ /dev/null @@ -1,206 +0,0 @@ -// 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-2020 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 - -// Get info about named pipe peer - -#include <windows.h> -#include <sddl.h> -#include <aclapi.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/common/abort.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/secattr.hpp> - -namespace openvpn { - namespace Win { - struct NamedPipeImpersonate - { - OPENVPN_EXCEPTION(named_pipe_impersonate); - - NamedPipeImpersonate(const HANDLE pipe) - { - if (!::ImpersonateNamedPipeClient(pipe)) - { - const Win::LastError err; - OPENVPN_THROW(named_pipe_impersonate, "ImpersonateNamedPipeClient failed: " << err.message()); - } - } - - ~NamedPipeImpersonate() - { - if (!::RevertToSelf()) - { - OPENVPN_LOG("NamedPipeImpersonate: RevertToSelf failed, must abort"); - std::abort(); - } - } - }; - - struct NamedPipePeerInfo - { - OPENVPN_EXCEPTION(npinfo_error); - - // Get process handle given PID. - static Win::ScopedHANDLE get_process(const ULONG pid, const bool limited) - { - // open process - Win::ScopedHANDLE proc(::OpenProcess( -#if _WIN32_WINNT >= 0x0600 // Vista and higher - limited ? (PROCESS_QUERY_LIMITED_INFORMATION|SYNCHRONIZE) : PROCESS_ALL_ACCESS, -#else - PROCESS_ALL_ACCESS, -#endif - FALSE, - pid)); - if (!proc.defined()) - { - const Win::LastError err; - OPENVPN_THROW(npinfo_error, "OpenProcess failed: " << err.message()); - } - return proc; - } - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - - // Servers must call this method to modify their process - // access rights to grant clients the - // PROCESS_QUERY_LIMITED_INFORMATION right, so that clients - // can validate the server's exe path via get_exe_path(). - static void allow_client_query() - { - SecurityAttributes sa( - "D:" // discretionary ACL - "(A;OICI;0x101000;;;S-1-1-0)" // grant PROCESS_QUERY_LIMITED_INFORMATION and SYNCHRONIZE access to Everyone - , - false, - "client query"); - - ACL* dacl; - BOOL bDaclPresent, bDaclDefaulted; - if (!::GetSecurityDescriptorDacl(sa.sa.lpSecurityDescriptor, - &bDaclPresent, - &dacl, - &bDaclDefaulted)) - { - const Win::LastError err; - OPENVPN_THROW(npinfo_error, "allow_client_query: GetSecurityDescriptorDacl failed: " << err.message()); - } - if (!bDaclPresent) - OPENVPN_THROW(npinfo_error, "allow_client_query: missing DACL"); - const DWORD ssi_status = ::SetSecurityInfo( - ::GetCurrentProcess(), - SE_KERNEL_OBJECT, - DACL_SECURITY_INFORMATION, - NULL, - NULL, - dacl, - NULL); - if (ssi_status != ERROR_SUCCESS) - { - const Win::Error err(ssi_status); - OPENVPN_THROW(npinfo_error, "allow_client_query: SetSecurityInfo failed: " << err.message()); - } - } - - // Get PID of process at other end of named pipe - static ULONG get_pid(const HANDLE np_handle, const bool client) - { - ULONG pid = 0; - if (client) - { - if (!::GetNamedPipeClientProcessId(np_handle, &pid)) - { - const Win::LastError err; - OPENVPN_THROW(npinfo_error, "GetNamedPipeClientProcessId failed: " << err.message()); - } - } - else - { - if (!::GetNamedPipeServerProcessId(np_handle, &pid)) - { - const Win::LastError err; - OPENVPN_THROW(npinfo_error, "GetNamedPipeServerProcessId failed: " << err.message()); - } - } - return pid; - } - - // Get exe path given process handle. - static std::wstring get_exe_path(const HANDLE proc) - { - // get exe path - const size_t exe_cap = 256; - wchar_t exe[exe_cap]; - DWORD exe_size = exe_cap; - if (!::QueryFullProcessImageNameW(proc, 0, exe, &exe_size)) - { - const Win::LastError err; - OPENVPN_THROW(npinfo_error, "QueryFullProcessImageNameW failed: " << err.message()); - } - return std::wstring(exe, exe_size); - } - -#endif - }; - -#if _WIN32_WINNT >= 0x0600 // Vista and higher - - struct NamedPipePeerInfoCS : public NamedPipePeerInfo - { - NamedPipePeerInfoCS(const HANDLE handle, const bool client) - { - const ULONG pid = get_pid(handle, client); - proc = get_process(pid, !client); - exe_path = get_exe_path(proc()); - } - - Win::ScopedHANDLE proc; - std::wstring exe_path; - }; - - // Used by server to get info about clients - struct NamedPipePeerInfoClient : public NamedPipePeerInfoCS - { - NamedPipePeerInfoClient(const HANDLE handle) - : NamedPipePeerInfoCS(handle, true) - { - } - }; - - // Used by clients to get info about the server - struct NamedPipePeerInfoServer : public NamedPipePeerInfoCS - { - NamedPipePeerInfoServer(const HANDLE handle) - : NamedPipePeerInfoCS(handle, false) - { - } - }; - -#endif - - } -} diff --git a/Sources/OpenVPN3/openvpn/win/reg.hpp b/Sources/OpenVPN3/openvpn/win/reg.hpp deleted file mode 100644 index 1da8614..0000000 --- a/Sources/OpenVPN3/openvpn/win/reg.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// 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-2020 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/>. - -// registry utilities for Windows - -#ifndef OPENVPN_WIN_REG_H -#define OPENVPN_WIN_REG_H - -#include <windows.h> -#include <openvpn/win/winerr.hpp> -#include <openvpn/common/size.hpp> - -namespace openvpn { - namespace Win { - - template<typename E> - static void check_reg_error(DWORD status, const std::string& key) - { - if (status != ERROR_SUCCESS) - { - const Win::Error err(status); - OPENVPN_THROW(E, "registry key " << key << " error: " << err.message()); - } - } - - // HKEY wrapper - class RegKey - { - RegKey(const RegKey&) = delete; - RegKey& operator=(const RegKey&) = delete; - - public: - RegKey() : key(nullptr) {} - bool defined() const { return key != nullptr; } - HKEY* ref() { return &key; } - HKEY operator()() { return key; } - - ~RegKey() - { - if (defined()) - ::RegCloseKey(key); - } - private: - HKEY key; - }; - - class RegKeyEnumerator : public std::vector<std::string> - { - public: - RegKeyEnumerator(HKEY hkey, const std::string& path) - { - RegKey regKey; - auto status = ::RegOpenKeyExA(hkey, - path.c_str(), - 0, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, - regKey.ref()); - if (status != ERROR_SUCCESS) - return; - - DWORD subkeys_num; - status = ::RegQueryInfoKeyA(regKey(), - nullptr, - nullptr, - NULL, - &subkeys_num, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr); - - if (status != ERROR_SUCCESS) - return; - - const int MAX_KEY_LENGTH = 255; - for (DWORD i = 0; i < subkeys_num; ++ i) - { - DWORD subkey_size = MAX_KEY_LENGTH; - char subkey[MAX_KEY_LENGTH]; - status = ::RegEnumKeyExA(regKey(), - i, - subkey, - &subkey_size, - nullptr, - nullptr, - nullptr, - nullptr); - if (status == ERROR_SUCCESS) - push_back(subkey); - } - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/scoped_handle.hpp b/Sources/OpenVPN3/openvpn/win/scoped_handle.hpp deleted file mode 100644 index 0a166f2..0000000 --- a/Sources/OpenVPN3/openvpn/win/scoped_handle.hpp +++ /dev/null @@ -1,125 +0,0 @@ -// 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-2020 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/>. - -// scoped HANDLE for windows - -#ifndef OPENVPN_WIN_SCOPED_HANDLE_H -#define OPENVPN_WIN_SCOPED_HANDLE_H - -#include <windows.h> - -#include <openvpn/common/size.hpp> -#include <openvpn/win/handle.hpp> - -namespace openvpn { - namespace Win { - class ScopedHANDLE - { - ScopedHANDLE(const ScopedHANDLE&) = delete; - ScopedHANDLE& operator=(const ScopedHANDLE&) = delete; - - public: - typedef HANDLE base_type; - - ScopedHANDLE() : handle(Handle::undefined()) {} - - explicit ScopedHANDLE(HANDLE h) - : handle(h) {} - - HANDLE release() - { - const HANDLE ret = handle; - handle = nullptr; - return ret; - } - - bool defined() const - { - return Handle::defined(handle); - } - - HANDLE operator()() const - { - return handle; - } - - HANDLE* ref() - { - return &handle; - } - - void reset(HANDLE h) - { - close(); - handle = h; - } - - void reset() - { - close(); - } - - // unusual semantics: replace handle without closing it first - void replace(HANDLE h) - { - handle = h; - } - - bool close() - { - if (defined()) - { - const BOOL ret = ::CloseHandle(handle); - //OPENVPN_LOG("**** SH CLOSE hand=" << handle << " ret=" << ret); - handle = nullptr; - return ret != 0; - } - else - return true; - } - - ~ScopedHANDLE() - { - close(); - } - - ScopedHANDLE(ScopedHANDLE&& other) noexcept - { - handle = other.handle; - other.handle = nullptr; - } - - ScopedHANDLE& operator=(ScopedHANDLE&& other) noexcept - { - close(); - handle = other.handle; - other.handle = nullptr; - return *this; - } - - private: - HANDLE handle; - }; - - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/secattr.hpp b/Sources/OpenVPN3/openvpn/win/secattr.hpp deleted file mode 100644 index 826c9a9..0000000 --- a/Sources/OpenVPN3/openvpn/win/secattr.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// 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-2020 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 - -// windows SECURITY_ATTRIBUTES utilities - -#include <windows.h> -#include <sddl.h> - -#include <openvpn/common/exception.hpp> -#include <openvpn/win/winerr.hpp> - -namespace openvpn { - namespace Win { - - struct SecurityAttributes - { - OPENVPN_EXCEPTION(win_sec_attr); - - SecurityAttributes(const std::string& sddl_string, - const bool inherit, - const std::string& title) - { - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = inherit ? TRUE : FALSE; - sa.lpSecurityDescriptor = nullptr; - if (!sddl_string.empty()) - { - if (!::ConvertStringSecurityDescriptorToSecurityDescriptorA( - sddl_string.c_str(), - SDDL_REVISION_1, - &sa.lpSecurityDescriptor, // allocates memory - NULL)) - { - const Win::LastError err; - OPENVPN_THROW(win_sec_attr, "failed to create security descriptor for " << title << " : " << err.message()); - } - } - } - - ~SecurityAttributes() - { - ::LocalFree(sa.lpSecurityDescriptor); - } - - SECURITY_ATTRIBUTES sa; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/win/sleep.hpp b/Sources/OpenVPN3/openvpn/win/sleep.hpp deleted file mode 100644 index 837c072..0000000 --- a/Sources/OpenVPN3/openvpn/win/sleep.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// 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-2020 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_WIN_SLEEP_H -#define OPENVPN_WIN_SLEEP_H - -#include <windows.h> - -#include <string> - -#include <openvpn/common/action.hpp> -#include <openvpn/common/to_string.hpp> - -namespace openvpn { - - class WinSleep : public Action - { - public: - typedef RCPtr<WinSleep> Ptr; - - WinSleep(DWORD dwMilliseconds_arg) - : dwMilliseconds(dwMilliseconds_arg) - { - } - - virtual void execute(std::ostream& os) override - { - os << to_string() << std::endl; - ::Sleep(dwMilliseconds); - } - - virtual std::string to_string() const override - { - return "Sleeping for " + openvpn::to_string(dwMilliseconds) + " milliseconds..."; - } - - private: - DWORD dwMilliseconds; - }; - -} -#endif diff --git a/Sources/OpenVPN3/openvpn/win/unicode.hpp b/Sources/OpenVPN3/openvpn/win/unicode.hpp deleted file mode 100644 index bfaf75c..0000000 --- a/Sources/OpenVPN3/openvpn/win/unicode.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// 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-2020 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_WIN_UNICODE_H -#define OPENVPN_WIN_UNICODE_H - -#include <windows.h> - -#include <string> -#include <memory> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> - -namespace openvpn { - namespace Win { - typedef std::unique_ptr<wchar_t[]> UTF16; - typedef std::unique_ptr<char[]> UTF8; - - OPENVPN_SIMPLE_EXCEPTION(win_utf16); - - inline wchar_t* utf16(const std::string& str, int cp=CP_UTF8) - { - // first get output length (return value includes space for trailing nul) - const int len = ::MultiByteToWideChar(cp, - 0, - str.c_str(), - -1, - nullptr, - 0); - if (len <= 0) - throw win_utf16(); - UTF16 ret(new wchar_t[len]); - const int len2 = ::MultiByteToWideChar(cp, - 0, - str.c_str(), - -1, - ret.get(), - len); - if (len != len2) - throw win_utf16(); - return ret.release(); - } - - inline size_t utf16_strlen(const wchar_t *str) - { - return ::wcslen(str); - } - - inline char* utf8(wchar_t* str) - { - // first get output length (return value includes space for trailing nul) - const int len = ::WideCharToMultiByte(CP_UTF8, - 0, - str, - -1, - NULL, - 0, - NULL, - NULL); - if (len <= 0) - throw win_utf16(); - UTF8 ret(new char[len]); - const int len2 = ::WideCharToMultiByte(CP_UTF8, - 0, - str, - -1, - ret.get(), - len, - NULL, - NULL); - if (len != len2) - throw win_utf16(); - return ret.release(); - } - } -} -#endif diff --git a/Sources/OpenVPN3/openvpn/win/winerr.hpp b/Sources/OpenVPN3/openvpn/win/winerr.hpp deleted file mode 100644 index ef7c66d..0000000 --- a/Sources/OpenVPN3/openvpn/win/winerr.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// 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-2020 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/>. - -// Windows error utilities - -#ifndef OPENVPN_WIN_WINERR_H -#define OPENVPN_WIN_WINERR_H - -#include <windows.h> - -#include <openvpn/io/io.hpp> - -namespace openvpn { - namespace Win { - struct Error : public openvpn_io::error_code - { - Error(const DWORD err) - : openvpn_io::error_code(err, openvpn_io::error::get_system_category()) - { - } - }; - - struct LastError : public Error - { - LastError() - : Error(::GetLastError()) - { - } - }; - } -} - -#endif diff --git a/Sources/OpenVPN3/openvpn/win/winsvc.hpp b/Sources/OpenVPN3/openvpn/win/winsvc.hpp deleted file mode 100644 index a07cf00..0000000 --- a/Sources/OpenVPN3/openvpn/win/winsvc.hpp +++ /dev/null @@ -1,413 +0,0 @@ -// 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-2020 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 - -// windows service utilities - -#include <windows.h> - -#include <string> -#include <cstring> -#include <vector> -#include <memory> -#include <mutex> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/wstring.hpp> -#include <openvpn/win/winerr.hpp> -#include <openvpn/win/modname.hpp> - -namespace openvpn { - namespace Win { - class Service { - public: - OPENVPN_EXCEPTION(winsvc_error); - - struct Config - { - std::string name; - std::string display_name; - std::vector<std::string> dependencies; - bool autostart = false; - bool restart_on_fail = false; - }; - - Service(const Config& config_arg) - : config(config_arg) - { - std::memset(&status, 0, sizeof(status)); - status_handle = nullptr; - checkpoint = 1; - } - - bool is_service() const - { - return bool(service); - } - - void install() - { - // open service control manager - ScopedSCHandle scmgr(::OpenSCManagerW( - NULL, // local computer - NULL, // ServicesActive database - SC_MANAGER_ALL_ACCESS)); // full access rights - if (!scmgr.defined()) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "OpenSCManagerW failed: " << err.message()); - } - - // convert service names to wide string - const std::wstring wname = wstring::from_utf8(config.name); - const std::wstring wdisplay_name = wstring::from_utf8(config.display_name); - - // get dependencies - const std::wstring deps = wstring::pack_string_vector(config.dependencies); - - // create the service - - // as stated here https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-createservicew - // path must be quoted if it contains a space - const std::wstring binary_path = L"\"" + Win::module_name() + L"\""; - ScopedSCHandle svc(::CreateServiceW( - scmgr(), // SCM database - wname.c_str(), // name of service - wdisplay_name.c_str(), // service name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - config.autostart ? SERVICE_AUTO_START : SERVICE_DEMAND_START, // start type - SERVICE_ERROR_NORMAL, // error control type - binary_path.c_str(), // path to service's binary - NULL, // no load ordering group - NULL, // no tag identifier - deps.c_str(), // dependencies - NULL, // LocalSystem account - NULL)); // no password - if (!svc.defined()) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "CreateServiceW failed: " << err.message()); - } - if (config.restart_on_fail) - { - // http://stackoverflow.com/questions/3242505/how-to-create-service-which-restarts-on-crash - SERVICE_FAILURE_ACTIONS servFailActions; - SC_ACTION failActions[3]; - - failActions[0].Type = SC_ACTION_RESTART; // Failure action: Restart Service - failActions[0].Delay = 1000; // number of seconds to wait before performing failure action, in milliseconds - failActions[1].Type = SC_ACTION_RESTART; - failActions[1].Delay = 5000; - failActions[2].Type = SC_ACTION_RESTART; - failActions[2].Delay = 30000; - - servFailActions.dwResetPeriod = 86400; // Reset Failures Counter, in Seconds - servFailActions.lpCommand = NULL; // Command to perform due to service failure, not used - servFailActions.lpRebootMsg = NULL; // Message during rebooting computer due to service failure, not used - servFailActions.cActions = 3; // Number of failure action to manage - servFailActions.lpsaActions = failActions; - - ::ChangeServiceConfig2(svc(), SERVICE_CONFIG_FAILURE_ACTIONS, &servFailActions); // Apply above settings - ::StartService(svc(), 0, NULL); - } - } - - void remove() - { - // convert service name to wide string - const std::wstring wname = wstring::from_utf8(config.name); - - // open service control manager - ScopedSCHandle scmgr(::OpenSCManagerW( - NULL, // local computer - NULL, // ServicesActive database - SC_MANAGER_ALL_ACCESS)); // full access rights - if (!scmgr.defined()) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "OpenSCManagerW failed: " << err.message()); - } - - // open the service - ScopedSCHandle svc(::OpenServiceW( - scmgr(), // SCM database - wname.c_str(), // name of service - SC_MANAGER_ALL_ACCESS)); // access requested - if (!svc.defined()) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "OpenServiceW failed: " << err.message()); - } - - // remove the service - if (!::DeleteService(svc())) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "DeleteService failed: " << err.message()); - } - } - - void start() - { - service = this; - - // convert service name to wide string - const std::wstring wname = wstring::from_utf8(config.name); - - // store it in a raw wchar_t array - std::unique_ptr<wchar_t[]> wname_raw = wstring::to_wchar_t(wname); - - const SERVICE_TABLE_ENTRYW dispatch_table[] = - { - { wname_raw.get(), (LPSERVICE_MAIN_FUNCTIONW) svc_main_static }, - { NULL, NULL } - }; - - // This call returns when the service has stopped. - // The process should simply terminate when the call returns. - if (!::StartServiceCtrlDispatcherW(dispatch_table)) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "StartServiceCtrlDispatcherW failed: " << err.message()); - } - } - - void report_service_running() - { - if (is_service()) - report_service_status(SERVICE_RUNNING, NO_ERROR, 0); - } - - // The work of the service. - virtual void service_work(DWORD argc, LPWSTR *argv) = 0; - - // Called by service control manager in another thread - // to signal the service_work() method to exit. - virtual void service_stop() = 0; - - private: - class ScopedSCHandle - { - ScopedSCHandle(const ScopedSCHandle&) = delete; - ScopedSCHandle& operator=(const ScopedSCHandle&) = delete; - - public: - ScopedSCHandle() : handle(nullptr) {} - - explicit ScopedSCHandle(SC_HANDLE h) - : handle(h) {} - - SC_HANDLE release() - { - const SC_HANDLE ret = handle; - handle = nullptr; - return ret; - } - - bool defined() const - { - return bool(handle); - } - - SC_HANDLE operator()() const - { - return handle; - } - - SC_HANDLE* ref() - { - return &handle; - } - - void reset(SC_HANDLE h) - { - close(); - handle = h; - } - - // unusual semantics: replace handle without closing it first - void replace(SC_HANDLE h) - { - handle = h; - } - - bool close() - { - if (defined()) - { - const BOOL ret = ::CloseServiceHandle(handle); - handle = nullptr; - return ret != 0; - } - else - return true; - } - - ~ScopedSCHandle() - { - close(); - } - - ScopedSCHandle(ScopedSCHandle&& other) noexcept - { - handle = other.handle; - other.handle = nullptr; - } - - ScopedSCHandle& operator=(ScopedSCHandle && other) noexcept - { - close(); - handle = other.handle; - other.handle = nullptr; - return *this; - } - - private: - SC_HANDLE handle; - }; - - static VOID WINAPI svc_main_static(DWORD argc, LPWSTR *argv) - { - service->svc_main(argc, argv); - } - - void svc_main(DWORD argc, LPWSTR *argv) - { - try { - // convert service name to wide string - const std::wstring wname = wstring::from_utf8(config.name); - - // Register the handler function for the service - status_handle = ::RegisterServiceCtrlHandlerW( - wname.c_str(), - svc_ctrl_handler_static); - if (!status_handle) - { - const Win::LastError err; - OPENVPN_THROW(winsvc_error, "RegisterServiceCtrlHandlerW failed: " << err.message()); - } - - // These SERVICE_STATUS members remain as set here - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - status.dwServiceSpecificExitCode = 0; - - // Report initial status to the SCM - report_service_status(SERVICE_START_PENDING, NO_ERROR, 0); - - // Perform service-specific initialization and work - service_work(argc, argv); - - // Tell SCM we are done - report_service_status(SERVICE_STOPPED, NO_ERROR, 0); - } - catch (const std::exception& e) - { - OPENVPN_LOG("service exception: " << e.what()); - report_service_status(SERVICE_STOPPED, NO_ERROR, 0); - } - } - - // Purpose: - // Called by SCM whenever a control code is sent to the service - // using the ControlService function. - // - // Parameters: - // dwCtrl - control code - void svc_ctrl_handler(DWORD dwCtrl) - { - // Handle the requested control code. - switch (dwCtrl) - { - case SERVICE_CONTROL_STOP: - report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 0); - - // Signal the service to stop. - try { - service_stop(); - } - catch (const std::exception& e) - { - OPENVPN_LOG("service stop exception: " << e.what()); - } - report_service_status(0, NO_ERROR, 0); - return; - - case SERVICE_CONTROL_INTERROGATE: - break; - - default: - break; - } - } - - static VOID WINAPI svc_ctrl_handler_static(DWORD dwCtrl) - { - service->svc_ctrl_handler(dwCtrl); - } - - // Purpose: - // Sets the current service status and reports it to the SCM. - // - // Parameters: - // dwCurrentState - The current state (see SERVICE_STATUS) - // dwWin32ExitCode - The system error code - // dwWaitHint - Estimated time for pending operation, in milliseconds - void report_service_status(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) - { - std::lock_guard<std::mutex> lock(mutex); - - // Fill in the SERVICE_STATUS structure. - if (dwCurrentState) - status.dwCurrentState = dwCurrentState; - status.dwWin32ExitCode = dwWin32ExitCode; - status.dwWaitHint = dwWaitHint; - - if (dwCurrentState == SERVICE_START_PENDING) - status.dwControlsAccepted = 0; - else - status.dwControlsAccepted = SERVICE_ACCEPT_STOP; - if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) - status.dwCheckPoint = 0; - else - status.dwCheckPoint = checkpoint++; - - // Report the status of the service to the SCM. - ::SetServiceStatus(status_handle, &status); - } - - static Service* service; // GLOBAL - - const Config config; - - SERVICE_STATUS status; - SERVICE_STATUS_HANDLE status_handle; - DWORD checkpoint; - - std::mutex mutex; - }; - - Service* Service::service = nullptr; // GLOBAL - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/chunked.hpp b/Sources/OpenVPN3/openvpn/ws/chunked.hpp deleted file mode 100644 index 52d489e..0000000 --- a/Sources/OpenVPN3/openvpn/ws/chunked.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// 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-2020 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> -#include <openvpn/common/hexstr.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/frame/frame.hpp> - -namespace openvpn { - namespace WS { - class ChunkedHelper - { - enum State { - hex, - post_hex, - post_hex_lf, - post_chunk_cr, - post_chunk_lf, - post_content_cr, - post_content_lf, - done, - chunk, - }; - - public: - ChunkedHelper() - : state(hex), - size(0) - { - } - - template <typename PARENT> - bool receive(PARENT& callback, BufferAllocated& buf) - { - while (buf.defined()) - { - if (state == chunk) - { - if (size) - { - if (buf.size() <= size) - { - size -= buf.size(); - callback.chunked_content_in(buf); - break; - } - else - { - BufferAllocated content(buf.read_alloc(size), size, 0); - size = 0; - callback.chunked_content_in(content); - } - } - else - state = post_chunk_cr; - } - else if (state == done) - break; - else - { - const char c = char(buf.pop_front()); - reprocess: - switch (state) - { - case hex: - { - const int v = parse_hex_char(c); - if (v >= 0) - size = (size << 4) + v; - else - { - state = post_hex; - goto reprocess; - } - } - break; - case post_hex: - if (c == '\r') - state = post_hex_lf; - break; - case post_hex_lf: - if (c == '\n') - { - if (size) - state = chunk; - else - state = post_content_cr; - } - else - { - state = post_hex; - goto reprocess; - } - break; - case post_chunk_cr: - if (c == '\r') - state = post_chunk_lf; - break; - case post_chunk_lf: - if (c == '\n') - state = hex; - else - { - state = post_chunk_cr; - goto reprocess; - } - break; - case post_content_cr: - if (c == '\r') - state = post_content_lf; - break; - case post_content_lf: - if (c == '\n') - state = done; - else - { - state = post_content_cr; - goto reprocess; - } - break; - default: // should never be reached - break; - } - } - } - return state == done; - } - - static BufferPtr transmit(BufferPtr buf) - { - const size_t headroom = 24; - const size_t tailroom = 16; - static const char crlf[] = "\r\n"; - - if (!buf || buf->offset() < headroom || buf->remaining() < tailroom) - { - // insufficient headroom/tailroom, must realloc - Frame::Context fc(headroom, 0, tailroom, 0, sizeof(size_t), 0); - buf = fc.copy(buf); - } - - size_t size = buf->size(); - buf->prepend((unsigned char *)crlf, 2); - if (size) - { - while (size) - { - char *pc = (char *)buf->prepend_alloc(1); - *pc = render_hex_char(size & 0xF); - size >>= 4; - } - } - else - { - char *pc = (char *)buf->prepend_alloc(1); - *pc = '0'; - } - buf->write((unsigned char *)crlf, 2); - return buf; - } - - private: - State state; - size_t size; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/httpcli.hpp b/Sources/OpenVPN3/openvpn/ws/httpcli.hpp deleted file mode 100644 index 959e73d..0000000 --- a/Sources/OpenVPN3/openvpn/ws/httpcli.hpp +++ /dev/null @@ -1,1455 +0,0 @@ -// 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-2020 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 - -// General purpose HTTP/HTTPS/Web-services client. -// Supports: -// * asynchronous I/O through Asio -// * http/https -// * chunking -// * keepalive -// * connect and overall timeouts -// * GET, POST, etc. -// * any OpenVPN SSL module (OpenSSL, MbedTLS) -// * server CA bundle -// * client certificate -// * HTTP basic auth -// * limits on content-size, header-size, and number of headers -// * cURL not needed -// -// See test/ws/wstest.cpp for usage examples including Dropwizard REST/JSON API client. -// See test/ws/asprof.cpp for sample AS REST API client. - -#include <string> -#include <vector> -#include <sstream> -#include <ostream> -#include <cstdint> -#include <utility> -#include <memory> -#include <algorithm> // for std::min, std::max - -#ifdef USE_ASYNC_RESOLVE -#include <openvpn/client/async_resolve.hpp> -#endif - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/olong.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/common/hostport.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/asio/asiopolysock.hpp> -#include <openvpn/asio/asioresolverres.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/error/error.hpp> -#include <openvpn/buffer/bufstream.hpp> -#include <openvpn/http/reply.hpp> -#include <openvpn/time/asiotimersafe.hpp> -#include <openvpn/time/coarsetime.hpp> -#include <openvpn/transport/tcplink.hpp> -#include <openvpn/transport/client/transbase.hpp> -#include <openvpn/ws/httpcommon.hpp> -#include <openvpn/ws/httpcreds.hpp> -#include <openvpn/ws/websocket.hpp> - -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) -#include <openvpn/asio/alt_routing.hpp> -#endif - -#if defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/win/scoped_handle.hpp> -#include <openvpn/win/winerr.hpp> -#endif - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures -#include <openvpn/common/periodic_fail.hpp> -#endif - -namespace openvpn { - namespace WS { - namespace Client { - - OPENVPN_EXCEPTION(http_client_exception); - - struct Status - { - // Error codes - enum { - E_SUCCESS=0, - E_RESOLVE, - E_CONNECT, - E_TRANSPORT, - E_PROXY, - E_TCP, - E_HTTP, - E_EXCEPTION, - E_BAD_REQUEST, - E_HEADER_SIZE, - E_CONTENT_SIZE, - E_CONTENT_TYPE, - E_EOF_SSL, - E_EOF_TCP, - E_CONNECT_TIMEOUT, - E_GENERAL_TIMEOUT, - E_KEEPALIVE_TIMEOUT, - E_SHUTDOWN, - E_ABORTED, - E_BOGON, // simulated fault injection for testing - - N_ERRORS - }; - - static std::string error_str(const int status) - { - static const char *error_names[] = { - "E_SUCCESS", - "E_RESOLVE", - "E_CONNECT", - "E_TRANSPORT", - "E_PROXY", - "E_TCP", - "E_HTTP", - "E_EXCEPTION", - "E_BAD_REQUEST", - "E_HEADER_SIZE", - "E_CONTENT_SIZE", - "E_CONTENT_TYPE", - "E_EOF_SSL", - "E_EOF_TCP", - "E_CONNECT_TIMEOUT", - "E_GENERAL_TIMEOUT", - "E_KEEPALIVE_TIMEOUT", - "E_SHUTDOWN", - "E_ABORTED", - "E_BOGON", - }; - - static_assert(N_ERRORS == array_size(error_names), "HTTP error names array inconsistency"); - if (status >= 0 && status < N_ERRORS) - return error_names[status]; - else if (status == -1) - return "E_UNDEF"; - else - return "E_?/" + openvpn::to_string(status); - } - - static bool is_error(const int status) - { - switch (status) - { - case E_SUCCESS: - case E_SHUTDOWN: - return false; - default: - return true; - } - } - }; - - struct Host; - -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - struct AltRoutingShimFactory : public RC<thread_unsafe_refcount> - { - typedef RCPtr<AltRoutingShimFactory> Ptr; - - virtual AltRouting::Shim::Ptr shim(const Host& host) = 0; - virtual void report_error(const Host& host, const bool alt_routing) {} - virtual bool is_reset(const Host& host, const bool alt_routing) { return false; } - virtual int connect_timeout() { return -1; } - virtual IP::Addr remote_ip() { return IP::Addr(); } - virtual int remote_port() { return -1; } - virtual int error_expire() { return 0; } - }; -#endif - - struct Config : public RCCopyable<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - SSLFactoryAPI::Ptr ssl_factory; - TransportClientFactory::Ptr transcli; - std::string user_agent; - unsigned int connect_timeout = 0; - unsigned int general_timeout = 0; - unsigned int keepalive_timeout = 0; - unsigned int max_headers = 0; - unsigned int max_header_bytes = 0; - bool enable_cache = false; // if true, supports TLS session resumption tickets - olong max_content_bytes = 0; - unsigned int msg_overhead_bytes = 0; - int debug_level = 0; - Frame::Ptr frame; - SessionStats::Ptr stats; - -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - AltRoutingShimFactory::Ptr shim_factory; -#endif - }; - - struct Host { - std::string host; - std::string hint; // overrides host for transport, may be IP address - std::string cn; // host for CN verification, defaults to host if empty - std::string key; // host for TLS session ticket cache key, defaults to host if empty - std::string head; // host to send in HTTP header, defaults to host if empty - std::string port; - - std::string local_addr; // bind to local IP addr (optional) - std::string local_port; // bind to local port (optional) - - const std::string& host_transport() const - { - return hint.empty() ? host : hint; - } - - const std::string* host_cn_ptr() const - { - return cn.empty() ? &host : &cn; - } - - const std::string& host_cn() const - { - return *host_cn_ptr(); - } - - const std::string& host_head() const - { - return head.empty() ? host : head; - } - - std::string host_port_str() const - { - std::string ret; - const std::string& ht = host_transport(); - if (ht == host) - { - ret += '['; - ret += host; - ret += "]:"; - ret += port; - } - else - { - ret += host; - ret += '['; - ret += ht; - ret += "]:"; - ret += port; - } - return ret; - } - - std::string cache_key() const - { - return key.empty() ? (host + '/' + port ) : key; - } - }; - - struct Request - { - bool creds_defined() const - { - return !username.empty() || !password.empty(); - } - - void set_creds(const Creds& creds) - { - username = creds.username; - password = creds.password; - } - - std::string method; - std::string uri; - std::string username; - std::string password; - }; - - struct ContentInfo { - // content length if Transfer-Encoding: chunked - static constexpr olong CHUNKED = -1; - - std::string type; - std::string content_encoding; - olong length = 0; - bool keepalive = false; - bool lean_headers = false; - std::vector<std::string> extra_headers; - WebSocket::Client::PerRequest::Ptr websocket; - }; - - struct TimeoutOverride - { - // Timeout overrides in seconds. - // Set to -1 to disable. - int connect = -1; - int general = -1; - int keepalive = -1; - }; - - class HTTPCore; - typedef HTTPBase<HTTPCore, Config, Status, HTTP::ReplyType, ContentInfo, olong, RC<thread_unsafe_refcount>> Base; - - class HTTPCore : public Base, public TransportClientParent -#ifdef USE_ASYNC_RESOLVE - , public AsyncResolvableTCP -#endif - { - public: - friend Base; - - typedef RCPtr<HTTPCore> Ptr; - - struct AsioProtocol - { - typedef AsioPolySock::Base socket; - }; - - HTTPCore(openvpn_io::io_context& io_context_arg, - Config::Ptr config_arg) - : Base(std::move(config_arg)), -#ifdef USE_ASYNC_RESOLVE - AsyncResolvableTCP(io_context_arg), -#endif - io_context(io_context_arg), -#ifndef USE_ASYNC_RESOLVE - resolver(io_context_arg), -#endif - connect_timer(io_context_arg), - general_timer(io_context_arg), - general_timeout_coarse(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024)) - { - } - - virtual ~HTTPCore() - { - stop(false); - } - - // Should be called before start_request(). - void override_timeouts(TimeoutOverride to_arg) - { - to = std::move(to_arg); - } - - bool is_alive() const - { - return alive; - } - - bool is_link_active() - { - return link && !halt; - } - - // return true if the alt-routing state for this session - // has changed, requiring a reset - bool is_alt_routing_reset() const - { -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - if (config->shim_factory - && socket - && config->shim_factory->is_reset(host, socket->alt_routing_enabled())) - return true; -#endif - return false; - } - - void check_ready() const - { - if (!is_ready()) - throw http_client_exception("not ready"); - } - - void start_request() - { - check_ready(); - ready = false; - cancel_keepalive_timer(); - openvpn_io::post(io_context, [self=Ptr(this)]() - { - self->handle_request(); - }); - } - - void start_request_after(const Time::Duration dur) - { - check_ready(); - ready = false; - cancel_keepalive_timer(); - if (!req_timer) - req_timer.reset(new AsioTimerSafe(io_context)); - req_timer->expires_after(dur); - req_timer->async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - self->handle_request(); - }); - } - - void stop(const bool shutdown) - { - if (!halt) - { - halt = true; - ready = false; - alive = false; - if (transcli) - transcli->stop(); - if (link) - link->stop(); - if (socket) - { - if (shutdown) - socket->shutdown(AsioPolySock::SHUTDOWN_SEND|AsioPolySock::SHUTDOWN_RECV); - socket->close(); - } -#ifdef USE_ASYNC_RESOLVE - async_resolve_cancel(); -#else - resolver.cancel(); -#endif - if (req_timer) - req_timer->cancel(); - cancel_keepalive_timer(); - general_timer.cancel(); - connect_timer.cancel(); - } - } - - void abort(const std::string& message, const int status=Status::E_ABORTED) - { - if (!halt) - error_handler(status, message); - } - - const HTTP::Reply& reply() const { - return request_reply(); - } - - std::string remote_endpoint_str() const - { - try { - if (socket) - return socket->remote_endpoint_str(); - } - catch (const std::exception& e) - { - } - return "[unknown endpoint]"; - } - - bool remote_ip_port(IP::Addr& addr, unsigned int& port) const - { - if (socket) - return socket->remote_ip_port(addr, port); - else - return false; - } - - // Return the current Host object, but - // set the hint/port fields to the live - // IP address/port of the connection. - Host host_hint() - { - Host h = host; - if (socket) - { - IP::Addr addr; - unsigned int port; - if (socket->remote_ip_port(addr, port)) - { - h.hint = addr.to_string(); - h.port = openvpn::to_string(port); - } - } - return h; - } - - bool host_match(const std::string& host_arg) const - { - if (host.host.empty()) - return false; - else - return host.host == host_arg; - } - - AsioPolySock::Base* get_socket() - { - return socket.get(); - } - - void streaming_start() - { - cancel_general_timeout(); - content_out_hold = false; - if (is_deferred()) - http_content_out_needed(); - } - - void streaming_restart() - { - if (content_out_hold) - throw http_client_exception("streaming_restart() called when content-out is still in hold state"); - if (is_deferred()) - http_content_out_needed(); - } - - bool is_streaming_restartable() const - { - return !content_out_hold; - } - - bool is_streaming_hold() const - { - return content_out_hold; - } - - // virtual methods - - virtual Host http_host() = 0; - - virtual Request http_request() = 0; - - virtual ContentInfo http_content_info() - { - return ContentInfo(); - } - - virtual BufferPtr http_content_out() - { - return BufferPtr(); - } - - virtual void http_content_out_needed() - { - } - - virtual void http_headers_received() - { - } - - virtual void http_headers_sent(const Buffer& buf) - { - } - - virtual void http_mutate_resolver_results(openvpn_io::ip::tcp::resolver::results_type& results) - { - } - - virtual void http_content_in(BufferAllocated& buf) = 0; - - virtual void http_done(const int status, const std::string& description) = 0; - - virtual void http_keepalive_close(const int status, const std::string& description) - { - } - - virtual void http_post_connect(AsioPolySock::Base& sock) - { - } - - private: - typedef TCPTransport::Link<AsioProtocol, HTTPCore*, false> LinkImpl; - friend LinkImpl::Base; // calls tcp_* handlers - - void verify_frame() - { - if (!frame) - throw http_client_exception("frame undefined"); - } - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - bool inject_fault(const char *caller) - { - if (periodic_fail.trigger("httpcli", SIMULATE_HTTPCLI_FAILURES)) - { - OPENVPN_LOG("HTTPCLI BOGON on " << host.host_port_str() << " (" << caller << ')'); - error_handler(Status::E_BOGON, caller); - return true; - } - else - return false; - } -#endif - - void activity(const bool init) - { - const Time now = Time::now(); - if (general_timeout_duration.defined()) - { - const Time next = now + general_timeout_duration; - if (init || !general_timeout_coarse.similar(next)) - { - general_timeout_coarse.reset(next); - general_timer.expires_at(next); - general_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - self->general_timeout_handler(error); - }); - } - } - else if (init) - { - general_timeout_coarse.reset(); - general_timer.cancel(); - } - } - - void handle_request() // called by Asio - { - if (halt) - return; - - try { - if (ready) - throw http_client_exception("handle_request called in ready state"); - - verify_frame(); - - general_timeout_duration = Time::Duration::seconds(to.general >= 0 - ? to.general - : config->general_timeout); - general_timeout_coarse.reset(); - activity(true); - - // already in persistent session? - if (alive) - { - generate_request(); - return; - } - - host = http_host(); - -#ifdef ASIO_HAS_LOCAL_SOCKETS - // unix domain socket? - if (host.port == "unix") - { - openvpn_io::local::stream_protocol::endpoint ep(host.host_transport()); - AsioPolySock::Unix* s = new AsioPolySock::Unix(io_context, 0); - socket.reset(s); - s->socket.async_connect(ep, - [self=Ptr(this)](const openvpn_io::error_code& error) - { - self->handle_unix_connect(error); - }); - set_connect_timeout(config->connect_timeout); - return; - } -#endif -#ifdef OPENVPN_PLATFORM_WIN - // windows named pipe? - if (host.port == "np") - { - const std::string& ht = host.host_transport(); - const HANDLE h = ::CreateFileA( - ht.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - if (!Win::Handle::defined(h)) - { - const Win::LastError err; - OPENVPN_THROW(http_client_exception, "failed to open existing named pipe: " << ht << " : " << err.message()); - } - socket.reset(new AsioPolySock::NamedPipe(openvpn_io::windows::stream_handle(io_context, h), 0)); - do_connect(true); - set_connect_timeout(config->connect_timeout); - return; - } -#endif -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - // alt routing? - if (config->shim_factory) - { - AltRouting::Shim::Ptr shim = config->shim_factory->shim(host); - if (shim) - { - alt_routing_connect(std::move(shim)); - return; - } - } -#endif - - // standard TCP (with or without SSL) - if (host.port.empty()) - host.port = config->ssl_factory ? "443" : "80"; - - if (config->ssl_factory) - { - if (config->enable_cache) - { - std::string cache_key = host.cache_key(); - ssl_sess = config->ssl_factory->ssl(host.host_cn_ptr(), &cache_key); - } - else - ssl_sess = config->ssl_factory->ssl(host.host_cn_ptr(), nullptr); - } - - if (config->transcli) - { - transcli = config->transcli->new_transport_client_obj(io_context, this); - transcli->transport_start(); - } - else - { -#ifdef USE_ASYNC_RESOLVE - async_resolve_name(host.host_transport(), host.port); -#else - resolver.async_resolve(host.host_transport(), host.port, - [self=Ptr(this)](const openvpn_io::error_code& error, openvpn_io::ip::tcp::resolver::results_type results) - { - self->resolve_callback(error, results); - }); -#endif - } - set_connect_timeout(config->connect_timeout); - } - catch (const std::exception& e) - { - handle_exception("handle_request", e); - } - } - - void resolve_callback(const openvpn_io::error_code& error, // called by Asio - openvpn_io::ip::tcp::resolver::results_type results) - { - if (halt) - return; - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - if (inject_fault("resolve_callback")) - return; -#endif - - if (error) - { - asio_error_handler(Status::E_RESOLVE, "resolve_callback", error); - return; - } - - try { - http_mutate_resolver_results(results); - if (results.empty()) - OPENVPN_THROW_EXCEPTION("no results"); - - AsioPolySock::TCP* s = new AsioPolySock::TCP(io_context, 0); - socket.reset(s); - bind_local_addr(s); - - if (config->debug_level >= 2) - OPENVPN_LOG("TCP HTTP CONNECT to " << s->remote_endpoint_str() << " res=" << asio_resolver_results_to_string(results)); - - openvpn_io::async_connect(s->socket, std::move(results), - [self=Ptr(this)](const openvpn_io::error_code& error, const openvpn_io::ip::tcp::endpoint& endpoint) - { - self->handle_tcp_connect(error, endpoint); - }); - } - catch (const std::exception& e) - { - handle_exception("resolve_callback", e); - } - } - - void handle_tcp_connect(const openvpn_io::error_code& error, // called by Asio - const openvpn_io::ip::tcp::endpoint& endpoint) - { - if (halt) - return; - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - if (inject_fault("handle_tcp_connect")) - return; -#endif - - if (error) - { - asio_error_handler(Status::E_CONNECT, "handle_tcp_connect", error); - return; - } - - try { - do_connect(true); - } - catch (const std::exception& e) - { - handle_exception("handle_tcp_connect", e); - } - } - -#ifdef ASIO_HAS_LOCAL_SOCKETS - void handle_unix_connect(const openvpn_io::error_code& error) // called by Asio - { - if (halt) - return; - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - if (inject_fault("handle_unix_connect")) - return; -#endif - - if (error) - { - asio_error_handler(Status::E_CONNECT, "handle_unix_connect", error); - return; - } - - try { - do_connect(true); - } - catch (const std::exception& e) - { - handle_exception("handle_unix_connect", e); - } - } -#endif - -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - void alt_routing_connect(AltRouting::Shim::Ptr shim) - { - AltRoutingShimFactory& sf = *config->shim_factory; - - // build socket and assign shim - AsioPolySock::TCP* s = new AsioPolySock::TCP(io_context, 0); - socket.reset(s); - bind_local_addr(s); - s->socket.shim = std::move(shim); - - // build results - int port = sf.remote_port(); - if (port < 0) - port = HostPort::parse_port(host.port, "AltRouting"); - IP::Addr addr = sf.remote_ip(); - if (!addr.defined()) - addr = IP::Addr(host.host_transport(), "AltRouting"); - openvpn_io::ip::tcp::resolver::results_type results = - openvpn_io::ip::tcp::resolver::results_type::create(openvpn_io::ip::tcp::endpoint(addr.to_asio(), - port), - host.host, - ""); - - if (config->debug_level >= 2) - OPENVPN_LOG("ALT_ROUTING HTTP CONNECT to " << s->remote_endpoint_str() << " res=" << asio_resolver_results_to_string(results)); - - // do async connect - openvpn_io::async_connect(s->socket, std::move(results), - [self=Ptr(this)](const openvpn_io::error_code& error, const openvpn_io::ip::tcp::endpoint& endpoint) - { - self->handle_tcp_connect(error, endpoint); - }); - - // set connect timeout - { - unsigned int ct = sf.connect_timeout(); - if (ct < 0) - ct = config->connect_timeout; - set_connect_timeout(ct); - } - } -#endif - - void do_connect(const bool use_link) - { - connect_timer.cancel(); - set_default_stats(); - - if (use_link) - { - socket->set_cloexec(); - socket->tcp_nodelay(); - http_post_connect(*socket); - link.reset(new LinkImpl(this, - *socket, - 0, // send_queue_max_size (unlimited) - 8, // free_list_max_size - (*frame)[Frame::READ_HTTP], - stats)); - link->set_raw_mode(true); - link->start(); - } - - if (ssl_sess) - ssl_sess->start_handshake(); - - // xmit the request - generate_request(); - } - - void set_connect_timeout(unsigned int connect_timeout) - { - if (config->connect_timeout) - { - connect_timer.expires_after(Time::Duration::seconds(to.connect >= 0 - ? to.connect - : connect_timeout)); - connect_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - self->connect_timeout_handler(error); - }); - } - } - - void bind_local_addr(AsioPolySock::TCP* s) - { - // optionally bind to local addr/port - if (!host.local_addr.empty()) - { -#if defined(OPENVPN_POLYSOCK_SUPPORTS_BIND) || defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - const IP::Addr local_addr(host.local_addr, "local_addr"); - unsigned short local_port = 0; - if (!host.local_port.empty()) - local_port = HostPort::parse_port(host.local_port, "local_port"); - s->socket.bind_local(local_addr, local_port); -#else - throw Exception("httpcli must be built with OPENVPN_POLYSOCK_SUPPORTS_BIND or OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING to support local bind"); -#endif - } - } - - void schedule_keepalive_timer() - { - if (config->keepalive_timeout || to.keepalive >= 0) - { - const Time::Duration dur = Time::Duration::seconds(to.keepalive >= 0 - ? to.keepalive - : config->keepalive_timeout); - if (!keepalive_timer) - keepalive_timer.reset(new AsioTimerSafe(io_context)); - keepalive_timer->expires_after(dur); - keepalive_timer->async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!self->halt && !error && self->ready) - { - self->error_handler(Status::E_KEEPALIVE_TIMEOUT, "Keepalive timeout"); - } - }); - } - } - - void cancel_keepalive_timer() - { - if (keepalive_timer) - keepalive_timer->cancel(); - } - - void cancel_general_timeout() - { - general_timeout_duration.set_zero(); - general_timer.cancel(); - } - - void general_timeout_handler(const openvpn_io::error_code& e) // called by Asio - { - if (!halt && !e) - error_handler(Status::E_GENERAL_TIMEOUT, "General timeout"); - } - - void connect_timeout_handler(const openvpn_io::error_code& e) // called by Asio - { - if (!halt && !e) - error_handler(Status::E_CONNECT_TIMEOUT, "Connect timeout"); - } - - void set_default_stats() - { - if (!stats) - stats.reset(new SessionStats()); - } - - void generate_request() - { - rr_reset(); - http_out_begin(); - - const Request req = http_request(); - content_info = http_content_info(); - - outbuf.reset(new BufferAllocated(512, BufferAllocated::GROW)); - BufferStreamOut os(*outbuf); - - if (content_info.websocket) - { - // no content-out until after server reply (content_out_hold kept at true) - generate_request_websocket(os, req); - } - else - { - // non-websocket allows immediate content-out - content_out_hold = false; - generate_request_http(os, req); - } - - http_headers_sent(*outbuf); - http_out(); - } - - void generate_request_http(std::ostream& os, const Request& req) - { - os << req.method << ' ' << req.uri << " HTTP/1.1\r\n"; - if (!content_info.lean_headers) - { - os << "Host: " << host.host_head() << "\r\n"; - if (!config->user_agent.empty()) - os << "User-Agent: " << config->user_agent << "\r\n"; - } - generate_basic_auth_headers(os, req); - if (content_info.length) - os << "Content-Type: " << content_info.type << "\r\n"; - if (content_info.length > 0) - os << "Content-Length: " << content_info.length << "\r\n"; - else if (content_info.length == ContentInfo::CHUNKED) - os << "Transfer-Encoding: chunked" << "\r\n"; - for (auto &h : content_info.extra_headers) - os << h << "\r\n"; - if (!content_info.content_encoding.empty()) - os << "Content-Encoding: " << content_info.content_encoding << "\r\n"; - if (content_info.keepalive) - os << "Connection: keep-alive\r\n"; - if (!content_info.lean_headers) - os << "Accept: */*\r\n"; - os << "\r\n"; - } - - void generate_request_websocket(std::ostream& os, const Request& req) - { - os << req.method << ' ' << req.uri << " HTTP/1.1\r\n"; - os << "Host: " << host.host_head() << "\r\n"; - if (!config->user_agent.empty()) - os << "User-Agent: " << config->user_agent << "\r\n"; - generate_basic_auth_headers(os, req); - if (content_info.length) - os << "Content-Type: " << content_info.type << "\r\n"; - if (content_info.websocket) - content_info.websocket->client_headers(os); - for (auto &h : content_info.extra_headers) - os << h << "\r\n"; - os << "\r\n"; - } - - void generate_basic_auth_headers(std::ostream& os, const Request& req) - { - if (!req.username.empty() || !req.password.empty()) - os << "Authorization: Basic " - << base64->encode(req.username + ':' + req.password) - << "\r\n"; - } - - // error handlers - - void asio_error_handler(int errcode, const char *func_name, const openvpn_io::error_code& error) - { - error_handler(errcode, std::string("HTTPCore Asio ") + func_name + ": " + error.message()); - } - - void handle_exception(const char *func_name, const std::exception& e) - { - error_handler(Status::E_EXCEPTION, std::string("HTTPCore Exception ") + func_name + ": " + e.what()); - } - - void error_handler(const int errcode, const std::string& err) - { - const bool in_transaction = !ready; - const bool keepalive = alive; - const bool error = Status::is_error(errcode); -#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING) - if (config->shim_factory && error && in_transaction && socket) - config->shim_factory->report_error(host, socket->alt_routing_enabled()); -#endif - stop(!error); - if (in_transaction) - http_done(errcode, err); - else if (keepalive) - http_keepalive_close(errcode, err); // keepalive connection close outside of transaction - } - - // methods called by LinkImpl - - bool tcp_read_handler(BufferAllocated& b) - { - if (halt) - return false; - - try { -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - if (inject_fault("tcp_read_handler")) - return false; -#endif - activity(false); - tcp_in(b); // call Base - return true; - } - catch (const std::exception& e) - { - handle_exception("tcp_read_handler", e); - return false; - } - } - - void tcp_write_queue_needs_send() - { - if (halt) - return; - - try { - http_out(); - } - catch (const std::exception& e) - { - handle_exception("tcp_write_queue_needs_send", e); - } - - } - - void tcp_eof_handler() - { - if (halt) - return; - - try { - error_handler(Status::E_EOF_TCP, "TCP EOF"); - return; - } - catch (const std::exception& e) - { - handle_exception("tcp_eof_handler", e); - } - } - - void tcp_error_handler(const char *error) - { - if (halt) - return; - error_handler(Status::E_TCP, std::string("HTTPCore TCP: ") + error); - } - - // methods called by Base - - BufferPtr base_http_content_out() - { - return http_content_out(); - } - - void base_http_content_out_needed() - { - if (!content_out_hold) - http_content_out_needed(); - } - - void base_http_out_eof() - { - if (websocket) - { - stop(true); - http_done(Status::E_SUCCESS, "Succeeded"); - } - } - - bool base_http_headers_received() - { - if (content_info.websocket) - websocket = true; // enable websocket in httpcommon - http_headers_received(); - return true; // continue to receive content - } - - void base_http_content_in(BufferAllocated& buf) - { - http_content_in(buf); - } - - bool base_link_send(BufferAllocated& buf) - { - try { -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - if (inject_fault("base_link_send")) - return false; -#endif - activity(false); - if (transcli) - return transcli->transport_send(buf); - else - return link->send(buf); - } - catch (const std::exception& e) - { - handle_exception("base_link_send", e); - return false; - } - } - - bool base_send_queue_empty() - { - if (transcli) - return transcli->transport_send_queue_empty(); - else - return link->send_queue_empty(); - } - - void base_http_done_handler(BufferAllocated& residual, - const bool parent_handoff) - { - if (halt) - return; - if ((content_info.keepalive || parent_handoff) && !websocket) - { - general_timer.cancel(); - schedule_keepalive_timer(); - alive = true; - ready = true; - } - else - stop(true); - http_done(Status::E_SUCCESS, "Succeeded"); - } - - void base_error_handler(const int errcode, const std::string& err) - { - error_handler(errcode, err); - } - - // TransportClientParent methods - - virtual bool transport_is_openvpn_protocol() - { - return false; - } - - virtual void transport_recv(BufferAllocated& buf) - { - tcp_read_handler(buf); - } - - virtual void transport_needs_send() - { - tcp_write_queue_needs_send(); - } - - std::string err_fmt(const Error::Type fatal_err, const std::string& err_text) - { - std::ostringstream os; - if (fatal_err != Error::SUCCESS) - os << Error::name(fatal_err) << " : "; - os << err_text; - return os.str(); - } - - virtual void transport_error(const Error::Type fatal_err, const std::string& err_text) - { - return error_handler(Status::E_TRANSPORT, err_fmt(fatal_err, err_text)); - } - - virtual void proxy_error(const Error::Type fatal_err, const std::string& err_text) - { - return error_handler(Status::E_PROXY, err_fmt(fatal_err, err_text)); - } - - virtual void transport_pre_resolve() - { - } - - virtual void transport_wait_proxy() - { - } - - virtual void transport_wait() - { - } - - virtual bool is_keepalive_enabled() const - { - return false; - } - - virtual void disable_keepalive(unsigned int& keepalive_ping, - unsigned int& keepalive_timeout) - { - } - - virtual void transport_connecting() - { - do_connect(false); - } - - openvpn_io::io_context& io_context; - - TimeoutOverride to; - - AsioPolySock::Base::Ptr socket; - -#ifndef USE_ASYNC_RESOLVE - openvpn_io::ip::tcp::resolver resolver; -#endif - Host host; - - LinkImpl::Ptr link; - - TransportClient::Ptr transcli; - - AsioTimerSafe connect_timer; - AsioTimerSafe general_timer; - std::unique_ptr<AsioTimerSafe> req_timer; - std::unique_ptr<AsioTimerSafe> keepalive_timer; - - Time::Duration general_timeout_duration; - CoarseTime general_timeout_coarse; - - bool content_out_hold = true; - bool alive = false; - -#ifdef SIMULATE_HTTPCLI_FAILURES // debugging -- simulate network failures - PeriodicFail periodic_fail; -#endif - }; - - template <typename PARENT> - class HTTPDelegate : public HTTPCore - { - public: - OPENVPN_EXCEPTION(http_delegate_error); - - typedef RCPtr<HTTPDelegate> Ptr; - - HTTPDelegate(openvpn_io::io_context& io_context, - WS::Client::Config::Ptr config, - PARENT* parent) - : WS::Client::HTTPCore(io_context, std::move(config)), - parent_(parent) - { - } - - void attach(PARENT* parent) - { - parent_ = parent; - } - - void detach(const bool keepalive, const bool shutdown) - { - if (parent_) - { - parent_ = nullptr; - if (!keepalive) - stop(shutdown); - } - } - - PARENT* parent() - { - return parent_; - } - - virtual Host http_host() - { - if (parent_) - return parent_->http_host(*this); - else - throw http_delegate_error("http_host"); - } - - virtual Request http_request() - { - if (parent_) - return parent_->http_request(*this); - else - throw http_delegate_error("http_request"); - } - - virtual ContentInfo http_content_info() - { - if (parent_) - return parent_->http_content_info(*this); - else - throw http_delegate_error("http_content_info"); - } - - virtual BufferPtr http_content_out() - { - if (parent_) - return parent_->http_content_out(*this); - else - throw http_delegate_error("http_content_out"); - } - - virtual void http_content_out_needed() - { - if (parent_) - parent_->http_content_out_needed(*this); - else - throw http_delegate_error("http_content_out_needed"); - } - - virtual void http_headers_received() - { - if (parent_) - parent_->http_headers_received(*this); - } - - virtual void http_headers_sent(const Buffer& buf) - { - if (parent_) - parent_->http_headers_sent(*this, buf); - } - - virtual void http_mutate_resolver_results(openvpn_io::ip::tcp::resolver::results_type& results) - { - if (parent_) - parent_->http_mutate_resolver_results(*this, results); - } - - virtual void http_content_in(BufferAllocated& buf) - { - if (parent_) - parent_->http_content_in(*this, buf); - } - - virtual void http_done(const int status, const std::string& description) - { - if (parent_) - parent_->http_done(*this, status, description); - } - - virtual void http_keepalive_close(const int status, const std::string& description) - { - if (parent_) - parent_->http_keepalive_close(*this, status, description); - } - - virtual void http_post_connect(AsioPolySock::Base& sock) - { - if (parent_) - parent_->http_post_connect(*this, sock); - } - - private: - PARENT* parent_; - }; - } - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/httpcliset.hpp b/Sources/OpenVPN3/openvpn/ws/httpcliset.hpp deleted file mode 100644 index 7cccf82..0000000 --- a/Sources/OpenVPN3/openvpn/ws/httpcliset.hpp +++ /dev/null @@ -1,959 +0,0 @@ -// 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-2020 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 <sstream> -#include <ostream> -#include <vector> -#include <memory> -#include <utility> -#include <algorithm> -#include <limits> -#include <map> - -#include <openvpn/asio/asiostop.hpp> -#include <openvpn/common/cleanup.hpp> -#include <openvpn/common/function.hpp> -#include <openvpn/common/complog.hpp> -#include <openvpn/time/asiotimersafe.hpp> -#include <openvpn/buffer/buflist.hpp> -#include <openvpn/buffer/bufstr.hpp> -#include <openvpn/buffer/zlib.hpp> -#include <openvpn/random/randapi.hpp> -#include <openvpn/http/urlparse.hpp> -#include <openvpn/http/headredact.hpp> -#include <openvpn/ws/httpcli.hpp> -#include <openvpn/ws/resolver_results.hpp> - -#ifndef OPENVPN_HTTP_CLISET_RC -#define OPENVPN_HTTP_CLISET_RC RC<thread_unsafe_refcount> -#endif - -namespace openvpn { - namespace WS { - - class ClientSet : public RC<thread_unsafe_refcount> - { - class Client; - - public: - typedef RCPtr<ClientSet> Ptr; - - typedef WS::Client::HTTPDelegate<Client> HTTPDelegate; - - struct SyncPersistState - { - std::unique_ptr<openvpn_io::io_context> io_context; - }; - - class HTTPStateContainer - { - public: - void create_container() - { - if (!c) - c.reset(new Container); - } - - void stop(const bool shutdown) - { - if (c && c->http) - c->http->stop(shutdown); - } - - void reset() - { - if (c) - c->http.reset(); - } - - void abort(const std::string& message) - { - if (c && c->http) - c->http->abort(message); - } - - bool alive() const - { - return c && c->http && c->http->is_alive(); - } - - bool alive(const std::string& host) const - { - return alive() && c->http->host_match(host); - } - -#ifdef ASIO_HAS_LOCAL_SOCKETS - int unix_fd() - { - if (!c || !c->http) - return -1; - AsioPolySock::Unix* us = dynamic_cast<AsioPolySock::Unix*>(c->http->get_socket()); - if (!us) - return -1; - return us->socket.native_handle(); - } -#endif - - private: - friend Client; - - struct Container : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Container> Ptr; - HTTPDelegate::Ptr http; - }; - - void attach(Client* parent) - { - c->http->attach(parent); - } - - void close(const bool keepalive, const bool shutdown) - { - if (c && c->http) - { - c->http->detach(keepalive, shutdown); - if (!keepalive) - stop(shutdown); - } - } - - void construct(openvpn_io::io_context& io_context, - const WS::Client::Config::Ptr config) - { - create_container(); - close(false, false); - c->http.reset(new HTTPDelegate(io_context, std::move(config), nullptr)); - } - - void start_request() - { - c->http->start_request(); - } - - Container::Ptr c; - }; - - class TransactionSet; - struct Transaction; - - struct ErrorRecovery : public RC<thread_unsafe_refcount> - { - typedef RCPtr<ErrorRecovery> Ptr; - virtual void retry(TransactionSet& ts, Transaction& t) = 0; - }; - - struct Transaction - { - static constexpr int UNDEF = -1; - - // input - WS::Client::Request req; - WS::Client::ContentInfo ci; - BufferList content_out; - bool accept_gzip_in = false; - bool randomize_resolver_results = false; - IP::Addr::Version ip_version_preference = IP::Addr::UNSPEC; - - // output - int status = UNDEF; - std::string description; - HTTP::Reply reply; - BufferList content_in; - - std::string url(const TransactionSet& ts) const - { - URL::Parse u = URL::Parse::from_components(bool(ts.http_config->ssl_factory), - ts.host.host, - ts.host.port, - req.uri); - return u.to_string(); - } - - std::string title(const TransactionSet& ts) const - { - return req.method + ' ' + url(ts); - } - - void compress_content_out(const unsigned int min_size=64, - const bool verbose=false) - { -#ifdef HAVE_ZLIB - if (content_out.join_size() >= min_size) - { - BufferPtr co = content_out.join(); - content_out.clear(); - const size_t orig_size = co->size(); - co = ZLib::compress_gzip(co, 0, 0, 1); - if (verbose) - log_compress("HTTPClientSet: GZIP COMPRESS", orig_size, co->size()); - ci.length = co->size(); - content_out.push_back(std::move(co)); - ci.content_encoding = "gzip"; - } -#endif - } - - // Return true if and only if HTTP transaction - // succeeded AND HTTP status code was in the - // successful range of 2xx. - bool http_status_success() const - { - return comm_status_success() && request_status_success(); - } - - // Return true if communication succeeded - bool comm_status_success() const - { - return status == WS::Client::Status::E_SUCCESS; - } - - bool comm_status_timeout() const - { - return status == WS::Client::Status::E_CONNECT_TIMEOUT; - } - - // Return true if request succeeded, i.e. HTTP status - // code was in the successful range of 2xx. - bool request_status_success() const - { - return reply.status_code >= 200 && reply.status_code < 300; - } - - bool is_redirect() const - { - return reply.status_code >= 300 && reply.status_code < 400 && reply.headers.get("location"); - } - - std::string get_redirect_location() const - { - return reply.headers.get_value_trim("location"); - } - - void dump(std::ostream& os, const TransactionSet& ts) const - { - os << "----- " << format_status(ts) << " -----\n"; - BufferPtr in = content_in.join(); - const std::string s = buf_to_string(*in); - os << s; - if (!s.empty() && !string::ends_with_newline(s)) - os << '\n'; - } - - std::string content_in_string() const - { - BufferPtr in = content_in.join(); - return buf_to_string(*in); - } - - BufferPtr content_in_buffer() const - { - return content_in.join(); - } - - std::string format_status(const TransactionSet& ts) const - { - std::string ret; - ret.reserve(256); - ret += title(ts); - ret += " : "; - ret += format_status(); - return ret; - } - - std::string format_status() const - { - std::string ret; - ret.reserve(64); - if (status == WS::Client::Status::E_SUCCESS) - { - ret += openvpn::to_string(reply.status_code); - ret += ' '; - ret += reply.status_text; - } - else - { - ret += WS::Client::Status::error_str(status); - ret += ' '; - ret += description; - } - return ret; - } - }; - - class TransactionSet : public RC<thread_unsafe_refcount> - { - private: - // optionally contains an openvpn_io::io_context for - // persistent synchronous operations - friend class ClientSet; - SyncPersistState sps; - - public: - typedef RCPtr<TransactionSet> Ptr; - typedef std::vector<std::unique_ptr<Transaction>> Vector; - - // Enable preserve_http_state to reuse HTTP session - // across multiple completions. - // hsc.stop() can be called to explicitly - // close persistent state. - bool preserve_http_state = false; - HTTPStateContainer hsc; - - // configuration - WS::Client::Config::Ptr http_config; - WS::Client::Host host; - unsigned int max_retries = 1; - int debug_level = 2; - Time::Duration delayed_start; - Time::Duration retry_duration = Time::Duration::seconds(5); - - // request/response vector - Vector transactions; - - // true if all requests were successful - bool status = false; - - // completion method - Function<void(TransactionSet& ts)> completion; - - // post-connect method, useful to validate server - // on local sockets - Function<void(TransactionSet& ts, AsioPolySock::Base& sock)> post_connect; - - // error recovery method, called before we retry a request - // after an error to possibly modify connection parameters - // such as the hostname. - ErrorRecovery::Ptr error_recovery; - - void assign_http_state(HTTPStateContainer& http_state) - { - http_state.create_container(); - hsc = http_state; - preserve_http_state = true; - } - - bool alive() const - { - return hsc.alive(host.host); - } - - WS::ClientSet::Transaction& first_transaction() - { - if (transactions.empty()) - throw Exception("TransactionSet::first_transaction: transaction list is empty"); - return *transactions[0]; - } - - // Return true if and only if all HTTP transactions - // succeeded AND each HTTP status code was in the - // successful range of 2xx. - bool http_status_success() const - { - if (!status) - return false; - if (transactions.empty()) - return false; - for (auto &t : transactions) - { - if (!t->http_status_success()) - return false; - } - return true; - } - - void reset_callbacks() - { - completion.reset(); - post_connect.reset(); - } - - void stop(const bool shutdown) - { - reset_callbacks(); - hsc.stop(shutdown); - } - - void dump(std::ostream& os, const bool content_only=false) const - { - for (auto &t : transactions) - { - if (content_only) - os << t->content_in_string(); - else - t->dump(os, *this); - } - } - }; - - class HostRetry : public std::vector<std::string>, - public ErrorRecovery - { - public: - typedef RCPtr<HostRetry> Ptr; - - HostRetry() {} - - template<typename T, typename... Args> - HostRetry(T first, Args... args) - { - reserve(1 + sizeof...(args)); - from_list(first, args...); - } - - void shuffle(RandomAPI& prng) - { - std::shuffle(begin(), end(), prng); - index = 0; - } - - std::string next_host() - { - if (empty()) - throw Exception("HostRetry: empty host list"); - if (index >= size()) - index = 0; - return (*this)[index++]; - } - - virtual void retry(TransactionSet& ts, Transaction& t) override - { - ts.host.host = next_host(); - } - - private: - void from_list(std::string arg) - { - push_back(std::move(arg)); - } - - void from_list(const char *arg) - { - push_back(std::string(arg)); - } - - template<typename T, typename... Args> - void from_list(T first, Args... args) - { - from_list(first); - from_list(args...); - } - - size_t index = 0; - }; - - ClientSet(openvpn_io::io_context& io_context_arg) - : io_context(io_context_arg), - halt(false), - next_id(0) - { - } - - void set_random(RandomAPI::Ptr prng_arg) - { - prng = std::move(prng_arg); - } - - void new_request(const TransactionSet::Ptr ts) - { - const client_t id = new_client_id(); - Client::Ptr cli = new Client(this, std::move(ts), id); - clients[id] = cli; - cli->start(); - } - - static void new_request_synchronous(const TransactionSet::Ptr ts, - Stop* stop=nullptr, - RandomAPI* prng=nullptr, - const bool sps=false) - { - std::unique_ptr<openvpn_io::io_context> io_context; - auto clean = Cleanup([&]() { - // ensure that TransactionSet reference to socket - // is reset before method returns (unless sps is true - // in which case we should retain it). - if (!sps) - ts->hsc.reset(); - }); - ts->preserve_http_state = sps; - if (sps) - io_context = std::move(ts->sps.io_context); - if (!io_context) - io_context.reset(new openvpn_io::io_context(1)); - ClientSet::Ptr cs; - try { - AsioStopScope scope(*io_context, stop, [&]() { - if (cs) - cs->abort("stop message received"); - }); - cs.reset(new ClientSet(*io_context)); - if (prng) - cs->set_random(RandomAPI::Ptr(prng)); - cs->new_request(ts); - if (sps) - { - while (cs->clients.size()) - io_context->run_one(); - } - else - io_context->run(); - } - catch (...) - { - if (cs) - cs->stop(); // on exception, stop ClientSet - io_context->poll(); // execute completion handlers - throw; - } - if (sps) - ts->sps.io_context = std::move(io_context); - } - - static void run_synchronous(Function<void(ClientSet::Ptr)> job, - Stop* stop=nullptr, - RandomAPI* prng=nullptr) - { - std::unique_ptr<openvpn_io::io_context> io_context(new openvpn_io::io_context(1)); - ClientSet::Ptr cs; - try { - AsioStopScope scope(*io_context, stop, [&]() { - if (cs) - cs->abort("stop message received"); - }); - cs.reset(new ClientSet(*io_context)); - cs->set_random(prng); - job(cs); - io_context->run(); - } - catch (...) - { - if (cs) - cs->stop(); // on exception, stop ClientSet - io_context->poll(); // execute completion handlers - throw; - } - } - - void stop() - { - if (halt) - return; - halt = true; - for (auto &c : clients) - { - c.second->stop(false, false); - c.second->reset_callbacks(); - } - } - - void abort(const std::string& message) - { - for (auto &c : clients) - c.second->abort(message); - } - - private: - typedef unsigned int client_t; - - class Client : public OPENVPN_HTTP_CLISET_RC - { - public: - typedef RCPtr<Client> Ptr; - friend HTTPDelegate; - - Client(ClientSet* parent_arg, - const TransactionSet::Ptr ts_arg, - client_t client_id_arg) - : parent(parent_arg), - ts(std::move(ts_arg)), - n_retries(0), - buf_tailroom((*ts->http_config->frame)[Frame::READ_HTTP].tailroom()), - reconnect_timer(parent_arg->io_context), - client_id(client_id_arg), - halt(false), - started(false) - { - } - - bool start() - { - if (started || halt) - return false; - started = true; - ts->status = false; - ts_iter = ts->transactions.begin(); - if (ts->delayed_start.defined()) - { - retry_duration = ts->delayed_start; - reconnect_schedule(false); - } - else - { - next_request(false); - } - return true; - } - - void stop(const bool keepalive, const bool shutdown) - { - if (halt) - return; - halt = true; - reconnect_timer.cancel(); - close_http(keepalive, shutdown); - } - - void reset_callbacks() - { - if (ts) - ts->reset_callbacks(); // break refcount cycles in callback closures - } - - void abort(const std::string& message) - { - if (ts) - ts->hsc.abort(message); - } - - private: - void close_http(const bool keepalive, const bool shutdown) - { - ts->hsc.close(keepalive, shutdown); - } - - void remove_self_from_map() - { - openvpn_io::post(parent->io_context, [id=client_id, parent=ClientSet::Ptr(parent)]() - { - parent->remove_client_id(id); - }); - } - - bool check_if_done() - { - if (ts_iter == ts->transactions.end()) - { - done(true, true); - return true; - } - else - return false; - } - - void done(const bool status, const bool shutdown) - { - { - auto clean = Cleanup([this, shutdown]() { - if (!ts->preserve_http_state) - ts->hsc.stop(shutdown); - }); - stop(status, shutdown); - remove_self_from_map(); - ts->status = status; - } - if (ts->completion) - ts->completion(*ts); - } - - Transaction& trans() - { - return **ts_iter; - } - - const Transaction& trans() const - { - return **ts_iter; - } - - std::string title() const - { - return trans().title(*ts); - } - - void next_request(const bool error_retry) - { - if (check_if_done()) - return; - - retry_duration = ts->retry_duration; - - // get current transaction - Transaction& t = trans(); - - // set up content out iterator - out_iter = t.content_out.begin(); - - // init buffer to receive content in - t.content_in.clear(); - - // if this is an error retry, allow user-defined recovery - if (error_retry && ts->error_recovery) - ts->error_recovery->retry(*ts, t); - - // init and attach HTTPStateContainer - if (!ts->alive()) - ts->hsc.construct(parent->io_context, ts->http_config); - ts->hsc.attach(this); - - ts->hsc.start_request(); - } - - void reconnect_schedule(const bool error_retry) - { - if (check_if_done()) - return; - reconnect_timer.expires_after(retry_duration); - reconnect_timer.async_wait([self=Ptr(this), error_retry](const openvpn_io::error_code& error) - { - if (!error && !self->halt) - self->next_request(error_retry); - }); - } - - WS::Client::Host http_host(HTTPDelegate& hd) const - { - return ts->host; - } - - WS::Client::Request http_request(HTTPDelegate& hd) const - { - return trans().req; - } - - WS::Client::ContentInfo http_content_info(HTTPDelegate& hd) const - { - const Transaction& t = trans(); - WS::Client::ContentInfo ci = t.ci; - if (!ci.length) - ci.length = t.content_out.join_size(); -#ifdef HAVE_ZLIB - if (t.accept_gzip_in) - ci.extra_headers.emplace_back("Accept-Encoding: gzip"); -#endif - return ci; - } - - void http_headers_received(HTTPDelegate& hd) - { - if (ts->debug_level >= 2) - { - std::ostringstream os; - os << "----- HEADERS RECEIVED -----\n"; - os << " " << title() << '\n'; - os << " ENDPOINT: " << hd.remote_endpoint_str() << '\n'; - os << " HANDSHAKE_DETAILS: " << hd.ssl_handshake_details() << '\n'; - os << " CONTENT-LENGTH: " << hd.content_length() << '\n'; - os << " HEADERS: " << string::indent(HTTP::headers_redact(hd.reply().to_string()), 0, 13) << '\n'; - OPENVPN_LOG_STRING(os.str()); - } - - Transaction& t = trans(); - - // save reply - t.reply = hd.reply(); - } - - BufferPtr http_content_out(HTTPDelegate& hd) - { - if (out_iter != trans().content_out.end()) - { - BufferPtr ret = new BufferAllocated(**out_iter); - ++out_iter; - return ret; - } - else - return BufferPtr(); - } - - void http_content_out_needed(HTTPDelegate& hd) - { - } - - void http_headers_sent(HTTPDelegate& hd, const Buffer& buf) - { - if (ts->debug_level >= 2) - { - std::ostringstream os; - os << "----- HEADERS SENT -----\n"; - os << " " << title() << '\n'; - os << " ENDPOINT: " << hd.remote_endpoint_str() << '\n'; - os << " HEADERS: " << string::indent(HTTP::headers_redact(buf_to_string(buf)), 0, 13) << '\n'; - OPENVPN_LOG_STRING(os.str()); - } - } - - void http_mutate_resolver_results(HTTPDelegate& hd, openvpn_io::ip::tcp::resolver::results_type& results) - { - // filter results by IP version - if (trans().ip_version_preference != IP::Addr::UNSPEC) - filter_by_ip_version(results, trans().ip_version_preference); - - // randomize results - if (parent->prng && trans().randomize_resolver_results) - randomize_results(results, *parent->prng); - } - - void http_content_in(HTTPDelegate& hd, BufferAllocated& buf) - { - trans().content_in.put_consume(buf, buf_tailroom); - } - - void http_done(HTTPDelegate& hd, const int status, const std::string& description) - { - Transaction& t = trans(); - try { - // debug output - if (ts->debug_level >= 2) - { - std::ostringstream os; - os << "----- DONE -----\n"; - os << " " << title() << '\n'; - os << " STATUS: " << WS::Client::Status::error_str(status) << '\n'; - os << " DESCRIPTION: " << description << '\n'; - OPENVPN_LOG_STRING(os.str()); - } - - // save status - t.status = status; - t.description = description; - - if (status == WS::Client::Status::E_SUCCESS && !http_status_should_retry(hd.reply().status_code)) - { - // uncompress if server sent gzip-compressed data - if (hd.reply().headers.get_value_trim("content-encoding") == "gzip") - { -#ifdef HAVE_ZLIB - BufferPtr bp = t.content_in.join(); - t.content_in.clear(); - bp = ZLib::decompress_gzip(std::move(bp), 0, 0, hd.http_config().max_content_bytes); - t.content_in.push_back(std::move(bp)); -#else - throw Exception("gzip-compressed data returned from server but app not linked with zlib"); -#endif - } - - // do next request - ++ts_iter; - - // Post a call to next_request() under a fresh stack. - // Currently we may actually be under tcp_read_handler() and - // next_request() can trigger destructors. - post_next_request(); - } - else - { - // failed - if (++n_retries >= ts->max_retries) - { - // fail -- no more retries - done(false, false); - } - else - { - // fail -- retry - close_http(false, false); - - // special case -- no delay after TCP EOF on first retry - if (status == WS::Client::Status::E_EOF_TCP && n_retries == 1) - post_next_request(); - else - reconnect_schedule(true); - } - } - } - catch (const std::exception& e) - { - t.status = WS::Client::Status::E_EXCEPTION; - t.description = std::string("http_done: ") + e.what(); - if (!halt) - done(false, false); - } - } - - void post_next_request() - { - openvpn_io::post(parent->io_context, [self=Ptr(this)]() - { - self->next_request(false); - }); - } - - void http_keepalive_close(HTTPDelegate& hd, const int status, const std::string& description) - { - // this may be a no-op because ts->hsc.alive() is always tested before construction - //OPENVPN_LOG("http_keepalive_close " << WS::Client::Status::error_str(status) << " description=" << description << " http_status=" << std::to_string(hd.reply().status_code) << " http_text=" << hd.reply().status_text); - } - - void http_post_connect(HTTPDelegate& hd, AsioPolySock::Base& sock) - { - if (ts->post_connect) - ts->post_connect(*ts, sock); - } - - bool http_status_should_retry(const int status) const - { - return status >= 500 && status < 600; - } - - ClientSet* parent; - TransactionSet::Ptr ts; - TransactionSet::Vector::const_iterator ts_iter; - BufferList content_out; - BufferList::const_iterator out_iter; - unsigned int n_retries; - unsigned int buf_tailroom; - Time::Duration retry_duration; - AsioTimerSafe reconnect_timer; - client_t client_id; - bool halt; - bool started; - }; - - void remove_client_id(const client_t client_id) - { - auto e = clients.find(client_id); - if (e != clients.end()) - clients.erase(e); - } - - client_t new_client_id() - { - while (true) - { - // find an ID that's not already in use - const client_t id = next_id++; - if (clients.find(id) == clients.end()) - return id; - } - } - - openvpn_io::io_context& io_context; - bool halt; - client_t next_id; - RandomAPI::Ptr prng; - std::map<client_t, Client::Ptr> clients; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/httpcommon.hpp b/Sources/OpenVPN3/openvpn/ws/httpcommon.hpp deleted file mode 100644 index 1a08367..0000000 --- a/Sources/OpenVPN3/openvpn/ws/httpcommon.hpp +++ /dev/null @@ -1,560 +0,0 @@ -// 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-2020 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 - -// HTTP code common to both clients and servers - -#include <string> -#include <memory> -#include <utility> - -#include <openvpn/common/size.hpp> -#include <openvpn/common/exception.hpp> -#include <openvpn/common/number.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/http/header.hpp> -#include <openvpn/http/status.hpp> -#include <openvpn/ssl/sslapi.hpp> -#include <openvpn/ssl/sslconsts.hpp> -#include <openvpn/ws/chunked.hpp> - -namespace openvpn { - namespace WS { - OPENVPN_EXCEPTION(http_exception); - - template <typename PARENT, - typename CONFIG, - typename STATUS, - typename REQUEST_REPLY, - typename CONTENT_INFO, - typename CONTENT_LENGTH_TYPE, // must be signed - typename REFCOUNT_BASE - > - class HTTPBase : public REFCOUNT_BASE - { - friend ChunkedHelper; - - enum HTTPOutState { - S_PRE, - S_OUT, - S_DEFERRED, - S_EOF, - S_DONE - }; - - public: - void rr_reset() - { - rr_obj.reset(); - rr_status = REQUEST_REPLY::Parser::pending; - rr_parser.reset(); - rr_header_bytes = 0; - rr_content_length = 0; - rr_content_bytes = 0; - rr_limit_bytes = 0; - rr_chunked.reset(); - max_content_bytes = config->max_content_bytes; - out_state = S_PRE; - } - - void reset() - { - if (halt) - { - halt = false; - ready = true; - } - } - - bool is_ready() const { - return !halt && ready; - } - - bool is_websocket() const { - return websocket; - } - - // If true, indicates that data can be transmitted - // now with immediate dispatch. - bool is_deferred() const - { - return out_state == S_DEFERRED; - } - - bool http_in_started() const - { - return rr_content_bytes > CONTENT_LENGTH_TYPE(0); - } - - bool http_out_started() const - { - return out_state != S_PRE; - } - - const typename REQUEST_REPLY::State& request_reply() const { - return rr_obj; - } - - const HTTP::HeaderList& headers() const { - return rr_obj.headers; - } - - const olong content_length() const { - return rr_content_length; - } - - std::string ssl_handshake_details() const { - if (ssl_sess) - return ssl_sess->ssl_handshake_details(); - else - return ""; - } - - bool ssl_did_full_handshake() const { - if (ssl_sess) - return ssl_sess->did_full_handshake(); - else - return false; - } - - void ssl_no_cache() - { - if (ssl_sess) - ssl_sess->mark_no_cache(); - } - - const CONFIG& http_config() const { - return *config; - } - - void set_async_out(const bool async_out_arg) - { - async_out = async_out_arg; - } - - void http_content_out_finish(BufferPtr buf) - { - if (halt) - return; - if (out_state == S_DEFERRED && (!outbuf || outbuf->empty())) - { - out_state = S_OUT; - outbuf = std::move(buf); - new_outbuf(); - http_out_buffer(); - } - else - OPENVPN_THROW(http_exception, "http_content_out_finish: no deferred state=" << http_out_state_string(out_state) << " outbuf_size=" + (std::to_string(outbuf ? int(outbuf->size()) : -1)) << " halt=" << halt << " ready=" << ready << " async_out=" << async_out << " websock=" << websocket); - } - - void reduce_max_content_bytes(const CONTENT_LENGTH_TYPE new_max_content_bytes) - { - if (new_max_content_bytes && new_max_content_bytes < max_content_bytes) - max_content_bytes = new_max_content_bytes; - } - - protected: - HTTPBase(const typename CONFIG::Ptr& config_arg) - : config(config_arg), - frame(config_arg->frame), - stats(config_arg->stats) - { - static_assert(CONTENT_LENGTH_TYPE(-1) < CONTENT_LENGTH_TYPE(0), "CONTENT_LENGTH_TYPE must be signed"); - rr_reset(); - } - - void http_out_begin() - { - out_state = S_OUT; - } - - // Transmit outgoing HTTP, either to SSL object (HTTPS) or TCP socket (HTTP) - void http_out() - { - if (halt) - return; - if (out_state == S_PRE) - { - if (ssl_sess) - ssl_down_stack(); - return; - } - if (out_state == S_OUT && (!outbuf || outbuf->empty())) - { - if (async_out) - { - out_state = S_DEFERRED; - parent().base_http_content_out_needed(); - return; - } - else - { - outbuf = parent().base_http_content_out(); - new_outbuf(); - } - } - http_out_buffer(); - } - - void tcp_in(BufferAllocated& b) - { - if (ssl_sess) - { - // HTTPS - BufferPtr buf(new BufferAllocated()); - buf->swap(b); // take ownership - ssl_sess->write_ciphertext(buf); - ssl_up_stack(); - ssl_down_stack(); - - // In some cases, such as immediately after handshake, - // a write becomes possible after a read has completed. - http_out(); - } - else - { - // HTTP - http_in(b); - } - } - - // Callback methods in parent: - // BufferPtr base_http_content_out(); - // void base_http_content_out_needed(); - // void base_http_out_eof(); - // bool base_http_headers_received(); - // void base_http_content_in(BufferAllocated& buf); - // bool base_link_send(BufferAllocated& buf); - // bool base_send_queue_empty(); - // void base_http_done_handler(BufferAllocated& residual) - // void base_error_handler(const int errcode, const std::string& err); - - // protected member vars - - bool halt = false; - bool ready = true; - bool async_out = false; - bool websocket = false; - - typename CONFIG::Ptr config; - CONTENT_INFO content_info; - SSLAPI::Ptr ssl_sess; - - BufferPtr outbuf; - - Frame::Ptr frame; - SessionStats::Ptr stats; - - private: - PARENT& parent() - { - return *static_cast<PARENT*>(this); - } - - void new_outbuf() - { - if (!outbuf || !outbuf->defined()) - out_state = S_EOF; - if (content_info.length == CONTENT_INFO::CHUNKED) - outbuf = ChunkedHelper::transmit(std::move(outbuf)); - } - - void http_out_buffer() - { - if (outbuf) - { - const size_t size = std::min(outbuf->size(), http_buf_size()); - if (size) - { - if (ssl_sess) - { - // HTTPS: send outgoing cleartext HTTP data from request/reply to SSL object - ssize_t actual = 0; - try { - actual = ssl_sess->write_cleartext_unbuffered(outbuf->data(), size); - } - catch (...) - { - stats->error(Error::SSL_ERROR); - throw; - } - if (actual >= 0) - { -#if defined(OPENVPN_DEBUG_HTTP) - BufferAllocated tmp(outbuf->c_data(), actual, 0); - OPENVPN_LOG("OUT: " << buf_to_string(tmp)); -#endif - outbuf->advance(actual); - } - else if (actual == SSLConst::SHOULD_RETRY) - ; - else - throw http_exception("unknown write status from SSL layer"); - ssl_down_stack(); - } - else - { - // HTTP: send outgoing cleartext HTTP data from request/reply to TCP socket - BufferAllocated buf; - frame->prepare(Frame::WRITE_HTTP, buf); - buf.write(outbuf->data(), size); -#if defined(OPENVPN_DEBUG_HTTP) - OPENVPN_LOG("OUT: " << buf_to_string(buf)); -#endif - if (parent().base_link_send(buf)) - outbuf->advance(size); - } - } - } - if (out_state == S_EOF && parent().base_send_queue_empty()) - { - out_state = S_DONE; - outbuf.reset(); - parent().base_http_out_eof(); - } - } - - void chunked_content_in(BufferAllocated& buf) // called by ChunkedHelper - { - do_http_content_in(buf); - } - - void do_http_content_in(BufferAllocated& buf) - { - if (halt) - return; - if (buf.defined()) - { - rr_content_bytes += buf.size(); - if (!websocket) - rr_limit_bytes += buf.size() + config->msg_overhead_bytes; - if (max_content_bytes && rr_limit_bytes > max_content_bytes) - { - parent().base_error_handler(STATUS::E_CONTENT_SIZE, "HTTP content too large"); - return; - } - parent().base_http_content_in(buf); - } - } - - // Receive incoming HTTP - void http_in(BufferAllocated& buf) - { - if (halt || ready || buf.empty()) // if ready, indicates unsolicited input - return; - -#if defined(OPENVPN_DEBUG_HTTP) - OPENVPN_LOG("IN: " << buf_to_string(buf)); -#endif - - if (rr_status == REQUEST_REPLY::Parser::pending) - { - // processing HTTP request/reply and headers - for (size_t i = 0; i < buf.size(); ++i) - { - rr_status = rr_parser.consume(rr_obj, (char)buf[i]); - if (rr_status == REQUEST_REPLY::Parser::pending) - { - ++rr_header_bytes; - if ((rr_header_bytes & 0x3F) == 0) - { - // only check header maximums once every 64 bytes - if ((config->max_header_bytes && rr_header_bytes > config->max_header_bytes) - || (config->max_headers && rr_obj.headers.size() > config->max_headers)) - { - parent().base_error_handler(STATUS::E_HEADER_SIZE, "HTTP headers too large"); - return; - } - } - } - else - { - // finished processing HTTP request/reply and headers - buf.advance(i+1); - if (rr_status == REQUEST_REPLY::Parser::success) - { - if (!websocket) - { - rr_content_length = get_content_length(rr_obj.headers); - if (rr_content_length == CONTENT_INFO::CHUNKED) - rr_chunked.reset(new ChunkedHelper()); - } - if (!parent().base_http_headers_received()) - { - // Parent wants to handle content itself, - // pass post-header residual data. - // Currently, only pgproxy uses this. - parent().base_http_done_handler(buf, true); - return; - } - break; - } - else - { - parent().base_error_handler(STATUS::E_HTTP, "HTTP headers parse error"); - return; - } - } - } - } - - if (rr_status == REQUEST_REPLY::Parser::success) - { - // processing HTTP content - bool done = false; - BufferAllocated residual; - - if (websocket) - { - do_http_content_in(buf); - } - else if (rr_content_length >= 0) - { - const size_t needed = std::max(rr_content_length - rr_content_bytes, CONTENT_LENGTH_TYPE(0)); - if (needed <= buf.size()) - { - done = true; - if (needed < buf.size()) - { - // residual data exists - residual.swap(buf); - buf = (*frame)[Frame::READ_HTTP].copy_by_value(residual.read_alloc(needed), needed); - } - } - do_http_content_in(buf); - } - else if (rr_chunked) - { - done = rr_chunked->receive(*this, buf); // will callback to chunked_content_in - } - if (done) - parent().base_http_done_handler(residual, false); - } - } - - // read outgoing ciphertext data from SSL object and xmit to TCP socket - void ssl_down_stack() - { - while (!halt && ssl_sess->read_ciphertext_ready()) - { - BufferPtr buf = ssl_sess->read_ciphertext(); - parent().base_link_send(*buf); - } - } - - // read incoming cleartext data from SSL object and pass to HTTP receiver - void ssl_up_stack() - { - BufferAllocated buf; - while (!halt && ssl_sess->read_cleartext_ready()) - { - const Frame::Context& fc = (*frame)[Frame::READ_SSL_CLEARTEXT]; - fc.prepare(buf); - ssize_t size = 0; - try { - size = ssl_sess->read_cleartext(buf.data(), fc.payload()); - } - catch (...) - { - stats->error(Error::SSL_ERROR); - throw; - } - if (size >= 0) - { - buf.set_size(size); - http_in(buf); - } - else if (size == SSLConst::SHOULD_RETRY) - break; - else if (size == SSLConst::PEER_CLOSE_NOTIFY) - parent().base_error_handler(STATUS::E_EOF_SSL, "SSL PEER_CLOSE_NOTIFY"); - else - throw http_exception("unknown read status from SSL layer"); - } - } - - size_t http_buf_size() const - { - return (*frame)[Frame::WRITE_HTTP].payload(); - } - - static CONTENT_LENGTH_TYPE get_content_length(const HTTP::HeaderList& headers) - { - const std::string transfer_encoding = headers.get_value_trim("transfer-encoding"); - if (!string::strcasecmp(transfer_encoding, "chunked")) - { - return CONTENT_INFO::CHUNKED; - } - else - { - const std::string content_length_str = headers.get_value_trim("content-length"); - if (content_length_str.empty()) - return 0; - const CONTENT_LENGTH_TYPE content_length = parse_number_throw<CONTENT_LENGTH_TYPE>(content_length_str, "content-length"); - if (content_length < 0) - throw number_parse_exception("content-length is < 0"); - return content_length; - } - } - - static std::string http_out_state_string(const HTTPOutState hos) - { - switch (hos) - { - case S_PRE: - return "S_PRE"; - case S_OUT: - return "S_OUT"; - case S_DEFERRED: - return "S_DEFERRED"; - case S_EOF: - return "S_EOF"; - case S_DONE: - return "S_DONE"; - default: - return "S_?"; - } - } - - // private member vars - - typename REQUEST_REPLY::Parser::status rr_status; - typename REQUEST_REPLY::Parser rr_parser; - typename REQUEST_REPLY::State rr_obj; - - unsigned int rr_header_bytes; - - CONTENT_LENGTH_TYPE rr_content_bytes; - CONTENT_LENGTH_TYPE rr_content_length; // Content-Length in header - CONTENT_LENGTH_TYPE rr_limit_bytes; - std::unique_ptr<ChunkedHelper> rr_chunked; - - CONTENT_LENGTH_TYPE max_content_bytes; - - HTTPOutState out_state; - }; - - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/httpcreds.hpp b/Sources/OpenVPN3/openvpn/ws/httpcreds.hpp deleted file mode 100644 index bffc293..0000000 --- a/Sources/OpenVPN3/openvpn/ws/httpcreds.hpp +++ /dev/null @@ -1,162 +0,0 @@ -// 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-2020 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 <vector> -#include <atomic> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/splitlines.hpp> -#include <openvpn/common/strneq.hpp> -#include <openvpn/common/unicode.hpp> -#include <openvpn/common/userpass.hpp> -#include <openvpn/common/platform.hpp> -#include <openvpn/common/writeprivate.hpp> -#include <openvpn/http/header.hpp> - -namespace openvpn { - namespace WS { - struct Creds - { - OPENVPN_EXCEPTION(web_creds_error); - - static Creds load_from_header(const HTTP::HeaderList& headlist, - const bool password_required, - const bool throw_on_error) - { - Creds ret; - try - { - // Authorization: Basic Zm9vOmJhcg== - for (auto &h : headlist) - { - if (string::strcasecmp(h.name, "authorization") == 0 - && h.value.length() >= 7 - && string::strcasecmp(h.value.substr(0, 6), "basic ") == 0) - { - const std::string creds = base64->decode(h.value.substr(6)); - const auto cv = string::split(creds, ':', 1); - if (cv.size() != 2) - throw Exception("error splitting credentials"); - if (!Unicode::is_valid_utf8(cv[0])) - throw Exception("username not UTF-8"); - if (!Unicode::is_valid_utf8(cv[1])) - throw Exception("password not UTF-8"); - if (cv[0].empty()) - throw Exception("username empty"); - if (password_required && cv[1].empty()) - throw Exception("password empty"); - ret.username = cv[0]; - ret.password = cv[1]; - break; - } - } - } - catch (const std::exception& e) - { - if (throw_on_error) - throw web_creds_error(e.what()); - } - return ret; - } - - static Creds load_from_file(const std::string& fn, - const bool password_required, - const bool throw_on_error) - { - Creds ret; - try - { - const std::string content = read_text_utf8(fn); - SplitLines sl(content, 1024); - std::string u, p; - if (sl.next(u) != SplitLines::S_OKAY) - throw Exception(fn + " : username missing"); - if (sl.next(p) != SplitLines::S_OKAY) - throw Exception(fn + " : password missing"); - if (u.empty()) - throw Exception(fn + " : username empty"); - if (password_required && p.empty()) - throw Exception(fn + " : password empty"); - ret.username = std::move(u); - ret.password = std::move(p); - } - catch (const std::exception& e) - { - if (throw_on_error) - throw web_creds_error(e.what()); - } - return ret; - } - - static Creds load_from_options(const OptionList& opt, - const std::string& opt_name, - const unsigned int flags) - { - Creds ret; - UserPass::parse(opt, opt_name, flags, ret.username, ret.password); - return ret; - } - - bool defined() const - { - return !username.empty(); - } - - bool defined_full() const - { - return !username.empty() && !password.empty(); - } - - void save_to_file(const std::string& fn) const - { - write_private(fn, username + '\n' + password + '\n'); - } - - bool operator==(const Creds& rhs) const - { - return !operator!=(rhs); - } - - bool operator!=(const Creds& rhs) const - { - bool neq = crypto::str_neq(username, rhs.username); - atomic_thread_fence(std::memory_order_acq_rel); - neq |= crypto::str_neq(password, rhs.password); - atomic_thread_fence(std::memory_order_acq_rel); - return neq; - } - - std::string to_string() const - { - return username + '/' + password; - } - - std::string username; - std::string password; - }; - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/httpserv.hpp b/Sources/OpenVPN3/openvpn/ws/httpserv.hpp deleted file mode 100644 index 47869d4..0000000 --- a/Sources/OpenVPN3/openvpn/ws/httpserv.hpp +++ /dev/null @@ -1,1101 +0,0 @@ -// 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-2020 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 <vector> -#include <sstream> -#include <ostream> -#include <cstdint> -#include <utility> -#include <memory> -#include <unordered_map> -#include <deque> - -#include <openvpn/io/io.hpp> - -#include <openvpn/common/platform.hpp> -#include <openvpn/common/options.hpp> -#include <openvpn/common/to_string.hpp> -#include <openvpn/common/arraysize.hpp> -#include <openvpn/common/function.hpp> -#include <openvpn/common/sockopt.hpp> -#include <openvpn/asio/asiopolysock.hpp> -#include <openvpn/common/core.hpp> -#include <openvpn/buffer/bufstream.hpp> -#include <openvpn/time/timestr.hpp> -#include <openvpn/time/asiotimersafe.hpp> -#include <openvpn/time/coarsetime.hpp> -#include <openvpn/addr/ip.hpp> -#include <openvpn/log/sessionstats.hpp> -#include <openvpn/options/merge.hpp> -#include <openvpn/frame/frame_init.hpp> -#include <openvpn/http/request.hpp> -#include <openvpn/http/reply.hpp> -#include <openvpn/http/status.hpp> -#include <openvpn/transport/tcplink.hpp> -#include <openvpn/ws/httpcommon.hpp> -#include <openvpn/ws/websocket.hpp> -#include <openvpn/server/listenlist.hpp> - -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING -#include <openvpn/kovpn/sock_mark.hpp> -#endif - -// include acceptors for different protocols -#include <openvpn/proxy/listener.hpp> -#include <openvpn/acceptor/base.hpp> -#include <openvpn/acceptor/tcp.hpp> -#if defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/acceptor/namedpipe.hpp> -#endif -#ifdef ASIO_HAS_LOCAL_SOCKETS -#include <openvpn/acceptor/unix.hpp> -#endif - -#ifndef OPENVPN_HTTP_SERV_RC -#define OPENVPN_HTTP_SERV_RC RC<thread_unsafe_refcount> -#endif - -namespace openvpn { - namespace WS { - namespace Server { - - OPENVPN_EXCEPTION(http_server_exception); - - typedef unsigned int client_t; - typedef std::int64_t content_len_t; - - struct Status - { - // Error codes - enum { - E_SUCCESS=0, - E_TCP, - E_HTTP, - E_EXCEPTION, - E_HEADER_SIZE, - E_CONTENT_SIZE, - E_EOF_SSL, - E_EOF_TCP, - E_GENERAL_TIMEOUT, - E_EXTERNAL_STOP, - E_PIPELINE_OVERFLOW, - E_SHUTDOWN, - E_ABORTED, - - N_ERRORS - }; - - static std::string error_str(const size_t status) - { - static const char *error_names[] = { - "E_SUCCESS", - "E_TCP", - "E_HTTP", - "E_EXCEPTION", - "E_HEADER_SIZE", - "E_CONTENT_SIZE", - "E_EOF_SSL", - "E_EOF_TCP", - "E_GENERAL_TIMEOUT", - "E_EXTERNAL_STOP", - "E_PIPELINE_OVERFLOW", - "E_SHUTDOWN", - "E_ABORTED", - }; - - static_assert(N_ERRORS == array_size(error_names), "HTTP error names array inconsistency"); - if (status < N_ERRORS) - return error_names[status]; - else - return "E_???"; - } - }; - - struct Config : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - SSLFactoryAPI::Ptr ssl_factory; -#if defined(OPENVPN_PLATFORM_WIN) - std::string sddl_string; // Windows named-pipe security descriptor as string -#endif -#ifdef ASIO_HAS_LOCAL_SOCKETS - mode_t unix_mode = 0; -#endif - unsigned int tcp_backlog = 16; - unsigned int tcp_throttle_max_connections_per_period = 0; // set > 0 to enable throttling - Time::Duration tcp_throttle_period; - unsigned int tcp_max = 0; - unsigned int general_timeout = 60; - unsigned int max_headers = 0; - unsigned int max_header_bytes = 0; - content_len_t max_content_bytes = 0; - unsigned int msg_overhead_bytes = 0; - unsigned int send_queue_max_size = 0; - unsigned int free_list_max_size = 8; - unsigned int pipeline_max_size = 64; - unsigned int sockopt_flags = 0; - std::string http_server_id; - Frame::Ptr frame; - SessionStats::Ptr stats; - }; - - struct ContentInfo { - // content length if Transfer-Encoding: chunked - static constexpr content_len_t CHUNKED = -1; - - int http_status = 0; - std::string http_status_str; // optional - std::string type; - std::string content_encoding; - std::string basic_realm; - content_len_t length = 0; - bool no_cache = false; - bool keepalive = false; - bool lean_headers = false; - std::vector<std::string> extra_headers; - WebSocket::Server::PerRequest::Ptr websocket; - }; - - class Listener : public ProxyListener - { - public: - class Client; - - private: - typedef WS::HTTPBase<Client, Config, Status, HTTP::RequestType, ContentInfo, content_len_t, OPENVPN_HTTP_SERV_RC> Base; - - public: - class Client : public Base - { - friend Base; - friend Listener; - - public: - struct AsioProtocol - { - typedef AsioPolySock::Base socket; - }; - - typedef RCPtr<Client> Ptr; - - class Initializer - { - friend Listener; - friend Client; - - Initializer(openvpn_io::io_context& io_context_arg, - Listener* parent_arg, - AsioPolySock::Base::Ptr&& socket_arg, - const client_t client_id_arg) - : io_context(io_context_arg), - parent(parent_arg), - socket(std::move(socket_arg)), - client_id(client_id_arg) - { - } - - openvpn_io::io_context& io_context; - Listener* parent; - AsioPolySock::Base::Ptr socket; - const client_t client_id; - }; - - struct Factory : public OPENVPN_HTTP_SERV_RC - { - typedef RCPtr<Factory> Ptr; - - virtual Client::Ptr new_client(Initializer& ci) = 0; - virtual void stop() {} - }; - - virtual ~Client() - { - stop(false, false); - } - - bool remote_ip_port(IP::Addr& addr, unsigned int& port) const - { - if (sock) - return sock->remote_ip_port(addr, port); - else - return false; - } - - IP::Addr remote_ip() const - { - IP::Addr addr; - unsigned int port; - if (remote_ip_port(addr, port)) - return addr; - else - return IP::Addr(); - } - - AuthCert::Ptr auth_cert() const - { - if (ssl_sess) - return ssl_sess->auth_cert(); - else - return AuthCert::Ptr(); - } - - bool is_ssl() const - { - return bool(ssl_sess); - } - - bool is_local() const - { - if (sock) - return sock->is_local(); - else - return false; - } - - bool is_alt_routing() const - { -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - return is_alt_routing_; -#else - return false; -#endif - } - - protected: - Client(Initializer& ci) - : Base(ci.parent->config), - io_context(ci.io_context), - sock(std::move(ci.socket)), - parent(ci.parent), - timeout_timer(ci.io_context), - client_id(ci.client_id) - { - } - - void generate_reply_headers(ContentInfo ci) - { - http_out_begin(); - - content_info = std::move(ci); - - outbuf.reset(new BufferAllocated(512, BufferAllocated::GROW)); - BufferStreamOut os(*outbuf); - - // websocket? - const bool ws = (content_info.websocket && content_info.http_status == HTTP::Status::SwitchingProtocols); - - if (ws) - generate_reply_headers_websocket(os); - else - generate_reply_headers_http(os); - - http_headers_sent(*outbuf); - http_out(); - - if (ws) - begin_websocket(); - } - - void generate_custom_reply_headers(BufferPtr& buf) - { - http_out_begin(); - outbuf = std::move(buf); - http_headers_sent(*outbuf); - http_out(); - } - - // return true if client asked for keepalive - bool keepalive_request() - { - return headers().get_value_trim("connection") == "keep-alive"; - } - - const HTTP::Request& request() const { - return request_reply(); - } - - void register_activity() - { - activity(); - } - - void external_stop(const std::string& description) - { - error_handler(Status::E_EXTERNAL_STOP, description); - } - - void abort(const std::string& description, const int status=Status::E_ABORTED) - { - if (!halt) - error_handler(status, description); - } - - std::string remote_endpoint_str() const - { - try { - if (sock) - return sock->remote_endpoint_str(); - } - catch (const std::exception&) - { - } - return "[unknown endpoint]"; - } - - client_t get_client_id() const - { - return client_id; - } - - Listener* get_parent() const - { - return parent; - } - -#ifdef ASIO_HAS_LOCAL_SOCKETS - int unix_fd() - { - AsioPolySock::Unix* uds = dynamic_cast<AsioPolySock::Unix*>(sock.get()); - if (uds) - return uds->socket.native_handle(); - else - return -1; - } -#endif - - openvpn_io::io_context& io_context; - AsioPolySock::Base::Ptr sock; - std::deque<BufferAllocated> pipeline; - Time::Duration timeout_duration; - - private: - typedef TCPTransport::Link<AsioProtocol, Client*, false> LinkImpl; - friend LinkImpl::Base; // calls tcp_* handlers - - void generate_reply_headers_http(std::ostream& os) - { - os << "HTTP/1.1 " << content_info.http_status << ' '; - if (content_info.http_status_str.empty()) - os << HTTP::Status::to_string(content_info.http_status); - else - os << content_info.http_status_str; - os << "\r\n"; - if (!content_info.lean_headers) - { - if (!parent->config->http_server_id.empty()) - os << "Server: " << parent->config->http_server_id << "\r\n"; - os << "Date: " << date_time_rfc822() << "\r\n"; - } - if (!content_info.basic_realm.empty()) - os << "WWW-Authenticate: Basic realm=\"" << content_info.basic_realm << "\"\r\n"; - if (content_info.length) - os << "Content-Type: " << content_info.type << "\r\n"; - if (content_info.length > 0) - os << "Content-Length: " << content_info.length << "\r\n"; - else if (content_info.length == ContentInfo::CHUNKED) - os << "Transfer-Encoding: chunked\r\n"; - for (auto &h : content_info.extra_headers) - os << h << "\r\n"; - if (!content_info.content_encoding.empty()) - os << "Content-Encoding: " << content_info.content_encoding << "\r\n"; - if (content_info.no_cache && !content_info.lean_headers) - os << "Cache-Control: no-cache, no-store, must-revalidate\r\n"; - if ((keepalive = content_info.keepalive)) - os << "Connection: keep-alive\r\n"; - else - os << "Connection: close\r\n"; - os << "\r\n"; - } - - void generate_reply_headers_websocket(std::ostream& os) - { - os << "HTTP/1.1 101 Switching Protocols\r\n"; - if (content_info.websocket) - content_info.websocket->server_headers(os); - for (auto &h : content_info.extra_headers) - os << h << "\r\n"; - os << "\r\n"; - } - - // transition to websocket i/o after we push HTTP - // headers to client - void begin_websocket() - { - cancel_general_timeout(); // timeouts could be harmful for long-running websockets - set_async_out(true); // websockets require async output - websocket = true; // enable websocket in httpcommon - ready = false; // enable tcp_in - consume_pipeline(); // process data received while tcp_in was disabled - } - - void cancel_general_timeout() - { - timeout_duration.set_zero(); - timeout_timer.cancel(); - } - - void start(const Acceptor::Item::SSLMode ssl_mode) - { - timeout_coarse.init(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024)); - link.reset(new LinkImpl(this, - *sock, - parent->config->send_queue_max_size, - parent->config->free_list_max_size, - (*parent->config->frame)[Frame::READ_HTTP], - stats)); - link->set_raw_mode(true); - switch (ssl_mode) - { - case Acceptor::Item::SSLOff: - break; - case Acceptor::Item::SSLOn: - ssl_sess = parent->config->ssl_factory->ssl(); - break; -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - case Acceptor::Item::AltRouting: - is_alt_routing_ = true; - break; -#endif - } - restart(true); - } - - void restart(const bool initial) - { - timeout_duration = Time::Duration::seconds(parent->config->general_timeout); - timeout_coarse.reset(); - activity(); - rr_reset(); - ready = false; - consume_pipeline(); - if (initial || handoff) - link->start(); - handoff = false; - } - - void stop(const bool remove_self_from_map, const bool shutdown) - { - if (halt) - return; - halt = true; - http_destroy(); - timeout_timer.cancel(); - if (link) - link->stop(); - if (sock) - { - if (shutdown) - sock->shutdown(AsioPolySock::SHUTDOWN_SEND|AsioPolySock::SHUTDOWN_RECV); - sock->close(); - } - if (remove_self_from_map) - openvpn_io::post(io_context, [self=Ptr(this), parent=Listener::Ptr(parent)]() mutable - { - parent->remove_client(std::move(self)); - }); - } - - void activity() - { - if (timeout_duration.defined()) - { - const Time now = Time::now(); - const Time next = now + timeout_duration; - if (!timeout_coarse.similar(next)) - { - timeout_coarse.reset(next); - timeout_timer.expires_at(next); - timeout_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (!error) - self->timeout_callback(error); - }); - } - } - } - - void timeout_callback(const openvpn_io::error_code& e) - { - if (halt || e) - return; - error_handler(Status::E_GENERAL_TIMEOUT, "General timeout"); - } - - void add_to_pipeline(BufferAllocated& buf) - { - if (!buf.empty()) - http_pipeline_peek(buf); - if (halt) - return; - if (buf.empty()) - return; - if (pipeline.size() >= parent->config->pipeline_max_size) - error_handler(Status::E_PIPELINE_OVERFLOW, "Pipeline overflow"); - pipeline.push_back(std::move(buf)); - } - - void consume_pipeline() - { - while (!pipeline.empty() && !ready) - { - BufferAllocated buf(std::move(pipeline.front())); - pipeline.pop_front(); - tcp_in(buf); - } - } - - // Implemented by child class for any kind of intercept processing - // (i.e. parsing and stripping the Proxy Protocol v1 header) - virtual void tcp_intercept(BufferAllocated& b) - { - } - - // methods called by LinkImpl - - bool tcp_read_handler(BufferAllocated& b) - { - if (halt) - return false; - - tcp_intercept(b); - - try { - activity(); - if (ready) - add_to_pipeline(b); - else - tcp_in(b); // call Base - } - catch (const std::exception& e) - { - handle_exception("tcp_read_handler", e); - } - return !handoff; // don't requeue read if handoff, i.e. parent wants to take control of session socket - } - - void tcp_write_queue_needs_send() - { - if (halt) - return; - - try { - http_out(); - } - catch (const std::exception& e) - { - handle_exception("tcp_write_queue_needs_send", e); - } - } - - void tcp_eof_handler() - { - if (halt) - return; - - try { - error_handler(Status::E_EOF_TCP, "TCP EOF"); - return; - } - catch (const std::exception& e) - { - handle_exception("tcp_eof_handler", e); - } - } - - void tcp_error_handler(const char *error) - { - if (halt) - return; - error_handler(Status::E_TCP, std::string("HTTPCore TCP: ") + error); - } - - // methods called by Base - - BufferPtr base_http_content_out() - { - return http_content_out(); - } - - void base_http_content_out_needed() - { - http_content_out_needed(); - } - - void base_http_out_eof() - { - if (http_out_eof()) - { - if (keepalive && !websocket) - restart(false); - else - error_handler(Status::E_SUCCESS, "Succeeded"); - } - } - - bool base_http_headers_received() - { - return http_headers_received(); - } - - void base_http_content_in(BufferAllocated& buf) - { - http_content_in(buf); - } - - bool base_link_send(BufferAllocated& buf) - { - activity(); - return link->send(buf); - } - - bool base_send_queue_empty() - { - return link->send_queue_empty(); - } - - void base_http_done_handler(BufferAllocated& residual, - const bool parent_handoff) - { - if (halt) - return; - ready = true; - handoff = parent_handoff; - add_to_pipeline(residual); - http_request_received(); - } - - void base_error_handler(const int errcode, const std::string& err) - { - error_handler(errcode, err); - } - - // error handlers - - void asio_error_handler(int errcode, const char *func_name, const openvpn_io::error_code& error) - { - error_handler(errcode, std::string("HTTPCore Asio ") + func_name + ": " + error.message()); - } - - void handle_exception(const char *func_name, const std::exception& e) - { - error_handler(Status::E_EXCEPTION, std::string("HTTPCore Exception ") + func_name + ": " + e.what()); - } - - void error_handler(const int errcode, const std::string& err) - { - const bool shutdown = http_stop(errcode, err); - stop(true, shutdown); - } - - // virtual methods - - virtual BufferPtr http_content_out() - { - return BufferPtr(); - } - - virtual void http_content_out_needed() - { - } - - virtual bool http_headers_received() - { - return true; - } - - virtual void http_request_received() - { - } - - virtual void http_pipeline_peek(BufferAllocated& buf) - { - } - - virtual void http_content_in(BufferAllocated& buf) - { - } - - virtual void http_headers_sent(const Buffer& buf) - { - } - - virtual bool http_out_eof() - { - return true; - } - - virtual bool http_stop(const int status, const std::string& description) - { - return false; - } - - virtual void http_destroy() - { - } - - Listener* parent; - AsioTimerSafe timeout_timer; - CoarseTime timeout_coarse; - client_t client_id; - LinkImpl::Ptr link; - bool keepalive = false; - bool handoff = false; -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - bool is_alt_routing_ = false; -#endif - }; - - public: - typedef RCPtr<Listener> Ptr; - - template <typename L> // L is a Listen::Item or Listen::List - Listener(openvpn_io::io_context& io_context_arg, - const Config::Ptr& config_arg, - const L& listen_item_or_list, - const Client::Factory::Ptr& client_factory_arg) - : io_context(io_context_arg), - listen_list(listen_item_or_list), - config(config_arg), - client_factory(client_factory_arg), - throttle_timer(io_context) - { - } - - virtual void start() override - { - if (halt) - return; - - acceptors.reserve(listen_list.size()); - for (const auto &listen_item : listen_list) - { - switch (listen_item.proto()) - { - case Protocol::TCPv4: - case Protocol::TCPv6: - { - // ssl enabled? - Acceptor::Item::SSLMode ssl_mode = Acceptor::Item::SSLOff; - switch (listen_item.ssl) - { - case Listen::Item::SSLUnspecified: - ssl_mode = bool(config->ssl_factory) ? Acceptor::Item::SSLOn : Acceptor::Item::SSLOff; - break; - case Listen::Item::SSLOn: - if (listen_item.ssl == Listen::Item::SSLOn && !config->ssl_factory) - throw http_server_exception("listen item has 'ssl' qualifier, but no SSL configuration"); - ssl_mode = Acceptor::Item::SSLOn; - break; - case Listen::Item::SSLOff: - break; -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - case Listen::Item::AltRouting: - ssl_mode = Acceptor::Item::AltRouting; - break; -#endif - } - - OPENVPN_LOG("HTTP" << ((ssl_mode == Acceptor::Item::SSLOn) ? "S" : "") << " Listen: " << listen_item.to_string()); - - // init TCP acceptor - Acceptor::TCP::Ptr a(new Acceptor::TCP(io_context)); - - // parse address/port of local endpoint - const IP::Addr ip_addr = IP::Addr::from_string(listen_item.addr); - a->local_endpoint.address(ip_addr.to_asio()); - a->local_endpoint.port(HostPort::parse_port(listen_item.port, "http listen")); - - // open socket - a->acceptor.open(a->local_endpoint.protocol()); - - // set options - a->set_socket_options(config->sockopt_flags); - - // bind to local address -#ifdef OPENVPN_DEBUG_ACCEPT - OPENVPN_LOG("ACCEPTOR BIND " << a->local_endpoint); -#endif - a->acceptor.bind(a->local_endpoint); - - // listen for incoming client connections - a->acceptor.listen(config->tcp_backlog); - - // save acceptor - acceptors.emplace_back(std::move(a), ssl_mode); - - // queue accept on listen socket - queue_accept_throttled(acceptors.size() - 1, false); - } - break; -#if defined(OPENVPN_PLATFORM_WIN) - case Protocol::NamedPipe: - { - OPENVPN_LOG("HTTP Listen: " << listen_item.to_string()); - - // create named pipe - Acceptor::NamedPipe::Ptr a(new Acceptor::NamedPipe(io_context, listen_item.addr, config->sddl_string)); - - // save acceptor - acceptors.emplace_back(std::move(a), Acceptor::Item::SSLOff); - - // queue accept on listen socket - queue_accept_throttled(acceptors.size() - 1, false); - } - break; -#endif -#ifdef ASIO_HAS_LOCAL_SOCKETS - case Protocol::UnixStream: - { - OPENVPN_LOG("HTTP Listen: " << listen_item.to_string()); - - Acceptor::Unix::Ptr a(new Acceptor::Unix(io_context)); - - // set endpoint - a->pre_listen(listen_item.addr); - a->local_endpoint.path(listen_item.addr); - - // open socket - a->acceptor.open(a->local_endpoint.protocol()); - - // bind to local address - a->acceptor.bind(a->local_endpoint); - - // set socket permissions in filesystem - a->set_socket_permissions(listen_item.addr, config->unix_mode); - - // listen for incoming client connections - a->acceptor.listen(); - - // save acceptor - acceptors.emplace_back(std::move(a), Acceptor::Item::SSLOff); - - // queue accept on listen socket - queue_accept_throttled(acceptors.size() - 1, false); - } - break; -#endif - default: - throw http_server_exception("listen on unknown protocol"); - } - } - } - - virtual void stop() override - { - if (halt) - return; - halt = true; - - // close acceptors - acceptors.close(); - - throttle_timer.cancel(); - - // stop clients - for (auto &c : clients) - c.second->stop(false, false); - clients.clear(); - - // stop client factory - if (client_factory) - client_factory->stop(); - } - - template <typename CLIENT_INSTANCE, typename FUNC> - void walk(FUNC func) const - { - for (auto &c : clients) - func(*static_cast<CLIENT_INSTANCE*>(c.second.get())); - } - - private: - typedef std::unordered_map<client_t, Client::Ptr> ClientMap; - - void queue_accept(const size_t acceptor_index) - { - acceptors[acceptor_index].acceptor->async_accept(this, acceptor_index, io_context); - } - - void queue_accept_throttled(const size_t acceptor_index, const bool debit_one) - { - if (config->tcp_throttle_max_connections_per_period) - { - if (throttle_acceptor_indices.empty()) - { - const Time now = Time::now(); - if (now >= throttle_expire) - throttle_reset(now, debit_one); - if (throttle_connections > 0) - { - --throttle_connections; - queue_accept(acceptor_index); - } - else - { - // throttle it - throttle_acceptor_indices.push_back(acceptor_index); - throttle_timer_wait(); - } - } - else - throttle_acceptor_indices.push_back(acceptor_index); - } - else - queue_accept(acceptor_index); - } - - void throttle_reset(const Time& now, const bool debit_one) - { - throttle_connections = config->tcp_throttle_max_connections_per_period; - if (debit_one) - --throttle_connections; - throttle_expire = now + config->tcp_throttle_period; - } - - void throttle_timer_wait() - { - throttle_timer.expires_at(throttle_expire); - throttle_timer.async_wait([self=Ptr(this)](const openvpn_io::error_code& error) - { - if (self->halt || error) - return; - self->throttle_timer_callback(); - }); - } - - void throttle_timer_callback() - { - throttle_reset(Time::now(), false); - while (!throttle_acceptor_indices.empty() && throttle_connections > 0) - { - const size_t acceptor_index = throttle_acceptor_indices.front(); - queue_accept(acceptor_index); - throttle_acceptor_indices.pop_front(); - --throttle_connections; - } - if (!throttle_acceptor_indices.empty()) - throttle_timer_wait(); - } - - virtual void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code& error) override - { - if (halt) - return; - - const size_t acceptor_index = sock->index(); - - try { - if (!error) - { - const Acceptor::Item::SSLMode ssl_mode = acceptors[acceptor_index].ssl_mode; - -#ifdef OPENVPN_DEBUG_ACCEPT - OPENVPN_LOG("ACCEPT from " << sock->remote_endpoint_str()); -#endif - - sock->non_blocking(true); - sock->set_cloexec(); - sock->tcp_nodelay(); - - if (config->tcp_max && clients.size() >= config->tcp_max) - throw http_server_exception("max clients exceeded"); - if (!allow_client(*sock)) - throw http_server_exception("client socket rejected"); - -#ifdef OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING - if (ssl_mode == Acceptor::Item::AltRouting) - { - const KovpnSockMark ksm(sock->native_handle()); - if (!ksm.is_internal()) - throw http_server_exception("non alt-routing socket: " + ksm.to_string()); - } -#endif - - const client_t client_id = new_client_id(); - Client::Initializer ci(io_context, this, std::move(sock), client_id); - Client::Ptr cli = client_factory->new_client(ci); - clients[client_id] = cli; - - cli->start(ssl_mode); - } - else - throw http_server_exception("accept failed: " + error.message()); - } - catch (const std::exception& e) - { - OPENVPN_LOG("exception in handle_accept: " << e.what()); - } - - queue_accept_throttled(acceptor_index, true); - } - - client_t new_client_id() - { - while (true) - { - // find an ID that's not already in use - const client_t id = next_id++; - if (clients.find(id) == clients.end()) - return id; - } - } - - void remove_client(Client::Ptr cli) - { - remove_client_id(cli->get_client_id()); - } - - void remove_client_id(const client_t client_id) - { - ClientMap::const_iterator e = clients.find(client_id); - if (e != clients.end()) - clients.erase(e); - } - - virtual bool allow_client(AsioPolySock::Base& sock) - { - return true; - } - - openvpn_io::io_context& io_context; - Listen::List listen_list; - Config::Ptr config; - Client::Factory::Ptr client_factory; - bool halt = false; - - Acceptor::Set acceptors; - - AsioTimerSafe throttle_timer; - Time throttle_expire; - int throttle_connections = 0; - std::deque<size_t> throttle_acceptor_indices; - - client_t next_id = 0; - ClientMap clients; - }; - - } - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/resolver_results.hpp b/Sources/OpenVPN3/openvpn/ws/resolver_results.hpp deleted file mode 100644 index 9188879..0000000 --- a/Sources/OpenVPN3/openvpn/ws/resolver_results.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// 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-2020 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 <algorithm> - -#include <openvpn/random/randapi.hpp> -#include <openvpn/addr/ip.hpp> - -namespace openvpn { - namespace WS { - - // These methods become no-ops unless building with a patched Asio and C++14 or higher. - // Define ASIO_RESOLVER_RESULTS_DATA_REQUIRED to force an error if these methods - // cannot be compiled. - -#if defined(HAVE_ASIO_RESOLVER_RESULTS_DATA) && __cplusplus >= 201402L - - template <typename RESULTS> - inline void randomize_results(RESULTS& results, RandomAPI& prng) - { - auto* data = results.data(); - if (!data) - return; - std::shuffle(data->begin(), data->end(), prng); - } - - template <typename RESULTS> - inline void filter_by_ip_version(RESULTS& results, const IP::Addr::Version ip_ver) - { - auto* data = results.data(); - if (!data) - return; - - bool v4; - switch (ip_ver) - { - case IP::Addr::V4: - v4 = true; - break; - case IP::Addr::V6: - v4 = false; - break; - default: - return; - } - - // the "auto" lambda parameter makes this C++14 code - data->erase(std::remove_if(data->begin(), data->end(), - [v4](auto& e) - { - return e.endpoint().address().is_v4() != v4; - }), - data->end()); - } - -#elif defined(ASIO_RESOLVER_RESULTS_DATA_REQUIRED) -#error ASIO_RESOLVER_RESULTS_DATA_REQUIRED is defined but Asio results data are not available or compiler is pre-C++14 -#else - - template <typename RESULTS> - inline void randomize_results(RESULTS& results, RandomAPI& prng) - { - } - - template <typename RESULTS> - inline void filter_by_ip_version(RESULTS& results, const IP::Addr::Version ip_ver) - { - } - -#endif - - } -} diff --git a/Sources/OpenVPN3/openvpn/ws/websocket.hpp b/Sources/OpenVPN3/openvpn/ws/websocket.hpp deleted file mode 100644 index 7424649..0000000 --- a/Sources/OpenVPN3/openvpn/ws/websocket.hpp +++ /dev/null @@ -1,564 +0,0 @@ -// 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-2020 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 <cstdint> -#include <ostream> -#include <tuple> -#include <utility> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/rc.hpp> -#include <openvpn/common/base64.hpp> -#include <openvpn/common/socktypes.hpp> -#include <openvpn/common/endian64.hpp> -#include <openvpn/crypto/hashstr.hpp> -#include <openvpn/buffer/buffer.hpp> -#include <openvpn/random/randapi.hpp> - -namespace openvpn { - namespace WebSocket { - - OPENVPN_EXCEPTION(websocket_error); - - class Receiver; - - inline std::string accept_confirmation(DigestFactory& digest_factory, - const std::string& websocket_key) - { - static const char guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - HashString h(digest_factory, CryptoAlgs::SHA1); - h.update(websocket_key + guid); - return h.final_base64(); - } - - class Protocol - { - public: - static constexpr size_t MAX_HEAD = 16; - - enum Opcode - { - Text = 0x1, - Binary = 0x2, - Close = 0x8, - Ping = 0x9, - Pong = 0xA, - }; - - static std::string opcode_to_string(const unsigned int opcode) - { - switch (opcode) - { - case Text: - return "Text"; - case Binary: - return "Binary"; - case Close: - return "Close"; - case Ping: - return "Ping"; - case Pong: - return "Pong"; - default: - return "WS-OPCODE-" + std::to_string(opcode); - } - } - - union MaskingKey - { - public: - MaskingKey(std::uint32_t mask) - : mask32(std::move(mask)) - { - } - - void xor_buf(Buffer& buf) const - { - const size_t size = buf.size(); - std::uint8_t* data = buf.data(); - for (size_t i = 0; i < size; ++i) - data[i] ^= mask8[i & 0x3]; - } - - void prepend_mask(Buffer& buf) const - { - buf.prepend(&mask32, sizeof(mask32)); - } - - private: - std::uint32_t mask32; - std::uint8_t mask8[4]; - }; - }; - - class Status - { - public: - Status() - : opcode_(0), - fin_(false), - close_status_code_(0) - { - } - - Status(unsigned int opcode, - bool fin=true, - unsigned int close_status_code=0) - : opcode_(std::move(opcode)), - fin_(std::move(fin)), - close_status_code_(std::move(close_status_code)) - { - } - - Status(const Status& ref, - const unsigned int opcode) - : opcode_(opcode), - fin_(ref.fin_), - close_status_code_(ref.close_status_code_) - { - } - - bool defined() const - { - return opcode_ != 0; - } - - unsigned int opcode() const - { - return opcode_; - } - - bool fin() const - { - return fin_; - } - - unsigned int close_status_code() const - { - return close_status_code_; - } - - bool operator==(const Status& rhs) const - { - return std::tie(opcode_, fin_, close_status_code_) == std::tie(rhs.opcode_, fin_, rhs.close_status_code_); - } - - bool operator!=(const Status& rhs) const - { - return std::tie(opcode_, fin_, close_status_code_) != std::tie(rhs.opcode_, fin_, rhs.close_status_code_); - } - - std::string to_string() const - { - std::string ret; - - ret.reserve(64); - ret += "[op="; - ret += Protocol::opcode_to_string(opcode_); - ret += " fin="; - ret += std::to_string(fin_); - if (opcode_ == Protocol::Close) - { - ret += " status="; - ret += std::to_string(close_status_code_); - } - ret += ']'; - return ret; - } - - private: - friend class Receiver; - - unsigned int opcode_; - bool fin_; - unsigned int close_status_code_; - }; - - class Sender - { - public: - Sender(RandomAPI::Ptr cli_rng_arg) // only provide rng on client side - : cli_rng(std::move(cli_rng_arg)) - { - if (cli_rng) - cli_rng->assert_crypto(); - } - - void frame(Buffer& buf, const Status& s) const - { - if (s.opcode() == Protocol::Close) - { - const std::uint16_t cs = htons(s.close_status_code()); - buf.prepend(&cs, sizeof(cs)); - } - - const size_t payload_len = buf.size(); - if (cli_rng) - { - const Protocol::MaskingKey mk(cli_rng->rand_get<std::uint32_t>()); - mk.xor_buf(buf); - mk.prepend_mask(buf); - } - prepend_payload_length(buf, payload_len); - - std::uint8_t head = s.opcode() & 0xF; - if (s.fin()) - head |= 0x80; - buf.prepend(&head, sizeof(head)); - - //OPENVPN_LOG("WS SEND HEAD\n" << dump_hex(buf)); - } - - private: - void prepend_payload_length(Buffer& buf, const size_t len) const - { - std::uint8_t len8; - - if (len <= 125) - len8 = len; - else if (len <= 65535) - { - len8 = 126; - const std::uint16_t len16 = htons(len); - buf.prepend(&len16, sizeof(len16)); - } - else - { - len8 = 127; - const std::uint64_t len64 = Endian::rev64(len); - buf.prepend(&len64, sizeof(len64)); - } - - if (cli_rng) - len8 |= 0x80; - buf.prepend(&len8, sizeof(len8)); - } - - RandomAPI::Ptr cli_rng; - }; - - class Receiver - { - public: - Receiver(const bool is_client_arg) - : is_client(is_client_arg) - { - reset_pod(); - } - - Buffer buf_unframed() - { - verify_message_complete(); - if (size > buf.size()) - throw websocket_error("Receiver::buf_unframed: internal error"); - return Buffer(buf.data(), size, true); - } - - // return true if message is complete - bool complete() - { - // already complete? - if (header_complete) - return complete_(); - - // we need at least 2 bytes before we can do anything - if (buf.size() < 2) - return false; - - // get first 2 bytes of header - Buffer b(buf.data(), buf.size(), true); - const std::uint8_t* head = b.read_alloc(2); - s.opcode_ = head[0] & 0xF; - s.fin_ = bool(head[0] & 0x80); - if (head[0] & 0x70) - throw websocket_error("Receiver: reserved bits are set"); - if (bool(head[1] & 0x80) == is_client) - throw websocket_error("Receiver: bad masking direction"); - - // process payload length - const std::uint8_t pl = head[1] & 0x7f; - if (pl <= 125) - { - size = pl; - } - else if (pl == 126) - { - std::uint16_t len16; - if (b.size() < sizeof(len16)) - return false; - b.read(&len16, sizeof(len16)); - size = ntohs(len16); - } - else // pl == 127 - { - std::uint64_t len64; - if (b.size() < sizeof(len64)) - return false; - b.read(&len64, sizeof(len64)); - size = Endian::rev64(len64); - } - - // read mask (server side only) - if (!is_client) - { - if (b.size() < sizeof(mask)) - return false; - b.read(&mask, sizeof(mask)); - } - - buf.advance(b.offset()); - header_complete = true; - return complete_(); - } - - void add_buf(BufferAllocated&& inbuf) - { - if (!buf.allocated()) - { - buf = std::move(inbuf); - buf.or_flags(BufferAllocated::GROW); - } - else - buf.append(inbuf); - } - - void reset() - { - verify_message_complete(); - s = Status(); - reset_buf(); - reset_pod(); - } - - Status status() const - { - verify_message_complete(); - return s; - } - - private: - void reset_buf() - { - if (buf.allocated()) - { - if (size < buf.size()) - { - buf.advance(size); - buf.realign(0); - } - else if (size == buf.size()) - buf.clear(); - else - throw websocket_error("Receiver::reset_buf: bad size"); - } - } - - void reset_pod() - { - header_complete = false; - message_complete = false; - mask = 0; - size = 0; - } - - void verify_message_complete() const - { - if (!message_complete) - throw websocket_error("Receiver: message incomplete"); - } - - bool complete_() - { - if (message_complete) - return true; - - if (header_complete && size <= buf.size()) - { - // un-xor the data on the server side only - if (!is_client) - { - Buffer b(buf.data(), size, true); - const Protocol::MaskingKey mk(mask); - mk.xor_buf(b); - } - - // get close status code - if (s.opcode_ == Protocol::Close && size >= 2) - { - std::uint16_t cs; - buf.read(&cs, sizeof(cs)); - size -= sizeof(cs); - s.close_status_code_ = ntohs(cs); - } - - message_complete = true; - return true; - } - return false; - } - - const bool is_client; - bool header_complete; - bool message_complete; - std::uint32_t mask; - std::uint64_t size; - Status s; - BufferAllocated buf; - }; - - namespace Client { - - struct Config : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - std::string origin; - std::string protocol; - RandomAPI::Ptr rng; - DigestFactory::Ptr digest_factory; - - // compression - bool compress = false; - size_t compress_threshold = 256; - }; - - class PerRequest : public RC<thread_unsafe_refcount> - { - private: - Config::Ptr conf; - - public: - typedef RCPtr<PerRequest> Ptr; - - PerRequest(Config::Ptr conf_arg) - : conf(validate_conf(std::move(conf_arg))), - sender(conf->rng), - receiver(true) - { - } - - void client_headers(std::ostream& os) - { - generate_websocket_key(); - os << "Sec-WebSocket-Key: " << websocket_key << "\r\n"; - os << "Sec-WebSocket-Version: 13\r\n"; - if (!conf->protocol.empty()) - os << "Sec-WebSocket-Protocol: " << conf->protocol << "\r\n"; - os << "Connection: Upgrade\r\n"; - os << "Upgrade: websocket\r\n"; - if (!conf->origin.empty()) - os << "Origin: " << conf->origin << "\r\n"; - } - - bool confirm_websocket_key(const std::string& ws_accept) const - { - return ws_accept == accept_confirmation(*conf->digest_factory, websocket_key); - } - - Sender sender; - Receiver receiver; - - private: - static Config::Ptr validate_conf(Config::Ptr conf) - { - if (!conf) - throw websocket_error("no config"); - conf->rng->assert_crypto(); - if (!conf->digest_factory) - throw websocket_error("no digest factory in config"); - return conf; - } - - void generate_websocket_key() - { - std::uint8_t data[16]; - conf->rng->rand_bytes(data, sizeof(data)); - websocket_key = base64->encode(data, sizeof(data)); - } - - std::string websocket_key; - }; - - } - - namespace Server { - - struct Config : public RC<thread_unsafe_refcount> - { - typedef RCPtr<Config> Ptr; - - std::string protocol; - DigestFactory::Ptr digest_factory; - }; - - class PerRequest : public RC<thread_unsafe_refcount> - { - private: - Config::Ptr conf; - - public: - typedef RCPtr<PerRequest> Ptr; - - PerRequest(Config::Ptr conf_arg) - : conf(validate_conf(std::move(conf_arg))), - sender(RandomAPI::Ptr()), - receiver(false) - { - } - - void set_websocket_key(const std::string& websocket_key) - { - websocket_accept = accept_confirmation(*conf->digest_factory, websocket_key); - } - - void server_headers(std::ostream& os) - { - os << "Upgrade: websocket\r\n"; - os << "Connection: Upgrade\r\n"; - if (!websocket_accept.empty()) - os << "Sec-WebSocket-Accept: " << websocket_accept << "\r\n"; - if (!conf->protocol.empty()) - os << "Sec-WebSocket-Protocol: " << conf->protocol << "\r\n"; - } - - Sender sender; - Receiver receiver; - - private: - static Config::Ptr validate_conf(Config::Ptr conf) - { - if (!conf) - throw websocket_error("no config"); - if (!conf->digest_factory) - throw websocket_error("no digest factory in config"); - return conf; - } - - std::string websocket_accept; - }; - - } - - } -} diff --git a/Sources/OpenVPN3/scripts/build b/Sources/OpenVPN3/scripts/build deleted file mode 100755 index 4c46ca4..0000000 --- a/Sources/OpenVPN3/scripts/build +++ /dev/null @@ -1,398 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree - exit 1 -fi - -enum_build_extras() -{ - ls -d $(echo $O3/*/scripts/build-extras/*) | sort -} - -if [ -z "$1" ]; then - echo "usage: ./build target" - echo "options:" - echo " PROF=<platform> -- source vars/vars-<platform> before running" - echo " DPROF=1 -- when PROF is specified, use the debugging variant" - echo " CLANG=1 -- use clang instead of gcc" - echo " DEBUG=1 -- enable debug symbols" - echo " CO=1 -- compile only" - echo " OBJC=1 -- top-level source file is Obj-C" - echo ' ECHO=1 -- show commands' - echo ' OUTBIN=name -- write binary to name' - echo " STRIP=1 -- strip binary" - echo " STRICT=1 -- more warnings" - echo " LTO=1 -- build with LTO" - echo " GPROF=1 -- build for gprof profiling" - echo " PGEN=1 -- generate data for profile-guided optimization" - echo " PUSE=1 -- use data from previous run of PGEN=1 build" - echo " ASIO=1 -- build with ASIO" - echo " ASIO_DIR=<dir> -- specify ASIO tree" - echo " MTLS=1 -- include mbedTLS" - echo " MTLS_SYS=1 -- use system mbedTLS" - echo " MTLS_PATH=path -- use user specified mbedTLS source folder" - echo " MTLS_LIBS=ldflags -- user specific mbedTLS LDFLAGS" - echo " MTLS_DIST=path -- use user-specified mbedTLS distribution" - echo " MA_HYBRID=1 -- use mbedTLS/AppleCrypto hybrid" - echo " OPENSSL_DIST=<dir> -- specify custom OpenSSL build" - echo " NOSSL=1 -- don't include OpenSSL" - echo " OPENSSL_SYS=1 -- include system OpenSSL" - echo " MINI=1 -- link with OpenSSL mini crypto lib" - echo " OSSL=1 -- include OpenSSL" - echo " SSL_BOTH=1 -- include OpenSSL and Apple SSL on Mac" - echo " NOTHREADS=1 -- disable threads" - echo ' GCC_EXTRA="-DITER=5" -- add build flags' - echo " LZO=1 -- build with LZO compression library" - echo " LZ4=1 -- build with LZ4 compression library" - echo " LZ4_SYS=1 -- build with system LZ4 compression library" - echo " SNAP=1 -- build with Snappy compression library" - echo " CITY=1 -- build with Cityhash hash library" - echo " CAP=1 -- build with libcap" - echo " VAL=1 -- build with valgrind run-time extensions" - echo " JAVA=1 -- build with JVM" - echo ' EXTRA_CPP="foo1.cpp foo2.cpp" -- add extra .cpp files' - echo " GTEST_DIR=<dir> -- specify googletest tree, required for building unit tests" - echo " PCRE=1 -- build with PCRE library" - for s in $(enum_build_extras) ; do - . $s args - done - exit 1 -fi - -# determine platform if PROF is set to "auto" -if [ "$PROF" = "auto" ]; then - if [ "$(uname)" == "Darwin" ]; then - export PROF=osx64 - elif [ "$(uname)" == "Linux" ]; then - export PROF=linux - else - echo "PROF=auto : cannot determine platform" - exit 1 - fi -fi - -# source vars file -if [ "$PROF" ]; then - suffix="" - [ "$DPROF" = "1" ] && suffix="-dbg" - pfn="$O3/core/vars/vars-$PROF$suffix" - if ! [ -f "$pfn" ]; then - pfn="$PROF" - fi - . $pfn || exit 1 -fi - -# remove previous build -[ -z "$OUTBIN" ] && OUTBIN="$(basename $1)" -rm -f $OUTBIN - -# build options -CPPFLAGS="" -LIBS="" -LIBDIRS="" -EXTRA_SRC_OBJ="" - -# MbedTLS/AppleCrypto hybrid -if [ "$MA_HYBRID" = "1" ]; then - MTLS=1 -fi - -# building on Mac OS X for osx, ios, or iossim? -if [ "$APPLE_FAMILY" = "1" ]; then - [ -z "$CLANG" ] && CLANG=1 -fi - -# clang support -if [ "$CLANG" = "1" ]; then - [ -z "$GPP_CMD" ] && GPP_CMD=clang++ -fi - -# building on Linux, use system OpenSSL -if [ "$PLATFORM" = "linux" ] && [ "$OSSL" = "1" ] && [ "$NOSSL" != "1" ] && [ -z "$OPENSSL_SYS" ]; then - OSSL=0 - OPENSSL_SYS=1 -fi - -# building on Linux, use system LZ4 -if [ "$PLATFORM" = "linux" ] && [ "$LZ4" = "1" ] && [ -z "$LZ4_SYS" ]; then - LZ4_SYS=1 -fi - -# default commands -[ -z "$STRIP_CMD" ] && STRIP_CMD=strip -[ -z "$GPP_CMD" ] && GPP_CMD=g++ - -# build flags -FLAGS="-Wall" -[ "$STRICT" = "1" ] && FLAGS="$FLAGS -Wextra" -[ "$CLANG" = "1" ] && FLAGS="$FLAGS -Wno-tautological-compare -Wno-unused-private-field -Wno-c++1y-extensions" -FLAGS="$FLAGS -Wno-sign-compare -Wno-unused-parameter" - -# The Mac OS X tun/tap driver doesn't play with with kqueue. -# utun devices, however, work fine with kqueue. -#if [ "$PLATFORM" = "osx" ]; then -# CPPFLAGS="$CPPFLAGS -DBOOST_ASIO_DISABLE_KQUEUE" -#fi - -# MbedTLS -if [ -n "$MTLS_DIST" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS -I$MTLS_DIST/include" - LIBDIRS="$LIBDIRS -L$MTLS_DIST/library" - LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" - MTLS=1 -elif [ "$MTLS_SYS" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS" - LIBS="$LIBS -lmbedtls -lmbedx509 -lmbedcrypto" -elif [ "$MTLS" = "1" ]; then - LIBS="$LIBS -lmbedtls $MTLS_LIBS" - if [ "$MA_HYBRID" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS_APPLE_HYBRID" - else - CPPFLAGS="$CPPFLAGS -DUSE_MBEDTLS" - fi - if [ -n "$MTLS_PATH" ]; then - CPPFLAGS="$CPPFLAGS -I$MTLS_PATH/include" - LIBDIRS="$LIBDIRS -L$MTLS_PATH/library" - else - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/mbedtls/mbedtls-$PLATFORM/include" - LIBDIRS="$LIBDIRS -L$DEP_DIR/mbedtls/mbedtls-$PLATFORM/library" - fi - if [ "$MINI" = "1" ]; then - LIBS="$LIBS -lminicrypto" - LIBDIRS="$LIBDIRS -L$DEP_DIR/minicrypto/minicrypto-$PLATFORM" - CPPFLAGS="$CPPFLAGS -DUSE_MINICRYPTO" - NOSSL=1 - fi -fi - -# OpenSSL -if [ "$OPENSSL_DIST" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL -I$OPENSSL_DIST/include" - LIBDIRS="$LIBDIRS -L$OPENSSL_DIST/lib" - LIBS="$LIBS -lssl -lcrypto" -elif [ "$APPLE_FAMILY" = "1" ]; then - # On Mac, only link with OpenSSL if OSSL is defined. - # On other platforms, usually link with OpenSSL. - if [ "$OPENSSL_SYS" == "1" ]; then - NO_DEPRECATE="-Wno-deprecated-declarations" - else - NO_DEPRECATE="" - fi - if [ "$OPENSSL_LINK" = "1" ]; then - LIBS="$LIBS -lcrypto -lssl" - elif [ "$OSSL" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL" - LIBS="$LIBS -lcrypto -lssl" - [ "$CLANG" = "1" ] && [ "$NO_DEPRECATE" ] && FLAGS="$FLAGS $NO_DEPRECATE" - elif [ "$SSL_BOTH" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_APPLE_SSL -DUSE_OPENSSL" - LIBS="$LIBS -lcrypto -lssl" - [ "$CLANG" = "1" ] && [ "$NO_DEPRECATE" ] && FLAGS="$FLAGS $NO_DEPRECATE" - elif [ "$MTLS" = "1" ]; then - NOSSL=1 - else - NOSSL=1 - CPPFLAGS="$CPPFLAGS -DUSE_APPLE_SSL" - fi - LIBS="$LIBS -framework Security" -else - if [ "$OPENSSL_LINK" = "1" ]; then - LIBS="$LIBS -lcrypto -lssl" - elif [ "$NOSSL" != "1" ]; then - CPPFLAGS="$CPPFLAGS -DUSE_OPENSSL" - LIBS="$LIBS -lssl -lcrypto -ldl" - fi -fi -if [ "$OPENSSL_SYS" != "1" ] && [ "$OPENSSL_LINK" != "1" ] && [ "$NOSSL" != "1" ] && [ -z "$OPENSSL_DIST" ]; then - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/openssl/openssl-$PLATFORM/include" - LIBDIRS="$LIBDIRS -L$DEP_DIR/openssl/openssl-$PLATFORM/lib" -fi - -# Apple libs -if [ "$APPLE_FAMILY" = "1" ]; then - LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration -framework IOKit -framework ApplicationServices" -fi - -# boost -#CPPFLAGS="$CPPFLAGS -I$DEP_DIR/boost" -#LIBS="$LIBS -lboost_system" -#LIBDIRS="$LIBDIRS -L$DEP_DIR/boost/stage-$PLATFORM/lib" -#if [ "$NOTHREADS" = "1" ]; then -# CPPFLAGS="$CPPFLAGS -DBOOST_DISABLE_THREADS" -#else -# #LIBS="$LIBS -lboost_thread" # no longer needed because we use std::thread now -# [ "$PLATFORM" != "android" ] && FLAGS="$FLAGS -pthread" -#fi - -# asio -if [ "$ASIO" = "1" ] || [ "$ASIO_DIR" ]; then - [ -z "$ASIO_DIR" ] && ASIO_DIR="$DEP_DIR/asio" - CPPFLAGS="$CPPFLAGS -DUSE_ASIO -DASIO_STANDALONE -DASIO_NO_DEPRECATED -I$ASIO_DIR/asio/include" -fi - -# gtest -if [ "$GTEST_DIR" ]; then - CPPFLAGS="$CPPFLAGS -I$GTEST_DIR/googletest/include" - LIBDIRS="$LIBDIRS -L$GTEST_DIR/lib" - LIBS="$LIBS -lgtest" -fi - -# LZO compression -if [ "$LZO" = "1" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/lzo/lzo-$PLATFORM/lib" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/lzo/lzo-$PLATFORM/include" - LIBS="$LIBS -llzo2" - CPPFLAGS="$CPPFLAGS -DHAVE_LZO" -fi - -# LZ4 compression -if [ "$LZ4_SYS" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DHAVE_LZ4" - LIBS="$LIBS -llz4" -elif [ "$LZ4" = "1" ]; then - EXTRA_SRC_OBJ="$EXTRA_SRC_OBJ $DEP_DIR/lz4/lz4-$PLATFORM/lib/liblz4.a" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/lz4/lz4-$PLATFORM/include -DHAVE_LZ4" -fi - -# Snappy compression -if [ "$SNAP" = "1" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/snappy/snappy-$PLATFORM/lib" - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/snappy/snappy-$PLATFORM/include" - LIBS="$LIBS -lsnappy" - CPPFLAGS="$CPPFLAGS -DHAVE_SNAPPY" -fi - -# Cityhash -if [ "$CITY" = "1" ]; then - if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" ]; then - LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" - fi - if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/include" ]; then - CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include" - fi - LIBS="$LIBS -lcityhash" - CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH" -fi - -# libcap -if [ "$CAP" = "1" ]; then - LIBS="$LIBS -lcap" - CPPFLAGS="$CPPFLAGS -DHAVE_LIBCAP" -fi - -# PCRE -if [ "$PCRE" = "1" ]; then - LIBS="$LIBS -lpcre" -fi - -# Valgrind -if [ "$VAL" = "1" ]; then - CPPFLAGS="$CPPFLAGS -DHAVE_VALGRIND" -fi - -# JVM -if [ "$JAVA" = "1" ]; then - if [ -z "$JAVA_HOME" ]; then - echo JAVA_HOME not defined - exit 1 - fi - LIBDIRS="$LIBDIRS -L$JAVA_HOME/jre/lib/amd64/server" - CPPFLAGS="$CPPFLAGS -I$JAVA_HOME/include -I$JAVA_HOME/include/linux" - LIBS="$LIBS -ljvm" -fi - -# other environments -for s in $(enum_build_extras) ; do - . $s deps -done - -# Android NDK -if [ "$PLATFORM" = "android" ]; then - CPPFLAGS="$CPPFLAGS -D__GLIBC__" - CPPFLAGS="$CPPFLAGS -D_GLIBCXX_HAVE_FENV_H=1" -# CPPFLAGS="$CPPFLAGS -DBOOST_NO_INTRINSIC_WCHAR_T" -fi - -# Special platform flags -if [ "$PLATFORM_FLAGS" ]; then - FLAGS="$FLAGS $PLATFORM_FLAGS" -fi - -# C++ compiler flags -if [ "$CXX_COMPILER_FLAGS" ]; then - FLAGS="$FLAGS $CXX_COMPILER_FLAGS" -fi - -# Other compiler flags -if [ "$OTHER_COMPILER_FLAGS" ]; then - FLAGS="$FLAGS $OTHER_COMPILER_FLAGS" -fi - -# ovpn3 -CPPFLAGS="$CPPFLAGS -I$O3/core" - -# profile-guided optimization -if [ "$PGEN" = "1" ]; then - FLAGS="$FLAGS -fprofile-generate" -elif [ "$PUSE" = "1" ]; then - FLAGS="$FLAGS -fprofile-use" -fi - -# compiler flags -FLAGS="$LIB_OPT_LEVEL $FLAGS" - -# whole-program -if [ "$CLANG" != "1" ] && [ "$DEBUG_BUILD" != "1" ] && [ -z "$EXTRA_CPP" ] && [ "$CO" != "1" ]; then - FLAGS="-fwhole-program $FLAGS" -fi - -# compile only -if [ "$CO" == "1" ]; then - OUTPUT="-c" - LIBDIRS="" - LIBS="" - EXTRA_SRC_OBJ="" -else - OUTPUT="-o $OUTBIN" -fi - -# main source file -MAIN_CPP="$1.cpp" -if ! [ -e "$MAIN_CPP" ] && [ "$EXTRA_CPP" ]; then - MAIN_CPP="" -fi - -# release/debug builds -if [ "$DEBUG" = "1" ]; then - # build with debug symbols - if [ "$PLATFORM" = "linux" ]; then - FLAGS="-ggdb $FLAGS" - else - FLAGS="-g $FLAGS" - fi -else - # release build - [ "$LTO" = "1" ] && [ "$CLANG" != "1" ] && FLAGS="$FLAGS -flto=4 -Wl,--no-as-needed" - [ "$GPROF" = "1" ] && FLAGS="$FLAGS -pg" -fi - -# Construct command -if [ "$OBJC" == "1" ]; then - FLAGS="$FLAGS -fobjc-arc" - LIBS="-framework Foundation $LIBS" - SRC="$1.mm" - CMD="$GPP_CMD $FLAGS $GCC_EXTRA $CPPFLAGS $LIBDIRS $SRC $EXTRA_CPP $EXTRA_SRC_OBJ $OUTPUT $LIBS" -else - CMD="$GPP_CMD $FLAGS $GCC_EXTRA $CPPFLAGS $LIBDIRS $MAIN_CPP $EXTRA_CPP $EXTRA_SRC_OBJ $OUTPUT $LIBS" -fi - -# execute CMD -[ "$ECHO" = "1" ] && echo $CMD -$CMD - -# maybe strip -[ "$STRIP" = "1" ] && $STRIP_CMD $OUTBIN -exit 0 diff --git a/Sources/OpenVPN3/scripts/build-extras/zlib.sh b/Sources/OpenVPN3/scripts/build-extras/zlib.sh deleted file mode 100644 index c06adab..0000000 --- a/Sources/OpenVPN3/scripts/build-extras/zlib.sh +++ /dev/null @@ -1,8 +0,0 @@ -if [ "$1" = "args" ]; then - echo " ZLIB=1 -- link with zlib" -elif [ "$1" = "deps" ]; then - if [ "$ZLIB" = "1" ]; then - LIBS="$LIBS -lz" - CPPFLAGS="$CPPFLAGS -DHAVE_ZLIB" - fi -fi diff --git a/Sources/OpenVPN3/scripts/linux/build-all b/Sources/OpenVPN3/scripts/linux/build-all deleted file mode 100755 index 0c91792..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-all +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -export DEP_DIR=${DEP_DIR:-$HOME/linux} -export TARGET=${TARGET:-linux} -cd $DEP_DIR -rm -rf asio* boost* lz4* lzo* minicrypto openssl* polarssl* snappy* -echo "******* ASIO" -$O3/core/deps/asio/build-asio -echo "******* MBEDTLS" -$O3/core/scripts/linux/build-mbedtls -echo "******* LZ4" -$O3/core/scripts/linux/build-lz4 -echo "******* CITYHASH" -$O3/core/scripts/linux/build-cityhash - -#$O3/core/scripts/linux/build-openssl x64 -#$O3/core/scripts/linux/build-lzo -#$O3/core/scripts/linux/build-boost -#$O3/core/scripts/linux/build-snappy -#$O3/core/scripts/linux/consolidate-so diff --git a/Sources/OpenVPN3/scripts/linux/build-boost b/Sources/OpenVPN3/scripts/linux/build-boost deleted file mode 100755 index 9e69ea2..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-boost +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf boost -mkdir boost - -export TARGETS="linux" - -$O3/core/deps/boost/build-boost -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-cityhash b/Sources/OpenVPN3/scripts/linux/build-cityhash deleted file mode 100755 index 4daa4c2..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-cityhash +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf cityhash -mkdir cityhash -TARGET=${TARGET:-linux} $O3/core/deps/cityhash/build-cityhash -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-lz4 b/Sources/OpenVPN3/scripts/linux/build-lz4 deleted file mode 100755 index 956fb56..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-lz4 +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf lz4 -mkdir lz4 -TARGET=${TARGET:-linux} $O3/core/deps/lz4/build-lz4 -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-lzo b/Sources/OpenVPN3/scripts/linux/build-lzo deleted file mode 100755 index 878dd33..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-lzo +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf lzo -mkdir lzo -TARGET=linux $O3/core/deps/lzo/build-lzo -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-mbedtls b/Sources/OpenVPN3/scripts/linux/build-mbedtls deleted file mode 100755 index de355db..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-mbedtls +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf mbedtls - -if [ "$LINK_MODE" = "shared" ]; then - SHARED=1 -else - SHARED=0 -fi -VERBOSE=1 TARGET=${TARGET:-linux} ENABLE_SERVER=1 SHARED=$SHARED $O3/core/deps/mbedtls/build-mbedtls -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-openssl b/Sources/OpenVPN3/scripts/linux/build-openssl deleted file mode 100755 index 1273c41..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-openssl +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$1" ]; then - echo "usage: build-openssl x64|arm" - exit 1 -fi -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf openssl -mkdir openssl - -export LINK_MODE=shared - -case $1 in -x64*) - export OPENSSL_TARGET=linux-x86_64 - ;; -arm*) - export OPENSSL_TARGET=linux-armv4 - ;; -*) - echo "unknown platform" - exit 1 - ;; -esac - -TARGET=linux $O3/core/deps/openssl/build-openssl -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-polarssl b/Sources/OpenVPN3/scripts/linux/build-polarssl deleted file mode 100755 index 982fd0f..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-polarssl +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf polarssl -mkdir polarssl -if [ "$LINK_MODE" = "shared" ]; then - SHARED=1 -else - SHARED=0 -fi -VERBOSE=1 TARGET=linux ENABLE_SERVER=1 SHARED=$SHARED $O3/core/deps/polarssl/build-polarssl -mv polarssl-linux polarssl -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-polarssl-ovpn2 b/Sources/OpenVPN3/scripts/linux/build-polarssl-ovpn2 deleted file mode 100755 index 7191732..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-polarssl-ovpn2 +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# When running OpenVPN 2.x ./configure script, use the following command: -# -# POLARSSL_CFLAGS="-I$HOME/linux/polarssl/polarssl-linux/include" POLARSSL_LIBS="-L$HOME/linux/polarssl/polarssl-linux/library -lpolarssl" ./configure --with-crypto-library=polarssl - -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi - -rm -rf polarssl -mkdir polarssl -VERBOSE=1 TARGET=linux ENABLE_SERVER=1 ENABLE_FS_IO=1 $O3/core/deps/polarssl/build-polarssl -mv polarssl-linux polarssl -exit 0 diff --git a/Sources/OpenVPN3/scripts/linux/build-snappy b/Sources/OpenVPN3/scripts/linux/build-snappy deleted file mode 100755 index f56ea48..0000000 --- a/Sources/OpenVPN3/scripts/linux/build-snappy +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf snappy -mkdir snappy -TARGET=linux $O3/core/deps/snappy/build-snappy diff --git a/Sources/OpenVPN3/scripts/linux/consolidate-so b/Sources/OpenVPN3/scripts/linux/consolidate-so deleted file mode 100755 index 1949652..0000000 --- a/Sources/OpenVPN3/scripts/linux/consolidate-so +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -rm -rf so -mkdir so -OPT=-d -[ -d boost ] && cp $OPT boost/stage-linux/lib/lib* so/ -[ -d lzo ] && cp $OPT lzo/lzo-linux/lib/lib* so/ -[ -d openssl ] && cp $OPT openssl/openssl-linux/lib/lib* so/ -[ -d snappy ] && cp $OPT snappy/snappy-linux/lib/lib* so/ -[ -d polarssl ] && cp $OPT polarssl/polarssl-linux/library/lib* so/ -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-all b/Sources/OpenVPN3/scripts/mac/build-all deleted file mode 100755 index 1fc503c..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-all +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e -export DEP_DIR=${DEP_DIR:-$HOME/src/mac} -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -cd $DEP_DIR -rm -rf asio* boost* lz4* lzo* minicrypto openssl* polarssl* mbedtls* snappy* - -echo "******* ASIO" -$O3/core/deps/asio/build-asio -if [ $MTLS = 0 ] ; then - echo "******* MBEDTLS (skipped)" -else - echo "******* MBEDTLS" - - # consider OSX_SERVER=0 - $O3/core/scripts/mac/build-mbedtls -fi -# - -$O3/core/deps/asio/build-asio -if [ $OSSL = 1 ] ; then - echo "******* OPENSSL" - $O3/core/scripts/mac/build-openssl -else - echo "******* OPENSSL (skipped)" -fi - - -echo "******* LZ4" -$O3/core/scripts/mac/build-lz4 -echo "******* CITYHASH" -$O3/core/scripts/mac/build-cityhash - -#echo "******* MINICRYPTO" -#$O3/core/scripts/mac/build-minicrypto -#echo "******* SNAPPY" -#$O3/core/scripts/mac/build-snappy diff --git a/Sources/OpenVPN3/scripts/mac/build-boost b/Sources/OpenVPN3/scripts/mac/build-boost deleted file mode 100755 index 3263d8a..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-boost +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf boost -mkdir boost - -export LINK_MODE=static -if [ "$OSX_ONLY" == "1" ]; then - export TARGETS="osx osx-dbg" -else - export TARGETS="ios ios-dbg iossim iossim-dbg osx osx-dbg" -fi - -$O3/core/deps/boost/build-boost -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-cityhash b/Sources/OpenVPN3/scripts/mac/build-cityhash deleted file mode 100755 index 274826c..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-cityhash +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR -rm -rf cityhash -mkdir cityhash -TARGET=osx $O3/core/deps/cityhash/build-cityhash -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-lz4 b/Sources/OpenVPN3/scripts/mac/build-lz4 deleted file mode 100755 index b87266e..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-lz4 +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf lz4 -mkdir lz4 - -if [ "$OSX_ONLY" != "1" ]; then - for target in ios ios-dbg iossim iossim-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lz4/build-lz4 - done -fi - -for target in osx osx-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lz4/build-lz4 -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-lzo b/Sources/OpenVPN3/scripts/mac/build-lzo deleted file mode 100755 index 2a58c14..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-lzo +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -set -e -[ "$DEP_DIR" ] && cd $DEP_DIR -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf lzo -mkdir lzo - -if [ "$OSX_ONLY" != "1" ]; then - for target in ios ios-dbg iossim iossim-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lzo/build-lzo - done -fi - -for target in osx64 osx64-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/lzo/build-lzo -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-mbedtls b/Sources/OpenVPN3/scripts/mac/build-mbedtls deleted file mode 100755 index 1fe4c7d..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-mbedtls +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf mbedtls - -if [ "$OSX_ONLY" != "1" ]; then - # for ios, build with minicrypto - for target in ios-dbg ios ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target USE_MINICRYPTO=0 $O3/core/deps/mbedtls/build-mbedtls - [ "$IOS_DBG_ONLY" = "1" ] && exit - done - - # ios simulators - for target in iossim iossim-dbg ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target $O3/core/deps/mbedtls/build-mbedtls - done -fi - -# osx -[ -z "$OSX_MINICRYPTO" ] && OSX_MINICRYPTO=0 -[ -z "$OSX_SERVER" ] && OSX_SERVER=1 -for target in osx osx-dbg ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target USE_MINICRYPTO=$OSX_MINICRYPTO MINICRYPTO_NO_AES=1 ENABLE_SERVER=$OSX_SERVER $O3/core/deps/mbedtls/build-mbedtls -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-minicrypto b/Sources/OpenVPN3/scripts/mac/build-minicrypto deleted file mode 100755 index af7452e..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-minicrypto +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -e -[ "$DEP_DIR" ] && cd $DEP_DIR -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf minicrypto -mkdir minicrypto - -for target in osx osx-dbg ; do - echo '***************' Minicrypto-32 $target - TARGET=$target ARCH=i386 $O3/core/deps/minicrypto/build-minicrypto-osx - echo '***************' Minicrypto-64 $target - TARGET=$target ARCH=x86_64 $O3/core/deps/minicrypto/build-minicrypto-osx - cd minicrypto/minicrypto-$target - lipo -create */libminicrypto.a -output libminicrypto.a - lipo -info libminicrypto.a - cd ../.. -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-openssl b/Sources/OpenVPN3/scripts/mac/build-openssl deleted file mode 100755 index 25376aa..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-openssl +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -set -e -[ "$DEP_DIR" ] && cd $DEP_DIR -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf openssl -mkdir openssl - -for target in ios osx; do - echo '***************' OpenSSL-64 $target - - if [ "$target" = "osx" ]; then - TARGET=$target OPENSSL_TARGET=darwin64-x86_64-cc $O3/core/deps/openssl/build-openssl - else - ARCH=arm64 CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer \ - CROSS_SDK=iPhoneOS.sdk TARGET=$target OPENSSL_TARGET="ios64-cross no-dso no-engine" \ - $O3/core/deps/openssl/build-openssl - - ARCH=armv7 CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer \ - CROSS_SDK=iPhoneOS.sdk TARGET=$target OPENSSL_TARGET="ios-cross no-dso no-engine" \ - $O3/core/deps/openssl/build-openssl - fi -done - -cd openssl/openssl-ios -mkdir -p fat/lib -for l in libcrypto.a libssl.a ; do - lipo -create arm64/lib/$l armv7/lib/$l -output fat/lib/$l -done - -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-polarssl b/Sources/OpenVPN3/scripts/mac/build-polarssl deleted file mode 100755 index 1afb5f6..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-polarssl +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf polarssl -mkdir polarssl - -if [ "$OSX_ONLY" != "1" ]; then - # for ios, build with minicrypto - for target in ios-dbg ios ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target USE_MINICRYPTO=0 $O3/core/deps/polarssl/build-polarssl - mv polarssl-$target polarssl - [ "$IOS_DBG_ONLY" = "1" ] && exit - done - - # ios simulators - for target in iossim iossim-dbg ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target $O3/core/deps/polarssl/build-polarssl - mv polarssl-$target polarssl/ - done -fi - -# osx -[ -z "$OSX_MINICRYPTO" ] && OSX_MINICRYPTO=0 -[ -z "$OSX_SERVER" ] && OSX_SERVER=1 -for target in osx osx-dbg ; do - echo '***************' TARGET $target - VERBOSE=1 TARGET=$target USE_MINICRYPTO=$OSX_MINICRYPTO MINICRYPTO_NO_AES=1 ENABLE_SERVER=$OSX_SERVER $O3/core/deps/polarssl/build-polarssl - mv polarssl-$target polarssl/ -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mac/build-snappy b/Sources/OpenVPN3/scripts/mac/build-snappy deleted file mode 100755 index 995829d..0000000 --- a/Sources/OpenVPN3/scripts/mac/build-snappy +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash - -set -e -if [ -z "$O3" ]; then - echo O3 var must point to ovpn3 tree ; exit 1 -fi -if [ -z "$DEP_DIR" ]; then - echo DEP_DIR var must point to ovpn3 dependency tree - exit 1 -fi -cd $DEP_DIR - -rm -rf snappy -mkdir snappy - -if [ "$OSX_ONLY" != "1" ]; then - for target in ios ios-dbg iossim iossim-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/snappy/build-snappy - done -fi - -for target in osx osx-dbg ; do - echo '***************' TARGET $target - TARGET=$target $O3/core/deps/snappy/build-snappy -done -exit 0 diff --git a/Sources/OpenVPN3/scripts/mingw/.gitignore b/Sources/OpenVPN3/scripts/mingw/.gitignore deleted file mode 100644 index 86f931c..0000000 --- a/Sources/OpenVPN3/scripts/mingw/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build-i686 -build-x86_64 -deps-i686 -deps-x86_64 diff --git a/Sources/OpenVPN3/scripts/mingw/build b/Sources/OpenVPN3/scripts/mingw/build deleted file mode 100755 index 4616d1e..0000000 --- a/Sources/OpenVPN3/scripts/mingw/build +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env bash - -set -e - -DL="${DL:-/tmp/dl}" -DEP_DIR_PREFIX=$PWD/deps -CMAKE_C_COMPILER="w64-mingw32-gcc-posix" -CMAKE_CXX_COMPILER="w64-mingw32-g++-posix" -ARCH=${ARCH:-i686 x86_64} - -download_deps() -{ - if [ -n "$NO_DEPS" ]; then - echo "Skip dependencies download" - return - fi - - pushd $DL - - rm -rf lz4 - git clone https://github.com/lz4/lz4.git - - rm -rf jsoncpp - git clone https://github.com/open-source-parsers/jsoncpp.git - - if [ -z "$NO_OPENSSL" ]; then - rm -rf openssl - git clone --single-branch --branch OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git - fi - - rm -rf tap-windows6 - git clone https://github.com/OpenVPN/tap-windows6.git - - rm -rf asio - git clone --single-branch --branch asio-1-16-1 https://github.com/chriskohlhoff/asio - - popd -} - -build_lz4() -{ - ARCH=$1 - - pushd $DL/lz4 - - mkdir build-${ARCH} - cd build-${ARCH} - - cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \ - ../build/cmake/ - make && make install - - popd -} - -build_jsoncpp() -{ - ARCH=$1 - - pushd $DL/jsoncpp - - mkdir build-${ARCH} - cd build-${ARCH} - - cmake -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_INSTALL_PREFIX=$DEP_DIR_PREFIX-$ARCH \ - -D JSONCPP_WITH_TESTS=false \ - -D BUILD_SHARED_LIBS=true \ - -D CMAKE_BUILD_TYPE=Release \ - .. - make && make install - - popd -} - -build_openssl() -{ - if [ -n "$NO_OPENSSL" ]; then - echo "Skip OpenSSL build" - return - fi - - ARCH=$1 - - pushd $DL/openssl - - [ "$ARCH" == "x86_64" ] && OUT="mingw64" || OUT="mingw" - make clean || true - ./Configure --prefix=$DEP_DIR_PREFIX-$ARCH no-idea no-mdc2 no-rc5 shared $OUT --cross-compile-prefix=$ARCH-w64-mingw32- - make && make -j1 install || true - - popd -} - -build_tap_windows6() -{ - ARCH=$1 - - cp $DL/tap-windows6/src/tap-windows.h $DEP_DIR_PREFIX-$ARCH/include -} - -build_asio() -{ - ARCH=$1 - - mkdir -p $DEP_DIR_PREFIX-$ARCH/asio - cp -R $DL/asio/* $DEP_DIR_PREFIX-$ARCH/asio -} - -build_deps() -{ - if [ -n "$NO_DEPS" ]; then - echo "Skip dependencies build" - return - fi - - ARCH=$1 - - echo "Building deps for $arch" - - mkdir -p $DEP_DIR_PREFIX-$ARCH - - build_lz4 $ARCH - build_jsoncpp $ARCH - build_tap_windows6 $ARCH - build_asio $ARCH - build_openssl $ARCH -} - -build_core() -{ - ARCH=$1 - - echo "Building core for $arch" - - rm -rf build-$ARCH - mkdir build-$ARCH - - CORE_DIR=$(dirname $(realpath -s $0))/../.. - - pushd build-$ARCH - - DEP_DIR=$DEP_DIR_PREFIX-$ARCH \ - OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR:-$DEP_DIR_PREFIX-$ARCH} \ - cmake -D CMAKE_C_COMPILER=$ARCH-$CMAKE_C_COMPILER \ - -D CMAKE_CXX_COMPILER=$ARCH-$CMAKE_CXX_COMPILER \ - -D CMAKE_SYSTEM_NAME=Windows \ - -D CMAKE_PREFIX_PATH=/usr/local/$ARCH-w64-mingw32 \ - -D CMAKE_BUILD_TYPE=Release \ - -D USE_WERROR=true \ - $CORE_DIR - - make - - popd -} - -mkdir -p $DL - -download_deps -for arch in $ARCH -do - echo "Building for $arch" - build_deps $arch - build_core $arch -done diff --git a/Sources/OpenVPN3/scripts/snapshot b/Sources/OpenVPN3/scripts/snapshot deleted file mode 100755 index 537a069..0000000 --- a/Sources/OpenVPN3/scripts/snapshot +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -# Create a tarball from a git checkout. -# -# DEP_DIR : dependency directory -# NAME : basename of git root directory in dependency directory -# DL : download directory, where to build tarball, defaults to ~/Downloads - -# Note: this script gives priority to $NAME-yyyymmdd as source location, -# so for Asio, make sure to delete such directories if you want to -# favor straight "asio" directory. - -set -e -if [ -z "$NAME" ]; then - echo "NAME var must exist" - exit 1 -fi -[ -z "$DL" ] && DL=~/Downloads -if ! [ -d "$DL" ]; then - echo $DL directory must exist - exit 1 -fi -[ "$DEP_DIR" ] && cd $DEP_DIR -NAMETS=$(ls -dt ${NAME}-* 2>/dev/null | head -n1) -if [ -z "$NAMETS" ]; then - cd $NAME - NAMETS=${NAME}-$(git log -1 --date=short --pretty=format:%cd | tr -d '-') - cd .. - mv $NAME $NAMETS -fi -NAMEVER=$(echo $NAME | awk '{print toupper($0)}')_VERSION -TGZ=$DL/$NAMETS.tar.gz -echo "creating $TGZ" -tar cfz $TGZ $NAMETS -echo 'Add to $O3/core/deps/lib-versions :' -echo "export $NAMEVER=$NAMETS" diff --git a/Sources/OpenVPN3/scripts/update-copyright b/Sources/OpenVPN3/scripts/update-copyright deleted file mode 100755 index d831fcf..0000000 --- a/Sources/OpenVPN3/scripts/update-copyright +++ /dev/null @@ -1,51 +0,0 @@ -#!/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 diff --git a/Sources/OpenVPN3/scripts/version b/Sources/OpenVPN3/scripts/version deleted file mode 100755 index 836c848..0000000 --- a/Sources/OpenVPN3/scripts/version +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# OpenVPN -- An application to securely tunnel IP networks -# over a single port, with support for SSL/TLS-based -# session authentication and key exchange, -# packet encryption, packet authentication, and -# packet compression. -# -# Copyright (C) 2018-2020 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/>. - -set -eu - -# ensure this script works even when core is used as submodule, by setting -# O3/core/.git as git folder -export GIT_DIR=$(dirname $0)/../.git - -MAJOR=3 -BRANCH="$(git rev-parse --symbolic-full-name HEAD | cut -d/ -f3- | tr / _)" -COMMIT_ID="$(git rev-list HEAD -1 --abbrev-commit)" - -echo "$MAJOR.git:$BRANCH:$COMMIT_ID" diff --git a/Sources/OpenVPN3/test/ovpncli/.gitignore b/Sources/OpenVPN3/test/ovpncli/.gitignore deleted file mode 100644 index 2b4d478..0000000 --- a/Sources/OpenVPN3/test/ovpncli/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -cli -cli.dSYM -build.tmp diff --git a/Sources/OpenVPN3/test/ovpncli/CMakeLists.txt b/Sources/OpenVPN3/test/ovpncli/CMakeLists.txt deleted file mode 100644 index 4ca810d..0000000 --- a/Sources/OpenVPN3/test/ovpncli/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -set(CMAKE_CXX_STANDARD 14) - -include(findcoredeps) - -option(CLI_NULLTUN "Build ovpncli variant with null tun" OFF) -option(CLI_KOVPN "Build ovpncli variant with kovpn kernel moduke support" OFF) -option(CLI_OVPNDCO "Build ovpncli variant with ovpn-dco kernel module support" OFF) - -set(KOVPN_SOURCE "${CORE_DIR}/../kovpn" CACHE PATH "ovpn-dco kernel module source tree") -set(OVPN_DCO_SOURCE "${CORE_DIR}/../ovpn-dco" CACHE PATH "ovpn-dco kernel module source tree") - -add_executable(ovpncli cli.cpp) - -add_core_dependencies(ovpncli) - -if (${CLI_NULLTUN}) - add_executable(ovpnclinull cli.cpp) - add_core_dependencies(ovpnclinull) - target_compile_definitions(ovpnclinull PRIVATE -DOPENVPN_FORCE_TUN_NULL) -endif () - -if (${CLI_KOVPN}) - add_executable(ovpnclikovpn cli.cpp) - add_core_dependencies(ovpnclikovpn) - - target_compile_definitions(ovpnclikovpn PRIVATE -DENABLE_KOVPN) - - include(kovpn) - add_kovpn_dependency(ovpnclikovpn) - target_include_directories(ovpnclikovpn PRIVATE ${KOVPN_SOURCE}) -endif() - -if (${CLI_OVPNDCO}) - add_executable(ovpncliovpndco cli.cpp) - add_core_dependencies(ovpncliovpndco) - - target_compile_definitions(ovpncliovpndco PRIVATE -DENABLE_OVPNDCO) - - find_package(PkgConfig) - pkg_search_module(LIBNL REQUIRED libnl-genl-3.0) - - target_include_directories(ovpncliovpndco PRIVATE ${OVPN_DCO_SOURCE}/include/uapi ${LIBNL_INCLUDE_DIRS}) - target_link_libraries(ovpncliovpndco ${LIBNL_LIBRARIES}) -endif() - -if (WIN32) - # for macos, agent-enabled client requires common and is built by scripts there - add_executable(ovpncliagent cli.cpp) - add_core_dependencies(ovpncliagent) - add_json_library(ovpncliagent) - target_compile_definitions(ovpncliagent PRIVATE -DOPENVPN_COMMAND_AGENT -DOVPNAGENT_DISABLE_PATH_CHECK) -endif () diff --git a/Sources/OpenVPN3/test/ovpncli/README.txt b/Sources/OpenVPN3/test/ovpncli/README.txt deleted file mode 100644 index 1c21868..0000000 --- a/Sources/OpenVPN3/test/ovpncli/README.txt +++ /dev/null @@ -1,24 +0,0 @@ -Build on Mac: - - With MbedTLS: - GCC_EXTRA="-ferror-limit=4" STRIP=1 MTLS=1 SNAP=1 LZ4=1 build cli - - With MbedTLS and Minicrypto: - GCC_EXTRA="-ferror-limit=4" STRIP=1 MTLS=1 MINI=1 SNAP=1 LZ4=1 build cli - - With MbedTLS, Minicrypto, and C++11 for optimized move constructors: - GCC_EXTRA="-ferror-limit=4 -std=c++11" STRIP=1 MTLS=1 MINI=1 SNAP=1 LZ4=1 build cli - - With OpenSSL: - GCC_EXTRA="-ferror-limit=4" STRIP=1 OSSL=1 OPENSSL_SYS=1 SNAP=1 LZ4=1 build cli - - With MbedTLS/AppleCrypto hybrid: - GCC_EXTRA="-ferror-limit=4" STRIP=1 HYBRID=1 SNAP=1 LZ4=1 build cli - -Build on Linux: - - With MbedTLS: - STRIP=1 SNAP=1 LZ4=1 MTLS=1 NOSSL=1 build cli - - With OpenSSL: - STRIP=1 SNAP=1 LZ4=1 build cli diff --git a/Sources/OpenVPN3/test/ovpncli/cli.cpp b/Sources/OpenVPN3/test/ovpncli/cli.cpp deleted file mode 100644 index 0341583..0000000 --- a/Sources/OpenVPN3/test/ovpncli/cli.cpp +++ /dev/null @@ -1,1227 +0,0 @@ -// 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-2020 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/>. - -// OpenVPN 3 test client - -#include <stdlib.h> // for atoi - -#include <string> -#include <iostream> -#include <thread> -#include <memory> -#include <mutex> - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_MAC -#include <CoreFoundation/CFBundle.h> -#include <ApplicationServices/ApplicationServices.h> -#endif - -// If enabled, don't direct ovpn3 core logging to -// ClientAPI::OpenVPNClient::log() virtual method. -// Instead, logging will go to LogBaseSimple::log(). -// In this case, make sure to define: -// LogBaseSimple log; -// at the top of your main() function to receive -// log messages from all threads. -// Also, note that the OPENVPN_LOG_GLOBAL setting -// MUST be consistent across all compilation units. -#ifdef OPENVPN_USE_LOG_BASE_SIMPLE -#define OPENVPN_LOG_GLOBAL // use global rather than thread-local log object pointer -#include <openvpn/log/logbasesimple.hpp> -#endif - -// don't export core symbols -#define OPENVPN_CORE_API_VISIBILITY_HIDDEN - -// use SITNL on Linux by default -#if defined(OPENVPN_PLATFORM_LINUX) && !defined(OPENVPN_USE_IPROUTE2) && !defined(OPENVPN_USE_SITNL) -#define OPENVPN_USE_SITNL -#endif - -// should be included before other openvpn includes, -// with the exception of openvpn/log includes -#include <client/ovpncli.cpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/string.hpp> -#include <openvpn/common/signal.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/getopt.hpp> -#include <openvpn/common/getpw.hpp> -#include <openvpn/common/cleanup.hpp> -#include <openvpn/time/timestr.hpp> -#include <openvpn/ssl/peerinfo.hpp> -#include <openvpn/ssl/sslchoose.hpp> - -#ifdef OPENVPN_REMOTE_OVERRIDE -#include <openvpn/common/process.hpp> -#endif - -#if defined(USE_MBEDTLS) -#include <openvpn/mbedtls/util/pkcs1.hpp> -#endif - -#if defined(OPENVPN_PLATFORM_WIN) -#include <openvpn/win/console.hpp> -#include <shellapi.h> -#endif - -#ifdef USE_NETCFG -#include "client/core-client-netcfg.hpp" -#endif - -#if defined(OPENVPN_PLATFORM_LINUX) - -#include <openvpn/tun/linux/client/tuncli.hpp> - -// we use a static polymorphism and define a -// platform-specific TunSetup class, responsible -// for setting up tun device -#define TUN_CLASS_SETUP TunLinuxSetup::Setup<TUN_LINUX> -#include <openvpn/tun/linux/client/tuncli.hpp> -#elif defined(OPENVPN_PLATFORM_MAC) -#include <openvpn/tun/mac/client/tuncli.hpp> -#define TUN_CLASS_SETUP TunMac::Setup -#endif - -using namespace openvpn; - -namespace { - OPENVPN_SIMPLE_EXCEPTION(usage); -} - -#ifdef USE_TUN_BUILDER -class ClientBase : public ClientAPI::OpenVPNClient -{ -public: - bool tun_builder_new() override - { - tbc.tun_builder_set_mtu(1500); - return true; - } - - int tun_builder_establish() override - { - if (!tun) - { - tun.reset(new TUN_CLASS_SETUP()); - } - - TUN_CLASS_SETUP::Config config; - config.layer = Layer(Layer::Type::OSI_LAYER_3); - // no need to add bypass routes on establish since we do it on socket_protect - config.add_bypass_routes_on_establish = false; - return tun->establish(tbc, &config, nullptr, std::cout); - } - - bool tun_builder_add_address(const std::string& address, - int prefix_length, - const std::string& gateway, // optional - bool ipv6, - bool net30) override - { - return tbc.tun_builder_add_address(address, prefix_length, gateway, ipv6, net30); - } - - bool tun_builder_add_route(const std::string& address, - int prefix_length, - int metric, - bool ipv6) override - { - return tbc.tun_builder_add_route(address, prefix_length, metric, ipv6); - } - - bool tun_builder_reroute_gw(bool ipv4, - bool ipv6, - unsigned int flags) override - { - return tbc.tun_builder_reroute_gw(ipv4, ipv6, flags); - } - - bool tun_builder_set_remote_address(const std::string& address, - bool ipv6) override - { - return tbc.tun_builder_set_remote_address(address, ipv6); - } - - bool tun_builder_set_session_name(const std::string& name) override - { - return tbc.tun_builder_set_session_name(name); - } - - bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override - { - return tbc.tun_builder_add_dns_server(address, ipv6); - } - - void tun_builder_teardown(bool disconnect) override - { - std::ostringstream os; - auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - tun->destroy(os); - } - - bool socket_protect(int socket, std::string remote, bool ipv6) override - { - (void)socket; - std::ostringstream os; - auto os_print = Cleanup([&os](){ OPENVPN_LOG_STRING(os.str()); }); - return tun->add_bypass_route(remote, ipv6, os); - } - -private: - TUN_CLASS_SETUP::Ptr tun = new TUN_CLASS_SETUP(); - TunBuilderCapture tbc; -}; -#else // USE_TUN_BUILDER -class ClientBase : public ClientAPI::OpenVPNClient -{ -public: - bool socket_protect(int socket, std::string remote, bool ipv6) override - { - std::cout << "NOT IMPLEMENTED: *** socket_protect " << socket << " " << remote << std::endl; - return true; - } -}; -#endif - -class Client : public ClientBase -{ -public: - enum ClockTickAction { - CT_UNDEF, - CT_STOP, - CT_RECONNECT, - CT_PAUSE, - CT_RESUME, - CT_STATS, - }; - - bool is_dynamic_challenge() const - { - return !dc_cookie.empty(); - } - - std::string dynamic_challenge_cookie() - { - return dc_cookie; - } - - std::string epki_ca; - std::string epki_cert; -#if defined(USE_MBEDTLS) - MbedTLSPKI::PKContext epki_ctx; // external PKI context -#endif - - void set_clock_tick_action(const ClockTickAction action) - { - clock_tick_action = action; - } - - void print_stats() - { - const int n = stats_n(); - std::vector<long long> stats = stats_bundle(); - - std::cout << "STATS:" << std::endl; - for (int i = 0; i < n; ++i) - { - const long long value = stats[i]; - if (value) - std::cout << " " << stats_name(i) << " : " << value << std::endl; - } - } - -#ifdef OPENVPN_REMOTE_OVERRIDE - void set_remote_override_cmd(const std::string& cmd) - { - remote_override_cmd = cmd; - } -#endif - - void set_write_url_fn(const std::string& fn) - { - write_url_fn = fn; - } - -private: - virtual void event(const ClientAPI::Event& ev) override - { - std::cout << date_time() << " EVENT: " << ev.name; - if (!ev.info.empty()) - std::cout << ' ' << ev.info; - if (ev.fatal) - std::cout << " [FATAL-ERR]"; - else if (ev.error) - std::cout << " [ERR]"; - std::cout << std::endl; - if (ev.name == "DYNAMIC_CHALLENGE") - { - dc_cookie = ev.info; - - ClientAPI::DynamicChallenge dc; - if (ClientAPI::OpenVPNClient::parse_dynamic_challenge(ev.info, dc)) { - std::cout << "DYNAMIC CHALLENGE" << std::endl; - std::cout << "challenge: " << dc.challenge << std::endl; - std::cout << "echo: " << dc.echo << std::endl; - std::cout << "responseRequired: " << dc.responseRequired << std::endl; - std::cout << "stateID: " << dc.stateID << std::endl; - } - } - else if (ev.name == "INFO" && (string::starts_with(ev.info, "OPEN_URL:http://") - || string::starts_with(ev.info, "OPEN_URL:https://"))) - { - // launch URL - const std::string url_str = ev.info.substr(9); - - if (!write_url_fn.empty()) - write_string(write_url_fn, url_str + '\n'); - -#ifdef OPENVPN_PLATFORM_MAC - std::thread thr([url_str]() { - CFURLRef url = CFURLCreateWithBytes( - NULL, // allocator - (UInt8*)url_str.c_str(), // URLBytes - url_str.length(), // length - kCFStringEncodingUTF8, // encoding - NULL // baseURL - ); - LSOpenCFURLRef(url, 0); - CFRelease(url); - }); - thr.detach(); -#else - std::cout << "No implementation to launch " << url_str << std::endl; -#endif - } - } - - virtual void log(const ClientAPI::LogInfo& log) override - { - std::lock_guard<std::mutex> lock(log_mutex); - std::cout << date_time() << ' ' << log.text << std::flush; - } - - virtual void clock_tick() override - { - const ClockTickAction action = clock_tick_action; - clock_tick_action = CT_UNDEF; - - switch (action) - { - case CT_STOP: - std::cout << "signal: CT_STOP" << std::endl; - stop(); - break; - case CT_RECONNECT: - std::cout << "signal: CT_RECONNECT" << std::endl; - reconnect(0); - break; - case CT_PAUSE: - std::cout << "signal: CT_PAUSE" << std::endl; - pause("clock-tick pause"); - break; - case CT_RESUME: - std::cout << "signal: CT_RESUME" << std::endl; - resume(); - break; - case CT_STATS: - std::cout << "signal: CT_STATS" << std::endl; - print_stats(); - break; - default: - break; - } - } - - virtual void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override - { - if (!epki_cert.empty()) - { - certreq.cert = epki_cert; - certreq.supportingChain = epki_ca; - } - else - { - certreq.error = true; - certreq.errorText = "external_pki_cert_request not implemented"; - } - } - - virtual void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override - { -#if defined(USE_MBEDTLS) - if (epki_ctx.defined()) - { - try { - // decode base64 sign request - BufferAllocated signdata(256, BufferAllocated::GROW); - base64->decode(signdata, signreq.data); - - // get MD alg - const mbedtls_md_type_t md_alg = PKCS1::DigestPrefix::MbedTLSParse().alg_from_prefix(signdata); - - // log info - OPENVPN_LOG("SIGN[" << PKCS1::DigestPrefix::MbedTLSParse::to_string(md_alg) << ',' << signdata.size() << "]: " << render_hex_generic(signdata)); - - // allocate buffer for signature - BufferAllocated sig(mbedtls_pk_get_len(epki_ctx.get()), BufferAllocated::ARRAY); - - // sign it - size_t sig_size = 0; - const int status = mbedtls_pk_sign(epki_ctx.get(), - md_alg, - signdata.c_data(), - signdata.size(), - sig.data(), - &sig_size, - rng_callback, - this); - if (status != 0) - throw Exception("mbedtls_pk_sign failed, err=" + openvpn::to_string(status)); - if (sig.size() != sig_size) - throw Exception("unexpected signature size"); - - // encode base64 signature - signreq.sig = base64->encode(sig); - OPENVPN_LOG("SIGNATURE[" << sig_size << "]: " << signreq.sig); - } - catch (const std::exception& e) - { - signreq.error = true; - signreq.errorText = std::string("external_pki_sign_request: ") + e.what(); - } - } - else -#endif - { - signreq.error = true; - signreq.errorText = "external_pki_sign_request not implemented"; - } - } - - // RNG callback - static int rng_callback(void *arg, unsigned char *data, size_t len) - { - Client *self = (Client *)arg; - if (!self->rng) - { - self->rng.reset(new SSLLib::RandomAPI(false)); - self->rng->assert_crypto(); - } - return self->rng->rand_bytes_noexcept(data, len) ? 0 : -1; // using -1 as a general-purpose mbed TLS error code - } - - virtual bool pause_on_connection_timeout() override - { - return false; - } - -#ifdef OPENVPN_REMOTE_OVERRIDE - virtual bool remote_override_enabled() override - { - return !remote_override_cmd.empty(); - } - - virtual void remote_override(ClientAPI::RemoteOverride& ro) - { - RedirectPipe::InOut pio; - Argv argv; - argv.emplace_back(remote_override_cmd); - OPENVPN_LOG(argv.to_string()); - const int status = system_cmd(remote_override_cmd, - argv, - nullptr, - pio, - RedirectPipe::IGNORE_ERR, - nullptr); - if (!status) - { - const std::string out = string::first_line(pio.out); - OPENVPN_LOG("REMOTE OVERRIDE: " << out); - auto svec = string::split(out, ','); - if (svec.size() == 4) - { - ro.host = svec[0]; - ro.ip = svec[1]; - ro.port = svec[2]; - ro.proto = svec[3]; - } - else - ro.error = "cannot parse remote-override, expecting host,ip,port,proto (at least one or both of host and ip must be defined)"; - } - else - ro.error = "status=" + std::to_string(status); - } -#endif - - std::mutex log_mutex; - std::string dc_cookie; - RandomAPI::Ptr rng; // random data source for epki - volatile ClockTickAction clock_tick_action = CT_UNDEF; - -#ifdef OPENVPN_REMOTE_OVERRIDE - std::string remote_override_cmd; -#endif - - std::string write_url_fn; -}; - -static Client *the_client = nullptr; // GLOBAL - -static void worker_thread() -{ -#if !defined(OPENVPN_OVPNCLI_SINGLE_THREAD) - openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread -#endif - try { - std::cout << "Thread starting..." << std::endl; - ClientAPI::Status connect_status = the_client->connect(); - if (connect_status.error) - { - std::cout << "connect error: "; - if (!connect_status.status.empty()) - std::cout << connect_status.status << ": "; - std::cout << connect_status.message << std::endl; - } - } - catch (const std::exception& e) - { - std::cout << "Connect thread exception: " << e.what() << std::endl; - } - std::cout << "Thread finished" << std::endl; -} - -static std::string read_profile(const char *fn, const std::string* profile_content) -{ - if (!string::strcasecmp(fn, "http") && profile_content && !profile_content->empty()) - return *profile_content; - else - { - ProfileMerge pm(fn, "ovpn", "", ProfileMerge::FOLLOW_FULL, - ProfileParseLimits::MAX_LINE_SIZE, ProfileParseLimits::MAX_PROFILE_SIZE); - if (pm.status() != ProfileMerge::MERGE_SUCCESS) - OPENVPN_THROW_EXCEPTION("merge config error: " << pm.status_string() << " : " << pm.error()); - return pm.profile_content(); - } -} - -#if defined(OPENVPN_PLATFORM_WIN) - -static void start_thread(Client& client) -{ - // Set Windows title bar - const std::string title_text = "F2:Stats F3:Reconnect F4:Stop F5:Pause"; - Win::Console::Title title(ClientAPI::OpenVPNClient::platform() + " " + title_text); - Win::Console::Input console; - - // start connect thread - std::unique_ptr<std::thread> thread; - volatile bool thread_exit = false; - the_client = &client; - thread.reset(new std::thread([&thread_exit]() { - worker_thread(); - thread_exit = true; - })); - - // wait for connect thread to exit, also check for keypresses - while (!thread_exit) - { - while (true) - { - const unsigned int c = console.get(); - if (!c) - break; - else if (c == 0x3C) // F2 - the_client->print_stats(); - else if (c == 0x3D) // F3 - the_client->reconnect(0); - else if (c == 0x3E) // F4 - the_client->stop(); - else if (c == 0x3F) // F5 - the_client->pause("user-pause"); - } - Sleep(1000); - } - - // wait for connect thread to exit - thread->join(); - - the_client = nullptr; -} - -#elif defined(OPENVPN_OVPNCLI_SINGLE_THREAD) - -static void handler(int signum) -{ - switch (signum) - { - case SIGTERM: - case SIGINT: - if (the_client) - the_client->set_clock_tick_action(Client::CT_STOP); - break; - case SIGHUP: - if (the_client) - the_client->set_clock_tick_action(Client::CT_RECONNECT); - break; - case SIGUSR1: - if (the_client) - the_client->set_clock_tick_action(Client::CT_STATS); - break; - case SIGUSR2: - { - // toggle pause/resume - static bool hup = false; - if (the_client) - { - if (hup) - the_client->set_clock_tick_action(Client::CT_RESUME); - else - the_client->set_clock_tick_action(Client::CT_PAUSE); - hup = !hup; - } - } - break; - default: - break; - } -} - -static void start_thread(Client& client) -{ - the_client = &client; - - // capture signals that might occur while we're in worker_thread - Signal signal(handler, Signal::F_SIGINT|Signal::F_SIGTERM|Signal::F_SIGHUP|Signal::F_SIGUSR1|Signal::F_SIGUSR2); - - // run the client - worker_thread(); - - the_client = nullptr; -} - -#else - -static void handler(int signum) -{ - switch (signum) - { - case SIGTERM: - case SIGINT: - std::cout << "received stop signal " << signum << std::endl; - if (the_client) - the_client->stop(); - break; - case SIGHUP: - std::cout << "received reconnect signal " << signum << std::endl; - if (the_client) - the_client->reconnect(0); - break; - case SIGUSR1: - if (the_client) - the_client->print_stats(); - break; - case SIGUSR2: - { - // toggle pause/resume - static bool hup = false; - std::cout << "received pause/resume toggle signal " << signum << std::endl; - if (the_client) - { - if (hup) - the_client->resume(); - else - the_client->pause("pause-resume-signal"); - hup = !hup; - } - } - break; - default: - std::cout << "received unknown signal " << signum << std::endl; - break; - } -} - -static void start_thread(Client& client) -{ - std::unique_ptr<std::thread> thread; - - // start connect thread - the_client = &client; - thread.reset(new std::thread([]() { - worker_thread(); - })); - - { - // catch signals that might occur while we're in join() - Signal signal(handler, Signal::F_SIGINT|Signal::F_SIGTERM|Signal::F_SIGHUP|Signal::F_SIGUSR1|Signal::F_SIGUSR2); - - // wait for connect thread to exit - thread->join(); - } - the_client = nullptr; -} - -#endif - -int openvpn_client(int argc, char *argv[], const std::string* profile_content) -{ - static const struct option longopts[] = { - { "username", required_argument, nullptr, 'u' }, - { "password", required_argument, nullptr, 'p' }, - { "response", required_argument, nullptr, 'r' }, - { "dc", required_argument, nullptr, 'D' }, - { "proto", required_argument, nullptr, 'P' }, - { "ipv6", required_argument, nullptr, '6' }, - { "server", required_argument, nullptr, 's' }, - { "port", required_argument, nullptr, 'R' }, - { "timeout", required_argument, nullptr, 't' }, - { "compress", required_argument, nullptr, 'c' }, - { "pk-password", required_argument, nullptr, 'z' }, - { "tvm-override", required_argument, nullptr, 'M' }, - { "proxy-host", required_argument, nullptr, 'h' }, - { "proxy-port", required_argument, nullptr, 'q' }, - { "proxy-username", required_argument, nullptr, 'U' }, - { "proxy-password", required_argument, nullptr, 'W' }, - { "peer-info", required_argument, nullptr, 'I' }, - { "gremlin", required_argument, nullptr, 'G' }, - { "proxy-basic", no_argument, nullptr, 'B' }, - { "alt-proxy", no_argument, nullptr, 'A' }, - { "dco", no_argument, nullptr, 'd' }, - { "eval", no_argument, nullptr, 'e' }, - { "self-test", no_argument, nullptr, 'T' }, - { "cache-password", no_argument, nullptr, 'C' }, - { "no-cert", no_argument, nullptr, 'x' }, - { "force-aes-cbc", no_argument, nullptr, 'f' }, - { "google-dns", no_argument, nullptr, 'g' }, - { "persist-tun", no_argument, nullptr, 'j' }, - { "wintun", no_argument, nullptr, 'w' }, - { "def-keydir", required_argument, nullptr, 'k' }, - { "merge", no_argument, nullptr, 'm' }, - { "version", no_argument, nullptr, 'v' }, - { "auto-sess", no_argument, nullptr, 'a' }, - { "auth-retry", no_argument, nullptr, 'Y' }, - { "tcprof-override", required_argument, nullptr, 'X' }, - { "write-url", required_argument, nullptr, 'Z' }, - { "sso-methods", required_argument, nullptr, 'S' }, - { "ssl-debug", required_argument, nullptr, 1 }, - { "epki-cert", required_argument, nullptr, 2 }, - { "epki-ca", required_argument, nullptr, 3 }, - { "epki-key", required_argument, nullptr, 4 }, -#ifdef OPENVPN_REMOTE_OVERRIDE - { "remote-override",required_argument, nullptr, 5 }, -#endif - { nullptr, 0, nullptr, 0 } - }; - - int ret = 0; - auto cleanup = Cleanup([]() { - the_client = nullptr; - }); - - try { - if (argc >= 2) - { - std::string username; - std::string password; - std::string response; - std::string dynamicChallengeCookie; - std::string proto; - std::string ipv6; - std::string server; - std::string port; - int timeout = 0; - std::string compress; - std::string privateKeyPassword; - std::string tlsVersionMinOverride; - std::string tlsCertProfileOverride; - std::string proxyHost; - std::string proxyPort; - std::string proxyUsername; - std::string proxyPassword; - std::string peer_info; - std::string gremlin; - std::string ssoMethods; - bool eval = false; - bool self_test = false; - bool cachePassword = false; - bool disableClientCert = false; - bool proxyAllowCleartextAuth = false; - int defaultKeyDirection = -1; - bool forceAesCbcCiphersuites = false; - int sslDebugLevel = 0; - bool googleDnsFallback = false; - bool autologinSessions = false; - bool retryOnAuthFailed = false; - bool tunPersist = false; - bool wintun = false; - bool merge = false; - bool version = false; - bool altProxy = false; - bool dco = false; - std::string epki_cert_fn; - std::string epki_ca_fn; - std::string epki_key_fn; -#ifdef OPENVPN_REMOTE_OVERRIDE - std::string remote_override_cmd; -#endif - std::string write_url_fn; - - int ch; - optind = 1; - while ((ch = getopt_long(argc, argv, "BAdeTCxfgjwmvaYu:p:r:D:P:6:s:S:t:c:z:M:h:q:U:W:I:G:k:X:R:Z:", longopts, nullptr)) != -1) - { - switch (ch) - { - case 1: // ssl-debug - sslDebugLevel = ::atoi(optarg); - break; - case 2: // --epki-cert - epki_cert_fn = optarg; - break; - case 3: // --epki-ca - epki_ca_fn = optarg; - break; - case 4: // --epki-key - epki_key_fn = optarg; - break; -#ifdef OPENVPN_REMOTE_OVERRIDE - case 5: // --remote-override - remote_override_cmd = optarg; - break; -#endif - case 'e': - eval = true; - break; - case 'T': - self_test = true; - break; - case 'C': - cachePassword = true; - break; - case 'x': - disableClientCert = true; - break; - case 'u': - username = optarg; - break; - case 'p': - password = optarg; - break; - case 'r': - response = optarg; - break; - case 'P': - proto = optarg; - break; - case '6': - ipv6 = optarg; - break; - case 's': - server = optarg; - break; - case 'R': - port = optarg; - break; - case 'S': - ssoMethods = optarg; - break; - case 't': - timeout = ::atoi(optarg); - break; - case 'c': - compress = optarg; - break; - case 'z': - privateKeyPassword = optarg; - break; - case 'M': - tlsVersionMinOverride = optarg; - break; - case 'X': - tlsCertProfileOverride = optarg; - break; - case 'h': - proxyHost = optarg; - break; - case 'q': - proxyPort = optarg; - break; - case 'U': - proxyUsername = optarg; - break; - case 'W': - proxyPassword = optarg; - break; - case 'B': - proxyAllowCleartextAuth = true; - break; - case 'A': - altProxy = true; - break; - case 'd': - dco = true; - break; - case 'f': - forceAesCbcCiphersuites = true; - break; - case 'g': - googleDnsFallback = true; - break; - case 'a': - autologinSessions = true; - break; - case 'Y': - retryOnAuthFailed = true; - break; - case 'j': - tunPersist = true; - break; - case 'w': - wintun = true; - break; - case 'm': - merge = true; - break; - case 'v': - version = true; - break; - case 'k': - { - const std::string arg = optarg; - if (arg == "bi" || arg == "bidirectional") - defaultKeyDirection = -1; - else if (arg == "0") - defaultKeyDirection = 0; - else if (arg == "1") - defaultKeyDirection = 1; - else - OPENVPN_THROW_EXCEPTION("bad default key-direction: " << arg); - } - break; - case 'D': - dynamicChallengeCookie = optarg; - break; - case 'I': - peer_info = optarg; - break; - case 'G': - gremlin = optarg; - break; - case 'Z': - write_url_fn = optarg; - break; - default: - throw usage(); - } - } - argc -= optind; - argv += optind; - - if (version) - { - std::cout << "OpenVPN cli 1.0" << std::endl; - std::cout << ClientAPI::OpenVPNClient::platform() << std::endl; - std::cout << ClientAPI::OpenVPNClient::copyright() << std::endl; - } - else if (self_test) - { - std::cout << ClientAPI::OpenVPNClient::crypto_self_test(); - } - else if (merge) - { - if (argc != 1) - throw usage(); - std::cout << read_profile(argv[0], profile_content); - } - else - { - if (argc < 1) - throw usage(); - - bool retry; - do { - retry = false; - - ClientAPI::Config config; - config.guiVersion = "cli 1.0"; -#if defined(OPENVPN_PLATFORM_WIN) - int nargs = 0; - auto argvw = CommandLineToArgvW(GetCommandLineW(), &nargs); - UTF8 utf8(Win::utf8(argvw[nargs - 1])); - config.content = read_profile(utf8.get(), profile_content); -#else - config.content = read_profile(argv[0], profile_content); -#endif - for (int i = 1; i < argc; ++i) - { - config.content += argv[i]; - config.content += '\n'; - } - config.serverOverride = server; - config.portOverride = port; - config.protoOverride = proto; - config.connTimeout = timeout; - config.compressionMode = compress; - config.ipv6 = ipv6; - config.privateKeyPassword = privateKeyPassword; - config.tlsVersionMinOverride = tlsVersionMinOverride; - config.tlsCertProfileOverride = tlsCertProfileOverride; - config.disableClientCert = disableClientCert; - config.proxyHost = proxyHost; - config.proxyPort = proxyPort; - config.proxyUsername = proxyUsername; - config.proxyPassword = proxyPassword; - config.proxyAllowCleartextAuth = proxyAllowCleartextAuth; - config.altProxy = altProxy; - config.dco = dco; - config.defaultKeyDirection = defaultKeyDirection; - config.forceAesCbcCiphersuites = forceAesCbcCiphersuites; - config.sslDebugLevel = sslDebugLevel; - config.googleDnsFallback = googleDnsFallback; - config.autologinSessions = autologinSessions; - config.retryOnAuthFailed = retryOnAuthFailed; - config.tunPersist = tunPersist; - config.gremlinConfig = gremlin; - config.info = true; - config.wintun = wintun; - config.ssoMethods =ssoMethods; -#if defined(OPENVPN_OVPNCLI_SINGLE_THREAD) - config.clockTickMS = 250; -#endif - - if (!epki_cert_fn.empty()) - config.externalPkiAlias = "epki"; // dummy string - - PeerInfo::Set::parse_flexible(peer_info, config.peerInfo); - - // allow -s server override to reference a friendly name - // in the config. - // setenv SERVER <HOST>/<FRIENDLY_NAME> - if (!config.serverOverride.empty()) - { - const ClientAPI::EvalConfig eval = ClientAPI::OpenVPNClient::eval_config_static(config); - for (auto &se : eval.serverList) - { - if (config.serverOverride == se.friendlyName) - { - config.serverOverride = se.server; - break; - } - } - } - - if (eval) - { - const ClientAPI::EvalConfig eval = ClientAPI::OpenVPNClient::eval_config_static(config); - std::cout << "EVAL PROFILE" << std::endl; - std::cout << "error=" << eval.error << std::endl; - std::cout << "message=" << eval.message << std::endl; - std::cout << "userlockedUsername=" << eval.userlockedUsername << std::endl; - std::cout << "profileName=" << eval.profileName << std::endl; - std::cout << "friendlyName=" << eval.friendlyName << std::endl; - std::cout << "autologin=" << eval.autologin << std::endl; - std::cout << "externalPki=" << eval.externalPki << std::endl; - std::cout << "staticChallenge=" << eval.staticChallenge << std::endl; - std::cout << "staticChallengeEcho=" << eval.staticChallengeEcho << std::endl; - std::cout << "privateKeyPasswordRequired=" << eval.privateKeyPasswordRequired << std::endl; - std::cout << "allowPasswordSave=" << eval.allowPasswordSave << std::endl; - - if (!config.serverOverride.empty()) - std::cout << "server=" << config.serverOverride << std::endl; - - for (size_t i = 0; i < eval.serverList.size(); ++i) - { - const ClientAPI::ServerEntry& se = eval.serverList[i]; - std::cout << '[' << i << "] " << se.server << '/' << se.friendlyName << std::endl; - } - } - else - { -#if defined(USE_NETCFG) - DBus conn(G_BUS_TYPE_SYSTEM); - conn.Connect(); - NetCfgTunBuilder<Client> client(conn.GetConnection()); -#else - Client client; -#endif - const ClientAPI::EvalConfig eval = client.eval_config(config); - if (eval.error) - OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message); - if (eval.autologin) - { - if (!username.empty() || !password.empty()) - std::cout << "NOTE: creds were not needed" << std::endl; - } - else - { - if (username.empty()) - OPENVPN_THROW_EXCEPTION("need creds"); - ClientAPI::ProvideCreds creds; - if (password.empty() && dynamicChallengeCookie.empty()) - password = get_password("Password:"); - creds.username = username; - creds.password = password; - creds.response = response; - creds.dynamicChallengeCookie = dynamicChallengeCookie; - creds.replacePasswordWithSessionID = true; - creds.cachePassword = cachePassword; - ClientAPI::Status creds_status = client.provide_creds(creds); - if (creds_status.error) - OPENVPN_THROW_EXCEPTION("creds error: " << creds_status.message); - } - - // external PKI - if (!epki_cert_fn.empty()) - { - client.epki_cert = read_text_utf8(epki_cert_fn); - if (!epki_ca_fn.empty()) - client.epki_ca = read_text_utf8(epki_ca_fn); -#if defined(USE_MBEDTLS) - if (!epki_key_fn.empty()) - { - const std::string epki_key_txt = read_text_utf8(epki_key_fn); - client.epki_ctx.parse(epki_key_txt, "EPKI", privateKeyPassword); - } - else - OPENVPN_THROW_EXCEPTION("--epki-key must be specified"); -#endif - } - -#ifdef OPENVPN_REMOTE_OVERRIDE - client.set_remote_override_cmd(remote_override_cmd); -#endif - - client.set_write_url_fn(write_url_fn); - - std::cout << "CONNECTING..." << std::endl; - - // start the client thread - start_thread(client); - - // Get dynamic challenge response - if (client.is_dynamic_challenge()) - { - std::cout << "ENTER RESPONSE" << std::endl; - std::getline(std::cin, response); - if (!response.empty()) - { - dynamicChallengeCookie = client.dynamic_challenge_cookie(); - retry = true; - } - } - else - { - // print closing stats - client.print_stats(); - } - } - } while (retry); - } - } - else - throw usage(); - } - catch (const usage&) - { - std::cout << "OpenVPN Client (ovpncli)" << std::endl; - std::cout << "usage: cli [options] <config-file> [extra-config-directives...]" << std::endl; - std::cout << "--version, -v : show version info" << std::endl; - std::cout << "--eval, -e : evaluate profile only (standalone)" << std::endl; - std::cout << "--merge, -m : merge profile into unified format (standalone)" << std::endl; - std::cout << "--username, -u : username" << std::endl; - std::cout << "--password, -p : password" << std::endl; - std::cout << "--response, -r : static response" << std::endl; - std::cout << "--dc, -D : dynamic challenge/response cookie" << std::endl; - std::cout << "--proto, -P : protocol override (udp|tcp)" << std::endl; - std::cout << "--server, -s : server override" << std::endl; - std::cout << "--port, -R : port override" << std::endl; -#ifdef OPENVPN_REMOTE_OVERRIDE - std::cout << "--remote-override : command to run to generate next remote (returning host,ip,port,proto)" << std::endl; -#endif - std::cout << "--ipv6, -6 : IPv6 (yes|no|default)" << std::endl; - std::cout << "--timeout, -t : timeout" << std::endl; - std::cout << "--compress, -c : compression mode (yes|no|asym)" << std::endl; - std::cout << "--pk-password, -z : private key password" << std::endl; - std::cout << "--tvm-override, -M : tls-version-min override (disabled, default, tls_1_x)" << std::endl; - std::cout << "--tcprof-override, -X : tls-cert-profile override (" << -#ifdef OPENVPN_USE_TLS_MD5 - "insecure, " << -#endif - "legacy, preferred, etc.)" << std::endl; - std::cout << "--proxy-host, -h : HTTP proxy hostname/IP" << std::endl; - std::cout << "--proxy-port, -q : HTTP proxy port" << std::endl; - std::cout << "--proxy-username, -U : HTTP proxy username" << std::endl; - std::cout << "--proxy-password, -W : HTTP proxy password" << std::endl; - std::cout << "--proxy-basic, -B : allow HTTP basic auth" << std::endl; - std::cout << "--alt-proxy, -A : enable alternative proxy module" << std::endl; - std::cout << "--dco, -d : enable data channel offload" << std::endl; - std::cout << "--cache-password, -C : cache password" << std::endl; - std::cout << "--no-cert, -x : disable client certificate" << std::endl; - std::cout << "--def-keydir, -k : default key direction ('bi', '0', or '1')" << std::endl; - std::cout << "--force-aes-cbc, -f : force AES-CBC ciphersuites" << std::endl; - std::cout << "--ssl-debug : SSL debug level" << std::endl; - std::cout << "--google-dns, -g : enable Google DNS fallback" << std::endl; - std::cout << "--auto-sess, -a : request autologin session" << std::endl; - std::cout << "--auth-retry, -Y : retry connection on auth failure" << std::endl; - std::cout << "--persist-tun, -j : keep TUN interface open across reconnects" << std::endl; - std::cout << "--wintun, -w : use WinTun instead of TAP-Windows6 on Windows" << std::endl; - std::cout << "--peer-info, -I : peer info key/value list in the form K1=V1,K2=V2,... or @kv.json" << std::endl; - std::cout << "--gremlin, -G : gremlin info (send_delay_ms, recv_delay_ms, send_drop_prob, recv_drop_prob)" << std::endl; - std::cout << "--epki-ca : simulate external PKI cert supporting intermediate/root certs" << std::endl; - std::cout << "--epki-cert : simulate external PKI cert" << std::endl; - std::cout << "--epki-key : simulate external PKI private key" << std::endl; - std::cout << "--sso-methods : auth pending methods to announce via IV_SSO" << std::endl; - std::cout << "--write-url, -Z : write INFO URL to file" << std::endl; - ret = 2; - } - return ret; -} - -#ifndef OPENVPN_OVPNCLI_OMIT_MAIN - -int main(int argc, char *argv[]) -{ - int ret = 0; - -#ifdef OPENVPN_LOG_LOGBASE_H - LogBaseSimple log; -#endif - -#if defined(OPENVPN_PLATFORM_WIN) - SetConsoleOutputCP(CP_UTF8); -#endif - - try { - ret = openvpn_client(argc, argv, nullptr); - } - catch (const std::exception& e) - { - std::cout << "Main thread exception: " << e.what() << std::endl; - ret = 1; - } - return ret; -} - -#endif diff --git a/Sources/OpenVPN3/test/ovpncli/go b/Sources/OpenVPN3/test/ovpncli/go deleted file mode 100755 index f88aeb8..0000000 --- a/Sources/OpenVPN3/test/ovpncli/go +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# Options: -# OSSL=1 -- build using OpenSSL -# MTLS=1 -- build using mbedTLS -# PTPROXY=1 -- build using Private Tunnel proxy - -# Other options -GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN" -[ "$EER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DTEST_EER" -[ "$NULL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_FORCE_TUN_NULL" -[ "$EXIT" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DTUN_NULL_EXIT" -[ "$GREMLIN" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_GREMLIN" -[ "$DEX" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_DISABLE_EXPLICIT_EXIT" -[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000" -[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE" -[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK" -[ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL" -[ "$MDNC" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DMBEDTLS_DISABLE_NAME_CONSTRAINTS" -if [ "$AGENT" = "1" ]; then - GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT" -fi -GCC_EXTRA="$GCC_EXTRA -DOPENVPN_VERSION=\"$($(dirname $0)/../../scripts/version)\"" -export GCC_EXTRA - -# determine platform -if [ "$(uname)" == "Darwin" ]; then - export PROF=${PROF:-osx64} -elif [ "$(uname)" == "Linux" ]; then - export PROF=${PROF:-linux} -else - echo this script only knows how to build on Mac OS or Linux -fi - -# use mbedTLS by default -[[ -z "$OSSL" && -z "$MTLS" ]] && export MTLS=1 - -# don't link with OpenSSL if mbedTLS is specified -if [ "$MTLS" = "1" ]; then - export OSSL=0 - export NOSSL=1 -fi - -# build -ASIO=1 LZ4=1 ../../scripts/build cli diff --git a/Sources/OpenVPN3/test/ssl/.gitignore b/Sources/OpenVPN3/test/ssl/.gitignore deleted file mode 100644 index 0814d2d..0000000 --- a/Sources/OpenVPN3/test/ssl/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -proto -proto.gcda -proto.dSYM -proto.exe -proto.obj diff --git a/Sources/OpenVPN3/test/ssl/CMakeLists.txt b/Sources/OpenVPN3/test/ssl/CMakeLists.txt deleted file mode 100644 index ff52fd3..0000000 --- a/Sources/OpenVPN3/test/ssl/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -include(findcoredeps) - -add_executable(proto proto.cpp) -add_core_dependencies(proto) - -if (NOT WIN32) - # We have a number of private fields that depend on compile flags for manual testing - target_compile_options(proto PRIVATE -Wno-unused-private-field) -endif () diff --git a/Sources/OpenVPN3/test/ssl/README.txt b/Sources/OpenVPN3/test/ssl/README.txt deleted file mode 100644 index 29c609a..0000000 --- a/Sources/OpenVPN3/test/ssl/README.txt +++ /dev/null @@ -1,80 +0,0 @@ -Building proto.cpp sample: - -On Mac - - Build with MbedTLS client and server (no minicrypto ASM algs for MbedTLS): - - MTLS=1 build proto - - Build with MbedTLS client and server using 4 concurrent threads (no minicrypto ASM algs for MbedTLS): - - -DN_THREADS=4" MTLS=1 build proto - - Build with MbedTLS client and OpenSSL server (no minicrypto ASM algs for MbedTLS): - - MTLS=1 OSSL=1 OPENSSL_SYS=1 build proto - - Build with OpenSSL client and server: - - OSSL=1 OPENSSL_SYS=1 build proto - - Build with AppleSSL client and OpenSSL server: - - SSL_BOTH=1 OPENSSL_SYS=1 build proto - - Build with MbedTLS client and server + minicrypto lib: - - MTLS=1 MINI=1 build proto - - Build with MbedTLS client and server (no minicrypto ASM algs for MbedTLS), - except substitute AppleSSL crypto algs for the client side: - - HYBRID=1 build proto - -On Linux: - - Build with MbedTLS client and server (no ASM crypto algs): - - MTLS=1 NOSSL=1 build proto - - Build with OpenSSL client and server: - - OSSL=1 build proto - - Build with MbedTLS client and OpenSSL server: - - MTLS=1 OSSL=1 build proto - - Build with MbedTLS client and server (no ASM crypto algs) - using Profile-Guided Optimization: - - PGEN=1 MTLS=1 NOSSL=1 build proto && ./proto && PUSE=1 MTLS=1 NOSSL=1 build proto - -Variations: - - To simulate less data-channel activity and more SSL renegotiations - (RENEG default is 900): - - GCC_EXTRA="-DRENEG=90" build proto - - For verbose output, lower the number of xmit/recv iterations by defining - ITER to be 10000 or less, e.g. - - GCC_EXTRA="-DITER=1000" build proto - - Crypto self-test (MbedTLS must be built with DEBUG_BUILD=1 or SELF_TEST=1): - - ./proto test - -Caveats: - - When using MbedTLS as both client and server, make sure to build - MbedTLS on Mac OS X with OSX_SERVER=1. - -Typical output: - - $ time ./proto - *** app bytes=73301015 net_bytes=146383320 data_bytes=36327640 prog=0000218807/0000218806 D=12600/600/12600/800 N=1982/1982 SH=17800/17800 HE=3/6 - real 0m11.003s - user 0m10.981s - sys 0m0.004s diff --git a/Sources/OpenVPN3/test/ssl/ca.crt b/Sources/OpenVPN3/test/ssl/ca.crt deleted file mode 100644 index a11bafa..0000000 --- a/Sources/OpenVPN3/test/ssl/ca.crt +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGKDCCBBCgAwIBAgIJAKFO3vqQ8q6BMA0GCSqGSIb3DQEBCwUAMGYxCzAJBgNV -BAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMM -T3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4w -HhcNMTQxMDIyMjE1OTUyWhcNMjQxMDE5MjE1OTUyWjBmMQswCQYDVQQGEwJLRzEL -MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsJVPCqt3vtoDW2U0DII1QIh2Qs0dqh88 -8nivxAIm2LTq93e9fJhsq3P/UVYAYSeCIrekXypR0EQgSgcNTvGBMe20BoHO5yvb -GjKPmjfLj6XRotCOGy8EDl/hLgRY9efiA8wsVfuvF2q/FblyJQPR/gPiDtTmUiqF -qXa7AJmMrqFsnWppOuGd7Qc6aTsae4TF1e/gUTCTraa7NeHowDaKhdyFmEEnCYR5 -CeUsx2JlFWAH8PCrxBpHYbmGyvS0kH3+rQkaSM/Pzc2bS4ayHaOYRK5XsGq8XiNG -KTTLnSaCdPeHsI+3xMHmEh+u5Og2DFGgvyD22gde6W2ezvEKCUDrzR7bsnYqqyUy -n7LxnkPXGyvR52T06G8KzLKQRmDlPIXhzKMO07qkHmIonXTdF7YI1azwHpAtN4dS -rUe1bvjiTSoEsQPfOAyvD0RMK/CBfgEZUzAB50e/IlbZ84c0DJfUMOm4xCyft1HF -YpYeyCf5dxoIjweCPOoP426+aTXM7kqq0ieIr6YxnKV6OGGLKEY+VNZh1DS7enqV -HP5i8eimyuUYPoQhbK9xtDGMgghnc6Hn8BldPMcvz98HdTEH4rBfA3yNuCxLSNow -4jJuLjNXh2QeiUtWtkXja7ec+P7VqKTduJoRaX7cs+8E3ImigiRnvmK+npk7Nt1y -YE9hBRhSoLsCAwEAAaOB2DCB1TAdBgNVHQ4EFgQUK0DlyX319JY46S/jL9lAZMmO -BZswgZgGA1UdIwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJ -BgNVBAYTAktHMQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UE -ChMMT3BlblZQTi1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21h -aW6CCQChTt76kPKugTAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG -9w0BAQsFAAOCAgEABc77f4C4P8fIS+V8qCJmVNSDU44UZBc+D+J6ZTgW8JeOHUIj -Bh++XDg3gwat7pIWQ8AU5R7h+fpBI9n3dadyIsMHGwSogHY9Gw7di2RVtSFajEth -rvrq0JbzpwoYedMh84sJ2qI/DGKW9/Is9+O52fR+3z3dY3gNRDPQ5675BQ5CQW9I -AJgLOqzD8Q0qrXYi7HaEqzNx6p7RDTuhFgvTd+vS5d5+28Z5fm2umnq+GKHF8W5P -ylp2Js119FTVO7brusAMKPe5emc7tC2ov8OFFemQvfHR41PLryap2VD81IOgmt/J -kX/j/y5KGux5HZ3lxXqdJbKcAq4NKYQT0mCkRD4l6szaCEJ+k0SiM9DdTcBDefhR -9q+pCOyMh7d8QjQ1075mF7T+PGkZQUW1DUjEfrZhICnKgq+iEoUmM0Ee5WtRqcnu -5BTGQ2mSfc6rV+Vr+eYXqcg7Nxb3vFXYSTod1UhefonVqwdmyJ2sC79zp36Tbo2+ -65NW2WJK7KzPUyOJU0U9bcu0utvDOvGWmG+aHbymJgcoFzvZmlXqMXn97pSFn4jV -y3SLRgJXOw1QLXL2Y5abcuoBVr4gCOxxk2vBeVxOMRXNqSWZOFIF1bu/PxuDA+Sa -hEi44aHbPXt9opdssz/hdGfd8Wo7vEJrbg7c6zR6C/Akav1Rzy9oohIdgOw= ------END CERTIFICATE----- diff --git a/Sources/OpenVPN3/test/ssl/client.crt b/Sources/OpenVPN3/test/ssl/client.crt deleted file mode 100644 index 1744cb2..0000000 --- a/Sources/OpenVPN3/test/ssl/client.crt +++ /dev/null @@ -1,103 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 2 (0x2) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - Validity - Not Before: Oct 22 21:59:53 2014 GMT - Not After : Oct 19 21:59:53 2024 GMT - Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Client/emailAddress=me@myhost.mydomain - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:ec:65:8f:e9:12:c2:1a:5b:e6:56:2a:08:a9:82: - 3a:2d:44:78:a3:00:3b:b0:9f:e7:27:10:40:93:ef: - f1:cc:3e:a0:aa:04:a2:80:1b:13:a9:e6:fe:81:d6: - 70:90:a8:d8:d4:de:30:d8:35:00:d2:be:62:f0:48: - da:fc:15:8d:c4:c6:6d:0b:99:f1:2b:83:00:0a:d3: - 2a:23:0b:e5:cd:f9:35:df:43:61:15:72:ad:95:98: - f6:73:21:41:5e:a0:dd:47:27:a0:d5:9a:d4:41:a8: - 1c:1d:57:20:71:17:8f:f7:28:9e:3e:07:ce:ec:d5: - 0e:42:4f:1e:74:47:8e:47:9d:d2:14:28:27:2c:14: - 10:f5:d1:96:b5:93:74:84:ef:f9:04:de:8d:4a:6f: - df:77:ab:ea:d1:58:d3:44:fe:5a:04:01:ff:06:7a: - 97:f7:fd:e3:57:48:e1:f0:df:40:13:9f:66:23:5a: - e3:55:54:3d:54:39:ee:00:f9:12:f1:d2:df:74:2e: - ba:d7:f0:8d:c6:dd:18:58:1c:93:22:0b:75:fa:a8: - d6:e0:b5:2f:2d:b9:d4:fe:b9:4f:86:e2:75:48:16: - 60:fb:3f:c9:b4:30:42:29:fb:3b:b3:2b:b9:59:81: - 6a:46:f3:45:83:bf:fd:d5:1a:ff:37:0c:6f:5b:fd: - 61:f1 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - X509v3 Subject Key Identifier: - D2:B4:36:0F:B1:FC:DD:A5:EA:2A:F7:C7:23:89:FA:E3:FA:7A:44:1D - X509v3 Authority Key Identifier: - keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B - DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - serial:A1:4E:DE:FA:90:F2:AE:81 - - Signature Algorithm: sha256WithRSAEncryption - 7f:e0:fe:84:a7:ec:df:62:a5:cd:3c:c1:e6:42:b1:31:12:f0: - b9:da:a7:9e:3f:bd:96:52:b6:fc:55:74:64:3e:e4:ff:7e:aa: - f7:3e:06:18:5f:73:85:f8:c8:e0:67:1b:4d:97:ca:05:d0:37: - 07:33:64:9b:e6:78:77:14:9a:55:bb:2a:ac:c3:7f:c9:15:08: - 83:5c:c8:c2:61:d3:71:4c:05:0b:2b:cb:a3:87:6d:a0:32:ed: - b0:b3:27:97:4a:55:8d:01:2a:30:56:68:ab:f2:da:5c:10:73: - c9:aa:0a:9c:4b:4c:a0:5b:51:6e:0a:7e:6c:53:80:b0:00:e1: - 1e:9a:4c:0a:37:9e:20:89:bc:c5:e5:79:58:b7:45:ff:d3:c4: - a1:fd:d9:78:3d:45:16:74:df:82:44:1d:1d:81:50:5a:b9:32: - 4c:e2:4f:3f:0e:3a:65:5a:64:83:3b:29:31:c4:99:88:bc:c5: - 84:39:f2:19:12:e1:66:d0:ea:fb:75:b1:d2:27:be:91:59:a3: - 2b:09:d5:5c:bf:46:8e:d6:67:d6:0b:ec:da:ab:f0:80:19:87: - 64:07:a9:77:b1:5e:0c:e2:c5:1d:6a:ac:5d:23:f3:30:75:36: - 4e:ca:c3:4e:b0:4d:8c:2c:ce:52:61:63:de:d5:f5:ef:ef:0a: - 6b:23:25:26:3c:3a:f2:c3:c2:16:19:3f:a9:32:ba:68:f9:c9: - 12:3c:3e:c6:1f:ff:9b:4e:f4:90:b0:63:f5:d1:33:00:30:5a: - e8:24:fa:35:44:9b:6a:80:f3:a6:cc:7b:3c:73:5f:50:c4:30: - 71:d8:74:90:27:0a:01:4e:a5:5e:b1:f8:da:c2:61:81:11:ae: - 29:a3:8f:fa:7e:4c:4e:62:b1:00:de:92:e3:8f:6a:2e:da:d9: - 38:5d:6b:7c:0d:e4:01:aa:c8:c6:6d:8b:cd:c0:c8:6e:e4:57: - 21:8a:f6:46:30:d9:ad:51:a1:87:96:a6:53:c9:1e:c6:bb:c3: - eb:55:fe:8c:d6:5c:d5:c6:f3:ca:b0:60:d2:d4:2a:1f:88:94: - d3:4c:1a:da:0c:94:fe:c1:5d:0d:2a:db:99:29:5d:f6:dd:16: - c4:c8:4d:74:9e:80:d9:d0:aa:ed:7b:e3:30:e4:47:d8:f5:15: - c1:71:b8:c6:fd:ee:fc:9e:b2:5f:b5:b7:92:ed:ff:ca:37:f6: - c7:82:b4:54:13:9b:83:cd:87:8b:7e:64:f6:2e:54:3a:22:b1: - c5:c1:f4:a5:25:53:9a:4d:a8:0f:e7:35:4b:89:df:19:83:66: - 64:d9:db:d1:61:2b:24:1b:1d:44:44:fb:49:30:87:b7:49:23: - 08:02:8a:e0:25:f3:f4:43 ------BEGIN CERTIFICATE----- -MIIFFDCCAvygAwIBAgIBAjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL -MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy -MjIxNTk1M1oXDTI0MTAxOTIxNTk1M1owajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT -Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtQ2xpZW50 -MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQDsZY/pEsIaW+ZWKgipgjotRHijADuwn+cnEECT -7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLwSNr8FY3Exm0LmfErgwAK0yoj -C+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwdVyBxF4/3KJ4+B87s1Q5CTx50 -R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rRWNNE/loEAf8Gepf3/eNXSOHw -30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhYHJMiC3X6qNbgtS8tudT+uU+G -4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83DG9b/WHxAgMBAAGjgcgwgcUw -CQYDVR0TBAIwADAdBgNVHQ4EFgQU0rQ2D7H83aXqKvfHI4n64/p6RB0wgZgGA1Ud -IwSBkDCBjYAUK0DlyX319JY46S/jL9lAZMmOBZuhaqRoMGYxCzAJBgNVBAYTAktH -MQswCQYDVQQIEwJOQTEQMA4GA1UEBxMHQklTSEtFSzEVMBMGA1UEChMMT3BlblZQ -Ti1URVNUMSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW6CCQChTt76 -kPKugTANBgkqhkiG9w0BAQsFAAOCAgEAf+D+hKfs32KlzTzB5kKxMRLwudqnnj+9 -llK2/FV0ZD7k/36q9z4GGF9zhfjI4GcbTZfKBdA3BzNkm+Z4dxSaVbsqrMN/yRUI -g1zIwmHTcUwFCyvLo4dtoDLtsLMnl0pVjQEqMFZoq/LaXBBzyaoKnEtMoFtRbgp+ -bFOAsADhHppMCjeeIIm8xeV5WLdF/9PEof3ZeD1FFnTfgkQdHYFQWrkyTOJPPw46 -ZVpkgzspMcSZiLzFhDnyGRLhZtDq+3Wx0ie+kVmjKwnVXL9GjtZn1gvs2qvwgBmH -ZAepd7FeDOLFHWqsXSPzMHU2TsrDTrBNjCzOUmFj3tX17+8KayMlJjw68sPCFhk/ -qTK6aPnJEjw+xh//m070kLBj9dEzADBa6CT6NUSbaoDzpsx7PHNfUMQwcdh0kCcK -AU6lXrH42sJhgRGuKaOP+n5MTmKxAN6S449qLtrZOF1rfA3kAarIxm2LzcDIbuRX -IYr2RjDZrVGhh5amU8kexrvD61X+jNZc1cbzyrBg0tQqH4iU00wa2gyU/sFdDSrb -mSld9t0WxMhNdJ6A2dCq7XvjMORH2PUVwXG4xv3u/J6yX7W3ku3/yjf2x4K0VBOb -g82Hi35k9i5UOiKxxcH0pSVTmk2oD+c1S4nfGYNmZNnb0WErJBsdRET7STCHt0kj -CAKK4CXz9EM= ------END CERTIFICATE----- diff --git a/Sources/OpenVPN3/test/ssl/client.key b/Sources/OpenVPN3/test/ssl/client.key deleted file mode 100644 index 6d31489..0000000 --- a/Sources/OpenVPN3/test/ssl/client.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDsZY/pEsIaW+ZW -KgipgjotRHijADuwn+cnEECT7/HMPqCqBKKAGxOp5v6B1nCQqNjU3jDYNQDSvmLw -SNr8FY3Exm0LmfErgwAK0yojC+XN+TXfQ2EVcq2VmPZzIUFeoN1HJ6DVmtRBqBwd -VyBxF4/3KJ4+B87s1Q5CTx50R45HndIUKCcsFBD10Za1k3SE7/kE3o1Kb993q+rR -WNNE/loEAf8Gepf3/eNXSOHw30ATn2YjWuNVVD1UOe4A+RLx0t90LrrX8I3G3RhY -HJMiC3X6qNbgtS8tudT+uU+G4nVIFmD7P8m0MEIp+zuzK7lZgWpG80WDv/3VGv83 -DG9b/WHxAgMBAAECggEBAIOdaCpUD02trOh8LqZxowJhBOl7z7/ex0uweMPk67LT -i5AdVHwOlzwZJ8oSIknoOBEMRBWcLQEojt1JMuL2/R95emzjIKshHHzqZKNulFvB -TIUpdnwChTKtH0mqUkLlPU3Ienty4IpNlpmfUKimfbkWHERdBJBHbtDsTABhdo3X -9pCF/yRKqJS2Fy/Mkl3gv1y/NB1OL4Jhl7vQbf+kmgfQN2qdOVe2BOKQ8NlPUDmE -/1XNIDaE3s6uvUaoFfwowzsCCwN2/8QrRMMKkjvV+lEVtNmQdYxj5Xj5IwS0vkK0 -6icsngW87cpZxxc1zsRWcSTloy5ohub4FgKhlolmigECgYEA+cBlxzLvaMzMlBQY -kCac9KQMvVL+DIFHlZA5i5L/9pRVp4JJwj3GUoehFJoFhsxnKr8HZyLwBKlCmUVm -VxnshRWiAU18emUmeAtSGawlAS3QXhikVZDdd/L20YusLT+DXV81wlKR97/r9+17 -klQOLkSdPm9wcMDOWMNHX8bUg8kCgYEA8k+hQv6+TR/+Beao2IIctFtw/EauaJiJ -wW5ql1cpCLPMAOQUvjs0Km3zqctfBF8mUjdkcyJ4uhL9FZtfywY22EtRIXOJ/8VR -we65mVo6RLR8YVM54sihanuFOnlyF9LIBWB+9pUfh1/Y7DSebh7W73uxhAxQhi3Y -QwfIQIFd8OkCgYBalH4VXhLYhpaYCiXSej6ot6rrK2N6c5Tb2MAWMA1nh+r84tMP -gMoh+pDgYPAqMI4mQbxUmqZEeoLuBe6VHpDav7rPECRaW781AJ4ZM4cEQ3Jz/inz -4qOAMn10CF081/Ez9ykPPlU0bsYNWHNd4eB2xWnmUBKOwk7UgJatVPaUiQKBgQCI -f18CVGpzG9CHFnaK8FCnMNOm6VIaTcNcGY0mD81nv5Dt943P054BQMsAHTY7SjZW -HioRyZtkhonXAB2oSqnekh7zzxgv4sG5k3ct8evdBCcE1FNJc2eqikZ0uDETRoOy -s7cRxNNr+QxDkyikM+80HOPU1PMPgwfOSrX90GJQ8QKBgEBKohGMV/sNa4t14Iau -qO8aagoqh/68K9GFXljsl3/iCSa964HIEREtW09Qz1w3dotEgp2w8bsDa+OwWrLy -0SY7T5jRViM3cDWRlUBLrGGiL0FiwsfqiRiji60y19erJgrgyGVIb1kIgIBRkgFM -2MMweASzTmZcri4PA/5C0HYb ------END PRIVATE KEY----- diff --git a/Sources/OpenVPN3/test/ssl/dh.pem b/Sources/OpenVPN3/test/ssl/dh.pem deleted file mode 100644 index 8eda59a..0000000 --- a/Sources/OpenVPN3/test/ssl/dh.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEArdnA32xujHPlPI+jPffHSoMUZ+b5gRz1H1Lw9//Gugm5TAsRiYrB -t2BDSsMKvAjyqN+i5SJv4TOk98kRRKB27iPvyXmiL945VaDQl/UehCySjYlGFUjW -9nuo+JwQxeSbw0TLiSYoYJZQ8X1CxPl9mgJl277O4cW1Gc8I/bWa+ipU/4K5wv3h -GI8nt+6A0jN3M/KebotMP101G4k0l0qsY4oRMTmP+z3oAP0qU9NZ1jiuMFVzRlNp -5FdYF7ctrH+tBF+QmyT4SRKSED4wE4oX6gp420NaBhIEQifIj75wlMDtxQlpkN+x -QkjsEbPlaPKHGQ4uupssChVUi8IM2yq5EwIBAg== ------END DH PARAMETERS----- diff --git a/Sources/OpenVPN3/test/ssl/go b/Sources/OpenVPN3/test/ssl/go deleted file mode 100755 index cbe2260..0000000 --- a/Sources/OpenVPN3/test/ssl/go +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -if [ "$(uname)" == "Darwin" ]; then - cd $O3/core - . vars/vars-osx64 - . vars/setpath - cd test/ssl - ASIO=1 MTLS=1 build proto -else - cd $O3/core - . vars/vars-linux - . vars/setpath - cd test/ssl - if [ "$MO_HYBRID" = "1" ]; then - # mbedTLS client, OpenSSL server - ASIO=1 OPENSSL_SYS=1 MTLS=1 build proto - elif [ "$OSSL" = "1" ]; then - # OpenSSL client/server - ASIO=1 OPENSSL_SYS=1 build proto - else - # mbedTLS client/server - ASIO=1 MTLS=1 NOSSL=1 build proto - fi -fi diff --git a/Sources/OpenVPN3/test/ssl/proto.cpp b/Sources/OpenVPN3/test/ssl/proto.cpp deleted file mode 100644 index 6a9a13d..0000000 --- a/Sources/OpenVPN3/test/ssl/proto.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -// 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-2020 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/>. - -// Unit test for OpenVPN Protocol implementation (class ProtoContext) - -#include <iostream> -#include <string> -#include <sstream> -#include <deque> -#include <algorithm> -#include <cstring> -#include <limits> -#include <thread> - -#include <openvpn/common/platform.hpp> - -#ifdef OPENVPN_PLATFORM_WIN -#include "protowin.h" -#endif - -#define OPENVPN_DEBUG -#define OPENVPN_ENABLE_ASSERT - -#if !defined(USE_TLS_AUTH) && !defined(USE_TLS_CRYPT) -//#define USE_TLS_AUTH -//#define USE_TLS_CRYPT -#define USE_TLS_CRYPT_V2 -#endif - -#define OPENVPN_INSTRUMENTATION - -// Data limits for Blowfish and other 64-bit block-size ciphers -#ifndef BF -#define BF 0 -#endif -#define OPENVPN_BS64_DATA_LIMIT 50000 -#if BF == 1 -#define PROTO_CIPHER "BF-CBC" -#define TLS_VER_MIN TLSVersion::UNDEF -#define HANDSHAKE_WINDOW 60 -#define BECOME_PRIMARY_CLIENT 5 -#define BECOME_PRIMARY_SERVER 5 -#define TLS_TIMEOUT_CLIENT 1000 -#define TLS_TIMEOUT_SERVER 1000 -#define FEEDBACK 0 -#elif BF == 2 -#define PROTO_CIPHER "BF-CBC" -#define TLS_VER_MIN TLSVersion::UNDEF -#define HANDSHAKE_WINDOW 10 -#define BECOME_PRIMARY_CLIENT 10 -#define BECOME_PRIMARY_SERVER 10 -#define TLS_TIMEOUT_CLIENT 2000 -#define TLS_TIMEOUT_SERVER 1000 -#define FEEDBACK 0 -#elif BF == 3 -#define PROTO_CIPHER "BF-CBC" -#define TLS_VER_MIN TLSVersion::UNDEF -#define HANDSHAKE_WINDOW 60 -#define BECOME_PRIMARY_CLIENT 60 -#define BECOME_PRIMARY_SERVER 10 -#define TLS_TIMEOUT_CLIENT 2000 -#define TLS_TIMEOUT_SERVER 1000 -#define FEEDBACK 0 -#elif BF != 0 -#error unknown BF value -#endif - -// TLS timeout -#ifndef TLS_TIMEOUT_CLIENT -#define TLS_TIMEOUT_CLIENT 2000 -#endif -#ifndef TLS_TIMEOUT_SERVER -#define TLS_TIMEOUT_SERVER 2000 -#endif - -// NoisyWire -#ifndef NOERR -#define SIMULATE_OOO -#define SIMULATE_DROPPED -#define SIMULATE_CORRUPTED -#endif - -// how many virtual seconds between SSL renegotiations -#ifndef RENEG -#define RENEG 900 -#endif - -// feedback -#ifndef FEEDBACK -#define FEEDBACK 1 -#else -#define FEEDBACK 0 -#endif - -// number of threads to use for test -#ifndef N_THREADS -#define N_THREADS 1 -#endif - -// number of iterations -#ifndef ITER -#define ITER 1000000 -#endif - -// number of high-level session iterations -#ifndef SITER -#define SITER 1 -#endif - -// abort if we reach this limit -//#define DROUGHT_LIMIT 100000 - -#if !defined(VERBOSE) && !defined(QUIET) && ITER <= 10000 -#define VERBOSE -#endif - -#ifdef VERBOSE -#define OPENVPN_DEBUG_PROTO 2 -#define OPENVPN_LOG_SSL(x) OPENVPN_LOG(x) -#else -#define OPENVPN_LOG_SSL(x) // disable -#endif - -#define STRINGIZE1(x) #x -#define STRINGIZE(x) STRINGIZE1(x) - -// setup cipher -#ifndef PROTO_CIPHER -#ifdef PROTOv2 -#define PROTO_CIPHER "AES-256-GCM" -#define TLS_VER_MIN TLSVersion::V1_2 -#else -#define PROTO_CIPHER "AES-128-CBC" -#define TLS_VER_MIN TLSVersion::UNDEF -#endif -#endif - -// setup digest -#ifndef PROTO_DIGEST -#define PROTO_DIGEST "SHA1" -#endif - -// setup compressor -#ifdef PROTOv2 -#ifdef HAVE_LZ4 -#define COMP_METH CompressContext::LZ4v2 -#else -#define COMP_METH CompressContext::COMP_STUBv2 -#endif -#else -#define COMP_METH CompressContext::LZO_STUB -#endif - -#include <openvpn/log/logsimple.hpp> - -#include <openvpn/common/exception.hpp> -#include <openvpn/common/file.hpp> -#include <openvpn/common/count.hpp> -#include <openvpn/time/time.hpp> -#include <openvpn/random/mtrandapi.hpp> -#include <openvpn/frame/frame.hpp> -#include <openvpn/ssl/proto.hpp> -#include <openvpn/init/initprocess.hpp> - -#include <openvpn/crypto/cryptodcsel.hpp> - -#if defined(USE_MBEDTLS_APPLE_HYBRID) -#define USE_MBEDTLS -#endif - -#if !(defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_APPLE_SSL)) -#error Must define one or more of USE_OPENSSL, USE_MBEDTLS, USE_APPLE_SSL. -#endif - -#if defined(USE_OPENSSL) && (defined(USE_MBEDTLS) || defined(USE_APPLE_SSL)) -#undef USE_OPENSSL -#define USE_OPENSSL_SERVER -#elif !defined(USE_OPENSSL) && defined(USE_MBEDTLS) -#define USE_MBEDTLS_SERVER -#elif defined(USE_OPENSSL) && !defined(USE_MBEDTLS) -#define USE_OPENSSL_SERVER -#else -#error no server setup -#endif - -#if defined(USE_OPENSSL) || defined(USE_OPENSSL_SERVER) -#include <openvpn/openssl/util/init.hpp> - -#include <openvpn/openssl/crypto/api.hpp> -#include <openvpn/openssl/ssl/sslctx.hpp> -#include <openvpn/openssl/util/rand.hpp> - -#endif - -#if defined(USE_APPLE_SSL) || defined(USE_MBEDTLS_APPLE_HYBRID) -#include <openvpn/applecrypto/crypto/api.hpp> -#include <openvpn/applecrypto/ssl/sslctx.hpp> -#include <openvpn/applecrypto/util/rand.hpp> -#endif - -#if defined(USE_MBEDTLS) || defined(USE_MBEDTLS_SERVER) -#include <openvpn/mbedtls/crypto/api.hpp> -#include <openvpn/mbedtls/ssl/sslctx.hpp> -#include <openvpn/mbedtls/util/rand.hpp> -#include <mbedtls/debug.h> -#endif - -#include <openvpn/crypto/selftest.hpp> - -using namespace openvpn; - -// server Crypto/SSL/Rand implementation -#if defined(USE_MBEDTLS_SERVER) -typedef MbedTLSCryptoAPI ServerCryptoAPI; -typedef MbedTLSContext ServerSSLAPI; -typedef MbedTLSRandom ServerRandomAPI; -#elif defined(USE_OPENSSL_SERVER) -typedef OpenSSLCryptoAPI ServerCryptoAPI; -typedef OpenSSLContext ServerSSLAPI; -typedef OpenSSLRandom ServerRandomAPI; -#else -#error No server SSL implementation defined -#endif - -// client SSL implementation can be OpenSSL, Apple SSL, or MbedTLS -#if defined(USE_MBEDTLS) -#if defined(USE_MBEDTLS_APPLE_HYBRID) -typedef AppleCryptoAPI ClientCryptoAPI; -#else -typedef MbedTLSCryptoAPI ClientCryptoAPI; -#endif -typedef MbedTLSContext ClientSSLAPI; -typedef MbedTLSRandom ClientRandomAPI; -#elif defined(USE_APPLE_SSL) -typedef AppleCryptoAPI ClientCryptoAPI; -typedef AppleSSLContext ClientSSLAPI; -typedef AppleRandom ClientRandomAPI; -#elif defined(USE_OPENSSL) -typedef OpenSSLCryptoAPI ClientCryptoAPI; -typedef OpenSSLContext ClientSSLAPI; -typedef OpenSSLRandom ClientRandomAPI; -#else -#error No client SSL implementation defined -#endif - -const char message[] = - "Message _->_ 0000000000 It was a bright cold day in April, and the clocks\n" - "were striking thirteen. Winston Smith, his chin nuzzled\n" - "into his breast in an effort to escape the vile wind,\n" - "slipped quickly through the glass doors of Victory\n" - "Mansions, though not quickly enough to prevent a\n" - "swirl of gritty dust from entering along with him.\n" -#ifdef LARGE_MESSAGE - "It was a bright cold day in April, and the clocks\n" - "were striking thirteen. Winston Smith, his chin nuzzled\n" - "into his breast in an effort to escape the vile wind,\n" - "slipped quickly through the glass doors of Victory\n" - "Mansions, though not quickly enough to prevent a\n" - "swirl of gritty dust from entering along with him.\n" - "It was a bright cold day in April, and the clocks\n" - "were striking thirteen. Winston Smith, his chin nuzzled\n" - "into his breast in an effort to escape the vile wind,\n" - "slipped quickly through the glass doors of Victory\n" - "Mansions, though not quickly enough to prevent a\n" - "swirl of gritty dust from entering along with him.\n" - "It was a bright cold day in April, and the clocks\n" - "were striking thirteen. Winston Smith, his chin nuzzled\n" - "into his breast in an effort to escape the vile wind,\n" - "slipped quickly through the glass doors of Victory\n" - "Mansions, though not quickly enough to prevent a\n" - "swirl of gritty dust from entering along with him.\n" - "It was a bright cold day in April, and the clocks\n" - "were striking thirteen. Winston Smith, his chin nuzzled\n" - "into his breast in an effort to escape the vile wind,\n" - "slipped quickly through the glass doors of Victory\n" - "Mansions, though not quickly enough to prevent a\n" - "swirl of gritty dust from entering along with him.\n" -#endif - ; - -// A "Drought" measures the maximum period of time between -// any two successive events. Used to measure worst-case -// packet loss. -class DroughtMeasure -{ -public: - OPENVPN_SIMPLE_EXCEPTION(drought_limit_exceeded); - - DroughtMeasure(const std::string& name_arg, TimePtr now_arg) - : now(now_arg), name(name_arg) - { - } - - void event() - { - if (last_event.defined()) - { - Time::Duration since_last = *now - last_event; - if (since_last > drought) - { - drought = since_last; -#if defined(VERBOSE) || defined(DROUGHT_LIMIT) - { - const unsigned int r = drought.raw(); -#if defined(VERBOSE) - std::cout << "*** Drought " << name << " has reached " << r << std::endl; -#endif -#ifdef DROUGHT_LIMIT - if (r > DROUGHT_LIMIT) - throw drought_limit_exceeded(); -#endif - } -#endif - } - } - last_event = *now; - } - - Time::Duration operator()() const { return drought; } - -private: - TimePtr now; - Time last_event; - Time::Duration drought; - std::string name; -}; - -// test the OpenVPN protocol implementation in ProtoContext -class TestProto : public ProtoContext -{ - typedef ProtoContext Base; - - using Base::now; - using Base::mode; - using Base::is_server; - -public: - using Base::flush; - - typedef Base::PacketType PacketType; - - OPENVPN_EXCEPTION(session_invalidated); - - TestProto(const Base::Config::Ptr& config, - const SessionStats::Ptr& stats) - : Base(config, stats), - control_drought("control", config->now), - data_drought("data", config->now), - frame(config->frame) - { - // zero progress value - std::memset(progress_, 0, 11); - } - - void reset() - { - net_out.clear(); - Base::reset(); - } - - void initial_app_send(const char *msg) - { - Base::start(); - const size_t msglen = std::strlen(msg) + 1; - BufferAllocated app_buf((unsigned char *)msg, msglen, 0); - copy_progress(app_buf); - control_send(std::move(app_buf)); - flush(true); - } - - void app_send_templ_init(const char *msg) - { - Base::start(); - const size_t msglen = std::strlen(msg) + 1; - templ.reset(new BufferAllocated((unsigned char *)msg, msglen, 0)); - flush(true); - } - - void app_send_templ() - { -#if !FEEDBACK - if (bool(iteration++ & 1) == is_server()) - { - modmsg(templ); - BufferAllocated app_buf(*templ); - control_send(std::move(app_buf)); - flush(true); - ++n_control_send_; - } -#endif - } - - bool do_housekeeping() - { - if (now() >= Base::next_housekeeping()) - { - Base::housekeeping(); - return true; - } - else - return false; - } - - void control_send(BufferPtr&& app_bp) - { - app_bytes_ += app_bp->size(); - Base::control_send(std::move(app_bp)); - } - - void control_send(BufferAllocated&& app_buf) - { - app_bytes_ += app_buf.size(); - Base::control_send(std::move(app_buf)); - } - - BufferPtr data_encrypt_string(const char *str) - { - BufferPtr bp = new BufferAllocated(); - frame->prepare(Frame::READ_LINK_UDP, *bp); - bp->write((unsigned char *)str, std::strlen(str)); - data_encrypt(*bp); - return bp; - } - - void data_encrypt(BufferAllocated& in_out) - { - Base::data_encrypt(in_out); - } - - void data_decrypt(const PacketType& type, BufferAllocated& in_out) - { - Base::data_decrypt(type, in_out); - if (in_out.size()) - { - data_bytes_ += in_out.size(); - data_drought.event(); - } - } - - size_t net_bytes() const { return net_bytes_; } - size_t app_bytes() const { return app_bytes_; } - size_t data_bytes() const { return data_bytes_; } - size_t n_control_recv() const { return n_control_recv_; } - size_t n_control_send() const { return n_control_send_; } - - const char *progress() const { return progress_; } - - void finalize() - { - data_drought.event(); - control_drought.event(); - } - - void check_invalidated() - { - if (Base::invalidated()) - throw session_invalidated(Error::name(Base::invalidation_reason())); - } - - std::deque<BufferPtr> net_out; - - DroughtMeasure control_drought; - DroughtMeasure data_drought; - -private: - virtual void control_net_send(const Buffer& net_buf) - { - net_bytes_ += net_buf.size(); - net_out.push_back(BufferPtr(new BufferAllocated(net_buf, 0))); - } - - virtual void control_recv(BufferPtr&& app_bp) - { - BufferPtr work; - work.swap(app_bp); - if (work->size() >= 23) - std::memcpy(progress_, work->data()+13, 10); - -#ifdef VERBOSE - { - const ssize_t trunc = 64; - const std::string show((char *)work->data(), trunc); - std::cout << now().raw() << " " << mode().str() << " " << show << std::endl; - } -#endif -#if FEEDBACK - modmsg(work); - control_send(std::move(work)); -#endif - control_drought.event(); - ++n_control_recv_; - } - - void copy_progress(Buffer& buf) - { - if (progress_[0]) // make sure progress was initialized - std::memcpy(buf.data()+13, progress_, 10); - } - - void modmsg(BufferPtr& buf) - { - char *msg = (char *) buf->data(); - if (is_server()) - { - msg[8] = 'S'; - msg[11] = 'C'; - } - else - { - msg[8] = 'C'; - msg[11] = 'S'; - } - - // increment embedded number - for (int i = 22; i >= 13; i--) - { - if (msg[i] != '9') - { - msg[i]++; - break; - } - else - msg[i] = '0'; - } - } - - Frame::Ptr frame; - size_t app_bytes_ = 0; - size_t net_bytes_ = 0; - size_t data_bytes_ = 0; - size_t n_control_send_ = 0; - size_t n_control_recv_ = 0; - BufferPtr templ; - size_t iteration = 0; - char progress_[11]; -}; - -class TestProtoClient : public TestProto -{ - typedef TestProto Base; -public: - TestProtoClient(const Base::Config::Ptr& config, - const SessionStats::Ptr& stats) - : Base(config, stats) - { - } - -private: - virtual void client_auth(Buffer& buf) - { - const std::string username("foo"); - const std::string password("bar"); - Base::write_auth_string(username, buf); - Base::write_auth_string(password, buf); - } -}; - -class TestProtoServer : public TestProto -{ - typedef TestProto Base; -public: - OPENVPN_SIMPLE_EXCEPTION(auth_failed); - - TestProtoServer(const Base::Config::Ptr& config, - const SessionStats::Ptr& stats) - : Base(config, stats) - { - } - -private: - virtual void server_auth(const std::string& username, - const SafeString& password, - const std::string& peer_info, - const AuthCert::Ptr& auth_cert) - { -#ifdef VERBOSE - std::cout << "**** AUTHENTICATE " << username << '/' << password << " PEER INFO:" << std::endl; - std::cout << peer_info; -#endif - if (username != "foo" || password != "bar") - throw auth_failed(); - } -}; - -// Simulate a noisy transmission channel where packets can be dropped, -// reordered, or corrupted. -class NoisyWire -{ -public: - NoisyWire(const std::string title_arg, - TimePtr now_arg, - RandomAPI& rand_arg, - const unsigned int reorder_prob_arg, - const unsigned int drop_prob_arg, - const unsigned int corrupt_prob_arg) - : title(title_arg), - now(now_arg), - random(rand_arg), - reorder_prob(reorder_prob_arg), - drop_prob(drop_prob_arg), - corrupt_prob(corrupt_prob_arg) - { - } - - template <typename T1, typename T2> - void xfer(T1& a, T2& b) - { - // check for errors - a.check_invalidated(); - b.check_invalidated(); - - // need to retransmit? - if (a.do_housekeeping()) - { -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Housekeeping" << std::endl; -#endif - } - - // queue a control channel packet - a.app_send_templ(); - - // queue a data channel packet - if (a.data_channel_ready()) - { - BufferPtr bp = a.data_encrypt_string("Waiting for godot A... Waiting for godot B... Waiting for godot C... Waiting for godot D... Waiting for godot E... Waiting for godot F... Waiting for godot G... Waiting for godot H... Waiting for godot I... Waiting for godot J..."); - wire.push_back(bp); - } - - // transfer network packets from A -> wire - while (!a.net_out.empty()) - { - BufferPtr bp = a.net_out.front(); -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " " << a.dump_packet(*bp) << std::endl; -#endif - a.net_out.pop_front(); - wire.push_back(bp); - } - - // transfer network packets from wire -> B - while (true) - { - BufferPtr bp = recv(); - if (!bp) - break; - typename T2::PacketType pt = b.packet_type(*bp); - if (pt.is_control()) - { -#ifdef VERBOSE - if (!b.control_net_validate(pt, *bp)) // not strictly necessary since control_net_recv will also validate - std::cout << now->raw() << " " << title << " CONTROL PACKET VALIDATION FAILED" << std::endl; -#endif - b.control_net_recv(pt, std::move(bp)); - } - else if (pt.is_data()) - { - try { - b.data_decrypt(pt, *bp); -#ifdef VERBOSE - if (bp->size()) - { - const std::string show((char *)bp->data(), std::min(bp->size(), size_t(40))); - std::cout << now->raw() << " " << title << " DATA CHANNEL DECRYPT: " << show << std::endl; - } -#endif - } - catch (const std::exception& e) - { -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Exception on data channel decrypt: " << e.what() << std::endl; -#endif - } - } - else - { -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " KEY_STATE_ERROR" << std::endl; -#endif - b.stat().error(Error::KEY_STATE_ERROR); - } - } - b.flush(true); - } - -private: - BufferPtr recv() - { -#ifdef SIMULATE_OOO - // simulate packets being received out of order - if (wire.size() >= 2 && !rand(reorder_prob)) - { - const size_t i = random.randrange(wire.size() - 1) + 1; -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating packet reordering " << i << " -> 0" << std::endl; -#endif - std::swap(wire[0], wire[i]); - } -#endif - - if (wire.size()) - { - BufferPtr bp = wire.front(); - wire.pop_front(); - -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Received packet, size=" << bp->size() << std::endl; -#endif - -#ifdef SIMULATE_DROPPED - // simulate dropped packet - if (!rand(drop_prob)) - { -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating a dropped packet" << std::endl; -#endif - return BufferPtr(); - } -#endif - -#ifdef SIMULATE_CORRUPTED - // simulate corrupted packet - if (bp->size() && !rand(corrupt_prob)) - { -#ifdef VERBOSE - std::cout << now->raw() << " " << title << " Simulating a corrupted packet" << std::endl; -#endif - const size_t pos = random.randrange(bp->size()); - const unsigned char value = random.randrange(256); - (*bp)[pos] = value; - } -#endif - return bp; - } - - return BufferPtr(); - } - - unsigned int rand(const unsigned int prob) - { - if (prob) - return random.randrange(prob); - else - return 1; - } - - std::string title; - TimePtr now; - RandomAPI& random; - unsigned int reorder_prob; - unsigned int drop_prob; - unsigned int corrupt_prob; - std::deque<BufferPtr> wire; -}; - -class MySessionStats : public SessionStats -{ -public: - typedef RCPtr<MySessionStats> Ptr; - - MySessionStats() - { - std::memset(errors, 0, sizeof(errors)); - } - - virtual void error(const size_t err_type, const std::string* text=nullptr) - { - if (err_type < Error::N_ERRORS) - ++errors[err_type]; - } - - count_t get_error_count(const Error::Type type) const - { - if (type < Error::N_ERRORS) - return errors[type]; - else - return 0; - } - - void show_error_counts() const - { - for (size_t i = 0; i < Error::N_ERRORS; ++i) - { - count_t c = errors[i]; - if (c) - std::cerr << Error::name(i) << " : " << c << std::endl; - } - } - -private: - count_t errors[Error::N_ERRORS]; -}; - -// execute the unit test in one thread -int test(const int thread_num) -{ - try { - // frame - Frame::Ptr frame(new Frame(Frame::Context(128, 378, 128, 0, 16, 0))); - - // RNG - ClientRandomAPI::Ptr rng_cli(new ClientRandomAPI(false)); - ClientRandomAPI::Ptr prng_cli(new ClientRandomAPI(true)); - ServerRandomAPI::Ptr rng_serv(new ServerRandomAPI(false)); - ServerRandomAPI::Ptr prng_serv(new ServerRandomAPI(true)); - MTRand rng_noncrypto; - - // init simulated time - Time time; - const Time::Duration time_step = Time::Duration::binary_ms(100); - - // client config files - const std::string ca_crt = read_text("ca.crt"); - const std::string client_crt = read_text("client.crt"); - const std::string client_key = read_text("client.key"); - const std::string server_crt = read_text("server.crt"); - const std::string server_key = read_text("server.key"); - const std::string dh_pem = read_text("dh.pem"); - const std::string tls_auth_key = read_text("tls-auth.key"); - const std::string tls_crypt_v2_server_key = read_text("tls-crypt-v2-server.key"); - const std::string tls_crypt_v2_client_key = read_text("tls-crypt-v2-client.key"); - - // client config - ClientSSLAPI::Config::Ptr cc(new ClientSSLAPI::Config()); - cc->set_mode(Mode(Mode::CLIENT)); - cc->set_frame(frame); -#ifdef USE_APPLE_SSL - cc->load_identity("etest"); -#else - cc->load_ca(ca_crt, true); - cc->load_cert(client_crt); - cc->load_private_key(client_key); -#endif - cc->set_tls_version_min(TLS_VER_MIN); -#ifdef VERBOSE - cc->set_debug_level(1); -#endif - cc->set_rng(rng_cli); - - // stats - MySessionStats::Ptr cli_stats(new MySessionStats); - MySessionStats::Ptr serv_stats(new MySessionStats); - - // client ProtoContext config - typedef ProtoContext ClientProtoContext; - ClientProtoContext::Config::Ptr cp(new ClientProtoContext::Config); - cp->ssl_factory = cc->new_factory(); - cp->dc.set_factory(new CryptoDCSelect<ClientCryptoAPI>(frame, cli_stats, prng_cli)); - cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<ClientCryptoAPI>()); - cp->frame = frame; - cp->now = &time; - cp->rng = rng_cli; - cp->prng = prng_cli; - cp->protocol = Protocol(Protocol::UDPv4); - cp->layer = Layer(Layer::OSI_LAYER_3); -#ifdef PROTOv2 - cp->enable_op32 = true; - cp->remote_peer_id = 100; -#endif - cp->comp_ctx = CompressContext(COMP_METH, false); - cp->dc.set_cipher(CryptoAlgs::lookup(PROTO_CIPHER)); - cp->dc.set_digest(CryptoAlgs::lookup(PROTO_DIGEST)); -#ifdef USE_TLS_AUTH - cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<ClientCryptoAPI>()); - cp->tls_key.parse(tls_auth_key); - cp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST)); - cp->key_direction = 0; -#endif -#ifdef USE_TLS_CRYPT - cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - cp->tls_key.parse(tls_auth_key); - cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); -#endif -#ifdef USE_TLS_CRYPT_V2 - cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); - { - TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context); - tls_crypt_v2_key.parse(tls_crypt_v2_client_key); - tls_crypt_v2_key.extract_key(cp->tls_key); - tls_crypt_v2_key.extract_wkc(cp->wkc); - } - cp->tls_crypt_v2 = true; -#endif - cp->reliable_window = 4; - cp->max_ack_list = 4; - cp->pid_mode = PacketIDReceive::UDP_MODE; -#if defined(HANDSHAKE_WINDOW) - cp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW); -#elif SITER > 1 - cp->handshake_window = Time::Duration::seconds(30); -#else - cp->handshake_window = Time::Duration::seconds(18); // will cause a small number of handshake failures -#endif -#ifdef BECOME_PRIMARY_CLIENT - cp->become_primary = Time::Duration::seconds(BECOME_PRIMARY_CLIENT); -#else - cp->become_primary = cp->handshake_window; -#endif - cp->tls_timeout = Time::Duration::milliseconds(TLS_TIMEOUT_CLIENT); -#if defined(CLIENT_NO_RENEG) - cp->renegotiate = Time::Duration::infinite(); -#else - cp->renegotiate = Time::Duration::seconds(RENEG); -#endif - cp->expire = cp->renegotiate + cp->renegotiate; - cp->keepalive_ping = Time::Duration::seconds(5); - cp->keepalive_timeout = Time::Duration::seconds(60); - -#ifdef VERBOSE - std::cout << "CLIENT OPTIONS: " << cp->options_string() << std::endl; - std::cout << "CLIENT PEER INFO:" << std::endl; - std::cout << cp->peer_info_string(); -#endif - - // server config - ClientSSLAPI::Config::Ptr sc(new ClientSSLAPI::Config()); - sc->set_mode(Mode(Mode::SERVER)); - sc->set_frame(frame); - sc->load_ca(ca_crt, true); - sc->load_cert(server_crt); - sc->load_private_key(server_key); - sc->load_dh(dh_pem); - sc->set_tls_version_min(TLS_VER_MIN); - sc->set_rng(rng_serv); -#ifdef VERBOSE - sc->set_debug_level(1); -#endif - - // server ProtoContext config - typedef ProtoContext ServerProtoContext; - ServerProtoContext::Config::Ptr sp(new ServerProtoContext::Config); - sp->ssl_factory = sc->new_factory(); - sp->dc.set_factory(new CryptoDCSelect<ServerCryptoAPI>(frame, serv_stats, prng_serv)); - sp->tlsprf_factory.reset(new CryptoTLSPRFFactory<ServerCryptoAPI>()); - sp->frame = frame; - sp->now = &time; - sp->rng = rng_serv; - sp->prng = prng_serv; - sp->protocol = Protocol(Protocol::UDPv4); - sp->layer = Layer(Layer::OSI_LAYER_3); -#ifdef PROTOv2 - sp->enable_op32 = true; - sp->remote_peer_id = 101; -#endif - sp->comp_ctx = CompressContext(COMP_METH, false); - sp->dc.set_cipher(CryptoAlgs::lookup(PROTO_CIPHER)); - sp->dc.set_digest(CryptoAlgs::lookup(PROTO_DIGEST)); -#ifdef USE_TLS_AUTH - sp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<ServerCryptoAPI>()); - sp->tls_key.parse(tls_auth_key); - sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST)); - sp->key_direction = 1; -#endif -#if defined(USE_TLS_CRYPT) - sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - sp->tls_key.parse(tls_auth_key); - sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); -#endif -#ifdef USE_TLS_CRYPT_V2 - sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>()); - { - TLSCryptV2ServerKey tls_crypt_v2_key; - tls_crypt_v2_key.parse(tls_crypt_v2_server_key); - tls_crypt_v2_key.extract_key(sp->tls_key); - } - sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR")); - sp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory()); - sp->tls_crypt_v2 = true; -#endif - sp->reliable_window = 4; - sp->max_ack_list = 4; - sp->pid_mode = PacketIDReceive::UDP_MODE; -#if defined(HANDSHAKE_WINDOW) - sp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW); -#elif SITER > 1 - sp->handshake_window = Time::Duration::seconds(30); -#else - sp->handshake_window = Time::Duration::seconds(17) + Time::Duration::binary_ms(512); -#endif -#ifdef BECOME_PRIMARY_SERVER - sp->become_primary = Time::Duration::seconds(BECOME_PRIMARY_SERVER); -#else - sp->become_primary = sp->handshake_window; -#endif - sp->tls_timeout = Time::Duration::milliseconds(TLS_TIMEOUT_SERVER); -#if defined(SERVER_NO_RENEG) - sp->renegotiate = Time::Duration::infinite(); -#else - // NOTE: if we don't add sp->handshake_window, both client and server reneg-sec (RENEG) - // will be equal and will therefore occasionally collide. Such collisions can sometimes - // produce this OpenSSL error: - // OpenSSLContext::SSL::read_cleartext: BIO_read failed, cap=400 status=-1: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init - // The issue was introduced by this patch in OpenSSL: - // https://github.com/openssl/openssl/commit/64193c8218540499984cd63cda41f3cd491f3f59 - sp->renegotiate = Time::Duration::seconds(RENEG) + sp->handshake_window; -#endif - sp->expire = sp->renegotiate + sp->renegotiate; - sp->keepalive_ping = Time::Duration::seconds(5); - sp->keepalive_timeout = Time::Duration::seconds(60); - -#ifdef VERBOSE - std::cout << "SERVER OPTIONS: " << sp->options_string() << std::endl; - std::cout << "SERVER PEER INFO:" << std::endl; - std::cout << sp->peer_info_string(); -#endif - - TestProtoClient cli_proto(cp, cli_stats); - TestProtoServer serv_proto(sp, serv_stats); - - for (int i = 0; i < SITER; ++i) - { -#ifdef VERBOSE - std::cout << "***** SITER " << i << std::endl; -#endif - cli_proto.reset(); - serv_proto.reset(); - - NoisyWire client_to_server("Client -> Server", &time, rng_noncrypto, 8, 16, 32); // last value: 32 - NoisyWire server_to_client("Server -> Client", &time, rng_noncrypto, 8, 16, 32); // last value: 32 - - int j = -1; - try { -#if FEEDBACK - // start feedback loop - cli_proto.initial_app_send(message); - serv_proto.start(); -#else - cli_proto.app_send_templ_init(message); - serv_proto.app_send_templ_init(message); -#endif - - // message loop - for (j = 0; j < ITER; ++j) - { - client_to_server.xfer(cli_proto, serv_proto); - server_to_client.xfer(serv_proto, cli_proto); - time += time_step; - } - } - catch (const std::exception& e) - { - std::cerr << "Exception[" << i << '/' << j << "]: " << e.what() << std::endl; - return 1; - } - } - - cli_proto.finalize(); - serv_proto.finalize(); - - const size_t ab = cli_proto.app_bytes() + serv_proto.app_bytes(); - const size_t nb = cli_proto.net_bytes() + serv_proto.net_bytes(); - const size_t db = cli_proto.data_bytes() + serv_proto.data_bytes(); - - std::cerr << "*** app bytes=" << ab - << " net_bytes=" << nb - << " data_bytes=" << db - << " prog=" << cli_proto.progress() << '/' << serv_proto.progress() -#if !FEEDBACK - << " CTRL=" << cli_proto.n_control_recv() << '/' << cli_proto.n_control_send() << '/' << serv_proto.n_control_recv() << '/' << serv_proto.n_control_send() -#endif - << " D=" << cli_proto.control_drought().raw() << '/' << cli_proto.data_drought().raw() << '/' << serv_proto.control_drought().raw() << '/' << serv_proto.data_drought().raw() - << " N=" << cli_proto.negotiations() << '/' << serv_proto.negotiations() - << " SH=" << cli_proto.slowest_handshake().raw() << '/' << serv_proto.slowest_handshake().raw() - << " HE=" << cli_stats->get_error_count(Error::HANDSHAKE_TIMEOUT) << '/' << serv_stats->get_error_count(Error::HANDSHAKE_TIMEOUT) - << std::endl; - -#ifdef STATS - std::cerr << "-------- CLIENT STATS --------" << std::endl; - cli_stats->show_error_counts(); - std::cerr << "-------- SERVER STATS --------" << std::endl; - serv_stats->show_error_counts(); -#endif -#ifdef OPENVPN_MAX_DATALIMIT_BYTES - std::cerr << "------------------------------" << std::endl; - std::cerr << "MAX_DATALIMIT_BYTES=" << DataLimit::max_bytes() << std::endl; -#endif - } - catch (const std::exception& e) - { - std::cerr << "Exception: " << e.what() << std::endl; - return 1; - } - return 0; -} - -int main(int argc, char* argv[]) -{ - int ret = 0; - // process-wide initialization - InitProcess::Init init; - - // set global MbedTLS debug level -#if defined(USE_MBEDTLS) - mbedtls_debug_set_threshold(1); -#endif - - if (argc >= 2 && !strcmp(argv[1], "test")) - { - const std::string out = SelfTest::crypto_self_test(); - OPENVPN_LOG(out); - goto out; - } - -#if N_THREADS >= 2 - std::thread* threads[N_THREADS]; - int i; - for (i = 0; i < N_THREADS; ++i) - { - threads[i] = new std::thread([i]() { - test(i); - }); - } - for (i = 0; i < N_THREADS; ++i) - { - threads[i]->join(); - delete threads[i]; - } -#else - ret = test(1); -#endif - -out: - return ret; -} diff --git a/Sources/OpenVPN3/test/ssl/protowin.h b/Sources/OpenVPN3/test/ssl/protowin.h deleted file mode 100644 index 071c93c..0000000 --- a/Sources/OpenVPN3/test/ssl/protowin.h +++ /dev/null @@ -1,2 +0,0 @@ -//#define RENEG 900 -//#define ITER 1000 diff --git a/Sources/OpenVPN3/test/ssl/server.crt b/Sources/OpenVPN3/test/ssl/server.crt deleted file mode 100644 index 76b4044..0000000 --- a/Sources/OpenVPN3/test/ssl/server.crt +++ /dev/null @@ -1,113 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=KG, ST=NA, L=BISHKEK, O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - Validity - Not Before: Oct 22 21:59:52 2014 GMT - Not After : Oct 19 21:59:52 2024 GMT - Subject: C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server/emailAddress=me@myhost.mydomain - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:a5:b8:a2:ee:ce:b1:a6:0f:6a:b2:9f:d3:22:17: - 79:de:09:98:71:78:fa:a7:ce:36:51:54:57:c7:31: - 99:56:d1:8a:d6:c5:fd:52:e6:88:0e:7b:f9:ea:27: - 7a:bf:3f:14:ec:aa:d2:ff:8b:56:58:ac:ca:51:77: - c5:3c:b6:e4:83:6f:22:06:2d:5b:eb:e7:59:d4:ab: - 42:c8:d5:a9:87:73:b3:73:36:51:2f:a5:d0:90:a2: - 87:64:54:6c:12:d3:b8:76:47:69:af:ae:8f:00:b3: - 70:b9:e7:67:3f:8c:6a:3d:79:5f:81:27:a3:0e:aa: - a7:3d:81:48:10:b1:18:6c:38:2e:8f:7a:7b:c5:3d: - 21:c8:f9:a0:7f:17:2b:88:4f:ba:f2:ec:6d:24:8e: - 6c:f1:0a:5c:d9:5b:b1:b0:fc:49:cb:4a:d2:58:c6: - 2a:25:b0:97:84:c3:9e:ff:34:8c:10:46:7f:0f:fb: - 3c:59:7a:a6:29:0c:ae:8e:50:3a:f2:53:84:40:2d: - d5:91:7b:0a:37:8e:82:77:ce:66:2f:34:77:5c:a5: - 45:3b:00:19:a7:07:d1:92:e6:66:b9:3b:4e:e9:63: - fc:33:98:1a:ae:7b:08:7d:0a:df:7a:ba:aa:59:6d: - 86:82:0a:64:2b:da:59:a7:4c:4e:ef:3d:bd:04:a2: - 4b:31 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Cert Type: - SSL Server - Netscape Comment: - OpenSSL Generated Server Certificate - X509v3 Subject Key Identifier: - B3:9D:81:E6:16:92:64:C4:86:87:F5:29:10:1B:5E:2F:74:F7:ED:B1 - X509v3 Authority Key Identifier: - keyid:2B:40:E5:C9:7D:F5:F4:96:38:E9:2F:E3:2F:D9:40:64:C9:8E:05:9B - DirName:/C=KG/ST=NA/L=BISHKEK/O=OpenVPN-TEST/emailAddress=me@myhost.mydomain - serial:A1:4E:DE:FA:90:F2:AE:81 - - X509v3 Extended Key Usage: - TLS Web Server Authentication - X509v3 Key Usage: - Digital Signature, Key Encipherment - Signature Algorithm: sha256WithRSAEncryption - 4e:25:80:1b:cb:b0:42:ff:bb:3f:e8:0d:58:c1:80:db:cf:d0: - 90:df:ca:c1:e6:41:e1:48:7f:a7:1e:c7:35:9f:9c:6d:7c:3e: - 82:e8:de:7e:ae:82:16:00:33:0f:02:23:f1:9d:fe:2b:06:16: - 05:55:16:89:dc:63:ac:5f:1a:31:13:79:21:a3:6e:60:28:e8: - e7:6b:54:00:22:a1:b7:69:5a:17:31:ce:0f:c2:a6:dd:a3:6f: - de:ea:19:6c:d2:d2:cb:35:9d:dd:87:51:33:68:cd:c3:9b:90: - 55:f1:80:3d:5c:b8:09:b6:e1:3c:13:a4:5d:4a:ce:a5:11:9e: - f9:08:ee:be:e3:54:1d:06:4c:bb:1b:72:13:ee:7d:a0:45:cc: - fe:d1:3b:02:03:c1:d4:ea:45:2d:a8:c9:97:e7:f3:8a:7a:a0: - 2f:dd:48:3a:75:c9:42:28:94:fc:af:44:52:16:68:98:d6:ad: - a8:65:b1:cd:ac:60:41:70:e5:44:e8:5a:f2:e7:fc:3b:fe:45: - 89:17:1d:6d:85:c6:f0:fc:69:87:d1:1d:07:f3:cb:7b:54:8d: - aa:a3:cc:e3:c6:fc:d6:05:76:35:d0:26:63:8e:d1:a8:b7:ff: - 61:42:8a:2c:63:1f:d4:ec:14:47:6b:1e:e3:81:61:12:3b:8c: - 16:b5:cf:87:6a:2d:42:21:83:9c:0e:3a:90:3a:1e:c1:36:61: - 41:f9:fb:4e:5d:ea:f4:df:23:92:33:2b:9b:14:9f:a0:f5:d3: - c4:f8:1f:2f:9c:11:36:af:2a:22:61:95:32:0b:c4:1c:2d:b1: - c1:0a:2a:97:c0:43:4a:6c:3e:db:00:cd:29:15:9e:7e:41:75: - 36:a8:56:86:8c:82:9e:46:20:e5:06:1e:60:d2:03:5f:9f:9e: - 69:bb:bf:c2:b4:43:e2:7d:85:17:83:18:41:b0:cb:a9:04:1b: - 18:52:9f:89:8b:76:9f:94:59:81:4f:60:5b:33:18:fc:c7:52: - d0:d2:69:fc:0b:a2:63:32:75:43:99:e9:d7:f8:6d:c7:55:31: - 0c:f3:ef:1a:71:e1:0a:57:e1:9d:13:b2:1e:fe:1d:ef:e4:f1: - 51:d9:95:b3:fd:28:28:93:91:4a:29:c5:37:0e:ab:d8:85:6a: - fe:a8:83:1f:7b:80:5d:1f:04:79:b7:a9:08:6e:0d:d6:2e:aa: - 7c:f6:63:7d:41:de:70:13:32:ce:dd:58:cc:a6:73:d4:72:7e: - d7:ac:74:a8:35:ba:c3:1b:2a:64:d7:5a:37:97:56:94:34:2b: - 2a:71:60:bc:69:ab:00:85:b9:4f:67:32:17:51:c3:da:57:3a: - 37:89:66:c4:7a:51:da:5f ------BEGIN CERTIFICATE----- -MIIFgDCCA2igAwIBAgIBATANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJLRzEL -MAkGA1UECBMCTkExEDAOBgNVBAcTB0JJU0hLRUsxFTATBgNVBAoTDE9wZW5WUE4t -VEVTVDEhMB8GCSqGSIb3DQEJARYSbWVAbXlob3N0Lm15ZG9tYWluMB4XDTE0MTAy -MjIxNTk1MloXDTI0MTAxOTIxNTk1MlowajELMAkGA1UEBhMCS0cxCzAJBgNVBAgT -Ak5BMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxFDASBgNVBAMTC1Rlc3QtU2VydmVy -MSEwHwYJKoZIhvcNAQkBFhJtZUBteWhvc3QubXlkb21haW4wggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCluKLuzrGmD2qyn9MiF3neCZhxePqnzjZRVFfH -MZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpRd8U8tuSDbyIGLVvr51nUq0LI -1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C552c/jGo9eV+BJ6MOqqc9gUgQ -sRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZW7Gw/EnLStJYxiolsJeEw57/ -NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3zmYvNHdcpUU7ABmnB9GS5ma5 -O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7vPb0EoksxAgMBAAGjggEzMIIB -LzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYk -T3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBSz -nYHmFpJkxIaH9SkQG14vdPftsTCBmAYDVR0jBIGQMIGNgBQrQOXJffX0ljjpL+Mv -2UBkyY4Fm6FqpGgwZjELMAkGA1UEBhMCS0cxCzAJBgNVBAgTAk5BMRAwDgYDVQQH -EwdCSVNIS0VLMRUwEwYDVQQKEwxPcGVuVlBOLVRFU1QxITAfBgkqhkiG9w0BCQEW -Em1lQG15aG9zdC5teWRvbWFpboIJAKFO3vqQ8q6BMBMGA1UdJQQMMAoGCCsGAQUF -BwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAgEATiWAG8uwQv+7P+gN -WMGA28/QkN/KweZB4Uh/px7HNZ+cbXw+gujefq6CFgAzDwIj8Z3+KwYWBVUWidxj -rF8aMRN5IaNuYCjo52tUACKht2laFzHOD8Km3aNv3uoZbNLSyzWd3YdRM2jNw5uQ -VfGAPVy4CbbhPBOkXUrOpRGe+QjuvuNUHQZMuxtyE+59oEXM/tE7AgPB1OpFLajJ -l+fzinqgL91IOnXJQiiU/K9EUhZomNatqGWxzaxgQXDlROha8uf8O/5FiRcdbYXG -8Pxph9EdB/PLe1SNqqPM48b81gV2NdAmY47RqLf/YUKKLGMf1OwUR2se44FhEjuM -FrXPh2otQiGDnA46kDoewTZhQfn7Tl3q9N8jkjMrmxSfoPXTxPgfL5wRNq8qImGV -MgvEHC2xwQoql8BDSmw+2wDNKRWefkF1NqhWhoyCnkYg5QYeYNIDX5+eabu/wrRD -4n2FF4MYQbDLqQQbGFKfiYt2n5RZgU9gWzMY/MdS0NJp/AuiYzJ1Q5np1/htx1Ux -DPPvGnHhClfhnROyHv4d7+TxUdmVs/0oKJORSinFNw6r2IVq/qiDH3uAXR8Eebep -CG4N1i6qfPZjfUHecBMyzt1YzKZz1HJ+16x0qDW6wxsqZNdaN5dWlDQrKnFgvGmr -AIW5T2cyF1HD2lc6N4lmxHpR2l8= ------END CERTIFICATE----- diff --git a/Sources/OpenVPN3/test/ssl/server.key b/Sources/OpenVPN3/test/ssl/server.key deleted file mode 100644 index 011df12..0000000 --- a/Sources/OpenVPN3/test/ssl/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCluKLuzrGmD2qy -n9MiF3neCZhxePqnzjZRVFfHMZlW0YrWxf1S5ogOe/nqJ3q/PxTsqtL/i1ZYrMpR -d8U8tuSDbyIGLVvr51nUq0LI1amHc7NzNlEvpdCQoodkVGwS07h2R2mvro8As3C5 -52c/jGo9eV+BJ6MOqqc9gUgQsRhsOC6PenvFPSHI+aB/FyuIT7ry7G0kjmzxClzZ -W7Gw/EnLStJYxiolsJeEw57/NIwQRn8P+zxZeqYpDK6OUDryU4RALdWRewo3joJ3 -zmYvNHdcpUU7ABmnB9GS5ma5O07pY/wzmBquewh9Ct96uqpZbYaCCmQr2lmnTE7v -Pb0EoksxAgMBAAECggEAPMOMin+jR75TYxeTNObiunVOPh0b2zeTVxLT9KfND7ZZ -cBK8pg79SEJRCnhbW5BnvbeNEkIm8PC6ZlDCM1bkRwUStq0fDUqQ95esLzOYq5/S -5qW98viblszhU/pYfja/Zi8dI1uf96PT63Zbt0NnGQ9N42+DLDeKhtTGdchZqiQA -LeSR0bQanY4tUUtCNYvBT8E3pzhoIsUzVwzIK53oovRpcOX3pMXVYZsmNhXdFFRy -YkjMXpj7fGyaAJK0QsC+PsgrKuhXDzDttsG2lI/mq9+7RXB3d/pzhmBVWynVH2lw -iQ7ONkSz7akDz/4I4WmxJep+FfQJYgK6rnLAlQqauQKBgQDammSAprnvDvNhSEp8 -W+xt7jQnFqaENbGgP0/D/OZMXc4khgexqlKFmSnBCRDmQ6JvLTWqDXC4+aqAbFQz -zAIjiKaT+so8xvFRob+rBMJY5JLYKNa+zUUanfORUNYLFJPvFqnrWGaJ9uufdaM7 -0a5bu95PN74NXee3DBbpBv8HLwKBgQDCEk+IjNbjMT+Neq0ywUeM5rFrUKi92abe -AgsVpjbighRV+6jA2lZFJcize+xYJ9wiOR1/TEI9PZ2OtBkqpwVdvTEHTagRLcvd -NfGcptREDnNLoNWA22buQpztiEduutACWQsrd+JQmqbUicUdW4zw86/oCMbYCW3V -QmYOLns7nwKBgHHUX20WZE91S4pmqFKlUzHTDdkk1ESX6Qx2q0R01j8BwawHFs6O -0DW9EZ7w55nfsh+OPRl1sjK/3ubMgfQO0TZLm+IGf3Sya0qEnVeiPMkpDMX+TgRA -wzEe+ou6uho+9uFSvdxMxeglaYA5M2ycvNwLsbEyZ4ZyVYxdgTiKahYFAoGAcIfP -iD0qKQiYcj/tB94cz+3AeJqHjbYT1O1YYhBECOkmQ4kuG80+cs/q5W/45lEOiuWV -Xgfo7Lu6jVGOujWoneci87oqtvNYH4e09oGh2WiLoBG9Wv9dWtBTUERSLzmxfXsG -SAk2uEhEbj8IhfJc8iZLHH9iVUh6YEslBBodqL8CgYEAlAhvcqAvw5SzsfBR5Mcu -4Nql6mXEVhHCvS4hdFCGaNF0z9A6eBORKJpdLWnqhpquDQDsghWE+Ga4QKSNFIi1 -fnAaykmZuY3ToqNOIaVlYM6HpMEz0wHQbTWfDLGcTFcElLZgMAk7VlDyiYVOco+E -QX9lXOO1PGpLzXhlDxSe63Y= ------END PRIVATE KEY----- diff --git a/Sources/OpenVPN3/test/ssl/tls-auth.key b/Sources/OpenVPN3/test/ssl/tls-auth.key deleted file mode 100644 index 267f730..0000000 --- a/Sources/OpenVPN3/test/ssl/tls-auth.key +++ /dev/null @@ -1,21 +0,0 @@ -# -# 2048 bit OpenVPN static key -# ------BEGIN OpenVPN Static key V1----- -02a83428cd0e690e4afe8e9f10b439cb -8405bdea3f0cada559df5d8398018258 -9727346c21655d956611b40ebbbc5280 -56bb220ac635a3432817110b8ff074af -bd3124c39fef2551c3dde7eeb6469c3a -a29b38c499e200ebed75c0381684676e -890e86da25be6473fb0e484aeed91896 -ffbc9e78457943a67803924cb6a32074 -0d314e5114c979ab3849c176d7738278 -d6d7db6c9a8d70cf1445f9aab193a701 -38f7af565a8fa368a656e0cec69d4a7b -6515ae50d30b269e1750ba59e9e12629 -cfbfcceefabda3a793f5cb5bbdf18ab3 -8d69293d8923d427136dd9fcd2660e12 -dfaa32c0f865f72fffea123b3c12425b -86f22ba328f5837ccfab21fc068925f3 ------END OpenVPN Static key V1----- diff --git a/Sources/OpenVPN3/test/ssl/tls-crypt-v2-client.key b/Sources/OpenVPN3/test/ssl/tls-crypt-v2-client.key deleted file mode 100644 index ea6f933..0000000 --- a/Sources/OpenVPN3/test/ssl/tls-crypt-v2-client.key +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN OpenVPN tls-crypt-v2 client key----- -fxgWlYpYT1H8ZCW3/139Ip6WSAa2QQZUu64N/x3g7RzhYuaInPRpP9GLpeDpj/PP -MOa0LuvbIr9Wm6V4+WUO+R8hOdfIMwtBlRleMDedFNRD5h1DCpoDdpgr5CxaPyqO -H6eCvNP7POmqdGJyo9L6H9ndyetQp4r/8wXeYWSkcJKsIJsmyBqRzuODTENGYCqG -FN3+XcUrEMYUyvb/c8NqDVQ6xpwc9+6N7840encSMZPYCq6o8J1QXZJ8sMoBEPa1 -gVtLCsPXp2oTs1h82NBpxO8BNPNFz1xIG+2Zy1NpU8PONnr0rtCRPNU7ejsG+p2I -vRDt3VOf+3aD2eVFesR4NAWYTZlxg3eLG4zD/xSiGblBltbB/7qGPxgK6WOP2XD/ -V0Yh+TruX2vo4xjEXqV1umTx9K8u6nvaC8uv/72NsvPWkuAOEpY6qpDrqiya+zod -zjrlKdLmftaTEMGURDIjooNygFOAania7UhLWOjhnzZFntLHoYmskF0C7om4CqPR -dhf1OuyaD436yQVdt3t/8sjBGuY4hQZ3PuMKDEsHEzmq8bYwfmDf3U8IsK39NbXO -Bh7Q3Gxxy0vTP2TRsGUbePh5ZveVtCJGe79tjtveLdEVdh+TsMB2xo/ZLFfjDPOx -6xvj5xKQtyou5YawuniHn5nrDWbyARQDTmVl7a5w5HvK3SbuVDrJsuLiRohfKyah -M17SAY5reFev6+piR+zT64zwTYdU20i28gEr ------END OpenVPN tls-crypt-v2 client key----- diff --git a/Sources/OpenVPN3/test/ssl/tls-crypt-v2-server.key b/Sources/OpenVPN3/test/ssl/tls-crypt-v2-server.key deleted file mode 100644 index e8152aa..0000000 --- a/Sources/OpenVPN3/test/ssl/tls-crypt-v2-server.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN OpenVPN tls-crypt-v2 server key----- -hn6VWraZG0o64iPI7faGYkwTMajjqhXqG2kC1X19jCl+aXhWPSgmDbRCT/pSfjLZ -a2pKXP6DGdi3nuINKuPw4655AcuMaBe4b45+zJz5xk92NnNosLaTsanXtjfBNOK5 -S/M1f4cLZViVsJTDSMcINK/RCclWVK+IFi//CThZQM8= ------END OpenVPN tls-crypt-v2 server key----- diff --git a/Sources/OpenVPN3/test/unittests/.gitignore b/Sources/OpenVPN3/test/unittests/.gitignore deleted file mode 100644 index 77441d8..0000000 --- a/Sources/OpenVPN3/test/unittests/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -test_all -test_b64 -test_common -test_comp -test_continuation -test_cpu_time -test_helper -test_log -test_mbedtls_x509certinfo -test_openssl_x509certinfo -test_route_emulation -test_sitnl -test_ssl -test_verify_x509_name diff --git a/Sources/OpenVPN3/test/unittests/CMakeLists.txt b/Sources/OpenVPN3/test/unittests/CMakeLists.txt deleted file mode 100644 index 6843315..0000000 --- a/Sources/OpenVPN3/test/unittests/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(tests) -set(CMAKE_CXX_STANDARD 14) - -include(findcoredeps) -include(dlgoogletest) - -# Extra includes/libraries that are currently only use by the core unit test -FIND_PATH(LZO_INCLUDE_DIR NAMES lzo/lzo1x.h) -FIND_LIBRARY(LZO_LIBRARIES NAMES lzo2) - -if (LZO_INCLUDE_DIR AND LZO_LIBRARIES) - list(APPEND CORE_TEST_DEFINES -DHAVE_LZO) - list(APPEND EXTRA_LIBS ${LZO_LIBRARIES}) - list(APPEND EXTRA_INCLUDES ${LZO_INCLUDE_DIR}) - message("lzo found, running lzo compression tests") -else () - message("lzo not found, skipping lzo compression tests") -endif () - - - -set(CORE_TEST_DEFINES - -DOPENVPN_FORCE_TUN_NULL - -DUNIT_TEST - -DUNITTEST_SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\" - ) - -add_executable(coreUnitTests - core_tests.cpp - test_route_emulation.cpp - test_log.cpp - test_comp.cpp - test_b64.cpp - test_verify_x509_name.cpp - test_ssl.cpp - test_continuation.cpp - ) - -if (${USE_MBEDTLS}) - target_sources(coreUnitTests PRIVATE - test_mbedtls_x509certinfo.cpp - ) -else () - target_sources(coreUnitTests PRIVATE - test_openssl_x509certinfo.cpp - ) -endif () - -if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - target_sources(coreUnitTests PRIVATE test_sitnl.cpp) -endif () - -if (UNIX) - target_sources(coreUnitTests PRIVATE test_cpu_time.cpp) -endif () - -if (WIN32) - target_sources(coreUnitTests PRIVATE test_iphelper.cpp) -endif () - -if (WIN32) - target_sources(coreUnitTests PRIVATE test_iphelper.cpp) -endif () - -add_core_dependencies(coreUnitTests) -target_link_libraries(coreUnitTests ${GTEST_LIB} ${EXTRA_LIBS}) - -target_compile_definitions(coreUnitTests PRIVATE ${CORE_TEST_DEFINES}) -target_include_directories(coreUnitTests PRIVATE ${EXTRA_INCLUDES}) - -add_test(NAME CoreTests COMMAND coreUnitTests) diff --git a/Sources/OpenVPN3/test/unittests/README-comp.txt b/Sources/OpenVPN3/test/unittests/README-comp.txt deleted file mode 100644 index 7d45d7f..0000000 --- a/Sources/OpenVPN3/test/unittests/README-comp.txt +++ /dev/null @@ -1,3 +0,0 @@ -To test and compare speed of the decomrpession algorithms define N_EXPAND to be more than 1 by either edition -the test-comp.c or by add a -DN_EXPAND=1000 or -DN_COMPRESS=1000 for the compression speed in the CmakeLists -and looks at the time the unit test take for the different combinations. diff --git a/Sources/OpenVPN3/test/unittests/README.md b/Sources/OpenVPN3/test/unittests/README.md deleted file mode 100644 index d2c9669..0000000 --- a/Sources/OpenVPN3/test/unittests/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Unit test framework for OpenVPN3 # - -The unit test framework is written in the [Google Test](https://github.com/google/googletest) -framework. - -## Building/running the unit tests ## -Before building the unit tests themselves, you should build the dependencies -as described in the [README.rst](../../README.rst). - -The unit test cmake files assume here that the deps directory is on the same -level as the openvpn3 directory unless overridden by the DEP_DIR variable. - -The directory for cmake to build a project can be everywhere, but it is recommended to keep -it outside of the source tree. - -Building unit tests (assuming you are in the openvpn3 directory): - - ➜ mkdir ../unit_test_build - ➜ cd ../unit_test_build - ➜ cmake ../openvpn3 - ➜ cmake --build . --target coreUnitTests - -Note: On Linux and Mac OS you can use `make coreUnitTests` instead of `cmake --build` - -Run the unit tests: - - ➜ ./test/unittests/coreUnitTests --gtest_shuffle - -On a Mac with OpenSSL from [homebrew](brew.sh): - - ➜ cmake ../openvpn3 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1 - -Using mbed TLS instead of OpenSSL - - ➜ cmake ../openvpn3 -DUSE_MBEDTLS - -A full list of build options can shown together with short descriptions can be shown with - - ➜ cmake -LH . - -Examplary commands for building and running on Windows: - - ➜ cmake -DDEP_DIR=C:\o3\deps -DUSE_MBEDTLS=true -DCMAKE_GENERATOR_PLATFORM=x64 C:\o3\openvpn3 - ➜ cmake --build . --target coreUnitTests - ➜ test\unittests\Debug\coreUnitTests.exe --gtest_output="xml:test_core.xml" --gtest_shuffle - -### Frequently used command line options ### - -Show the help for gtest command line options: - - ➜ ./test/unittests/coreUnitTests --help - -Run only tests starting with Base64 or a sepcific Base64 test: - - ➜ ./test/unittests/coreUnitTests --gtest_filter='Base64.*' - ➜ ./test/unittests/coreUnitTests --gtest_filter=Base64.tooshortdest - -Run all test but the Base64 tests - - ➜ ./test/unittests/coreUnitTests --gtest_filter='-Base64.*' - -Multiple pattern can be specified with a list separated by : - - ➜ ./test/unittests/coreUnitTests --gtest_filter='OpenSSL_X509_get_serial.*:Base64.*' - - -Shuffle order the order in which the tests are run: - - ➜ ./test/unittests/coreUnitTests --gtest_shuffle - -If a certain order yields failures, repeat that order: - - ➜ ./test/unittests/coreUnitTests --gtest_shuffle --gtest_random_seed=23 - -Run also the tests that are normally disabled - - ➜ ./test/unittests/coreUnitTests --gtest_also_run_disabled_tests - -## Writing unit tetss ## - -Each new test suite should be a new a file called `test_suitename.cpp` and added to the -`CMAKELists.txt` file. Eah test includes an `#include test_common.h` at the top to setup -common openvpn3 library parameter and to set the `OPENVPN_EXTERN` define to `extern`. This -is done so header files that define globals can be included multiple times. The only file that -includes headers without the `OPENVPN_EXTERN` being set is the `core_tests.cpp` file. All -global includes should be done in this file. - -Currently all tests can fit in the same compilation unit `coreUnitTests`. If a unit test -requires special compile/includes or other options that are not compatible with the rest of -the unit tests, another compilation unit should be added to the CMAKELists.txt - -The `test_helper.cc` file adds helper functions that can be used for unit tests. See the file -for more information. diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/alice29.txt b/Sources/OpenVPN3/test/unittests/comp-testdata/alice29.txt deleted file mode 100644 index f115686..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/alice29.txt +++ /dev/null @@ -1,3609 +0,0 @@ - - - - - ALICE'S ADVENTURES IN WONDERLAND - - Lewis Carroll - - THE MILLENNIUM FULCRUM EDITION 2.9 - - - - - CHAPTER I - - Down the Rabbit-Hole - - - Alice was beginning to get very tired of sitting by her sister -on the bank, and of having nothing to do: once or twice she had -peeped into the book her sister was reading, but it had no -pictures or conversations in it, `and what is the use of a book,' -thought Alice `without pictures or conversation?' - - So she was considering in her own mind (as well as she could, -for the hot day made her feel very sleepy and stupid), whether -the pleasure of making a daisy-chain would be worth the trouble -of getting up and picking the daisies, when suddenly a White -Rabbit with pink eyes ran close by her. - - There was nothing so VERY remarkable in that; nor did Alice -think it so VERY much out of the way to hear the Rabbit say to -itself, `Oh dear! Oh dear! I shall be late!' (when she thought -it over afterwards, it occurred to her that she ought to have -wondered at this, but at the time it all seemed quite natural); -but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- -POCKET, and looked at it, and then hurried on, Alice started to -her feet, for it flashed across her mind that she had never -before seen a rabbit with either a waistcoat-pocket, or a watch to -take out of it, and burning with curiosity, she ran across the -field after it, and fortunately was just in time to see it pop -down a large rabbit-hole under the hedge. - - In another moment down went Alice after it, never once -considering how in the world she was to get out again. - - The rabbit-hole went straight on like a tunnel for some way, -and then dipped suddenly down, so suddenly that Alice had not a -moment to think about stopping herself before she found herself -falling down a very deep well. - - Either the well was very deep, or she fell very slowly, for she -had plenty of time as she went down to look about her and to -wonder what was going to happen next. First, she tried to look -down and make out what she was coming to, but it was too dark to -see anything; then she looked at the sides of the well, and -noticed that they were filled with cupboards and book-shelves; -here and there she saw maps and pictures hung upon pegs. She -took down a jar from one of the shelves as she passed; it was -labelled `ORANGE MARMALADE', but to her great disappointment it -was empty: she did not like to drop the jar for fear of killing -somebody, so managed to put it into one of the cupboards as she -fell past it. - - `Well!' thought Alice to herself, `after such a fall as this, I -shall think nothing of tumbling down stairs! How brave they'll -all think me at home! Why, I wouldn't say anything about it, -even if I fell off the top of the house!' (Which was very likely -true.) - - Down, down, down. Would the fall NEVER come to an end! `I -wonder how many miles I've fallen by this time?' she said aloud. -`I must be getting somewhere near the centre of the earth. Let -me see: that would be four thousand miles down, I think--' (for, -you see, Alice had learnt several things of this sort in her -lessons in the schoolroom, and though this was not a VERY good -opportunity for showing off her knowledge, as there was no one to -listen to her, still it was good practice to say it over) `--yes, -that's about the right distance--but then I wonder what Latitude -or Longitude I've got to?' (Alice had no idea what Latitude was, -or Longitude either, but thought they were nice grand words to -say.) - - Presently she began again. `I wonder if I shall fall right -THROUGH the earth! How funny it'll seem to come out among the -people that walk with their heads downward! The Antipathies, I -think--' (she was rather glad there WAS no one listening, this -time, as it didn't sound at all the right word) `--but I shall -have to ask them what the name of the country is, you know. -Please, Ma'am, is this New Zealand or Australia?' (and she tried -to curtsey as she spoke--fancy CURTSEYING as you're falling -through the air! Do you think you could manage it?) `And what -an ignorant little girl she'll think me for asking! No, it'll -never do to ask: perhaps I shall see it written up somewhere.' - - Down, down, down. There was nothing else to do, so Alice soon -began talking again. `Dinah'll miss me very much to-night, I -should think!' (Dinah was the cat.) `I hope they'll remember -her saucer of milk at tea-time. Dinah my dear! I wish you were -down here with me! There are no mice in the air, I'm afraid, but -you might catch a bat, and that's very like a mouse, you know. -But do cats eat bats, I wonder?' And here Alice began to get -rather sleepy, and went on saying to herself, in a dreamy sort of -way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do -bats eat cats?' for, you see, as she couldn't answer either -question, it didn't much matter which way she put it. She felt -that she was dozing off, and had just begun to dream that she -was walking hand in hand with Dinah, and saying to her very -earnestly, `Now, Dinah, tell me the truth: did you ever eat a -bat?' when suddenly, thump! thump! down she came upon a heap of -sticks and dry leaves, and the fall was over. - - Alice was not a bit hurt, and she jumped up on to her feet in a -moment: she looked up, but it was all dark overhead; before her -was another long passage, and the White Rabbit was still in -sight, hurrying down it. There was not a moment to be lost: -away went Alice like the wind, and was just in time to hear it -say, as it turned a corner, `Oh my ears and whiskers, how late -it's getting!' She was close behind it when she turned the -corner, but the Rabbit was no longer to be seen: she found -herself in a long, low hall, which was lit up by a row of lamps -hanging from the roof. - - There were doors all round the hall, but they were all locked; -and when Alice had been all the way down one side and up the -other, trying every door, she walked sadly down the middle, -wondering how she was ever to get out again. - - Suddenly she came upon a little three-legged table, all made of -solid glass; there was nothing on it except a tiny golden key, -and Alice's first thought was that it might belong to one of the -doors of the hall; but, alas! either the locks were too large, or -the key was too small, but at any rate it would not open any of -them. However, on the second time round, she came upon a low -curtain she had not noticed before, and behind it was a little -door about fifteen inches high: she tried the little golden key -in the lock, and to her great delight it fitted! - - Alice opened the door and found that it led into a small -passage, not much larger than a rat-hole: she knelt down and -looked along the passage into the loveliest garden you ever saw. -How she longed to get out of that dark hall, and wander about -among those beds of bright flowers and those cool fountains, but -she could not even get her head though the doorway; `and even if -my head would go through,' thought poor Alice, `it would be of -very little use without my shoulders. Oh, how I wish -I could shut up like a telescope! I think I could, if I only -know how to begin.' For, you see, so many out-of-the-way things -had happened lately, that Alice had begun to think that very few -things indeed were really impossible. - - There seemed to be no use in waiting by the little door, so she -went back to the table, half hoping she might find another key on -it, or at any rate a book of rules for shutting people up like -telescopes: this time she found a little bottle on it, (`which -certainly was not here before,' said Alice,) and round the neck -of the bottle was a paper label, with the words `DRINK ME' -beautifully printed on it in large letters. - - It was all very well to say `Drink me,' but the wise little -Alice was not going to do THAT in a hurry. `No, I'll look -first,' she said, `and see whether it's marked "poison" or not'; -for she had read several nice little histories about children who -had got burnt, and eaten up by wild beasts and other unpleasant -things, all because they WOULD not remember the simple rules -their friends had taught them: such as, that a red-hot poker -will burn you if you hold it too long; and that if you cut your -finger VERY deeply with a knife, it usually bleeds; and she had -never forgotten that, if you drink much from a bottle marked -`poison,' it is almost certain to disagree with you, sooner or -later. - - However, this bottle was NOT marked `poison,' so Alice ventured -to taste it, and finding it very nice, (it had, in fact, a sort -of mixed flavour of cherry-tart, custard, pine-apple, roast -turkey, toffee, and hot buttered toast,) she very soon finished -it off. - - * * * * * * * - - * * * * * * - - * * * * * * * - - `What a curious feeling!' said Alice; `I must be shutting up -like a telescope.' - - And so it was indeed: she was now only ten inches high, and -her face brightened up at the thought that she was now the right -size for going though the little door into that lovely garden. -First, however, she waited for a few minutes to see if she was -going to shrink any further: she felt a little nervous about -this; `for it might end, you know,' said Alice to herself, `in my -going out altogether, like a candle. I wonder what I should be -like then?' And she tried to fancy what the flame of a candle is -like after the candle is blown out, for she could not remember -ever having seen such a thing. - - After a while, finding that nothing more happened, she decided -on going into the garden at once; but, alas for poor Alice! when -she got to the door, she found he had forgotten the little golden -key, and when she went back to the table for it, she found she -could not possibly reach it: she could see it quite plainly -through the glass, and she tried her best to climb up one of the -legs of the table, but it was too slippery; and when she had -tired herself out with trying, the poor little thing sat down and -cried. - - `Come, there's no use in crying like that!' said Alice to -herself, rather sharply; `I advise you to leave off this minute!' -She generally gave herself very good advice, (though she very -seldom followed it), and sometimes she scolded herself so -severely as to bring tears into her eyes; and once she remembered -trying to box her own ears for having cheated herself in a game -of croquet she was playing against herself, for this curious -child was very fond of pretending to be two people. `But it's no -use now,' thought poor Alice, `to pretend to be two people! Why, -there's hardly enough of me left to make ONE respectable -person!' - - Soon her eye fell on a little glass box that was lying under -the table: she opened it, and found in it a very small cake, on -which the words `EAT ME' were beautifully marked in currants. -`Well, I'll eat it,' said Alice, `and if it makes me grow larger, -I can reach the key; and if it makes me grow smaller, I can creep -under the door; so either way I'll get into the garden, and I -don't care which happens!' - - She ate a little bit, and said anxiously to herself, `Which -way? Which way?', holding her hand on the top of her head to -feel which way it was growing, and she was quite surprised to -find that she remained the same size: to be sure, this generally -happens when one eats cake, but Alice had got so much into the -way of expecting nothing but out-of-the-way things to happen, -that it seemed quite dull and stupid for life to go on in the -common way. - - So she set to work, and very soon finished off the cake. - - * * * * * * * - - * * * * * * - - * * * * * * * - - - - - CHAPTER II - - The Pool of Tears - - - `Curiouser and curiouser!' cried Alice (she was so much -surprised, that for the moment she quite forgot how to speak good -English); `now I'm opening out like the largest telescope that -ever was! Good-bye, feet!' (for when she looked down at her -feet, they seemed to be almost out of sight, they were getting so -far off). `Oh, my poor little feet, I wonder who will put on -your shoes and stockings for you now, dears? I'm sure _I_ shan't -be able! I shall be a great deal too far off to trouble myself -about you: you must manage the best way you can; --but I must be -kind to them,' thought Alice, `or perhaps they won't walk the -way I want to go! Let me see: I'll give them a new pair of -boots every Christmas.' - - And she went on planning to herself how she would manage it. -`They must go by the carrier,' she thought; `and how funny it'll -seem, sending presents to one's own feet! And how odd the -directions will look! - - ALICE'S RIGHT FOOT, ESQ. - HEARTHRUG, - NEAR THE FENDER, - (WITH ALICE'S LOVE). - -Oh dear, what nonsense I'm talking!' - - Just then her head struck against the roof of the hall: in -fact she was now more than nine feet high, and she at once took -up the little golden key and hurried off to the garden door. - - Poor Alice! It was as much as she could do, lying down on one -side, to look through into the garden with one eye; but to get -through was more hopeless than ever: she sat down and began to -cry again. - - `You ought to be ashamed of yourself,' said Alice, `a great -girl like you,' (she might well say this), `to go on crying in -this way! Stop this moment, I tell you!' But she went on all -the same, shedding gallons of tears, until there was a large pool -all round her, about four inches deep and reaching half down the -hall. - - After a time she heard a little pattering of feet in the -distance, and she hastily dried her eyes to see what was coming. -It was the White Rabbit returning, splendidly dressed, with a -pair of white kid gloves in one hand and a large fan in the -other: he came trotting along in a great hurry, muttering to -himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she -be savage if I've kept her waiting!' Alice felt so desperate -that she was ready to ask help of any one; so, when the Rabbit -came near her, she began, in a low, timid voice, `If you please, -sir--' The Rabbit started violently, dropped the white kid -gloves and the fan, and skurried away into the darkness as hard -as he could go. - - Alice took up the fan and gloves, and, as the hall was very -hot, she kept fanning herself all the time she went on talking: -`Dear, dear! How queer everything is to-day! And yesterday -things went on just as usual. I wonder if I've been changed in -the night? Let me think: was I the same when I got up this -morning? I almost think I can remember feeling a little -different. But if I'm not the same, the next question is, Who in -the world am I? Ah, THAT'S the great puzzle!' And she began -thinking over all the children she knew that were of the same age -as herself, to see if she could have been changed for any of -them. - - `I'm sure I'm not Ada,' she said, `for her hair goes in such -long ringlets, and mine doesn't go in ringlets at all; and I'm -sure I can't be Mabel, for I know all sorts of things, and she, -oh! she knows such a very little! Besides, SHE'S she, and I'm I, -and--oh dear, how puzzling it all is! I'll try if I know all the -things I used to know. Let me see: four times five is twelve, -and four times six is thirteen, and four times seven is--oh dear! -I shall never get to twenty at that rate! However, the -Multiplication Table doesn't signify: let's try Geography. -London is the capital of Paris, and Paris is the capital of Rome, -and Rome--no, THAT'S all wrong, I'm certain! I must have been -changed for Mabel! I'll try and say "How doth the little--"' -and she crossed her hands on her lap as if she were saying lessons, -and began to repeat it, but her voice sounded hoarse and -strange, and the words did not come the same as they used to do:-- - - `How doth the little crocodile - Improve his shining tail, - And pour the waters of the Nile - On every golden scale! - - `How cheerfully he seems to grin, - How neatly spread his claws, - And welcome little fishes in - With gently smiling jaws!' - - `I'm sure those are not the right words,' said poor Alice, and -her eyes filled with tears again as she went on, `I must be Mabel -after all, and I shall have to go and live in that poky little -house, and have next to no toys to play with, and oh! ever so -many lessons to learn! No, I've made up my mind about it; if I'm -Mabel, I'll stay down here! It'll be no use their putting their -heads down and saying "Come up again, dear!" I shall only look -up and say "Who am I then? Tell me that first, and then, if I -like being that person, I'll come up: if not, I'll stay down -here till I'm somebody else"--but, oh dear!' cried Alice, with a -sudden burst of tears, `I do wish they WOULD put their heads -down! I am so VERY tired of being all alone here!' - - As she said this she looked down at her hands, and was -surprised to see that she had put on one of the Rabbit's little -white kid gloves while she was talking. `How CAN I have done -that?' she thought. `I must be growing small again.' She got up -and went to the table to measure herself by it, and found that, -as nearly as she could guess, she was now about two feet high, -and was going on shrinking rapidly: she soon found out that the -cause of this was the fan she was holding, and she dropped it -hastily, just in time to avoid shrinking away altogether. - -`That WAS a narrow escape!' said Alice, a good deal frightened at -the sudden change, but very glad to find herself still in -existence; `and now for the garden!' and she ran with all speed -back to the little door: but, alas! the little door was shut -again, and the little golden key was lying on the glass table as -before, `and things are worse than ever,' thought the poor child, -`for I never was so small as this before, never! And I declare -it's too bad, that it is!' - - As she said these words her foot slipped, and in another -moment, splash! she was up to her chin in salt water. He first -idea was that she had somehow fallen into the sea, `and in that -case I can go back by railway,' she said to herself. (Alice had -been to the seaside once in her life, and had come to the general -conclusion, that wherever you go to on the English coast you find -a number of bathing machines in the sea, some children digging in -the sand with wooden spades, then a row of lodging houses, and -behind them a railway station.) However, she soon made out that -she was in the pool of tears which she had wept when she was nine -feet high. - - `I wish I hadn't cried so much!' said Alice, as she swam about, -trying to find her way out. `I shall be punished for it now, I -suppose, by being drowned in my own tears! That WILL be a queer -thing, to be sure! However, everything is queer to-day.' - - Just then she heard something splashing about in the pool a -little way off, and she swam nearer to make out what it was: at -first she thought it must be a walrus or hippopotamus, but then -she remembered how small she was now, and she soon made out that -it was only a mouse that had slipped in like herself. - - `Would it be of any use, now,' thought Alice, `to speak to this -mouse? Everything is so out-of-the-way down here, that I should -think very likely it can talk: at any rate, there's no harm in -trying.' So she began: `O Mouse, do you know the way out of -this pool? I am very tired of swimming about here, O Mouse!' -(Alice thought this must be the right way of speaking to a mouse: -she had never done such a thing before, but she remembered having -seen in her brother's Latin Grammar, `A mouse--of a mouse--to a -mouse--a mouse--O mouse!' The Mouse looked at her rather -inquisitively, and seemed to her to wink with one of its little -eyes, but it said nothing. - - `Perhaps it doesn't understand English,' thought Alice; `I -daresay it's a French mouse, come over with William the -Conqueror.' (For, with all her knowledge of history, Alice had -no very clear notion how long ago anything had happened.) So she -began again: `Ou est ma chatte?' which was the first sentence in -her French lesson-book. The Mouse gave a sudden leap out of the -water, and seemed to quiver all over with fright. `Oh, I beg -your pardon!' cried Alice hastily, afraid that she had hurt the -poor animal's feelings. `I quite forgot you didn't like cats.' - - `Not like cats!' cried the Mouse, in a shrill, passionate -voice. `Would YOU like cats if you were me?' - - `Well, perhaps not,' said Alice in a soothing tone: `don't be -angry about it. And yet I wish I could show you our cat Dinah: -I think you'd take a fancy to cats if you could only see her. -She is such a dear quiet thing,' Alice went on, half to herself, -as she swam lazily about in the pool, `and she sits purring so -nicely by the fire, licking her paws and washing her face--and -she is such a nice soft thing to nurse--and she's such a capital -one for catching mice--oh, I beg your pardon!' cried Alice again, -for this time the Mouse was bristling all over, and she felt -certain it must be really offended. `We won't talk about her any -more if you'd rather not.' - - `We indeed!' cried the Mouse, who was trembling down to the end -of his tail. `As if I would talk on such a subject! Our family -always HATED cats: nasty, low, vulgar things! Don't let me hear -the name again!' - - `I won't indeed!' said Alice, in a great hurry to change the -subject of conversation. `Are you--are you fond--of--of dogs?' -The Mouse did not answer, so Alice went on eagerly: `There is -such a nice little dog near our house I should like to show you! -A little bright-eyed terrier, you know, with oh, such long curly -brown hair! And it'll fetch things when you throw them, and -it'll sit up and beg for its dinner, and all sorts of things--I -can't remember half of them--and it belongs to a farmer, you -know, and he says it's so useful, it's worth a hundred pounds! -He says it kills all the rats and--oh dear!' cried Alice in a -sorrowful tone, `I'm afraid I've offended it again!' For the -Mouse was swimming away from her as hard as it could go, and -making quite a commotion in the pool as it went. - - So she called softly after it, `Mouse dear! Do come back -again, and we won't talk about cats or dogs either, if you don't -like them!' When the Mouse heard this, it turned round and swam -slowly back to her: its face was quite pale (with passion, Alice -thought), and it said in a low trembling voice, `Let us get to -the shore, and then I'll tell you my history, and you'll -understand why it is I hate cats and dogs.' - - It was high time to go, for the pool was getting quite crowded -with the birds and animals that had fallen into it: there were a -Duck and a Dodo, a Lory and an Eaglet, and several other curious -creatures. Alice led the way, and the whole party swam to the -shore. - - - - CHAPTER III - - A Caucus-Race and a Long Tale - - - They were indeed a queer-looking party that assembled on the -bank--the birds with draggled feathers, the animals with their -fur clinging close to them, and all dripping wet, cross, and -uncomfortable. - - The first question of course was, how to get dry again: they -had a consultation about this, and after a few minutes it seemed -quite natural to Alice to find herself talking familiarly with -them, as if she had known them all her life. Indeed, she had -quite a long argument with the Lory, who at last turned sulky, -and would only say, `I am older than you, and must know better'; -and this Alice would not allow without knowing how old it was, -and, as the Lory positively refused to tell its age, there was no -more to be said. - - At last the Mouse, who seemed to be a person of authority among -them, called out, `Sit down, all of you, and listen to me! I'LL -soon make you dry enough!' They all sat down at once, in a large -ring, with the Mouse in the middle. Alice kept her eyes -anxiously fixed on it, for she felt sure she would catch a bad -cold if she did not get dry very soon. - - `Ahem!' said the Mouse with an important air, `are you all ready? -This is the driest thing I know. Silence all round, if you please! -"William the Conqueror, whose cause was favoured by the pope, was -soon submitted to by the English, who wanted leaders, and had been -of late much accustomed to usurpation and conquest. Edwin and -Morcar, the earls of Mercia and Northumbria--"' - - `Ugh!' said the Lory, with a shiver. - - `I beg your pardon!' said the Mouse, frowning, but very -politely: `Did you speak?' - - `Not I!' said the Lory hastily. - - `I thought you did,' said the Mouse. `--I proceed. "Edwin and -Morcar, the earls of Mercia and Northumbria, declared for him: -and even Stigand, the patriotic archbishop of Canterbury, found -it advisable--"' - - `Found WHAT?' said the Duck. - - `Found IT,' the Mouse replied rather crossly: `of course you -know what "it" means.' - - `I know what "it" means well enough, when I find a thing,' said -the Duck: `it's generally a frog or a worm. The question is, -what did the archbishop find?' - - The Mouse did not notice this question, but hurriedly went on, -`"--found it advisable to go with Edgar Atheling to meet William -and offer him the crown. William's conduct at first was -moderate. But the insolence of his Normans--" How are you -getting on now, my dear?' it continued, turning to Alice as it -spoke. - - `As wet as ever,' said Alice in a melancholy tone: `it doesn't -seem to dry me at all.' - - `In that case,' said the Dodo solemnly, rising to its feet, `I -move that the meeting adjourn, for the immediate adoption of more -energetic remedies--' - - `Speak English!' said the Eaglet. `I don't know the meaning of -half those long words, and, what's more, I don't believe you do -either!' And the Eaglet bent down its head to hide a smile: -some of the other birds tittered audibly. - - `What I was going to say,' said the Dodo in an offended tone, -`was, that the best thing to get us dry would be a Caucus-race.' - - `What IS a Caucus-race?' said Alice; not that she wanted much -to know, but the Dodo had paused as if it thought that SOMEBODY -ought to speak, and no one else seemed inclined to say anything. - - `Why,' said the Dodo, `the best way to explain it is to do it.' -(And, as you might like to try the thing yourself, some winter -day, I will tell you how the Dodo managed it.) - - First it marked out a race-course, in a sort of circle, (`the -exact shape doesn't matter,' it said,) and then all the party -were placed along the course, here and there. There was no `One, -two, three, and away,' but they began running when they liked, -and left off when they liked, so that it was not easy to know -when the race was over. However, when they had been running half -an hour or so, and were quite dry again, the Dodo suddenly called -out `The race is over!' and they all crowded round it, panting, -and asking, `But who has won?' - - This question the Dodo could not answer without a great deal of -thought, and it sat for a long time with one finger pressed upon -its forehead (the position in which you usually see Shakespeare, -in the pictures of him), while the rest waited in silence. At -last the Dodo said, `EVERYBODY has won, and all must have -prizes.' - - `But who is to give the prizes?' quite a chorus of voices -asked. - - `Why, SHE, of course,' said the Dodo, pointing to Alice with -one finger; and the whole party at once crowded round her, -calling out in a confused way, `Prizes! Prizes!' - - Alice had no idea what to do, and in despair she put her hand -in her pocket, and pulled out a box of comfits, (luckily the salt -water had not got into it), and handed them round as prizes. -There was exactly one a-piece all round. - - `But she must have a prize herself, you know,' said the Mouse. - - `Of course,' the Dodo replied very gravely. `What else have -you got in your pocket?' he went on, turning to Alice. - - `Only a thimble,' said Alice sadly. - - `Hand it over here,' said the Dodo. - - Then they all crowded round her once more, while the Dodo -solemnly presented the thimble, saying `We beg your acceptance of -this elegant thimble'; and, when it had finished this short -speech, they all cheered. - - Alice thought the whole thing very absurd, but they all looked -so grave that she did not dare to laugh; and, as she could not -think of anything to say, she simply bowed, and took the thimble, -looking as solemn as she could. - - The next thing was to eat the comfits: this caused some noise -and confusion, as the large birds complained that they could not -taste theirs, and the small ones choked and had to be patted on -the back. However, it was over at last, and they sat down again -in a ring, and begged the Mouse to tell them something more. - - `You promised to tell me your history, you know,' said Alice, -`and why it is you hate--C and D,' she added in a whisper, half -afraid that it would be offended again. - - `Mine is a long and a sad tale!' said the Mouse, turning to -Alice, and sighing. - - `It IS a long tail, certainly,' said Alice, looking down with -wonder at the Mouse's tail; `but why do you call it sad?' And -she kept on puzzling about it while the Mouse was speaking, so -that her idea of the tale was something like this:-- - - `Fury said to a - mouse, That he - met in the - house, - "Let us - both go to - law: I will - prosecute - YOU. --Come, - I'll take no - denial; We - must have a - trial: For - really this - morning I've - nothing - to do." - Said the - mouse to the - cur, "Such - a trial, - dear Sir, - With - no jury - or judge, - would be - wasting - our - breath." - "I'll be - judge, I'll - be jury," - Said - cunning - old Fury: - "I'll - try the - whole - cause, - and - condemn - you - to - death."' - - - `You are not attending!' said the Mouse to Alice severely. -`What are you thinking of?' - - `I beg your pardon,' said Alice very humbly: `you had got to -the fifth bend, I think?' - - `I had NOT!' cried the Mouse, sharply and very angrily. - - `A knot!' said Alice, always ready to make herself useful, and -looking anxiously about her. `Oh, do let me help to undo it!' - - `I shall do nothing of the sort,' said the Mouse, getting up -and walking away. `You insult me by talking such nonsense!' - - `I didn't mean it!' pleaded poor Alice. `But you're so easily -offended, you know!' - - The Mouse only growled in reply. - - `Please come back and finish your story!' Alice called after -it; and the others all joined in chorus, `Yes, please do!' but -the Mouse only shook its head impatiently, and walked a little -quicker. - - `What a pity it wouldn't stay!' sighed the Lory, as soon as it -was quite out of sight; and an old Crab took the opportunity of -saying to her daughter `Ah, my dear! Let this be a lesson to you -never to lose YOUR temper!' `Hold your tongue, Ma!' said the -young Crab, a little snappishly. `You're enough to try the -patience of an oyster!' - - `I wish I had our Dinah here, I know I do!' said Alice aloud, -addressing nobody in particular. `She'd soon fetch it back!' - - `And who is Dinah, if I might venture to ask the question?' -said the Lory. - - Alice replied eagerly, for she was always ready to talk about -her pet: `Dinah's our cat. And she's such a capital one for -catching mice you can't think! And oh, I wish you could see her -after the birds! Why, she'll eat a little bird as soon as look -at it!' - - This speech caused a remarkable sensation among the party. -Some of the birds hurried off at once: one the old Magpie began -wrapping itself up very carefully, remarking, `I really must be -getting home; the night-air doesn't suit my throat!' and a Canary -called out in a trembling voice to its children, `Come away, my -dears! It's high time you were all in bed!' On various pretexts -they all moved off, and Alice was soon left alone. - - `I wish I hadn't mentioned Dinah!' she said to herself in a -melancholy tone. `Nobody seems to like her, down here, and I'm -sure she's the best cat in the world! Oh, my dear Dinah! I -wonder if I shall ever see you any more!' And here poor Alice -began to cry again, for she felt very lonely and low-spirited. -In a little while, however, she again heard a little pattering of -footsteps in the distance, and she looked up eagerly, half hoping -that the Mouse had changed his mind, and was coming back to -finish his story. - - - - CHAPTER IV - - The Rabbit Sends in a Little Bill - - - It was the White Rabbit, trotting slowly back again, and -looking anxiously about as it went, as if it had lost something; -and she heard it muttering to itself `The Duchess! The Duchess! -Oh my dear paws! Oh my fur and whiskers! She'll get me -executed, as sure as ferrets are ferrets! Where CAN I have -dropped them, I wonder?' Alice guessed in a moment that it was -looking for the fan and the pair of white kid gloves, and she -very good-naturedly began hunting about for them, but they were -nowhere to be seen--everything seemed to have changed since her -swim in the pool, and the great hall, with the glass table and -the little door, had vanished completely. - - Very soon the Rabbit noticed Alice, as she went hunting about, -and called out to her in an angry tone, `Why, Mary Ann, what ARE -you doing out here? Run home this moment, and fetch me a pair of -gloves and a fan! Quick, now!' And Alice was so much frightened -that she ran off at once in the direction it pointed to, without -trying to explain the mistake it had made. - - `He took me for his housemaid,' she said to herself as she ran. -`How surprised he'll be when he finds out who I am! But I'd -better take him his fan and gloves--that is, if I can find them.' -As she said this, she came upon a neat little house, on the door -of which was a bright brass plate with the name `W. RABBIT' -engraved upon it. She went in without knocking, and hurried -upstairs, in great fear lest she should meet the real Mary Ann, -and be turned out of the house before she had found the fan and -gloves. - - `How queer it seems,' Alice said to herself, `to be going -messages for a rabbit! I suppose Dinah'll be sending me on -messages next!' And she began fancying the sort of thing that -would happen: `"Miss Alice! Come here directly, and get ready -for your walk!" "Coming in a minute, nurse! But I've got to see -that the mouse doesn't get out." Only I don't think,' Alice went -on, `that they'd let Dinah stop in the house if it began ordering -people about like that!' - - By this time she had found her way into a tidy little room with -a table in the window, and on it (as she had hoped) a fan and two -or three pairs of tiny white kid gloves: she took up the fan and -a pair of the gloves, and was just going to leave the room, when -her eye fell upon a little bottle that stood near the looking- -glass. There was no label this time with the words `DRINK ME,' -but nevertheless she uncorked it and put it to her lips. `I know -SOMETHING interesting is sure to happen,' she said to herself, -`whenever I eat or drink anything; so I'll just see what this -bottle does. I do hope it'll make me grow large again, for -really I'm quite tired of being such a tiny little thing!' - - It did so indeed, and much sooner than she had expected: -before she had drunk half the bottle, she found her head pressing -against the ceiling, and had to stoop to save her neck from being -broken. She hastily put down the bottle, saying to herself -`That's quite enough--I hope I shan't grow any more--As it is, I -can't get out at the door--I do wish I hadn't drunk quite so -much!' - - Alas! it was too late to wish that! She went on growing, and -growing, and very soon had to kneel down on the floor: in -another minute there was not even room for this, and she tried -the effect of lying down with one elbow against the door, and the -other arm curled round her head. Still she went on growing, and, -as a last resource, she put one arm out of the window, and one -foot up the chimney, and said to herself `Now I can do no more, -whatever happens. What WILL become of me?' - - Luckily for Alice, the little magic bottle had now had its full -effect, and she grew no larger: still it was very uncomfortable, -and, as there seemed to be no sort of chance of her ever getting -out of the room again, no wonder she felt unhappy. - - `It was much pleasanter at home,' thought poor Alice, `when one -wasn't always growing larger and smaller, and being ordered about -by mice and rabbits. I almost wish I hadn't gone down that -rabbit-hole--and yet--and yet--it's rather curious, you know, -this sort of life! I do wonder what CAN have happened to me! -When I used to read fairy-tales, I fancied that kind of thing -never happened, and now here I am in the middle of one! There -ought to be a book written about me, that there ought! And when -I grow up, I'll write one--but I'm grown up now,' she added in a -sorrowful tone; `at least there's no room to grow up any more -HERE.' - - `But then,' thought Alice, `shall I NEVER get any older than I -am now? That'll be a comfort, one way--never to be an old woman- --but then--always to have lessons to learn! Oh, I shouldn't like -THAT!' - - `Oh, you foolish Alice!' she answered herself. `How can you -learn lessons in here? Why, there's hardly room for YOU, and no -room at all for any lesson-books!' - - And so she went on, taking first one side and then the other, -and making quite a conversation of it altogether; but after a few -minutes she heard a voice outside, and stopped to listen. - - `Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves -this moment!' Then came a little pattering of feet on the -stairs. Alice knew it was the Rabbit coming to look for her, and -she trembled till she shook the house, quite forgetting that she -was now about a thousand times as large as the Rabbit, and had no -reason to be afraid of it. - - Presently the Rabbit came up to the door, and tried to open it; -but, as the door opened inwards, and Alice's elbow was pressed -hard against it, that attempt proved a failure. Alice heard it -say to itself `Then I'll go round and get in at the window.' - - `THAT you won't' thought Alice, and, after waiting till she -fancied she heard the Rabbit just under the window, she suddenly -spread out her hand, and made a snatch in the air. She did not -get hold of anything, but she heard a little shriek and a fall, -and a crash of broken glass, from which she concluded that it was -just possible it had fallen into a cucumber-frame, or something -of the sort. - - Next came an angry voice--the Rabbit's--`Pat! Pat! Where are -you?' And then a voice she had never heard before, `Sure then -I'm here! Digging for apples, yer honour!' - - `Digging for apples, indeed!' said the Rabbit angrily. `Here! -Come and help me out of THIS!' (Sounds of more broken glass.) - - `Now tell me, Pat, what's that in the window?' - - `Sure, it's an arm, yer honour!' (He pronounced it `arrum.') - - `An arm, you goose! Who ever saw one that size? Why, it -fills the whole window!' - - `Sure, it does, yer honour: but it's an arm for all that.' - - `Well, it's got no business there, at any rate: go and take it -away!' - - There was a long silence after this, and Alice could only hear -whispers now and then; such as, `Sure, I don't like it, yer -honour, at all, at all!' `Do as I tell you, you coward!' and at -last she spread out her hand again, and made another snatch in -the air. This time there were TWO little shrieks, and more -sounds of broken glass. `What a number of cucumber-frames there -must be!' thought Alice. `I wonder what they'll do next! As for -pulling me out of the window, I only wish they COULD! I'm sure I -don't want to stay in here any longer!' - - She waited for some time without hearing anything more: at -last came a rumbling of little cartwheels, and the sound of a -good many voice all talking together: she made out the words: -`Where's the other ladder?--Why, I hadn't to bring but one; -Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up -at this corner--No, tie 'em together first--they don't reach half -high enough yet--Oh! they'll do well enough; don't be particular- --Here, Bill! catch hold of this rope--Will the roof bear?--Mind -that loose slate--Oh, it's coming down! Heads below!' (a loud -crash)--`Now, who did that?--It was Bill, I fancy--Who's to go -down the chimney?--Nay, I shan't! YOU do it!--That I won't, -then!--Bill's to go down--Here, Bill! the master says you're to -go down the chimney!' - - `Oh! So Bill's got to come down the chimney, has he?' said -Alice to herself. `Shy, they seem to put everything upon Bill! -I wouldn't be in Bill's place for a good deal: this fireplace is -narrow, to be sure; but I THINK I can kick a little!' - - She drew her foot as far down the chimney as she could, and -waited till she heard a little animal (she couldn't guess of what -sort it was) scratching and scrambling about in the chimney close -above her: then, saying to herself `This is Bill,' she gave one -sharp kick, and waited to see what would happen next. - - The first thing she heard was a general chorus of `There goes -Bill!' then the Rabbit's voice along--`Catch him, you by the -hedge!' then silence, and then another confusion of voices--`Hold -up his head--Brandy now--Don't choke him--How was it, old fellow? -What happened to you? Tell us all about it!' - - Last came a little feeble, squeaking voice, (`That's Bill,' -thought Alice,) `Well, I hardly know--No more, thank ye; I'm -better now--but I'm a deal too flustered to tell you--all I know -is, something comes at me like a Jack-in-the-box, and up I goes -like a sky-rocket!' - - `So you did, old fellow!' said the others. - - `We must burn the house down!' said the Rabbit's voice; and -Alice called out as loud as she could, `If you do. I'll set -Dinah at you!' - - There was a dead silence instantly, and Alice thought to -herself, `I wonder what they WILL do next! If they had any -sense, they'd take the roof off.' After a minute or two, they -began moving about again, and Alice heard the Rabbit say, `A -barrowful will do, to begin with.' - - `A barrowful of WHAT?' thought Alice; but she had not long to -doubt, for the next moment a shower of little pebbles came -rattling in at the window, and some of them hit her in the face. -`I'll put a stop to this,' she said to herself, and shouted out, -`You'd better not do that again!' which produced another dead -silence. - - Alice noticed with some surprise that the pebbles were all -turning into little cakes as they lay on the floor, and a bright -idea came into her head. `If I eat one of these cakes,' she -thought, `it's sure to make SOME change in my size; and as it -can't possibly make me larger, it must make me smaller, I -suppose.' - - So she swallowed one of the cakes, and was delighted to find -that she began shrinking directly. As soon as she was small -enough to get through the door, she ran out of the house, and -found quite a crowd of little animals and birds waiting outside. -The poor little Lizard, Bill, was in the middle, being held up by -two guinea-pigs, who were giving it something out of a bottle. -They all made a rush at Alice the moment she appeared; but she -ran off as hard as she could, and soon found herself safe in a -thick wood. - - `The first thing I've got to do,' said Alice to herself, as she -wandered about in the wood, `is to grow to my right size again; -and the second thing is to find my way into that lovely garden. -I think that will be the best plan.' - - It sounded an excellent plan, no doubt, and very neatly and -simply arranged; the only difficulty was, that she had not the -smallest idea how to set about it; and while she was peering -about anxiously among the trees, a little sharp bark just over -her head made her look up in a great hurry. - - An enormous puppy was looking down at her with large round -eyes, and feebly stretching out one paw, trying to touch her. -`Poor little thing!' said Alice, in a coaxing tone, and she tried -hard to whistle to it; but she was terribly frightened all the -time at the thought that it might be hungry, in which case it -would be very likely to eat her up in spite of all her coaxing. - - Hardly knowing what she did, she picked up a little bit of -stick, and held it out to the puppy; whereupon the puppy jumped -into the air off all its feet at once, with a yelp of delight, -and rushed at the stick, and made believe to worry it; then Alice -dodged behind a great thistle, to keep herself from being run -over; and the moment she appeared on the other side, the puppy -made another rush at the stick, and tumbled head over heels in -its hurry to get hold of it; then Alice, thinking it was very -like having a game of play with a cart-horse, and expecting every -moment to be trampled under its feet, ran round the thistle -again; then the puppy began a series of short charges at the -stick, running a very little way forwards each time and a long -way back, and barking hoarsely all the while, till at last it sat -down a good way off, panting, with its tongue hanging out of its -mouth, and its great eyes half shut. - - This seemed to Alice a good opportunity for making her escape; -so she set off at once, and ran till she was quite tired and out -of breath, and till the puppy's bark sounded quite faint in the -distance. - - `And yet what a dear little puppy it was!' said Alice, as she -leant against a buttercup to rest herself, and fanned herself -with one of the leaves: `I should have liked teaching it tricks -very much, if--if I'd only been the right size to do it! Oh -dear! I'd nearly forgotten that I've got to grow up again! Let -me see--how IS it to be managed? I suppose I ought to eat or -drink something or other; but the great question is, what?' - - The great question certainly was, what? Alice looked all round -her at the flowers and the blades of grass, but she did not see -anything that looked like the right thing to eat or drink under -the circumstances. There was a large mushroom growing near her, -about the same height as herself; and when she had looked under -it, and on both sides of it, and behind it, it occurred to her -that she might as well look and see what was on the top of it. - - She stretched herself up on tiptoe, and peeped over the edge of -the mushroom, and her eyes immediately met those of a large -caterpillar, that was sitting on the top with its arms folded, -quietly smoking a long hookah, and taking not the smallest notice -of her or of anything else. - - - - CHAPTER V - - Advice from a Caterpillar - - - The Caterpillar and Alice looked at each other for some time in -silence: at last the Caterpillar took the hookah out of its -mouth, and addressed her in a languid, sleepy voice. - - `Who are YOU?' said the Caterpillar. - - This was not an encouraging opening for a conversation. Alice -replied, rather shyly, `I--I hardly know, sir, just at present-- -at least I know who I WAS when I got up this morning, but I think -I must have been changed several times since then.' - - `What do you mean by that?' said the Caterpillar sternly. -`Explain yourself!' - - `I can't explain MYSELF, I'm afraid, sir' said Alice, `because -I'm not myself, you see.' - - `I don't see,' said the Caterpillar. - - `I'm afraid I can't put it more clearly,' Alice replied very -politely, `for I can't understand it myself to begin with; and -being so many different sizes in a day is very confusing.' - - `It isn't,' said the Caterpillar. - - `Well, perhaps you haven't found it so yet,' said Alice; `but -when you have to turn into a chrysalis--you will some day, you -know--and then after that into a butterfly, I should think you'll -feel it a little queer, won't you?' - - `Not a bit,' said the Caterpillar. - - `Well, perhaps your feelings may be different,' said Alice; -`all I know is, it would feel very queer to ME.' - - `You!' said the Caterpillar contemptuously. `Who are YOU?' - - Which brought them back again to the beginning of the -conversation. Alice felt a little irritated at the Caterpillar's -making such VERY short remarks, and she drew herself up and said, -very gravely, `I think, you ought to tell me who YOU are, first.' - - `Why?' said the Caterpillar. - - Here was another puzzling question; and as Alice could not -think of any good reason, and as the Caterpillar seemed to be in -a VERY unpleasant state of mind, she turned away. - - `Come back!' the Caterpillar called after her. `I've something -important to say!' - - This sounded promising, certainly: Alice turned and came back -again. - - `Keep your temper,' said the Caterpillar. - - `Is that all?' said Alice, swallowing down her anger as well as -she could. - - `No,' said the Caterpillar. - - Alice thought she might as well wait, as she had nothing else -to do, and perhaps after all it might tell her something worth -hearing. For some minutes it puffed away without speaking, but -at last it unfolded its arms, took the hookah out of its mouth -again, and said, `So you think you're changed, do you?' - - `I'm afraid I am, sir,' said Alice; `I can't remember things as -I used--and I don't keep the same size for ten minutes together!' - - `Can't remember WHAT things?' said the Caterpillar. - - `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it -all came different!' Alice replied in a very melancholy voice. - - `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar. - - Alice folded her hands, and began:-- - - `You are old, Father William,' the young man said, - `And your hair has become very white; - And yet you incessantly stand on your head-- - Do you think, at your age, it is right?' - - `In my youth,' Father William replied to his son, - `I feared it might injure the brain; - But, now that I'm perfectly sure I have none, - Why, I do it again and again.' - - `You are old,' said the youth, `as I mentioned before, - And have grown most uncommonly fat; - Yet you turned a back-somersault in at the door-- - Pray, what is the reason of that?' - - `In my youth,' said the sage, as he shook his grey locks, - `I kept all my limbs very supple - By the use of this ointment--one shilling the box-- - Allow me to sell you a couple?' - - `You are old,' said the youth, `and your jaws are too weak - For anything tougher than suet; - Yet you finished the goose, with the bones and the beak-- - Pray how did you manage to do it?' - - `In my youth,' said his father, `I took to the law, - And argued each case with my wife; - And the muscular strength, which it gave to my jaw, - Has lasted the rest of my life.' - - `You are old,' said the youth, `one would hardly suppose - That your eye was as steady as ever; - Yet you balanced an eel on the end of your nose-- - What made you so awfully clever?' - - `I have answered three questions, and that is enough,' - Said his father; `don't give yourself airs! - Do you think I can listen all day to such stuff? - Be off, or I'll kick you down stairs!' - - - `That is not said right,' said the Caterpillar. - - `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the -words have got altered.' - - `It is wrong from beginning to end,' said the Caterpillar -decidedly, and there was silence for some minutes. - - The Caterpillar was the first to speak. - - `What size do you want to be?' it asked. - - `Oh, I'm not particular as to size,' Alice hastily replied; -`only one doesn't like changing so often, you know.' - - `I DON'T know,' said the Caterpillar. - - Alice said nothing: she had never been so much contradicted in -her life before, and she felt that she was losing her temper. - - `Are you content now?' said the Caterpillar. - - `Well, I should like to be a LITTLE larger, sir, if you -wouldn't mind,' said Alice: `three inches is such a wretched -height to be.' - - `It is a very good height indeed!' said the Caterpillar -angrily, rearing itself upright as it spoke (it was exactly three -inches high). - - `But I'm not used to it!' pleaded poor Alice in a piteous tone. -And she thought of herself, `I wish the creatures wouldn't be so -easily offended!' - - `You'll get used to it in time,' said the Caterpillar; and it -put the hookah into its mouth and began smoking again. - - This time Alice waited patiently until it chose to speak again. -In a minute or two the Caterpillar took the hookah out of its -mouth and yawned once or twice, and shook itself. Then it got -down off the mushroom, and crawled away in the grass, merely -remarking as it went, `One side will make you grow taller, and -the other side will make you grow shorter.' - - `One side of WHAT? The other side of WHAT?' thought Alice to -herself. - - `Of the mushroom,' said the Caterpillar, just as if she had -asked it aloud; and in another moment it was out of sight. - - Alice remained looking thoughtfully at the mushroom for a -minute, trying to make out which were the two sides of it; and as -it was perfectly round, she found this a very difficult question. -However, at last she stretched her arms round it as far as they -would go, and broke off a bit of the edge with each hand. - - `And now which is which?' she said to herself, and nibbled a -little of the right-hand bit to try the effect: the next moment -she felt a violent blow underneath her chin: it had struck her -foot! - - She was a good deal frightened by this very sudden change, but -she felt that there was no time to be lost, as she was shrinking -rapidly; so she set to work at once to eat some of the other bit. -Her chin was pressed so closely against her foot, that there was -hardly room to open her mouth; but she did it at last, and -managed to swallow a morsel of the lefthand bit. - - - * * * * * * * - - * * * * * * - - * * * * * * * - - `Come, my head's free at last!' said Alice in a tone of -delight, which changed into alarm in another moment, when she -found that her shoulders were nowhere to be found: all she could -see, when she looked down, was an immense length of neck, which -seemed to rise like a stalk out of a sea of green leaves that lay -far below her. - - `What CAN all that green stuff be?' said Alice. `And where -HAVE my shoulders got to? And oh, my poor hands, how is it I -can't see you?' She was moving them about as she spoke, but no -result seemed to follow, except a little shaking among the -distant green leaves. - - As there seemed to be no chance of getting her hands up to her -head, she tried to get her head down to them, and was delighted -to find that her neck would bend about easily in any direction, -like a serpent. She had just succeeded in curving it down into a -graceful zigzag, and was going to dive in among the leaves, which -she found to be nothing but the tops of the trees under which she -had been wandering, when a sharp hiss made her draw back in a -hurry: a large pigeon had flown into her face, and was beating -her violently with its wings. - - `Serpent!' screamed the Pigeon. - - `I'm NOT a serpent!' said Alice indignantly. `Let me alone!' - - `Serpent, I say again!' repeated the Pigeon, but in a more -subdued tone, and added with a kind of sob, `I've tried every -way, and nothing seems to suit them!' - - `I haven't the least idea what you're talking about,' said -Alice. - - `I've tried the roots of trees, and I've tried banks, and I've -tried hedges,' the Pigeon went on, without attending to her; `but -those serpents! There's no pleasing them!' - - Alice was more and more puzzled, but she thought there was no -use in saying anything more till the Pigeon had finished. - - `As if it wasn't trouble enough hatching the eggs,' said the -Pigeon; `but I must be on the look-out for serpents night and -day! Why, I haven't had a wink of sleep these three weeks!' - - `I'm very sorry you've been annoyed,' said Alice, who was -beginning to see its meaning. - - `And just as I'd taken the highest tree in the wood,' continued -the Pigeon, raising its voice to a shriek, `and just as I was -thinking I should be free of them at last, they must needs come -wriggling down from the sky! Ugh, Serpent!' - - `But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm -a--' - - `Well! WHAT are you?' said the Pigeon. `I can see you're -trying to invent something!' - - `I--I'm a little girl,' said Alice, rather doubtfully, as she -remembered the number of changes she had gone through that day. - - `A likely story indeed!' said the Pigeon in a tone of the -deepest contempt. `I've seen a good many little girls in my -time, but never ONE with such a neck as that! No, no! You're a -serpent; and there's no use denying it. I suppose you'll be -telling me next that you never tasted an egg!' - - `I HAVE tasted eggs, certainly,' said Alice, who was a very -truthful child; `but little girls eat eggs quite as much as -serpents do, you know.' - - `I don't believe it,' said the Pigeon; `but if they do, why -then they're a kind of serpent, that's all I can say.' - - This was such a new idea to Alice, that she was quite silent -for a minute or two, which gave the Pigeon the opportunity of -adding, `You're looking for eggs, I know THAT well enough; and -what does it matter to me whether you're a little girl or a -serpent?' - - `It matters a good deal to ME,' said Alice hastily; `but I'm -not looking for eggs, as it happens; and if I was, I shouldn't -want YOURS: I don't like them raw.' - - `Well, be off, then!' said the Pigeon in a sulky tone, as it -settled down again into its nest. Alice crouched down among the -trees as well as she could, for her neck kept getting entangled -among the branches, and every now and then she had to stop and -untwist it. After a while she remembered that she still held the -pieces of mushroom in her hands, and she set to work very -carefully, nibbling first at one and then at the other, and -growing sometimes taller and sometimes shorter, until she had -succeeded in bringing herself down to her usual height. - - It was so long since she had been anything near the right size, -that it felt quite strange at first; but she got used to it in a -few minutes, and began talking to herself, as usual. `Come, -there's half my plan done now! How puzzling all these changes -are! I'm never sure what I'm going to be, from one minute to -another! However, I've got back to my right size: the next -thing is, to get into that beautiful garden--how IS that to be -done, I wonder?' As she said this, she came suddenly upon an -open place, with a little house in it about four feet high. -`Whoever lives there,' thought Alice, `it'll never do to come -upon them THIS size: why, I should frighten them out of their -wits!' So she began nibbling at the righthand bit again, and did -not venture to go near the house till she had brought herself -down to nine inches high. - - - - CHAPTER VI - - Pig and Pepper - - - For a minute or two she stood looking at the house, and -wondering what to do next, when suddenly a footman in livery came -running out of the wood--(she considered him to be a footman -because he was in livery: otherwise, judging by his face only, -she would have called him a fish)--and rapped loudly at the door -with his knuckles. It was opened by another footman in livery, -with a round face, and large eyes like a frog; and both footmen, -Alice noticed, had powdered hair that curled all over their -heads. She felt very curious to know what it was all about, and -crept a little way out of the wood to listen. - - The Fish-Footman began by producing from under his arm a great -letter, nearly as large as himself, and this he handed over to -the other, saying, in a solemn tone, `For the Duchess. An -invitation from the Queen to play croquet.' The Frog-Footman -repeated, in the same solemn tone, only changing the order of the -words a little, `From the Queen. An invitation for the Duchess -to play croquet.' - - Then they both bowed low, and their curls got entangled -together. - - Alice laughed so much at this, that she had to run back into -the wood for fear of their hearing her; and when she next peeped -out the Fish-Footman was gone, and the other was sitting on the -ground near the door, staring stupidly up into the sky. - - Alice went timidly up to the door, and knocked. - - `There's no sort of use in knocking,' said the Footman, `and -that for two reasons. First, because I'm on the same side of the -door as you are; secondly, because they're making such a noise -inside, no one could possibly hear you.' And certainly there was -a most extraordinary noise going on within--a constant howling -and sneezing, and every now and then a great crash, as if a dish -or kettle had been broken to pieces. - - `Please, then,' said Alice, `how am I to get in?' - - `There might be some sense in your knocking,' the Footman went -on without attending to her, `if we had the door between us. For -instance, if you were INSIDE, you might knock, and I could let -you out, you know.' He was looking up into the sky all the time -he was speaking, and this Alice thought decidedly uncivil. `But -perhaps he can't help it,' she said to herself; `his eyes are so -VERY nearly at the top of his head. But at any rate he might -answer questions.--How am I to get in?' she repeated, aloud. - - `I shall sit here,' the Footman remarked, `till tomorrow--' - - At this moment the door of the house opened, and a large plate -came skimming out, straight at the Footman's head: it just -grazed his nose, and broke to pieces against one of the trees -behind him. - - `--or next day, maybe,' the Footman continued in the same tone, -exactly as if nothing had happened. - - `How am I to get in?' asked Alice again, in a louder tone. - - `ARE you to get in at all?' said the Footman. `That's the -first question, you know.' - - It was, no doubt: only Alice did not like to be told so. -`It's really dreadful,' she muttered to herself, `the way all the -creatures argue. It's enough to drive one crazy!' - - The Footman seemed to think this a good opportunity for -repeating his remark, with variations. `I shall sit here,' he -said, `on and off, for days and days.' - - `But what am I to do?' said Alice. - - `Anything you like,' said the Footman, and began whistling. - - `Oh, there's no use in talking to him,' said Alice desperately: -`he's perfectly idiotic!' And she opened the door and went in. - - The door led right into a large kitchen, which was full of -smoke from one end to the other: the Duchess was sitting on a -three-legged stool in the middle, nursing a baby; the cook was -leaning over the fire, stirring a large cauldron which seemed to -be full of soup. - - `There's certainly too much pepper in that soup!' Alice said to -herself, as well as she could for sneezing. - - There was certainly too much of it in the air. Even the -Duchess sneezed occasionally; and as for the baby, it was -sneezing and howling alternately without a moment's pause. The -only things in the kitchen that did not sneeze, were the cook, -and a large cat which was sitting on the hearth and grinning from -ear to ear. - - `Please would you tell me,' said Alice, a little timidly, for -she was not quite sure whether it was good manners for her to -speak first, `why your cat grins like that?' - - `It's a Cheshire cat,' said the Duchess, `and that's why. -Pig!' - - She said the last word with such sudden violence that Alice -quite jumped; but she saw in another moment that it was addressed -to the baby, and not to her, so she took courage, and went on -again:-- - - `I didn't know that Cheshire cats always grinned; in fact, I -didn't know that cats COULD grin.' - - `They all can,' said the Duchess; `and most of 'em do.' - - `I don't know of any that do,' Alice said very politely, -feeling quite pleased to have got into a conversation. - - `You don't know much,' said the Duchess; `and that's a fact.' - - Alice did not at all like the tone of this remark, and thought -it would be as well to introduce some other subject of -conversation. While she was trying to fix on one, the cook took -the cauldron of soup off the fire, and at once set to work -throwing everything within her reach at the Duchess and the baby ---the fire-irons came first; then followed a shower of saucepans, -plates, and dishes. The Duchess took no notice of them even when -they hit her; and the baby was howling so much already, that it -was quite impossible to say whether the blows hurt it or not. - - `Oh, PLEASE mind what you're doing!' cried Alice, jumping up -and down in an agony of terror. `Oh, there goes his PRECIOUS -nose'; as an unusually large saucepan flew close by it, and very -nearly carried it off. - - `If everybody minded their own business,' the Duchess said in a -hoarse growl, `the world would go round a deal faster than it -does.' - - `Which would NOT be an advantage,' said Alice, who felt very -glad to get an opportunity of showing off a little of her -knowledge. `Just think of what work it would make with the day -and night! You see the earth takes twenty-four hours to turn -round on its axis--' - - `Talking of axes,' said the Duchess, `chop off her head!' - - Alice glanced rather anxiously at the cook, to see if she meant -to take the hint; but the cook was busily stirring the soup, and -seemed not to be listening, so she went on again: `Twenty-four -hours, I THINK; or is it twelve? I--' - - `Oh, don't bother ME,' said the Duchess; `I never could abide -figures!' And with that she began nursing her child again, -singing a sort of lullaby to it as she did so, and giving it a -violent shake at the end of every line: - - `Speak roughly to your little boy, - And beat him when he sneezes: - He only does it to annoy, - Because he knows it teases.' - - CHORUS. - - (In which the cook and the baby joined):-- - - `Wow! wow! wow!' - - While the Duchess sang the second verse of the song, she kept -tossing the baby violently up and down, and the poor little thing -howled so, that Alice could hardly hear the words:-- - - `I speak severely to my boy, - I beat him when he sneezes; - For he can thoroughly enjoy - The pepper when he pleases!' - - CHORUS. - - `Wow! wow! wow!' - - `Here! you may nurse it a bit, if you like!' the Duchess said -to Alice, flinging the baby at her as she spoke. `I must go and -get ready to play croquet with the Queen,' and she hurried out of -the room. The cook threw a frying-pan after her as she went out, -but it just missed her. - - Alice caught the baby with some difficulty, as it was a queer- -shaped little creature, and held out its arms and legs in all -directions, `just like a star-fish,' thought Alice. The poor -little thing was snorting like a steam-engine when she caught it, -and kept doubling itself up and straightening itself out again, -so that altogether, for the first minute or two, it was as much -as she could do to hold it. - - As soon as she had made out the proper way of nursing it, -(which was to twist it up into a sort of knot, and then keep -tight hold of its right ear and left foot, so as to prevent its -undoing itself,) she carried it out into the open air. `IF I -don't take this child away with me,' thought Alice, `they're sure -to kill it in a day or two: wouldn't it be murder to leave it -behind?' She said the last words out loud, and the little thing -grunted in reply (it had left off sneezing by this time). `Don't -grunt,' said Alice; `that's not at all a proper way of expressing -yourself.' - - The baby grunted again, and Alice looked very anxiously into -its face to see what was the matter with it. There could be no -doubt that it had a VERY turn-up nose, much more like a snout -than a real nose; also its eyes were getting extremely small for -a baby: altogether Alice did not like the look of the thing at -all. `But perhaps it was only sobbing,' she thought, and looked -into its eyes again, to see if there were any tears. - - No, there were no tears. `If you're going to turn into a pig, -my dear,' said Alice, seriously, `I'll have nothing more to do -with you. Mind now!' The poor little thing sobbed again (or -grunted, it was impossible to say which), and they went on for -some while in silence. - - Alice was just beginning to think to herself, `Now, what am I -to do with this creature when I get it home?' when it grunted -again, so violently, that she looked down into its face in some -alarm. This time there could be NO mistake about it: it was -neither more nor less than a pig, and she felt that it would be -quite absurd for her to carry it further. - - So she set the little creature down, and felt quite relieved to -see it trot away quietly into the wood. `If it had grown up,' -she said to herself, `it would have made a dreadfully ugly child: -but it makes rather a handsome pig, I think.' And she began -thinking over other children she knew, who might do very well as -pigs, and was just saying to herself, `if one only knew the right -way to change them--' when she was a little startled by seeing -the Cheshire Cat sitting on a bough of a tree a few yards off. - - The Cat only grinned when it saw Alice. It looked good- -natured, she thought: still it had VERY long claws and a great -many teeth, so she felt that it ought to be treated with respect. - - `Cheshire Puss,' she began, rather timidly, as she did not at -all know whether it would like the name: however, it only -grinned a little wider. `Come, it's pleased so far,' thought -Alice, and she went on. `Would you tell me, please, which way I -ought to go from here?' - - `That depends a good deal on where you want to get to,' said -the Cat. - - `I don't much care where--' said Alice. - - `Then it doesn't matter which way you go,' said the Cat. - - `--so long as I get SOMEWHERE,' Alice added as an explanation. - - `Oh, you're sure to do that,' said the Cat, `if you only walk -long enough.' - - Alice felt that this could not be denied, so she tried another -question. `What sort of people live about here?' - - `In THAT direction,' the Cat said, waving its right paw round, -`lives a Hatter: and in THAT direction,' waving the other paw, -`lives a March Hare. Visit either you like: they're both mad.' - - `But I don't want to go among mad people,' Alice remarked. - - `Oh, you can't help that,' said the Cat: `we're all mad here. -I'm mad. You're mad.' - - `How do you know I'm mad?' said Alice. - - `You must be,' said the Cat, `or you wouldn't have come here.' - - Alice didn't think that proved it at all; however, she went on -`And how do you know that you're mad?' - - `To begin with,' said the Cat, `a dog's not mad. You grant -that?' - - `I suppose so,' said Alice. - - `Well, then,' the Cat went on, `you see, a dog growls when it's -angry, and wags its tail when it's pleased. Now I growl when I'm -pleased, and wag my tail when I'm angry. Therefore I'm mad.' - - `I call it purring, not growling,' said Alice. - - `Call it what you like,' said the Cat. `Do you play croquet -with the Queen to-day?' - - `I should like it very much,' said Alice, `but I haven't been -invited yet.' - - `You'll see me there,' said the Cat, and vanished. - - Alice was not much surprised at this, she was getting so used -to queer things happening. While she was looking at the place -where it had been, it suddenly appeared again. - - `By-the-bye, what became of the baby?' said the Cat. `I'd -nearly forgotten to ask.' - - `It turned into a pig,' Alice quietly said, just as if it had -come back in a natural way. - - `I thought it would,' said the Cat, and vanished again. - - Alice waited a little, half expecting to see it again, but it -did not appear, and after a minute or two she walked on in the -direction in which the March Hare was said to live. `I've seen -hatters before,' she said to herself; `the March Hare will be -much the most interesting, and perhaps as this is May it won't be -raving mad--at least not so mad as it was in March.' As she said -this, she looked up, and there was the Cat again, sitting on a -branch of a tree. - - `Did you say pig, or fig?' said the Cat. - - `I said pig,' replied Alice; `and I wish you wouldn't keep -appearing and vanishing so suddenly: you make one quite giddy.' - - `All right,' said the Cat; and this time it vanished quite -slowly, beginning with the end of the tail, and ending with the -grin, which remained some time after the rest of it had gone. - - `Well! I've often seen a cat without a grin,' thought Alice; -`but a grin without a cat! It's the most curious thing I ever -say in my life!' - - She had not gone much farther before she came in sight of the -house of the March Hare: she thought it must be the right house, -because the chimneys were shaped like ears and the roof was -thatched with fur. It was so large a house, that she did not -like to go nearer till she had nibbled some more of the lefthand -bit of mushroom, and raised herself to about two feet high: even -then she walked up towards it rather timidly, saying to herself -`Suppose it should be raving mad after all! I almost wish I'd -gone to see the Hatter instead!' - - - - CHAPTER VII - - A Mad Tea-Party - - - There was a table set out under a tree in front of the house, -and the March Hare and the Hatter were having tea at it: a -Dormouse was sitting between them, fast asleep, and the other two -were using it as a cushion, resting their elbows on it, and the -talking over its head. `Very uncomfortable for the Dormouse,' -thought Alice; `only, as it's asleep, I suppose it doesn't mind.' - - The table was a large one, but the three were all crowded -together at one corner of it: `No room! No room!' they cried -out when they saw Alice coming. `There's PLENTY of room!' said -Alice indignantly, and she sat down in a large arm-chair at one -end of the table. - - `Have some wine,' the March Hare said in an encouraging tone. - - Alice looked all round the table, but there was nothing on it -but tea. `I don't see any wine,' she remarked. - - `There isn't any,' said the March Hare. - - `Then it wasn't very civil of you to offer it,' said Alice -angrily. - - `It wasn't very civil of you to sit down without being -invited,' said the March Hare. - - `I didn't know it was YOUR table,' said Alice; `it's laid for a -great many more than three.' - - `Your hair wants cutting,' said the Hatter. He had been -looking at Alice for some time with great curiosity, and this was -his first speech. - - `You should learn not to make personal remarks,' Alice said -with some severity; `it's very rude.' - - The Hatter opened his eyes very wide on hearing this; but all -he SAID was, `Why is a raven like a writing-desk?' - - `Come, we shall have some fun now!' thought Alice. `I'm glad -they've begun asking riddles.--I believe I can guess that,' she -added aloud. - - `Do you mean that you think you can find out the answer to it?' -said the March Hare. - - `Exactly so,' said Alice. - - `Then you should say what you mean,' the March Hare went on. - - `I do,' Alice hastily replied; `at least--at least I mean what -I say--that's the same thing, you know.' - - `Not the same thing a bit!' said the Hatter. `You might just -as well say that "I see what I eat" is the same thing as "I eat -what I see"!' - - `You might just as well say,' added the March Hare, `that "I -like what I get" is the same thing as "I get what I like"!' - - `You might just as well say,' added the Dormouse, who seemed to -be talking in his sleep, `that "I breathe when I sleep" is the -same thing as "I sleep when I breathe"!' - - `It IS the same thing with you,' said the Hatter, and here the -conversation dropped, and the party sat silent for a minute, -while Alice thought over all she could remember about ravens and -writing-desks, which wasn't much. - - The Hatter was the first to break the silence. `What day of -the month is it?' he said, turning to Alice: he had taken his -watch out of his pocket, and was looking at it uneasily, shaking -it every now and then, and holding it to his ear. - - Alice considered a little, and then said `The fourth.' - - `Two days wrong!' sighed the Hatter. `I told you butter -wouldn't suit the works!' he added looking angrily at the March -Hare. - - `It was the BEST butter,' the March Hare meekly replied. - - `Yes, but some crumbs must have got in as well,' the Hatter -grumbled: `you shouldn't have put it in with the bread-knife.' - - The March Hare took the watch and looked at it gloomily: then -he dipped it into his cup of tea, and looked at it again: but he -could think of nothing better to say than his first remark, `It -was the BEST butter, you know.' - - Alice had been looking over his shoulder with some curiosity. -`What a funny watch!' she remarked. `It tells the day of the -month, and doesn't tell what o'clock it is!' - - `Why should it?' muttered the Hatter. `Does YOUR watch tell -you what year it is?' - - `Of course not,' Alice replied very readily: `but that's -because it stays the same year for such a long time together.' - - `Which is just the case with MINE,' said the Hatter. - - Alice felt dreadfully puzzled. The Hatter's remark seemed to -have no sort of meaning in it, and yet it was certainly English. -`I don't quite understand you,' she said, as politely as she -could. - - `The Dormouse is asleep again,' said the Hatter, and he poured -a little hot tea upon its nose. - - The Dormouse shook its head impatiently, and said, without -opening its eyes, `Of course, of course; just what I was going to -remark myself.' - - `Have you guessed the riddle yet?' the Hatter said, turning to -Alice again. - - `No, I give it up,' Alice replied: `what's the answer?' - - `I haven't the slightest idea,' said the Hatter. - - `Nor I,' said the March Hare. - - Alice sighed wearily. `I think you might do something better -with the time,' she said, `than waste it in asking riddles that -have no answers.' - - `If you knew Time as well as I do,' said the Hatter, `you -wouldn't talk about wasting IT. It's HIM.' - - `I don't know what you mean,' said Alice. - - `Of course you don't!' the Hatter said, tossing his head -contemptuously. `I dare say you never even spoke to Time!' - - `Perhaps not,' Alice cautiously replied: `but I know I have to -beat time when I learn music.' - - `Ah! that accounts for it,' said the Hatter. `He won't stand -beating. Now, if you only kept on good terms with him, he'd do -almost anything you liked with the clock. For instance, suppose -it were nine o'clock in the morning, just time to begin lessons: -you'd only have to whisper a hint to Time, and round goes the -clock in a twinkling! Half-past one, time for dinner!' - - (`I only wish it was,' the March Hare said to itself in a -whisper.) - - `That would be grand, certainly,' said Alice thoughtfully: -`but then--I shouldn't be hungry for it, you know.' - - `Not at first, perhaps,' said the Hatter: `but you could keep -it to half-past one as long as you liked.' - - `Is that the way YOU manage?' Alice asked. - - The Hatter shook his head mournfully. `Not I!' he replied. -`We quarrelled last March--just before HE went mad, you know--' -(pointing with his tea spoon at the March Hare,) `--it was at the -great concert given by the Queen of Hearts, and I had to sing - - "Twinkle, twinkle, little bat! - How I wonder what you're at!" - -You know the song, perhaps?' - - `I've heard something like it,' said Alice. - - `It goes on, you know,' the Hatter continued, `in this way:-- - - "Up above the world you fly, - Like a tea-tray in the sky. - Twinkle, twinkle--"' - -Here the Dormouse shook itself, and began singing in its sleep -`Twinkle, twinkle, twinkle, twinkle--' and went on so long that -they had to pinch it to make it stop. - - `Well, I'd hardly finished the first verse,' said the Hatter, -`when the Queen jumped up and bawled out, "He's murdering the -time! Off with his head!"' - - `How dreadfully savage!' exclaimed Alice. - - `And ever since that,' the Hatter went on in a mournful tone, -`he won't do a thing I ask! It's always six o'clock now.' - - A bright idea came into Alice's head. `Is that the reason so -many tea-things are put out here?' she asked. - - `Yes, that's it,' said the Hatter with a sigh: `it's always -tea-time, and we've no time to wash the things between whiles.' - - `Then you keep moving round, I suppose?' said Alice. - - `Exactly so,' said the Hatter: `as the things get used up.' - - `But what happens when you come to the beginning again?' Alice -ventured to ask. - - `Suppose we change the subject,' the March Hare interrupted, -yawning. `I'm getting tired of this. I vote the young lady -tells us a story.' - - `I'm afraid I don't know one,' said Alice, rather alarmed at -the proposal. - - `Then the Dormouse shall!' they both cried. `Wake up, -Dormouse!' And they pinched it on both sides at once. - - The Dormouse slowly opened his eyes. `I wasn't asleep,' he -said in a hoarse, feeble voice: `I heard every word you fellows -were saying.' - - `Tell us a story!' said the March Hare. - - `Yes, please do!' pleaded Alice. - - `And be quick about it,' added the Hatter, `or you'll be asleep -again before it's done.' - - `Once upon a time there were three little sisters,' the -Dormouse began in a great hurry; `and their names were Elsie, -Lacie, and Tillie; and they lived at the bottom of a well--' - - `What did they live on?' said Alice, who always took a great -interest in questions of eating and drinking. - - `They lived on treacle,' said the Dormouse, after thinking a -minute or two. - - `They couldn't have done that, you know,' Alice gently -remarked; `they'd have been ill.' - - `So they were,' said the Dormouse; `VERY ill.' - - Alice tried to fancy to herself what such an extraordinary ways -of living would be like, but it puzzled her too much, so she went -on: `But why did they live at the bottom of a well?' - - `Take some more tea,' the March Hare said to Alice, very -earnestly. - - `I've had nothing yet,' Alice replied in an offended tone, `so -I can't take more.' - - `You mean you can't take LESS,' said the Hatter: `it's very -easy to take MORE than nothing.' - - `Nobody asked YOUR opinion,' said Alice. - - `Who's making personal remarks now?' the Hatter asked -triumphantly. - - Alice did not quite know what to say to this: so she helped -herself to some tea and bread-and-butter, and then turned to the -Dormouse, and repeated her question. `Why did they live at the -bottom of a well?' - - The Dormouse again took a minute or two to think about it, and -then said, `It was a treacle-well.' - - `There's no such thing!' Alice was beginning very angrily, but -the Hatter and the March Hare went `Sh! sh!' and the Dormouse -sulkily remarked, `If you can't be civil, you'd better finish the -story for yourself.' - - `No, please go on!' Alice said very humbly; `I won't interrupt -again. I dare say there may be ONE.' - - `One, indeed!' said the Dormouse indignantly. However, he -consented to go on. `And so these three little sisters--they -were learning to draw, you know--' - - `What did they draw?' said Alice, quite forgetting her promise. - - `Treacle,' said the Dormouse, without considering at all this -time. - - `I want a clean cup,' interrupted the Hatter: `let's all move -one place on.' - - He moved on as he spoke, and the Dormouse followed him: the -March Hare moved into the Dormouse's place, and Alice rather -unwillingly took the place of the March Hare. The Hatter was the -only one who got any advantage from the change: and Alice was a -good deal worse off than before, as the March Hare had just upset -the milk-jug into his plate. - - Alice did not wish to offend the Dormouse again, so she began -very cautiously: `But I don't understand. Where did they draw -the treacle from?' - - `You can draw water out of a water-well,' said the Hatter; `so -I should think you could draw treacle out of a treacle-well--eh, -stupid?' - - `But they were IN the well,' Alice said to the Dormouse, not -choosing to notice this last remark. - - `Of course they were', said the Dormouse; `--well in.' - - This answer so confused poor Alice, that she let the Dormouse -go on for some time without interrupting it. - - `They were learning to draw,' the Dormouse went on, yawning and -rubbing its eyes, for it was getting very sleepy; `and they drew -all manner of things--everything that begins with an M--' - - `Why with an M?' said Alice. - - `Why not?' said the March Hare. - - Alice was silent. - - The Dormouse had closed its eyes by this time, and was going -off into a doze; but, on being pinched by the Hatter, it woke up -again with a little shriek, and went on: `--that begins with an -M, such as mouse-traps, and the moon, and memory, and muchness-- -you know you say things are "much of a muchness"--did you ever -see such a thing as a drawing of a muchness?' - - `Really, now you ask me,' said Alice, very much confused, `I -don't think--' - - `Then you shouldn't talk,' said the Hatter. - - This piece of rudeness was more than Alice could bear: she got -up in great disgust, and walked off; the Dormouse fell asleep -instantly, and neither of the others took the least notice of her -going, though she looked back once or twice, half hoping that -they would call after her: the last time she saw them, they were -trying to put the Dormouse into the teapot. - - `At any rate I'll never go THERE again!' said Alice as she -picked her way through the wood. `It's the stupidest tea-party I -ever was at in all my life!' - - Just as she said this, she noticed that one of the trees had a -door leading right into it. `That's very curious!' she thought. -`But everything's curious today. I think I may as well go in at -once.' And in she went. - - Once more she found herself in the long hall, and close to the -little glass table. `Now, I'll manage better this time,' she -said to herself, and began by taking the little golden key, and -unlocking the door that led into the garden. Then she went to -work nibbling at the mushroom (she had kept a piece of it in her -pocked) till she was about a foot high: then she walked down the -little passage: and THEN--she found herself at last in the -beautiful garden, among the bright flower-beds and the cool -fountains. - - - - CHAPTER VIII - - The Queen's Croquet-Ground - - - A large rose-tree stood near the entrance of the garden: the -roses growing on it were white, but there were three gardeners at -it, busily painting them red. Alice thought this a very curious -thing, and she went nearer to watch them, and just as she came up -to them she heard one of them say, `Look out now, Five! Don't go -splashing paint over me like that!' - - `I couldn't help it,' said Five, in a sulky tone; `Seven jogged -my elbow.' - - On which Seven looked up and said, `That's right, Five! Always -lay the blame on others!' - - `YOU'D better not talk!' said Five. `I heard the Queen say only -yesterday you deserved to be beheaded!' - - `What for?' said the one who had spoken first. - - `That's none of YOUR business, Two!' said Seven. - - `Yes, it IS his business!' said Five, `and I'll tell him--it -was for bringing the cook tulip-roots instead of onions.' - - Seven flung down his brush, and had just begun `Well, of all -the unjust things--' when his eye chanced to fall upon Alice, as -she stood watching them, and he checked himself suddenly: the -others looked round also, and all of them bowed low. - - `Would you tell me,' said Alice, a little timidly, `why you are -painting those roses?' - - Five and Seven said nothing, but looked at Two. Two began in a -low voice, `Why the fact is, you see, Miss, this here ought to -have been a RED rose-tree, and we put a white one in by mistake; -and if the Queen was to find it out, we should all have our heads -cut off, you know. So you see, Miss, we're doing our best, afore -she comes, to--' At this moment Five, who had been anxiously -looking across the garden, called out `The Queen! The Queen!' -and the three gardeners instantly threw themselves flat upon -their faces. There was a sound of many footsteps, and Alice -looked round, eager to see the Queen. - - First came ten soldiers carrying clubs; these were all shaped -like the three gardeners, oblong and flat, with their hands and -feet at the corners: next the ten courtiers; these were -ornamented all over with diamonds, and walked two and two, as the -soldiers did. After these came the royal children; there were -ten of them, and the little dears came jumping merrily along hand -in hand, in couples: they were all ornamented with hearts. Next -came the guests, mostly Kings and Queens, and among them Alice -recognised the White Rabbit: it was talking in a hurried nervous -manner, smiling at everything that was said, and went by without -noticing her. Then followed the Knave of Hearts, carrying the -King's crown on a crimson velvet cushion; and, last of all this -grand procession, came THE KING AND QUEEN OF HEARTS. - - Alice was rather doubtful whether she ought not to lie down on -her face like the three gardeners, but she could not remember -every having heard of such a rule at processions; `and besides, -what would be the use of a procession,' thought she, `if people -had all to lie down upon their faces, so that they couldn't see -it?' So she stood still where she was, and waited. - - When the procession came opposite to Alice, they all stopped -and looked at her, and the Queen said severely `Who is this?' -She said it to the Knave of Hearts, who only bowed and smiled in -reply. - - `Idiot!' said the Queen, tossing her head impatiently; and, -turning to Alice, she went on, `What's your name, child?' - - `My name is Alice, so please your Majesty,' said Alice very -politely; but she added, to herself, `Why, they're only a pack of -cards, after all. I needn't be afraid of them!' - - `And who are THESE?' said the Queen, pointing to the three -gardeners who were lying round the rosetree; for, you see, as -they were lying on their faces, and the pattern on their backs -was the same as the rest of the pack, she could not tell whether -they were gardeners, or soldiers, or courtiers, or three of her -own children. - - `How should I know?' said Alice, surprised at her own courage. -`It's no business of MINE.' - - The Queen turned crimson with fury, and, after glaring at her -for a moment like a wild beast, screamed `Off with her head! -Off--' - - `Nonsense!' said Alice, very loudly and decidedly, and the -Queen was silent. - - The King laid his hand upon her arm, and timidly said -`Consider, my dear: she is only a child!' - - The Queen turned angrily away from him, and said to the Knave -`Turn them over!' - - The Knave did so, very carefully, with one foot. - - `Get up!' said the Queen, in a shrill, loud voice, and the -three gardeners instantly jumped up, and began bowing to the -King, the Queen, the royal children, and everybody else. - - `Leave off that!' screamed the Queen. `You make me giddy.' -And then, turning to the rose-tree, she went on, `What HAVE you -been doing here?' - - `May it please your Majesty,' said Two, in a very humble tone, -going down on one knee as he spoke, `we were trying--' - - `I see!' said the Queen, who had meanwhile been examining the -roses. `Off with their heads!' and the procession moved on, -three of the soldiers remaining behind to execute the unfortunate -gardeners, who ran to Alice for protection. - - `You shan't be beheaded!' said Alice, and she put them into a -large flower-pot that stood near. The three soldiers wandered -about for a minute or two, looking for them, and then quietly -marched off after the others. - - `Are their heads off?' shouted the Queen. - - `Their heads are gone, if it please your Majesty!' the soldiers -shouted in reply. - - `That's right!' shouted the Queen. `Can you play croquet?' - - The soldiers were silent, and looked at Alice, as the question -was evidently meant for her. - - `Yes!' shouted Alice. - - `Come on, then!' roared the Queen, and Alice joined the -procession, wondering very much what would happen next. - - `It's--it's a very fine day!' said a timid voice at her side. -She was walking by the White Rabbit, who was peeping anxiously -into her face. - - `Very,' said Alice: `--where's the Duchess?' - - `Hush! Hush!' said the Rabbit in a low, hurried tone. He -looked anxiously over his shoulder as he spoke, and then raised -himself upon tiptoe, put his mouth close to her ear, and -whispered `She's under sentence of execution.' - - `What for?' said Alice. - - `Did you say "What a pity!"?' the Rabbit asked. - - `No, I didn't,' said Alice: `I don't think it's at all a pity. -I said "What for?"' - - `She boxed the Queen's ears--' the Rabbit began. Alice gave a -little scream of laughter. `Oh, hush!' the Rabbit whispered in a -frightened tone. `The Queen will hear you! You see, she came -rather late, and the Queen said--' - - `Get to your places!' shouted the Queen in a voice of thunder, -and people began running about in all directions, tumbling up -against each other; however, they got settled down in a minute or -two, and the game began. Alice thought she had never seen such a -curious croquet-ground in her life; it was all ridges and -furrows; the balls were live hedgehogs, the mallets live -flamingoes, and the soldiers had to double themselves up and to -stand on their hands and feet, to make the arches. - - The chief difficulty Alice found at first was in managing her -flamingo: she succeeded in getting its body tucked away, -comfortably enough, under her arm, with its legs hanging down, -but generally, just as she had got its neck nicely straightened -out, and was going to give the hedgehog a blow with its head, it -WOULD twist itself round and look up in her face, with such a -puzzled expression that she could not help bursting out laughing: -and when she had got its head down, and was going to begin again, -it was very provoking to find that the hedgehog had unrolled -itself, and was in the act of crawling away: besides all this, -there was generally a ridge or furrow in the way wherever she -wanted to send the hedgehog to, and, as the doubled-up soldiers -were always getting up and walking off to other parts of the -ground, Alice soon came to the conclusion that it was a very -difficult game indeed. - - The players all played at once without waiting for turns, -quarrelling all the while, and fighting for the hedgehogs; and in -a very short time the Queen was in a furious passion, and went -stamping about, and shouting `Off with his head!' or `Off with -her head!' about once in a minute. - - Alice began to feel very uneasy: to be sure, she had not as -yet had any dispute with the Queen, but she knew that it might -happen any minute, `and then,' thought she, `what would become of -me? They're dreadfully fond of beheading people here; the great -wonder is, that there's any one left alive!' - - She was looking about for some way of escape, and wondering -whether she could get away without being seen, when she noticed a -curious appearance in the air: it puzzled her very much at -first, but, after watching it a minute or two, she made it out to -be a grin, and she said to herself `It's the Cheshire Cat: now I -shall have somebody to talk to.' - - `How are you getting on?' said the Cat, as soon as there was -mouth enough for it to speak with. - - Alice waited till the eyes appeared, and then nodded. `It's no -use speaking to it,' she thought, `till its ears have come, or at -least one of them.' In another minute the whole head appeared, -and then Alice put down her flamingo, and began an account of the -game, feeling very glad she had someone to listen to her. The -Cat seemed to think that there was enough of it now in sight, and -no more of it appeared. - - `I don't think they play at all fairly,' Alice began, in rather -a complaining tone, `and they all quarrel so dreadfully one can't -hear oneself speak--and they don't seem to have any rules in -particular; at least, if there are, nobody attends to them--and -you've no idea how confusing it is all the things being alive; -for instance, there's the arch I've got to go through next -walking about at the other end of the ground--and I should have -croqueted the Queen's hedgehog just now, only it ran away when it -saw mine coming!' - - `How do you like the Queen?' said the Cat in a low voice. - - `Not at all,' said Alice: `she's so extremely--' Just then -she noticed that the Queen was close behind her, listening: so -she went on, `--likely to win, that it's hardly worth while -finishing the game.' - - The Queen smiled and passed on. - - `Who ARE you talking to?' said the King, going up to Alice, and -looking at the Cat's head with great curiosity. - - `It's a friend of mine--a Cheshire Cat,' said Alice: `allow me -to introduce it.' - - `I don't like the look of it at all,' said the King: `however, -it may kiss my hand if it likes.' - - `I'd rather not,' the Cat remarked. - - `Don't be impertinent,' said the King, `and don't look at me -like that!' He got behind Alice as he spoke. - - `A cat may look at a king,' said Alice. `I've read that in -some book, but I don't remember where.' - - `Well, it must be removed,' said the King very decidedly, and -he called the Queen, who was passing at the moment, `My dear! I -wish you would have this cat removed!' - - The Queen had only one way of settling all difficulties, great -or small. `Off with his head!' she said, without even looking -round. - - `I'll fetch the executioner myself,' said the King eagerly, and -he hurried off. - - Alice thought she might as well go back, and see how the game -was going on, as she heard the Queen's voice in the distance, -screaming with passion. She had already heard her sentence three -of the players to be executed for having missed their turns, and -she did not like the look of things at all, as the game was in -such confusion that she never knew whether it was her turn or -not. So she went in search of her hedgehog. - - The hedgehog was engaged in a fight with another hedgehog, -which seemed to Alice an excellent opportunity for croqueting one -of them with the other: the only difficulty was, that her -flamingo was gone across to the other side of the garden, where -Alice could see it trying in a helpless sort of way to fly up -into a tree. - - By the time she had caught the flamingo and brought it back, -the fight was over, and both the hedgehogs were out of sight: -`but it doesn't matter much,' thought Alice, `as all the arches -are gone from this side of the ground.' So she tucked it away -under her arm, that it might not escape again, and went back for -a little more conversation with her friend. - - When she got back to the Cheshire Cat, she was surprised to -find quite a large crowd collected round it: there was a dispute -going on between the executioner, the King, and the Queen, who -were all talking at once, while all the rest were quite silent, -and looked very uncomfortable. - - The moment Alice appeared, she was appealed to by all three to -settle the question, and they repeated their arguments to her, -though, as they all spoke at once, she found it very hard indeed -to make out exactly what they said. - - The executioner's argument was, that you couldn't cut off a -head unless there was a body to cut it off from: that he had -never had to do such a thing before, and he wasn't going to begin -at HIS time of life. - - The King's argument was, that anything that had a head could be -beheaded, and that you weren't to talk nonsense. - - The Queen's argument was, that if something wasn't done about -it in less than no time she'd have everybody executed, all round. -(It was this last remark that had made the whole party look so -grave and anxious.) - - Alice could think of nothing else to say but `It belongs to the -Duchess: you'd better ask HER about it.' - - `She's in prison,' the Queen said to the executioner: `fetch -her here.' And the executioner went off like an arrow. - - The Cat's head began fading away the moment he was gone, and, -by the time he had come back with the Dutchess, it had entirely -disappeared; so the King and the executioner ran wildly up and -down looking for it, while the rest of the party went back to the game. - - - - CHAPTER IX - - The Mock Turtle's Story - - - `You can't think how glad I am to see you again, you dear old -thing!' said the Duchess, as she tucked her arm affectionately -into Alice's, and they walked off together. - - Alice was very glad to find her in such a pleasant temper, and -thought to herself that perhaps it was only the pepper that had -made her so savage when they met in the kitchen. - - `When I'M a Duchess,' she said to herself, (not in a very -hopeful tone though), `I won't have any pepper in my kitchen AT -ALL. Soup does very well without--Maybe it's always pepper that -makes people hot-tempered,' she went on, very much pleased at -having found out a new kind of rule, `and vinegar that makes them -sour--and camomile that makes them bitter--and--and barley-sugar -and such things that make children sweet-tempered. I only wish -people knew that: then they wouldn't be so stingy about it, you -know--' - - She had quite forgotten the Duchess by this time, and was a -little startled when she heard her voice close to her ear. -`You're thinking about something, my dear, and that makes you -forget to talk. I can't tell you just now what the moral of that -is, but I shall remember it in a bit.' - - `Perhaps it hasn't one,' Alice ventured to remark. - - `Tut, tut, child!' said the Duchess. `Everything's got a -moral, if only you can find it.' And she squeezed herself up -closer to Alice's side as she spoke. - - Alice did not much like keeping so close to her: first, -because the Duchess was VERY ugly; and secondly, because she was -exactly the right height to rest her chin upon Alice's shoulder, -and it was an uncomfortably sharp chin. However, she did not -like to be rude, so she bore it as well as she could. - - `The game's going on rather better now,' she said, by way of -keeping up the conversation a little. - - `'Tis so,' said the Duchess: `and the moral of that is--"Oh, -'tis love, 'tis love, that makes the world go round!"' - - `Somebody said,' Alice whispered, `that it's done by everybody -minding their own business!' - - `Ah, well! It means much the same thing,' said the Duchess, -digging her sharp little chin into Alice's shoulder as she added, -`and the moral of THAT is--"Take care of the sense, and the -sounds will take care of themselves."' - - `How fond she is of finding morals in things!' Alice thought to -herself. - - `I dare say you're wondering why I don't put my arm round your -waist,' the Duchess said after a pause: `the reason is, that I'm -doubtful about the temper of your flamingo. Shall I try the -experiment?' - - `HE might bite,' Alice cautiously replied, not feeling at all -anxious to have the experiment tried. - - `Very true,' said the Duchess: `flamingoes and mustard both -bite. And the moral of that is--"Birds of a feather flock -together."' - - `Only mustard isn't a bird,' Alice remarked. - - `Right, as usual,' said the Duchess: `what a clear way you -have of putting things!' - - `It's a mineral, I THINK,' said Alice. - - `Of course it is,' said the Duchess, who seemed ready to agree -to everything that Alice said; `there's a large mustard-mine near -here. And the moral of that is--"The more there is of mine, the -less there is of yours."' - - `Oh, I know!' exclaimed Alice, who had not attended to this -last remark, `it's a vegetable. It doesn't look like one, but it -is.' - - `I quite agree with you,' said the Duchess; `and the moral of -that is--"Be what you would seem to be"--or if you'd like it put -more simply--"Never imagine yourself not to be otherwise than -what it might appear to others that what you were or might have -been was not otherwise than what you had been would have appeared -to them to be otherwise."' - - `I think I should understand that better,' Alice said very -politely, `if I had it written down: but I can't quite follow it -as you say it.' - - `That's nothing to what I could say if I chose,' the Duchess -replied, in a pleased tone. - - `Pray don't trouble yourself to say it any longer than that,' -said Alice. - - `Oh, don't talk about trouble!' said the Duchess. `I make you -a present of everything I've said as yet.' - - `A cheap sort of present!' thought Alice. `I'm glad they don't -give birthday presents like that!' But she did not venture to -say it out loud. - - `Thinking again?' the Duchess asked, with another dig of her -sharp little chin. - - `I've a right to think,' said Alice sharply, for she was -beginning to feel a little worried. - - `Just about as much right,' said the Duchess, `as pigs have to -fly; and the m--' - - But here, to Alice's great surprise, the Duchess's voice died -away, even in the middle of her favourite word `moral,' and the -arm that was linked into hers began to tremble. Alice looked up, -and there stood the Queen in front of them, with her arms folded, -frowning like a thunderstorm. - - `A fine day, your Majesty!' the Duchess began in a low, weak -voice. - - `Now, I give you fair warning,' shouted the Queen, stamping on -the ground as she spoke; `either you or your head must be off, -and that in about half no time! Take your choice!' - - The Duchess took her choice, and was gone in a moment. - - `Let's go on with the game,' the Queen said to Alice; and Alice -was too much frightened to say a word, but slowly followed her -back to the croquet-ground. - - The other guests had taken advantage of the Queen's absence, -and were resting in the shade: however, the moment they saw her, -they hurried back to the game, the Queen merely remarking that a -moment's delay would cost them their lives. - - All the time they were playing the Queen never left off -quarrelling with the other players, and shouting `Off with his -head!' or `Off with her head!' Those whom she sentenced were -taken into custody by the soldiers, who of course had to leave -off being arches to do this, so that by the end of half an hour -or so there were no arches left, and all the players, except the -King, the Queen, and Alice, were in custody and under sentence of -execution. - - Then the Queen left off, quite out of breath, and said to -Alice, `Have you seen the Mock Turtle yet?' - - `No,' said Alice. `I don't even know what a Mock Turtle is.' - - `It's the thing Mock Turtle Soup is made from,' said the Queen. - - `I never saw one, or heard of one,' said Alice. - - `Come on, then,' said the Queen, `and he shall tell you his -history,' - - As they walked off together, Alice heard the King say in a low -voice, to the company generally, `You are all pardoned.' `Come, -THAT'S a good thing!' she said to herself, for she had felt quite -unhappy at the number of executions the Queen had ordered. - - They very soon came upon a Gryphon, lying fast asleep in the -sun. (IF you don't know what a Gryphon is, look at the picture.) -`Up, lazy thing!' said the Queen, `and take this young lady to -see the Mock Turtle, and to hear his history. I must go back and -see after some executions I have ordered'; and she walked off, -leaving Alice alone with the Gryphon. Alice did not quite like -the look of the creature, but on the whole she thought it would -be quite as safe to stay with it as to go after that savage -Queen: so she waited. - - The Gryphon sat up and rubbed its eyes: then it watched the -Queen till she was out of sight: then it chuckled. `What fun!' -said the Gryphon, half to itself, half to Alice. - - `What IS the fun?' said Alice. - - `Why, SHE,' said the Gryphon. `It's all her fancy, that: they -never executes nobody, you know. Come on!' - - `Everybody says "come on!" here,' thought Alice, as she went -slowly after it: `I never was so ordered about in all my life, -never!' - - They had not gone far before they saw the Mock Turtle in the -distance, sitting sad and lonely on a little ledge of rock, and, -as they came nearer, Alice could hear him sighing as if his heart -would break. She pitied him deeply. `What is his sorrow?' she -asked the Gryphon, and the Gryphon answered, very nearly in the -same words as before, `It's all his fancy, that: he hasn't got -no sorrow, you know. Come on!' - - So they went up to the Mock Turtle, who looked at them with -large eyes full of tears, but said nothing. - - `This here young lady,' said the Gryphon, `she wants for to -know your history, she do.' - - `I'll tell it her,' said the Mock Turtle in a deep, hollow -tone: `sit down, both of you, and don't speak a word till I've -finished.' - - So they sat down, and nobody spoke for some minutes. Alice -thought to herself, `I don't see how he can EVEN finish, if he -doesn't begin.' But she waited patiently. - - `Once,' said the Mock Turtle at last, with a deep sigh, `I was -a real Turtle.' - - These words were followed by a very long silence, broken only -by an occasional exclamation of `Hjckrrh!' from the Gryphon, and -the constant heavy sobbing of the Mock Turtle. Alice was very -nearly getting up and saying, `Thank you, sir, for your -interesting story,' but she could not help thinking there MUST be -more to come, so she sat still and said nothing. - - `When we were little,' the Mock Turtle went on at last, more -calmly, though still sobbing a little now and then, `we went to -school in the sea. The master was an old Turtle--we used to call -him Tortoise--' - - `Why did you call him Tortoise, if he wasn't one?' Alice asked. - - `We called him Tortoise because he taught us,' said the Mock -Turtle angrily: `really you are very dull!' - - `You ought to be ashamed of yourself for asking such a simple -question,' added the Gryphon; and then they both sat silent and -looked at poor Alice, who felt ready to sink into the earth. At -last the Gryphon said to the Mock Turtle, `Drive on, old fellow! -Don't be all day about it!' and he went on in these words: - - `Yes, we went to school in the sea, though you mayn't believe -it--' - - `I never said I didn't!' interrupted Alice. - - `You did,' said the Mock Turtle. - - `Hold your tongue!' added the Gryphon, before Alice could speak -again. The Mock Turtle went on. - - `We had the best of educations--in fact, we went to school -every day--' - - `I'VE been to a day-school, too,' said Alice; `you needn't be -so proud as all that.' - - `With extras?' asked the Mock Turtle a little anxiously. - - `Yes,' said Alice, `we learned French and music.' - - `And washing?' said the Mock Turtle. - - `Certainly not!' said Alice indignantly. - - `Ah! then yours wasn't a really good school,' said the Mock -Turtle in a tone of great relief. `Now at OURS they had at the -end of the bill, "French, music, AND WASHING--extra."' - - `You couldn't have wanted it much,' said Alice; `living at the -bottom of the sea.' - - `I couldn't afford to learn it.' said the Mock Turtle with a -sigh. `I only took the regular course.' - - `What was that?' inquired Alice. - - `Reeling and Writhing, of course, to begin with,' the Mock -Turtle replied; `and then the different branches of Arithmetic-- -Ambition, Distraction, Uglification, and Derision.' - - `I never heard of "Uglification,"' Alice ventured to say. `What -is it?' - - The Gryphon lifted up both its paws in surprise. `What! Never -heard of uglifying!' it exclaimed. `You know what to beautify -is, I suppose?' - - `Yes,' said Alice doubtfully: `it means--to--make--anything-- -prettier.' - - `Well, then,' the Gryphon went on, `if you don't know what to -uglify is, you ARE a simpleton.' - - Alice did not feel encouraged to ask any more questions about -it, so she turned to the Mock Turtle, and said `What else had you -to learn?' - - `Well, there was Mystery,' the Mock Turtle replied, counting -off the subjects on his flappers, `--Mystery, ancient and modern, -with Seaography: then Drawling--the Drawling-master was an old -conger-eel, that used to come once a week: HE taught us -Drawling, Stretching, and Fainting in Coils.' - - `What was THAT like?' said Alice. - - `Well, I can't show it you myself,' the Mock Turtle said: `I'm -too stiff. And the Gryphon never learnt it.' - - `Hadn't time,' said the Gryphon: `I went to the Classics -master, though. He was an old crab, HE was.' - - `I never went to him,' the Mock Turtle said with a sigh: `he -taught Laughing and Grief, they used to say.' - - `So he did, so he did,' said the Gryphon, sighing in his turn; -and both creatures hid their faces in their paws. - - `And how many hours a day did you do lessons?' said Alice, in a -hurry to change the subject. - - `Ten hours the first day,' said the Mock Turtle: `nine the -next, and so on.' - - `What a curious plan!' exclaimed Alice. - - `That's the reason they're called lessons,' the Gryphon -remarked: `because they lessen from day to day.' - - This was quite a new idea to Alice, and she thought it over a -little before she made her next remark. `Then the eleventh day -must have been a holiday?' - - `Of course it was,' said the Mock Turtle. - - `And how did you manage on the twelfth?' Alice went on eagerly. - - `That's enough about lessons,' the Gryphon interrupted in a -very decided tone: `tell her something about the games now.' - - - - CHAPTER X - - The Lobster Quadrille - - - The Mock Turtle sighed deeply, and drew the back of one flapper -across his eyes. He looked at Alice, and tried to speak, but for -a minute or two sobs choked his voice. `Same as if he had a bone -in his throat,' said the Gryphon: and it set to work shaking him -and punching him in the back. At last the Mock Turtle recovered -his voice, and, with tears running down his cheeks, he went on -again:-- - - `You may not have lived much under the sea--' (`I haven't,' -said Alice)--`and perhaps you were never even introduced to a lobster--' -(Alice began to say `I once tasted--' but checked herself hastily, -and said `No, never') `--so you can have no idea what a delightful -thing a Lobster Quadrille is!' - - `No, indeed,' said Alice. `What sort of a dance is it?' - - `Why,' said the Gryphon, `you first form into a line along the -sea-shore--' - - `Two lines!' cried the Mock Turtle. `Seals, turtles, salmon, -and so on; then, when you've cleared all the jelly-fish out of -the way--' - - `THAT generally takes some time,' interrupted the Gryphon. - - `--you advance twice--' - - `Each with a lobster as a partner!' cried the Gryphon. - - `Of course,' the Mock Turtle said: `advance twice, set to -partners--' - - `--change lobsters, and retire in same order,' continued the -Gryphon. - - `Then, you know,' the Mock Turtle went on, `you throw the--' - - `The lobsters!' shouted the Gryphon, with a bound into the air. - - `--as far out to sea as you can--' - - `Swim after them!' screamed the Gryphon. - - `Turn a somersault in the sea!' cried the Mock Turtle, -capering wildly about. - - `Back to land again, and that's all the first figure,' said the -Mock Turtle, suddenly dropping his voice; and the two creatures, -who had been jumping about like mad things all this time, sat -down again very sadly and quietly, and looked at Alice. - - `It must be a very pretty dance,' said Alice timidly. - - `Would you like to see a little of it?' said the Mock Turtle. - - `Very much indeed,' said Alice. - - `Come, let's try the first figure!' said the Mock Turtle to the -Gryphon. `We can do without lobsters, you know. Which shall -sing?' - - `Oh, YOU sing,' said the Gryphon. `I've forgotten the words.' - - So they began solemnly dancing round and round Alice, every now -and then treading on her toes when they passed too close, and -waving their forepaws to mark the time, while the Mock Turtle -sang this, very slowly and sadly:-- - - -`"Will you walk a little faster?" said a whiting to a snail. -"There's a porpoise close behind us, and he's treading on my - tail. -See how eagerly the lobsters and the turtles all advance! -They are waiting on the shingle--will you come and join the -dance? - -Will you, won't you, will you, won't you, will you join the -dance? -Will you, won't you, will you, won't you, won't you join the -dance? - - -"You can really have no notion how delightful it will be -When they take us up and throw us, with the lobsters, out to - sea!" -But the snail replied "Too far, too far!" and gave a look - askance-- -Said he thanked the whiting kindly, but he would not join the - dance. - Would not, could not, would not, could not, would not join - the dance. - Would not, could not, would not, could not, could not join - the dance. - -`"What matters it how far we go?" his scaly friend replied. -"There is another shore, you know, upon the other side. -The further off from England the nearer is to France-- -Then turn not pale, beloved snail, but come and join the dance. - - Will you, won't you, will you, won't you, will you join the - dance? - Will you, won't you, will you, won't you, won't you join the - dance?"' - - - - `Thank you, it's a very interesting dance to watch,' said -Alice, feeling very glad that it was over at last: `and I do so -like that curious song about the whiting!' - - `Oh, as to the whiting,' said the Mock Turtle, `they--you've -seen them, of course?' - - `Yes,' said Alice, `I've often seen them at dinn--' she -checked herself hastily. - - `I don't know where Dinn may be,' said the Mock Turtle, `but -if you've seen them so often, of course you know what they're -like.' - - `I believe so,' Alice replied thoughtfully. `They have their -tails in their mouths--and they're all over crumbs.' - - `You're wrong about the crumbs,' said the Mock Turtle: -`crumbs would all wash off in the sea. But they HAVE their tails -in their mouths; and the reason is--' here the Mock Turtle -yawned and shut his eyes.--`Tell her about the reason and all -that,' he said to the Gryphon. - - `The reason is,' said the Gryphon, `that they WOULD go with -the lobsters to the dance. So they got thrown out to sea. So -they had to fall a long way. So they got their tails fast in -their mouths. So they couldn't get them out again. That's all.' - - `Thank you,' said Alice, `it's very interesting. I never knew -so much about a whiting before.' - - `I can tell you more than that, if you like,' said the -Gryphon. `Do you know why it's called a whiting?' - - `I never thought about it,' said Alice. `Why?' - - `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very -solemnly. - - Alice was thoroughly puzzled. `Does the boots and shoes!' she -repeated in a wondering tone. - - `Why, what are YOUR shoes done with?' said the Gryphon. `I -mean, what makes them so shiny?' - - Alice looked down at them, and considered a little before she -gave her answer. `They're done with blacking, I believe.' - - `Boots and shoes under the sea,' the Gryphon went on in a deep -voice, `are done with a whiting. Now you know.' - - `And what are they made of?' Alice asked in a tone of great -curiosity. - - `Soles and eels, of course,' the Gryphon replied rather -impatiently: `any shrimp could have told you that.' - - `If I'd been the whiting,' said Alice, whose thoughts were -still running on the song, `I'd have said to the porpoise, "Keep -back, please: we don't want YOU with us!"' - - `They were obliged to have him with them,' the Mock Turtle -said: `no wise fish would go anywhere without a porpoise.' - - `Wouldn't it really?' said Alice in a tone of great surprise. - - `Of course not,' said the Mock Turtle: `why, if a fish came -to ME, and told me he was going a journey, I should say "With -what porpoise?"' - - `Don't you mean "purpose"?' said Alice. - - `I mean what I say,' the Mock Turtle replied in an offended -tone. And the Gryphon added `Come, let's hear some of YOUR -adventures.' - - `I could tell you my adventures--beginning from this morning,' -said Alice a little timidly: `but it's no use going back to -yesterday, because I was a different person then.' - - `Explain all that,' said the Mock Turtle. - - `No, no! The adventures first,' said the Gryphon in an -impatient tone: `explanations take such a dreadful time.' - - So Alice began telling them her adventures from the time when -she first saw the White Rabbit. She was a little nervous about -it just at first, the two creatures got so close to her, one on -each side, and opened their eyes and mouths so VERY wide, but she -gained courage as she went on. Her listeners were perfectly -quiet till she got to the part about her repeating `YOU ARE OLD, -FATHER WILLIAM,' to the Caterpillar, and the words all coming -different, and then the Mock Turtle drew a long breath, and said -`That's very curious.' - - `It's all about as curious as it can be,' said the Gryphon. - - `It all came different!' the Mock Turtle repeated -thoughtfully. `I should like to hear her try and repeat -something now. Tell her to begin.' He looked at the Gryphon as -if he thought it had some kind of authority over Alice. - - `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said -the Gryphon. - - `How the creatures order one about, and make one repeat -lessons!' thought Alice; `I might as well be at school at once.' -However, she got up, and began to repeat it, but her head was so -full of the Lobster Quadrille, that she hardly knew what she was -saying, and the words came very queer indeed:-- - - `'Tis the voice of the Lobster; I heard him declare, - "You have baked me too brown, I must sugar my hair." - As a duck with its eyelids, so he with his nose - Trims his belt and his buttons, and turns out his toes.' - - [later editions continued as follows - When the sands are all dry, he is gay as a lark, - And will talk in contemptuous tones of the Shark, - But, when the tide rises and sharks are around, - His voice has a timid and tremulous sound.] - - `That's different from what I used to say when I was a child,' -said the Gryphon. - - `Well, I never heard it before,' said the Mock Turtle; `but it -sounds uncommon nonsense.' - - Alice said nothing; she had sat down with her face in her -hands, wondering if anything would EVER happen in a natural way -again. - - `I should like to have it explained,' said the Mock Turtle. - - `She can't explain it,' said the Gryphon hastily. `Go on with -the next verse.' - - `But about his toes?' the Mock Turtle persisted. `How COULD -he turn them out with his nose, you know?' - - `It's the first position in dancing.' Alice said; but was -dreadfully puzzled by the whole thing, and longed to change the -subject. - - `Go on with the next verse,' the Gryphon repeated impatiently: -`it begins "I passed by his garden."' - - Alice did not dare to disobey, though she felt sure it would -all come wrong, and she went on in a trembling voice:-- - - `I passed by his garden, and marked, with one eye, - How the Owl and the Panther were sharing a pie--' - - [later editions continued as follows - The Panther took pie-crust, and gravy, and meat, - While the Owl had the dish as its share of the treat. - When the pie was all finished, the Owl, as a boon, - Was kindly permitted to pocket the spoon: - While the Panther received knife and fork with a growl, - And concluded the banquet--] - - `What IS the use of repeating all that stuff,' the Mock Turtle -interrupted, `if you don't explain it as you go on? It's by far -the most confusing thing I ever heard!' - - `Yes, I think you'd better leave off,' said the Gryphon: and -Alice was only too glad to do so. - - `Shall we try another figure of the Lobster Quadrille?' the -Gryphon went on. `Or would you like the Mock Turtle to sing you -a song?' - - `Oh, a song, please, if the Mock Turtle would be so kind,' -Alice replied, so eagerly that the Gryphon said, in a rather -offended tone, `Hm! No accounting for tastes! Sing her "Turtle -Soup," will you, old fellow?' - - The Mock Turtle sighed deeply, and began, in a voice sometimes -choked with sobs, to sing this:-- - - - `Beautiful Soup, so rich and green, - Waiting in a hot tureen! - Who for such dainties would not stoop? - Soup of the evening, beautiful Soup! - Soup of the evening, beautiful Soup! - Beau--ootiful Soo--oop! - Beau--ootiful Soo--oop! - Soo--oop of the e--e--evening, - Beautiful, beautiful Soup! - - `Beautiful Soup! Who cares for fish, - Game, or any other dish? - Who would not give all else for two p - ennyworth only of beautiful Soup? - Pennyworth only of beautiful Soup? - Beau--ootiful Soo--oop! - Beau--ootiful Soo--oop! - Soo--oop of the e--e--evening, - Beautiful, beauti--FUL SOUP!' - - `Chorus again!' cried the Gryphon, and the Mock Turtle had -just begun to repeat it, when a cry of `The trial's beginning!' -was heard in the distance. - - `Come on!' cried the Gryphon, and, taking Alice by the hand, -it hurried off, without waiting for the end of the song. - - `What trial is it?' Alice panted as she ran; but the Gryphon -only answered `Come on!' and ran the faster, while more and more -faintly came, carried on the breeze that followed them, the -melancholy words:-- - - `Soo--oop of the e--e--evening, - Beautiful, beautiful Soup!' - - - - CHAPTER XI - - Who Stole the Tarts? - - - The King and Queen of Hearts were seated on their throne when -they arrived, with a great crowd assembled about them--all sorts -of little birds and beasts, as well as the whole pack of cards: -the Knave was standing before them, in chains, with a soldier on -each side to guard him; and near the King was the White Rabbit, -with a trumpet in one hand, and a scroll of parchment in the -other. In the very middle of the court was a table, with a large -dish of tarts upon it: they looked so good, that it made Alice -quite hungry to look at them--`I wish they'd get the trial done,' -she thought, `and hand round the refreshments!' But there seemed -to be no chance of this, so she began looking at everything about -her, to pass away the time. - - Alice had never been in a court of justice before, but she had -read about them in books, and she was quite pleased to find that -she knew the name of nearly everything there. `That's the -judge,' she said to herself, `because of his great wig.' - - The judge, by the way, was the King; and as he wore his crown -over the wig, (look at the frontispiece if you want to see how he -did it,) he did not look at all comfortable, and it was certainly -not becoming. - - `And that's the jury-box,' thought Alice, `and those twelve -creatures,' (she was obliged to say `creatures,' you see, because -some of them were animals, and some were birds,) `I suppose they -are the jurors.' She said this last word two or three times over -to herself, being rather proud of it: for she thought, and -rightly too, that very few little girls of her age knew the -meaning of it at all. However, `jury-men' would have done just -as well. - - The twelve jurors were all writing very busily on slates. -`What are they doing?' Alice whispered to the Gryphon. `They -can't have anything to put down yet, before the trial's begun.' - - `They're putting down their names,' the Gryphon whispered in -reply, `for fear they should forget them before the end of the -trial.' - - `Stupid things!' Alice began in a loud, indignant voice, but -she stopped hastily, for the White Rabbit cried out, `Silence in -the court!' and the King put on his spectacles and looked -anxiously round, to make out who was talking. - - Alice could see, as well as if she were looking over their -shoulders, that all the jurors were writing down `stupid things!' -on their slates, and she could even make out that one of them -didn't know how to spell `stupid,' and that he had to ask his -neighbour to tell him. `A nice muddle their slates'll be in -before the trial's over!' thought Alice. - - One of the jurors had a pencil that squeaked. This of course, -Alice could not stand, and she went round the court and got -behind him, and very soon found an opportunity of taking it -away. She did it so quickly that the poor little juror (it was -Bill, the Lizard) could not make out at all what had become of -it; so, after hunting all about for it, he was obliged to write -with one finger for the rest of the day; and this was of very -little use, as it left no mark on the slate. - - `Herald, read the accusation!' said the King. - - On this the White Rabbit blew three blasts on the trumpet, and -then unrolled the parchment scroll, and read as follows:-- - - `The Queen of Hearts, she made some tarts, - All on a summer day: - The Knave of Hearts, he stole those tarts, - And took them quite away!' - - `Consider your verdict,' the King said to the jury. - - `Not yet, not yet!' the Rabbit hastily interrupted. `There's -a great deal to come before that!' - - `Call the first witness,' said the King; and the White Rabbit -blew three blasts on the trumpet, and called out, `First -witness!' - - The first witness was the Hatter. He came in with a teacup in -one hand and a piece of bread-and-butter in the other. `I beg -pardon, your Majesty,' he began, `for bringing these in: but I -hadn't quite finished my tea when I was sent for.' - - `You ought to have finished,' said the King. `When did you -begin?' - - The Hatter looked at the March Hare, who had followed him into -the court, arm-in-arm with the Dormouse. `Fourteenth of March, I -think it was,' he said. - - `Fifteenth,' said the March Hare. - - `Sixteenth,' added the Dormouse. - - `Write that down,' the King said to the jury, and the jury -eagerly wrote down all three dates on their slates, and then -added them up, and reduced the answer to shillings and pence. - - `Take off your hat,' the King said to the Hatter. - - `It isn't mine,' said the Hatter. - - `Stolen!' the King exclaimed, turning to the jury, who -instantly made a memorandum of the fact. - - `I keep them to sell,' the Hatter added as an explanation; -`I've none of my own. I'm a hatter.' - - Here the Queen put on her spectacles, and began staring at the -Hatter, who turned pale and fidgeted. - - `Give your evidence,' said the King; `and don't be nervous, or -I'll have you executed on the spot.' - - This did not seem to encourage the witness at all: he kept -shifting from one foot to the other, looking uneasily at the -Queen, and in his confusion he bit a large piece out of his -teacup instead of the bread-and-butter. - - Just at this moment Alice felt a very curious sensation, which -puzzled her a good deal until she made out what it was: she was -beginning to grow larger again, and she thought at first she -would get up and leave the court; but on second thoughts she -decided to remain where she was as long as there was room for -her. - - `I wish you wouldn't squeeze so.' said the Dormouse, who was -sitting next to her. `I can hardly breathe.' - - `I can't help it,' said Alice very meekly: `I'm growing.' - - `You've no right to grow here,' said the Dormouse. - - `Don't talk nonsense,' said Alice more boldly: `you know -you're growing too.' - - `Yes, but I grow at a reasonable pace,' said the Dormouse: -`not in that ridiculous fashion.' And he got up very sulkily -and crossed over to the other side of the court. - - All this time the Queen had never left off staring at the -Hatter, and, just as the Dormouse crossed the court, she said to -one of the officers of the court, `Bring me the list of the -singers in the last concert!' on which the wretched Hatter -trembled so, that he shook both his shoes off. - - `Give your evidence,' the King repeated angrily, `or I'll have -you executed, whether you're nervous or not.' - - `I'm a poor man, your Majesty,' the Hatter began, in a -trembling voice, `--and I hadn't begun my tea--not above a week -or so--and what with the bread-and-butter getting so thin--and -the twinkling of the tea--' - - `The twinkling of the what?' said the King. - - `It began with the tea,' the Hatter replied. - - `Of course twinkling begins with a T!' said the King sharply. -`Do you take me for a dunce? Go on!' - - `I'm a poor man,' the Hatter went on, `and most things -twinkled after that--only the March Hare said--' - - `I didn't!' the March Hare interrupted in a great hurry. - - `You did!' said the Hatter. - - `I deny it!' said the March Hare. - - `He denies it,' said the King: `leave out that part.' - - `Well, at any rate, the Dormouse said--' the Hatter went on, -looking anxiously round to see if he would deny it too: but the -Dormouse denied nothing, being fast asleep. - - `After that,' continued the Hatter, `I cut some more bread- -and-butter--' - - `But what did the Dormouse say?' one of the jury asked. - - `That I can't remember,' said the Hatter. - - `You MUST remember,' remarked the King, `or I'll have you -executed.' - - The miserable Hatter dropped his teacup and bread-and-butter, -and went down on one knee. `I'm a poor man, your Majesty,' he -began. - - `You're a very poor speaker,' said the King. - - Here one of the guinea-pigs cheered, and was immediately -suppressed by the officers of the court. (As that is rather a -hard word, I will just explain to you how it was done. They had -a large canvas bag, which tied up at the mouth with strings: -into this they slipped the guinea-pig, head first, and then sat -upon it.) - - `I'm glad I've seen that done,' thought Alice. `I've so often -read in the newspapers, at the end of trials, "There was some -attempts at applause, which was immediately suppressed by the -officers of the court," and I never understood what it meant -till now.' - - `If that's all you know about it, you may stand down,' -continued the King. - - `I can't go no lower,' said the Hatter: `I'm on the floor, as -it is.' - - `Then you may SIT down,' the King replied. - - Here the other guinea-pig cheered, and was suppressed. - - `Come, that finished the guinea-pigs!' thought Alice. `Now we -shall get on better.' - - `I'd rather finish my tea,' said the Hatter, with an anxious -look at the Queen, who was reading the list of singers. - - `You may go,' said the King, and the Hatter hurriedly left the -court, without even waiting to put his shoes on. - - `--and just take his head off outside,' the Queen added to one -of the officers: but the Hatter was out of sight before the -officer could get to the door. - - `Call the next witness!' said the King. - - The next witness was the Duchess's cook. She carried the -pepper-box in her hand, and Alice guessed who it was, even before -she got into the court, by the way the people near the door began -sneezing all at once. - - `Give your evidence,' said the King. - - `Shan't,' said the cook. - - The King looked anxiously at the White Rabbit, who said in a -low voice, `Your Majesty must cross-examine THIS witness.' - - `Well, if I must, I must,' the King said, with a melancholy -air, and, after folding his arms and frowning at the cook till -his eyes were nearly out of sight, he said in a deep voice, `What -are tarts made of?' - - `Pepper, mostly,' said the cook. - - `Treacle,' said a sleepy voice behind her. - - `Collar that Dormouse,' the Queen shrieked out. `Behead that -Dormouse! Turn that Dormouse out of court! Suppress him! Pinch -him! Off with his whiskers!' - - For some minutes the whole court was in confusion, getting the -Dormouse turned out, and, by the time they had settled down -again, the cook had disappeared. - - `Never mind!' said the King, with an air of great relief. -`Call the next witness.' And he added in an undertone to the -Queen, `Really, my dear, YOU must cross-examine the next witness. -It quite makes my forehead ache!' - - Alice watched the White Rabbit as he fumbled over the list, -feeling very curious to see what the next witness would be like, -`--for they haven't got much evidence YET,' she said to herself. -Imagine her surprise, when the White Rabbit read out, at the top -of his shrill little voice, the name `Alice!' - - - - CHAPTER XII - - Alice's Evidence - - - `Here!' cried Alice, quite forgetting in the flurry of the -moment how large she had grown in the last few minutes, and she -jumped up in such a hurry that she tipped over the jury-box with -the edge of her skirt, upsetting all the jurymen on to the heads -of the crowd below, and there they lay sprawling about, reminding -her very much of a globe of goldfish she had accidentally upset -the week before. - - `Oh, I BEG your pardon!' she exclaimed in a tone of great -dismay, and began picking them up again as quickly as she could, -for the accident of the goldfish kept running in her head, and -she had a vague sort of idea that they must be collected at once -and put back into the jury-box, or they would die. - - `The trial cannot proceed,' said the King in a very grave -voice, `until all the jurymen are back in their proper places-- -ALL,' he repeated with great emphasis, looking hard at Alice as -he said do. - - Alice looked at the jury-box, and saw that, in her haste, she -had put the Lizard in head downwards, and the poor little thing -was waving its tail about in a melancholy way, being quite unable -to move. She soon got it out again, and put it right; `not that -it signifies much,' she said to herself; `I should think it -would be QUITE as much use in the trial one way up as the other.' - - As soon as the jury had a little recovered from the shock of -being upset, and their slates and pencils had been found and -handed back to them, they set to work very diligently to write -out a history of the accident, all except the Lizard, who seemed -too much overcome to do anything but sit with its mouth open, -gazing up into the roof of the court. - - `What do you know about this business?' the King said to -Alice. - - `Nothing,' said Alice. - - `Nothing WHATEVER?' persisted the King. - - `Nothing whatever,' said Alice. - - `That's very important,' the King said, turning to the jury. -They were just beginning to write this down on their slates, when -the White Rabbit interrupted: `UNimportant, your Majesty means, -of course,' he said in a very respectful tone, but frowning and -making faces at him as he spoke. - - `UNimportant, of course, I meant,' the King hastily said, and -went on to himself in an undertone, `important--unimportant-- -unimportant--important--' as if he were trying which word -sounded best. - - Some of the jury wrote it down `important,' and some -`unimportant.' Alice could see this, as she was near enough to -look over their slates; `but it doesn't matter a bit,' she -thought to herself. - - At this moment the King, who had been for some time busily -writing in his note-book, cackled out `Silence!' and read out -from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE -HIGH TO LEAVE THE COURT.' - - Everybody looked at Alice. - - `I'M not a mile high,' said Alice. - - `You are,' said the King. - - `Nearly two miles high,' added the Queen. - - `Well, I shan't go, at any rate,' said Alice: `besides, -that's not a regular rule: you invented it just now.' - - `It's the oldest rule in the book,' said the King. - - `Then it ought to be Number One,' said Alice. - - The King turned pale, and shut his note-book hastily. -`Consider your verdict,' he said to the jury, in a low, trembling -voice. - - `There's more evidence to come yet, please your Majesty,' said -the White Rabbit, jumping up in a great hurry; `this paper has -just been picked up.' - - `What's in it?' said the Queen. - - `I haven't opened it yet,' said the White Rabbit, `but it seems -to be a letter, written by the prisoner to--to somebody.' - - `It must have been that,' said the King, `unless it was -written to nobody, which isn't usual, you know.' - - `Who is it directed to?' said one of the jurymen. - - `It isn't directed at all,' said the White Rabbit; `in fact, -there's nothing written on the OUTSIDE.' He unfolded the paper -as he spoke, and added `It isn't a letter, after all: it's a set -of verses.' - - `Are they in the prisoner's handwriting?' asked another of -they jurymen. - - `No, they're not,' said the White Rabbit, `and that's the -queerest thing about it.' (The jury all looked puzzled.) - - `He must have imitated somebody else's hand,' said the King. -(The jury all brightened up again.) - - `Please your Majesty,' said the Knave, `I didn't write it, and -they can't prove I did: there's no name signed at the end.' - - `If you didn't sign it,' said the King, `that only makes the -matter worse. You MUST have meant some mischief, or else you'd -have signed your name like an honest man.' - - There was a general clapping of hands at this: it was the -first really clever thing the King had said that day. - - `That PROVES his guilt,' said the Queen. - - `It proves nothing of the sort!' said Alice. `Why, you don't -even know what they're about!' - - `Read them,' said the King. - - The White Rabbit put on his spectacles. `Where shall I begin, -please your Majesty?' he asked. - - `Begin at the beginning,' the King said gravely, `and go on -till you come to the end: then stop.' - - These were the verses the White Rabbit read:-- - - `They told me you had been to her, - And mentioned me to him: - She gave me a good character, - But said I could not swim. - - He sent them word I had not gone - (We know it to be true): - If she should push the matter on, - What would become of you? - - I gave her one, they gave him two, - You gave us three or more; - They all returned from him to you, - Though they were mine before. - - If I or she should chance to be - Involved in this affair, - He trusts to you to set them free, - Exactly as we were. - - My notion was that you had been - (Before she had this fit) - An obstacle that came between - Him, and ourselves, and it. - - Don't let him know she liked them best, - For this must ever be - A secret, kept from all the rest, - Between yourself and me.' - - `That's the most important piece of evidence we've heard yet,' -said the King, rubbing his hands; `so now let the jury--' - - `If any one of them can explain it,' said Alice, (she had -grown so large in the last few minutes that she wasn't a bit -afraid of interrupting him,) `I'll give him sixpence. _I_ don't -believe there's an atom of meaning in it.' - - The jury all wrote down on their slates, `SHE doesn't believe -there's an atom of meaning in it,' but none of them attempted to -explain the paper. - - `If there's no meaning in it,' said the King, `that saves a -world of trouble, you know, as we needn't try to find any. And -yet I don't know,' he went on, spreading out the verses on his -knee, and looking at them with one eye; `I seem to see some -meaning in them, after all. "--SAID I COULD NOT SWIM--" you -can't swim, can you?' he added, turning to the Knave. - - The Knave shook his head sadly. `Do I look like it?' he said. -(Which he certainly did NOT, being made entirely of cardboard.) - - `All right, so far,' said the King, and he went on muttering -over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's -the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why, -that must be what he did with the tarts, you know--' - - `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said -Alice. - - `Why, there they are!' said the King triumphantly, pointing to -the tarts on the table. `Nothing can be clearer than THAT. -Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my -dear, I think?' he said to the Queen. - - `Never!' said the Queen furiously, throwing an inkstand at the -Lizard as she spoke. (The unfortunate little Bill had left off -writing on his slate with one finger, as he found it made no -mark; but he now hastily began again, using the ink, that was -trickling down his face, as long as it lasted.) - - `Then the words don't FIT you,' said the King, looking round -the court with a smile. There was a dead silence. - - `It's a pun!' the King added in an offended tone, and -everybody laughed, `Let the jury consider their verdict,' the -King said, for about the twentieth time that day. - - `No, no!' said the Queen. `Sentence first--verdict afterwards.' - - `Stuff and nonsense!' said Alice loudly. `The idea of having -the sentence first!' - - `Hold your tongue!' said the Queen, turning purple. - - `I won't!' said Alice. - - `Off with her head!' the Queen shouted at the top of her voice. -Nobody moved. - - `Who cares for you?' said Alice, (she had grown to her full -size by this time.) `You're nothing but a pack of cards!' - - At this the whole pack rose up into the air, and came flying -down upon her: she gave a little scream, half of fright and half -of anger, and tried to beat them off, and found herself lying on -the bank, with her head in the lap of her sister, who was gently -brushing away some dead leaves that had fluttered down from the -trees upon her face. - - `Wake up, Alice dear!' said her sister; `Why, what a long -sleep you've had!' - - `Oh, I've had such a curious dream!' said Alice, and she told -her sister, as well as she could remember them, all these strange -Adventures of hers that you have just been reading about; and -when she had finished, her sister kissed her, and said, `It WAS a -curious dream, dear, certainly: but now run in to your tea; it's -getting late.' So Alice got up and ran off, thinking while she -ran, as well she might, what a wonderful dream it had been. - - But her sister sat still just as she left her, leaning her -head on her hand, watching the setting sun, and thinking of -little Alice and all her wonderful Adventures, till she too began -dreaming after a fashion, and this was her dream:-- - - First, she dreamed of little Alice herself, and once again the -tiny hands were clasped upon her knee, and the bright eager eyes -were looking up into hers--she could hear the very tones of her -voice, and see that queer little toss of her head to keep back -the wandering hair that WOULD always get into her eyes--and -still as she listened, or seemed to listen, the whole place -around her became alive the strange creatures of her little -sister's dream. - - The long grass rustled at her feet as the White Rabbit hurried -by--the frightened Mouse splashed his way through the -neighbouring pool--she could hear the rattle of the teacups as -the March Hare and his friends shared their never-ending meal, -and the shrill voice of the Queen ordering off her unfortunate -guests to execution--once more the pig-baby was sneezing on the -Duchess's knee, while plates and dishes crashed around it--once -more the shriek of the Gryphon, the squeaking of the Lizard's -slate-pencil, and the choking of the suppressed guinea-pigs, -filled the air, mixed up with the distant sobs of the miserable -Mock Turtle. - - So she sat on, with closed eyes, and half believed herself in -Wonderland, though she knew she had but to open them again, and -all would change to dull reality--the grass would be only -rustling in the wind, and the pool rippling to the waving of the -reeds--the rattling teacups would change to tinkling sheep- -bells, and the Queen's shrill cries to the voice of the shepherd -boy--and the sneeze of the baby, the shriek of the Gryphon, and -all thy other queer noises, would change (she knew) to the -confused clamour of the busy farm-yard--while the lowing of the -cattle in the distance would take the place of the Mock Turtle's -heavy sobs. - - Lastly, she pictured to herself how this same little sister of -hers would, in the after-time, be herself a grown woman; and how -she would keep, through all her riper years, the simple and -loving heart of her childhood: and how she would gather about -her other little children, and make THEIR eyes bright and eager -with many a strange tale, perhaps even with the dream of -Wonderland of long ago: and how she would feel with all their -simple sorrows, and find a pleasure in all their simple joys, -remembering her own child-life, and the happy summer days. - - THE END - \ No newline at end of file diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/asyoulik.txt b/Sources/OpenVPN3/test/unittests/comp-testdata/asyoulik.txt deleted file mode 100644 index ed5e409..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/asyoulik.txt +++ /dev/null @@ -1,4122 +0,0 @@ - AS YOU LIKE IT - - - DRAMATIS PERSONAE - - -DUKE SENIOR living in banishment. - -DUKE FREDERICK his brother, an usurper of his dominions. - - -AMIENS | - | lords attending on the banished duke. -JAQUES | - - -LE BEAU a courtier attending upon Frederick. - -CHARLES wrestler to Frederick. - - -OLIVER | - | -JAQUES (JAQUES DE BOYS:) | sons of Sir Rowland de Boys. - | -ORLANDO | - - -ADAM | - | servants to Oliver. -DENNIS | - - -TOUCHSTONE a clown. - -SIR OLIVER MARTEXT a vicar. - - -CORIN | - | shepherds. -SILVIUS | - - -WILLIAM a country fellow in love with Audrey. - - A person representing HYMEN. (HYMEN:) - -ROSALIND daughter to the banished duke. - -CELIA daughter to Frederick. - -PHEBE a shepherdess. - -AUDREY a country wench. - - Lords, pages, and attendants, &c. - (Forester:) - (A Lord:) - (First Lord:) - (Second Lord:) - (First Page:) - (Second Page:) - - -SCENE Oliver's house; Duke Frederick's court; and the - Forest of Arden. - - - - - AS YOU LIKE IT - - -ACT I - - - -SCENE I Orchard of Oliver's house. - - - [Enter ORLANDO and ADAM] - -ORLANDO As I remember, Adam, it was upon this fashion - bequeathed me by will but poor a thousand crowns, - and, as thou sayest, charged my brother, on his - blessing, to breed me well: and there begins my - sadness. My brother Jaques he keeps at school, and - report speaks goldenly of his profit: for my part, - he keeps me rustically at home, or, to speak more - properly, stays me here at home unkept; for call you - that keeping for a gentleman of my birth, that - differs not from the stalling of an ox? His horses - are bred better; for, besides that they are fair - with their feeding, they are taught their manage, - and to that end riders dearly hired: but I, his - brother, gain nothing under him but growth; for the - which his animals on his dunghills are as much - bound to him as I. Besides this nothing that he so - plentifully gives me, the something that nature gave - me his countenance seems to take from me: he lets - me feed with his hinds, bars me the place of a - brother, and, as much as in him lies, mines my - gentility with my education. This is it, Adam, that - grieves me; and the spirit of my father, which I - think is within me, begins to mutiny against this - servitude: I will no longer endure it, though yet I - know no wise remedy how to avoid it. - -ADAM Yonder comes my master, your brother. - -ORLANDO Go apart, Adam, and thou shalt hear how he will - shake me up. - - [Enter OLIVER] - -OLIVER Now, sir! what make you here? - -ORLANDO Nothing: I am not taught to make any thing. - -OLIVER What mar you then, sir? - -ORLANDO Marry, sir, I am helping you to mar that which God - made, a poor unworthy brother of yours, with idleness. - -OLIVER Marry, sir, be better employed, and be naught awhile. - -ORLANDO Shall I keep your hogs and eat husks with them? - What prodigal portion have I spent, that I should - come to such penury? - -OLIVER Know you where your are, sir? - -ORLANDO O, sir, very well; here in your orchard. - -OLIVER Know you before whom, sir? - -ORLANDO Ay, better than him I am before knows me. I know - you are my eldest brother; and, in the gentle - condition of blood, you should so know me. The - courtesy of nations allows you my better, in that - you are the first-born; but the same tradition - takes not away my blood, were there twenty brothers - betwixt us: I have as much of my father in me as - you; albeit, I confess, your coming before me is - nearer to his reverence. - -OLIVER What, boy! - -ORLANDO Come, come, elder brother, you are too young in this. - -OLIVER Wilt thou lay hands on me, villain? - -ORLANDO I am no villain; I am the youngest son of Sir - Rowland de Boys; he was my father, and he is thrice - a villain that says such a father begot villains. - Wert thou not my brother, I would not take this hand - from thy throat till this other had pulled out thy - tongue for saying so: thou hast railed on thyself. - -ADAM Sweet masters, be patient: for your father's - remembrance, be at accord. - -OLIVER Let me go, I say. - -ORLANDO I will not, till I please: you shall hear me. My - father charged you in his will to give me good - education: you have trained me like a peasant, - obscuring and hiding from me all gentleman-like - qualities. The spirit of my father grows strong in - me, and I will no longer endure it: therefore allow - me such exercises as may become a gentleman, or - give me the poor allottery my father left me by - testament; with that I will go buy my fortunes. - -OLIVER And what wilt thou do? beg, when that is spent? - Well, sir, get you in: I will not long be troubled - with you; you shall have some part of your will: I - pray you, leave me. - -ORLANDO I will no further offend you than becomes me for my good. - -OLIVER Get you with him, you old dog. - -ADAM Is 'old dog' my reward? Most true, I have lost my - teeth in your service. God be with my old master! - he would not have spoke such a word. - - [Exeunt ORLANDO and ADAM] - -OLIVER Is it even so? begin you to grow upon me? I will - physic your rankness, and yet give no thousand - crowns neither. Holla, Dennis! - - [Enter DENNIS] - -DENNIS Calls your worship? - -OLIVER Was not Charles, the duke's wrestler, here to speak with me? - -DENNIS So please you, he is here at the door and importunes - access to you. - -OLIVER Call him in. - - [Exit DENNIS] - - 'Twill be a good way; and to-morrow the wrestling is. - - [Enter CHARLES] - -CHARLES Good morrow to your worship. - -OLIVER Good Monsieur Charles, what's the new news at the - new court? - -CHARLES There's no news at the court, sir, but the old news: - that is, the old duke is banished by his younger - brother the new duke; and three or four loving lords - have put themselves into voluntary exile with him, - whose lands and revenues enrich the new duke; - therefore he gives them good leave to wander. - -OLIVER Can you tell if Rosalind, the duke's daughter, be - banished with her father? - -CHARLES O, no; for the duke's daughter, her cousin, so loves - her, being ever from their cradles bred together, - that she would have followed her exile, or have died - to stay behind her. She is at the court, and no - less beloved of her uncle than his own daughter; and - never two ladies loved as they do. - -OLIVER Where will the old duke live? - -CHARLES They say he is already in the forest of Arden, and - a many merry men with him; and there they live like - the old Robin Hood of England: they say many young - gentlemen flock to him every day, and fleet the time - carelessly, as they did in the golden world. - -OLIVER What, you wrestle to-morrow before the new duke? - -CHARLES Marry, do I, sir; and I came to acquaint you with a - matter. I am given, sir, secretly to understand - that your younger brother Orlando hath a disposition - to come in disguised against me to try a fall. - To-morrow, sir, I wrestle for my credit; and he that - escapes me without some broken limb shall acquit him - well. Your brother is but young and tender; and, - for your love, I would be loath to foil him, as I - must, for my own honour, if he come in: therefore, - out of my love to you, I came hither to acquaint you - withal, that either you might stay him from his - intendment or brook such disgrace well as he shall - run into, in that it is a thing of his own search - and altogether against my will. - -OLIVER Charles, I thank thee for thy love to me, which - thou shalt find I will most kindly requite. I had - myself notice of my brother's purpose herein and - have by underhand means laboured to dissuade him from - it, but he is resolute. I'll tell thee, Charles: - it is the stubbornest young fellow of France, full - of ambition, an envious emulator of every man's - good parts, a secret and villanous contriver against - me his natural brother: therefore use thy - discretion; I had as lief thou didst break his neck - as his finger. And thou wert best look to't; for if - thou dost him any slight disgrace or if he do not - mightily grace himself on thee, he will practise - against thee by poison, entrap thee by some - treacherous device and never leave thee till he - hath ta'en thy life by some indirect means or other; - for, I assure thee, and almost with tears I speak - it, there is not one so young and so villanous this - day living. I speak but brotherly of him; but - should I anatomize him to thee as he is, I must - blush and weep and thou must look pale and wonder. - -CHARLES I am heartily glad I came hither to you. If he come - to-morrow, I'll give him his payment: if ever he go - alone again, I'll never wrestle for prize more: and - so God keep your worship! - -OLIVER Farewell, good Charles. - - [Exit CHARLES] - - Now will I stir this gamester: I hope I shall see - an end of him; for my soul, yet I know not why, - hates nothing more than he. Yet he's gentle, never - schooled and yet learned, full of noble device, of - all sorts enchantingly beloved, and indeed so much - in the heart of the world, and especially of my own - people, who best know him, that I am altogether - misprised: but it shall not be so long; this - wrestler shall clear all: nothing remains but that - I kindle the boy thither; which now I'll go about. - - [Exit] - - - - - AS YOU LIKE IT - - -ACT I - - - -SCENE II Lawn before the Duke's palace. - - - [Enter CELIA and ROSALIND] - -CELIA I pray thee, Rosalind, sweet my coz, be merry. - -ROSALIND Dear Celia, I show more mirth than I am mistress of; - and would you yet I were merrier? Unless you could - teach me to forget a banished father, you must not - learn me how to remember any extraordinary pleasure. - -CELIA Herein I see thou lovest me not with the full weight - that I love thee. If my uncle, thy banished father, - had banished thy uncle, the duke my father, so thou - hadst been still with me, I could have taught my - love to take thy father for mine: so wouldst thou, - if the truth of thy love to me were so righteously - tempered as mine is to thee. - -ROSALIND Well, I will forget the condition of my estate, to - rejoice in yours. - -CELIA You know my father hath no child but I, nor none is - like to have: and, truly, when he dies, thou shalt - be his heir, for what he hath taken away from thy - father perforce, I will render thee again in - affection; by mine honour, I will; and when I break - that oath, let me turn monster: therefore, my - sweet Rose, my dear Rose, be merry. - -ROSALIND From henceforth I will, coz, and devise sports. Let - me see; what think you of falling in love? - -CELIA Marry, I prithee, do, to make sport withal: but - love no man in good earnest; nor no further in sport - neither than with safety of a pure blush thou mayst - in honour come off again. - -ROSALIND What shall be our sport, then? - -CELIA Let us sit and mock the good housewife Fortune from - her wheel, that her gifts may henceforth be bestowed equally. - -ROSALIND I would we could do so, for her benefits are - mightily misplaced, and the bountiful blind woman - doth most mistake in her gifts to women. - -CELIA 'Tis true; for those that she makes fair she scarce - makes honest, and those that she makes honest she - makes very ill-favouredly. - -ROSALIND Nay, now thou goest from Fortune's office to - Nature's: Fortune reigns in gifts of the world, - not in the lineaments of Nature. - - [Enter TOUCHSTONE] - -CELIA No? when Nature hath made a fair creature, may she - not by Fortune fall into the fire? Though Nature - hath given us wit to flout at Fortune, hath not - Fortune sent in this fool to cut off the argument? - -ROSALIND Indeed, there is Fortune too hard for Nature, when - Fortune makes Nature's natural the cutter-off of - Nature's wit. - -CELIA Peradventure this is not Fortune's work neither, but - Nature's; who perceiveth our natural wits too dull - to reason of such goddesses and hath sent this - natural for our whetstone; for always the dulness of - the fool is the whetstone of the wits. How now, - wit! whither wander you? - -TOUCHSTONE Mistress, you must come away to your father. - -CELIA Were you made the messenger? - -TOUCHSTONE No, by mine honour, but I was bid to come for you. - -ROSALIND Where learned you that oath, fool? - -TOUCHSTONE Of a certain knight that swore by his honour they - were good pancakes and swore by his honour the - mustard was naught: now I'll stand to it, the - pancakes were naught and the mustard was good, and - yet was not the knight forsworn. - -CELIA How prove you that, in the great heap of your - knowledge? - -ROSALIND Ay, marry, now unmuzzle your wisdom. - -TOUCHSTONE Stand you both forth now: stroke your chins, and - swear by your beards that I am a knave. - -CELIA By our beards, if we had them, thou art. - -TOUCHSTONE By my knavery, if I had it, then I were; but if you - swear by that that is not, you are not forsworn: no - more was this knight swearing by his honour, for he - never had any; or if he had, he had sworn it away - before ever he saw those pancakes or that mustard. - -CELIA Prithee, who is't that thou meanest? - -TOUCHSTONE One that old Frederick, your father, loves. - -CELIA My father's love is enough to honour him: enough! - speak no more of him; you'll be whipped for taxation - one of these days. - -TOUCHSTONE The more pity, that fools may not speak wisely what - wise men do foolishly. - -CELIA By my troth, thou sayest true; for since the little - wit that fools have was silenced, the little foolery - that wise men have makes a great show. Here comes - Monsieur Le Beau. - -ROSALIND With his mouth full of news. - -CELIA Which he will put on us, as pigeons feed their young. - -ROSALIND Then shall we be news-crammed. - -CELIA All the better; we shall be the more marketable. - - [Enter LE BEAU] - - Bon jour, Monsieur Le Beau: what's the news? - -LE BEAU Fair princess, you have lost much good sport. - -CELIA Sport! of what colour? - -LE BEAU What colour, madam! how shall I answer you? - -ROSALIND As wit and fortune will. - -TOUCHSTONE Or as the Destinies decree. - -CELIA Well said: that was laid on with a trowel. - -TOUCHSTONE Nay, if I keep not my rank,-- - -ROSALIND Thou losest thy old smell. - -LE BEAU You amaze me, ladies: I would have told you of good - wrestling, which you have lost the sight of. - -ROSALIND You tell us the manner of the wrestling. - -LE BEAU I will tell you the beginning; and, if it please - your ladyships, you may see the end; for the best is - yet to do; and here, where you are, they are coming - to perform it. - -CELIA Well, the beginning, that is dead and buried. - -LE BEAU There comes an old man and his three sons,-- - -CELIA I could match this beginning with an old tale. - -LE BEAU Three proper young men, of excellent growth and presence. - -ROSALIND With bills on their necks, 'Be it known unto all men - by these presents.' - -LE BEAU The eldest of the three wrestled with Charles, the - duke's wrestler; which Charles in a moment threw him - and broke three of his ribs, that there is little - hope of life in him: so he served the second, and - so the third. Yonder they lie; the poor old man, - their father, making such pitiful dole over them - that all the beholders take his part with weeping. - -ROSALIND Alas! - -TOUCHSTONE But what is the sport, monsieur, that the ladies - have lost? - -LE BEAU Why, this that I speak of. - -TOUCHSTONE Thus men may grow wiser every day: it is the first - time that ever I heard breaking of ribs was sport - for ladies. - -CELIA Or I, I promise thee. - -ROSALIND But is there any else longs to see this broken music - in his sides? is there yet another dotes upon - rib-breaking? Shall we see this wrestling, cousin? - -LE BEAU You must, if you stay here; for here is the place - appointed for the wrestling, and they are ready to - perform it. - -CELIA Yonder, sure, they are coming: let us now stay and see it. - - [Flourish. Enter DUKE FREDERICK, Lords, ORLANDO, - CHARLES, and Attendants] - -DUKE FREDERICK Come on: since the youth will not be entreated, his - own peril on his forwardness. - -ROSALIND Is yonder the man? - -LE BEAU Even he, madam. - -CELIA Alas, he is too young! yet he looks successfully. - -DUKE FREDERICK How now, daughter and cousin! are you crept hither - to see the wrestling? - -ROSALIND Ay, my liege, so please you give us leave. - -DUKE FREDERICK You will take little delight in it, I can tell you; - there is such odds in the man. In pity of the - challenger's youth I would fain dissuade him, but he - will not be entreated. Speak to him, ladies; see if - you can move him. - -CELIA Call him hither, good Monsieur Le Beau. - -DUKE FREDERICK Do so: I'll not be by. - -LE BEAU Monsieur the challenger, the princesses call for you. - -ORLANDO I attend them with all respect and duty. - -ROSALIND Young man, have you challenged Charles the wrestler? - -ORLANDO No, fair princess; he is the general challenger: I - come but in, as others do, to try with him the - strength of my youth. - -CELIA Young gentleman, your spirits are too bold for your - years. You have seen cruel proof of this man's - strength: if you saw yourself with your eyes or - knew yourself with your judgment, the fear of your - adventure would counsel you to a more equal - enterprise. We pray you, for your own sake, to - embrace your own safety and give over this attempt. - -ROSALIND Do, young sir; your reputation shall not therefore - be misprised: we will make it our suit to the duke - that the wrestling might not go forward. - -ORLANDO I beseech you, punish me not with your hard - thoughts; wherein I confess me much guilty, to deny - so fair and excellent ladies any thing. But let - your fair eyes and gentle wishes go with me to my - trial: wherein if I be foiled, there is but one - shamed that was never gracious; if killed, but one - dead that was willing to be so: I shall do my - friends no wrong, for I have none to lament me, the - world no injury, for in it I have nothing; only in - the world I fill up a place, which may be better - supplied when I have made it empty. - -ROSALIND The little strength that I have, I would it were with you. - -CELIA And mine, to eke out hers. - -ROSALIND Fare you well: pray heaven I be deceived in you! - -CELIA Your heart's desires be with you! - -CHARLES Come, where is this young gallant that is so - desirous to lie with his mother earth? - -ORLANDO Ready, sir; but his will hath in it a more modest working. - -DUKE FREDERICK You shall try but one fall. - -CHARLES No, I warrant your grace, you shall not entreat him - to a second, that have so mightily persuaded him - from a first. - -ORLANDO An you mean to mock me after, you should not have - mocked me before: but come your ways. - -ROSALIND Now Hercules be thy speed, young man! - -CELIA I would I were invisible, to catch the strong - fellow by the leg. - - [They wrestle] - -ROSALIND O excellent young man! - -CELIA If I had a thunderbolt in mine eye, I can tell who - should down. - - [Shout. CHARLES is thrown] - -DUKE FREDERICK No more, no more. - -ORLANDO Yes, I beseech your grace: I am not yet well breathed. - -DUKE FREDERICK How dost thou, Charles? - -LE BEAU He cannot speak, my lord. - -DUKE FREDERICK Bear him away. What is thy name, young man? - -ORLANDO Orlando, my liege; the youngest son of Sir Rowland de Boys. - -DUKE FREDERICK I would thou hadst been son to some man else: - The world esteem'd thy father honourable, - But I did find him still mine enemy: - Thou shouldst have better pleased me with this deed, - Hadst thou descended from another house. - But fare thee well; thou art a gallant youth: - I would thou hadst told me of another father. - - [Exeunt DUKE FREDERICK, train, and LE BEAU] - -CELIA Were I my father, coz, would I do this? - -ORLANDO I am more proud to be Sir Rowland's son, - His youngest son; and would not change that calling, - To be adopted heir to Frederick. - -ROSALIND My father loved Sir Rowland as his soul, - And all the world was of my father's mind: - Had I before known this young man his son, - I should have given him tears unto entreaties, - Ere he should thus have ventured. - -CELIA Gentle cousin, - Let us go thank him and encourage him: - My father's rough and envious disposition - Sticks me at heart. Sir, you have well deserved: - If you do keep your promises in love - But justly, as you have exceeded all promise, - Your mistress shall be happy. - -ROSALIND Gentleman, - - [Giving him a chain from her neck] - - Wear this for me, one out of suits with fortune, - That could give more, but that her hand lacks means. - Shall we go, coz? - -CELIA Ay. Fare you well, fair gentleman. - -ORLANDO Can I not say, I thank you? My better parts - Are all thrown down, and that which here stands up - Is but a quintain, a mere lifeless block. - -ROSALIND He calls us back: my pride fell with my fortunes; - I'll ask him what he would. Did you call, sir? - Sir, you have wrestled well and overthrown - More than your enemies. - -CELIA Will you go, coz? - -ROSALIND Have with you. Fare you well. - - [Exeunt ROSALIND and CELIA] - -ORLANDO What passion hangs these weights upon my tongue? - I cannot speak to her, yet she urged conference. - O poor Orlando, thou art overthrown! - Or Charles or something weaker masters thee. - - [Re-enter LE BEAU] - -LE BEAU Good sir, I do in friendship counsel you - To leave this place. Albeit you have deserved - High commendation, true applause and love, - Yet such is now the duke's condition - That he misconstrues all that you have done. - The duke is humorous; what he is indeed, - More suits you to conceive than I to speak of. - -ORLANDO I thank you, sir: and, pray you, tell me this: - Which of the two was daughter of the duke - That here was at the wrestling? - -LE BEAU Neither his daughter, if we judge by manners; - But yet indeed the lesser is his daughter - The other is daughter to the banish'd duke, - And here detain'd by her usurping uncle, - To keep his daughter company; whose loves - Are dearer than the natural bond of sisters. - But I can tell you that of late this duke - Hath ta'en displeasure 'gainst his gentle niece, - Grounded upon no other argument - But that the people praise her for her virtues - And pity her for her good father's sake; - And, on my life, his malice 'gainst the lady - Will suddenly break forth. Sir, fare you well: - Hereafter, in a better world than this, - I shall desire more love and knowledge of you. - -ORLANDO I rest much bounden to you: fare you well. - - [Exit LE BEAU] - - Thus must I from the smoke into the smother; - From tyrant duke unto a tyrant brother: - But heavenly Rosalind! - - [Exit] - - - - - AS YOU LIKE IT - - -ACT I - - - -SCENE III A room in the palace. - - - [Enter CELIA and ROSALIND] - -CELIA Why, cousin! why, Rosalind! Cupid have mercy! not a word? - -ROSALIND Not one to throw at a dog. - -CELIA No, thy words are too precious to be cast away upon - curs; throw some of them at me; come, lame me with reasons. - -ROSALIND Then there were two cousins laid up; when the one - should be lamed with reasons and the other mad - without any. - -CELIA But is all this for your father? - -ROSALIND No, some of it is for my child's father. O, how - full of briers is this working-day world! - -CELIA They are but burs, cousin, thrown upon thee in - holiday foolery: if we walk not in the trodden - paths our very petticoats will catch them. - -ROSALIND I could shake them off my coat: these burs are in my heart. - -CELIA Hem them away. - -ROSALIND I would try, if I could cry 'hem' and have him. - -CELIA Come, come, wrestle with thy affections. - -ROSALIND O, they take the part of a better wrestler than myself! - -CELIA O, a good wish upon you! you will try in time, in - despite of a fall. But, turning these jests out of - service, let us talk in good earnest: is it - possible, on such a sudden, you should fall into so - strong a liking with old Sir Rowland's youngest son? - -ROSALIND The duke my father loved his father dearly. - -CELIA Doth it therefore ensue that you should love his son - dearly? By this kind of chase, I should hate him, - for my father hated his father dearly; yet I hate - not Orlando. - -ROSALIND No, faith, hate him not, for my sake. - -CELIA Why should I not? doth he not deserve well? - -ROSALIND Let me love him for that, and do you love him - because I do. Look, here comes the duke. - -CELIA With his eyes full of anger. - - [Enter DUKE FREDERICK, with Lords] - -DUKE FREDERICK Mistress, dispatch you with your safest haste - And get you from our court. - -ROSALIND Me, uncle? - -DUKE FREDERICK You, cousin - Within these ten days if that thou be'st found - So near our public court as twenty miles, - Thou diest for it. - -ROSALIND I do beseech your grace, - Let me the knowledge of my fault bear with me: - If with myself I hold intelligence - Or have acquaintance with mine own desires, - If that I do not dream or be not frantic,-- - As I do trust I am not--then, dear uncle, - Never so much as in a thought unborn - Did I offend your highness. - -DUKE FREDERICK Thus do all traitors: - If their purgation did consist in words, - They are as innocent as grace itself: - Let it suffice thee that I trust thee not. - -ROSALIND Yet your mistrust cannot make me a traitor: - Tell me whereon the likelihood depends. - -DUKE FREDERICK Thou art thy father's daughter; there's enough. - -ROSALIND So was I when your highness took his dukedom; - So was I when your highness banish'd him: - Treason is not inherited, my lord; - Or, if we did derive it from our friends, - What's that to me? my father was no traitor: - Then, good my liege, mistake me not so much - To think my poverty is treacherous. - -CELIA Dear sovereign, hear me speak. - -DUKE FREDERICK Ay, Celia; we stay'd her for your sake, - Else had she with her father ranged along. - -CELIA I did not then entreat to have her stay; - It was your pleasure and your own remorse: - I was too young that time to value her; - But now I know her: if she be a traitor, - Why so am I; we still have slept together, - Rose at an instant, learn'd, play'd, eat together, - And wheresoever we went, like Juno's swans, - Still we went coupled and inseparable. - -DUKE FREDERICK She is too subtle for thee; and her smoothness, - Her very silence and her patience - Speak to the people, and they pity her. - Thou art a fool: she robs thee of thy name; - And thou wilt show more bright and seem more virtuous - When she is gone. Then open not thy lips: - Firm and irrevocable is my doom - Which I have pass'd upon her; she is banish'd. - -CELIA Pronounce that sentence then on me, my liege: - I cannot live out of her company. - -DUKE FREDERICK You are a fool. You, niece, provide yourself: - If you outstay the time, upon mine honour, - And in the greatness of my word, you die. - - [Exeunt DUKE FREDERICK and Lords] - -CELIA O my poor Rosalind, whither wilt thou go? - Wilt thou change fathers? I will give thee mine. - I charge thee, be not thou more grieved than I am. - -ROSALIND I have more cause. - -CELIA Thou hast not, cousin; - Prithee be cheerful: know'st thou not, the duke - Hath banish'd me, his daughter? - -ROSALIND That he hath not. - -CELIA No, hath not? Rosalind lacks then the love - Which teacheth thee that thou and I am one: - Shall we be sunder'd? shall we part, sweet girl? - No: let my father seek another heir. - Therefore devise with me how we may fly, - Whither to go and what to bear with us; - And do not seek to take your change upon you, - To bear your griefs yourself and leave me out; - For, by this heaven, now at our sorrows pale, - Say what thou canst, I'll go along with thee. - -ROSALIND Why, whither shall we go? - -CELIA To seek my uncle in the forest of Arden. - -ROSALIND Alas, what danger will it be to us, - Maids as we are, to travel forth so far! - Beauty provoketh thieves sooner than gold. - -CELIA I'll put myself in poor and mean attire - And with a kind of umber smirch my face; - The like do you: so shall we pass along - And never stir assailants. - -ROSALIND Were it not better, - Because that I am more than common tall, - That I did suit me all points like a man? - A gallant curtle-axe upon my thigh, - A boar-spear in my hand; and--in my heart - Lie there what hidden woman's fear there will-- - We'll have a swashing and a martial outside, - As many other mannish cowards have - That do outface it with their semblances. - -CELIA What shall I call thee when thou art a man? - -ROSALIND I'll have no worse a name than Jove's own page; - And therefore look you call me Ganymede. - But what will you be call'd? - -CELIA Something that hath a reference to my state - No longer Celia, but Aliena. - -ROSALIND But, cousin, what if we assay'd to steal - The clownish fool out of your father's court? - Would he not be a comfort to our travel? - -CELIA He'll go along o'er the wide world with me; - Leave me alone to woo him. Let's away, - And get our jewels and our wealth together, - Devise the fittest time and safest way - To hide us from pursuit that will be made - After my flight. Now go we in content - To liberty and not to banishment. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE I The Forest of Arden. - - - [Enter DUKE SENIOR, AMIENS, and two or three Lords, - like foresters] - -DUKE SENIOR Now, my co-mates and brothers in exile, - Hath not old custom made this life more sweet - Than that of painted pomp? Are not these woods - More free from peril than the envious court? - Here feel we but the penalty of Adam, - The seasons' difference, as the icy fang - And churlish chiding of the winter's wind, - Which, when it bites and blows upon my body, - Even till I shrink with cold, I smile and say - 'This is no flattery: these are counsellors - That feelingly persuade me what I am.' - Sweet are the uses of adversity, - Which, like the toad, ugly and venomous, - Wears yet a precious jewel in his head; - And this our life exempt from public haunt - Finds tongues in trees, books in the running brooks, - Sermons in stones and good in every thing. - I would not change it. - -AMIENS Happy is your grace, - That can translate the stubbornness of fortune - Into so quiet and so sweet a style. - -DUKE SENIOR Come, shall we go and kill us venison? - And yet it irks me the poor dappled fools, - Being native burghers of this desert city, - Should in their own confines with forked heads - Have their round haunches gored. - -First Lord Indeed, my lord, - The melancholy Jaques grieves at that, - And, in that kind, swears you do more usurp - Than doth your brother that hath banish'd you. - To-day my Lord of Amiens and myself - Did steal behind him as he lay along - Under an oak whose antique root peeps out - Upon the brook that brawls along this wood: - To the which place a poor sequester'd stag, - That from the hunter's aim had ta'en a hurt, - Did come to languish, and indeed, my lord, - The wretched animal heaved forth such groans - That their discharge did stretch his leathern coat - Almost to bursting, and the big round tears - Coursed one another down his innocent nose - In piteous chase; and thus the hairy fool - Much marked of the melancholy Jaques, - Stood on the extremest verge of the swift brook, - Augmenting it with tears. - -DUKE SENIOR But what said Jaques? - Did he not moralize this spectacle? - -First Lord O, yes, into a thousand similes. - First, for his weeping into the needless stream; - 'Poor deer,' quoth he, 'thou makest a testament - As worldlings do, giving thy sum of more - To that which had too much:' then, being there alone, - Left and abandon'd of his velvet friends, - ''Tis right:' quoth he; 'thus misery doth part - The flux of company:' anon a careless herd, - Full of the pasture, jumps along by him - And never stays to greet him; 'Ay' quoth Jaques, - 'Sweep on, you fat and greasy citizens; - 'Tis just the fashion: wherefore do you look - Upon that poor and broken bankrupt there?' - Thus most invectively he pierceth through - The body of the country, city, court, - Yea, and of this our life, swearing that we - Are mere usurpers, tyrants and what's worse, - To fright the animals and to kill them up - In their assign'd and native dwelling-place. - -DUKE SENIOR And did you leave him in this contemplation? - -Second Lord We did, my lord, weeping and commenting - Upon the sobbing deer. - -DUKE SENIOR Show me the place: - I love to cope him in these sullen fits, - For then he's full of matter. - -First Lord I'll bring you to him straight. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE II A room in the palace. - - - [Enter DUKE FREDERICK, with Lords] - -DUKE FREDERICK Can it be possible that no man saw them? - It cannot be: some villains of my court - Are of consent and sufferance in this. - -First Lord I cannot hear of any that did see her. - The ladies, her attendants of her chamber, - Saw her abed, and in the morning early - They found the bed untreasured of their mistress. - -Second Lord My lord, the roynish clown, at whom so oft - Your grace was wont to laugh, is also missing. - Hisperia, the princess' gentlewoman, - Confesses that she secretly o'erheard - Your daughter and her cousin much commend - The parts and graces of the wrestler - That did but lately foil the sinewy Charles; - And she believes, wherever they are gone, - That youth is surely in their company. - -DUKE FREDERICK Send to his brother; fetch that gallant hither; - If he be absent, bring his brother to me; - I'll make him find him: do this suddenly, - And let not search and inquisition quail - To bring again these foolish runaways. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE III Before OLIVER'S house. - - - [Enter ORLANDO and ADAM, meeting] - -ORLANDO Who's there? - -ADAM What, my young master? O, my gentle master! - O my sweet master! O you memory - Of old Sir Rowland! why, what make you here? - Why are you virtuous? why do people love you? - And wherefore are you gentle, strong and valiant? - Why would you be so fond to overcome - The bonny priser of the humorous duke? - Your praise is come too swiftly home before you. - Know you not, master, to some kind of men - Their graces serve them but as enemies? - No more do yours: your virtues, gentle master, - Are sanctified and holy traitors to you. - O, what a world is this, when what is comely - Envenoms him that bears it! - -ORLANDO Why, what's the matter? - -ADAM O unhappy youth! - Come not within these doors; within this roof - The enemy of all your graces lives: - Your brother--no, no brother; yet the son-- - Yet not the son, I will not call him son - Of him I was about to call his father-- - Hath heard your praises, and this night he means - To burn the lodging where you use to lie - And you within it: if he fail of that, - He will have other means to cut you off. - I overheard him and his practises. - This is no place; this house is but a butchery: - Abhor it, fear it, do not enter it. - -ORLANDO Why, whither, Adam, wouldst thou have me go? - -ADAM No matter whither, so you come not here. - -ORLANDO What, wouldst thou have me go and beg my food? - Or with a base and boisterous sword enforce - A thievish living on the common road? - This I must do, or know not what to do: - Yet this I will not do, do how I can; - I rather will subject me to the malice - Of a diverted blood and bloody brother. - -ADAM But do not so. I have five hundred crowns, - The thrifty hire I saved under your father, - Which I did store to be my foster-nurse - When service should in my old limbs lie lame - And unregarded age in corners thrown: - Take that, and He that doth the ravens feed, - Yea, providently caters for the sparrow, - Be comfort to my age! Here is the gold; - And all this I give you. Let me be your servant: - Though I look old, yet I am strong and lusty; - For in my youth I never did apply - Hot and rebellious liquors in my blood, - Nor did not with unbashful forehead woo - The means of weakness and debility; - Therefore my age is as a lusty winter, - Frosty, but kindly: let me go with you; - I'll do the service of a younger man - In all your business and necessities. - -ORLANDO O good old man, how well in thee appears - The constant service of the antique world, - When service sweat for duty, not for meed! - Thou art not for the fashion of these times, - Where none will sweat but for promotion, - And having that, do choke their service up - Even with the having: it is not so with thee. - But, poor old man, thou prunest a rotten tree, - That cannot so much as a blossom yield - In lieu of all thy pains and husbandry - But come thy ways; well go along together, - And ere we have thy youthful wages spent, - We'll light upon some settled low content. - -ADAM Master, go on, and I will follow thee, - To the last gasp, with truth and loyalty. - From seventeen years till now almost fourscore - Here lived I, but now live here no more. - At seventeen years many their fortunes seek; - But at fourscore it is too late a week: - Yet fortune cannot recompense me better - Than to die well and not my master's debtor. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE IV The Forest of Arden. - - - [Enter ROSALIND for Ganymede, CELIA for Aliena, - and TOUCHSTONE] - -ROSALIND O Jupiter, how weary are my spirits! - -TOUCHSTONE I care not for my spirits, if my legs were not weary. - -ROSALIND I could find in my heart to disgrace my man's - apparel and to cry like a woman; but I must comfort - the weaker vessel, as doublet and hose ought to show - itself courageous to petticoat: therefore courage, - good Aliena! - -CELIA I pray you, bear with me; I cannot go no further. - -TOUCHSTONE For my part, I had rather bear with you than bear - you; yet I should bear no cross if I did bear you, - for I think you have no money in your purse. - -ROSALIND Well, this is the forest of Arden. - -TOUCHSTONE Ay, now am I in Arden; the more fool I; when I was - at home, I was in a better place: but travellers - must be content. - -ROSALIND Ay, be so, good Touchstone. - - [Enter CORIN and SILVIUS] - - Look you, who comes here; a young man and an old in - solemn talk. - -CORIN That is the way to make her scorn you still. - -SILVIUS O Corin, that thou knew'st how I do love her! - -CORIN I partly guess; for I have loved ere now. - -SILVIUS No, Corin, being old, thou canst not guess, - Though in thy youth thou wast as true a lover - As ever sigh'd upon a midnight pillow: - But if thy love were ever like to mine-- - As sure I think did never man love so-- - How many actions most ridiculous - Hast thou been drawn to by thy fantasy? - -CORIN Into a thousand that I have forgotten. - -SILVIUS O, thou didst then ne'er love so heartily! - If thou remember'st not the slightest folly - That ever love did make thee run into, - Thou hast not loved: - Or if thou hast not sat as I do now, - Wearying thy hearer in thy mistress' praise, - Thou hast not loved: - Or if thou hast not broke from company - Abruptly, as my passion now makes me, - Thou hast not loved. - O Phebe, Phebe, Phebe! - - [Exit] - -ROSALIND Alas, poor shepherd! searching of thy wound, - I have by hard adventure found mine own. - -TOUCHSTONE And I mine. I remember, when I was in love I broke - my sword upon a stone and bid him take that for - coming a-night to Jane Smile; and I remember the - kissing of her batlet and the cow's dugs that her - pretty chopt hands had milked; and I remember the - wooing of a peascod instead of her, from whom I took - two cods and, giving her them again, said with - weeping tears 'Wear these for my sake.' We that are - true lovers run into strange capers; but as all is - mortal in nature, so is all nature in love mortal in folly. - -ROSALIND Thou speakest wiser than thou art ware of. - -TOUCHSTONE Nay, I shall ne'er be ware of mine own wit till I - break my shins against it. - -ROSALIND Jove, Jove! this shepherd's passion - Is much upon my fashion. - -TOUCHSTONE And mine; but it grows something stale with me. - -CELIA I pray you, one of you question yond man - If he for gold will give us any food: - I faint almost to death. - -TOUCHSTONE Holla, you clown! - -ROSALIND Peace, fool: he's not thy kinsman. - -CORIN Who calls? - -TOUCHSTONE Your betters, sir. - -CORIN Else are they very wretched. - -ROSALIND Peace, I say. Good even to you, friend. - -CORIN And to you, gentle sir, and to you all. - -ROSALIND I prithee, shepherd, if that love or gold - Can in this desert place buy entertainment, - Bring us where we may rest ourselves and feed: - Here's a young maid with travel much oppress'd - And faints for succor. - -CORIN Fair sir, I pity her - And wish, for her sake more than for mine own, - My fortunes were more able to relieve her; - But I am shepherd to another man - And do not shear the fleeces that I graze: - My master is of churlish disposition - And little recks to find the way to heaven - By doing deeds of hospitality: - Besides, his cote, his flocks and bounds of feed - Are now on sale, and at our sheepcote now, - By reason of his absence, there is nothing - That you will feed on; but what is, come see. - And in my voice most welcome shall you be. - -ROSALIND What is he that shall buy his flock and pasture? - -CORIN That young swain that you saw here but erewhile, - That little cares for buying any thing. - -ROSALIND I pray thee, if it stand with honesty, - Buy thou the cottage, pasture and the flock, - And thou shalt have to pay for it of us. - -CELIA And we will mend thy wages. I like this place. - And willingly could waste my time in it. - -CORIN Assuredly the thing is to be sold: - Go with me: if you like upon report - The soil, the profit and this kind of life, - I will your very faithful feeder be - And buy it with your gold right suddenly. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE V The Forest. - - - [Enter AMIENS, JAQUES, and others] - - SONG. -AMIENS Under the greenwood tree - Who loves to lie with me, - And turn his merry note - Unto the sweet bird's throat, - Come hither, come hither, come hither: - Here shall he see No enemy - But winter and rough weather. - -JAQUES More, more, I prithee, more. - -AMIENS It will make you melancholy, Monsieur Jaques. - -JAQUES I thank it. More, I prithee, more. I can suck - melancholy out of a song, as a weasel sucks eggs. - More, I prithee, more. - -AMIENS My voice is ragged: I know I cannot please you. - -JAQUES I do not desire you to please me; I do desire you to - sing. Come, more; another stanzo: call you 'em stanzos? - -AMIENS What you will, Monsieur Jaques. - -JAQUES Nay, I care not for their names; they owe me - nothing. Will you sing? - -AMIENS More at your request than to please myself. - -JAQUES Well then, if ever I thank any man, I'll thank you; - but that they call compliment is like the encounter - of two dog-apes, and when a man thanks me heartily, - methinks I have given him a penny and he renders me - the beggarly thanks. Come, sing; and you that will - not, hold your tongues. - -AMIENS Well, I'll end the song. Sirs, cover the while; the - duke will drink under this tree. He hath been all - this day to look you. - -JAQUES And I have been all this day to avoid him. He is - too disputable for my company: I think of as many - matters as he, but I give heaven thanks and make no - boast of them. Come, warble, come. - - SONG. - Who doth ambition shun - - [All together here] - - And loves to live i' the sun, - Seeking the food he eats - And pleased with what he gets, - Come hither, come hither, come hither: - Here shall he see No enemy - But winter and rough weather. - -JAQUES I'll give you a verse to this note that I made - yesterday in despite of my invention. - -AMIENS And I'll sing it. - -JAQUES Thus it goes:-- - - If it do come to pass - That any man turn ass, - Leaving his wealth and ease, - A stubborn will to please, - Ducdame, ducdame, ducdame: - Here shall he see - Gross fools as he, - An if he will come to me. - -AMIENS What's that 'ducdame'? - -JAQUES 'Tis a Greek invocation, to call fools into a - circle. I'll go sleep, if I can; if I cannot, I'll - rail against all the first-born of Egypt. - -AMIENS And I'll go seek the duke: his banquet is prepared. - - [Exeunt severally] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE VI The forest. - - - [Enter ORLANDO and ADAM] - -ADAM Dear master, I can go no further. O, I die for food! - Here lie I down, and measure out my grave. Farewell, - kind master. - -ORLANDO Why, how now, Adam! no greater heart in thee? Live - a little; comfort a little; cheer thyself a little. - If this uncouth forest yield any thing savage, I - will either be food for it or bring it for food to - thee. Thy conceit is nearer death than thy powers. - For my sake be comfortable; hold death awhile at - the arm's end: I will here be with thee presently; - and if I bring thee not something to eat, I will - give thee leave to die: but if thou diest before I - come, thou art a mocker of my labour. Well said! - thou lookest cheerly, and I'll be with thee quickly. - Yet thou liest in the bleak air: come, I will bear - thee to some shelter; and thou shalt not die for - lack of a dinner, if there live any thing in this - desert. Cheerly, good Adam! - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT II - - - -SCENE VII The forest. - - - [A table set out. Enter DUKE SENIOR, AMIENS, and - Lords like outlaws] - -DUKE SENIOR I think he be transform'd into a beast; - For I can no where find him like a man. - -First Lord My lord, he is but even now gone hence: - Here was he merry, hearing of a song. - -DUKE SENIOR If he, compact of jars, grow musical, - We shall have shortly discord in the spheres. - Go, seek him: tell him I would speak with him. - - [Enter JAQUES] - -First Lord He saves my labour by his own approach. - -DUKE SENIOR Why, how now, monsieur! what a life is this, - That your poor friends must woo your company? - What, you look merrily! - -JAQUES A fool, a fool! I met a fool i' the forest, - A motley fool; a miserable world! - As I do live by food, I met a fool - Who laid him down and bask'd him in the sun, - And rail'd on Lady Fortune in good terms, - In good set terms and yet a motley fool. - 'Good morrow, fool,' quoth I. 'No, sir,' quoth he, - 'Call me not fool till heaven hath sent me fortune:' - And then he drew a dial from his poke, - And, looking on it with lack-lustre eye, - Says very wisely, 'It is ten o'clock: - Thus we may see,' quoth he, 'how the world wags: - 'Tis but an hour ago since it was nine, - And after one hour more 'twill be eleven; - And so, from hour to hour, we ripe and ripe, - And then, from hour to hour, we rot and rot; - And thereby hangs a tale.' When I did hear - The motley fool thus moral on the time, - My lungs began to crow like chanticleer, - That fools should be so deep-contemplative, - And I did laugh sans intermission - An hour by his dial. O noble fool! - A worthy fool! Motley's the only wear. - -DUKE SENIOR What fool is this? - -JAQUES O worthy fool! One that hath been a courtier, - And says, if ladies be but young and fair, - They have the gift to know it: and in his brain, - Which is as dry as the remainder biscuit - After a voyage, he hath strange places cramm'd - With observation, the which he vents - In mangled forms. O that I were a fool! - I am ambitious for a motley coat. - -DUKE SENIOR Thou shalt have one. - -JAQUES It is my only suit; - Provided that you weed your better judgments - Of all opinion that grows rank in them - That I am wise. I must have liberty - Withal, as large a charter as the wind, - To blow on whom I please; for so fools have; - And they that are most galled with my folly, - They most must laugh. And why, sir, must they so? - The 'why' is plain as way to parish church: - He that a fool doth very wisely hit - Doth very foolishly, although he smart, - Not to seem senseless of the bob: if not, - The wise man's folly is anatomized - Even by the squandering glances of the fool. - Invest me in my motley; give me leave - To speak my mind, and I will through and through - Cleanse the foul body of the infected world, - If they will patiently receive my medicine. - -DUKE SENIOR Fie on thee! I can tell what thou wouldst do. - -JAQUES What, for a counter, would I do but good? - -DUKE SENIOR Most mischievous foul sin, in chiding sin: - For thou thyself hast been a libertine, - As sensual as the brutish sting itself; - And all the embossed sores and headed evils, - That thou with licence of free foot hast caught, - Wouldst thou disgorge into the general world. - -JAQUES Why, who cries out on pride, - That can therein tax any private party? - Doth it not flow as hugely as the sea, - Till that the weary very means do ebb? - What woman in the city do I name, - When that I say the city-woman bears - The cost of princes on unworthy shoulders? - Who can come in and say that I mean her, - When such a one as she such is her neighbour? - Or what is he of basest function - That says his bravery is not of my cost, - Thinking that I mean him, but therein suits - His folly to the mettle of my speech? - There then; how then? what then? Let me see wherein - My tongue hath wrong'd him: if it do him right, - Then he hath wrong'd himself; if he be free, - Why then my taxing like a wild-goose flies, - Unclaim'd of any man. But who comes here? - - [Enter ORLANDO, with his sword drawn] - -ORLANDO Forbear, and eat no more. - -JAQUES Why, I have eat none yet. - -ORLANDO Nor shalt not, till necessity be served. - -JAQUES Of what kind should this cock come of? - -DUKE SENIOR Art thou thus bolden'd, man, by thy distress, - Or else a rude despiser of good manners, - That in civility thou seem'st so empty? - -ORLANDO You touch'd my vein at first: the thorny point - Of bare distress hath ta'en from me the show - Of smooth civility: yet am I inland bred - And know some nurture. But forbear, I say: - He dies that touches any of this fruit - Till I and my affairs are answered. - -JAQUES An you will not be answered with reason, I must die. - -DUKE SENIOR What would you have? Your gentleness shall force - More than your force move us to gentleness. - -ORLANDO I almost die for food; and let me have it. - -DUKE SENIOR Sit down and feed, and welcome to our table. - -ORLANDO Speak you so gently? Pardon me, I pray you: - I thought that all things had been savage here; - And therefore put I on the countenance - Of stern commandment. But whate'er you are - That in this desert inaccessible, - Under the shade of melancholy boughs, - Lose and neglect the creeping hours of time - If ever you have look'd on better days, - If ever been where bells have knoll'd to church, - If ever sat at any good man's feast, - If ever from your eyelids wiped a tear - And know what 'tis to pity and be pitied, - Let gentleness my strong enforcement be: - In the which hope I blush, and hide my sword. - -DUKE SENIOR True is it that we have seen better days, - And have with holy bell been knoll'd to church - And sat at good men's feasts and wiped our eyes - Of drops that sacred pity hath engender'd: - And therefore sit you down in gentleness - And take upon command what help we have - That to your wanting may be minister'd. - -ORLANDO Then but forbear your food a little while, - Whiles, like a doe, I go to find my fawn - And give it food. There is an old poor man, - Who after me hath many a weary step - Limp'd in pure love: till he be first sufficed, - Oppress'd with two weak evils, age and hunger, - I will not touch a bit. - -DUKE SENIOR Go find him out, - And we will nothing waste till you return. - -ORLANDO I thank ye; and be blest for your good comfort! - - [Exit] - -DUKE SENIOR Thou seest we are not all alone unhappy: - This wide and universal theatre - Presents more woeful pageants than the scene - Wherein we play in. - -JAQUES All the world's a stage, - And all the men and women merely players: - They have their exits and their entrances; - And one man in his time plays many parts, - His acts being seven ages. At first the infant, - Mewling and puking in the nurse's arms. - And then the whining school-boy, with his satchel - And shining morning face, creeping like snail - Unwillingly to school. And then the lover, - Sighing like furnace, with a woeful ballad - Made to his mistress' eyebrow. Then a soldier, - Full of strange oaths and bearded like the pard, - Jealous in honour, sudden and quick in quarrel, - Seeking the bubble reputation - Even in the cannon's mouth. And then the justice, - In fair round belly with good capon lined, - With eyes severe and beard of formal cut, - Full of wise saws and modern instances; - And so he plays his part. The sixth age shifts - Into the lean and slipper'd pantaloon, - With spectacles on nose and pouch on side, - His youthful hose, well saved, a world too wide - For his shrunk shank; and his big manly voice, - Turning again toward childish treble, pipes - And whistles in his sound. Last scene of all, - That ends this strange eventful history, - Is second childishness and mere oblivion, - Sans teeth, sans eyes, sans taste, sans everything. - - [Re-enter ORLANDO, with ADAM] - -DUKE SENIOR Welcome. Set down your venerable burthen, - And let him feed. - -ORLANDO I thank you most for him. - -ADAM So had you need: - I scarce can speak to thank you for myself. - -DUKE SENIOR Welcome; fall to: I will not trouble you - As yet, to question you about your fortunes. - Give us some music; and, good cousin, sing. - - SONG. -AMIENS Blow, blow, thou winter wind. - Thou art not so unkind - As man's ingratitude; - Thy tooth is not so keen, - Because thou art not seen, - Although thy breath be rude. - Heigh-ho! sing, heigh-ho! unto the green holly: - Most friendship is feigning, most loving mere folly: - Then, heigh-ho, the holly! - This life is most jolly. - Freeze, freeze, thou bitter sky, - That dost not bite so nigh - As benefits forgot: - Though thou the waters warp, - Thy sting is not so sharp - As friend remember'd not. - Heigh-ho! sing, &c. - -DUKE SENIOR If that you were the good Sir Rowland's son, - As you have whisper'd faithfully you were, - And as mine eye doth his effigies witness - Most truly limn'd and living in your face, - Be truly welcome hither: I am the duke - That loved your father: the residue of your fortune, - Go to my cave and tell me. Good old man, - Thou art right welcome as thy master is. - Support him by the arm. Give me your hand, - And let me all your fortunes understand. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT III - - - -SCENE I A room in the palace. - - - [Enter DUKE FREDERICK, Lords, and OLIVER] - -DUKE FREDERICK Not see him since? Sir, sir, that cannot be: - But were I not the better part made mercy, - I should not seek an absent argument - Of my revenge, thou present. But look to it: - Find out thy brother, wheresoe'er he is; - Seek him with candle; bring him dead or living - Within this twelvemonth, or turn thou no more - To seek a living in our territory. - Thy lands and all things that thou dost call thine - Worth seizure do we seize into our hands, - Till thou canst quit thee by thy brothers mouth - Of what we think against thee. - -OLIVER O that your highness knew my heart in this! - I never loved my brother in my life. - -DUKE FREDERICK More villain thou. Well, push him out of doors; - And let my officers of such a nature - Make an extent upon his house and lands: - Do this expediently and turn him going. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT III - - - -SCENE II The forest. - - - [Enter ORLANDO, with a paper] - -ORLANDO Hang there, my verse, in witness of my love: - And thou, thrice-crowned queen of night, survey - With thy chaste eye, from thy pale sphere above, - Thy huntress' name that my full life doth sway. - O Rosalind! these trees shall be my books - And in their barks my thoughts I'll character; - That every eye which in this forest looks - Shall see thy virtue witness'd every where. - Run, run, Orlando; carve on every tree - The fair, the chaste and unexpressive she. - - [Exit] - - [Enter CORIN and TOUCHSTONE] - -CORIN And how like you this shepherd's life, Master Touchstone? - -TOUCHSTONE Truly, shepherd, in respect of itself, it is a good - life, but in respect that it is a shepherd's life, - it is naught. In respect that it is solitary, I - like it very well; but in respect that it is - private, it is a very vile life. Now, in respect it - is in the fields, it pleaseth me well; but in - respect it is not in the court, it is tedious. As - is it a spare life, look you, it fits my humour well; - but as there is no more plenty in it, it goes much - against my stomach. Hast any philosophy in thee, shepherd? - -CORIN No more but that I know the more one sickens the - worse at ease he is; and that he that wants money, - means and content is without three good friends; - that the property of rain is to wet and fire to - burn; that good pasture makes fat sheep, and that a - great cause of the night is lack of the sun; that - he that hath learned no wit by nature nor art may - complain of good breeding or comes of a very dull kindred. - -TOUCHSTONE Such a one is a natural philosopher. Wast ever in - court, shepherd? - -CORIN No, truly. - -TOUCHSTONE Then thou art damned. - -CORIN Nay, I hope. - -TOUCHSTONE Truly, thou art damned like an ill-roasted egg, all - on one side. - -CORIN For not being at court? Your reason. - -TOUCHSTONE Why, if thou never wast at court, thou never sawest - good manners; if thou never sawest good manners, - then thy manners must be wicked; and wickedness is - sin, and sin is damnation. Thou art in a parlous - state, shepherd. - -CORIN Not a whit, Touchstone: those that are good manners - at the court are as ridiculous in the country as the - behavior of the country is most mockable at the - court. You told me you salute not at the court, but - you kiss your hands: that courtesy would be - uncleanly, if courtiers were shepherds. - -TOUCHSTONE Instance, briefly; come, instance. - -CORIN Why, we are still handling our ewes, and their - fells, you know, are greasy. - -TOUCHSTONE Why, do not your courtier's hands sweat? and is not - the grease of a mutton as wholesome as the sweat of - a man? Shallow, shallow. A better instance, I say; come. - -CORIN Besides, our hands are hard. - -TOUCHSTONE Your lips will feel them the sooner. Shallow again. - A more sounder instance, come. - -CORIN And they are often tarred over with the surgery of - our sheep: and would you have us kiss tar? The - courtier's hands are perfumed with civet. - -TOUCHSTONE Most shallow man! thou worms-meat, in respect of a - good piece of flesh indeed! Learn of the wise, and - perpend: civet is of a baser birth than tar, the - very uncleanly flux of a cat. Mend the instance, shepherd. - -CORIN You have too courtly a wit for me: I'll rest. - -TOUCHSTONE Wilt thou rest damned? God help thee, shallow man! - God make incision in thee! thou art raw. - -CORIN Sir, I am a true labourer: I earn that I eat, get - that I wear, owe no man hate, envy no man's - happiness, glad of other men's good, content with my - harm, and the greatest of my pride is to see my ewes - graze and my lambs suck. - -TOUCHSTONE That is another simple sin in you, to bring the ewes - and the rams together and to offer to get your - living by the copulation of cattle; to be bawd to a - bell-wether, and to betray a she-lamb of a - twelvemonth to a crooked-pated, old, cuckoldly ram, - out of all reasonable match. If thou beest not - damned for this, the devil himself will have no - shepherds; I cannot see else how thou shouldst - 'scape. - -CORIN Here comes young Master Ganymede, my new mistress's brother. - - [Enter ROSALIND, with a paper, reading] - -ROSALIND From the east to western Ind, - No jewel is like Rosalind. - Her worth, being mounted on the wind, - Through all the world bears Rosalind. - All the pictures fairest lined - Are but black to Rosalind. - Let no fair be kept in mind - But the fair of Rosalind. - -TOUCHSTONE I'll rhyme you so eight years together, dinners and - suppers and sleeping-hours excepted: it is the - right butter-women's rank to market. - -ROSALIND Out, fool! - -TOUCHSTONE For a taste: - If a hart do lack a hind, - Let him seek out Rosalind. - If the cat will after kind, - So be sure will Rosalind. - Winter garments must be lined, - So must slender Rosalind. - They that reap must sheaf and bind; - Then to cart with Rosalind. - Sweetest nut hath sourest rind, - Such a nut is Rosalind. - He that sweetest rose will find - Must find love's prick and Rosalind. - This is the very false gallop of verses: why do you - infect yourself with them? - -ROSALIND Peace, you dull fool! I found them on a tree. - -TOUCHSTONE Truly, the tree yields bad fruit. - -ROSALIND I'll graff it with you, and then I shall graff it - with a medlar: then it will be the earliest fruit - i' the country; for you'll be rotten ere you be half - ripe, and that's the right virtue of the medlar. - -TOUCHSTONE You have said; but whether wisely or no, let the - forest judge. - - [Enter CELIA, with a writing] - -ROSALIND Peace! Here comes my sister, reading: stand aside. - -CELIA [Reads] - - Why should this a desert be? - For it is unpeopled? No: - Tongues I'll hang on every tree, - That shall civil sayings show: - Some, how brief the life of man - Runs his erring pilgrimage, - That the stretching of a span - Buckles in his sum of age; - Some, of violated vows - 'Twixt the souls of friend and friend: - But upon the fairest boughs, - Or at every sentence end, - Will I Rosalinda write, - Teaching all that read to know - The quintessence of every sprite - Heaven would in little show. - Therefore Heaven Nature charged - That one body should be fill'd - With all graces wide-enlarged: - Nature presently distill'd - Helen's cheek, but not her heart, - Cleopatra's majesty, - Atalanta's better part, - Sad Lucretia's modesty. - Thus Rosalind of many parts - By heavenly synod was devised, - Of many faces, eyes and hearts, - To have the touches dearest prized. - Heaven would that she these gifts should have, - And I to live and die her slave. - -ROSALIND O most gentle pulpiter! what tedious homily of love - have you wearied your parishioners withal, and never - cried 'Have patience, good people!' - -CELIA How now! back, friends! Shepherd, go off a little. - Go with him, sirrah. - -TOUCHSTONE Come, shepherd, let us make an honourable retreat; - though not with bag and baggage, yet with scrip and scrippage. - - [Exeunt CORIN and TOUCHSTONE] - -CELIA Didst thou hear these verses? - -ROSALIND O, yes, I heard them all, and more too; for some of - them had in them more feet than the verses would bear. - -CELIA That's no matter: the feet might bear the verses. - -ROSALIND Ay, but the feet were lame and could not bear - themselves without the verse and therefore stood - lamely in the verse. - -CELIA But didst thou hear without wondering how thy name - should be hanged and carved upon these trees? - -ROSALIND I was seven of the nine days out of the wonder - before you came; for look here what I found on a - palm-tree. I was never so be-rhymed since - Pythagoras' time, that I was an Irish rat, which I - can hardly remember. - -CELIA Trow you who hath done this? - -ROSALIND Is it a man? - -CELIA And a chain, that you once wore, about his neck. - Change you colour? - -ROSALIND I prithee, who? - -CELIA O Lord, Lord! it is a hard matter for friends to - meet; but mountains may be removed with earthquakes - and so encounter. - -ROSALIND Nay, but who is it? - -CELIA Is it possible? - -ROSALIND Nay, I prithee now with most petitionary vehemence, - tell me who it is. - -CELIA O wonderful, wonderful, and most wonderful - wonderful! and yet again wonderful, and after that, - out of all hooping! - -ROSALIND Good my complexion! dost thou think, though I am - caparisoned like a man, I have a doublet and hose in - my disposition? One inch of delay more is a - South-sea of discovery; I prithee, tell me who is it - quickly, and speak apace. I would thou couldst - stammer, that thou mightst pour this concealed man - out of thy mouth, as wine comes out of a narrow- - mouthed bottle, either too much at once, or none at - all. I prithee, take the cork out of thy mouth that - may drink thy tidings. - -CELIA So you may put a man in your belly. - -ROSALIND Is he of God's making? What manner of man? Is his - head worth a hat, or his chin worth a beard? - -CELIA Nay, he hath but a little beard. - -ROSALIND Why, God will send more, if the man will be - thankful: let me stay the growth of his beard, if - thou delay me not the knowledge of his chin. - -CELIA It is young Orlando, that tripped up the wrestler's - heels and your heart both in an instant. - -ROSALIND Nay, but the devil take mocking: speak, sad brow and - true maid. - -CELIA I' faith, coz, 'tis he. - -ROSALIND Orlando? - -CELIA Orlando. - -ROSALIND Alas the day! what shall I do with my doublet and - hose? What did he when thou sawest him? What said - he? How looked he? Wherein went he? What makes - him here? Did he ask for me? Where remains he? - How parted he with thee? and when shalt thou see - him again? Answer me in one word. - -CELIA You must borrow me Gargantua's mouth first: 'tis a - word too great for any mouth of this age's size. To - say ay and no to these particulars is more than to - answer in a catechism. - -ROSALIND But doth he know that I am in this forest and in - man's apparel? Looks he as freshly as he did the - day he wrestled? - -CELIA It is as easy to count atomies as to resolve the - propositions of a lover; but take a taste of my - finding him, and relish it with good observance. - I found him under a tree, like a dropped acorn. - -ROSALIND It may well be called Jove's tree, when it drops - forth such fruit. - -CELIA Give me audience, good madam. - -ROSALIND Proceed. - -CELIA There lay he, stretched along, like a wounded knight. - -ROSALIND Though it be pity to see such a sight, it well - becomes the ground. - -CELIA Cry 'holla' to thy tongue, I prithee; it curvets - unseasonably. He was furnished like a hunter. - -ROSALIND O, ominous! he comes to kill my heart. - -CELIA I would sing my song without a burden: thou bringest - me out of tune. - -ROSALIND Do you not know I am a woman? when I think, I must - speak. Sweet, say on. - -CELIA You bring me out. Soft! comes he not here? - - [Enter ORLANDO and JAQUES] - -ROSALIND 'Tis he: slink by, and note him. - -JAQUES I thank you for your company; but, good faith, I had - as lief have been myself alone. - -ORLANDO And so had I; but yet, for fashion sake, I thank you - too for your society. - -JAQUES God be wi' you: let's meet as little as we can. - -ORLANDO I do desire we may be better strangers. - -JAQUES I pray you, mar no more trees with writing - love-songs in their barks. - -ORLANDO I pray you, mar no more of my verses with reading - them ill-favouredly. - -JAQUES Rosalind is your love's name? - -ORLANDO Yes, just. - -JAQUES I do not like her name. - -ORLANDO There was no thought of pleasing you when she was - christened. - -JAQUES What stature is she of? - -ORLANDO Just as high as my heart. - -JAQUES You are full of pretty answers. Have you not been - acquainted with goldsmiths' wives, and conned them - out of rings? - -ORLANDO Not so; but I answer you right painted cloth, from - whence you have studied your questions. - -JAQUES You have a nimble wit: I think 'twas made of - Atalanta's heels. Will you sit down with me? and - we two will rail against our mistress the world and - all our misery. - -ORLANDO I will chide no breather in the world but myself, - against whom I know most faults. - -JAQUES The worst fault you have is to be in love. - -ORLANDO 'Tis a fault I will not change for your best virtue. - I am weary of you. - -JAQUES By my troth, I was seeking for a fool when I found - you. - -ORLANDO He is drowned in the brook: look but in, and you - shall see him. - -JAQUES There I shall see mine own figure. - -ORLANDO Which I take to be either a fool or a cipher. - -JAQUES I'll tarry no longer with you: farewell, good - Signior Love. - -ORLANDO I am glad of your departure: adieu, good Monsieur - Melancholy. - - [Exit JAQUES] - -ROSALIND [Aside to CELIA] I will speak to him, like a saucy - lackey and under that habit play the knave with him. - Do you hear, forester? - -ORLANDO Very well: what would you? - -ROSALIND I pray you, what is't o'clock? - -ORLANDO You should ask me what time o' day: there's no clock - in the forest. - -ROSALIND Then there is no true lover in the forest; else - sighing every minute and groaning every hour would - detect the lazy foot of Time as well as a clock. - -ORLANDO And why not the swift foot of Time? had not that - been as proper? - -ROSALIND By no means, sir: Time travels in divers paces with - divers persons. I'll tell you who Time ambles - withal, who Time trots withal, who Time gallops - withal and who he stands still withal. - -ORLANDO I prithee, who doth he trot withal? - -ROSALIND Marry, he trots hard with a young maid between the - contract of her marriage and the day it is - solemnized: if the interim be but a se'nnight, - Time's pace is so hard that it seems the length of - seven year. - -ORLANDO Who ambles Time withal? - -ROSALIND With a priest that lacks Latin and a rich man that - hath not the gout, for the one sleeps easily because - he cannot study, and the other lives merrily because - he feels no pain, the one lacking the burden of lean - and wasteful learning, the other knowing no burden - of heavy tedious penury; these Time ambles withal. - -ORLANDO Who doth he gallop withal? - -ROSALIND With a thief to the gallows, for though he go as - softly as foot can fall, he thinks himself too soon there. - -ORLANDO Who stays it still withal? - -ROSALIND With lawyers in the vacation, for they sleep between - term and term and then they perceive not how Time moves. - -ORLANDO Where dwell you, pretty youth? - -ROSALIND With this shepherdess, my sister; here in the - skirts of the forest, like fringe upon a petticoat. - -ORLANDO Are you native of this place? - -ROSALIND As the cony that you see dwell where she is kindled. - -ORLANDO Your accent is something finer than you could - purchase in so removed a dwelling. - -ROSALIND I have been told so of many: but indeed an old - religious uncle of mine taught me to speak, who was - in his youth an inland man; one that knew courtship - too well, for there he fell in love. I have heard - him read many lectures against it, and I thank God - I am not a woman, to be touched with so many - giddy offences as he hath generally taxed their - whole sex withal. - -ORLANDO Can you remember any of the principal evils that he - laid to the charge of women? - -ROSALIND There were none principal; they were all like one - another as half-pence are, every one fault seeming - monstrous till his fellow fault came to match it. - -ORLANDO I prithee, recount some of them. - -ROSALIND No, I will not cast away my physic but on those that - are sick. There is a man haunts the forest, that - abuses our young plants with carving 'Rosalind' on - their barks; hangs odes upon hawthorns and elegies - on brambles, all, forsooth, deifying the name of - Rosalind: if I could meet that fancy-monger I would - give him some good counsel, for he seems to have the - quotidian of love upon him. - -ORLANDO I am he that is so love-shaked: I pray you tell me - your remedy. - -ROSALIND There is none of my uncle's marks upon you: he - taught me how to know a man in love; in which cage - of rushes I am sure you are not prisoner. - -ORLANDO What were his marks? - -ROSALIND A lean cheek, which you have not, a blue eye and - sunken, which you have not, an unquestionable - spirit, which you have not, a beard neglected, - which you have not; but I pardon you for that, for - simply your having in beard is a younger brother's - revenue: then your hose should be ungartered, your - bonnet unbanded, your sleeve unbuttoned, your shoe - untied and every thing about you demonstrating a - careless desolation; but you are no such man; you - are rather point-device in your accoutrements as - loving yourself than seeming the lover of any other. - -ORLANDO Fair youth, I would I could make thee believe I love. - -ROSALIND Me believe it! you may as soon make her that you - love believe it; which, I warrant, she is apter to - do than to confess she does: that is one of the - points in the which women still give the lie to - their consciences. But, in good sooth, are you he - that hangs the verses on the trees, wherein Rosalind - is so admired? - -ORLANDO I swear to thee, youth, by the white hand of - Rosalind, I am that he, that unfortunate he. - -ROSALIND But are you so much in love as your rhymes speak? - -ORLANDO Neither rhyme nor reason can express how much. - -ROSALIND Love is merely a madness, and, I tell you, deserves - as well a dark house and a whip as madmen do: and - the reason why they are not so punished and cured - is, that the lunacy is so ordinary that the whippers - are in love too. Yet I profess curing it by counsel. - -ORLANDO Did you ever cure any so? - -ROSALIND Yes, one, and in this manner. He was to imagine me - his love, his mistress; and I set him every day to - woo me: at which time would I, being but a moonish - youth, grieve, be effeminate, changeable, longing - and liking, proud, fantastical, apish, shallow, - inconstant, full of tears, full of smiles, for every - passion something and for no passion truly any - thing, as boys and women are for the most part - cattle of this colour; would now like him, now loathe - him; then entertain him, then forswear him; now weep - for him, then spit at him; that I drave my suitor - from his mad humour of love to a living humour of - madness; which was, to forswear the full stream of - the world, and to live in a nook merely monastic. - And thus I cured him; and this way will I take upon - me to wash your liver as clean as a sound sheep's - heart, that there shall not be one spot of love in't. - -ORLANDO I would not be cured, youth. - -ROSALIND I would cure you, if you would but call me Rosalind - and come every day to my cote and woo me. - -ORLANDO Now, by the faith of my love, I will: tell me - where it is. - -ROSALIND Go with me to it and I'll show it you and by the way - you shall tell me where in the forest you live. - Will you go? - -ORLANDO With all my heart, good youth. - -ROSALIND Nay you must call me Rosalind. Come, sister, will you go? - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT III - - - -SCENE III The forest. - - - [Enter TOUCHSTONE and AUDREY; JAQUES behind] - -TOUCHSTONE Come apace, good Audrey: I will fetch up your - goats, Audrey. And how, Audrey? am I the man yet? - doth my simple feature content you? - -AUDREY Your features! Lord warrant us! what features! - -TOUCHSTONE I am here with thee and thy goats, as the most - capricious poet, honest Ovid, was among the Goths. - -JAQUES [Aside] O knowledge ill-inhabited, worse than Jove - in a thatched house! - -TOUCHSTONE When a man's verses cannot be understood, nor a - man's good wit seconded with the forward child - Understanding, it strikes a man more dead than a - great reckoning in a little room. Truly, I would - the gods had made thee poetical. - -AUDREY I do not know what 'poetical' is: is it honest in - deed and word? is it a true thing? - -TOUCHSTONE No, truly; for the truest poetry is the most - feigning; and lovers are given to poetry, and what - they swear in poetry may be said as lovers they do feign. - -AUDREY Do you wish then that the gods had made me poetical? - -TOUCHSTONE I do, truly; for thou swearest to me thou art - honest: now, if thou wert a poet, I might have some - hope thou didst feign. - -AUDREY Would you not have me honest? - -TOUCHSTONE No, truly, unless thou wert hard-favoured; for - honesty coupled to beauty is to have honey a sauce to sugar. - -JAQUES [Aside] A material fool! - -AUDREY Well, I am not fair; and therefore I pray the gods - make me honest. - -TOUCHSTONE Truly, and to cast away honesty upon a foul slut - were to put good meat into an unclean dish. - -AUDREY I am not a slut, though I thank the gods I am foul. - -TOUCHSTONE Well, praised be the gods for thy foulness! - sluttishness may come hereafter. But be it as it may - be, I will marry thee, and to that end I have been - with Sir Oliver Martext, the vicar of the next - village, who hath promised to meet me in this place - of the forest and to couple us. - -JAQUES [Aside] I would fain see this meeting. - -AUDREY Well, the gods give us joy! - -TOUCHSTONE Amen. A man may, if he were of a fearful heart, - stagger in this attempt; for here we have no temple - but the wood, no assembly but horn-beasts. But what - though? Courage! As horns are odious, they are - necessary. It is said, 'many a man knows no end of - his goods:' right; many a man has good horns, and - knows no end of them. Well, that is the dowry of - his wife; 'tis none of his own getting. Horns? - Even so. Poor men alone? No, no; the noblest deer - hath them as huge as the rascal. Is the single man - therefore blessed? No: as a walled town is more - worthier than a village, so is the forehead of a - married man more honourable than the bare brow of a - bachelor; and by how much defence is better than no - skill, by so much is a horn more precious than to - want. Here comes Sir Oliver. - - [Enter SIR OLIVER MARTEXT] - - Sir Oliver Martext, you are well met: will you - dispatch us here under this tree, or shall we go - with you to your chapel? - -SIR OLIVER MARTEXT Is there none here to give the woman? - -TOUCHSTONE I will not take her on gift of any man. - -SIR OLIVER MARTEXT Truly, she must be given, or the marriage is not lawful. - -JAQUES [Advancing] - - Proceed, proceed I'll give her. - -TOUCHSTONE Good even, good Master What-ye-call't: how do you, - sir? You are very well met: God 'ild you for your - last company: I am very glad to see you: even a - toy in hand here, sir: nay, pray be covered. - -JAQUES Will you be married, motley? - -TOUCHSTONE As the ox hath his bow, sir, the horse his curb and - the falcon her bells, so man hath his desires; and - as pigeons bill, so wedlock would be nibbling. - -JAQUES And will you, being a man of your breeding, be - married under a bush like a beggar? Get you to - church, and have a good priest that can tell you - what marriage is: this fellow will but join you - together as they join wainscot; then one of you will - prove a shrunk panel and, like green timber, warp, warp. - -TOUCHSTONE [Aside] I am not in the mind but I were better to be - married of him than of another: for he is not like - to marry me well; and not being well married, it - will be a good excuse for me hereafter to leave my wife. - -JAQUES Go thou with me, and let me counsel thee. - -TOUCHSTONE 'Come, sweet Audrey: - We must be married, or we must live in bawdry. - Farewell, good Master Oliver: not,-- - O sweet Oliver, - O brave Oliver, - Leave me not behind thee: but,-- - Wind away, - Begone, I say, - I will not to wedding with thee. - - [Exeunt JAQUES, TOUCHSTONE and AUDREY] - -SIR OLIVER MARTEXT 'Tis no matter: ne'er a fantastical knave of them - all shall flout me out of my calling. - - [Exit] - - - - - AS YOU LIKE IT - - -ACT III - - - -SCENE IV The forest. - - - [Enter ROSALIND and CELIA] - -ROSALIND Never talk to me; I will weep. - -CELIA Do, I prithee; but yet have the grace to consider - that tears do not become a man. - -ROSALIND But have I not cause to weep? - -CELIA As good cause as one would desire; therefore weep. - -ROSALIND His very hair is of the dissembling colour. - -CELIA Something browner than Judas's marry, his kisses are - Judas's own children. - -ROSALIND I' faith, his hair is of a good colour. - -CELIA An excellent colour: your chestnut was ever the only colour. - -ROSALIND And his kissing is as full of sanctity as the touch - of holy bread. - -CELIA He hath bought a pair of cast lips of Diana: a nun - of winter's sisterhood kisses not more religiously; - the very ice of chastity is in them. - -ROSALIND But why did he swear he would come this morning, and - comes not? - -CELIA Nay, certainly, there is no truth in him. - -ROSALIND Do you think so? - -CELIA Yes; I think he is not a pick-purse nor a - horse-stealer, but for his verity in love, I do - think him as concave as a covered goblet or a - worm-eaten nut. - -ROSALIND Not true in love? - -CELIA Yes, when he is in; but I think he is not in. - -ROSALIND You have heard him swear downright he was. - -CELIA 'Was' is not 'is:' besides, the oath of a lover is - no stronger than the word of a tapster; they are - both the confirmer of false reckonings. He attends - here in the forest on the duke your father. - -ROSALIND I met the duke yesterday and had much question with - him: he asked me of what parentage I was; I told - him, of as good as he; so he laughed and let me go. - But what talk we of fathers, when there is such a - man as Orlando? - -CELIA O, that's a brave man! he writes brave verses, - speaks brave words, swears brave oaths and breaks - them bravely, quite traverse, athwart the heart of - his lover; as a puisny tilter, that spurs his horse - but on one side, breaks his staff like a noble - goose: but all's brave that youth mounts and folly - guides. Who comes here? - - [Enter CORIN] - -CORIN Mistress and master, you have oft inquired - After the shepherd that complain'd of love, - Who you saw sitting by me on the turf, - Praising the proud disdainful shepherdess - That was his mistress. - -CELIA Well, and what of him? - -CORIN If you will see a pageant truly play'd, - Between the pale complexion of true love - And the red glow of scorn and proud disdain, - Go hence a little and I shall conduct you, - If you will mark it. - -ROSALIND O, come, let us remove: - The sight of lovers feedeth those in love. - Bring us to this sight, and you shall say - I'll prove a busy actor in their play. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT III - - - -SCENE V Another part of the forest. - - - [Enter SILVIUS and PHEBE] - -SILVIUS Sweet Phebe, do not scorn me; do not, Phebe; - Say that you love me not, but say not so - In bitterness. The common executioner, - Whose heart the accustom'd sight of death makes hard, - Falls not the axe upon the humbled neck - But first begs pardon: will you sterner be - Than he that dies and lives by bloody drops? - - [Enter ROSALIND, CELIA, and CORIN, behind] - -PHEBE I would not be thy executioner: - I fly thee, for I would not injure thee. - Thou tell'st me there is murder in mine eye: - 'Tis pretty, sure, and very probable, - That eyes, that are the frail'st and softest things, - Who shut their coward gates on atomies, - Should be call'd tyrants, butchers, murderers! - Now I do frown on thee with all my heart; - And if mine eyes can wound, now let them kill thee: - Now counterfeit to swoon; why now fall down; - Or if thou canst not, O, for shame, for shame, - Lie not, to say mine eyes are murderers! - Now show the wound mine eye hath made in thee: - Scratch thee but with a pin, and there remains - Some scar of it; lean but upon a rush, - The cicatrice and capable impressure - Thy palm some moment keeps; but now mine eyes, - Which I have darted at thee, hurt thee not, - Nor, I am sure, there is no force in eyes - That can do hurt. - -SILVIUS O dear Phebe, - If ever,--as that ever may be near,-- - You meet in some fresh cheek the power of fancy, - Then shall you know the wounds invisible - That love's keen arrows make. - -PHEBE But till that time - Come not thou near me: and when that time comes, - Afflict me with thy mocks, pity me not; - As till that time I shall not pity thee. - -ROSALIND And why, I pray you? Who might be your mother, - That you insult, exult, and all at once, - Over the wretched? What though you have no beauty,-- - As, by my faith, I see no more in you - Than without candle may go dark to bed-- - Must you be therefore proud and pitiless? - Why, what means this? Why do you look on me? - I see no more in you than in the ordinary - Of nature's sale-work. 'Od's my little life, - I think she means to tangle my eyes too! - No, faith, proud mistress, hope not after it: - 'Tis not your inky brows, your black silk hair, - Your bugle eyeballs, nor your cheek of cream, - That can entame my spirits to your worship. - You foolish shepherd, wherefore do you follow her, - Like foggy south puffing with wind and rain? - You are a thousand times a properer man - Than she a woman: 'tis such fools as you - That makes the world full of ill-favour'd children: - 'Tis not her glass, but you, that flatters her; - And out of you she sees herself more proper - Than any of her lineaments can show her. - But, mistress, know yourself: down on your knees, - And thank heaven, fasting, for a good man's love: - For I must tell you friendly in your ear, - Sell when you can: you are not for all markets: - Cry the man mercy; love him; take his offer: - Foul is most foul, being foul to be a scoffer. - So take her to thee, shepherd: fare you well. - -PHEBE Sweet youth, I pray you, chide a year together: - I had rather hear you chide than this man woo. - -ROSALIND He's fallen in love with your foulness and she'll - fall in love with my anger. If it be so, as fast as - she answers thee with frowning looks, I'll sauce her - with bitter words. Why look you so upon me? - -PHEBE For no ill will I bear you. - -ROSALIND I pray you, do not fall in love with me, - For I am falser than vows made in wine: - Besides, I like you not. If you will know my house, - 'Tis at the tuft of olives here hard by. - Will you go, sister? Shepherd, ply her hard. - Come, sister. Shepherdess, look on him better, - And be not proud: though all the world could see, - None could be so abused in sight as he. - Come, to our flock. - - [Exeunt ROSALIND, CELIA and CORIN] - -PHEBE Dead Shepherd, now I find thy saw of might, - 'Who ever loved that loved not at first sight?' - -SILVIUS Sweet Phebe,-- - -PHEBE Ha, what say'st thou, Silvius? - -SILVIUS Sweet Phebe, pity me. - -PHEBE Why, I am sorry for thee, gentle Silvius. - -SILVIUS Wherever sorrow is, relief would be: - If you do sorrow at my grief in love, - By giving love your sorrow and my grief - Were both extermined. - -PHEBE Thou hast my love: is not that neighbourly? - -SILVIUS I would have you. - -PHEBE Why, that were covetousness. - Silvius, the time was that I hated thee, - And yet it is not that I bear thee love; - But since that thou canst talk of love so well, - Thy company, which erst was irksome to me, - I will endure, and I'll employ thee too: - But do not look for further recompense - Than thine own gladness that thou art employ'd. - -SILVIUS So holy and so perfect is my love, - And I in such a poverty of grace, - That I shall think it a most plenteous crop - To glean the broken ears after the man - That the main harvest reaps: loose now and then - A scatter'd smile, and that I'll live upon. - -PHEBE Know'st now the youth that spoke to me erewhile? - -SILVIUS Not very well, but I have met him oft; - And he hath bought the cottage and the bounds - That the old carlot once was master of. - -PHEBE Think not I love him, though I ask for him: - 'Tis but a peevish boy; yet he talks well; - But what care I for words? yet words do well - When he that speaks them pleases those that hear. - It is a pretty youth: not very pretty: - But, sure, he's proud, and yet his pride becomes him: - He'll make a proper man: the best thing in him - Is his complexion; and faster than his tongue - Did make offence his eye did heal it up. - He is not very tall; yet for his years he's tall: - His leg is but so so; and yet 'tis well: - There was a pretty redness in his lip, - A little riper and more lusty red - Than that mix'd in his cheek; 'twas just the difference - Between the constant red and mingled damask. - There be some women, Silvius, had they mark'd him - In parcels as I did, would have gone near - To fall in love with him; but, for my part, - I love him not nor hate him not; and yet - I have more cause to hate him than to love him: - For what had he to do to chide at me? - He said mine eyes were black and my hair black: - And, now I am remember'd, scorn'd at me: - I marvel why I answer'd not again: - But that's all one; omittance is no quittance. - I'll write to him a very taunting letter, - And thou shalt bear it: wilt thou, Silvius? - -SILVIUS Phebe, with all my heart. - -PHEBE I'll write it straight; - The matter's in my head and in my heart: - I will be bitter with him and passing short. - Go with me, Silvius. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT IV - - - -SCENE I The forest. - - - [Enter ROSALIND, CELIA, and JAQUES] - -JAQUES I prithee, pretty youth, let me be better acquainted - with thee. - -ROSALIND They say you are a melancholy fellow. - -JAQUES I am so; I do love it better than laughing. - -ROSALIND Those that are in extremity of either are abominable - fellows and betray themselves to every modern - censure worse than drunkards. - -JAQUES Why, 'tis good to be sad and say nothing. - -ROSALIND Why then, 'tis good to be a post. - -JAQUES I have neither the scholar's melancholy, which is - emulation, nor the musician's, which is fantastical, - nor the courtier's, which is proud, nor the - soldier's, which is ambitious, nor the lawyer's, - which is politic, nor the lady's, which is nice, nor - the lover's, which is all these: but it is a - melancholy of mine own, compounded of many simples, - extracted from many objects, and indeed the sundry's - contemplation of my travels, in which my often - rumination wraps me m a most humorous sadness. - -ROSALIND A traveller! By my faith, you have great reason to - be sad: I fear you have sold your own lands to see - other men's; then, to have seen much and to have - nothing, is to have rich eyes and poor hands. - -JAQUES Yes, I have gained my experience. - -ROSALIND And your experience makes you sad: I had rather have - a fool to make me merry than experience to make me - sad; and to travel for it too! - - [Enter ORLANDO] - -ORLANDO Good day and happiness, dear Rosalind! - -JAQUES Nay, then, God be wi' you, an you talk in blank verse. - - [Exit] - -ROSALIND Farewell, Monsieur Traveller: look you lisp and - wear strange suits, disable all the benefits of your - own country, be out of love with your nativity and - almost chide God for making you that countenance you - are, or I will scarce think you have swam in a - gondola. Why, how now, Orlando! where have you been - all this while? You a lover! An you serve me such - another trick, never come in my sight more. - -ORLANDO My fair Rosalind, I come within an hour of my promise. - -ROSALIND Break an hour's promise in love! He that will - divide a minute into a thousand parts and break but - a part of the thousandth part of a minute in the - affairs of love, it may be said of him that Cupid - hath clapped him o' the shoulder, but I'll warrant - him heart-whole. - -ORLANDO Pardon me, dear Rosalind. - -ROSALIND Nay, an you be so tardy, come no more in my sight: I - had as lief be wooed of a snail. - -ORLANDO Of a snail? - -ROSALIND Ay, of a snail; for though he comes slowly, he - carries his house on his head; a better jointure, - I think, than you make a woman: besides he brings - his destiny with him. - -ORLANDO What's that? - -ROSALIND Why, horns, which such as you are fain to be - beholding to your wives for: but he comes armed in - his fortune and prevents the slander of his wife. - -ORLANDO Virtue is no horn-maker; and my Rosalind is virtuous. - -ROSALIND And I am your Rosalind. - -CELIA It pleases him to call you so; but he hath a - Rosalind of a better leer than you. - -ROSALIND Come, woo me, woo me, for now I am in a holiday - humour and like enough to consent. What would you - say to me now, an I were your very very Rosalind? - -ORLANDO I would kiss before I spoke. - -ROSALIND Nay, you were better speak first, and when you were - gravelled for lack of matter, you might take - occasion to kiss. Very good orators, when they are - out, they will spit; and for lovers lacking--God - warn us!--matter, the cleanliest shift is to kiss. - -ORLANDO How if the kiss be denied? - -ROSALIND Then she puts you to entreaty, and there begins new matter. - -ORLANDO Who could be out, being before his beloved mistress? - -ROSALIND Marry, that should you, if I were your mistress, or - I should think my honesty ranker than my wit. - -ORLANDO What, of my suit? - -ROSALIND Not out of your apparel, and yet out of your suit. - Am not I your Rosalind? - -ORLANDO I take some joy to say you are, because I would be - talking of her. - -ROSALIND Well in her person I say I will not have you. - -ORLANDO Then in mine own person I die. - -ROSALIND No, faith, die by attorney. The poor world is - almost six thousand years old, and in all this time - there was not any man died in his own person, - videlicit, in a love-cause. Troilus had his brains - dashed out with a Grecian club; yet he did what he - could to die before, and he is one of the patterns - of love. Leander, he would have lived many a fair - year, though Hero had turned nun, if it had not been - for a hot midsummer night; for, good youth, he went - but forth to wash him in the Hellespont and being - taken with the cramp was drowned and the foolish - coroners of that age found it was 'Hero of Sestos.' - But these are all lies: men have died from time to - time and worms have eaten them, but not for love. - -ORLANDO I would not have my right Rosalind of this mind, - for, I protest, her frown might kill me. - -ROSALIND By this hand, it will not kill a fly. But come, now - I will be your Rosalind in a more coming-on - disposition, and ask me what you will. I will grant - it. - -ORLANDO Then love me, Rosalind. - -ROSALIND Yes, faith, will I, Fridays and Saturdays and all. - -ORLANDO And wilt thou have me? - -ROSALIND Ay, and twenty such. - -ORLANDO What sayest thou? - -ROSALIND Are you not good? - -ORLANDO I hope so. - -ROSALIND Why then, can one desire too much of a good thing? - Come, sister, you shall be the priest and marry us. - Give me your hand, Orlando. What do you say, sister? - -ORLANDO Pray thee, marry us. - -CELIA I cannot say the words. - -ROSALIND You must begin, 'Will you, Orlando--' - -CELIA Go to. Will you, Orlando, have to wife this Rosalind? - -ORLANDO I will. - -ROSALIND Ay, but when? - -ORLANDO Why now; as fast as she can marry us. - -ROSALIND Then you must say 'I take thee, Rosalind, for wife.' - -ORLANDO I take thee, Rosalind, for wife. - -ROSALIND I might ask you for your commission; but I do take - thee, Orlando, for my husband: there's a girl goes - before the priest; and certainly a woman's thought - runs before her actions. - -ORLANDO So do all thoughts; they are winged. - -ROSALIND Now tell me how long you would have her after you - have possessed her. - -ORLANDO For ever and a day. - -ROSALIND Say 'a day,' without the 'ever.' No, no, Orlando; - men are April when they woo, December when they wed: - maids are May when they are maids, but the sky - changes when they are wives. I will be more jealous - of thee than a Barbary cock-pigeon over his hen, - more clamorous than a parrot against rain, more - new-fangled than an ape, more giddy in my desires - than a monkey: I will weep for nothing, like Diana - in the fountain, and I will do that when you are - disposed to be merry; I will laugh like a hyen, and - that when thou art inclined to sleep. - -ORLANDO But will my Rosalind do so? - -ROSALIND By my life, she will do as I do. - -ORLANDO O, but she is wise. - -ROSALIND Or else she could not have the wit to do this: the - wiser, the waywarder: make the doors upon a woman's - wit and it will out at the casement; shut that and - 'twill out at the key-hole; stop that, 'twill fly - with the smoke out at the chimney. - -ORLANDO A man that had a wife with such a wit, he might say - 'Wit, whither wilt?' - -ROSALIND Nay, you might keep that cheque for it till you met - your wife's wit going to your neighbour's bed. - -ORLANDO And what wit could wit have to excuse that? - -ROSALIND Marry, to say she came to seek you there. You shall - never take her without her answer, unless you take - her without her tongue. O, that woman that cannot - make her fault her husband's occasion, let her - never nurse her child herself, for she will breed - it like a fool! - -ORLANDO For these two hours, Rosalind, I will leave thee. - -ROSALIND Alas! dear love, I cannot lack thee two hours. - -ORLANDO I must attend the duke at dinner: by two o'clock I - will be with thee again. - -ROSALIND Ay, go your ways, go your ways; I knew what you - would prove: my friends told me as much, and I - thought no less: that flattering tongue of yours - won me: 'tis but one cast away, and so, come, - death! Two o'clock is your hour? - -ORLANDO Ay, sweet Rosalind. - -ROSALIND By my troth, and in good earnest, and so God mend - me, and by all pretty oaths that are not dangerous, - if you break one jot of your promise or come one - minute behind your hour, I will think you the most - pathetical break-promise and the most hollow lover - and the most unworthy of her you call Rosalind that - may be chosen out of the gross band of the - unfaithful: therefore beware my censure and keep - your promise. - -ORLANDO With no less religion than if thou wert indeed my - Rosalind: so adieu. - -ROSALIND Well, Time is the old justice that examines all such - offenders, and let Time try: adieu. - - [Exit ORLANDO] - -CELIA You have simply misused our sex in your love-prate: - we must have your doublet and hose plucked over your - head, and show the world what the bird hath done to - her own nest. - -ROSALIND O coz, coz, coz, my pretty little coz, that thou - didst know how many fathom deep I am in love! But - it cannot be sounded: my affection hath an unknown - bottom, like the bay of Portugal. - -CELIA Or rather, bottomless, that as fast as you pour - affection in, it runs out. - -ROSALIND No, that same wicked bastard of Venus that was begot - of thought, conceived of spleen and born of madness, - that blind rascally boy that abuses every one's eyes - because his own are out, let him be judge how deep I - am in love. I'll tell thee, Aliena, I cannot be out - of the sight of Orlando: I'll go find a shadow and - sigh till he come. - -CELIA And I'll sleep. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT IV - - - -SCENE II The forest. - - - [Enter JAQUES, Lords, and Foresters] - -JAQUES Which is he that killed the deer? - -A Lord Sir, it was I. - -JAQUES Let's present him to the duke, like a Roman - conqueror; and it would do well to set the deer's - horns upon his head, for a branch of victory. Have - you no song, forester, for this purpose? - -Forester Yes, sir. - -JAQUES Sing it: 'tis no matter how it be in tune, so it - make noise enough. - - SONG. -Forester What shall he have that kill'd the deer? - His leather skin and horns to wear. - Then sing him home; - - [The rest shall bear this burden] - - Take thou no scorn to wear the horn; - It was a crest ere thou wast born: - Thy father's father wore it, - And thy father bore it: - The horn, the horn, the lusty horn - Is not a thing to laugh to scorn. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT IV - - - -SCENE III The forest. - - - [Enter ROSALIND and CELIA] - -ROSALIND How say you now? Is it not past two o'clock? and - here much Orlando! - -CELIA I warrant you, with pure love and troubled brain, he - hath ta'en his bow and arrows and is gone forth to - sleep. Look, who comes here. - - [Enter SILVIUS] - -SILVIUS My errand is to you, fair youth; - My gentle Phebe bid me give you this: - I know not the contents; but, as I guess - By the stern brow and waspish action - Which she did use as she was writing of it, - It bears an angry tenor: pardon me: - I am but as a guiltless messenger. - -ROSALIND Patience herself would startle at this letter - And play the swaggerer; bear this, bear all: - She says I am not fair, that I lack manners; - She calls me proud, and that she could not love me, - Were man as rare as phoenix. 'Od's my will! - Her love is not the hare that I do hunt: - Why writes she so to me? Well, shepherd, well, - This is a letter of your own device. - -SILVIUS No, I protest, I know not the contents: - Phebe did write it. - -ROSALIND Come, come, you are a fool - And turn'd into the extremity of love. - I saw her hand: she has a leathern hand. - A freestone-colour'd hand; I verily did think - That her old gloves were on, but 'twas her hands: - She has a huswife's hand; but that's no matter: - I say she never did invent this letter; - This is a man's invention and his hand. - -SILVIUS Sure, it is hers. - -ROSALIND Why, 'tis a boisterous and a cruel style. - A style for-challengers; why, she defies me, - Like Turk to Christian: women's gentle brain - Could not drop forth such giant-rude invention - Such Ethiope words, blacker in their effect - Than in their countenance. Will you hear the letter? - -SILVIUS So please you, for I never heard it yet; - Yet heard too much of Phebe's cruelty. - -ROSALIND She Phebes me: mark how the tyrant writes. - - [Reads] - - Art thou god to shepherd turn'd, - That a maiden's heart hath burn'd? - Can a woman rail thus? - -SILVIUS Call you this railing? - -ROSALIND [Reads] - - Why, thy godhead laid apart, - Warr'st thou with a woman's heart? - Did you ever hear such railing? - Whiles the eye of man did woo me, - That could do no vengeance to me. - Meaning me a beast. - If the scorn of your bright eyne - Have power to raise such love in mine, - Alack, in me what strange effect - Would they work in mild aspect! - Whiles you chid me, I did love; - How then might your prayers move! - He that brings this love to thee - Little knows this love in me: - And by him seal up thy mind; - Whether that thy youth and kind - Will the faithful offer take - Of me and all that I can make; - Or else by him my love deny, - And then I'll study how to die. - -SILVIUS Call you this chiding? - -CELIA Alas, poor shepherd! - -ROSALIND Do you pity him? no, he deserves no pity. Wilt - thou love such a woman? What, to make thee an - instrument and play false strains upon thee! not to - be endured! Well, go your way to her, for I see - love hath made thee a tame snake, and say this to - her: that if she love me, I charge her to love - thee; if she will not, I will never have her unless - thou entreat for her. If you be a true lover, - hence, and not a word; for here comes more company. - - [Exit SILVIUS] - - [Enter OLIVER] - -OLIVER Good morrow, fair ones: pray you, if you know, - Where in the purlieus of this forest stands - A sheep-cote fenced about with olive trees? - -CELIA West of this place, down in the neighbour bottom: - The rank of osiers by the murmuring stream - Left on your right hand brings you to the place. - But at this hour the house doth keep itself; - There's none within. - -OLIVER If that an eye may profit by a tongue, - Then should I know you by description; - Such garments and such years: 'The boy is fair, - Of female favour, and bestows himself - Like a ripe sister: the woman low - And browner than her brother.' Are not you - The owner of the house I did inquire for? - -CELIA It is no boast, being ask'd, to say we are. - -OLIVER Orlando doth commend him to you both, - And to that youth he calls his Rosalind - He sends this bloody napkin. Are you he? - -ROSALIND I am: what must we understand by this? - -OLIVER Some of my shame; if you will know of me - What man I am, and how, and why, and where - This handkercher was stain'd. - -CELIA I pray you, tell it. - -OLIVER When last the young Orlando parted from you - He left a promise to return again - Within an hour, and pacing through the forest, - Chewing the food of sweet and bitter fancy, - Lo, what befell! he threw his eye aside, - And mark what object did present itself: - Under an oak, whose boughs were moss'd with age - And high top bald with dry antiquity, - A wretched ragged man, o'ergrown with hair, - Lay sleeping on his back: about his neck - A green and gilded snake had wreathed itself, - Who with her head nimble in threats approach'd - The opening of his mouth; but suddenly, - Seeing Orlando, it unlink'd itself, - And with indented glides did slip away - Into a bush: under which bush's shade - A lioness, with udders all drawn dry, - Lay couching, head on ground, with catlike watch, - When that the sleeping man should stir; for 'tis - The royal disposition of that beast - To prey on nothing that doth seem as dead: - This seen, Orlando did approach the man - And found it was his brother, his elder brother. - -CELIA O, I have heard him speak of that same brother; - And he did render him the most unnatural - That lived amongst men. - -OLIVER And well he might so do, - For well I know he was unnatural. - -ROSALIND But, to Orlando: did he leave him there, - Food to the suck'd and hungry lioness? - -OLIVER Twice did he turn his back and purposed so; - But kindness, nobler ever than revenge, - And nature, stronger than his just occasion, - Made him give battle to the lioness, - Who quickly fell before him: in which hurtling - From miserable slumber I awaked. - -CELIA Are you his brother? - -ROSALIND Wast you he rescued? - -CELIA Was't you that did so oft contrive to kill him? - -OLIVER 'Twas I; but 'tis not I I do not shame - To tell you what I was, since my conversion - So sweetly tastes, being the thing I am. - -ROSALIND But, for the bloody napkin? - -OLIVER By and by. - When from the first to last betwixt us two - Tears our recountments had most kindly bathed, - As how I came into that desert place:-- - In brief, he led me to the gentle duke, - Who gave me fresh array and entertainment, - Committing me unto my brother's love; - Who led me instantly unto his cave, - There stripp'd himself, and here upon his arm - The lioness had torn some flesh away, - Which all this while had bled; and now he fainted - And cried, in fainting, upon Rosalind. - Brief, I recover'd him, bound up his wound; - And, after some small space, being strong at heart, - He sent me hither, stranger as I am, - To tell this story, that you might excuse - His broken promise, and to give this napkin - Dyed in his blood unto the shepherd youth - That he in sport doth call his Rosalind. - - [ROSALIND swoons] - -CELIA Why, how now, Ganymede! sweet Ganymede! - -OLIVER Many will swoon when they do look on blood. - -CELIA There is more in it. Cousin Ganymede! - -OLIVER Look, he recovers. - -ROSALIND I would I were at home. - -CELIA We'll lead you thither. - I pray you, will you take him by the arm? - -OLIVER Be of good cheer, youth: you a man! you lack a - man's heart. - -ROSALIND I do so, I confess it. Ah, sirrah, a body would - think this was well counterfeited! I pray you, tell - your brother how well I counterfeited. Heigh-ho! - -OLIVER This was not counterfeit: there is too great - testimony in your complexion that it was a passion - of earnest. - -ROSALIND Counterfeit, I assure you. - -OLIVER Well then, take a good heart and counterfeit to be a man. - -ROSALIND So I do: but, i' faith, I should have been a woman by right. - -CELIA Come, you look paler and paler: pray you, draw - homewards. Good sir, go with us. - -OLIVER That will I, for I must bear answer back - How you excuse my brother, Rosalind. - -ROSALIND I shall devise something: but, I pray you, commend - my counterfeiting to him. Will you go? - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT V - - - -SCENE I The forest. - - - [Enter TOUCHSTONE and AUDREY] - -TOUCHSTONE We shall find a time, Audrey; patience, gentle Audrey. - -AUDREY Faith, the priest was good enough, for all the old - gentleman's saying. - -TOUCHSTONE A most wicked Sir Oliver, Audrey, a most vile - Martext. But, Audrey, there is a youth here in the - forest lays claim to you. - -AUDREY Ay, I know who 'tis; he hath no interest in me in - the world: here comes the man you mean. - -TOUCHSTONE It is meat and drink to me to see a clown: by my - troth, we that have good wits have much to answer - for; we shall be flouting; we cannot hold. - - [Enter WILLIAM] - -WILLIAM Good even, Audrey. - -AUDREY God ye good even, William. - -WILLIAM And good even to you, sir. - -TOUCHSTONE Good even, gentle friend. Cover thy head, cover thy - head; nay, prithee, be covered. How old are you, friend? - -WILLIAM Five and twenty, sir. - -TOUCHSTONE A ripe age. Is thy name William? - -WILLIAM William, sir. - -TOUCHSTONE A fair name. Wast born i' the forest here? - -WILLIAM Ay, sir, I thank God. - -TOUCHSTONE 'Thank God;' a good answer. Art rich? - -WILLIAM Faith, sir, so so. - -TOUCHSTONE 'So so' is good, very good, very excellent good; and - yet it is not; it is but so so. Art thou wise? - -WILLIAM Ay, sir, I have a pretty wit. - -TOUCHSTONE Why, thou sayest well. I do now remember a saying, - 'The fool doth think he is wise, but the wise man - knows himself to be a fool.' The heathen - philosopher, when he had a desire to eat a grape, - would open his lips when he put it into his mouth; - meaning thereby that grapes were made to eat and - lips to open. You do love this maid? - -WILLIAM I do, sir. - -TOUCHSTONE Give me your hand. Art thou learned? - -WILLIAM No, sir. - -TOUCHSTONE Then learn this of me: to have, is to have; for it - is a figure in rhetoric that drink, being poured out - of a cup into a glass, by filling the one doth empty - the other; for all your writers do consent that ipse - is he: now, you are not ipse, for I am he. - -WILLIAM Which he, sir? - -TOUCHSTONE He, sir, that must marry this woman. Therefore, you - clown, abandon,--which is in the vulgar leave,--the - society,--which in the boorish is company,--of this - female,--which in the common is woman; which - together is, abandon the society of this female, or, - clown, thou perishest; or, to thy better - understanding, diest; or, to wit I kill thee, make - thee away, translate thy life into death, thy - liberty into bondage: I will deal in poison with - thee, or in bastinado, or in steel; I will bandy - with thee in faction; I will o'errun thee with - policy; I will kill thee a hundred and fifty ways: - therefore tremble and depart. - -AUDREY Do, good William. - -WILLIAM God rest you merry, sir. - - [Exit] - - [Enter CORIN] - -CORIN Our master and mistress seeks you; come, away, away! - -TOUCHSTONE Trip, Audrey! trip, Audrey! I attend, I attend. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT V - - - -SCENE II The forest. - - - [Enter ORLANDO and OLIVER] - -ORLANDO Is't possible that on so little acquaintance you - should like her? that but seeing you should love - her? and loving woo? and, wooing, she should - grant? and will you persever to enjoy her? - -OLIVER Neither call the giddiness of it in question, the - poverty of her, the small acquaintance, my sudden - wooing, nor her sudden consenting; but say with me, - I love Aliena; say with her that she loves me; - consent with both that we may enjoy each other: it - shall be to your good; for my father's house and all - the revenue that was old Sir Rowland's will I - estate upon you, and here live and die a shepherd. - -ORLANDO You have my consent. Let your wedding be to-morrow: - thither will I invite the duke and all's contented - followers. Go you and prepare Aliena; for look - you, here comes my Rosalind. - - [Enter ROSALIND] - -ROSALIND God save you, brother. - -OLIVER And you, fair sister. - - [Exit] - -ROSALIND O, my dear Orlando, how it grieves me to see thee - wear thy heart in a scarf! - -ORLANDO It is my arm. - -ROSALIND I thought thy heart had been wounded with the claws - of a lion. - -ORLANDO Wounded it is, but with the eyes of a lady. - -ROSALIND Did your brother tell you how I counterfeited to - swoon when he showed me your handkerchief? - -ORLANDO Ay, and greater wonders than that. - -ROSALIND O, I know where you are: nay, 'tis true: there was - never any thing so sudden but the fight of two rams - and Caesar's thrasonical brag of 'I came, saw, and - overcame:' for your brother and my sister no sooner - met but they looked, no sooner looked but they - loved, no sooner loved but they sighed, no sooner - sighed but they asked one another the reason, no - sooner knew the reason but they sought the remedy; - and in these degrees have they made a pair of stairs - to marriage which they will climb incontinent, or - else be incontinent before marriage: they are in - the very wrath of love and they will together; clubs - cannot part them. - -ORLANDO They shall be married to-morrow, and I will bid the - duke to the nuptial. But, O, how bitter a thing it - is to look into happiness through another man's - eyes! By so much the more shall I to-morrow be at - the height of heart-heaviness, by how much I shall - think my brother happy in having what he wishes for. - -ROSALIND Why then, to-morrow I cannot serve your turn for Rosalind? - -ORLANDO I can live no longer by thinking. - -ROSALIND I will weary you then no longer with idle talking. - Know of me then, for now I speak to some purpose, - that I know you are a gentleman of good conceit: I - speak not this that you should bear a good opinion - of my knowledge, insomuch I say I know you are; - neither do I labour for a greater esteem than may in - some little measure draw a belief from you, to do - yourself good and not to grace me. Believe then, if - you please, that I can do strange things: I have, - since I was three year old, conversed with a - magician, most profound in his art and yet not - damnable. If you do love Rosalind so near the heart - as your gesture cries it out, when your brother - marries Aliena, shall you marry her: I know into - what straits of fortune she is driven; and it is - not impossible to me, if it appear not inconvenient - to you, to set her before your eyes tomorrow human - as she is and without any danger. - -ORLANDO Speakest thou in sober meanings? - -ROSALIND By my life, I do; which I tender dearly, though I - say I am a magician. Therefore, put you in your - best array: bid your friends; for if you will be - married to-morrow, you shall, and to Rosalind, if you will. - - [Enter SILVIUS and PHEBE] - - Look, here comes a lover of mine and a lover of hers. - -PHEBE Youth, you have done me much ungentleness, - To show the letter that I writ to you. - -ROSALIND I care not if I have: it is my study - To seem despiteful and ungentle to you: - You are there followed by a faithful shepherd; - Look upon him, love him; he worships you. - -PHEBE Good shepherd, tell this youth what 'tis to love. - -SILVIUS It is to be all made of sighs and tears; - And so am I for Phebe. - -PHEBE And I for Ganymede. - -ORLANDO And I for Rosalind. - -ROSALIND And I for no woman. - -SILVIUS It is to be all made of faith and service; - And so am I for Phebe. - -PHEBE And I for Ganymede. - -ORLANDO And I for Rosalind. - -ROSALIND And I for no woman. - -SILVIUS It is to be all made of fantasy, - All made of passion and all made of wishes, - All adoration, duty, and observance, - All humbleness, all patience and impatience, - All purity, all trial, all observance; - And so am I for Phebe. - -PHEBE And so am I for Ganymede. - -ORLANDO And so am I for Rosalind. - -ROSALIND And so am I for no woman. - -PHEBE If this be so, why blame you me to love you? - -SILVIUS If this be so, why blame you me to love you? - -ORLANDO If this be so, why blame you me to love you? - -ROSALIND Who do you speak to, 'Why blame you me to love you?' - -ORLANDO To her that is not here, nor doth not hear. - -ROSALIND Pray you, no more of this; 'tis like the howling - of Irish wolves against the moon. - - [To SILVIUS] - - I will help you, if I can: - - [To PHEBE] - - I would love you, if I could. To-morrow meet me all together. - - [To PHEBE] - - I will marry you, if ever I marry woman, and I'll be - married to-morrow: - - [To ORLANDO] - - I will satisfy you, if ever I satisfied man, and you - shall be married to-morrow: - - [To SILVIUS] - - I will content you, if what pleases you contents - you, and you shall be married to-morrow. - - [To ORLANDO] - - As you love Rosalind, meet: - - [To SILVIUS] - - as you love Phebe, meet: and as I love no woman, - I'll meet. So fare you well: I have left you commands. - -SILVIUS I'll not fail, if I live. - -PHEBE Nor I. - -ORLANDO Nor I. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT V - - - -SCENE III The forest. - - - [Enter TOUCHSTONE and AUDREY] - -TOUCHSTONE To-morrow is the joyful day, Audrey; to-morrow will - we be married. - -AUDREY I do desire it with all my heart; and I hope it is - no dishonest desire to desire to be a woman of the - world. Here comes two of the banished duke's pages. - - [Enter two Pages] - -First Page Well met, honest gentleman. - -TOUCHSTONE By my troth, well met. Come, sit, sit, and a song. - -Second Page We are for you: sit i' the middle. - -First Page Shall we clap into't roundly, without hawking or - spitting or saying we are hoarse, which are the only - prologues to a bad voice? - -Second Page I'faith, i'faith; and both in a tune, like two - gipsies on a horse. - - SONG. - It was a lover and his lass, - With a hey, and a ho, and a hey nonino, - That o'er the green corn-field did pass - In the spring time, the only pretty ring time, - When birds do sing, hey ding a ding, ding: - Sweet lovers love the spring. - - Between the acres of the rye, - With a hey, and a ho, and a hey nonino - These pretty country folks would lie, - In spring time, &c. - - This carol they began that hour, - With a hey, and a ho, and a hey nonino, - How that a life was but a flower - In spring time, &c. - - And therefore take the present time, - With a hey, and a ho, and a hey nonino; - For love is crowned with the prime - In spring time, &c. - -TOUCHSTONE Truly, young gentlemen, though there was no great - matter in the ditty, yet the note was very - untuneable. - -First Page You are deceived, sir: we kept time, we lost not our time. - -TOUCHSTONE By my troth, yes; I count it but time lost to hear - such a foolish song. God be wi' you; and God mend - your voices! Come, Audrey. - - [Exeunt] - - - - - AS YOU LIKE IT - - -ACT V - - - -SCENE IV The forest. - - - [Enter DUKE SENIOR, AMIENS, JAQUES, ORLANDO, OLIVER, - and CELIA] - -DUKE SENIOR Dost thou believe, Orlando, that the boy - Can do all this that he hath promised? - -ORLANDO I sometimes do believe, and sometimes do not; - As those that fear they hope, and know they fear. - - [Enter ROSALIND, SILVIUS, and PHEBE] - -ROSALIND Patience once more, whiles our compact is urged: - You say, if I bring in your Rosalind, - You will bestow her on Orlando here? - -DUKE SENIOR That would I, had I kingdoms to give with her. - -ROSALIND And you say, you will have her, when I bring her? - -ORLANDO That would I, were I of all kingdoms king. - -ROSALIND You say, you'll marry me, if I be willing? - -PHEBE That will I, should I die the hour after. - -ROSALIND But if you do refuse to marry me, - You'll give yourself to this most faithful shepherd? - -PHEBE So is the bargain. - -ROSALIND You say, that you'll have Phebe, if she will? - -SILVIUS Though to have her and death were both one thing. - -ROSALIND I have promised to make all this matter even. - Keep you your word, O duke, to give your daughter; - You yours, Orlando, to receive his daughter: - Keep your word, Phebe, that you'll marry me, - Or else refusing me, to wed this shepherd: - Keep your word, Silvius, that you'll marry her. - If she refuse me: and from hence I go, - To make these doubts all even. - - [Exeunt ROSALIND and CELIA] - -DUKE SENIOR I do remember in this shepherd boy - Some lively touches of my daughter's favour. - -ORLANDO My lord, the first time that I ever saw him - Methought he was a brother to your daughter: - But, my good lord, this boy is forest-born, - And hath been tutor'd in the rudiments - Of many desperate studies by his uncle, - Whom he reports to be a great magician, - Obscured in the circle of this forest. - - [Enter TOUCHSTONE and AUDREY] - -JAQUES There is, sure, another flood toward, and these - couples are coming to the ark. Here comes a pair of - very strange beasts, which in all tongues are called fools. - -TOUCHSTONE Salutation and greeting to you all! - -JAQUES Good my lord, bid him welcome: this is the - motley-minded gentleman that I have so often met in - the forest: he hath been a courtier, he swears. - -TOUCHSTONE If any man doubt that, let him put me to my - purgation. I have trod a measure; I have flattered - a lady; I have been politic with my friend, smooth - with mine enemy; I have undone three tailors; I have - had four quarrels, and like to have fought one. - -JAQUES And how was that ta'en up? - -TOUCHSTONE Faith, we met, and found the quarrel was upon the - seventh cause. - -JAQUES How seventh cause? Good my lord, like this fellow. - -DUKE SENIOR I like him very well. - -TOUCHSTONE God 'ild you, sir; I desire you of the like. I - press in here, sir, amongst the rest of the country - copulatives, to swear and to forswear: according as - marriage binds and blood breaks: a poor virgin, - sir, an ill-favoured thing, sir, but mine own; a poor - humour of mine, sir, to take that that no man else - will: rich honesty dwells like a miser, sir, in a - poor house; as your pearl in your foul oyster. - -DUKE SENIOR By my faith, he is very swift and sententious. - -TOUCHSTONE According to the fool's bolt, sir, and such dulcet diseases. - -JAQUES But, for the seventh cause; how did you find the - quarrel on the seventh cause? - -TOUCHSTONE Upon a lie seven times removed:--bear your body more - seeming, Audrey:--as thus, sir. I did dislike the - cut of a certain courtier's beard: he sent me word, - if I said his beard was not cut well, he was in the - mind it was: this is called the Retort Courteous. - If I sent him word again 'it was not well cut,' he - would send me word, he cut it to please himself: - this is called the Quip Modest. If again 'it was - not well cut,' he disabled my judgment: this is - called the Reply Churlish. If again 'it was not - well cut,' he would answer, I spake not true: this - is called the Reproof Valiant. If again 'it was not - well cut,' he would say I lied: this is called the - Counter-cheque Quarrelsome: and so to the Lie - Circumstantial and the Lie Direct. - -JAQUES And how oft did you say his beard was not well cut? - -TOUCHSTONE I durst go no further than the Lie Circumstantial, - nor he durst not give me the Lie Direct; and so we - measured swords and parted. - -JAQUES Can you nominate in order now the degrees of the lie? - -TOUCHSTONE O sir, we quarrel in print, by the book; as you have - books for good manners: I will name you the degrees. - The first, the Retort Courteous; the second, the - Quip Modest; the third, the Reply Churlish; the - fourth, the Reproof Valiant; the fifth, the - Countercheque Quarrelsome; the sixth, the Lie with - Circumstance; the seventh, the Lie Direct. All - these you may avoid but the Lie Direct; and you may - avoid that too, with an If. I knew when seven - justices could not take up a quarrel, but when the - parties were met themselves, one of them thought but - of an If, as, 'If you said so, then I said so;' and - they shook hands and swore brothers. Your If is the - only peacemaker; much virtue in If. - -JAQUES Is not this a rare fellow, my lord? he's as good at - any thing and yet a fool. - -DUKE SENIOR He uses his folly like a stalking-horse and under - the presentation of that he shoots his wit. - - [Enter HYMEN, ROSALIND, and CELIA] - - [Still Music] - -HYMEN Then is there mirth in heaven, - When earthly things made even - Atone together. - Good duke, receive thy daughter - Hymen from heaven brought her, - Yea, brought her hither, - That thou mightst join her hand with his - Whose heart within his bosom is. - -ROSALIND [To DUKE SENIOR] To you I give myself, for I am yours. - - [To ORLANDO] - - To you I give myself, for I am yours. - -DUKE SENIOR If there be truth in sight, you are my daughter. - -ORLANDO If there be truth in sight, you are my Rosalind. - -PHEBE If sight and shape be true, - Why then, my love adieu! - -ROSALIND I'll have no father, if you be not he: - I'll have no husband, if you be not he: - Nor ne'er wed woman, if you be not she. - -HYMEN Peace, ho! I bar confusion: - 'Tis I must make conclusion - Of these most strange events: - Here's eight that must take hands - To join in Hymen's bands, - If truth holds true contents. - You and you no cross shall part: - You and you are heart in heart - You to his love must accord, - Or have a woman to your lord: - You and you are sure together, - As the winter to foul weather. - Whiles a wedlock-hymn we sing, - Feed yourselves with questioning; - That reason wonder may diminish, - How thus we met, and these things finish. - - SONG. - Wedding is great Juno's crown: - O blessed bond of board and bed! - 'Tis Hymen peoples every town; - High wedlock then be honoured: - Honour, high honour and renown, - To Hymen, god of every town! - -DUKE SENIOR O my dear niece, welcome thou art to me! - Even daughter, welcome, in no less degree. - -PHEBE I will not eat my word, now thou art mine; - Thy faith my fancy to thee doth combine. - - [Enter JAQUES DE BOYS] - -JAQUES DE BOYS Let me have audience for a word or two: - I am the second son of old Sir Rowland, - That bring these tidings to this fair assembly. - Duke Frederick, hearing how that every day - Men of great worth resorted to this forest, - Address'd a mighty power; which were on foot, - In his own conduct, purposely to take - His brother here and put him to the sword: - And to the skirts of this wild wood he came; - Where meeting with an old religious man, - After some question with him, was converted - Both from his enterprise and from the world, - His crown bequeathing to his banish'd brother, - And all their lands restored to them again - That were with him exiled. This to be true, - I do engage my life. - -DUKE SENIOR Welcome, young man; - Thou offer'st fairly to thy brothers' wedding: - To one his lands withheld, and to the other - A land itself at large, a potent dukedom. - First, in this forest, let us do those ends - That here were well begun and well begot: - And after, every of this happy number - That have endured shrewd days and nights with us - Shall share the good of our returned fortune, - According to the measure of their states. - Meantime, forget this new-fall'n dignity - And fall into our rustic revelry. - Play, music! And you, brides and bridegrooms all, - With measure heap'd in joy, to the measures fall. - -JAQUES Sir, by your patience. If I heard you rightly, - The duke hath put on a religious life - And thrown into neglect the pompous court? - -JAQUES DE BOYS He hath. - -JAQUES To him will I : out of these convertites - There is much matter to be heard and learn'd. - - [To DUKE SENIOR] - - You to your former honour I bequeath; - Your patience and your virtue well deserves it: - - [To ORLANDO] - - You to a love that your true faith doth merit: - - [To OLIVER] - - You to your land and love and great allies: - - [To SILVIUS] - - You to a long and well-deserved bed: - - [To TOUCHSTONE] - - And you to wrangling; for thy loving voyage - Is but for two months victuall'd. So, to your pleasures: - I am for other than for dancing measures. - -DUKE SENIOR Stay, Jaques, stay. - -JAQUES To see no pastime I what you would have - I'll stay to know at your abandon'd cave. - - [Exit] - -DUKE SENIOR Proceed, proceed: we will begin these rites, - As we do trust they'll end, in true delights. - - [A dance] - - - - - AS YOU LIKE IT - - EPILOGUE - - -ROSALIND It is not the fashion to see the lady the epilogue; - but it is no more unhandsome than to see the lord - the prologue. If it be true that good wine needs - no bush, 'tis true that a good play needs no - epilogue; yet to good wine they do use good bushes, - and good plays prove the better by the help of good - epilogues. What a case am I in then, that am - neither a good epilogue nor cannot insinuate with - you in the behalf of a good play! I am not - furnished like a beggar, therefore to beg will not - become me: my way is to conjure you; and I'll begin - with the women. I charge you, O women, for the love - you bear to men, to like as much of this play as - please you: and I charge you, O men, for the love - you bear to women--as I perceive by your simpering, - none of you hates them--that between you and the - women the play may please. If I were a woman I - would kiss as many of you as had beards that pleased - me, complexions that liked me and breaths that I - defied not: and, I am sure, as many as have good - beards or good faces or sweet breaths will, for my - kind offer, when I make curtsy, bid me farewell. - - [Exeunt] diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata1.snappy b/Sources/OpenVPN3/test/unittests/comp-testdata/baddata1.snappy deleted file mode 100644 index 99d970f..0000000 Binary files a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata1.snappy and /dev/null differ diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata2.snappy b/Sources/OpenVPN3/test/unittests/comp-testdata/baddata2.snappy deleted file mode 100644 index 8f5cb13..0000000 Binary files a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata2.snappy and /dev/null differ diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata3.snappy b/Sources/OpenVPN3/test/unittests/comp-testdata/baddata3.snappy deleted file mode 100644 index 774aead..0000000 Binary files a/Sources/OpenVPN3/test/unittests/comp-testdata/baddata3.snappy and /dev/null differ diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/cp.html b/Sources/OpenVPN3/test/unittests/comp-testdata/cp.html deleted file mode 100644 index 343ea97..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/cp.html +++ /dev/null @@ -1,645 +0,0 @@ -<head> -<title>Compression Pointers - - - - - -
-

Compression Pointers

- - - -
- -

-Compression resources, conferences, and some research -groups and companies, are listed towards the end of this page.

- -Use this handy form to add something to this page, or to simply say you liked this page -

- - - - - -

- -

What's New?

- - -Jean-loup Gailly -- Mr. gzip, -PNG, CCR (1996-06-10) - -
- -MPEG Pointers and Resources - -
- -Robert M. Gray -- Signal -compression, VQ, image quality evaluation (1996-04-22) -
- -Compression and -Classification Group -- ISL,EE,Stanford (1996-04-22) -
- -Signal Processing -and the International Information Infrastructure -- Web sites (1996-04-22) -
- -Valenta, Vladimir -- (1996-04-22) -
- - -Jordan, Frederic -- Parallel Image Compression (1996-04-12) -
-Electro-Optical Technologies, Inc. -- Consultant (1996-04-12) -
-quicktime.apple.com -- Quicktime site (1996-03-11) -
-IBM Hardware -- Compression chips (1996-03-11) -
- - - - - - - - - - - - - - - - - - - - - - - - -

- - -

- - -

People

-

A

- -Adler, Mark -- Info-ZIP; Zip, UnZip, gzip and zlib co-author; PNG group -

- -

B

- -Baker, Matthew -- Region based video compression -

-Bamberger, Roberto H. -

-Bell, Daniel -- Region based image compression -

-Bell, Tim -- compression, computer science for children, and computers and music. -

-Bellard, Fabrice -- Author of LZEXE -

-Berghorn, Willy -

-Bhaskaran, Vasudev -- Image and Video compression -

-Bloom, Charles -- text compression, LZ methods, PPM methods... -

-Brito, Roger -- Arithmetic Coding, LZW, Text Compression -

-Budge, Scott E. -- medical/lossy image compression -

-Burnett, Ian -- Speech coding, prototype waveform techniques -

- - -

C

- -Chan, Christopher -- universal lossy source coding, adaptive VQ -

-Chao, Hong-yang -- Lightning strike image compressor -

-Chao, Stewart -

-Cherriman, Peter -

-Cheung, S.C. -- Scalable video compression algorithms (18th Feb 1996) -

- -Christopoulos, Charilaos -- Image and Video compression -

-Chrysafis, Christos -

-Chung, Wilson C. -- R-D image and video coding, subband/wavelet, filter banks -

-Clark, Alan -- primary contact for V.42bis. Developed BTLZ variant of LZW -

-Cleary, John -- PPM, PPM*, K* -

-Cohn, Martin -

- -Cormack, Gordon V. -- DMC -

-Cramer, Chris -- neural network image compression -

- -

D

-Danskin, John -- Protocol compression, document compression (9th Feb 1996) -

-Davis, Geoff -- wavelets, image compression, medical -

-Dilger, Andreas -- fractal block coding of video sequences -

- - -

E

-Estes, Robert -

- - - -

F

-Fisher, Yuval -- Fractal Image Compression -

-Ford, Adrian -- Subjective and Objective Compression quality (5th Mar 1996) -

- -

G

-Jean-loup Gailly -- -Mr. gzip, PNG, CCR (1996-06-10) -

- -Gersho, Allen -- Vector Quantisation, Image Compression -

-Goertzel, Ben -

-Gooch, Mark -- High Performance Hardware Compression (7th Feb 1996) -

-Goyal, Vivek -- overcomplete representations, adaptive transform coding, VQ -

-Robert M. Gray -- Signal -compression, VQ, image quality evaluation -

- -

H

-Hafner, Ullrich -- WFA image compression -

-Hirschberg, Dan -- algorithm theory, compression -

-Holland, Scott -

-Horspool, R. Nigel -- text compression, ECG compression - -

I

-Inglis, Stuart -- image compression, OCR, lossy/lossless document compression -

- -

J

-Jones, Douglas -- splay-tree based compression and encryption -

-Jones, Simon -- Lossless compression, High Performance Hardware (7th Feb 1996) -

-Jordan, Frederic -- Parallel Image Compression (12th April 1996) -

-Jung, Robert K. -- ARJ -

-jutta -

- - - -

K

-Kominek, John -- Fractal and spline based compression -

-Kjelso, Morten -- Main memory compression, High performance hardware -

-Kuhn, Markus -- JBIG implementation -

-Kuo, C.-C. Jay -

-Kuru, Esa -

-Kyfonidis, Theodoros -

- -

L

-Lamparter, Bernd -

-Langdon, Glen -

-Larsson, Jesper -- algorithms and data structures, text compression -

- - -

M

-Manber, Udi -

-Mangen, Jean-Michel -- image compression, wavelets, satellite -

-Moffat, Alistair -- text and index compression, coding methods, information retrieval, document databases -

-Montgomery, Christopher -- OggSquish, audio compression -

-Mueller, Urban Dominik -- XPK system -

-

N

-Neal, Radford -

-Nevill-Manning, Craig -

-Nicholls, Jeremy -

-Noah, Matt -- speech, ATC, ACELP and IMBE -

-Nuri, Veyis -- wavelets, data compression, DSP (speech & image) - -

O

-Oleg -- Lots of code -

-Ortega, Antonio -- Video compression, Packet video, Adaptive quantization -

-Owen, Charles -

- -

P

-Provine, -Joseph -- Model based coding -

- -

R

-Robinson, John -- Binary Tree Predictive Coding -

-Roelofs, Greg -- Info-ZIP; primary UnZip author; PNG group -

-Rose, Kenneth -

-Russo, Roberto Maria -- Multiplatform Data Compression -

- -

S

-Schmidt, Bill -

-Shaw, Sandy C. -

-Sharifi, Kamran -- Video over ATM networks -

-Shende, Sunil M. -

-Silverstein, D. Amnon -

-Smoot, Steve -- MPEG -

-Storer, James A. -

-Streit, Jurgen -- Low bitrate coding -

-Strutz, Tilo -- Wavelet image compressor, demonstration execs -

- - -

T

-Tate, Steve -

-Teahan, Bill -- PPM, PPM*, master of the Calgary Corpus -

-Thomson, Duncan -- ECG compression with ANNs -

-Tilton, James C. -

-Tomczyk, Marek -

-Turpin, Andrew -- Prefix Codes -

- -

V

-Vetterli, Martin -- wavelets, subband coding, video compression, computational complexity -

-Vitter, Jeff -

-Voukelatos, Stathis -

-de Vries, Nico -- AIP-NL, UltraCompressor II development -

- -

W

- -Wareham, Paul -- Region-oriented video coding -

-Wegener, Al -- DSP, lossless audio compression and AC-2 -

-Wei, Dong -- Wavelet compression -

-Williams, Ross -

-Witten, Ian -- PPM, mg, arithmetic coding -

-Wolff, Gerry -

-Woo, Woon-Tack -- stereo image and video compression (12th Feb 1996) -

-Wu, Xiaolin -- CALIC -

- - -

Z

-Zobel, Justin -- index compression, database compression -

- -
-
- - - - -

Conferences

-Data Compression Conference (DCC), Snowbird, Utah, USA.
-

- - - -

Resources

-
-Where to get answers... -
-
International Telecommunication Union (ITU) -- standards documents (CCITT) -
-
comp.compression -- Frequently Asked Questions -- Come here 1st! -
-JPEG - Frequently Asked Questions -
-MPEG - Frequently Asked Questions -
-Standards - Frequenty Asked Questions -
-usenet newsgroup: comp.compression.research -
-
-Archive Compression Test -- Summary of all archivers -
-
-Fractal compression bibliography -- bibtex file -
-
-LZ/Complexity Seminars -- (in German) -
-
-Comparitive Compression Ratios -- Sofar...B&W, Gray Scale, Text Compression -
-
-VCN (Video, Compression, Networking) -Glossary -
-
-Digital Library -- search for compression -
- - -
-
-Reports/Ph.D. Theses -
-Paul Howards Ph.D. thesis
-
The Design and Analysis of Efficient Lossless Data Compression Systems -
- - - - -
-
-Source code -
-Arithmetic coding routines -
        (from Moffat, Neal and Witten, Proc. DCC, April 1995) -
-
-CACM Arithmetic coding package -
        (Witten, Neal and Cleary, CACM 30:520-541, June 1987) -
-
-JBIG Source code Includes a Q-coder -
-
Markus Kuhn's JBIG implementation -
-
-k-arithmetic coder -
-
-Lossless Data Compression toolkit 1.1 -
-
-Splay Trees Code -- by Douglas W. Jones -
-
Block compression code -- Excellent text compressor -
- - - -
-
-Test Files -
-Test Images -- CCITT images (pbm), Lena etc. (Sun raster) -
-
-Stockholm test images -- You have to buy a CDROM, thats all I know! :-( -
         mail me at singlis@cs.waikato.ac.nz if you know anything about them. -
-
-Calgary Text Compression Corpus (Text Compression, Bell, Cleary and Witten, 1990) -
- - -
- - - - -

Research Projects, Standards & Companies

- -

-

-Research/Free software Groups -
Compression and -Classification Group -- ISL,EE,Stanford (22th April 1996) - -
Voice email -- Lossless audio compression (18th Feb 1996) - - -
Electro-Optical Technologies, Inc. -- Consultant (12th April 1996) - -
quicktime.apple.com -- Quicktime site (11th Mar 1996) - -
IMAGE etc. -- Commercial image compression software (Fractals/Wavelets) (29th Feb 1996) - -
NCAR CCM Compression and Visualisation -- (18th Feb 1996) -
-
SPIHT -- Wavelet Natural Image Compressor (12th Feb 1996) -
-
Real-Time Lossless Compression Systems -- Loughborough University -
-
Web site for Multirate Signal Processing -- University of Wisconsin, Madison -
-
Info-ZIP -- free, -portable Zip and UnZip utilities -
-
CEDIS -- NASA, Maryland, Image/data compression -
-
CIC-3 Image Compression -- FBI Fingerprints -
-
Signal Compression Lab at UCSB -
-
University of -Washington compression lab -- VQ, Wavelets, Shlomo -
- - - -

-

-Snippets -
Signal Processing -and the International Information Infrastructure -- Web sites (22th April 1996) -
Increasing Web bandwith -- comparing GIF, JPEG, Fractal compression -
-
Fractal Links on Yahoo -
-
Digital Speech Compression GSM 06.10 RPE-LTP -- DDJ -
-
CREW -- Continuous tone loss(y/less) wavelet compression -
-
CALIC -- Context-based adaptive lossless image compressor -
-
Berkeley MPEG -- MPEG tools -
-
MPEG Pointers and Resources -
- - - - - - -

-

-Wavelets -
- - EPIC (Efficient Pyramid Image Coder) -- by Eero Simoncelli -
-
-Tucker, Michael -- FASTWAVE, audio/image compression -
-
-HARC -- Lossy Wavelet Compression technology -
-
-UC Berkeley Wavelet Group -
-
-Khoros Wavetlet and Compression Toolbox -
-
-The Wavelet Digest -
-
-Rice DSP Publications Archive -- Wavelets, Time Frequency/Scale -
- - -

-

-Fractals -
-Fractal Image Compression -- Software, Pointers, Conferences -
-
-Fractal Design Corporation -
-
-New Fractal Image Compression program -
- - -

-

-Companies -
IBM Hardware -- Compression chips (11th Mar 1996) - -
Summus Wavelet Technology -- Wavelet image and video compressors (11th Mar 1996) -
Fractal Image Compression -- Mitsubishi (18th Feb 1996) - -
Terran Interactive -- Video compression for the Mac (1st Feb 1996) -
- -
DV Mpeg -- Windows drivers (18th Feb 1996) -
- -
Crawford Compression Services -- MPEG post-production (18th Feb 1996) -
- -
Intelligent Compression Technologies (18th Feb 1996) -
- -
Pegasus Imaging -- Compression software/dev. kits (12th Feb 1996) -
-
Aladdin Systems -- StuffIt compression products -
-
Stac Electronics -
-
DCP Research -- Hardware solutions -
-
Aware Inc. -- Specialised compression company -
-
IVS - INRIA Videoconferencing System -
-
Telvox Teleinformatica -- Multiplatform Data Compressor -
-
Compression Technologies, -Inc -- Canada -
-
Optivision -- MPEG -
-
PKWARE -- Makers of PKZIP -
-
Multimedia Imaging Services -
- - -

-

-Audio compression -
Fraunhofer Institut für Integrierte Schaltungen -
-
Shorten -
-
digital speech compression -
-
Audio compression references -
-
SpeakFreely - compression -
-
SpeakFreely - Contents -
diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/fields.c b/Sources/OpenVPN3/test/unittests/comp-testdata/fields.c deleted file mode 100644 index 63cdc03..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/fields.c +++ /dev/null @@ -1,431 +0,0 @@ -#ifndef lint -static char Rcs_Id[] = - "$Id: fields.c,v 1.7 1994/01/06 05:26:37 geoff Exp $"; -#endif - -/* - * $Log: fields.c,v $ - * Revision 1.7 1994/01/06 05:26:37 geoff - * Get rid of all references to System V string routines, for portability - * (sigh). - * - * Revision 1.6 1994/01/05 20:13:43 geoff - * Add the maxf parameter - * - * Revision 1.5 1994/01/04 02:40:21 geoff - * Make the increments settable (field_line_inc and field_field_inc). - * Add support for the FLD_NOSHRINK flag. - * - * Revision 1.4 1993/09/27 17:48:02 geoff - * Fix some lint complaints and some parenthesization errors. - * - * Revision 1.3 1993/09/09 01:11:11 geoff - * Add a return value to fieldwrite. Add support for backquotes and for - * unstripped backslashes. - * - * Revision 1.2 1993/08/26 00:02:50 geoff - * Fix a stupid null-pointer bug - * - * Revision 1.1 1993/08/25 21:32:05 geoff - * Initial revision - * - */ - -#include -#include "config.h" -#include "fields.h" - -field_t * fieldread P ((FILE * file, char * delims, - int flags, int maxf)); - /* Read a line with fields from a file */ -field_t * fieldmake P ((char * line, int allocated, char * delims, - int flags, int maxf)); - /* Make a field structure from a line */ -static field_t * fieldparse P ((field_t * fieldp, char * line, char * delims, - int flags, int maxf)); - /* Parse the fields in a line */ -static int fieldbackch P ((char * str, char ** out, int strip)); - /* Process backslash sequences */ -int fieldwrite P ((FILE * file, field_t * fieldp, int delim)); - /* Write a line with fields to a file */ -void fieldfree P ((field_t * fieldp)); - /* Free a field returned by fieldread */ - -unsigned int field_field_inc = 20; /* Increment to increase # fields by */ -unsigned int field_line_inc = 512; /* Incr to increase line length by */ - -#ifndef USG -#define strchr index -#endif /* USG */ - -extern void free (); -extern char * malloc (); -extern char * realloc (); -extern char * strchr (); -extern int strlen (); - -/* - * Read one line of the given file into a buffer, break it up into - * fields, and return them to the caller. The field_t structure - * returned must eventually be freed with fieldfree. - */ -field_t * fieldread (file, delims, flags, maxf) - FILE * file; /* File to read lines from */ - char * delims; /* Characters to use for field delimiters */ - int flags; /* Option flags; see fields.h */ - int maxf; /* Maximum number of fields to parse */ - { - register char * linebuf; /* Buffer to hold the line read in */ - int linemax; /* Maximum line buffer size */ - int linesize; /* Current line buffer size */ - - linebuf = (char *) malloc (field_line_inc); - if (linebuf == NULL) - return NULL; - linemax = field_line_inc; - linesize = 0; - /* - * Read in the line. - */ - while (fgets (&linebuf[linesize], linemax - linesize, file) - != NULL) - { - linesize += strlen (&linebuf[linesize]); - if (linebuf[linesize - 1] == '\n') - break; - else - { - linemax += field_line_inc; - linebuf = (char *) realloc (linebuf, linemax); - if (linebuf == NULL) - return NULL; - } - } - if (linesize == 0) - { - free (linebuf); - return NULL; - } - return fieldmake (linebuf, 1, delims, flags, maxf); - } - -field_t * fieldmake (line, allocated, delims, flags, maxf) - char * line; /* Line to make into a field structure */ - int allocated; /* NZ if line allocated with malloc */ - char * delims; /* Characters to use for field delimiters */ - int flags; /* Option flags; see fields.h */ - int maxf; /* Maximum number of fields to parse */ - { - register field_t * fieldp; /* Structure describing the fields */ - int linesize; /* Current line buffer size */ - - fieldp = (field_t *) malloc (sizeof (field_t)); - if (fieldp == NULL) - return NULL; - fieldp->nfields = 0; - fieldp->linebuf = allocated ? line : NULL; - fieldp->fields = NULL; - fieldp->hadnl = 0; - linesize = strlen (line); - if (line[linesize - 1] == '\n') - { - line[--linesize] = '\0'; - fieldp->hadnl = 1; - } - /* - * Shrink the line buffer if necessary. - */ - if (allocated && (flags & FLD_NOSHRINK) == 0) - { - line = fieldp->linebuf = - (char *) realloc (fieldp->linebuf, linesize + 1); - if (fieldp->linebuf == NULL) - { - fieldfree (fieldp); - return NULL; - } - } - return fieldparse (fieldp, line, delims, flags, maxf); - } - -static field_t * fieldparse (fieldp, line, delims, flags, maxf) - register field_t * fieldp; /* Field structure to parse into */ - register char * line; /* Line to be parsed */ - char * delims; /* Characters to use for field delimiters */ - int flags; /* Option flags; see fields.h */ - int maxf; /* Maximum number of fields to parse */ - { - int fieldmax; /* Max size of fields array */ - char * lineout; /* Where to store xlated char in line */ - char quote; /* Quote character in use */ - - fieldp->nfields = 0; - fieldmax = - (maxf != 0 && maxf < field_field_inc) ? maxf + 2 : field_field_inc; - fieldp->fields = (char **) malloc (fieldmax * sizeof (char *)); - if (fieldp->fields == NULL) - { - fieldfree (fieldp); - return NULL; - } - if ((flags - & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES)) - == FLD_SHQUOTES) - flags |= FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES; - while (1) - { - if (flags & FLD_RUNS) - { - while (*line != '\0' && strchr (delims, *line) != NULL) - line++; /* Skip runs of delimiters */ - if (*line == '\0') - break; - } - fieldp->fields[fieldp->nfields] = lineout = line; - /* - * Skip to the next delimiter. At the end of skipping, "line" will - * point to either a delimiter or a null byte. - */ - if (flags - & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES - | FLD_DBLQUOTES | FLD_BACKSLASH)) - { - while (*line != '\0') - { - if (strchr (delims, *line) != NULL) - break; - else if (((flags & FLD_SNGLQUOTES) && *line == '\'') - || ((flags & FLD_BACKQUOTES) && *line == '`') - || ((flags & FLD_DBLQUOTES) && *line == '"')) - { - if ((flags & FLD_SHQUOTES) == 0 - && line != fieldp->fields[fieldp->nfields]) - quote = '\0'; - else - quote = *line; - } - else - quote = '\0'; - if (quote == '\0') - { - if (*line == '\\' && (flags & FLD_BACKSLASH)) - { - line++; - if (*line == '\0') - break; - line += fieldbackch (line, &lineout, - flags & FLD_STRIPQUOTES); - } - else - *lineout++ = *line++; - } - else - { - /* Process quoted string */ - if ((flags & FLD_STRIPQUOTES) == 0) - *lineout++ = quote; - ++line; - while (*line != '\0') - { - if (*line == quote) - { - if ((flags & FLD_STRIPQUOTES) == 0) - *lineout++ = quote; - line++; /* Go on past quote */ - if ((flags & FLD_SHQUOTES) == 0) - { - while (*line != '\0' - && strchr (delims, *line) == NULL) - line++; /* Skip to delimiter */ - } - break; - } - else if (*line == '\\') - { - if (flags & FLD_BACKSLASH) - { - line++; - if (*line == '\0') - break; - else - line += fieldbackch (line, &lineout, - flags & FLD_STRIPQUOTES); - } - else - { - *lineout++ = '\\'; - if (*++line == '\0') - break; - *lineout++ = *line; - } - } - else - *lineout++ = *line++; - } - } - } - } - else - { - while (*line != '\0' && strchr (delims, *line) == NULL) - line++; /* Skip to delimiter */ - lineout = line; - } - fieldp->nfields++; - if (*line++ == '\0') - break; - if (maxf != 0 && fieldp->nfields > maxf) - break; - *lineout = '\0'; - if (fieldp->nfields >= fieldmax) - { - fieldmax += field_field_inc; - fieldp->fields = - (char **) realloc (fieldp->fields, fieldmax * sizeof (char *)); - if (fieldp->fields == NULL) - { - fieldfree (fieldp); - return NULL; - } - } - } - /* - * Shrink the field pointers and return the field structure. - */ - if ((flags & FLD_NOSHRINK) == 0 && fieldp->nfields >= fieldmax) - { - fieldp->fields = (char **) realloc (fieldp->fields, - (fieldp->nfields + 1) * sizeof (char *)); - if (fieldp->fields == NULL) - { - fieldfree (fieldp); - return NULL; - } - } - fieldp->fields[fieldp->nfields] = NULL; - return fieldp; - } - -static int fieldbackch (str, out, strip) - register char * str; /* First char of backslash sequence */ - register char ** out; /* Where to store result */ - int strip; /* NZ to convert the sequence */ - { - register int ch; /* Character being developed */ - char * origstr; /* Original value of str */ - - if (!strip) - { - *(*out)++ = '\\'; - if (*str != 'x' && *str != 'X' && (*str < '0' || *str > '7')) - { - *(*out)++ = *str; - return *str != '\0'; - } - } - switch (*str) - { - case '\0': - *(*out)++ = '\0'; - return 0; - case 'a': - *(*out)++ = '\007'; - return 1; - case 'b': - *(*out)++ = '\b'; - return 1; - case 'f': - *(*out)++ = '\f'; - return 1; - case 'n': - *(*out)++ = '\n'; - return 1; - case 'r': - *(*out)++ = '\r'; - return 1; - case 'v': - *(*out)++ = '\v'; - return 1; - case 'X': - case 'x': - /* Hexadecimal sequence */ - origstr = str++; - ch = 0; - if (*str >= '0' && *str <= '9') - ch = *str++ - '0'; - else if (*str >= 'a' && *str <= 'f') - ch = *str++ - 'a' + 0xa; - else if (*str >= 'A' && *str <= 'F') - ch = *str++ - 'A' + 0xa; - if (*str >= '0' && *str <= '9') - ch = (ch << 4) | (*str++ - '0'); - else if (*str >= 'a' && *str <= 'f') - ch = (ch << 4) | (*str++ - 'a' + 0xa); - else if (*str >= 'A' && *str <= 'F') - ch = (ch << 4) | (*str++ - 'A' + 0xa); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - /* Octal sequence */ - origstr = str; - ch = *str++ - '0'; - if (*str >= '0' && *str <= '7') - ch = (ch << 3) | (*str++ - '0'); - if (*str >= '0' && *str <= '7') - ch = (ch << 3) | (*str++ - '0'); - break; - default: - *(*out)++ = *str; - return 1; - } - if (strip) - { - *(*out)++ = ch; - return str - origstr; - } - else - { - for (ch = 0; origstr < str; ch++) - *(*out)++ = *origstr++; - return ch; - } - } - -int fieldwrite (file, fieldp, delim) - FILE * file; /* File to write to */ - register field_t * fieldp; /* Field structure to write */ - int delim; /* Delimiter to place between fields */ - { - int error; /* NZ if an error occurs */ - register int fieldno; /* Number of field being written */ - - error = 0; - for (fieldno = 0; fieldno < fieldp->nfields; fieldno++) - { - if (fieldno != 0) - error |= putc (delim, file) == EOF; - error |= fputs (fieldp->fields[fieldno], file) == EOF; - } - if (fieldp->hadnl) - error |= putc ('\n', file) == EOF; - return error; - } - -void fieldfree (fieldp) - register field_t * fieldp; /* Field structure to free */ - { - - if (fieldp == NULL) - return; - if (fieldp->linebuf != NULL) - free ((char *) fieldp->linebuf); - if (fieldp->fields != NULL) - free ((char *) fieldp->fields); - free ((char *) fieldp); - } diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/geo.protodata b/Sources/OpenVPN3/test/unittests/comp-testdata/geo.protodata deleted file mode 100644 index c4e3e0d..0000000 Binary files a/Sources/OpenVPN3/test/unittests/comp-testdata/geo.protodata and /dev/null differ diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/grammar.lsp b/Sources/OpenVPN3/test/unittests/comp-testdata/grammar.lsp deleted file mode 100644 index 1ba8bc7..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/grammar.lsp +++ /dev/null @@ -1,94 +0,0 @@ -;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- - -(define-language - :grammar - '(((S $any) -> (S1 $any)) - ((S (Compound $s1 $s2)) -> (S1 $s1) (Conjunction) (S1 $s2)) - - ((S1 (Statement $v)) -> (NP $subj) (VP $subj $tense $v)) - ((S1 (Acknowledge $a)) -> (Acknowledge $a)) - ((S1 (Command $v)) -> (VP Self present $v)) - ((S1 (Question $v)) -> (Aux $tense) (NP $subj) (VP $subj $tense $v)) - ((S1 (Question $v)) -> (Be $tense) (NP $subj) (Be-Arg $subj $tense $v)) - - ((Be-Arg $subj $tense (Occur $tense (loc $subj $loc))) -> - (Loc-Adjunct $tense (loc $subj $loc))) - - ((VP $subj $tense (Occur $tense $v)) -> (VP1 $subj $tense $v)) - ((VP $subj $tense (Occur $tense $v)) -> (Aux $tense)(VP1 $subj present $v)) - - ((VP1 $subj $tense $v) -> (VP2 $subj $tense $v) (Adjunct? $v)) - - ((VP2 $subj $tense ($rel $subj $loc)) -> - (Verb/in $rel $tense)) - ((VP2 $subj $tense ($rel $subj $loc $obj)) -> - (Verb/tr $rel $tense) (NP $obj)) - ((VP2 $subj $tense ($rel $subj $loc $obj $obj2)) -> - (Verb/di $rel $tense) (NP $obj) (NP $obj2)) - ((VP2 $subj $tense (loc $subj $loc)) -> - (Be $tense) (Loc-Adjunct $tense (loc $subj $loc))) - - ((NP $n) -> (Pronoun $n)) - ((NP $n) -> (Article) (Noun $n)) - ((NP $n) -> (Noun $n)) - ((NP ($x $y)) -> (Number $x) (Number $y)) - - ((PP ($prep $n)) -> (Prep $prep) (NP $n)) - ((Adjunct? $v) ->) - ((Adjunct? $v) -> (Loc-Adjunct $tense $v)) - #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (PP $loc)) - #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (Adjunct $loc)) - #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (PP $loc)) - #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (Adjunct $loc)) - - ) - :lexicon - '( - ((Acknowledge $a) -> (yes true) (no false) (maybe unknown) (huh unparsed)) - ((Adjunct $loc) -> here there (nearby near) near left right up down) - ((Article) -> a an the) - ((Aux $tense) -> (will future) (did past) (do $finite)) - ((Be $tense) -> (am present) (are present) (is present) (be $finite) - (was past) (were past)) - ((Conjunction) -> and --) - ((Noun $n) -> gold Wumpus pit breeze stench glitter nothing) - ((Number $n) -> 0 1 2 3 4 5 6 7 8 9) - ((Prep $prep) -> in at to near) - ((Pronoun $n) -> (you self) (me master) (I master)) - - ((Verb/in $rel $tense) -> (go move $finite) (went move past) - (move move $finite) (move move past) (shoot shoot $finite)) - ((Verb/tr $rel $tense) -> (move carry $finite) (moved carry past) - (carry carry $finite) (carry carried past) - (grab grab $finite) (grab grabbed past) (get grab $finite) - (got grab past) (release release $finite) (release release past) - (drop release $finite) (dropped release past) (shoot shoot-at $finite) - (shot shoot-at past) (kill shoot-at $finite) (killed shoot-at past) - (smell perceive $finite) (feel perceive $finite) (felt perceive past)) - ((Verb/di $rel $tense) -> (bring bring $finite) (brought bring past) - (get bring $finite) (got bring past)) - )) - -(defparameter *sentences* - '((I will shoot the wumpus at 4 4) - (yes) - (You went right -- I will go left) - (carry the gold) - (yes and no) - (did you bring me the gold) - (a breeze is here -- I am near 5 3) - (a stench is in 3 5) - (a pit is nearby) - (is the wumpus near) - (Did you go to 3 8) - (Yes -- Nothing is there) - (Shoot -- Shoot left) - (Kill the wumpus -- shoot up))) - -(defun ss (&optional (sentences *sentences*)) - "Run some test sentences, and count how many were not parsed." - (count-if-not - #'(lambda (s) - (format t "~2&>>> ~(~{~a ~}~)~%" s) - (write (second (parse s)) :pretty t)) - *sentences*)) diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/house.jpg b/Sources/OpenVPN3/test/unittests/comp-testdata/house.jpg deleted file mode 100644 index 6b3aae8..0000000 Binary files a/Sources/OpenVPN3/test/unittests/comp-testdata/house.jpg and /dev/null differ diff --git a/Sources/OpenVPN3/test/unittests/comp-testdata/html b/Sources/OpenVPN3/test/unittests/comp-testdata/html deleted file mode 100644 index ef768cc..0000000 --- a/Sources/OpenVPN3/test/unittests/comp-testdata/html +++ /dev/null @@ -1 +0,0 @@ - content: @ 1099872000000000: 'HTTP/1.1 200 OK\r\nX-Google-Crawl-Date: Mon, 08 Nov 2004 17:22:09 GMT\r\nContent-Type: text/html\r\nConnection: close\r\nX-Powered-By: PHP/4.3.8\r\nServer: Apache/1.3.31 (Unix) mod_gzip/1.3.19.1a PHP/4.3.8\r\nDate: Mon, 08 Nov 2004 17:19:07 GMT\r\n\r\n \r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\nMicro Achat : Ordinateurs, PDA - Toute l\'informatique avec 01Informatique, L\'Ordinateur Individuel, Micro Hebdo, D\351cision Informatique et 01R\351seaux\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

Derni\350re mise \340 jour de cette page : lundi 8 novembre 2004  |  16:45
\r\n \r\n\r\n\r\n\r\n\t\r\n\r\n\t\t\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n\t\t\r\n\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t

\r\n\r\n\r\n\r\n


\r\n\r\n\r\n\r\n
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\"\"
Imagerie 
\"\"\n\t\t\t\t\t\t\t\tLG L1720B\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
332.89 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tAcer Veriton 7600G\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
705 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Ordinateurs 
\"\"\n\t\t\t\t\t\t\t\tShuttle SN95G5\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
375 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tAsus A7N8X-E Deluxe\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
91.99 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
Composants 
\"\"\n\t\t\t\t\t\t\t\tThermalright SP-94\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\340 partir de\n\t\t\t\t\t\t\t\t\t
49 €
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\"\"
1 \">\"PC Look
2 \">\"Atelier Informatique
3 \">\"Zanax Multim\351dia
4 \">\"MISTEROOPS
5 \">\"168 Golden Avenue
6 \">\"microchoix
7 \">\"e-Soph
8 \">\"PC Price Club
9 \">\"PC 77
10 \">\"Web In Informatique
\n\t\t\t\t
\n\t\t\t\t
\r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t
\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\r\n\r\n\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n

\r\n\t\t\t

\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\r\n \r\n \r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

CD et DVD bient\364t insensibles aux rayures
OpenOffice gagne son service
La messagerie en cinq minutes selon Ipswitch
> toutes les news


\r\n\t\t
\r\n \r\n\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Recevez chaque jour l\'actualit\351 des produits et des promos
\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n\r\n\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t \r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

Entreprise
\r\n\t\t\t\tQuand le billet papier s\'envole vers la d\351mat\351rialisation


Trucs et astuces
\r\n\t\t\t\tD\351pannez Windows XP


Conso
\r\n\t\t\t\tVos photos sur papier imprimante ou labo ?


Produits & Tests
\r\n\t\t\t\t5 programmes d\222encodage vid\351o gratuits


\r\n\t\t
\r\n\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n
\r\n
\r\n\t\t\r\n\t\t

\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\t\r\n
\r\n
\r\nPortable
\r\nUn nouvel ultra portable r\351alis\351 par Nec
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nLe Versa S940 a un format r\351duit, mais ses performances sont \340 la hauteur.
\r\n\340 partir de 1663 \200\r\n
\r\n
\r\nPortable
\r\nAsus pr\351sente trois petits nouveaux dans la gamme A3N
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\nCes trois portables Centrino int\350grent, entre autres, une webcam et un contr\364leur Wi-Fi.
\r\n\340 partir de 1346 \200\r\n
\r\n
\r\n\t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t\r\n \t\r\n\t\r\n\t
\r\n\t\r\n\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
BON PLAN
\r\n
\r\n
\r\nLes derni\350res technologies INTEL dans un nouveau design pour ce shuttle haut de gamme, pour un prix abordable.
\r\n

\r\n
\r\n\340 partir de
\r\n
415 \200
\r\n
\r\n
\r\n
publicit\351
\r\n
\r\n\t\r\n\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t

\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\tDesktops
\r\n\t\t\t\tPortables
\r\n\t\t\t\tMini-PC
\r\n\t\t\t\tPda / Tablets-PC
\r\n\t\t\t\tApple
\r\n\t\t\t\tGPS
\r\n\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t


\r\n\t\t\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n

\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\r\n\t\r\n\t\r\n\t\t\t\t\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\tPortable Toshiba consacre deux gammes de machines au multim\351dia
\r\n\tEquipement haut de gamme et Windows Media Center sont au menu de ces portables \340 vocation multim\351dia.

\r\n\tOrdinateur Arriv\351e d\'un Power Mac G5 d\'entr\351e de gamme
\r\n\tLa firme \340 la pomme propose une station de travail \351volutive et relativement abordable.

\r\n\tPC Alienware propose deux machines au look \351trange
\r\n\tAurora et Area 51 sont deux gammes d\'ordinateurs enti\350rement configurables.

\r\n\tPortable Trois nouveaux iBook G4 chez Apple
\r\n\tChez Apple, les portables gagnent en vitesse et communiquent sans fil en standard.

\r\n\t\t\t\t> toutes les news\r\n\t\t\t
\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n\r\n

\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tAsus A3N15-C Pro
\r\n Voici un portable autonome et puissant gr\342ce \340 la technologie Intel Centrino.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1170 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tSoltek EQ3702A Miroir
\r\n Ce mini PC est une solution int\351ressante pour les utilisateurs poss\351dant d\351j\340 un \351cran.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t559 \200
\r\n
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \tIBM ThinkPad R51
\r\n Voici un portable complet et pourtant relativement l\351ger.
\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t\r\n\t
\r\n\t1299 \200
\r\n
\r\n\t\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n\t\t\t\t> toutes les promos\r\n\t\t
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n

\r\n
\r\n\t\t\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t\t\r\n\r\n\r\n\r\n \r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n\t\r\n\r\n
\r\n\r\n\t\t\t\t\t \t \t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t \t\r\n
\r\n
\r\nLes graveurs de DVD
\r\nQuel graveur choisir ? Quel type de format ? Quelle vitesse ? Double couche ou simple couche ? Voici tout ce qu\'il faut savoir pour faire le bon choix.
\r\n\t\t\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t
\r\n
\r\n\r\n\r\n\t\r\n\t\t\r\n\r\n\r\n \t\r\n
\r\n\t\t
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\t\t

\r\n\t\t\t\tChoisir une r\351gion
\r\n\r\n
Un d\351partement
\r\n\r\n
\r\n
Un arrondissement
\r\n\r\n
\r\n
\r\n\t\t\t\tRecherche directe
\r\n\t\t\t\trechercher une ville
et/ou une boutique
\r\n\t\t\t\t

\r\n\t\t\t\t \r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
Recherche avanc\351e
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n\t\r\n\t\t\r\n\t\r\n
\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t
Bureautique
\r\n\t\t\t\tTraducteur, organiseur...

\r\n\t\t\t\t

Multim\351dia
\r\n\t\t\t\tPhoto, audio, vid\351o...

\r\n\t\t\t\t

Utilitaires
\r\n\t\t\t\tAntivirus, pilotes, gravure...

\r\n\t\t\t\t

Personnaliser son PC
\r\n\t\t\t\tEcrans de veille, th\350mes...

\r\n\t\t\t\t

D\351veloppement
\r\n\t\t\t\tCr\351ation de logiciels, BDD...

\r\n\t\t\t\t

Jeux
\r\n\t\t\t\tAction, simulation...

\r\n\t\t\t\t

Internet
\r\n\t\t\t\tUtilitaires, email, FTP...

\r\n\t\t\t\t

Loisirs
\r\n\t\t\t\tHumour, culture...

\r\n\t\t\t\t
\r\n\t\t
\r\n
\r\n
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\r\n\t\t
\r\n\t\t
\r\n\t\t\r\n\t\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\r\n\t\t

\r\n\t\t\t\r\n\r\n\r\n\r\n\r\n\r\n
\r\n
\r\n
\r\n\r\n\r\n\r\n - - -// We also need to import here all header files that -// define globals so that consumers that use them despite -// requesting them not to be declared with OPENVPN_EXTERN - -#include -#include "test_helper.hpp" -#include -#include - -openvpn::LogOutputCollector *testLog; - -int main (int argc, char **argv) -{ - testLog = new openvpn::LogOutputCollector(); - ::testing::InitGoogleTest (&argc, argv); - openvpn::InitProcess::Init init; - auto ret = RUN_ALL_TESTS (); - - delete testLog; - return ret; -} diff --git a/Sources/OpenVPN3/test/unittests/test_b64.cpp b/Sources/OpenVPN3/test/unittests/test_b64.cpp deleted file mode 100644 index 05b3319..0000000 --- a/Sources/OpenVPN3/test/unittests/test_b64.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// 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-2020 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. - - -#include "test_common.h" - -#include - -#include -#include - -using namespace openvpn; - - -#ifdef USE_OPENSSL -#include -#include -#include -#include - -#include - -std::string ssllib_b64enc(const char* text, size_t textlen) -{ - BIO *bio, *b64; - - b64 = BIO_new(BIO_f_base64()); - bio = BIO_new(BIO_s_mem()); - bio = BIO_push(b64, bio); - - BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line - BIO_write(bio, text, (int)textlen); - EXPECT_TRUE(BIO_flush(bio) == 1); - const char* encdata; - long len = BIO_get_mem_data(bio, &encdata); - - /* If there is nothing to encode OpenSSL gives back a nullptr */ - if (len == 0) - encdata = ""; - - std::string ret(encdata, (size_t)len); - BIO_free_all(bio); - - return ret; -} -#else -#include - -std::string ssllib_b64enc(const char* text, size_t textlen) -{ - size_t olen, outlen; - - //make a pessimistic assumption about length always calculate 3 padding bytes - outlen = 3 + 4*(textlen+3)/3; - - char *dst = new char[outlen]; - - EXPECT_EQ(mbedtls_base64_encode(reinterpret_cast(dst), outlen, - &olen, reinterpret_cast(text), textlen), 0); - std::string ret(dst, olen); - delete[] dst; - return ret; -} -#endif - - -void b64_test(const Base64& b64, const std::string& text) -{ - const std::string enc = b64.encode(text); - std::string dec = b64.decode(enc); - std::string libenc = ssllib_b64enc(text.c_str(), text.size()); - - EXPECT_EQ(text, dec) << "Encode/Decode results differ"; - EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result"; -} - -void b64_test_binary(const Base64& b64, const char* data, unsigned int len) -{ - auto enc = b64.encode(data, len); - - char* decdata = new char[len]; - size_t decode_len = b64.decode(decdata, len, enc); - std::string libenc = ssllib_b64enc(data, len); - - EXPECT_EQ(enc, libenc) << "Encode differs from Crypto lib result"; - - ASSERT_EQ(decode_len, len) << "Encode/decode length differs"; - ASSERT_EQ(std::vector(decdata, decdata + decode_len), - std::vector(data, data + len)) << "Encode/Decode results differ"; - - delete[] decdata; -} - -TEST(Base64, tooshortdest) -{ - const Base64 b64; - auto enc = b64.encode(std::string("abc")); - - char buf[2]; - EXPECT_THROW(b64.decode(buf, 2, enc), Base64::base64_decode_out_of_bound_error); -} - -void b64_test_bad_decode(const Base64& b64, const std::string& text) -{ - std::string dec; - EXPECT_THROW(b64.decode(dec, text), Base64::base64_decode_error); -} - -TEST(Base64, baddecode) -{ - const Base64 b64; - - b64_test_bad_decode(b64, "!@#$%^&*()_"); - b64_test_bad_decode(b64, "plausible deniability"); - b64_test_bad_decode(b64, "plausible != deniability"); - b64_test_bad_decode(b64, "x"); - b64_test_bad_decode(b64, "===="); - b64_test_bad_decode(b64, "xxxx="); - b64_test_bad_decode(b64, "01*="); -} - -TEST(Base64, encode) -{ - const Base64 b64; - - b64_test(b64, "Hello world!"); - b64_test(b64, "привет!"); - b64_test(b64, "ûmbrellaûmbrella"); - b64_test(b64, "一旦在一个è“色的月亮"); - b64_test(b64, "x"); - b64_test(b64, "one two three"); - b64_test(b64, "aa"); - b64_test(b64, "get your kicks on ... route 66"); - b64_test(b64, "fight the future"); - b64_test(b64, ""); - b64_test(b64, "I want to believe..."); - b64_test(b64, "it was a weather balloon"); - b64_test(b64, "hyperspatial bypass"); - b64_test(b64, "ode to a vogon"); - b64_test(b64, "Acme Travel"); - b64_test(b64, "there's no sunshine when she's gone"); - b64_test(b64, "??????????????????????"); - b64_test(b64, "???????????????????????"); - b64_test(b64, "????????????????????????"); - b64_test(b64, "???x>>>>>>>>>?????????????"); - b64_test(b64, "???x>>>>>>>>>??????????????"); - b64_test(b64, "???x>>>>>>>>>?????????????x>>"); -} - -TEST(Base64, binary_data) -{ - - const Base64 b64; - std::srand(0); - for(unsigned int i=0;i<20;i++) - { - char* data = new char[i]; - for (unsigned int j=0;j -#include "test_helper.hpp" -#include diff --git a/Sources/OpenVPN3/test/unittests/test_comp.cpp b/Sources/OpenVPN3/test/unittests/test_comp.cpp deleted file mode 100644 index 925fcdd..0000000 --- a/Sources/OpenVPN3/test/unittests/test_comp.cpp +++ /dev/null @@ -1,262 +0,0 @@ -// 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-2020 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 . - -#include -#include // for std::min - -#ifndef BLOCK_SIZE -#define BLOCK_SIZE 1500 -#endif - -#ifndef N_COMPRESS -#define N_COMPRESS 1 -#endif - -#ifndef N_EXPAND -#define N_EXPAND 1 -#endif - -#ifndef SUPPORT_SWAP -#define SUPPORT_SWAP false -#endif - -// other defines: -// must define TEST_x to define compressor/decompressor pair -// OPENVPN_DEBUG_COMPRESS = 0|1|2 - -#include "test_common.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace openvpn; - -Frame::Ptr frame_init(const size_t payload) -{ - const size_t headroom = 512; - const size_t tailroom = 512; - const size_t align_block = 16; - const unsigned int buffer_flags = 0; - - Frame::Ptr frame(new Frame(Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags))); - frame->standardize_capacity(~0); - return frame; -} - -class MySessionStats : public SessionStats -{ -public: - typedef RCPtr Ptr; - - MySessionStats() - { - std::memset(errors, 0, sizeof(errors)); - } - - virtual void error(const size_t err_type, const std::string* text=NULL) - { - if (err_type < Error::N_ERRORS) - ++errors[err_type]; - } - - count_t get_error_count(const Error::Type type) const - { - if (type < Error::N_ERRORS) - return errors[type]; - else - return 0; - } - -private: - count_t errors[Error::N_ERRORS]; -}; - -inline void verify_eq(const Buffer& b1, const Buffer& b2) -{ - ASSERT_EQ(b1, b2) << "decompressed data doesn't match original data"; -} - -void test(const std::string& filename, - Compress& compressor, - Compress& decompressor, - const Frame& frame, - const size_t block_size, - const size_t n_compress, - const size_t n_expand_per_compress, - size_t& bytes, - size_t& compress_bytes) -{ - BufferPtr source_data = read_binary(filename); - for (size_t offset = 0; offset < source_data->size(); offset += block_size) - { - const size_t length = std::min(block_size, source_data->size() - offset); - BufferAllocated data_seg; - frame.prepare(Frame::DECRYPT_WORK, data_seg); - data_seg.write(source_data->data_raw() + offset, length); - for (size_t compress_iter = 0; compress_iter < n_compress; ++compress_iter) - { - BufferAllocated data1(data_seg); - bytes += data1.size(); - compressor.compress(data1, true); - compress_bytes += data1.size(); - if (n_expand_per_compress == 1) - { - decompressor.decompress(data1); - verify_eq(data_seg, data1); - } - else - { - for (size_t decompress_iter = 0; decompress_iter < n_expand_per_compress; ++decompress_iter) - { - BufferAllocated data2(data1); - decompressor.decompress(data2); - verify_eq(data_seg, data2); - } - } - } - } -} - -void test_with_corpus(Compress& compressor, - Compress& decompressor, - const Frame& frame, - const size_t block_size, - const size_t n_compress, - const size_t n_expand_per_compress, - size_t& bytes, - size_t& compress_bytes) -{ - static const std::vector filenames = { - "comp-testdata/alice29.txt", - "comp-testdata/asyoulik.txt", - "comp-testdata/cp.html", - "comp-testdata/fields.c", - "comp-testdata/geo.protodata", - "comp-testdata/grammar.lsp", - "comp-testdata/house.jpg", - "comp-testdata/html", - "comp-testdata/html_x_4", - "comp-testdata/kennedy.xls", - "comp-testdata/kppkn.gtb", - "comp-testdata/lcet10.txt", - "comp-testdata/mapreduce-osdi-1.pdf", - "comp-testdata/plrabn12.txt", - "comp-testdata/ptt5", - "comp-testdata/sum", - "comp-testdata/urls.10K", - "comp-testdata/xargs.1", - }; - for (auto fn: filenames) { - test(std::string(UNITTEST_SOURCE_DIR) + '/' + fn, compressor, decompressor, frame, block_size, n_compress, n_expand_per_compress, bytes, - compress_bytes); - } -} - -enum class comppair { - lzo, - lzoasym, - snappy, - lz4 -}; - -void runTest(comppair alg, bool verbose=false) -{ - CompressContext::init_static(); - MySessionStats::Ptr stats(new MySessionStats); - Frame::Ptr frame = frame_init(BLOCK_SIZE); - - - Compress::Ptr compress; - Compress::Ptr decompress; - - switch (alg) { -#if defined(HAVE_LZO) - case comppair::lzoasym: - compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false)); - decompress.reset(new CompressLZOAsym(frame, stats, SUPPORT_SWAP, false)); - break; - - case comppair::lzo: - compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false)); - decompress = compress; - break; - -#endif -#if defined(HAVE_LZ4) - case comppair::lz4: - compress.reset(new CompressLZ4(frame, stats, false)); - decompress = compress; - break; -#endif -#if defined(HAVE_SNAPPY) - case comppair::snappy: - compress.reset(new CompressSnappy(frame, stats, false)); - decompress = compress; - break; -#endif - default: - ASSERT_TRUE(false) << "compressor/decompressor pair not supported"; - } - size_t bytes = 0; - size_t compress_bytes = 0; - test_with_corpus(*compress, *decompress, *frame, BLOCK_SIZE, N_COMPRESS, N_EXPAND, bytes, compress_bytes); - - if (verbose) - std::cout << "comp=" << compress->name() << '[' << N_COMPRESS << ']' - << " decomp=" << decompress->name() << '[' << N_EXPAND << ']' - << " blk=" << BLOCK_SIZE - << " bytes=" << bytes - << " comp-bytes=" << compress_bytes - << " comp-ratio=" << (float) compress_bytes / bytes - << std::endl; -} - -namespace unittests -{ -#if defined(HAVE_SNAPPY) - TEST(Compression, snappy) - { - runTest(comppair::snappy); - } -#endif -#if defined(HAVE_LZO) - TEST(Compression, lzo) - { - runTest(comppair::lzo); - } - - TEST(Compression, lzoasym) - { - runTest(comppair::lzoasym); - } -#endif -#if defined(HAVE_LZ4) - TEST(Compression, lz4) - { - runTest(comppair::lz4); - } -#endif -} diff --git a/Sources/OpenVPN3/test/unittests/test_continuation.cpp b/Sources/OpenVPN3/test/unittests/test_continuation.cpp deleted file mode 100644 index 491c89a..0000000 --- a/Sources/OpenVPN3/test/unittests/test_continuation.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// 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. - -//#define OPENVPN_BUFFER_ABORT - -#include - -#include "test_common.h" - -#include -#include - -#include -#include - -using namespace openvpn; - -static void require_equal(const OptionList& opt1, const OptionList& opt2, const std::string& title) -{ - if (opt1 != opt2) - { - OPENVPN_LOG(title); - ASSERT_EQ(opt1.render(Option::RENDER_BRACKET), opt2.render(Option::RENDER_BRACKET)); - } -} - -static void require_equal(const Buffer& buf1, const Buffer& buf2, const std::string& title) -{ - if (buf1 != buf2) - { - OPENVPN_LOG(title); - ASSERT_EQ(buf_to_string(buf1), buf_to_string(buf2)); - } -} - -// push continuation mode -enum PCMode { - NO_PC, - PC_1, - PC_2, -}; - -static std::string get_csv(Buffer buf, const PCMode pc_mode) -{ - // verify PUSH_REPLY then remove it - if (!string::starts_with(buf, "PUSH_REPLY,")) - throw Exception("expected that buffer would begin with PUSH_REPLY"); - buf.advance(11); - - // possibly remove push-continuation options from tail of buffer - if (pc_mode == PC_1) - { - if (!string::ends_with(buf, ",push-continuation 1")) - throw Exception("expected that buffer would end with push-continuation 1"); - buf.set_size(buf.size() - 20); - } - else if (pc_mode == PC_2) - { - if (!string::ends_with(buf, ",push-continuation 2")) - throw Exception("expected that buffer would end with push-continuation 2"); - buf.set_size(buf.size() - 20); - } - - return buf_to_string(buf); -} - -static std::string get_csv_from_frag(Buffer buf, const size_t index, const size_t size) -{ - if (size < 2) - return get_csv(buf, NO_PC); - else if (index == size - 1) - return get_csv(buf, PC_1); - else - return get_csv(buf, PC_2); -} - -static std::string random_term(RandomAPI& prng) -{ - static const std::string rchrs = "012abcABC,\"\\"; - - std::string ret; - const int len = prng.randrange32(1, 16); - ret.reserve(len); - for (int i = 0; i < len; ++i) - ret += rchrs[prng.randrange32(rchrs.size())]; - return ret; -} - -static Option random_opt(RandomAPI& prng) -{ - Option ret; - const int len = prng.randrange32(1, 4); - ret.reserve(len); - for (int i = 0; i < len; ++i) - ret.push_back(random_term(prng)); - return ret; -} - -static OptionList random_optionlist(RandomAPI& prng) -{ - static const int sizes[3] = {10, 100, 1000}; - - OptionList ret; - const int len = prng.randrange32(1, sizes[prng.randrange32(3)]); - ret.reserve(len); - for (int i = 0; i < len; ++i) - ret.push_back(random_opt(prng)); - return ret; -} - -static void test_roundtrip(const OptionList& opt_orig) -{ - // first render to CSV - BufferAllocated buf(opt_orig.size() * 128, BufferAllocated::GROW); - buf_append_string(buf, "PUSH_REPLY,"); - buf_append_string(buf, opt_orig.render_csv()); - - // parse back to OptionList and verify round trip - const OptionList opt = OptionList::parse_from_csv_static_nomap(get_csv(buf, NO_PC), nullptr); - require_equal(opt_orig, opt, "TEST_ROUNDTRIP #1"); - - // fragment into multiple buffers using push-continuation - const PushContinuationFragment frag(buf); - - // parse fragments separately and verify with original - OptionList new_opt; - for (size_t i = 0; i < frag.size(); ++i) - new_opt.parse_from_csv(get_csv_from_frag(*frag[i], i, frag.size()), nullptr); - require_equal(opt_orig, new_opt, "TEST_ROUNDTRIP #2"); - - // test client-side continuation parser - OptionListContinuation cc; - for (size_t i = 0; i < frag.size(); ++i) - { - const OptionList cli_opt = OptionList::parse_from_csv_static(get_csv(*frag[i], NO_PC), nullptr); - cc.add(cli_opt, nullptr); - ASSERT_TRUE(cc.partial()); - ASSERT_EQ(cc.complete(), i == frag.size() - 1); - } - - // remove client-side push-continuation directives before comparison - cc.erase(std::remove_if(cc.begin(), cc.end(), - [](const Option& o) - { - return o.size() >= 1 && o.ref(0) == "push-continuation"; - }), - cc.end()); - require_equal(opt_orig, cc, "TEST_ROUNDTRIP #3"); - - // defragment back to original form - BufferPtr defrag = PushContinuationFragment::defragment(frag); - require_equal(buf, *defrag, "TEST_ROUNDTRIP #4"); -} - -// test roundtrip for random configurations -TEST(continuation, test1) -{ - RandomAPI::Ptr prng(new MTRand); - - // Note: this code runs ~100x slower with valgrind - const int n = 100; - - for (int i = 0; i < n; ++i) - { - const OptionList opt = random_optionlist(*prng); - test_roundtrip(opt); - } -} - -// test maximum fragment sizes and optionally generate -// push-list for further testing -TEST(continuation, test2) -{ - BufferAllocated buf(65536, BufferAllocated::GROW); - buf_append_string(buf, "PUSH_REPLY,route-gateway 10.213.0.1,ifconfig 10.213.0.48 255.255.0.0,ifconfig-ipv6 fdab::48/64 fdab::1,client-ip 192.168.4.1,ping 1,ping-restart 8,reneg-sec 60,cipher AES-128-GCM,compress stub-v2,peer-id 4,topology subnet,explicit-exit-notify"); - - // pack the buffers, so several reach the maximum - // fragment size of PushContinuationFragment::FRAGMENT_SIZE - for (int i = 0; i < 1000; ++i) - { - if (i % 100 == 0) - buf_append_string(buf, ",echo rogue-agent-neptune-" + std::to_string(i/100)); - buf_append_string(buf, ",echo test-" + std::to_string(i)); - } - - // fragment into multiple buffers using push-continuation - const PushContinuationFragment frag(buf); - int count = 0; - for (auto &e : frag) - { - //OPENVPN_LOG(e->size()); - if (e->size() == PushContinuationFragment::FRAGMENT_SIZE) - ++count; - } - - // 8 buffers should have reached maximum size - ASSERT_EQ(count, 8); - - // defragment the buffer - BufferPtr defrag = PushContinuationFragment::defragment(frag); - const OptionList opt = OptionList::parse_from_csv_static_nomap(get_csv(*defrag, NO_PC), nullptr); - -#if 0 - // dump for inclusion in JSON push list - for (const auto &e : opt) - { - OPENVPN_LOG(" \"" << e.render(0) << "\","); - } -#endif -} diff --git a/Sources/OpenVPN3/test/unittests/test_cpu_time.cpp b/Sources/OpenVPN3/test/unittests/test_cpu_time.cpp deleted file mode 100644 index 32819bf..0000000 --- a/Sources/OpenVPN3/test/unittests/test_cpu_time.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// 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) 2019-2020 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 . - - -// We have two set of measurements for these tests -// -// 1. A coarse measurement based on time() -// These are tracked in 'chk_start' and 'chk_end' -// -// 2. A fine grained measurement from cpu_time() -// These are tracked in 'start' and 'end' -// -// We calculate the difference before and after a -// a workload has run, to measure how long it ran. -// This is done for both measurement approaches. -// The runtime is saved in runtime and chk_runtime -// -// To pass this test, absolute difference between -// runtime and chk_runtime must be less than 1 second. -// - -//#define DEBUG // Define this macro to get more details - -#include "test_common.h" -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) \ - std::cout << msg << std::endl \ - << "start = " << std::to_string(st) << std::endl \ - << "end = " << std::to_string(en) << std::endl \ - << "runtime = " << std::to_string(rt) << std::endl \ - << "chk_start = " << std::to_string(chst) << std::endl \ - << "chk_end = " << std::to_string(chen) << std::endl \ - << "chk_runtime = " << std::to_string(chrt) << std::endl \ - << "measurement difference = " \ - << std::to_string(md) << std::endl \ - << "--------------------------------------" << std::endl - -#else -#define DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) {} -#endif - -#define MEASURE(v, chkv, thread) \ - double v = openvpn::cpu_time(thread); \ - ASSERT_GE(v, 0); \ - double chkv = time(NULL) - -#define CALCULATE(msg, st, en, rt, chst, chen, chrt, md) \ - double rt = en - st; \ - double chrt = chen - chst; \ - double md = std::max(rt, chrt) - std::min(rt, chrt); \ - DEBUG_DUMP(msg, st, en, rt, chst, chen, chrt, md) - - -typedef std::shared_ptr ThreadPtr; - - -// For simplicty, keep the total thread runtime -// in a global variable, protected by a mutex -// on updates -std::mutex update_guard; -double thread_runtime = 0; - -void update_thread_runtime(double val) -{ - std::lock_guard ug(update_guard); - thread_runtime += val; -} - - -namespace unittests -{ - static void workload(const uint16_t multiplier) - { - // A very simple busy loop workload - // - // We can't use sleep() or any similar timing - // as this does not increase the tracked runtime - // in the kernel; the process does not really run. - // - - std::random_device rd; - std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() - - - double d=0; - for (unsigned int i = UINT16_MAX * multiplier; i > 0; i--) - { - d += gen(); - } - } - - - TEST(CPUTime, cpu_time_pid) - { - // Measure the runtime of the workload - MEASURE(start, chk_start, false); - workload(400); - MEASURE(end, chk_end, false); - - // Calculate runtimes and differences - CALCULATE("single PID", - start, end, runtime, - chk_start, chk_end, chk_runtime, - measurement_diff); - - ASSERT_LT(measurement_diff, 10); - } - - - void worker_thread(const uint8_t id) - { - MEASURE(thr_start, chk_thr_start, true); - workload(400); - MEASURE(thr_end, chk_thr_end, true); - - CALCULATE("Worker thread " << std::to_string(id), - thr_start, thr_end, thr_runtime, - chk_thr_start, chk_thr_end, chk_thr_runtime, - thr_measurement_diff); - update_thread_runtime(thr_runtime); - - // Since the chk_thr_runtime (chk_thr_end - chk_thr_start) - // is based on epoc seconds of the system, this doesn't - // give a too good number when running multiple threads. - // - // If more threads are running on the same CPU core, - // one of the threads might be preempted. The clock time - // (chk_thr_runtime) will continue to tick, but the real - // runtime (thr_runtime) will not. Which will increase - // the difference between the measured runtimes. - // - // The value of 5 is just an educated guess of what - // we might find acceptable. This might be too high - // on an idle system, but too low on a loaded system. - // - ASSERT_LT(thr_measurement_diff, 5); - } - - - void run_threads(const uint8_t num_threads) - { - std::vector threads; - for (uint8_t i = 0; i < num_threads; i++) - { - ThreadPtr tp; - tp = std::make_shared([id=i](){ worker_thread(id); }); - threads.push_back(tp); - } - - for (const auto& t : threads) - { - t->join(); - } - } - - - TEST(CPUTime, cpu_time_thread_1) - { - // Meassure running a single worker thread - MEASURE(parent_start, chk_parent_start, false); - run_threads(1); - MEASURE(parent_end, chk_parent_end, false); - - CALCULATE("Parent thread - 1 child thread", - parent_start, parent_end, runtime, - chk_parent_start, chk_parent_end, chk_runtime, - parent_diff); - - ASSERT_LT(parent_diff, 10); - } - - - TEST(CPUTime, cpu_time_thread_numcores) - { - // Use number of available cores - auto num_cores = std::min(std::thread::hardware_concurrency(), 1u); - - // Meassure running a single worker thread - MEASURE(parent_start, chk_parent_start, false); - run_threads(num_cores); - MEASURE(parent_end, chk_parent_end, false); - - CALCULATE("Parent thread - " << std::to_string(num_cores) << " child thread", - parent_start, parent_end, runtime, - chk_parent_start, chk_parent_end, chk_runtime, - parent_diff); -#ifdef DEBUG - std::cout << "Total thread runtime: " << std::to_string(thread_runtime) << std::endl; -#endif - - // The main process (this PID) will have a total runtime - // which accounts for all runtime of the running threads. - // We still give a bit extra slack, to reduce the risk of - // false positives, due to the possibility of premption - // (see comment in worker_thread() for details). But - // the difference should not neccesarily deviate as much - // here. - ASSERT_LT(parent_diff, 3 + thread_runtime); - } -} // namespace diff --git a/Sources/OpenVPN3/test/unittests/test_helper.hpp b/Sources/OpenVPN3/test/unittests/test_helper.hpp deleted file mode 100644 index aba3b3c..0000000 --- a/Sources/OpenVPN3/test/unittests/test_helper.hpp +++ /dev/null @@ -1,313 +0,0 @@ -// 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-2020 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. - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace openvpn { - class LogOutputCollector : public LogBase - { - public: - LogOutputCollector() : log_context(this) - { - } - - void log(const std::string& l) override - { - std::lock_guard lock(mutex); - - if (output_log) - std::cout << l; - if (collect_log) - out << l; - } - - /** - * Return the collected log out - * @return the log output as string - */ - std::string getOutput() const - { - return out.str(); - } - - /** - * Allow to access the underlying output stream to direct - * output from function that want to write to a stream to it - * @return that will be captured by this log - */ - std::ostream& getStream() - { - return out; - } - - /** - * Changes if the logging to stdout should be done - * @param doOutput - */ - void setPrintOutput(bool doOutput) - { - output_log = doOutput; - } - - /** - * Return current state of stdout output - * @return current state of output - */ - bool isStdoutEnabled() const - { - return output_log; - } - - /** - * Starts collecting log output. This will also - * disable stdout output and clear the collected output if there is any - */ - void startCollecting() - { - collect_log = true; - output_log = false; - // Reset our buffer - out.str(std::string()); - out.clear(); - } - - /** - * Stops collecting log output. Will reenable stdout output. - * @return the output collected - */ - std::string stopCollecting() - { - collect_log = false; - output_log = true; - return getOutput(); - } - - private: - bool output_log = true; - bool collect_log = false; - std::stringstream out; - std::mutex mutex{}; - Log::Context log_context; - }; -} - -extern openvpn::LogOutputCollector* testLog; - -/** - * Overrides stdout during the run of a function. Primarly for silencing - * log function that throw an exception when something is wrong - * @param doLogOutput Use stdout while running - * @param test_func function to run - */ -inline void override_logOutput(bool doLogOutput, void (* test_func)()) -{ - bool previousOutputState = testLog->isStdoutEnabled(); - testLog->setPrintOutput(doLogOutput); - test_func(); - testLog->setPrintOutput(previousOutputState); -} - -/** - * Reads the file with the expected output and returns it as a - * string. This function delibrately does not include the - * ASSERT_EQ call since otherwise gtest will report a the - * assert failure in this file rather than in the right place - * @param filename - * @return - */ -inline std::string getExpectedOutput(const std::string& filename) -{ - auto fullpath = UNITTEST_SOURCE_DIR "/output/" + filename; - std::ifstream f(fullpath); - if (!f.good()) - { - throw std::runtime_error("Error opening file " + fullpath); - } - std::string expected_output((std::istreambuf_iterator(f)), - std::istreambuf_iterator()); - return expected_output; -} - -#ifdef WIN32 -#include - -inline std::string getTempDirPath(const std::string& fn) -{ - char buf [MAX_PATH]; - - EXPECT_NE(GetTempPathA(MAX_PATH, buf), 0); - return std::string(buf) + fn; -} -#else - -inline std::string getTempDirPath(const std::string& fn) -{ - return "/tmp/" + fn; -} - -#endif - -/** - * Returns a sorted string join with the delimiter - * This function modifes the input - * @param r the array to join - * @param delim the delimiter to use - * @return A string joined by delim from the sorted vector r - */ -template -inline std::string getSortedJoinedString(std::vector& r, const std::string& delim = "|") -{ - std::sort(r.begin(), r.end()); - std::stringstream s; - std::copy(r.begin(), r.end(), std::ostream_iterator(s, delim.c_str())); - return s.str(); -} - -namespace detail { - class line - { - std::string data; - public: - friend std::istream& operator>>(std::istream& is, line& l) - { - std::getline(is, l.data); - return is; - } - - operator std::string() const - { return data; } - }; -} - -/** - * Splits a string into lines and returns them in a sorted output string - */ -inline std::string getSortedString(const std::string& output) -{ - std::stringstream ss{output}; - - std::istream_iterator begin{ss}; - std::istream_iterator end; - std::vector lines {begin, end}; - - // sort lines - std::sort(lines.begin(), lines.end()); - - // join strings with \n - std::stringstream s; - std::copy(lines.begin(), lines.end(), std::ostream_iterator(s, "\n")); - return s.str(); -} - -/** - * Predictable RNG that claims to be secure to be used in reproducable unit - * tests - */ -class FakeSecureRand : public openvpn::RandomAPI -{ -public: - FakeSecureRand(const unsigned char initial=0) - : next(initial) - { - } - - virtual std::string name() const override - { - return "FakeRNG"; - } - - virtual bool is_crypto() const override - { - return true; - } - - virtual void rand_bytes(unsigned char *buf, size_t size) override - { - rand_bytes_(buf, size); - //OPENVPN_LOG("RAND: " << openvpn::render_hex(buf, size)); - } - - virtual bool rand_bytes_noexcept(unsigned char *buf, size_t size) override - { - rand_bytes(buf, size); - return true; - } - -private: - // fake RNG -- just use an incrementing sequence - void rand_bytes_(unsigned char *buf, size_t size) - { - while (size--) - *buf++ = next++; - } - - unsigned char next; -}; - -// googletest is missing the ability to test for specific -// text inside a thrown exception, so we implement it here - -#define JY_EXPECT_THROW(statement, expected_exception, expected_text) \ -try { \ - statement; \ - OPENVPN_THROW_EXCEPTION("JY_EXPECT_THROW: no exception was thrown " << __FILE__ << ':' << __LINE__); \ -} \ -catch (const expected_exception& e) \ -{ \ - if (std::string(e.what()).find(expected_text) == std::string::npos) \ - OPENVPN_THROW_EXCEPTION("JY_EXPECT_THROW: did not find expected text in exception at " << __FILE__ << ':' << __LINE__); \ -} - -// googletest ASSERT macros can't be used inside constructors -// or non-void-returning functions, so implement workaround here - -#define JY_ASSERT_TRUE(value) \ -{ \ - if (!(value)) \ - OPENVPN_THROW_EXCEPTION("JY_ASSERT_TRUE: failure at " << __FILE__ << ':' << __LINE__); \ -} - -#define JY_ASSERT_FALSE(value) \ -{ \ - if (value) \ - OPENVPN_THROW_EXCEPTION("JY_ASSERT_FALSE: failure at " << __FILE__ << ':' << __LINE__); \ -} - -#define JY_ASSERT_EQ(v1, v2) \ -{ \ - if ((v1) != (v2)) \ - OPENVPN_THROW_EXCEPTION("JY_ASSERT_EQ: failure at " << __FILE__ << ':' << __LINE__); \ -} - -#define JY_ASSERT_NE(v1, v2) \ -{ \ - if ((v1) == (v2)) \ - OPENVPN_THROW_EXCEPTION("JY_ASSERT_NE: failure at " << __FILE__ << ':' << __LINE__); \ -} diff --git a/Sources/OpenVPN3/test/unittests/test_iphelper.cpp b/Sources/OpenVPN3/test/unittests/test_iphelper.cpp deleted file mode 100644 index 5a3b670..0000000 --- a/Sources/OpenVPN3/test/unittests/test_iphelper.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// 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-2020 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. - -#include -#include "test_common.h" - -#include -#include -#include - -using namespace openvpn; -using namespace openvpn::TunWin::Util; - -namespace unittests -{ - static std::string path_to_ip; - - class IpHelperTest : public testing::Test - { - protected: - void SetUp() override - { - // get index of default network adapter - DWORD addr; - inet_pton(AF_INET, "8.8.8.8", &addr); - ::GetBestInterface(addr, &tap.index); - } - - virtual void TearDown() - { - remove_cmds.execute(os); - remove_cmds.clear(); - } - - TapNameGuidPair tap; - ActionList remove_cmds; - std::ostringstream os; - }; - - TEST_F(IpHelperTest, TestAddRoute4) - { - const char* gw = "10.10.123.123"; - const char* route = "10.10.0.0"; - int route_prefix = 16; - int metric = 123; - - TunIPHELPER::AddRoute4Cmd cmd{route, route_prefix, tap, gw, metric, true}; - remove_cmds.add(new TunIPHELPER::AddRoute4Cmd{route, route_prefix, tap, gw, metric, false}); - - // add route - cmd.execute(os); - - // get next hop for routed address - MIB_IPFORWARDROW row; - DWORD addr; - inet_pton(AF_INET, "10.10.0.3", &addr); - GetBestRoute(addr, 0, &row); - char next_hop[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &row.dwForwardNextHop, next_hop, INET_ADDRSTRLEN); - - // the next hop should equal route gw - ASSERT_STREQ(gw, next_hop); - } -} diff --git a/Sources/OpenVPN3/test/unittests/test_log.cpp b/Sources/OpenVPN3/test/unittests/test_log.cpp deleted file mode 100644 index cbce744..0000000 --- a/Sources/OpenVPN3/test/unittests/test_log.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// 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-2020 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 . - -#include "test_common.h" - - -// The ovpncli.cpp file is not all OPENVPN_EXTERN safe and totally breaks -// if included in two files. We probably need to fix this or rename this -// file test_ovpncli and do ALL test that require ovpncli in this file -// (or have multiple test suites) - -// This file needs to included with OPENVPN_EXTERN still defined otherwise -// the include from ovpncli.cpp breaks with duplicate symbols -#include - - -#include - - -#include -#include - -namespace unittests -{ - TEST(LogInfoTest, TestLogInfo) - { - std::string msg("logMessage"); - openvpn::ClientAPI::LogInfo logInfo(msg); - auto text = logInfo.text; - - ASSERT_EQ(text, msg); - } -} // namespace diff --git a/Sources/OpenVPN3/test/unittests/test_mbedtls_x509certinfo.cpp b/Sources/OpenVPN3/test/unittests/test_mbedtls_x509certinfo.cpp deleted file mode 100644 index 9cb82e4..0000000 --- a/Sources/OpenVPN3/test/unittests/test_mbedtls_x509certinfo.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// 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-2020 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 . -// -// -// Basic unit test for the openvpn/openssl/pki/x509certinfo.hpp functions -// - -#include - -#include "test_common.h" -#include "openvpn/mbedtls/pki/x509cert.hpp" -#include "openvpn/mbedtls/pki/x509certinfo.hpp" - -using namespace openvpn; - -namespace unittests { - -std::string test_cert = - "-----BEGIN CERTIFICATE-----\n" - "MIIFrjCCA5agAwIBAgIJFXABl4gwlJIEMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV\n" - "BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UEBwwKUGxlYXNhbnRvbjEYMBYGA1UE\n" - "CgwPT3BlblZQTi1URVNULUNBMSUwIwYJKoZIhvcNAQkBFhZleGFtcGxlLmNhQGV4\n" - "YW1wbGUubmV0MB4XDTE5MTAwMjEyMzY0OFoXDTI5MDkyOTEyMzY0OFowezELMAkG\n" - "A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQKDAxPcGVuVlBOLVRFU1QxHTAb\n" - "BgNVBAMMFHNlcnZlci0xLmV4YW1wbGUubmV0MSkwJwYJKoZIhvcNAQkBFhpleGFt\n" - "cGxlLXNlcnZlckBleGFtcGxlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" - "AQoCggEBAN7KKMU2A7X74KYn+agBvQmW2zr/OFH/PJn6sMk94aDAIWsa7KccuV8W\n" - "d/69XH2FXK2ygSd9df8kO8mGkDl1w5nC/LUk5V0KNqsZGLyNDRvulSFJ2eQChOOs\n" - "snOdpf17e/yzs08KY5RME9+HBWx2GpQQWHVsmqvPF+pPJnBctOm8azBOAUZRDBuj\n" - "TxCWtwLwVjnFHGSATETuvCiTPuDa9sbw5ibCLFz9ge94ptXcXEU6z+GuighQI9rU\n" - "o8BVFF6DiaWZn3jC5KsA1dX81c+UpDpxwOpG9MXg8RRm8rWwsvC/RvjVYjGDBdra\n" - "oSuHWPjzH1DIJ31ptjKUPAVdR8ZxAGcCAwEAAaOCAT4wggE6MAkGA1UdEwQCMAAw\n" - "EQYJYIZIAYb4QgEBBAQDAgZAMDQGCWCGSAGG+EIBDQQnFiVUZXN0IENlcnRpZmlj\n" - "YXRlIC0gTk9UIEZPUiBQUk9EVUNUSU9OMB0GA1UdDgQWBBRsQDoK1XxrwQdrKmcC\n" - "7/HfbSrQFTCBogYDVR0jBIGaMIGXgBTa10VpSdTIo1PhrwMuGmGrUMerq6F0pHIw\n" - "cDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRMwEQYDVQQHDApQbGVhc2FudG9u\n" - "MRgwFgYDVQQKDA9PcGVuVlBOLVRFU1QtQ0ExJTAjBgkqhkiG9w0BCQEWFmV4YW1w\n" - "bGUuY2FAZXhhbXBsZS5uZXSCCQDm/rJ9Tz3bEDATBgNVHSUEDDAKBggrBgEFBQcD\n" - "ATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAHl41WvFsh+nscCx+1X2\n" - "RudmnsuKHFUAktpAOdG3vh+5zh2v3PZYWoS4sgmBl0Zvia4VC/xTrcC2ywJILLAM\n" - "cda6CUXMF3+kJMi+qlgn6WRn9RsUHLQFa1/y7zNkuo38zkLlJaiKPQfm1YPkUtnr\n" - "n74W9XBrZ2rWBsqL2XCDayEs1IAjL9zs0F1Bs0MCgf+BccCu7wFL886+Y8mhAkRJ\n" - "c0aniG/bsawOrrF8JwW2MP/QpPls2BSWmfwJASxX57AbSQ8TmMf289ozTupcBVMC\n" - "N973ks9n/35cRtW9SHtwpdsb4nvXFZi6DCfyS3PBpHgi/mRuhgWWSLaVr40RnlHI\n" - "NvW0x7SPJwkbHeWz6PStrZJLjkJ9LuvRQwb2+wH6SjIxQiJ/AMXlSL2USASdLR32\n" - "eiPUWq5xalTrNQINcnEfVT/ruTInY2vytUaQgFTQvJKp0DJZZHEmkvEQC77IkI7Y\n" - "ED4Icu9CLCpXN7axV4Ga0iM53kX4MsDt419mmD8NoYJciHzBZHuJ6cD1tAsUUov7\n" - "NJZQLYfixIs63ZNEgb5gCkKywy40gZ+jaK3ard5LzyRUhgWHXdV7oZU7DkY5yAON\n" - "63gBg9THgEvcEhG/Ci60y6pB+YpXTiVGkuJvqLdSCn3qota8v+/Fm9ujrlJk1evR\n" - "fYFKjF0w1F5ftfpCbucSMbqt\n" - "-----END CERTIFICATE-----\n"; - -TEST(mbedTLS_x509_get_subject, old_format) { - MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); - std::string expect( - "/C=US/ST=CA/O=OpenVPN-TEST/CN=server-1.example.net/" - "emailAddress=example-server@example.net"); - - ASSERT_EQ(MbedTLSPKI::x509_get_subject(x509crt.get()), expect); - ASSERT_EQ(MbedTLSPKI::x509_get_subject(x509crt.get(), false), expect); -} - -TEST(mbesTLS_x509_get_subject, new_format) { - MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); - std::string expect( - "C=US, ST=CA, O=OpenVPN-TEST, CN=server-1.example.net, " - "emailAddress=example-server@example.net"); - - ASSERT_EQ(MbedTLSPKI::x509_get_subject(x509crt.get(), true), expect); -} - -TEST(mbedTLS_x509_get_common_name, basic_check) { - MbedTLSPKI::X509Cert x509crt(test_cert, "Embedded Test Server Cert", true); - - ASSERT_EQ(MbedTLSPKI::x509_get_common_name(x509crt.get()), - "server-1.example.net"); -} - -} // namespace unittests diff --git a/Sources/OpenVPN3/test/unittests/test_openssl_x509certinfo.cpp b/Sources/OpenVPN3/test/unittests/test_openssl_x509certinfo.cpp deleted file mode 100644 index f30aec7..0000000 --- a/Sources/OpenVPN3/test/unittests/test_openssl_x509certinfo.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// 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-2020 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 . -// -// -// Basic unit test for the openvpn/openssl/pki/x509certinfo.hpp functions -// - -#include - -#include "test_common.h" -#include "openvpn/openssl/pki/x509.hpp" -#include "openvpn/openssl/pki/x509certinfo.hpp" - -using namespace openvpn; - -namespace unittests { - -std::string test_cert = - "-----BEGIN CERTIFICATE-----\n" - "MIIFrjCCA5agAwIBAgIJFXABl4gwlJIEMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV\n" - "BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UEBwwKUGxlYXNhbnRvbjEYMBYGA1UE\n" - "CgwPT3BlblZQTi1URVNULUNBMSUwIwYJKoZIhvcNAQkBFhZleGFtcGxlLmNhQGV4\n" - "YW1wbGUubmV0MB4XDTE5MTAwMjEyMzY0OFoXDTI5MDkyOTEyMzY0OFowezELMAkG\n" - "A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQKDAxPcGVuVlBOLVRFU1QxHTAb\n" - "BgNVBAMMFHNlcnZlci0xLmV4YW1wbGUubmV0MSkwJwYJKoZIhvcNAQkBFhpleGFt\n" - "cGxlLXNlcnZlckBleGFtcGxlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" - "AQoCggEBAN7KKMU2A7X74KYn+agBvQmW2zr/OFH/PJn6sMk94aDAIWsa7KccuV8W\n" - "d/69XH2FXK2ygSd9df8kO8mGkDl1w5nC/LUk5V0KNqsZGLyNDRvulSFJ2eQChOOs\n" - "snOdpf17e/yzs08KY5RME9+HBWx2GpQQWHVsmqvPF+pPJnBctOm8azBOAUZRDBuj\n" - "TxCWtwLwVjnFHGSATETuvCiTPuDa9sbw5ibCLFz9ge94ptXcXEU6z+GuighQI9rU\n" - "o8BVFF6DiaWZn3jC5KsA1dX81c+UpDpxwOpG9MXg8RRm8rWwsvC/RvjVYjGDBdra\n" - "oSuHWPjzH1DIJ31ptjKUPAVdR8ZxAGcCAwEAAaOCAT4wggE6MAkGA1UdEwQCMAAw\n" - "EQYJYIZIAYb4QgEBBAQDAgZAMDQGCWCGSAGG+EIBDQQnFiVUZXN0IENlcnRpZmlj\n" - "YXRlIC0gTk9UIEZPUiBQUk9EVUNUSU9OMB0GA1UdDgQWBBRsQDoK1XxrwQdrKmcC\n" - "7/HfbSrQFTCBogYDVR0jBIGaMIGXgBTa10VpSdTIo1PhrwMuGmGrUMerq6F0pHIw\n" - "cDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRMwEQYDVQQHDApQbGVhc2FudG9u\n" - "MRgwFgYDVQQKDA9PcGVuVlBOLVRFU1QtQ0ExJTAjBgkqhkiG9w0BCQEWFmV4YW1w\n" - "bGUuY2FAZXhhbXBsZS5uZXSCCQDm/rJ9Tz3bEDATBgNVHSUEDDAKBggrBgEFBQcD\n" - "ATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAHl41WvFsh+nscCx+1X2\n" - "RudmnsuKHFUAktpAOdG3vh+5zh2v3PZYWoS4sgmBl0Zvia4VC/xTrcC2ywJILLAM\n" - "cda6CUXMF3+kJMi+qlgn6WRn9RsUHLQFa1/y7zNkuo38zkLlJaiKPQfm1YPkUtnr\n" - "n74W9XBrZ2rWBsqL2XCDayEs1IAjL9zs0F1Bs0MCgf+BccCu7wFL886+Y8mhAkRJ\n" - "c0aniG/bsawOrrF8JwW2MP/QpPls2BSWmfwJASxX57AbSQ8TmMf289ozTupcBVMC\n" - "N973ks9n/35cRtW9SHtwpdsb4nvXFZi6DCfyS3PBpHgi/mRuhgWWSLaVr40RnlHI\n" - "NvW0x7SPJwkbHeWz6PStrZJLjkJ9LuvRQwb2+wH6SjIxQiJ/AMXlSL2USASdLR32\n" - "eiPUWq5xalTrNQINcnEfVT/ruTInY2vytUaQgFTQvJKp0DJZZHEmkvEQC77IkI7Y\n" - "ED4Icu9CLCpXN7axV4Ga0iM53kX4MsDt419mmD8NoYJciHzBZHuJ6cD1tAsUUov7\n" - "NJZQLYfixIs63ZNEgb5gCkKywy40gZ+jaK3ard5LzyRUhgWHXdV7oZU7DkY5yAON\n" - "63gBg9THgEvcEhG/Ci60y6pB+YpXTiVGkuJvqLdSCn3qota8v+/Fm9ujrlJk1evR\n" - "fYFKjF0w1F5ftfpCbucSMbqt\n" - "-----END CERTIFICATE-----\n"; - -TEST(OpenSSL_X509_get_subject, old_format) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect( - "/C=US/ST=CA/O=OpenVPN-TEST/CN=server-1.example.net/" - "emailAddress=example-server@example.net"); - - ASSERT_EQ(OpenSSLPKI::x509_get_subject(x509crt.obj()), expect); - ASSERT_EQ(OpenSSLPKI::x509_get_subject(x509crt.obj(), false), expect); -} - -TEST(OpenSSL_X509_get_subject, new_format) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect( - "C=US, ST=CA, O=OpenVPN-TEST, CN=server-1.example.net, " - "emailAddress=example-server@example.net"); - - ASSERT_EQ(OpenSSLPKI::x509_get_subject(x509crt.obj(), true), expect); -} - -TEST(OpenSSL_X509_get_serial, numeric) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect("395452524166311612932"); - - ASSERT_EQ(OpenSSLPKI::x509_get_serial(x509crt.obj()), expect); -} - -TEST(OpenSSL_X509_get_serial, hexadecimal) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - std::string expect("15:70:01:97:88:30:94:92:04"); - - ASSERT_EQ(OpenSSLPKI::x509_get_serial_hex(x509crt.obj()), expect); -} - -TEST(OpenSSL_X509_get_field, basic_checks) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_commonName), - "server-1.example.net"); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_stateOrProvinceName), - "CA"); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_localityName), ""); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_pkcs9_emailAddress), - "example-server@example.net"); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_organizationName), - "OpenVPN-TEST"); - - ASSERT_EQ(OpenSSLPKI::x509_get_field(x509crt.obj(), NID_countryName), "US"); -} - -TEST(OpenSSL_X509_get_field, signature) { - OpenSSLPKI::X509 x509crt(test_cert, "Embedded Test Server Cert"); - - ASSERT_EQ(OpenSSLPKI::x509_get_signature_algorithm(x509crt.obj()), "RSA-SHA256"); - - } - - -} // namespace unittests diff --git a/Sources/OpenVPN3/test/unittests/test_route_emulation.cpp b/Sources/OpenVPN3/test/unittests/test_route_emulation.cpp deleted file mode 100644 index 74ab39a..0000000 --- a/Sources/OpenVPN3/test/unittests/test_route_emulation.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// 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-2020 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. - -/* Without doing this log dance core will not compile ... */ - -#include "test_common.h" - -#include - - -namespace unittests { -#define DEBUG_PRINT_ROUTES for(auto & rt: tb->routes) std::cout << rt << std::endl; - - /* Helper function for quick result comparision */ - std::string join_string_vector_sorted(std::vector vec, const char* const delim = ", ") - { - std::sort(vec.begin(), vec.end()); - std::ostringstream res; - std::copy(vec.begin(), vec.end(), std::ostream_iterator(res, delim)); - return res.str(); - } - - /* Simple class that just records */ - class TunBuilderMock : public openvpn::TunBuilderBase { - public: - bool is_ipv6; - TunBuilderMock(bool ipv6) - :is_ipv6(ipv6) - { - - } - - bool tun_builder_add_route(const std::string& address, - int prefix_length, - int metric, - bool ipv6) override - { - auto rt = address+"/"+std::to_string(prefix_length); - routes.push_back(rt); - routesAddr.push_back(openvpn::IP::Route(rt)); - return is_ipv6==ipv6; - } - - bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override - { - addresses.push_back(address); - return is_ipv6==ipv6; - } - - std::vector addresses; - std::vector routes; - std::vector routesAddr; - - bool containsIP(std::string ipaddr) - { - return containsIP(openvpn::IP::Addr(ipaddr)); - } - - bool containsIP(openvpn::IP::Addr ipaddr) - { - for (auto& rt: routesAddr) { - if (rt.contains(ipaddr)) - return true; - } - return false; - } - - }; - - class RouteEmulationTest : public testing::Test { - protected: - openvpn::IPVerFlags* ipflags; - openvpn::EmulateExcludeRoute::Ptr emu; - TunBuilderMock* tb; - openvpn::OptionList emptyOptionList; - - RouteEmulationTest() - : ipflags(nullptr), tb(nullptr) - { - - } - - void teardown() - { - delete tb; - delete ipflags; - } - - void setup(bool ipv6, bool excludeServer, bool keepEmu = false) - { - teardown(); - - tb = new TunBuilderMock(ipv6); - - ipflags = new openvpn::IPVerFlags(emptyOptionList, - ipv6 ? openvpn::IP::Addr::V6_MASK : openvpn::IP::Addr::V4_MASK); - - if (!keepEmu) - { - openvpn::EmulateExcludeRouteFactory::Ptr factory( - new openvpn::EmulateExcludeRouteFactoryImpl(excludeServer)); - - emu = factory->new_obj(); - } - } - - // Helper functions to make writing test suite a bit easier - void inclRoute(const std::string& incRoute) - { - addRoute(true, incRoute); - } - void exclRoute(const std::string& exclRoute) - { - addRoute(false, exclRoute); - } - - void addRoute(bool include, const std::string& route) - { - std::string ipstr = route.substr(0, route.find('/')); - std::string mask = route.substr(route.find('/')+1); - emu->add_route(include, openvpn::IP::Addr(ipstr), std::stoi(mask)); - } - - void doEmulate(std::string serverip = "1.2.3.4") - { - emu->emulate(this->tb, *this->ipflags, openvpn::IP::Addr(serverip)); - } - - ~RouteEmulationTest() - { - teardown(); - } - }; - - TEST_F(RouteEmulationTest, ExcludeOneSubnet) - { - setup(false, false); - - emu->add_default_routes(true, true); - - emu->add_route(false, openvpn::IP::Addr("192.168.100.0"), 24); - - doEmulate(); - - ASSERT_EQ (tb->routes.size(), 24); - - } - - TEST_F(RouteEmulationTest, ExcludeSubnetsNoDefault) - { - setup(false, false); - // include this net - emu->add_route(true, openvpn::IP::Addr("10.20.0.0"), 16); - - // but not the first half - emu->add_route(false, openvpn::IP::Addr("10.20.0.0"), 17); - - doEmulate(); - - ASSERT_EQ(tb->routes.size(), 1); - ASSERT_EQ(tb->routes.at(0), "10.20.128.0/17"); - - setup(true, false); - - emu->add_route(true, openvpn::IP::Addr("2500:1000::"), 32); - // but not the first half - emu->add_route(false, openvpn::IP::Addr("2500:1000:8000::"), 33); - - doEmulate(); - - ASSERT_EQ(tb->routes.size(), 1); - ASSERT_EQ(tb->routes.at(0), "2500:1000::/33"); - - } - - TEST_F(RouteEmulationTest, excludeServer) - { - setup(false, true); - emu->add_default_routes(true, true); - doEmulate("1.2.3.4"); - - ASSERT_EQ(tb->routes.size(), 32); - ASSERT_FALSE(tb->containsIP("1.2.3.4")); - ASSERT_TRUE(tb->containsIP("1.2.3.5")); - ASSERT_TRUE(tb->containsIP("1.2.3.3")); - ASSERT_TRUE(tb->containsIP("4.3.2.1")); - - setup(true, true); - emu->add_default_routes(true, true); - doEmulate("::1.2.3.4"); - - ASSERT_EQ(tb->routes.size(), 128); - ASSERT_FALSE(tb->containsIP("::1.2.3.4")); - ASSERT_TRUE(tb->containsIP("::1.2.3.5")); - ASSERT_TRUE(tb->containsIP("::1.2.3.3")); - ASSERT_TRUE(tb->containsIP("::4.3.2.1")); - } - - TEST_F(RouteEmulationTest, nestedIPRoutes) - { - // This sets up a number of routes that are all included in each - - setup(false, false); - inclRoute("192.64.0.0/16"); - // second quarter. - exclRoute("192.64.64.0/18"); - // last quarter - inclRoute("192.64.112.0/20"); - // first quarter - exclRoute("192.64.112.0/22"); - // first quarter again - inclRoute("192.64.112.0/24"); - // second quarter - exclRoute("192.64.112.64/26"); - - doEmulate(); - - // Excluded by 192.64.112.64/26 - ASSERT_FALSE(tb->containsIP("192.64.112.64")); - ASSERT_FALSE(tb->containsIP("192.64.112.87")); - - // Included by 192.64.112.0/24 - ASSERT_TRUE(tb->containsIP("192.64.112.5")); - ASSERT_TRUE(tb->containsIP("192.64.112.129")); - ASSERT_TRUE(tb->containsIP("192.64.112.255")); - - // Excluded by 192.64.112.0/22 - ASSERT_FALSE(tb->containsIP("192.64.113.91")); - ASSERT_FALSE(tb->containsIP("192.64.114.92")); - ASSERT_FALSE(tb->containsIP("192.64.115.93")); - - - // Included by 192.64.112.0/20 - ASSERT_TRUE(tb->containsIP("192.64.116.94")); - ASSERT_TRUE(tb->containsIP("192.64.123.95")); - - - // Excluded by 192.64.64.0/18" - ASSERT_FALSE(tb->containsIP("192.64.64.96")); - ASSERT_FALSE(tb->containsIP("192.64.97.98")); - ASSERT_FALSE(tb->containsIP("192.64.111.99")); - - // included in 192.64.0.0/16 - ASSERT_TRUE(tb->containsIP("192.64.0.0")); - ASSERT_TRUE(tb->containsIP("192.64.1.2")); - - // Not in the at all - ASSERT_FALSE(tb->containsIP("1.2.3.4")); - ASSERT_FALSE(tb->containsIP("192.63.255.255")); - ASSERT_FALSE(tb->containsIP("192.65.0.0")); - ASSERT_FALSE(tb->containsIP("128.0.0.0")); - ASSERT_FALSE(tb->containsIP("192.0.0.0")); - ASSERT_FALSE(tb->containsIP("255.255.255.255")); - } - - TEST_F(RouteEmulationTest, DefaultRoute) - { - setup(false, false); - - emu->add_default_routes(true, true); - - doEmulate(); - - ASSERT_EQ(tb->routes.size(), 1); - ASSERT_EQ(tb->routes.at(0), "0.0.0.0/0"); - - // Now something more tricky add unnecessary extra route - // to confuse our emulation layer - setup(false, false, true); - - inclRoute("192.168.0.0/24"); - - doEmulate(); - - ASSERT_EQ(tb->routes.size(), 2); - ASSERT_EQ(tb->routes.at(0), "0.0.0.0/0"); - } - -} \ No newline at end of file diff --git a/Sources/OpenVPN3/test/unittests/test_sitnl.cpp b/Sources/OpenVPN3/test/unittests/test_sitnl.cpp deleted file mode 100644 index 0fa80bf..0000000 --- a/Sources/OpenVPN3/test/unittests/test_sitnl.cpp +++ /dev/null @@ -1,326 +0,0 @@ -// 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-2020 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. - -#include -#include "test_common.h" - -#include "openvpn/common/argv.hpp" -#include "openvpn/common/process.hpp" -#include "openvpn/common/redir.hpp" -#include "openvpn/common/splitlines.hpp" - -#include "openvpn/tun/linux/client/sitnl.hpp" - -using namespace openvpn; -using namespace TunNetlink; - -namespace unittests -{ - static std::string path_to_ip; - - class SitnlTest : public testing::Test - { - private: - void add_device(std::string name) - { - RedirectPipe::InOut pipe; - Argv argv; - argv.emplace_back(path_to_ip); - argv.emplace_back("tuntap"); - argv.emplace_back("add"); - argv.emplace_back("mode"); - argv.emplace_back("tun"); - argv.emplace_back(std::move(name)); - system_cmd(argv[0], argv, nullptr, pipe, 0, nullptr); - } - - void remove_device(std::string name) - { - RedirectPipe::InOut pipe; - Argv argv; - argv.emplace_back(path_to_ip); - argv.emplace_back("tuntap"); - argv.emplace_back("delete"); - argv.emplace_back("mode"); - argv.emplace_back("tun"); - argv.emplace_back(std::move(name)); - system_cmd(argv[0], argv, nullptr, pipe, 0, nullptr); - } - - protected: - static void SetUpTestSuite() - { - // different distros have ip tool in different places - std::vector paths{"/bin/ip", "/sbin/ip", "/usr/bin/ip", "/usr/sbin/ip"}; - for (const auto& path : paths) - { - std::ifstream f(path); - if (f) - { - path_to_ip = path; - break; - } - } - ASSERT_FALSE(path_to_ip.empty()) << "unable to find ip tool"; - } - - void SetUp() override - { - if (geteuid() != 0) - GTEST_SKIP() << "Need root to run this test"; - - add_device(dev); - add_device(dev2); - } - - void TearDown() override - { - remove_device(dev); - remove_device(dev2); - } - - template - void cmd(Argv argv, CALLBACK cb) - { - // runs command, reads output and calls a callback - RedirectPipe::InOut pipe; - ASSERT_EQ(system_cmd(argv[0], argv, nullptr, pipe, 0, nullptr), 0) << "failed to run command " << argv[0]; - - SplitLines sl(pipe.out); - bool called = false; - while (sl()) { - const std::string &line = sl.line_ref(); - - std::vector v = Split::by_space, NullLex, SpaceMatch, Split::NullLimit>(line); - - // blank line? - if (v.empty()) - continue; - - cb(v, pipe.out, called); - } - - ASSERT_TRUE(called) << pipe.out; - } - - template - void ip_a_show_dev(CALLBACK cb) - { - // get addrs with "ip a show dev" - RedirectPipe::InOut pipe; - Argv argv; - argv.emplace_back(path_to_ip); - argv.emplace_back("a"); - argv.emplace_back("show"); - argv.emplace_back("dev"); - argv.emplace_back(dev); - cmd(argv, cb); - } - - template - void ip_route_get(std::string dst, CALLBACK cb) - { - // get route with "ip route get" - RedirectPipe::InOut pipe; - Argv argv; - argv.emplace_back(path_to_ip); - argv.emplace_back("route"); - argv.emplace_back("get"); - argv.emplace_back(std::move(dst)); - cmd(argv, cb); - } - - std::string dev = "tun999"; - std::string dev2 = "tun9999"; - - std::string addr4 = "10.10.0.2"; - std::string route4 = "10.110.0.0/24"; - std::string gw4 = "10.10.0.1"; - - std::string addr6 = "fe80:20c3:aaaa:bbbb::cccc"; - std::string route6 = "fe80:20c3:cccc:dddd::0/64"; - std::string gw6 = "fe80:20c3:aaaa:bbbb:cccc:dddd:eeee:1"; - - int ipv4_prefix_len = 16; - int ipv6_prefix_len = 64; - int mtu = 1234; - }; - - TEST_F(SitnlTest, TestAddrAdd4) - { - auto broadcast = IPv4::Addr::from_string(addr4) | ~IPv4::Addr::netmask_from_prefix_len(ipv4_prefix_len); - ASSERT_EQ(SITNL::net_addr_add(dev, IPv4::Addr::from_string(addr4), ipv4_prefix_len, broadcast), 0); - - ip_a_show_dev([this, &broadcast](std::vector& v, const std::string& out, bool& called) { - if (v[0] == "inet") - { - called = true; - ASSERT_EQ(v[1], addr4 + "/" + std::to_string(ipv4_prefix_len)) << out; - ASSERT_EQ(v[3], broadcast.to_string()) << out; - } - }); - } - - TEST_F(SitnlTest, TestAddrAdd6) - { - ASSERT_EQ(SITNL::net_addr_add(dev, IPv6::Addr::from_string(addr6), ipv6_prefix_len), 0); - - ip_a_show_dev([this](std::vector& v, const std::string& out, bool& called) { - if (v[0] == "inet6") - { - called = true; - ASSERT_EQ(v[1], addr6 + "/" + std::to_string(ipv6_prefix_len)) << out; - } - }); - } - - TEST_F(SitnlTest, TestSetMTU) - { - ASSERT_EQ(SITNL::net_iface_mtu_set(dev, mtu), 0); - - ip_a_show_dev([this](std::vector& v, const std::string& out, bool& called) { - if (dev + ":" == v[1]) - { - called = true; - ASSERT_EQ(v[4], std::to_string(mtu)) << out; - } - }); - } - - TEST_F(SitnlTest, TestAddRoute4) - { - // add address - auto broadcast = IPv4::Addr::from_string(addr4) | ~IPv4::Addr::netmask_from_prefix_len(ipv4_prefix_len); - ASSERT_EQ(SITNL::net_addr_add(dev, IPv4::Addr::from_string(addr4), ipv4_prefix_len, broadcast), 0); - - // up interface - ASSERT_EQ(SITNL::net_iface_up(dev, true), 0); - - // add route - ASSERT_EQ(SITNL::net_route_add(IP::Route4(route4), IPv4::Addr::from_string(gw4), dev, 0, 0), 0); - - std::string dst{"10.110.0.100"}; - - ip_route_get(dst, [this, &dst](std::vector& v, const std::string& out, bool& called) { - if (v[0] == dst) - { - called = true; - v.resize(7); - auto expected = std::vector{dst, "via", gw4, "dev", dev, "src", addr4}; - ASSERT_EQ(v, expected) << out; - } - }); - } - - TEST_F(SitnlTest, TestAddRoute6) - { - // add address - ASSERT_EQ(SITNL::net_addr_add(dev, IPv6::Addr::from_string(addr6), ipv6_prefix_len), 0); - - // up interface - ASSERT_EQ(SITNL::net_iface_up(dev, true), 0); - - // add route - ASSERT_EQ(SITNL::net_route_add(IP::Route6(route6), IPv6::Addr::from_string(gw6), dev, 0, 0), 0); - - std::string dst{"fe80:20c3:cccc:dddd:cccc:dddd:eeee:ffff"}; - - ip_route_get(dst, [this, &dst](std::vector &v1, const std::string &out, bool &called) { - if (v1[0] == dst) - { - called = true; - v1.resize(7); - // iptools 4.15 (Ubuntu 18) - auto expected1 = std::vector{dst, "from", "::", "via", gw6, "dev", dev}; - auto ok1 = (v1 == expected1); - - auto v2 = v1; - v2.resize(5); - // iptools 4.11 (CentOS 7) - auto expected2 = std::vector{dst, "via", gw6, "dev", dev}; - auto ok2 = (v2 == expected2); - - if (!ok1 && !ok2) - { - // this is just a way to print actual value and all expected values - EXPECT_EQ(v1, expected1); - EXPECT_EQ(v2, expected2); - } - } - }); - } - - TEST_F(SitnlTest, TestBestGw4) - { - // add address - auto broadcast = IPv4::Addr::from_string(addr4) | ~IPv4::Addr::netmask_from_prefix_len(ipv4_prefix_len); - ASSERT_EQ(SITNL::net_addr_add(dev, IPv4::Addr::from_string(addr4), ipv4_prefix_len, broadcast), 0); - - // up interface - ASSERT_EQ(SITNL::net_iface_up(dev, true), 0); - - // add routes - - // shortest prefix - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.0.0.0/8"), IPv4::Addr::from_string("10.10.10.10"), dev, 0, 0), 0); - // longest prefix, lowest metric - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.10.10.0/24"), IPv4::Addr::from_string("10.10.10.13"), dev, 0, 0), 0); - // short prefix - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.10.0.0/16"), IPv4::Addr::from_string("10.10.10.11"), dev, 0, 0), 0); - // longest prefix, highest metric - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.10.10.0/24"), IPv4::Addr::from_string("10.10.10.12"), dev, 0, 10), 0); - - IPv4::Addr best_gw; - std::string best_iface; - ASSERT_EQ(SITNL::net_route_best_gw(IP::Route4("10.10.10.1/32"), best_gw, best_iface), 0); - - // we should get a gateway with longest prefix and lowest metric - - ASSERT_EQ(best_gw.to_string(), "10.10.10.13"); - ASSERT_EQ(best_iface, dev); - } - - TEST_F(SitnlTest, TestBestGw4FilterIface) - { - // add addresses - auto broadcast = IPv4::Addr::from_string(addr4) | ~IPv4::Addr::netmask_from_prefix_len(ipv4_prefix_len); - ASSERT_EQ(SITNL::net_addr_add(dev, IPv4::Addr::from_string(addr4), ipv4_prefix_len, broadcast), 0); - - broadcast = IPv4::Addr::from_string("10.20.0.2") | ~IPv4::Addr::netmask_from_prefix_len(ipv4_prefix_len); - ASSERT_EQ(SITNL::net_addr_add(dev2, IPv4::Addr::from_string("10.20.0.2"), ipv4_prefix_len, broadcast), 0); - - // up interfaces - SITNL::net_iface_up(dev, true); - SITNL::net_iface_up(dev2, true); - - // add routes - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.11.0.0/16"), IPv4::Addr::from_string("10.10.0.1"), dev, 0, 0), 0); - ASSERT_EQ(SITNL::net_route_add(IP::Route4("10.11.12.0/24"), IPv4::Addr::from_string("10.20.0.1"), dev2, 0, 0), 0); - - IPv4::Addr best_gw; - std::string best_iface; - - // filter out gateway with longest prefix route - SITNL::net_route_best_gw(IP::Route4("10.11.12.13/32"), best_gw, best_iface, dev2); - - ASSERT_EQ(best_gw.to_string(), "10.10.0.1"); - ASSERT_EQ(best_iface, dev); - } -} diff --git a/Sources/OpenVPN3/test/unittests/test_ssl.cpp b/Sources/OpenVPN3/test/unittests/test_ssl.cpp deleted file mode 100644 index 0df4efa..0000000 --- a/Sources/OpenVPN3/test/unittests/test_ssl.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -#include "test_common.h" - - -using namespace openvpn; - -#include -#include - -TEST(ssl, sslciphersuites) -{ - SSLFactoryAPI::Ptr sslfact; - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); - sslcfg->set_local_cert_enabled(false); - sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); - - sslcfg->set_tls_ciphersuite_list("TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_CCM_SHA256"); - - sslfact = sslcfg->new_factory(); - - - sslcfg->set_tls_ciphersuite_list("TLS_CHACHA2000"); -#if defined(USE_MBEDTLS) || OPENSSL_VERSION_NUMBER < 0x10100000L - /* Ignored on non TLS 1.3 implementations */ - sslfact = sslcfg->new_factory(); -#else - /* This is invalid and should throw an exception */ - EXPECT_THROW(sslcfg->new_factory(), SSLFactoryAPI::ssl_context_error); -#endif -} - -TEST(ssl, sslciphers) -{ - RandomAPI::Ptr rng(new FakeSecureRand); - - bool previousLogOutput = testLog->isStdoutEnabled(); - testLog->setPrintOutput(false); - SSLFactoryAPI::Ptr sslfact; - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); - sslcfg->set_local_cert_enabled(false); - sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); - sslcfg->set_rng(rng); - - /* This list mixes IANA and OpenSSL ciphers to see if ciphers are translated for mbed TLS and for OpenSSL */ - sslcfg->set_tls_cipher_list("TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:AES256-SHA"); - - sslfact = sslcfg->new_factory(); - sslfact->ssl(); - - testLog->setPrintOutput(previousLogOutput); -} - -TEST(ssl, tls_groups) -{ - RandomAPI::Ptr rng(new FakeSecureRand); - - SSLFactoryAPI::Ptr sslfact; - - SSLLib::SSLAPI::Config::Ptr sslcfg(new SSLLib::SSLAPI::Config); - sslcfg->set_local_cert_enabled(false); - sslcfg->set_flags(SSLConst::NO_VERIFY_PEER); - sslcfg->set_rng(rng); - - sslcfg->set_tls_groups("secp521r1:secp384r1"); - - /* Should not throw an error */ - auto f = sslcfg->new_factory(); - f->ssl(); - - sslcfg->set_tls_groups("secp521r1:secp384r1:greenhell"); - - - testLog->startCollecting(); - f = sslcfg->new_factory(); - f->ssl(); -#ifdef USE_OPENSSL - EXPECT_EQ("OpenSSL -- warning ignoring unknown group 'greenhell' in tls-groups\n",testLog->stopCollecting()); -#else - EXPECT_EQ("mbed TLS -- warning ignoring unknown group 'greenhell' in tls-groups\n", testLog->stopCollecting()); -#endif - -} - -#if defined(USE_OPENSSL) -TEST(ssl, translate_ciphers_openssl) -{ - bool previousLogOutput = testLog->isStdoutEnabled(); - testLog->setPrintOutput(false); - EXPECT_EQ("ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:AES256-SHA", - OpenSSLContext::translate_cipher_list("TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:AES256-SHA")); - EXPECT_EQ("DEFAULT", OpenSSLContext::translate_cipher_list("DEFAULT")); - EXPECT_EQ("NONSENSE:AES256-SHA", OpenSSLContext::translate_cipher_list("NONSENSE:AES256-SHA")); - - testLog->setPrintOutput(previousLogOutput); -} -#endif diff --git a/Sources/OpenVPN3/test/unittests/test_verify_x509_name.cpp b/Sources/OpenVPN3/test/unittests/test_verify_x509_name.cpp deleted file mode 100644 index 0470b68..0000000 --- a/Sources/OpenVPN3/test/unittests/test_verify_x509_name.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// 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-2020 OpenVPN Inc. -// Copyright (C) 2019-2020 David Sommerseth -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License Version 3 -// as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program in the COPYING file. -// If not, see . -// - -#include -#include "test_common.h" -#include "openvpn/client/cliconstants.hpp" -#include "openvpn/common/options.hpp" -#include "openvpn/ssl/verify_x509_name.hpp" - -using namespace openvpn; - -namespace unittests { - -OptionList parse_testcfg(std::string& config) { - OptionList::Limits limits( - "profile is too large", ProfileParseLimits::MAX_PROFILE_SIZE, - ProfileParseLimits::OPT_OVERHEAD, ProfileParseLimits::TERM_OVERHEAD, - ProfileParseLimits::MAX_LINE_SIZE, - ProfileParseLimits::MAX_DIRECTIVE_SIZE); - OptionList opts; - opts.parse_from_config(config, &limits); - opts.update_map(); - return opts; -} - -TEST(VerifyX509Name, config_missing_args) { - // Missing both needed arguments - std::string config = "verify-x509-name"; - EXPECT_THROW(VerifyX509Name err_no_args(parse_testcfg(config)), option_error); -} - -TEST(VerifyX509Name, config_incorrect_type) { - // Incorrect type - std::string config = "verify-x509-name localhost nonsense-arg"; - EXPECT_THROW(VerifyX509Name err_wrong_type(parse_testcfg(config)), - option_error); -} - -TEST(VerifyX509Name, config_correct_default_type) { - // Missing type argument - defaults to complete subject DN - std::string config = - "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain\""; - VerifyX509Name ok_default_subj(parse_testcfg(config)); -} - -TEST(VerifyX509Name, config_correct_subject) { - // Correct - type: subject - std::string config = - "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain\" subject"; - VerifyX509Name ok_subj(parse_testcfg(config)); -} - -TEST(VerifyX509Name, config_correct_name) { - // Correct - type: name - std::string config = "verify-x509-name localhost name"; - VerifyX509Name ok_name(parse_testcfg(config)); -} - -TEST(VerifyX509Name, config_correct_name_prefix) { - // Correct - type: name-prefix - std::string config = "verify-x509-name Server- name-prefix"; - VerifyX509Name ok_name_prefix(parse_testcfg(config)); -} - -TEST(VerifyX509Name, test_subject) { - std::string config = - "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain\""; - VerifyX509Name verify_def(parse_testcfg(config)); - - ASSERT_TRUE(verify_def.verify( - "C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain")); - ASSERT_FALSE(verify_def.verify( - "C=KG, ST=NA, O=OpenVPN-TEST-FAIL, CN=Wrong-Server, " - "emailAddress=me@myhost.mydomain")); - ASSERT_FALSE(verify_def.verify("server-1.example.org")); - - // This is basically the same config as the one above, - // just with the 'subject' type defined explicitly - config = - "verify-x509-name \"C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain\" subject"; - VerifyX509Name verify_subj(parse_testcfg(config)); - - ASSERT_TRUE(verify_subj.verify( - "C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server, " - "emailAddress=me@myhost.mydomain")); - ASSERT_FALSE(verify_subj.verify( - "C=KG, ST=NA, O=OpenVPN-TEST-FAIL, CN=Wrong-Server, " - "emailAddress=me@myhost.mydomain")); - ASSERT_FALSE(verify_subj.verify("server-1.example.org")); -} - -TEST(VerifyX509Name, test_name) { - std::string config = "verify-x509-name server-1.example.org name"; - VerifyX509Name verify(parse_testcfg(config)); - - ASSERT_TRUE(verify.verify("server-1.example.org")); - ASSERT_FALSE(verify.verify("server-2.example.org")); - ASSERT_FALSE(verify.verify("server")); -} - -TEST(VerifyX509Name, test_name_prefix) { - std::string config = "verify-x509-name server name-prefix"; - VerifyX509Name verify(parse_testcfg(config)); - - ASSERT_TRUE(verify.verify("server-1.example.org")); - ASSERT_TRUE(verify.verify("server-2.sub.example.net")); - ASSERT_TRUE(verify.verify("server")); - ASSERT_FALSE(verify.verify("some-other.example.org")); -} - -} // namespace unittests diff --git a/Sources/OpenVPN3/test/unused b/Sources/OpenVPN3/test/unused deleted file mode 100644 index 8cbbbd0..0000000 --- a/Sources/OpenVPN3/test/unused +++ /dev/null @@ -1,402 +0,0 @@ -// 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-2020 OpenVPN 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 . - -// These classes define function objects to be used as asynchronous callbacks -// for Asio methods. Think of these as optimized special cases of function -// objects that could be more generally (but perhaps less optimally) defined -// with lambdas. - -#ifndef OPENVPN_COMMON_ASIODISPATCH_H -#define OPENVPN_COMMON_ASIODISPATCH_H - -#include - -#include -#include - -namespace openvpn { - // Dispatcher for asio async_write - - template - class AsioDispatchWrite - { - public: - AsioDispatchWrite(Handler handle_write, C* obj) - : handle_write_(handle_write), obj_(obj) {} - - void operator()(const asio::error_code& error, const size_t bytes_sent) - { - (obj_.get()->*handle_write_)(error, bytes_sent); - } - - private: - Handler handle_write_; - RCPtr obj_; - }; - - template - AsioDispatchWrite asio_dispatch_write(Handler handle_write, C* obj) - { - return AsioDispatchWrite(handle_write, obj); - } - - // Dispatcher for asio async_read with argument - - template - class AsioDispatchRead - { - public: - AsioDispatchRead(Handler handle_read, C* obj, Data data) - : handle_read_(handle_read), obj_(obj), data_(data) {} - - void operator()(const asio::error_code& error, const size_t bytes_recvd) - { - (obj_.get()->*handle_read_)(data_, error, bytes_recvd); - } - - private: - Handler handle_read_; - RCPtr obj_; - Data data_; - }; - - template - AsioDispatchRead asio_dispatch_read(Handler handle_read, C* obj, Data data) - { - return AsioDispatchRead(handle_read, obj, data); - } - - // Dispatcher for asio async_read without argument - - template - class AsioDispatchReadNoArg - { - public: - AsioDispatchReadNoArg(Handler handle_read, C* obj) - : handle_read_(handle_read), obj_(obj) {} - - void operator()(const asio::error_code& error, const size_t bytes_recvd) - { - (obj_.get()->*handle_read_)(error, bytes_recvd); - } - - private: - Handler handle_read_; - RCPtr obj_; - }; - - template - AsioDispatchReadNoArg asio_dispatch_read_noarg(Handler handle_read, C* obj) - { - return AsioDispatchReadNoArg(handle_read, obj); - } - - // Dispatcher for asio async_wait with argument - - template - class AsioDispatchTimerArg - { - public: - AsioDispatchTimerArg(Handler handler, C* obj, Data data) - : handler_(handler), obj_(obj), data_(data) {} - - void operator()(const asio::error_code& error) - { - (obj_.get()->*handler_)(data_, error); - } - - private: - Handler handler_; - RCPtr obj_; - Data data_; - }; - - template - AsioDispatchTimerArg asio_dispatch_timer_arg(Handler handler, C* obj, Data data) - { - return AsioDispatchTimerArg(handler, obj, data); - } - - // Dispatcher for asio async_wait without argument - - template - class AsioDispatchTimer - { - public: - AsioDispatchTimer(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(const asio::error_code& error) - { - (obj_.get()->*handler_)(error); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - template - AsioDispatchTimer asio_dispatch_timer(Handler handler, C* obj) - { - return AsioDispatchTimer(handler, obj); - } - - // Dispatcher for asio async_connect with argument - - template - class AsioDispatchConnectArg - { - public: - AsioDispatchConnectArg(Handler handler, C* obj, Data data) - : handler_(handler), obj_(obj), data_(data) {} - - void operator()(const asio::error_code& error) - { - (obj_.get()->*handler_)(data_, error); - } - - private: - Handler handler_; - RCPtr obj_; - Data data_; - }; - - template - AsioDispatchConnectArg asio_dispatch_connect_arg(Handler handler, C* obj, Data data) - { - return AsioDispatchConnectArg(handler, obj, data); - } - - // Dispatcher for asio async_connect without argument - - template - class AsioDispatchConnect - { - public: - AsioDispatchConnect(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(const asio::error_code& error) - { - (obj_.get()->*handler_)(error); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - template - AsioDispatchConnect asio_dispatch_connect(Handler handler, C* obj) - { - return AsioDispatchConnect(handler, obj); - } - - // Dispatcher for asio async_connect (ComposedConnectHandler) without argument - - template - class AsioDispatchComposedConnect - { - public: - AsioDispatchComposedConnect(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(const asio::error_code& error, asio::ip::tcp::resolver::iterator endpoint_iterator) - { - (obj_.get()->*handler_)(error, endpoint_iterator); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - template - AsioDispatchComposedConnect asio_dispatch_composed_connect(Handler handler, C* obj) - { - return AsioDispatchComposedConnect(handler, obj); - } - - // Dispatcher for asio async_accept with argument - - template - class AsioDispatchAcceptArg - { - public: - AsioDispatchAcceptArg(Handler handler, C* obj, Data data) - : handler_(handler), obj_(obj), data_(data) {} - - void operator()(const asio::error_code& error) - { - (obj_.get()->*handler_)(data_, error); - } - - private: - Handler handler_; - RCPtr obj_; - Data data_; - }; - - template - AsioDispatchAcceptArg asio_dispatch_accept_arg(Handler handler, C* obj, Data data) - { - return AsioDispatchAcceptArg(handler, obj, data); - } - - // Dispatcher for asio post with argument - - template - class AsioDispatchPostArg - { - public: - AsioDispatchPostArg(Handler handler, C* obj, Data data) - : handler_(handler), obj_(obj), data_(data) {} - - void operator()() - { - (obj_.get()->*handler_)(data_); - } - - private: - Handler handler_; - RCPtr obj_; - Data data_; - }; - - template - AsioDispatchPostArg asio_dispatch_post_arg(Handler handler, C* obj, Data data) - { - return AsioDispatchPostArg(handler, obj, data); - } - - // Dispatcher for asio post without argument - - template - class AsioDispatchPost - { - public: - AsioDispatchPost(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()() - { - (obj_.get()->*handler_)(); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - template - AsioDispatchPost asio_dispatch_post(Handler handler, C* obj) - { - return AsioDispatchPost(handler, obj); - } - - // Dispatcher for asynchronous resolver without argument - - template - class AsioDispatchResolve - { - public: - AsioDispatchResolve(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(const asio::error_code& error, EndpointIterator iter) - { - (obj_.get()->*handler_)(error, iter); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - // Dispatcher for asynchronous resolver with argument - - template - class AsioDispatchResolveArg - { - public: - AsioDispatchResolveArg(Handler handler, C* obj, Data data) - : handler_(handler), obj_(obj), data_(data) {} - - void operator()(const asio::error_code& error, EndpointIterator iter) - { - (obj_.get()->*handler_)(error, iter, data_); - } - - private: - Handler handler_; - RCPtr obj_; - Data data_; - }; - - - // Dispatcher for asio signal - - template - class AsioDispatchSignal - { - public: - AsioDispatchSignal(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(const asio::error_code& error, int signal_number) - { - (obj_.get()->*handler_)(error, signal_number); - } - - private: - Handler handler_; - RCPtr obj_; - }; - - template - AsioDispatchSignal asio_dispatch_signal(Handler handler, C* obj) - { - return AsioDispatchSignal(handler, obj); - } - - // General purpose dispatcher with data - - template - class SimpleDispatch - { - public: - SimpleDispatch(Handler handler, C* obj) - : handler_(handler), obj_(obj) {} - - void operator()(Data data) - { - (obj_->*handler_)(data); - } - - private: - Handler handler_; - C* obj_; - }; - -} // namespace openvpn - -#endif // OPENVPN_COMMON_ASIODISPATCH_H diff --git a/Sources/OpenVPN3/vars/o3 b/Sources/OpenVPN3/vars/o3 deleted file mode 100644 index 54c9fb6..0000000 --- a/Sources/OpenVPN3/vars/o3 +++ /dev/null @@ -1 +0,0 @@ -export O3="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" diff --git a/Sources/OpenVPN3/vars/setlibpath b/Sources/OpenVPN3/vars/setlibpath deleted file mode 100644 index e8245c0..0000000 --- a/Sources/OpenVPN3/vars/setlibpath +++ /dev/null @@ -1 +0,0 @@ -export LD_LIBRARY_PATH=".:$DEP_DIR/so" diff --git a/Sources/OpenVPN3/vars/setpath b/Sources/OpenVPN3/vars/setpath deleted file mode 100644 index a5292f7..0000000 --- a/Sources/OpenVPN3/vars/setpath +++ /dev/null @@ -1 +0,0 @@ -export PATH="$O3/core/scripts:$PATH" diff --git a/Sources/OpenVPN3/vars/vars-android-a7a b/Sources/OpenVPN3/vars/vars-android-a7a deleted file mode 100644 index ac72bf1..0000000 --- a/Sources/OpenVPN3/vars/vars-android-a7a +++ /dev/null @@ -1,15 +0,0 @@ -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android -export PLATFORM=android-a7a -export ABI=armeabi-v7a -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="-D__LP32__ -march=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot" -export GPP_CMD="$TC/bin/arm-linux-androideabi-g++" -export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc" - -[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH" -export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH" diff --git a/Sources/OpenVPN3/vars/vars-android-a7a-dbg b/Sources/OpenVPN3/vars/vars-android-a7a-dbg deleted file mode 100644 index 2efa1af..0000000 --- a/Sources/OpenVPN3/vars/vars-android-a7a-dbg +++ /dev/null @@ -1,15 +0,0 @@ -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android -export PLATFORM=android-a7a-dbg -export ABI=armeabi-v7a -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=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot" -export GPP_CMD="$TC/bin/arm-linux-androideabi-g++" -export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc" - -[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH" -export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH" diff --git a/Sources/OpenVPN3/vars/vars-android-a8a b/Sources/OpenVPN3/vars/vars-android-a8a deleted file mode 100644 index 0f29a51..0000000 --- a/Sources/OpenVPN3/vars/vars-android-a8a +++ /dev/null @@ -1,15 +0,0 @@ -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android -export PLATFORM=android-a8a -export ABI=arm64-v8a -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-arm64 -export PLATFORM_FLAGS="-march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot" -export GPP_CMD="$TC/bin/aarch64-linux-android-g++" -export GCC_CMD="$TC/bin/aarch64-linux-android-gcc" - -[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH" -export PATH="$TC/bin:$TC/aarch64-linux-android/bin:$VARS_SAVE_PATH" diff --git a/Sources/OpenVPN3/vars/vars-android-a8a-dbg b/Sources/OpenVPN3/vars/vars-android-a8a-dbg deleted file mode 100644 index 2634a21..0000000 --- a/Sources/OpenVPN3/vars/vars-android-a8a-dbg +++ /dev/null @@ -1,15 +0,0 @@ -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android -export PLATFORM=android-a8a-dbg -export ABI=arm64-v8a -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-arm64 -export PLATFORM_FLAGS="-march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot" -export GPP_CMD="$TC/bin/aarch64-linux-android-g++" -export GCC_CMD="$TC/bin/aarch64-linux-android-gcc" - -[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH" -export PATH="$TC/bin:$TC/aarch64-linux-android/bin:$VARS_SAVE_PATH" diff --git a/Sources/OpenVPN3/vars/vars-android-srconly b/Sources/OpenVPN3/vars/vars-android-srconly deleted file mode 100644 index 67bb063..0000000 --- a/Sources/OpenVPN3/vars/vars-android-srconly +++ /dev/null @@ -1 +0,0 @@ -# Nothing in here diff --git a/Sources/OpenVPN3/vars/vars-android-x86 b/Sources/OpenVPN3/vars/vars-android-x86 deleted file mode 100644 index 6f6c74f..0000000 --- a/Sources/OpenVPN3/vars/vars-android-x86 +++ /dev/null @@ -1,15 +0,0 @@ -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android -export PLATFORM=android-x86 -export ABI=x86 -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-x86 -export PLATFORM_FLAGS="-D__LP32__ -march=i686 -fomit-frame-pointer --sysroot=$TC/sysroot" -export GPP_CMD="$TC/bin/i686-linux-android-g++" -export GCC_CMD="$TC/bin/i686-linux-android-gcc" - -[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH" -export PATH="$TC/bin:$TC/i686-linux-android/bin:$VARS_SAVE_PATH" diff --git a/Sources/OpenVPN3/vars/vars-arm-cross b/Sources/OpenVPN3/vars/vars-arm-cross deleted file mode 100644 index d10fe28..0000000 --- a/Sources/OpenVPN3/vars/vars-arm-cross +++ /dev/null @@ -1,5 +0,0 @@ -export PLATFORM=linux-arm -export GPP_CMD=arm-linux-gnueabi-g++-4.6 -export STRIP_CMD=arm-linux-gnueabi-strip -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" diff --git a/Sources/OpenVPN3/vars/vars-ios b/Sources/OpenVPN3/vars/vars-ios deleted file mode 100644 index 9769df0..0000000 --- a/Sources/OpenVPN3/vars/vars-ios +++ /dev/null @@ -1,10 +0,0 @@ -export PLATFORM=ios -export APPLE_FAMILY=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export IOS_SDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk" -export PLATFORM_FLAGS="-arch armv7 -arch armv7s -arch arm64 -mthumb -miphoneos-version-min=9.0 -isysroot $IOS_SDK" -export OTHER_COMPILER_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-ios-dbg b/Sources/OpenVPN3/vars/vars-ios-dbg deleted file mode 100644 index 08f1f8a..0000000 --- a/Sources/OpenVPN3/vars/vars-ios-dbg +++ /dev/null @@ -1,11 +0,0 @@ -export PLATFORM=ios-dbg -export APPLE_FAMILY=1 -export DEBUG_BUILD=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export IOS_SDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk" -export PLATFORM_FLAGS="-arch armv7 -arch armv7s -arch arm64 -mthumb -miphoneos-version-min=9.0 -isysroot $IOS_SDK" -export OTHER_COMPILER_FLAGS="-g" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-iossim b/Sources/OpenVPN3/vars/vars-iossim deleted file mode 100644 index 8a68b36..0000000 --- a/Sources/OpenVPN3/vars/vars-iossim +++ /dev/null @@ -1,10 +0,0 @@ -export PLATFORM=iossim -export APPLE_FAMILY=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export IOS_SDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk" -export PLATFORM_FLAGS="-arch i386 -arch x86_64 -miphoneos-version-min=5.1.1 -isysroot $IOS_SDK" -export OTHER_COMPILER_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-iossim-dbg b/Sources/OpenVPN3/vars/vars-iossim-dbg deleted file mode 100644 index 9d90848..0000000 --- a/Sources/OpenVPN3/vars/vars-iossim-dbg +++ /dev/null @@ -1,11 +0,0 @@ -export PLATFORM=iossim-dbg -export DEBUG_BUILD=1 -export APPLE_FAMILY=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export IOS_SDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk" -export PLATFORM_FLAGS="-arch i386 -arch x86_64 -miphoneos-version-min=5.1.1 -isysroot $IOS_SDK" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export OTHER_COMPILER_FLAGS="-g" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-linux b/Sources/OpenVPN3/vars/vars-linux deleted file mode 100644 index b043991..0000000 --- a/Sources/OpenVPN3/vars/vars-linux +++ /dev/null @@ -1,18 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=0 -LTO_FLAGS="-flto=4 -Wl,--no-as-needed" # add to OTHER_COMPILER_FLAGS for LTO -export OTHER_COMPILER_FLAGS="$LTO_FLAGS -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -# Workaround for CentOS7/RHEL7 g++ -if g++ --version |grep 4.8.5 > /dev/null ; then - export CXX_COMPILER_FLAGS="-std=c++1y" -else - export CXX_COMPILER_FLAGS="-std=c++14" -fi -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" -export GPP_CMD=g++ -export GCC_CMD=gcc -export AR_CMD=gcc-ar -export RANLIB_CMD=gcc-ranlib diff --git a/Sources/OpenVPN3/vars/vars-linux-dbg b/Sources/OpenVPN3/vars/vars-linux-dbg deleted file mode 100644 index 33006b2..0000000 --- a/Sources/OpenVPN3/vars/vars-linux-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=1 -export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++14" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="-fPIC" -export GPP_CMD=g++ -export GCC_CMD=gcc -export AR_CMD=gcc-ar -export RANLIB_CMD=gcc-ranlib diff --git a/Sources/OpenVPN3/vars/vars-linux-libcpp b/Sources/OpenVPN3/vars/vars-linux-libcpp deleted file mode 100644 index e928d6d..0000000 --- a/Sources/OpenVPN3/vars/vars-linux-libcpp +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=0 -export OTHER_COMPILER_FLAGS="$LTO_FLAGS -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++14 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD=gcc-ar -export RANLIB_CMD=gcc-ranlib diff --git a/Sources/OpenVPN3/vars/vars-linux-libcpp-dbg b/Sources/OpenVPN3/vars/vars-linux-libcpp-dbg deleted file mode 100644 index 8050e38..0000000 --- a/Sources/OpenVPN3/vars/vars-linux-libcpp-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export JAVA_DIR=/usr/lib/jvm/java-7-openjdk-amd64 -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/linux -export PLATFORM=linux -export DEBUG_BUILD=1 -export OTHER_COMPILER_FLAGS="-ggdb -Wno-unused-local-typedefs -Wno-unused-variable -Wno-shift-count-overflow -pthread" -export CXX_COMPILER_FLAGS="-std=c++14 -stdlib=libc++" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="-fPIC" -export GPP_CMD=clang++ -export GCC_CMD=clang -export AR_CMD=gcc-ar -export RANLIB_CMD=gcc-ranlib diff --git a/Sources/OpenVPN3/vars/vars-osx b/Sources/OpenVPN3/vars/vars-osx deleted file mode 100644 index 5da17a8..0000000 --- a/Sources/OpenVPN3/vars/vars-osx +++ /dev/null @@ -1,12 +0,0 @@ -export PLATFORM=osx -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/mac -export APPLE_FAMILY=1 -export DEBUG_BUILD=0 -export GPP_CMD=clang++ -export GCC_CMD=clang -export MIN_DEPLOY_TARGET="-mmacosx-version-min=10.12" -export PLATFORM_FLAGS="-arch x86_64 -arch i386 $MIN_DEPLOY_TARGET" -export OTHER_COMPILER_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-osx-dbg b/Sources/OpenVPN3/vars/vars-osx-dbg deleted file mode 100644 index 34f5f5d..0000000 --- a/Sources/OpenVPN3/vars/vars-osx-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export PLATFORM=osx-dbg -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/mac -export APPLE_FAMILY=1 -export DEBUG_BUILD=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export MIN_DEPLOY_TARGET="-mmacosx-version-min=10.8" -export PLATFORM_FLAGS="-arch x86_64 -arch i386 $MIN_DEPLOY_TARGET" -export CXX_COMPILER_FLAGS="-std=c++11 -stdlib=libc++" -export OTHER_COMPILER_FLAGS="-g" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-osx64 b/Sources/OpenVPN3/vars/vars-osx64 deleted file mode 100644 index 623f07d..0000000 --- a/Sources/OpenVPN3/vars/vars-osx64 +++ /dev/null @@ -1,12 +0,0 @@ -export PLATFORM=osx -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/mac -export APPLE_FAMILY=1 -export DEBUG_BUILD=0 -export GPP_CMD=clang++ -export GCC_CMD=clang -export MIN_DEPLOY_TARGET="-mmacosx-version-min=10.8" -export PLATFORM_FLAGS="-arch x86_64 $MIN_DEPLOY_TARGET" -export OTHER_COMPILER_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" -export CXX_COMPILER_FLAGS="-std=c++14 -stdlib=libc++" -export LIB_OPT_LEVEL="-O3" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-osx64-dbg b/Sources/OpenVPN3/vars/vars-osx64-dbg deleted file mode 100644 index 3122149..0000000 --- a/Sources/OpenVPN3/vars/vars-osx64-dbg +++ /dev/null @@ -1,12 +0,0 @@ -export PLATFORM=osx-dbg -[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/mac -export APPLE_FAMILY=1 -export DEBUG_BUILD=1 -export GPP_CMD=clang++ -export GCC_CMD=clang -export MIN_DEPLOY_TARGET="-mmacosx-version-min=10.8" -export PLATFORM_FLAGS="-arch x86_64 $MIN_DEPLOY_TARGET" -export CXX_COMPILER_FLAGS="-std=c++14 -stdlib=libc++" -export OTHER_COMPILER_FLAGS="-g" -export LIB_OPT_LEVEL="-O0" -export LIB_FPIC="" diff --git a/Sources/OpenVPN3/vars/vars-reset b/Sources/OpenVPN3/vars/vars-reset deleted file mode 100644 index e82f179..0000000 --- a/Sources/OpenVPN3/vars/vars-reset +++ /dev/null @@ -1,21 +0,0 @@ -unset PLATFORM -unset PLATFORM_FLAGS -unset MIN_DEPLOY_TARGET -unset OTHER_COMPILER_FLAGS -unset IOS_SDK -unset BOOST_DIR -unset BOOST_STAGE -unset OPENSSL_DIR -unset SNAPPY_DIR -unset LZ4_DIR -unset JAVA_DIR -unset GPP_CMD -unset GCC_CMD -unset STRIP_CMD -unset LD_LIBRARY_PATH -unset APPLE_FAMILY -unset LIB_OPT_LEVEL -unset LIB_FPIC -unset DEBUG_BUILD -unset LINK_MODE -unset CXX_COMPILER_FLAGS diff --git a/Sources/OpenVPN3/vars/vars-win b/Sources/OpenVPN3/vars/vars-win deleted file mode 100644 index 28e0d95..0000000 --- a/Sources/OpenVPN3/vars/vars-win +++ /dev/null @@ -1 +0,0 @@ -alias build="python ~/ovpn3/win/build.py" diff --git a/Sources/OpenVPNAdapter/library/OpenVPNAdapterImpl.mm b/Sources/OpenVPNAdapter/library/OpenVPNAdapterImpl.mm index b8a0a4f..2f2b8d6 100644 --- a/Sources/OpenVPNAdapter/library/OpenVPNAdapterImpl.mm +++ b/Sources/OpenVPNAdapter/library/OpenVPNAdapterImpl.mm @@ -51,21 +51,27 @@ #pragma mark - OpenVPNClient Lifecycle + (nullable OpenVPNConfigurationEvaluation *)evaluateConfiguration:(OpenVPNConfiguration *)configuration error:(NSError **)error { - ClientAPI::EvalConfig eval = OpenVPNClient::eval_config_static(configuration.config); - - if (eval.error) { - if (error) { - NSString *message = [NSString stringWithUTF8String:eval.message.c_str()]; - *error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorConfigurationFailure - description:@"Failed to evaluate OpenVPN configuration." - message:message - fatal:YES]; - } - - return nil; - } - - return [[OpenVPNConfigurationEvaluation alloc] initWithEvalConfig:eval]; +// ClientAPI::EvalConfig eval = self.vpnClient->apply_config(configuration.config); +// +// if (eval.error) { +// if (error) { +// NSString *message = [NSString stringWithUTF8String:eval.message.c_str()]; +// *error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorConfigurationFailure +// description:@"Failed to evaluate OpenVPN configuration." +// message:message +// fatal:YES]; +// } +// +// return nil; +// } +// +// return [[OpenVPNConfigurationEvaluation alloc] initWithEvalConfig:eval]; +// NSString *message = [NSString stringWithUTF8String:eval.message.c_str()]; + *error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorConfigurationFailure + description:@"Function not support" + message:@"Function not support" + fatal:YES]; + return nil; } - (OpenVPNConfigurationEvaluation *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError * __autoreleasing *)error { @@ -152,11 +158,11 @@ #pragma mark - OpenVPNClient Information + (NSString *)copyright { - return [NSString stringWithUTF8String:OpenVPNClient::copyright().c_str()]; + return @"amnezia"; } + (NSString *)platform { - return [NSString stringWithUTF8String:OpenVPNClient::platform().c_str()]; + return @"iOS"; } - (OpenVPNConnectionInfo *)connectionInformation { diff --git a/Sources/OpenVPNAdapter/library/OpenVPNClient.h b/Sources/OpenVPNAdapter/library/OpenVPNClient.h index b7df300..e15a37f 100644 --- a/Sources/OpenVPNAdapter/library/OpenVPNClient.h +++ b/Sources/OpenVPNAdapter/library/OpenVPNClient.h @@ -64,7 +64,7 @@ public: ~OpenVPNClient(); ClientAPI::EvalConfig apply_config(const ClientAPI::Config& config); - + ClientAPI::EvalConfig eval_config_static(const ClientAPI::Config& config); bool tun_builder_new() override; bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override; @@ -81,7 +81,7 @@ public: bool tun_builder_set_proxy_auto_config_url(const std::string& urlString) override; bool tun_builder_set_proxy_http(const std::string& host, int port) override; bool tun_builder_set_proxy_https(const std::string& host, int port) override; - bool tun_builder_set_block_ipv6(bool block_ipv6) override; + bool tun_builder_set_block_ipv6(bool block_ipv6); int tun_builder_establish() override; bool tun_builder_persist() override; diff --git a/Sources/OpenVPNAdapter/library/OpenVPNClient.mm b/Sources/OpenVPNAdapter/library/OpenVPNClient.mm index b2adbae..7f2068c 100644 --- a/Sources/OpenVPNAdapter/library/OpenVPNClient.mm +++ b/Sources/OpenVPNAdapter/library/OpenVPNClient.mm @@ -26,11 +26,18 @@ OpenVPNClient::~OpenVPNClient() { ClientAPI::EvalConfig OpenVPNClient::apply_config(const ClientAPI::Config& config) { if (this->config != nullptr) { delete this->config; } +// this->config->usePluggableTransports = TRUE; this->config = new ClientAPI::Config(config); return eval_config(config); } +ClientAPI::EvalConfig OpenVPNClient::eval_config_static(const ClientAPI::Config& config){ + if (this->config != nullptr) { delete this->config; } + this->config = new ClientAPI::Config(config); + return eval_config_static(config); +} + bool OpenVPNClient::tun_builder_new() { [this->delegate resetSettings]; [this->delegate resetTun]; diff --git a/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.h b/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.h index b80f14f..3fb0314 100644 --- a/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.h +++ b/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.h @@ -138,15 +138,6 @@ typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile); */ @property (nonatomic) NSInteger keyDirection; -/** - If YES, force ciphersuite to be one of: - 1. TLS_DHE_RSA_WITH_AES_256_CBC_SHA, or - 2. TLS_DHE_RSA_WITH_AES_128_CBC_SHA - and disable setting TLS minimum version. - This is intended for compatibility with legacy systems. - */ -@property (nonatomic) BOOL forceCiphersuitesAESCBC; - /** Override the minimum TLS version */ @@ -183,10 +174,11 @@ typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile); @property (nonatomic) BOOL info; /** - Periodic convenience clock tick in milliseconds. Will call + Periodic convenience clock tick in milliseconds. Will call [OpenVPNAdapterDelegate tick] at a frequency defined by this parameter. Set to 0 to disable. */ @property (nonatomic) NSUInteger clockTick; - +- (void)setFileContent:(NSData *_Nullable)fileContent; +- (void)setPTCloak; @end diff --git a/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.mm b/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.mm index b716b8a..975054b 100644 --- a/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.mm +++ b/Sources/OpenVPNAdapter/library/OpenVPNConfiguration.mm @@ -67,7 +67,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; NSString *currentValue = [value length] == 0 ? OpenVPNTransportProtocolDefaultValue : value; NSNumber *transportProtocol = options[currentValue]; - NSAssert(transportProtocol != nil, @"Incorrect protocol value: %@", currentValue); + NSAssert(transportProtocol != nil, @"amnezia -> Incorrect protocol value: %@", currentValue); return (OpenVPNTransportProtocol)[transportProtocol integerValue]; } @@ -81,7 +81,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; }; NSString *value = options[@(protocol)]; - NSAssert(value != nil, @"Incorrect protocol value: %li", (long)protocol); + NSAssert(value != nil, @"amnezia -> Incorrect protocol value: %li", (long)protocol); return value; } @@ -96,7 +96,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; NSString *currentValue = [value length] == 0 ? OpenVPNIPv6PreferenceDefaultValue : value; NSNumber *ipv6 = options[currentValue]; - NSAssert(ipv6 != nil, @"Incorrect ipv6 value: %@", currentValue); + NSAssert(ipv6 != nil, @"amnezia -> Incorrect ipv6 value: %@", currentValue); return (OpenVPNIPv6Preference)[ipv6 integerValue]; } @@ -109,7 +109,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; }; NSString *value = options[@(preference)]; - NSAssert(value != nil, @"Incorrect ipv6 value: %li", (long)preference); + NSAssert(value != nil, @"amnezia -> Incorrect ipv6 value: %li", (long)preference); return value; } @@ -125,7 +125,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; NSString *currentValue = [value length] == 0 ? OpenVPNCompressionModeDefaultValue : value; NSNumber *compressionMode = options[currentValue]; - NSAssert(compressionMode != nil, @"Incorrect compressionMode value: %@", currentValue); + NSAssert(compressionMode != nil, @"amnezia -> Incorrect compressionMode value: %@", currentValue); return (OpenVPNCompressionMode)[compressionMode integerValue]; } @@ -139,7 +139,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; }; NSString *value = options[@(compressionMode)]; - NSAssert(value != nil, @"Incorrect compressionMode value: %li", (long)compressionMode); + NSAssert(value != nil, @"amnezia -> Incorrect compressionMode value: %li", (long)compressionMode); return value; } @@ -156,7 +156,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; NSString *currentValue = [value length] == 0 ? OpenVPNMinTLSVersionDefaultValue : value; NSNumber *minTLSVersion = options[currentValue]; - NSAssert(minTLSVersion != nil, @"Incorrect minTLS value: %@", currentValue); + NSAssert(minTLSVersion != nil, @"amnezia -> Incorrect minTLS value: %@", currentValue); return (OpenVPNMinTLSVersion)[minTLSVersion integerValue]; } @@ -171,7 +171,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; }; NSString *value = options[@(minTLS)]; - NSAssert(value != nil, @"Incorrect minTLS value: %li", (long)minTLS); + NSAssert(value != nil, @"amnezia -> Incorrect minTLS value: %li", (long)minTLS); return value; } @@ -189,7 +189,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; NSString *currentValue = [value length] == 0 ? OpenVPNTLSCertProfileDefaultValue : value; NSNumber *tlsCertProfile = options[currentValue]; - NSAssert(tlsCertProfile != nil, @"Incorrect tlsCertProfile value: %@", currentValue); + NSAssert(tlsCertProfile != nil, @"amnezia -> Incorrect tlsCertProfile value: %@", currentValue); return (OpenVPNTLSCertProfile)[tlsCertProfile integerValue]; } @@ -205,7 +205,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; }; NSString *value = options[@(tlsCertProfile)]; - NSAssert(value != nil, @"Incorrect tlsCertProfile value: %li", (long)tlsCertProfile); + NSAssert(value != nil, @"amnezia -> Incorrect tlsCertProfile value: %li", (long)tlsCertProfile); return value; } @@ -214,6 +214,10 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; @implementation OpenVPNConfiguration +- (void)setPTCloak { + _config.usePluggableTransports = TRUE; +} + - (NSData *)fileContent { return !_config.content.empty() ? [NSData dataWithBytes:_config.content.data() length:_config.content.size()] : nil; } @@ -315,13 +319,14 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; } - (OpenVPNIPv6Preference)ipv6 { - NSString *currentValue = [NSString stringWithUTF8String:_config.ipv6.c_str()]; +// NSString *currentValue = [NSString stringWithUTF8String:_config.ipv6.c_str()]; + NSString *currentValue = @""; return [OpenVPNConfiguration getIPv6PreferenceFromValue:currentValue]; } - (void)setIpv6:(OpenVPNIPv6Preference)ipv6 { NSString *value = [OpenVPNConfiguration getValueFromIPv6Preference:ipv6]; - _config.ipv6 = std::string([value UTF8String]); +// _config.ipv6 = std::string([value UTF8String]); } - (NSInteger)connectionTimeout { @@ -414,14 +419,6 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; _config.defaultKeyDirection = keyDirection; } -- (BOOL)forceCiphersuitesAESCBC { - return _config.forceAesCbcCiphersuites; -} - -- (void)setForceCiphersuitesAESCBC:(BOOL)forceCiphersuitesAESCBC { - _config.forceAesCbcCiphersuites = forceCiphersuitesAESCBC; -} - - (OpenVPNMinTLSVersion)minTLSVersion { NSString *currentValue = [NSString stringWithUTF8String:_config.tlsVersionMinOverride.c_str()]; return [OpenVPNConfiguration getMinTLSFromValue:currentValue]; @@ -545,7 +542,6 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; configuration.compressionMode = self.compressionMode; configuration.privateKeyPassword = [self.privateKeyPassword copyWithZone:zone]; configuration.keyDirection = self.keyDirection; - configuration.forceCiphersuitesAESCBC = self.forceCiphersuitesAESCBC; configuration.minTLSVersion = self.minTLSVersion; configuration.tlsCertProfile = self.tlsCertProfile; configuration.peerInfo = [self.peerInfo copyWithZone:zone]; @@ -575,7 +571,6 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; [aCoder encodeInteger:self.compressionMode forKey:NSStringFromSelector(@selector(compressionMode))]; [aCoder encodeObject:self.privateKeyPassword forKey:NSStringFromSelector(@selector(privateKeyPassword))]; [aCoder encodeInteger:self.keyDirection forKey:NSStringFromSelector(@selector(keyDirection))]; - [aCoder encodeBool:self.forceCiphersuitesAESCBC forKey:NSStringFromSelector(@selector(forceCiphersuitesAESCBC))]; [aCoder encodeInteger:self.minTLSVersion forKey:NSStringFromSelector(@selector(minTLSVersion))]; [aCoder encodeInteger:self.tlsCertProfile forKey:NSStringFromSelector(@selector(tlsCertProfile))]; [aCoder encodeObject:self.peerInfo forKey:NSStringFromSelector(@selector(peerInfo))]; @@ -605,7 +600,6 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default"; self.compressionMode = (OpenVPNCompressionMode)[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(compressionMode))]; self.privateKeyPassword = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(privateKeyPassword))]; self.keyDirection = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(keyDirection))]; - self.forceCiphersuitesAESCBC = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(forceCiphersuitesAESCBC))]; self.minTLSVersion = (OpenVPNMinTLSVersion)[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(minTLSVersion))]; self.tlsCertProfile = (OpenVPNTLSCertProfile)[aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(tlsCertProfile))]; self.peerInfo = [aDecoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(peerInfo))];