Squashed 'Sources/OpenVPNAdapter/Libraries/Vendors/openvpn/' changes from cc90cde57..6608878d5

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

git-subtree-dir: Sources/OpenVPNAdapter/Libraries/Vendors/openvpn
git-subtree-split: 6608878d57eec1c64c16c5a13ee65b2cf0418ca1
This commit is contained in:
Sergey Abramchuk
2019-01-13 13:08:42 +03:00
parent a01ecd6c88
commit f5fda0fa73
72 changed files with 3685 additions and 490 deletions

View File

@@ -9,8 +9,8 @@ env:
- secure: "dqiLqbzug/xs6F4Q9ei1pGpNf9Q6H3+iKN1W+P0TtODbCXPr/mLWdvHGVMIMqr7H7rBrIUPFPrfqd80nu3jQuQonjcHK/XyJJfmf5hUdhGAszSaixhWnGfVmn/VSV7/5+9DGAU3l9S6YZg4lvi12+cOrlblNgx8GeI5VdN/6HBSHkEqKNI56qn3Y+ugSdLeL1opmzlY58vRsCCmpBH8Ronn4tmSyi85/WZXfF43o9FGGJcygdh6QVWA1CDdNMeLTCt9ld+oToUIiFLiUrhfS1JpSvzysz2xsuEntxZaTMDYPyL4+O8Mj/scl6ejLLXzxTNa7AZOgySLBahf+F4b+yhL1deSVuu40MfxPW6XiM1jKy3KPH/GlYgM8CZQ3D1hQIq1CIUg8DgnTa06RUzevsR5DqDvz+EcPanFHE7dHGrPy9Rs/0y59dNHp3qWKjWMoSA06GerbF61XFOb4mcE29053kV8uxqIa5ZShZ/ndoLeVpQ4mZ+/XSkUybysVl0gWrKnnNNEPtqrdmKf+jlmKY0jyRPdwf425Ldn+wcbGw9ZEnkosYzqAhDBDX4OETAKLi8G0FEYECKKQcd1OX+HNvsOIyOAoLOj7H30F8UkPsjR3ysdIEmc6702ly06gDYjWmwQaCigL/1ktRKgf7ePB0HS+8fOa5SML7619kQrGrWA="
- PREFIX="${HOME}/opt"
- ASIO_VERSION="862aed305dcf91387535519c9549c17630339a12"
- LZ4_VERSION="1.7.5"
- MBEDTLS_VERSION="2.5.1"
- LZ4_VERSION="1.8.3"
- MBEDTLS_VERSION="2.7.5"
- MBEDTLS_CFLAGS="-I${PREFIX}/include"
- MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto"
- OPENSSL_VERSION="1.0.2l"
@@ -22,11 +22,9 @@ matrix:
include:
- env: SSLLIB="openssl"
os: osx
osx_image: xcode8.3
compiler: clang
- env: SSLLIB="mbedtls"
os: osx
osx_image: xcode8.3
compiler: clang
- env: SSLLIB="openssl" RUN_COVERITY_SCAN="1"
os: linux

View File

@@ -259,10 +259,10 @@ namespace openvpn {
parent = parent_arg;
}
virtual bool socket_protect(int socket)
bool socket_protect(int socket, IP::Addr endpoint) override
{
if (parent)
return parent->socket_protect(socket);
return parent->socket_protect(socket, endpoint.to_string(), endpoint.is_ipv6());
else
return true;
}

View File

@@ -466,7 +466,8 @@ namespace openvpn {
// Callback to "protect" a socket from being routed through the tunnel.
// Will be called from the thread executing connect().
virtual bool socket_protect(int socket) = 0;
// The remote and ipv6 are the remote host this socket will connect to
virtual bool socket_protect(int socket, std::string remote, bool ipv6) = 0;
// Primary VPN client connect method, doesn't return until disconnect.
// Should be called by a worker thread. This method will make callbacks

4
deps/lib-versions vendored
View File

@@ -1,8 +1,8 @@
export ASIO_VERSION=asio-1-12-0
export ASIO_CSUM=fa8c3a16dc2163f5b3451f2a14ce95277c971f46700497d4e94af6059c00dc06
export LZ4_VERSION=lz4-1.8.0
export LZ4_CSUM=2ca482ea7a9bb103603108b5a7510b7592b90158c151ff50a28f1ca8389fccf6
export LZ4_VERSION=lz4-1.8.3
export LZ4_CSUM=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43
export MBEDTLS_VERSION=mbedtls-2.7.5
export MBEDTLS_CSUM=a1302ad9094aabb9880d2755927b466a6bac8e02b68e04dee77321f3859e9b40

View File

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

View File

@@ -557,7 +557,8 @@ namespace openvpn {
init_headroom(headroom);
}
void append(const BufferType& other)
template <typename B>
void append(const B& other)
{
write(other.c_data(), other.size());
}

View File

@@ -693,6 +693,7 @@ namespace openvpn {
cp->dc_deferred = true; // defer data channel setup until after options pull
cp->tls_auth_factory.reset(new CryptoOvpnHMACFactory<SSLLib::CryptoAPI>());
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<SSLLib::CryptoAPI>());
cp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
cp->tlsprf_factory.reset(new CryptoTLSPRFFactory<SSLLib::CryptoAPI>());
cp->ssl_factory = cc->new_factory();
cp->load(opt, *proto_context_options, config.default_key_direction, false);

View File

@@ -600,6 +600,13 @@ namespace openvpn {
else
OPENVPN_LOG("Options continuation...");
}
else if (received_options.complete() && string::starts_with(msg, "PUSH_REPLY,"))
{
// We got a PUSH REPLY in the middle of a session. Ignore it apart from
// updating the auth-token if included in the push reply
auto opts = OptionList::parse_from_csv_static(msg.substr(11), nullptr);
extract_auth_token(opts);
}
else if (string::starts_with(msg, "AUTH_FAILED"))
{
std::string reason;

View File

@@ -276,8 +276,7 @@ namespace openvpn {
PreResolve(openvpn_io::io_context& io_context_arg,
const RemoteList::Ptr& remote_list_arg,
const SessionStats::Ptr& stats_arg)
: io_context(io_context_arg),
resolver(io_context_arg),
: resolver(io_context_arg),
notify_callback(nullptr),
remote_list(remote_list_arg),
stats(stats_arg),
@@ -385,7 +384,6 @@ namespace openvpn {
}
}
openvpn_io::io_context& io_context;
openvpn_io::ip::tcp::resolver resolver;
NotifyCallback* notify_callback;
RemoteList::Ptr remote_list;

View File

@@ -34,11 +34,13 @@
#include <mutex>
#include <openvpn/common/extern.hpp>
namespace openvpn {
namespace bigmutex {
OPENVPN_EXTERN std::recursive_mutex the_recursive_mutex;
}
#ifdef OPENVPN_ENABLE_BIGMUTEX
#define OPENVPN_ASYNC_HANDLER \
std::lock_guard<std::recursive_mutex> lg(bigmutex::the_recursive_mutex);

View File

@@ -19,25 +19,13 @@
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#ifndef OPENVPN_COMMON_ENDIAN_H
#define OPENVPN_COMMON_ENDIAN_H
#pragma once
#include <openvpn/common/size.hpp>
// test for machine endiannes
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && defined(__ORDER_LITTLE_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define OPENVPN_BIG_ENDIAN
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define OPENVPN_LITTLE_ENDIAN
#endif
#elif defined(_WIN32)
#define OPENVPN_LITTLE_ENDIAN // assume that Windows is always little-endian
#endif
#include <openvpn/common/endian_platform.hpp>
namespace openvpn {
namespace Endian {
# ifdef OPENVPN_LITTLE_ENDIAN
# if defined(OPENVPN_LITTLE_ENDIAN)
inline size_t e16(const size_t v)
{
return v;
@@ -62,7 +50,7 @@ namespace openvpn {
{
return 1-v;
}
# elif OPENVPN_BIG_ENDIAN
# elif defined(OPENVPN_BIG_ENDIAN)
inline size_t e16rev(const size_t v)
{
return v;
@@ -92,5 +80,3 @@ namespace openvpn {
# endif
}
} // namespace openvpn
#endif // OPENVPN_COMMON_ENDIAN_H

View File

@@ -0,0 +1,35 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2018 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <openvpn/common/size.hpp>
// test for machine endiannes
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && defined(__ORDER_LITTLE_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define OPENVPN_BIG_ENDIAN
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define OPENVPN_LITTLE_ENDIAN
#endif
#elif defined(_WIN32)
#define OPENVPN_LITTLE_ENDIAN // assume that Windows is always little-endian
#endif

View File

@@ -32,18 +32,88 @@ namespace openvpn {
#if defined(__GNUC__)
inline int find_first_set(unsigned int v)
template <typename T>
inline constexpr int n_bits_type()
{
return sizeof(T) * 8;
}
template <typename T>
inline constexpr int n_bits_type(const T& v)
{
return sizeof(v) * 8;
}
inline int find_first_set(const unsigned int v)
{
if (!v)
return 0;
return __builtin_ffs(v);
}
inline int find_last_set(unsigned int v)
inline int find_first_set(const int v)
{
return find_first_set(static_cast<unsigned int>(v));
}
inline int find_last_set(const unsigned int v)
{
if (!v)
return 0;
return 32 - __builtin_clz(v);
return n_bits_type(v) - __builtin_clz(v);
}
inline int find_last_set(const int v)
{
return find_last_set(static_cast<unsigned int>(v));
}
inline int find_first_set(const unsigned long v)
{
if (!v)
return 0;
return __builtin_ffsl(v);
}
inline int find_first_set(const long v)
{
return find_first_set(static_cast<unsigned long>(v));
}
inline int find_last_set(const unsigned long v)
{
if (!v)
return 0;
return n_bits_type(v) - __builtin_clzl(v);
}
inline int find_last_set(const long v)
{
return find_last_set(static_cast<unsigned long>(v));
}
inline int find_first_set(const unsigned long long v)
{
if (!v)
return 0;
return __builtin_ffsll(v);
}
inline int find_first_set(const long long v)
{
return find_first_set(static_cast<unsigned long long>(v));
}
inline int find_last_set(const unsigned long long v)
{
if (!v)
return 0;
return n_bits_type(v) - __builtin_clzll(v);
}
inline int find_last_set(const long long v)
{
return find_last_set(static_cast<unsigned long long>(v));
}
#elif defined(_MSC_VER)

View File

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

View File

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

View File

@@ -28,8 +28,12 @@
#include <string>
#include <openvpn/common/platform.hpp>
namespace openvpn {
#if defined(OPENVPN_PLATFORM_LINUX)
inline int update_file_mod_time_nanoseconds(const std::string& filename,
const std::uint64_t nanoseconds_since_epooch)
{
@@ -54,4 +58,20 @@ namespace openvpn {
return 0;
}
#else
inline int update_file_mod_time_nanoseconds(const std::string& filename,
const std::uint64_t nanoseconds_since_epooch)
{
return 0;
}
inline int update_file_mod_time_nanoseconds(const int fd,
const std::uint64_t nanoseconds_since_epooch)
{
return 0;
}
#endif
}

View File

@@ -113,6 +113,56 @@ namespace openvpn {
return "";
}
// return true if path is a regular file that doesn't try to traverse via ".." or "/..."
inline bool is_contained(const std::string& path)
{
if (path.empty())
return false;
if (win_dev(path, false))
return false;
if (is_dirsep(path[0]))
return false;
// look for ".." in path
enum State {
SEP, // immediately after separator
MID, // middle of dir
DOT_2, // looking for second '.'
POST_DOT_2, // after ".."
};
State state = SEP;
for (const auto c : path)
{
switch (state)
{
case SEP:
if (c == '.')
state = DOT_2;
else if (!is_dirsep(c))
state = MID;
break;
case MID:
if (is_dirsep(c))
state = SEP;
break;
case DOT_2:
if (c == '.')
state = POST_DOT_2;
else if (is_dirsep(c))
state = SEP;
else
state = MID;
break;
case POST_DOT_2:
if (is_dirsep(c))
return false;
state = MID;
break;
}
}
return state != POST_DOT_2;
}
inline std::string ext(const std::string& basename)
{
const size_t pos = basename.find_last_of('.');

View File

@@ -325,7 +325,8 @@ namespace openvpn {
cancel();
}
void signal(const openvpn_io::error_code& error, int signum)
protected:
virtual void signal(const openvpn_io::error_code& error, int signum)
{
if (!error && !halt)
{
@@ -346,10 +347,14 @@ namespace openvpn {
signal_rearm();
break;
#endif
default:
signal_rearm();
break;
}
}
}
private:
void signal_rearm()
{
signals->register_signals_all([self=Ptr(this)](const openvpn_io::error_code& error, int signal_number)
@@ -392,7 +397,6 @@ namespace openvpn {
// servlist and related vars protected by mutex
std::vector<ServerThread*> servlist;
int thread_count = 0;
volatile bool halt = false;
// stop
Stop* async_stop_ = nullptr;
@@ -404,6 +408,9 @@ namespace openvpn {
// logging
Log::Context log_context;
Log::Context::Wrapper log_wrap; // must be constructed after log_context
protected:
volatile bool halt = false;
};
}

View File

@@ -296,7 +296,7 @@ namespace openvpn {
inline bool contains_non_space_ctrl(const std::string& str)
{
for (auto &c : str)
if (!is_space(c) && is_ctrl(c))
if ((!is_space(c) && is_ctrl(c)) || c == 127)
return true;
return false;
}

View File

@@ -26,9 +26,16 @@
#include <openvpn/common/pthreadcond.hpp>
namespace openvpn {
#ifdef HAVE_VALGRIND
static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 300;
#else
static constexpr unsigned int WAIT_BARRIER_TIMEOUT = 30;
#endif
template <typename THREAD_COMMON>
inline void event_loop_wait_barrier(THREAD_COMMON& tc,
const unsigned int seconds=30)
const unsigned int seconds=WAIT_BARRIER_TIMEOUT)
{
// barrier prior to event-loop entry
switch (tc.event_loop_bar.wait(seconds))

View File

@@ -89,11 +89,8 @@ namespace openvpn {
bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len)
{
if (header_len < head_size + output_hmac_size())
return false;
hmac_pre(header, payload, payload_len);
ctx_hmac.final(header + head_size);
hmac_pre(header, header_len, payload, payload_len);
ctx_hmac.final(header + header_len);
return true;
}
@@ -103,13 +100,10 @@ namespace openvpn {
{
unsigned char local_hmac[CRYPTO_API::HMACContext::MAX_HMAC_SIZE];
if (header_len < head_size + output_hmac_size())
return false;
hmac_pre(header, payload, payload_len);
hmac_pre(header, header_len, payload, payload_len);
ctx_hmac.final(local_hmac);
return !crypto::memneq(header + head_size, local_hmac, output_hmac_size());
return !crypto::memneq(header + header_len, local_hmac, output_hmac_size());
}
size_t encrypt(const unsigned char *iv, unsigned char *out, const size_t olen,
@@ -132,11 +126,11 @@ namespace openvpn {
private:
// assume length check on header has already been performed
void hmac_pre(const unsigned char *header, const unsigned char *payload,
const size_t payload_len)
void hmac_pre(const unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len)
{
ctx_hmac.reset();
ctx_hmac.update(header, head_size);
ctx_hmac.update(header, header_len);
ctx_hmac.update(payload, payload_len);
}
@@ -159,19 +153,8 @@ namespace openvpn {
typename CRYPTO_API::HMACContext ctx_hmac;
typename CRYPTO_API::CipherContext ctx_crypt;
int mode;
static const size_t head_size;
};
// initialize static member with non-constexpr.
// This is the size of the header in a TLSCrypt-wrapped packets,
// excluding the HMAC. Format:
//
// [OP] [PSID] [PID] [HMAC] [...]
//
template <typename CRYPTO_API>
const size_t TLSCrypt<CRYPTO_API>::head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
// OvpnHMAC wrapper API using dynamic polymorphism
class TLSCryptInstance : public RC<thread_unsafe_refcount>
@@ -208,8 +191,19 @@ namespace openvpn {
virtual TLSCryptInstance::Ptr new_obj_send() = 0;
virtual TLSCryptInstance::Ptr new_obj_recv() = 0;
static const size_t hmac_offset;
};
// initialize static member with non-constexpr.
// This is the size of the header in a TLSCrypt-wrapped packets,
// excluding the HMAC. Format:
//
// [OP] [PSID] [PID] [HMAC] [...]
//
const size_t TLSCryptContext::hmac_offset = 1 + ProtoSessionID::SIZE +
PacketID::size(PacketID::LONG_FORM);
class TLSCryptFactory : public RC<thread_unsafe_refcount>
{
public:
@@ -244,21 +238,6 @@ namespace openvpn {
return tls_crypt.output_hmac_size();
}
void ovpn_hmac_reset()
{
tls_crypt.ovpn_hmac_reset();
}
void ovpn_hmac_update(const unsigned char *in, const size_t in_size)
{
tls_crypt.ovpn_hmac_update(in, in_size);
}
void ovpn_hmac_write(unsigned char *out)
{
tls_crypt.ovpn_hmac_write(out);
}
bool hmac_gen(unsigned char *header, const size_t header_len,
const unsigned char *payload, const size_t payload_len)
{

View File

@@ -0,0 +1,198 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2017-2018 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Classes for handling OpenVPN tls-crypt-v2 internals
#ifndef OPENVPN_CRYPTO_TLS_CRYPT_V2_H
#define OPENVPN_CRYPTO_TLS_CRYPT_V2_H
#include <string>
#include <openvpn/common/exception.hpp>
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/crypto/static_key.hpp>
#include <openvpn/crypto/tls_crypt.hpp>
#include <openvpn/ssl/sslchoose.hpp>
namespace openvpn {
class TLSCryptV2ServerKey
{
public:
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_parse_error);
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_encode_error);
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_server_key_bad_size);
TLSCryptV2ServerKey()
: key_size(128),
key(key_size, BufferAllocated::DESTRUCT_ZERO)
{}
bool defined() const
{
return key.defined();
}
void parse(const std::string& key_text)
{
if (!SSLLib::PEMAPI::pem_decode(key, key_text.c_str(), key_text.length(),
tls_crypt_v2_server_key_name))
throw tls_crypt_v2_server_key_parse_error();
if (key.size() != key_size)
throw tls_crypt_v2_server_key_bad_size();
}
void extract_key(OpenVPNStaticKey& tls_key)
{
std::memcpy(tls_key.raw_alloc(), key.c_data(), key_size);
}
std::string render() const
{
BufferAllocated data(32 + 2 * key.size(), 0);
if (!SSLLib::PEMAPI::pem_encode(data, key.c_data(), key.size(),
tls_crypt_v2_server_key_name))
throw tls_crypt_v2_server_key_encode_error();
return std::string((const char *)data.c_data());
}
private:
const size_t key_size;
BufferAllocated key;
static const std::string tls_crypt_v2_server_key_name;
};
const std::string TLSCryptV2ServerKey::tls_crypt_v2_server_key_name = "OpenVPN tls-crypt-v2 server key";
class TLSCryptV2ClientKey
{
public:
enum {
WKC_MAX_SIZE = 1024, // bytes
};
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_parse_error);
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_encode_error);
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_client_key_bad_size);
TLSCryptV2ClientKey() = delete;
TLSCryptV2ClientKey(TLSCryptContext::Ptr context)
: key_size(OpenVPNStaticKey::KEY_SIZE),
tag_size(context->digest_size())
{}
bool defined() const
{
return key.defined() && wkc.defined();
}
void parse(const std::string& key_text)
{
BufferAllocated data(key_size + WKC_MAX_SIZE, BufferAllocated::DESTRUCT_ZERO);
if (!SSLLib::PEMAPI::pem_decode(data, key_text.c_str(), key_text.length(),
tls_crypt_v2_client_key_name))
throw tls_crypt_v2_client_key_parse_error();
if (data.size() < (tag_size + key_size))
throw tls_crypt_v2_client_key_bad_size();
key.init(data.data(), key_size, BufferAllocated::DESTRUCT_ZERO);
wkc.init(data.data() + key_size, data.size() - key_size, BufferAllocated::DESTRUCT_ZERO);
}
void extract_key(OpenVPNStaticKey& tls_key)
{
std::memcpy(tls_key.raw_alloc(), key.c_data(), key_size);
}
std::string render() const
{
BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0);
BufferAllocated in(key, BufferAllocated::GROW);
in.append(wkc);
if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), tls_crypt_v2_client_key_name))
throw tls_crypt_v2_client_key_encode_error();
return std::string((const char *)data.c_data());
}
void extract_wkc(BufferAllocated& wkc_out) const
{
wkc_out = wkc;
}
private:
BufferAllocated key;
BufferAllocated wkc;
const size_t key_size;
const size_t tag_size;
static const std::string tls_crypt_v2_client_key_name;
};
const std::string TLSCryptV2ClientKey::tls_crypt_v2_client_key_name = "OpenVPN tls-crypt-v2 client key";
// the user can extend the TLSCryptMetadata and the TLSCryptMetadataFactory
// classes to implement its own metadata verification method.
//
// default method is to *ignore* the metadata contained in the WKc sent by the client
class TLSCryptMetadata : public RC<thread_unsafe_refcount>
{
public:
typedef RCPtr<TLSCryptMetadata> Ptr;
// override this method with your own verification mechanism.
//
// If type is -1 it means that metadata is empty.
//
virtual bool verify(int type, Buffer& metadata) const
{
return true;
}
};
// abstract class to be extended when creating other factories
class TLSCryptMetadataFactory : public RC<thread_unsafe_refcount>
{
public:
typedef RCPtr<TLSCryptMetadataFactory> Ptr;
virtual TLSCryptMetadata::Ptr new_obj() = 0;
};
// factory implementation for the basic verification method
class CryptoTLSCryptMetadataFactory : public TLSCryptMetadataFactory
{
public:
TLSCryptMetadata::Ptr new_obj()
{
return new TLSCryptMetadata();
}
};
}
#endif /* OPENVPN_CRYPTO_TLS_CRYPT_V2_H */

View File

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

View File

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

View File

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

View File

@@ -36,6 +36,11 @@ namespace openvpn {
UDP = 17, /* UDP protocol */
};
enum {
IPv4 = 4,
IPv6 = 6
};
inline unsigned int version(const std::uint8_t version_len_prio)
{
return (version_len_prio >> 4) & 0x0F;

90
openvpn/ip/tcp.hpp Normal file
View File

@@ -0,0 +1,90 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <openvpn/common/endian.hpp>
#include <openvpn/ip/ipcommon.hpp>
namespace openvpn {
#pragma pack(push)
#pragma pack(1)
struct TCPHeader {
static unsigned int length(const std::uint8_t doff_res)
{
return ((doff_res) & 0xF0) >> 2;
}
std::uint16_t source;
std::uint16_t dest;
std::uint32_t seq;
std::uint32_t ack_seq;
std::uint8_t doff_res;
std::uint8_t flags;
std::uint16_t window;
std::uint16_t check;
std::uint16_t urgent_p;
// helper enum to parse options in TCP header
enum {
OPT_EOL = 0,
OPT_NOP = 1,
OPT_MAXSEG = 2,
OPTLEN_MAXSEG = 4
};
enum {
FLAG_SYN = 1 << 1
};
};
#pragma pack(pop)
/*
* The following routine is used to update an
* internet checksum. "acc" is a 32-bit
* accumulation of all the changes to the
* checksum (adding in old 16-bit words and
* subtracting out new words), and "cksum"
* is the checksum value to be updated.
*/
inline void tcp_adjust_checksum(int acc, std::uint16_t& cksum)
{
int _acc = acc;
_acc += cksum;
if (_acc < 0)
{
_acc = -_acc;
_acc = (_acc >> 16) + (_acc & 0xffff);
_acc += _acc >> 16;
cksum = (uint16_t)~_acc;
}
else
{
_acc = (_acc >> 16) + (_acc & 0xffff);
_acc += _acc >> 16;
cksum = (uint16_t)_acc;
}
}
}

View File

@@ -826,8 +826,15 @@ namespace openvpn {
// set our own certificate, supporting chain (i.e. extra-certs), and external private key
if (c.crt_chain)
{
epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len);
mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get());
if (mbedtls_pk_get_type(&c.crt_chain.get()->get()->pk) == MBEDTLS_PK_RSA)
{
epki_ctx.epki_enable(ctx, epki_decrypt, epki_sign, epki_key_len);
mbedtls_ssl_conf_own_cert(sslconf, c.crt_chain->get(), epki_ctx.get());
}
else
{
throw MbedTLSException("cert has unsupported type for external pki support");
}
}
else
throw MbedTLSException("cert is undefined");
@@ -1217,7 +1224,11 @@ namespace openvpn {
{
const int SHA_DIGEST_LEN = 20;
static_assert(sizeof(AuthCert::issuer_fp) == SHA_DIGEST_LEN, "size inconsistency");
mbedtls_sha1(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp);
if(mbedtls_sha1_ret(cert->raw.p, cert->raw.len, ssl->authcert->issuer_fp))
{
OPENVPN_LOG_SSL("VERIFY FAIL -- SHA1 calculation failed.");
fail = true;
}
}
}
else if (depth == 0) // leaf-cert

View File

@@ -0,0 +1,77 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2017-2018 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Wrap the mbedTLS PEM API defined in <mbedtls/pem.h> so
// that it can be used as part of the crypto layer of the OpenVPN core.
#ifndef OPENVPN_MBEDTLS_UTIL_PEM_H
#define OPENVPN_MBEDTLS_UTIL_PEM_H
#include <mbedtls/pem.h>
namespace openvpn {
class MbedTLSPEM
{
public:
static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
size_t src_len, const std::string& key_name)
{
std::string header = "-----BEGIN " + key_name + "-----\n";
std::string footer = "-----END " + key_name + "-----\n";
size_t out_len = 0;
int ret = mbedtls_pem_write_buffer(header.c_str(), footer.c_str(),
src, src_len, dst.data(),
dst.max_size(), &out_len);
if (ret == 0)
dst.set_size(out_len);
else
{
char buf[128];
mbedtls_strerror(ret, buf, 128);
OPENVPN_LOG("mbedtls_pem_write_buffer error: " << buf);
}
return (ret == 0);
}
static bool pem_decode(BufferAllocated& dst, const char *src,
size_t src_len, const std::string& key_name)
{
std::string header = "-----BEGIN " + key_name + "-----";
std::string footer = "-----END " + key_name + "-----";
mbedtls_pem_context ctx = { 0 };
size_t out_len = 0;
int ret = mbedtls_pem_read_buffer(&ctx, header.c_str(), footer.c_str(),
(unsigned char *)src, nullptr, 0,
&out_len);
if (ret == 0)
dst.init(ctx.buf, ctx.buflen, BufferAllocated::DESTRUCT_ZERO);
mbedtls_pem_free(&ctx);
return (ret == 0);
}
};
};
#endif /* OPENVPN_MBEDTLS_UTIL_PEM_H */

View File

@@ -0,0 +1,141 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Find default gateways on Linux using ip route command
#pragma once
#include <string>
#include <openvpn/common/exception.hpp>
#include <openvpn/addr/ip.hpp>
#include <openvpn/addr/ipv4.hpp>
#include <openvpn/addr/ipv6.hpp>
#include <openvpn/tun/linux/client/sitnl.hpp>
namespace openvpn {
class LinuxGWNetlink
{
public:
OPENVPN_EXCEPTION(linux_gw_netlink_error);
LinuxGWNetlink(bool ipv6)
{
try
{
if (ipv6)
{
IPv6::Addr addr6;
if (TunNetlink::SITNL::net_route_best_gw(IP::Route6(IPv6::Addr::from_zero(), 0),
addr6, dev_) < 0)
{
OPENVPN_THROW(linux_gw_netlink_error,
"error retrieving default IPv6 GW");
}
addr_ = IP::Addr::from_ipv6(addr6);
}
else
{
IPv4::Addr addr4;
if (TunNetlink::SITNL::net_route_best_gw(IP::Route4(IPv4::Addr::from_zero(), 0),
addr4, dev_) < 0)
{
OPENVPN_THROW(linux_gw_netlink_error,
"error retrieving default IPv4 GW");
}
addr_ = IP::Addr::from_ipv4(addr4);
}
} catch (...)
{
/* nothing to do. just leave default GW unassigned */
}
}
const std::string& dev() const
{
return dev_;
}
const IP::Addr& addr() const
{
return addr_;
}
bool defined() const
{
return !dev_.empty() && addr_.defined();
}
std::string to_string() const
{
return dev_ + '/' + addr_.to_string();
}
private:
IP::Addr addr_;
std::string dev_;
};
struct LinuxGW46Netlink
{
LinuxGW46Netlink()
: v4(false),
v6(true)
{
}
std::string to_string() const
{
std::string ret = "[";
if (v4.defined())
{
ret += "4:";
ret += v4.to_string();
}
if (v6.defined())
{
if (v4.defined())
ret += ' ';
ret += "6:";
ret += v6.to_string();
}
ret += "]";
return ret;
}
std::string dev() const
{
if (v4.defined())
return v4.dev();
else if (v6.defined())
return v6.dev();
else
throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface");
}
LinuxGWNetlink v4;
LinuxGWNetlink v6;
};
}

View File

@@ -520,6 +520,8 @@ namespace openvpn {
static void init_static()
{
SSL_library_init();
mydata_index = SSL_get_ex_new_index(0, (char *)"OpenSSLContext::SSL", nullptr, nullptr, nullptr);
// We actually override some of the OpenSSL SSLv23 methods here,
@@ -867,7 +869,7 @@ namespace openvpn {
try
{
// Create new SSL_CTX for server or client mode
const bool ssl23 = (config->force_aes_cbc_ciphersuites || (config->tls_version_min > TLSVersion::UNDEF));
const bool ssl23 = (!config->force_aes_cbc_ciphersuites || (config->tls_version_min > TLSVersion::UNDEF));
if (config->mode.is_server())
{
ctx = SSL_CTX_new(ssl23 ? SSL::ssl23_method_server() : TLSv1_server_method());
@@ -910,20 +912,17 @@ namespace openvpn {
if (ssl23)
{
sslopt |= SSL_OP_NO_SSLv2;
if (!config->force_aes_cbc_ciphersuites || config->tls_version_min > TLSVersion::UNDEF)
{
sslopt |= SSL_OP_NO_SSLv3;
if (config->tls_version_min > TLSVersion::V1_0)
sslopt |= SSL_OP_NO_TLSv1;
# ifdef SSL_OP_NO_TLSv1_1
if (config->tls_version_min > TLSVersion::V1_1)
sslopt |= SSL_OP_NO_TLSv1_1;
# endif
# ifdef SSL_OP_NO_TLSv1_2
if (config->tls_version_min > TLSVersion::V1_2)
sslopt |= SSL_OP_NO_TLSv1_2;
# endif
}
sslopt |= SSL_OP_NO_SSLv3;
if (config->tls_version_min > TLSVersion::V1_0)
sslopt |= SSL_OP_NO_TLSv1;
# ifdef SSL_OP_NO_TLSv1_1
if (config->tls_version_min > TLSVersion::V1_1)
sslopt |= SSL_OP_NO_TLSv1_1;
# endif
# ifdef SSL_OP_NO_TLSv1_2
if (config->tls_version_min > TLSVersion::V1_2)
sslopt |= SSL_OP_NO_TLSv1_2;
# endif
}
SSL_CTX_set_options(ctx, sslopt);

View File

@@ -0,0 +1,103 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2017-2018 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Wrap the OpenSSL PEM API defined in <openssl/pem.h> so
// that it can be used as part of the crypto layer of the OpenVPN core.
#ifndef OPENVPN_OPENSSL_UTIL_PEM_H
#define OPENVPN_OPENSSL_UTIL_PEM_H
#include <openvpn/openssl/util/error.hpp>
#include <openssl/pem.h>
namespace openvpn {
class OpenSSLPEM
{
public:
static bool pem_encode(BufferAllocated& dst, const unsigned char *src,
size_t src_len, const std::string& key_name)
{
bool ret = false;
BIO *bio = BIO_new(BIO_s_mem());
if (!bio)
return false;
if (!PEM_write_bio(bio, key_name.c_str(), "", src, src_len))
goto out;
BUF_MEM *bptr;
BIO_get_mem_ptr(bio, &bptr);
dst.write((unsigned char *)bptr->data, bptr->length);
ret = true;
out:
if (!BIO_free(bio))
ret = false;
return ret;
}
static bool pem_decode(BufferAllocated& dst, const char *src,
size_t src_len, const std::string& key_name)
{
bool ret = false;
BIO *bio;
if (!(bio = BIO_new_mem_buf(src, src_len)))
throw OpenSSLException("Cannot open memory BIO for PEM decode");
char *name_read = NULL;
char *header_read = NULL;
uint8_t *data_read = NULL;
long data_read_len = 0;
if (!PEM_read_bio(bio, &name_read, &header_read, &data_read,
&data_read_len))
{
OPENVPN_LOG("PEM decode failed");
goto out;
}
if (key_name.compare(std::string(name_read)))
{
OPENVPN_LOG("unexpected PEM name (got '" << name_read <<
"', expected '" << key_name << "')");
goto out;
}
dst.write(data_read, data_read_len);
ret = true;
out:
OPENSSL_free(name_read);
OPENSSL_free(header_read);
OPENSSL_free(data_read);
if (!BIO_free(bio))
ret = false;
return ret;
}
};
};
#endif /* OPENVPN_OPENSSL_UTIL_PEM_H */

View File

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

View File

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

View File

@@ -48,6 +48,10 @@
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/buffer/safestr.hpp>
#include <openvpn/buffer/bufcomposed.hpp>
#include <openvpn/ip/ip4.hpp>
#include <openvpn/ip/ip6.hpp>
#include <openvpn/ip/udp.hpp>
#include <openvpn/ip/tcp.hpp>
#include <openvpn/time/time.hpp>
#include <openvpn/time/durhelper.hpp>
#include <openvpn/frame/frame.hpp>
@@ -57,6 +61,7 @@
#include <openvpn/crypto/cipher.hpp>
#include <openvpn/crypto/ovpnhmac.hpp>
#include <openvpn/crypto/tls_crypt.hpp>
#include <openvpn/crypto/tls_crypt_v2.hpp>
#include <openvpn/crypto/packet_id.hpp>
#include <openvpn/crypto/static_key.hpp>
#include <openvpn/crypto/bs64_data_limit.hpp>
@@ -65,6 +70,8 @@
#include <openvpn/ssl/psid.hpp>
#include <openvpn/ssl/tlsprf.hpp>
#include <openvpn/ssl/datalimit.hpp>
#include <openvpn/ssl/mssparms.hpp>
#include <openvpn/transport/mssfix.hpp>
#include <openvpn/transport/protocol.hpp>
#include <openvpn/tun/layer.hpp>
#include <openvpn/tun/tunmtu.hpp>
@@ -171,6 +178,7 @@ namespace openvpn {
// indicates key_method >= 2
CONTROL_HARD_RESET_CLIENT_V2 = 7, // initial key from client, forget previous state
CONTROL_HARD_RESET_CLIENT_V3 = 10, // initial key from client, forget previous state
CONTROL_HARD_RESET_SERVER_V2 = 8, // initial key from server, forget previous state
// define the range of legal opcodes
@@ -291,8 +299,10 @@ namespace openvpn {
// compressor
CompressContext comp_ctx;
// tls_auth parms
// tls_auth/crypt parms
OpenVPNStaticKey tls_key; // leave this undefined to disable tls_auth/crypt
bool tls_crypt_v2 = false; // needed to distinguish between tls-crypt and tls-crypt-v2 server mode
BufferAllocated wkc; // leave this undefined to disable tls-crypt-v2 on client
OvpnHMACFactory::Ptr tls_auth_factory;
OvpnHMACContext::Ptr tls_auth_context;
@@ -301,6 +311,8 @@ namespace openvpn {
TLSCryptFactory::Ptr tls_crypt_factory;
TLSCryptContext::Ptr tls_crypt_context;
TLSCryptMetadataFactory::Ptr tls_crypt_metadata_factory;
// reliability layer parms
reliable::id_t reliable_window = 0;
size_t max_ack_list = 0;
@@ -332,13 +344,15 @@ namespace openvpn {
// MTU
unsigned int tun_mtu = 1500;
MSSParms mss_parms;
unsigned int mss_inter = 0;
// Debugging
int debug_level = 1;
// Compatibility
bool force_aes_cbc_ciphersuites = false;
// For compatibility with openvpn2 we send initial options on rekeying,
// instead of possible modifications caused by NCP
std::string initial_options;
@@ -433,6 +447,8 @@ namespace openvpn {
{
if (tls_auth_context)
throw proto_option_error("tls-auth and tls-crypt are mutually exclusive");
if (tls_crypt_context)
throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive");
tls_key.parse(o->get(1, 0));
@@ -445,6 +461,46 @@ namespace openvpn {
set_tls_crypt_algs(digest, cipher);
}
}
// tls-crypt-v2
{
const Option *o = opt.get_ptr(relay_prefix("tls-crypt-v2"));
if (o)
{
if (tls_auth_context)
throw proto_option_error("tls-auth and tls-crypt-v2 are mutually exclusive");
if (tls_crypt_context)
throw proto_option_error("tls-crypt and tls-crypt-v2 are mutually exclusive");
digest = CryptoAlgs::lookup("SHA256");
cipher = CryptoAlgs::lookup("AES-256-CTR");
if ((digest == CryptoAlgs::NONE) || (cipher == CryptoAlgs::NONE))
throw proto_option_error("missing support for tls-crypt-v2 algorithms");
// initialize tls_crypt_context
set_tls_crypt_algs(digest, cipher);
std::string keyfile = o->get(1, 0);
if (opt.exists("client"))
{
// in client mode expect the key to be a PEM encoded tls-crypt-v2 client key (key + WKc)
TLSCryptV2ClientKey tls_crypt_v2_key(tls_crypt_context);
tls_crypt_v2_key.parse(keyfile);
tls_crypt_v2_key.extract_key(tls_key);
tls_crypt_v2_key.extract_wkc(wkc);
}
else
{
// in server mode this is a PEM encoded tls-crypt-v2 server key
TLSCryptV2ServerKey tls_crypt_v2_key;
tls_crypt_v2_key.parse(keyfile);
tls_crypt_v2_key.extract_key(tls_key);
}
tls_crypt_v2 = true;
}
}
}
// key-direction
@@ -507,6 +563,9 @@ namespace openvpn {
// tun-mtu
tun_mtu = parse_tun_mtu(opt, tun_mtu);
// mssfix
mss_parms.parse(opt);
// load parameters that can be present in both config file or pushed options
load_common(opt, pco, server ? LOAD_COMMON_SERVER : LOAD_COMMON_CLIENT);
}
@@ -680,13 +739,18 @@ namespace openvpn {
return tls_key.defined() && tls_crypt_context;
}
bool tls_crypt_v2_enabled() const
{
return tls_crypt_enabled() && tls_crypt_v2;
}
// generate a string summarizing options that will be
// transmitted to peer for options consistency check
std::string options_string()
{
if (!initial_options.empty())
return initial_options;
std::ostringstream out;
const bool server = ssl_factory->mode().is_server();
@@ -726,7 +790,7 @@ namespace openvpn {
out << ",tls-server";
else
out << ",tls-client";
initial_options = out.str();
return initial_options;
@@ -892,6 +956,7 @@ namespace openvpn {
break;
}
case CONTROL_HARD_RESET_CLIENT_V2:
case CONTROL_HARD_RESET_CLIENT_V3:
{
if (!proto.is_server())
return;
@@ -946,6 +1011,8 @@ namespace openvpn {
return "DATA_V2";
case CONTROL_HARD_RESET_CLIENT_V2:
return "CONTROL_HARD_RESET_CLIENT_V2";
case CONTROL_HARD_RESET_CLIENT_V3:
return "CONTROL_HARD_RESET_CLIENT_V3";
case CONTROL_HARD_RESET_SERVER_V2:
return "CONTROL_HARD_RESET_SERVER_V2";
}
@@ -1217,6 +1284,8 @@ namespace openvpn {
public:
typedef RCPtr<KeyContext> Ptr;
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_unwrap_wkc_error);
// KeyContext events occur on two basic key types:
// Primary Key -- the key we transmit/encrypt on.
// Secondary Key -- new keys and retiring keys.
@@ -1351,7 +1420,7 @@ namespace openvpn {
send_reset();
set_state(state+1);
dirty = true;
}
}
}
// control channel flush
@@ -1466,6 +1535,10 @@ namespace openvpn {
// decompress packet
if (compress)
compress->decompress(buf);
// set MSS for segments server can receive
if (proto.config->mss_inter > 0)
MSSFix::mssfix(buf, proto.config->mss_inter);
}
else
buf.reset_size(); // no crypto context available
@@ -1607,6 +1680,15 @@ namespace openvpn {
{
case TLS_AUTH:
return validate_tls_auth(recv, proto, now);
case TLS_CRYPT_V2:
if (opcode_extract(recv[0]) == CONTROL_HARD_RESET_CLIENT_V3)
{
// skip validation of HARD_RESET_V3 because the tls-crypt
// engine has not been initialized yet
OPENVPN_LOG_PROTO_VERBOSE("SKIPPING VALIDATION OF HARD_RESET_V3");
return true;
}
/* no break */
case TLS_CRYPT:
return validate_tls_crypt(recv, proto, now);
case TLS_PLAIN:
@@ -1675,6 +1757,35 @@ namespace openvpn {
// cache op32 for hot path in do_encrypt
cache_op32();
int crypto_encap = (enable_op32 ? OP_SIZE_V2 : 1) +
c.comp_ctx.extra_payload_bytes() +
PacketID::size(PacketID::SHORT_FORM) +
c.dc.context().encap_overhead();
int transport_encap = 0;
if (c.mss_parms.mtu)
{
if (proto.is_tcp())
transport_encap += sizeof(struct TCPHeader);
else
transport_encap += sizeof(struct UDPHeader);
if (c.protocol.is_ipv6())
transport_encap += sizeof(struct IPv6Header);
else
transport_encap += sizeof(struct IPv4Header);
transport_encap += c.protocol.extra_transport_bytes();
}
if (c.mss_parms.mssfix != 0)
{
OPENVPN_LOG_PROTO("MTU mssfix=" << c.mss_parms.mssfix <<
" crypto_encap=" << crypto_encap <<
" transport_encap=" << transport_encap);
c.mss_inter = c.mss_parms.mssfix - (crypto_encap + transport_encap);
}
}
}
@@ -1765,7 +1876,9 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
if (!proto.tls_crypt_recv->hmac_cmp(orig_data, orig_size, work.c_data(), work.size()))
if (!proto.tls_crypt_recv->hmac_cmp(orig_data,
TLSCryptContext::hmac_offset,
work.c_data(), work.size()))
return false;
// verify source PSID
@@ -1819,6 +1932,10 @@ namespace openvpn {
{
bool pid_wrap;
// set MSS for segments client can receive
if (proto.config->mss_inter > 0)
MSSFix::mssfix(buf, proto.config->mss_inter);
// compress packet
if (compress)
compress->compress(buf, compress_hint);
@@ -1990,25 +2107,36 @@ namespace openvpn {
set_event(ev);
}
unsigned int initial_op(const bool sender) const
unsigned int initial_op(const bool sender, const bool tls_crypt_v2) const
{
if (key_id_)
return CONTROL_SOFT_RESET_V1;
{
return CONTROL_SOFT_RESET_V1;
}
else
return (proto.is_server() == sender) ? CONTROL_HARD_RESET_SERVER_V2 : CONTROL_HARD_RESET_CLIENT_V2;
{
if (proto.is_server() == sender)
return CONTROL_HARD_RESET_SERVER_V2;
if (!tls_crypt_v2)
return CONTROL_HARD_RESET_CLIENT_V2;
else
return CONTROL_HARD_RESET_CLIENT_V3;
}
}
void send_reset()
{
Packet pkt;
pkt.opcode = initial_op(true);
pkt.opcode = initial_op(true, proto.tls_wrap_mode == TLS_CRYPT_V2);
pkt.frame_prepare(*proto.config->frame, Frame::WRITE_SSL_INIT);
raw_send(std::move(pkt));
}
void raw_recv(Packet&& raw_pkt) // called by ProtoStackBase
{
if (raw_pkt.buf->empty() && raw_pkt.opcode == initial_op(false))
if (raw_pkt.buf->empty() &&
raw_pkt.opcode == initial_op(false, proto.tls_wrap_mode == TLS_CRYPT_V2))
{
switch (state)
{
@@ -2265,14 +2393,15 @@ namespace openvpn {
// write opcode
work.push_front(op_compose(opcode, key_id_));
// compute HMAC using header fields (from 'work') and plaintext payload (from 'buf')
proto.tls_crypt_send->hmac_gen(work.data(), work.size(), buf.c_data(), buf.size());
// compute HMAC using header fields (from 'work') and plaintext
// payload (from 'buf')
proto.tls_crypt_send->hmac_gen(work.data(), TLSCryptContext::hmac_offset,
buf.c_data(), buf.size());
const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
const size_t data_offset = head_size + proto.hmac_size;
const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size;
// encrypt the content of 'buf' (packet payload) into 'work'
const size_t decrypt_bytes = proto.tls_crypt_send->encrypt(work.c_data() + head_size,
const size_t decrypt_bytes = proto.tls_crypt_send->encrypt(work.c_data() + TLSCryptContext::hmac_offset,
work.data() + data_offset,
work.max_size() - data_offset,
buf.c_data(), buf.size());
@@ -2283,6 +2412,11 @@ namespace openvpn {
}
work.inc_size(decrypt_bytes);
// append WKc to wrapped packet for tls-crypt-v2
if ((opcode == CONTROL_HARD_RESET_CLIENT_V3)
&& (proto.tls_wrap_mode == TLS_CRYPT_V2))
proto.tls_crypt_append_wkc(work);
// 'work' now contains the complete packet ready to go. swap it with 'buf'
buf.swap(work);
}
@@ -2303,6 +2437,7 @@ namespace openvpn {
gen_head_tls_auth(opcode, buf);
break;
case TLS_CRYPT:
case TLS_CRYPT_V2:
gen_head_tls_crypt(opcode, buf);
break;
case TLS_PLAIN:
@@ -2448,15 +2583,14 @@ namespace openvpn {
// skip the hmac
recv.advance(proto.hmac_size);
const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
const size_t data_offset = head_size + proto.hmac_size;
const size_t data_offset = TLSCryptContext::hmac_offset + proto.hmac_size;
if (orig_size < data_offset)
return false;
// decrypt payload
proto.config->frame->prepare(Frame::DECRYPT_WORK, work);
const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + head_size,
const size_t decrypt_bytes = proto.tls_crypt_recv->decrypt(orig_data + TLSCryptContext::hmac_offset,
work.data(), work.max_size(),
recv.c_data(), recv.size());
if (!decrypt_bytes)
@@ -2470,7 +2604,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
if (!proto.tls_crypt_recv->hmac_cmp(orig_data, orig_size, work.c_data(), work.size()))
if (!proto.tls_crypt_recv->hmac_cmp(orig_data, TLSCryptContext::hmac_offset,
work.c_data(), work.size()))
{
proto.stats->error(Error::HMAC_ERROR);
if (proto.is_tcp())
@@ -2528,6 +2663,100 @@ namespace openvpn {
return false;
}
bool unwrap_tls_crypt_wkc(Buffer &recv)
{
// the ``WKc`` is located at the end of the packet, after the tls-crypt
// payload.
// Format is as follows (as documented by Steffan Krager):
//
// ``len = len(WKc)`` (16 bit, network byte order)
// ``T = HMAC-SHA256(Ka, len || Kc || metadata)``
// ``IV = 128 most significant bits of T``
// ``WKc = T || AES-256-CTR(Ke, IV, Kc || metadata) || len``
const unsigned char *orig_data = recv.data();
const size_t orig_size = recv.size();
const size_t hmac_size = proto.config->tls_crypt_context->digest_size();
const size_t tls_frame_size = 1 + ProtoSessionID::SIZE +
PacketID::size(PacketID::LONG_FORM) +
hmac_size +
// the following is the tls-crypt payload
sizeof(char) + // length of ACK array
sizeof(id_t); // reliable ID
// check that at least the authentication tag ``T`` is present
if (orig_size < (tls_frame_size + hmac_size))
return false;
// the ``WKc`` is just appended after the standard tls-crypt frame
const unsigned char *wkc_raw = orig_data + tls_frame_size;
const size_t wkc_raw_size = orig_size - tls_frame_size - sizeof(uint16_t);
// retrieve the ``WKc`` len from the bottom of the packet and convert it to Host Order
uint16_t wkc_len = ntohs(*(uint16_t *)(wkc_raw + wkc_raw_size));
// length sanity check (the size of the ``len`` field is included in the value)
if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size)
return false;
BufferAllocated plaintext(wkc_len, BufferAllocated::CONSTRUCT_ZERO);
// plaintext will be used to compute the Auth Tag, therefore start by prepnding
// the WKc length in network order
wkc_len = htons(wkc_len);
plaintext.write(&wkc_len, sizeof(wkc_len));
const size_t decrypt_bytes = proto.tls_crypt_server->decrypt(wkc_raw,
plaintext.data() + 2,
plaintext.max_size() - 2,
wkc_raw + hmac_size,
wkc_raw_size - hmac_size);
plaintext.inc_size(decrypt_bytes);
// decrypted data must at least contain a full 2048bits client key
// (metadata is optional)
if (plaintext.size() < OpenVPNStaticKey::KEY_SIZE)
{
proto.stats->error(Error::DECRYPT_ERROR);
if (proto.is_tcp())
invalidate(Error::DECRYPT_ERROR);
return false;
}
if (!proto.tls_crypt_server->hmac_cmp(wkc_raw, 0,
plaintext.c_data(),
plaintext.size()))
{
proto.stats->error(Error::HMAC_ERROR);
if (proto.is_tcp())
invalidate(Error::HMAC_ERROR);
return false;
}
// we can now remove the WKc length from the plaintext, as it is not
// really part of the key material
plaintext.advance(sizeof(wkc_len));
// WKc has been authenticated: it contains the client key followed
// by the optional metadata. Let's initialize the tls-crypt context
// with the client key
OpenVPNStaticKey client_key;
plaintext.read(client_key.raw_alloc(), OpenVPNStaticKey::KEY_SIZE);
proto.reset_tls_crypt(*proto.config, client_key);
// verify metadata
int metadata_type = -1;
if (!plaintext.empty())
metadata_type = plaintext.pop_front();
if (!proto.tls_crypt_metadata->verify(metadata_type, plaintext))
{
proto.stats->error(Error::TLS_CRYPT_META_FAIL);
return false;
}
// virtually remove the WKc from the packet
recv.set_size(tls_frame_size);
return true;
}
bool decapsulate(Packet& pkt) // called by ProtoStackBase
{
try {
@@ -2535,6 +2764,20 @@ namespace openvpn {
{
case TLS_AUTH:
return decapsulate_tls_auth(pkt);
case TLS_CRYPT_V2:
if (pkt.opcode == CONTROL_HARD_RESET_CLIENT_V3)
{
// unwrap WKc and extract Kc (client key) from packet.
// This way we can initialize the tls-crypt per-client contexts
// (this happens on the server side only)
if (!unwrap_tls_crypt_wkc(*pkt.buf))
{
return false;
}
}
// now that the tls-crypt contexts have been initialized it is
// possible to proceed with the standard tls-crypt decapsulation
/* no break */
case TLS_CRYPT:
return decapsulate_tls_crypt(pkt);
case TLS_PLAIN:
@@ -2724,15 +2967,14 @@ namespace openvpn {
if (opcode_extract(op) != reset_op || key_id_extract(op) != 0)
return false;
const size_t head_size = 1 + ProtoSessionID::SIZE + PacketID::size(PacketID::LONG_FORM);
const size_t data_offset = head_size + tls_crypt_recv->output_hmac_size();
const size_t data_offset = TLSCryptContext::hmac_offset + tls_crypt_recv->output_hmac_size();
if (net_buf.size() < data_offset)
return false;
frame->prepare(Frame::DECRYPT_WORK, work);
// decrypt payload from 'net_buf' into 'work'
const size_t decrypt_bytes = tls_crypt_recv->decrypt(net_buf.c_data() + head_size,
const size_t decrypt_bytes = tls_crypt_recv->decrypt(net_buf.c_data() + TLSCryptContext::hmac_offset,
work.data(), work.max_size(),
net_buf.c_data() + data_offset,
net_buf.size() - data_offset);
@@ -2742,7 +2984,8 @@ namespace openvpn {
work.inc_size(decrypt_bytes);
// verify HMAC
return tls_crypt_recv->hmac_cmp(net_buf.c_data(), net_buf.size(),
return tls_crypt_recv->hmac_cmp(net_buf.c_data(),
TLSCryptContext::hmac_offset,
work.data(), work.size());
}
catch (BufferException&)
@@ -2751,11 +2994,30 @@ namespace openvpn {
return false;
}
protected:
unsigned int reset_op;
private:
TLSCryptInstance::Ptr tls_crypt_recv;
Frame::Ptr frame;
BufferAllocated work;
unsigned int reset_op;
};
class TLSCryptV2PreValidate : public TLSCryptPreValidate
{
public:
OPENVPN_SIMPLE_EXCEPTION(tls_crypt_v2_pre_validate);
TLSCryptV2PreValidate(const Config& c, const bool server)
: TLSCryptPreValidate(c, server)
{
if (!c.tls_crypt_v2_enabled())
throw tls_crypt_v2_pre_validate();
// in case of server peer, we expect the new v3 packet type
if (server)
reset_op = CONTROL_HARD_RESET_CLIENT_V3;
}
};
OPENVPN_SIMPLE_EXCEPTION(select_key_context_error);
@@ -2771,20 +3033,27 @@ namespace openvpn {
const Config& c = *config;
// tls-auth setup
if (c.tls_auth_context)
if (c.tls_crypt_v2_enabled())
{
tls_wrap_mode = TLS_AUTH;
tls_wrap_mode = TLS_CRYPT_V2;
// get HMAC size from Digest object
hmac_size = c.tls_auth_context->size();
hmac_size = c.tls_crypt_context->digest_size();
}
else if (c.tls_crypt_context)
else if (c.tls_crypt_enabled())
{
tls_wrap_mode = TLS_CRYPT;
// get HMAC size from Digest object
hmac_size = c.tls_crypt_context->digest_size();
}
else if (c.tls_auth_enabled())
{
tls_wrap_mode = TLS_AUTH;
// get HMAC size from Digest object
hmac_size = c.tls_auth_context->size();
}
else
{
tls_wrap_mode = TLS_PLAIN;
@@ -2801,6 +3070,43 @@ namespace openvpn {
return 0;
}
void reset_tls_crypt(const Config& c, const OpenVPNStaticKey& key)
{
tls_crypt_send = c.tls_crypt_context->new_obj_send();
tls_crypt_recv = c.tls_crypt_context->new_obj_recv();
// static direction assignment - not user configurable
unsigned int key_dir = is_server() ?
OpenVPNStaticKey::NORMAL :
OpenVPNStaticKey::INVERSE;
tls_crypt_send->init(key.slice(OpenVPNStaticKey::HMAC |
OpenVPNStaticKey::ENCRYPT | key_dir),
key.slice(OpenVPNStaticKey::CIPHER |
OpenVPNStaticKey::ENCRYPT | key_dir));
tls_crypt_recv->init(key.slice(OpenVPNStaticKey::HMAC |
OpenVPNStaticKey::DECRYPT | key_dir),
key.slice(OpenVPNStaticKey::CIPHER |
OpenVPNStaticKey::DECRYPT | key_dir));
}
void reset_tls_crypt_server(const Config& c)
{
//tls-crypt session key is derived later from WKc received from the client
tls_crypt_send.reset();
tls_crypt_recv.reset();
//server context is used only to process incoming WKc's
tls_crypt_server = c.tls_crypt_context->new_obj_recv();
//the server key is composed by one key set only, therefore direction and
//mode should not be specified when slicing
tls_crypt_server->init(c.tls_key.slice(OpenVPNStaticKey::HMAC),
c.tls_key.slice(OpenVPNStaticKey::CIPHER));
tls_crypt_metadata = c.tls_crypt_metadata_factory->new_obj();
}
void reset()
{
const Config& c = *config;
@@ -2820,16 +3126,19 @@ namespace openvpn {
switch (tls_wrap_mode)
{
case TLS_CRYPT:
tls_crypt_send = c.tls_crypt_context->new_obj_send();
tls_crypt_recv = c.tls_crypt_context->new_obj_recv();
// static direction assignment - not user configurable
key_dir = is_server() ? OpenVPNStaticKey::NORMAL : OpenVPNStaticKey::INVERSE;
tls_crypt_send->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::ENCRYPT | key_dir),
c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::ENCRYPT | key_dir));
tls_crypt_recv->init(c.tls_key.slice(OpenVPNStaticKey::HMAC | OpenVPNStaticKey::DECRYPT | key_dir),
c.tls_key.slice(OpenVPNStaticKey::CIPHER | OpenVPNStaticKey::DECRYPT | key_dir));
reset_tls_crypt(c, c.tls_key);
// init tls_crypt packet ID
ta_pid_send.init(PacketID::LONG_FORM);
ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
break;
case TLS_CRYPT_V2:
if (is_server())
// setup key to be used to unwrap WKc upon client connection.
// tls-crypt session key setup is postponed to reception of WKc
// from client
reset_tls_crypt_server(c);
else
reset_tls_crypt(c, c.tls_key);
// init tls_crypt packet ID
ta_pid_send.init(PacketID::LONG_FORM);
ta_pid_recv.init(c.pid_mode, PacketID::LONG_FORM, "SSL-CC", 0, stats);
@@ -2860,7 +3169,7 @@ namespace openvpn {
break;
case TLS_PLAIN:
break;
}
}
// initialize proto session ID
psid_self.randomize(*c.prng);
@@ -3199,7 +3508,8 @@ namespace openvpn {
enum TLSWrapMode {
TLS_PLAIN,
TLS_AUTH,
TLS_CRYPT
TLS_CRYPT,
TLS_CRYPT_V2
};
void reset_all()
@@ -3483,6 +3793,13 @@ namespace openvpn {
keepalive_xmit = kx;
}
void tls_crypt_append_wkc(BufferAllocated& dst)
{
if (!config->wkc.defined())
throw proto_error("Client Key Wrapper undefined");
dst.append(config->wkc);
}
// BEGIN ProtoContext data members
Config::Ptr config;
@@ -3506,6 +3823,9 @@ namespace openvpn {
TLSCryptInstance::Ptr tls_crypt_send;
TLSCryptInstance::Ptr tls_crypt_recv;
TLSCryptInstance::Ptr tls_crypt_server;
TLSCryptMetadata::Ptr tls_crypt_metadata;
PacketIDSend ta_pid_send;
PacketIDReceive ta_pid_recv;

View File

@@ -26,6 +26,7 @@
#include <openvpn/openssl/crypto/api.hpp>
#include <openvpn/openssl/ssl/sslctx.hpp>
#include <openvpn/openssl/util/rand.hpp>
#include <openvpn/openssl/util/pem.hpp>
#endif
#ifdef USE_APPLE_SSL
@@ -46,6 +47,7 @@
#ifdef OPENVPN_PLATFORM_UWP
#include <openvpn/mbedtls/util/uwprand.hpp>
#endif
#include <openvpn/mbedtls/util/pem.hpp>
#endif
#ifdef USE_MBEDTLS_APPLE_HYBRID
@@ -69,6 +71,7 @@ namespace openvpn {
#else
typedef MbedTLSRandom RandomAPI;
#endif
typedef MbedTLSPEM PEMAPI;
#elif defined(USE_MBEDTLS_APPLE_HYBRID)
// Uses Apple framework for CryptoAPI and MbedTLS for SSLAPI and RandomAPI
#define SSL_LIB_NAME "MbedTLSAppleHybrid"
@@ -85,6 +88,7 @@ namespace openvpn {
typedef OpenSSLCryptoAPI CryptoAPI;
typedef OpenSSLContext SSLAPI;
typedef OpenSSLRandom RandomAPI;
typedef OpenSSLPEM PEMAPI;
#else
#error no SSL library defined
#endif

View File

@@ -0,0 +1,78 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2017 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <openvpn/time/asiotimer.hpp>
// AsioTimerSafe is like AsioTimer but with an epoch counter
// that allows a handler to determine if it is the most recent
// handler to be queued.
namespace openvpn {
class AsioTimerSafe
{
public:
typedef std::size_t epoch_t;
AsioTimerSafe(openvpn_io::io_context& io_context)
: timer_(io_context)
{
}
std::size_t expires_at(const Time& t)
{
++epoch_;
return timer_.expires_at(t);
}
std::size_t expires_after(const Time::Duration& d)
{
++epoch_;
return timer_.expires_after(d);
}
std::size_t cancel()
{
++epoch_;
return timer_.cancel();
}
epoch_t epoch() const
{
return epoch_;
}
template <typename F>
void async_wait(F&& func)
{
++epoch_;
timer_.async_wait([func=std::move(func), epoch=epoch_](const openvpn_io::error_code& error) mutable
{
func(error, epoch);
});
}
private:
AsioTimer timer_;
epoch_t epoch_ = 0;
};
}

View File

@@ -916,7 +916,7 @@ namespace openvpn {
#ifdef OPENVPN_PLATFORM_TYPE_UNIX
if (config->socket_protect)
{
if (!config->socket_protect->socket_protect(socket.native_handle()))
if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();

View File

@@ -287,7 +287,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect)
{
if (!config->socket_protect->socket_protect(socket.native_handle()))
if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();

View File

@@ -91,6 +91,8 @@ namespace openvpn {
// the keepalive parameters (in seconds).
virtual void disable_keepalive(unsigned int& keepalive_ping,
unsigned int& keepalive_timeout) = 0;
virtual ~TransportClientParent() {}
};
// Factory for client transport object.

View File

@@ -181,8 +181,7 @@ namespace openvpn {
Client(openvpn_io::io_context& io_context_arg,
ClientConfig* config_arg,
TransportClientParent* parent_arg)
: io_context(io_context_arg),
socket(io_context_arg),
: socket(io_context_arg),
config(config_arg),
parent(parent_arg),
resolver(io_context_arg),
@@ -274,7 +273,7 @@ namespace openvpn {
#if defined(OPENVPN_PLATFORM_TYPE_UNIX) || defined(OPENVPN_PLATFORM_UWP)
if (config->socket_protect)
{
if (!config->socket_protect->socket_protect(socket.native_handle()))
if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
{
config->stats->error(Error::SOCKET_PROTECT_ERROR);
stop();
@@ -321,7 +320,6 @@ namespace openvpn {
std::string server_host;
std::string server_port;
openvpn_io::io_context& io_context;
openvpn_io::ip::udp::socket socket;
ClientConfig::Ptr config;
TransportClientParent* parent;

View File

@@ -0,0 +1,150 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2018 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/ip/ipcommon.hpp>
#include <openvpn/ip/ip4.hpp>
#include <openvpn/ip/ip6.hpp>
#include <openvpn/ip/tcp.hpp>
#if OPENVPN_DEBUG_PROTO >= 2
#define OPENVPN_LOG_MSSFIX(x) OPENVPN_LOG(x)
#else
#define OPENVPN_LOG_MSSFIX(x)
#endif
namespace openvpn {
class MSSFix {
public:
static void mssfix(BufferAllocated& buf, int mss_inter)
{
if (buf.empty())
return;
switch (IPCommon::version(buf[0]))
{
case IPCommon::IPv4:
{
if (buf.length() <= sizeof(struct IPv4Header))
break;
const IPv4Header *iphdr = (const IPv4Header *)buf.c_data();
auto ipv4hlen = IPv4Header::length(iphdr->version_len);
if (iphdr->protocol == IPCommon::TCP &&
ntohs(iphdr->tot_len) == buf.length() &&
(ntohs(iphdr->frag_off) & IPv4Header::OFFMASK) == 0 &&
ipv4hlen <= buf.length() &&
buf.length() - ipv4hlen >= sizeof(struct TCPHeader))
{
TCPHeader* tcphdr = (TCPHeader*)(buf.data() + ipv4hlen);
int ip_payload_len = buf.length() - ipv4hlen;
do_mssfix(tcphdr, mss_inter - (sizeof(struct IPv4Header) + sizeof(struct TCPHeader)), ip_payload_len);
}
}
break;
case IPCommon::IPv6:
{
if (buf.length() <= sizeof(struct IPv6Header))
break;
const IPv6Header *iphdr = (const IPv6Header *)buf.c_data();
if (buf.length() != ntohs(iphdr->payload_len) + sizeof(struct IPv6Header))
break;
/* follow header chain until we reach final header, then check for TCP
*
* An IPv6 packet could, theoretically, have a chain of multiple headers
* before the final header (TCP, UDP, ...), so we'd need to walk that
* chain (see RFC 2460 and RFC 6564 for details).
*
* In practice, "most typically used" extention headers (AH, routing,
* fragment, mobility) are very unlikely to be seen inside an OpenVPN
* tun, so for now, we only handle the case of "single next header = TCP"
*/
if (iphdr->nexthdr != IPCommon::TCP)
break;
/* skip IPv6 header (40 bytes),
* verify remainder is large enough to contain a full TCP header
*/
int payload_len = buf.length() - sizeof(struct IPv6Header);
if (payload_len >= (int) sizeof(struct TCPHeader))
{
TCPHeader *tcphdr = (TCPHeader *)(buf.data() + sizeof(struct IPv6Header));
do_mssfix(tcphdr, mss_inter - (sizeof(struct IPv6Header) + sizeof(struct TCPHeader)),
payload_len);
}
}
break;
}
}
private:
static void do_mssfix(TCPHeader *tcphdr, int max_mss, int ip_payload_len)
{
if ((tcphdr->flags & TCPHeader::FLAG_SYN) == 0)
return;
int tcphlen = TCPHeader::length(tcphdr->doff_res);
if (tcphlen <= (int) sizeof(struct TCPHeader) || tcphlen > ip_payload_len)
return;
int olen, optlen; // length of options field and Option-Length
uint8_t *opt; // option type
for (olen = tcphlen - sizeof(struct TCPHeader), opt = (uint8_t *)(tcphdr + 1);
olen > 1;
olen -= optlen, opt += optlen)
{
if (*opt == TCPHeader::OPT_EOL)
break;
else if (*opt == TCPHeader::OPT_NOP)
optlen = 1;
else
{
optlen = *(opt + 1);
if (optlen <= 0 || optlen > olen)
break;
if ((*opt == TCPHeader::OPT_MAXSEG) && (optlen == TCPHeader::OPTLEN_MAXSEG))
{
uint16_t mssval = (opt[2] << 8) + opt[3];
if (mssval > max_mss)
{
OPENVPN_LOG_MSSFIX("MTU MSS " << mssval << " -> " << max_mss);
int accumulate = htons(mssval);
opt[2] = (max_mss >> 8) & 0xff;
opt[3] = max_mss & 0xff;
accumulate -= htons(max_mss);
tcp_adjust_checksum(accumulate, tcphdr->check);
}
}
}
}
}
};
}

View File

@@ -22,6 +22,7 @@
#ifndef OPENVPN_TRANSPORT_SOCKET_PROTECT_H
#define OPENVPN_TRANSPORT_SOCKET_PROTECT_H
#include <openvpn/addr/ip.hpp>
#ifdef OPENVPN_PLATFORM_UWP
#include <openvpn/transport/uwp_socket_protect.hpp>
#endif
@@ -33,7 +34,7 @@ namespace openvpn {
// the socket from being routed into the VPN tunnel.
class BaseSocketProtect {
public:
virtual bool socket_protect(int socket) = 0;
virtual bool socket_protect(int socket, IP::Addr endpoint) = 0;
};
#ifdef OPENVPN_PLATFORM_UWP

View File

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

View File

@@ -485,7 +485,7 @@ namespace openvpn {
const Option& o = opt[*i];
try {
const std::string& type = o.get(1, 64);
if (type == "DNS")
if (type == "DNS" || type == "DNS6")
{
o.exact_args(3);
const IP::Addr ip = IP::Addr::from_string(o.get(2, 256), "dns-server-ip");

View File

@@ -0,0 +1,917 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2018 OpenVPN Inc.
// Copyright (C) 2018 Antonio Quartulli <antonio@openvpn.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <openvpn/addr/ip.hpp>
#include <openvpn/addr/ipv4.hpp>
#include <openvpn/addr/ipv6.hpp>
#include <openvpn/addr/route.hpp>
#ifdef DEBUG_RTNL
#define OPENVPN_LOG_RTNL(_x) OPENVPN_LOG(_x)
#else
#define OPENVPN_LOG_RTNL(_x)
#endif
namespace openvpn {
namespace TunNetlink {
#define SNDBUF_SIZE (1024 * 2)
#define RCVBUF_SIZE (1024 * 4)
#define SITNL_ADDATTR(_msg, _max_size, _attr, _data, _size) \
{ \
if (sitnl_addattr(_msg, _max_size, _attr, _data, _size) < 0)\
{ \
goto err; \
} \
}
#define NLMSG_TAIL(nmsg) \
((struct rtattr *)(((uint8_t *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
/* this class contains only static members */
class SITNL
{
private:
/**
* Link state request message
*/
struct sitnl_link_req
{
struct nlmsghdr n;
struct ifinfomsg i;
char buf[256];
};
/**
* Address request message
*/
struct sitnl_addr_req
{
struct nlmsghdr n;
struct ifaddrmsg i;
char buf[256];
};
/**
* Route request message
*/
struct sitnl_route_req
{
struct nlmsghdr n;
struct rtmsg r;
char buf[256];
};
typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *msg, void *arg);
/**
* Helper function used to easily add attributes to a rtnl message
*/
static int
sitnl_addattr(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen)
{
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen)
{
OPENVPN_LOG(__func__ << ": rtnl: message exceeded bound of " << maxlen);
return -EMSGSIZE;
}
rta = NLMSG_TAIL(n);
rta->rta_type = type;
rta->rta_len = len;
if (!data)
{
memset(RTA_DATA(rta), 0, alen);
}
else
{
memcpy(RTA_DATA(rta), data, alen);
}
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0;
}
/**
* Open RTNL socket
*/
static int
sitnl_socket(void)
{
int sndbuf = SNDBUF_SIZE;
int rcvbuf = RCVBUF_SIZE;
int fd;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (fd < 0)
{
OPENVPN_LOG(__func__ << ": cannot open netlink socket");
return fd;
}
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0)
{
OPENVPN_LOG(__func__ << ": SO_SNDBUF");
close(fd);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0)
{
OPENVPN_LOG(__func__ << ": SO_RCVBUF");
close(fd);
return -1;
}
return fd;
}
/**
* Bind socket to Netlink subsystem
*/
static int
sitnl_bind(int fd, uint32_t groups)
{
socklen_t addr_len;
struct sockaddr_nl local = { };
local.nl_family = AF_NETLINK;
local.nl_groups = groups;
if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
{
OPENVPN_LOG(__func__ << ": cannot bind netlink socket");
return -errno;
}
addr_len = sizeof(local);
if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0)
{
OPENVPN_LOG(__func__ << ": cannot getsockname");
return -errno;
}
if (addr_len != sizeof(local))
{
OPENVPN_LOG(__func__ << ": wrong address length " << addr_len);
return -EINVAL;
}
if (local.nl_family != AF_NETLINK)
{
OPENVPN_LOG(__func__ << ": wrong address family " << local.nl_family);
return -EINVAL;
}
return 0;
}
/**
* Send Netlink message and run callback on reply (if specified)
*/
static int
sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups,
sitnl_parse_reply_cb cb, void *arg_cb)
{
int len, rem_len, fd, ret, rcv_len;
struct sockaddr_nl nladdr = { };
struct nlmsgerr *err;
struct nlmsghdr *h;
unsigned int seq;
char buf[1024 * 16];
struct iovec iov =
{
.iov_base = payload,
.iov_len = payload->nlmsg_len,
};
struct msghdr nlmsg =
{
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = peer;
nladdr.nl_groups = groups;
payload->nlmsg_seq = seq = time(NULL);
/* no need to send reply */
if (!cb)
{
payload->nlmsg_flags |= NLM_F_ACK;
}
fd = sitnl_socket();
if (fd < 0)
{
OPENVPN_LOG(__func__ << ": can't open rtnl socket");
return -errno;
}
ret = sitnl_bind(fd, 0);
if (ret < 0)
{
OPENVPN_LOG(__func__ << ": can't bind rtnl socket");
ret = -errno;
goto out;
}
ret = sendmsg(fd, &nlmsg, 0);
if (ret < 0)
{
OPENVPN_LOG(__func__ << ": rtnl: error on sendmsg()");
ret = -errno;
goto out;
}
/* prepare buffer to store RTNL replies */
memset(buf, 0, sizeof(buf));
iov.iov_base = buf;
while (1)
{
/*
* iov_len is modified by recvmsg(), therefore has to be initialized before
* using it again
*/
OPENVPN_LOG_RTNL(__func__ << ": checking for received messages");
iov.iov_len = sizeof(buf);
rcv_len = recvmsg(fd, &nlmsg, 0);
OPENVPN_LOG_RTNL(__func__ << ": rtnl: received " << rcv_len << " bytes");
if (rcv_len < 0)
{
if ((errno == EINTR) || (errno == EAGAIN))
{
OPENVPN_LOG(__func__ << ": interrupted call");
continue;
}
OPENVPN_LOG(__func__ << ": rtnl: error on recvmsg()");
ret = -errno;
goto out;
}
if (rcv_len == 0)
{
OPENVPN_LOG(__func__ << ": rtnl: socket reached unexpected EOF");
ret = -EIO;
goto out;
}
if (nlmsg.msg_namelen != sizeof(nladdr))
{
OPENVPN_LOG(__func__ << ": sender address length: "
<< nlmsg.msg_namelen << " (expected " << sizeof(nladdr)
<< ")");
ret = -EIO;
goto out;
}
h = (struct nlmsghdr *)buf;
while (rcv_len >= (int)sizeof(*h))
{
len = h->nlmsg_len;
rem_len = len - sizeof(*h);
if ((rem_len < 0) || (len > rcv_len))
{
if (nlmsg.msg_flags & MSG_TRUNC)
{
OPENVPN_LOG(__func__ << ": truncated message");
ret = -EIO;
goto out;
}
OPENVPN_LOG(__func__ << ": malformed message: len=" << len);
ret = -EIO;
goto out;
}
if (h->nlmsg_type == NLMSG_ERROR)
{
err = (struct nlmsgerr *)NLMSG_DATA(h);
if (rem_len < (int)sizeof(struct nlmsgerr))
{
OPENVPN_LOG(__func__ << ": ERROR truncated");
ret = -EIO;
}
else
{
if (!err->error)
{
ret = 0;
if (cb)
ret = cb(h, arg_cb);
}
else
{
OPENVPN_LOG(__func__ << ": rtnl: generic error: "
<< strerror(-err->error)
<< " (" << err->error << ")");
ret = err->error;
}
}
goto out;
}
if (cb)
{
ret = cb(h, arg_cb);
goto out;
}
else
{
OPENVPN_LOG(__func__ << ": RTNL: unexpected reply");
}
rcv_len -= NLMSG_ALIGN(len);
h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
}
if (nlmsg.msg_flags & MSG_TRUNC)
{
OPENVPN_LOG(__func__ << ": message truncated");
continue;
}
if (rcv_len)
{
OPENVPN_LOG(__func__ << ": rtnl: " << rcv_len
<< " not parsed bytes");
ret = -1;
goto out;
}
}
out:
close(fd);
return ret;
}
/* store the route entry resulting from the query */
typedef struct
{
sa_family_t family;
IP::Addr gw;
std::string iface;
} route_res_t;
static int
sitnl_route_save(struct nlmsghdr *n, void *arg)
{
route_res_t *res = (route_res_t *)arg;
struct rtmsg *r = (struct rtmsg *)NLMSG_DATA(n);
struct rtattr *rta = RTM_RTA(r);
int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
int ifindex = 0;
while (RTA_OK(rta, len))
{
switch (rta->rta_type)
{
case RTA_OIF:
/* route interface */
ifindex = *(unsigned int *)RTA_DATA(rta);
break;
case RTA_DST:
/* route prefix */
RTA_DATA(rta);
break;
case RTA_GATEWAY:
/* GW for the route */
{
const unsigned char *bytestr = (unsigned char *)RTA_DATA(rta);
switch (res->family)
{
case AF_INET:
res->gw = IP::Addr::from_ipv4(IPv4::Addr::from_bytes_net(bytestr));
break;
case AF_INET6:
res->gw = IP::Addr::from_ipv6(IPv6::Addr::from_byte_string(bytestr));
break;
}
}
break;
}
rta = RTA_NEXT(rta, len);
}
if (ifindex > 0)
{
char iface[IFNAMSIZ];
if (!if_indextoname(ifindex, iface))
{
OPENVPN_LOG(__func__ << ": rtnl: can't get ifname for index "
<< ifindex);
return -1;
}
res->iface = iface;
}
return 0;
}
static int
sitnl_route_best_gw(const IP::Route& route, IP::Addr& best_gw,
std::string& best_iface)
{
struct sitnl_route_req req = { };
route_res_t res;
int ret = -EINVAL;
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
req.n.nlmsg_type = RTM_GETROUTE;
req.n.nlmsg_flags = NLM_F_REQUEST;
res.family = req.r.rtm_family = route.addr.family();
req.r.rtm_dst_len = route.prefix_len;
if (route.addr.family() == AF_INET)
{
req.n.nlmsg_flags |= NLM_F_DUMP;
}
{
unsigned char bytestr[IP::Addr::V6_SIZE / 8];
route.addr.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, bytestr,
route.addr.size_bytes());
}
ret = sitnl_send(&req.n, 0, 0, sitnl_route_save, &res);
if (ret >= 0)
{
/* save result in output variables */
best_gw = std::move(res.gw);
best_iface = std::move(res.iface);
OPENVPN_LOG(__func__ << " result: via " << best_gw << " dev " << best_iface);
}
else
{
OPENVPN_LOG(__func__ << ": failed to retrieve route, err=" << ret);
}
err:
return ret;
}
static int
sitnl_addr_set(const int cmd, const uint32_t flags, const std::string& iface,
const IP::Addr& local, const IP::Addr& remote, int prefixlen,
const IP::Addr& broadcast)
{
struct sitnl_addr_req req = { };
int ret = -EINVAL;
if (iface.empty())
{
OPENVPN_LOG(__func__ << ": passed empty interface");
return -EINVAL;
}
if (local.unspecified())
{
OPENVPN_LOG(__func__ << ": passed zero IP address");
return -EINVAL;
}
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
req.n.nlmsg_type = cmd;
req.n.nlmsg_flags = NLM_F_REQUEST | flags;
req.i.ifa_family = local.family();
req.i.ifa_index = if_nametoindex(iface.c_str());
if (req.i.ifa_index == 0)
{
OPENVPN_LOG(__func__ << ": cannot get ifindex for " << iface << " "
<< strerror(errno));
return -ENOENT;
}
/* if no prefixlen has been specified, assume host address */
if (prefixlen == 0)
{
prefixlen = local.size();
}
req.i.ifa_prefixlen = prefixlen;
{
unsigned char bytestr[IP::Addr::V6_SIZE / 8];
local.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), IFA_LOCAL, bytestr, local.size_bytes());
if (remote.specified())
{
remote.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), IFA_ADDRESS, bytestr, remote.size_bytes());
}
if (broadcast.specified())
{
broadcast.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), IFA_BROADCAST, bytestr, broadcast.size_bytes());
}
}
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
if ((ret < 0) && (errno == EEXIST))
{
ret = 0;
}
err:
return ret;
}
static int
sitnl_addr_ptp_add(const std::string& iface, const IP::Addr& local,
const IP::Addr& remote)
{
return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, iface,
local, remote, 0,
IP::Addr::from_zero(local.version()));
}
static int
sitnl_addr_ptp_del(const std::string& iface, const IP::Addr& local)
{
return sitnl_addr_set(RTM_DELADDR, 0, iface, local,
IP::Addr::from_zero(local.version()),
0, IP::Addr::from_zero(local.version()));
}
static int
sitnl_route_set(const int cmd, const uint32_t flags,
const std::string& iface, const IP::Route& route,
const IP::Addr& gw, const enum rt_class_t table,
const int metric, const enum rt_scope_t scope,
const int protocol, const int type)
{
struct sitnl_route_req req = { };
int ret = -1;
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
req.n.nlmsg_type = cmd;
req.n.nlmsg_flags = NLM_F_REQUEST | flags;
req.r.rtm_family = route.addr.family();
req.r.rtm_scope = scope;
req.r.rtm_protocol = protocol;
req.r.rtm_type = type;
req.r.rtm_dst_len = route.prefix_len;
if (table < 256)
{
req.r.rtm_table = table;
}
else
{
req.r.rtm_table = RT_TABLE_UNSPEC;
SITNL_ADDATTR(&req.n, sizeof(req), RTA_TABLE, &table, 4);
}
{
unsigned char bytestr[IP::Addr::V6_SIZE / 8];
route.addr.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, bytestr, route.addr.size_bytes());
if (gw.specified())
{
gw.to_byte_string_variable(bytestr);
SITNL_ADDATTR(&req.n, sizeof(req), RTA_GATEWAY, bytestr, gw.size_bytes());
}
}
if (!iface.empty())
{
int ifindex = if_nametoindex(iface.c_str());
if (ifindex == 0)
{
OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface);
return -ENOENT;
}
SITNL_ADDATTR(&req.n, sizeof(req), RTA_OIF, &ifindex, 4);
}
if (metric > 0)
{
SITNL_ADDATTR(&req.n, sizeof(req), RTA_PRIORITY, &metric, 4);
}
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
if ((ret < 0) && (errno == EEXIST))
{
ret = 0;
}
err:
return ret;
}
static int
sitnl_addr_add(const std::string& iface, const IP::Addr& addr,
int prefixlen, const IP::Addr& broadcast)
{
return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, iface,
addr, IP::Addr::from_zero(addr.version()),
prefixlen, broadcast);
}
static int
sitnl_addr_del(const std::string& iface, const IP::Addr& addr, int prefixlen)
{
return sitnl_addr_set(RTM_DELADDR, 0, iface, addr,
IP::Addr::from_zero(addr.version()), prefixlen,
IP::Addr::from_zero(addr.version()));
}
static int
sitnl_route_add(const IP::Route& route, const IP::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
return sitnl_route_set(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE, iface,
route, gw,
(enum rt_class_t)(!table ? RT_TABLE_MAIN : table),
metric, RT_SCOPE_UNIVERSE, RTPROT_BOOT, RTN_UNICAST);
}
static int
sitnl_route_del(const IP::Route& route, const IP::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
return sitnl_route_set(RTM_DELROUTE, 0, iface, route, gw,
(enum rt_class_t)(!table ? RT_TABLE_MAIN : table),
metric, RT_SCOPE_NOWHERE,
0, 0);
}
public:
static int
net_route_best_gw(const IP::Route6& route, IPv6::Addr& best_gw6,
std::string& best_iface)
{
IP::Addr best_gw;
int ret;
OPENVPN_LOG(__func__ << " query IPv6: " << route);
ret = sitnl_route_best_gw(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
best_gw, best_iface);
if (ret >= 0)
{
best_gw6 = best_gw.to_ipv6();
}
return ret;
}
static int
net_route_best_gw(const IP::Route4& route, IPv4::Addr &best_gw4,
std::string& best_iface)
{
IP::Addr best_gw;
int ret;
OPENVPN_LOG(__func__ << " query IPv4: " << route);
ret = sitnl_route_best_gw(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
best_gw, best_iface);
if (ret >= 0)
{
best_gw4 = best_gw.to_ipv4();
}
return ret;
}
static int
net_iface_up(std::string& iface, bool up)
{
struct sitnl_link_req req = { };
int ifindex;
if (iface.empty())
{
OPENVPN_LOG(__func__ << ": passed empty interface");
return -EINVAL;
}
ifindex = if_nametoindex(iface.c_str());
if (ifindex == 0)
{
OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface
<< ": " << strerror(errno));
return -ENOENT;
}
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_NEWLINK;
req.i.ifi_family = AF_PACKET;
req.i.ifi_index = ifindex;
req.i.ifi_change |= IFF_UP;
if (up)
{
req.i.ifi_flags |= IFF_UP;
}
else
{
req.i.ifi_flags &= ~IFF_UP;
}
OPENVPN_LOG(__func__ << ": set " << iface << " " << (up ? "up" : "down"));
return sitnl_send(&req.n, 0, 0, NULL, NULL);
}
static int
net_iface_mtu_set(std::string& iface, uint32_t mtu)
{
struct sitnl_link_req req = { };
int ifindex;
if (iface.empty())
{
OPENVPN_LOG(__func__ << ": passed empty interface");
return -EINVAL;
}
ifindex = if_nametoindex(iface.c_str());
if (ifindex == 0)
{
OPENVPN_LOG(__func__ << ": rtnl: cannot get ifindex for " << iface);
return -1;
}
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_NEWLINK;
req.i.ifi_family = AF_PACKET;
req.i.ifi_index = ifindex;
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
OPENVPN_LOG(__func__ << ": mtu " << mtu << " for " << iface);
err:
return sitnl_send(&req.n, 0, 0, NULL, NULL);
}
static int
net_addr_add(const std::string& iface, const IPv4::Addr& addr,
const int prefixlen, const IPv4::Addr& broadcast)
{
OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " brd "
<< broadcast << " dev " << iface);
return sitnl_addr_add(iface, IP::Addr::from_ipv4(addr), prefixlen,
IP::Addr::from_ipv4(broadcast));
}
static int
net_addr_add(const std::string& iface, const IPv6::Addr& addr,
const int prefixlen)
{
OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
return sitnl_addr_add(iface, IP::Addr::from_ipv6(addr), prefixlen,
IP::Addr::from_zero(IP::Addr::V6));
}
static int
net_addr_del(const std::string& iface, const IPv4::Addr& addr,
const int prefixlen)
{
OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
return sitnl_addr_del(iface, IP::Addr::from_ipv4(addr), prefixlen);
}
static int
net_addr_del(const std::string& iface, const IPv6::Addr& addr,
const int prefixlen)
{
OPENVPN_LOG(__func__ << ": " << addr << "/" << prefixlen << " dev " << iface);
return sitnl_addr_del(iface, IP::Addr::from_ipv6(addr), prefixlen);
}
static int
net_addr_ptp_add(const std::string& iface, const IPv4::Addr& local,
const IPv4::Addr& remote)
{
OPENVPN_LOG(__func__ << ": " << local << " peer " << remote << " dev " << iface);
return sitnl_addr_ptp_add(iface, IP::Addr::from_ipv4(local),
IP::Addr::from_ipv4(remote));
}
static int
net_addr_ptp_del(const std::string& iface, const IPv4::Addr& local,
const IPv4::Addr& remote)
{
OPENVPN_LOG(__func__ << ": " << local << " dev " << iface);
return sitnl_addr_ptp_del(iface, IP::Addr::from_ipv4(local));
}
static int
net_route_add(const IP::Route4& route, const IPv4::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
<< " table " << table << " metric " << metric);
return sitnl_route_add(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
IP::Addr::from_ipv4(gw), iface, table, metric);
}
static int
net_route_add(const IP::Route6& route, const IPv6::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
<< " table " << table << " metric " << metric);
return sitnl_route_add(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
IP::Addr::from_ipv6(gw), iface, table, metric);
}
static int
net_route_del(const IP::Route4& route, const IPv4::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
<< " table " << table << " metric " << metric);
return sitnl_route_del(IP::Route(IP::Addr::from_ipv4(route.addr), route.prefix_len),
IP::Addr::from_ipv4(gw), iface, table, metric);
}
static int
net_route_del(const IP::Route6& route, const IPv6::Addr& gw,
const std::string& iface, const uint32_t table,
const int metric)
{
OPENVPN_LOG(__func__ << ": " << route << " via " << gw << " dev " << iface
<< " table " << table << " metric " << metric);
return sitnl_route_del(IP::Route(IP::Addr::from_ipv6(route.addr), route.prefix_len),
IP::Addr::from_ipv6(gw), iface, table, metric);
}
};
}
}

View File

@@ -30,7 +30,15 @@
#include <openvpn/tun/builder/setup.hpp>
#include <openvpn/tun/tunio.hpp>
#include <openvpn/tun/persist/tunpersist.hpp>
// check if Netlink has been selected at compile time
#ifdef OPENVPN_USE_SITNL
#include <openvpn/tun/linux/client/tunnetlink.hpp>
#define TUN_LINUX TunNetlink
#else
#include <openvpn/tun/linux/client/tunsetup.hpp>
#define TUN_LINUX TunLinux
#endif
namespace openvpn {
namespace TunLinux {
@@ -114,7 +122,7 @@ namespace openvpn {
if (tun_setup_factory)
return tun_setup_factory->new_setup_obj();
else
return new TunLinux::Setup();
return new TUN_LINUX::Setup();
}
private:
@@ -129,7 +137,7 @@ namespace openvpn {
typedef Tun<Client*> TunImpl;
public:
virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&)
virtual void tun_start(const OptionList& opt, TransportClient& transcli, CryptoDCSettings&) override
{
if (!impl)
{
@@ -184,7 +192,7 @@ namespace openvpn {
tun_setup = config->new_setup_obj();
// create config object for tun setup layer
Setup::Config tsconf;
TUN_LINUX::Setup::Config tsconf;
tsconf.layer = config->tun_prop.layer;
tsconf.dev_name = config->dev_name;
tsconf.txqueuelen = config->txqueuelen;
@@ -228,12 +236,12 @@ namespace openvpn {
}
}
virtual bool tun_send(BufferAllocated& buf)
virtual bool tun_send(BufferAllocated& buf) override
{
return send(buf);
}
virtual std::string tun_name() const
virtual std::string tun_name() const override
{
if (impl)
return impl->name();
@@ -241,7 +249,7 @@ namespace openvpn {
return "UNDEF_TUN";
}
virtual std::string vpn_ip4() const
virtual std::string vpn_ip4() const override
{
if (state->vpn_ip4_addr.specified())
return state->vpn_ip4_addr.to_string();
@@ -249,7 +257,7 @@ namespace openvpn {
return "";
}
virtual std::string vpn_ip6() const
virtual std::string vpn_ip6() const override
{
if (state->vpn_ip6_addr.specified())
return state->vpn_ip6_addr.to_string();
@@ -273,11 +281,11 @@ namespace openvpn {
return "";
}
virtual void set_disconnect()
virtual void set_disconnect() override
{
}
virtual void stop() { stop_(); }
virtual void stop() override { stop_(); }
virtual ~Client() { stop_(); }
private:

View File

@@ -0,0 +1,821 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2018 OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <net/if.h>
#include <linux/if_tun.h>
#include <openvpn/netconf/linux/gwnetlink.hpp>
#include <openvpn/common/action.hpp>
#include <openvpn/tun/linux/client/sitnl.hpp>
#include <openvpn/tun/client/tunbase.hpp>
namespace openvpn {
namespace TunNetlink {
OPENVPN_EXCEPTION(tun_linux_error);
OPENVPN_EXCEPTION(tun_open_error);
OPENVPN_EXCEPTION(tun_layer_error);
OPENVPN_EXCEPTION(tun_ioctl_error);
OPENVPN_EXCEPTION(tun_fcntl_error);
OPENVPN_EXCEPTION(tun_name_error);
OPENVPN_EXCEPTION(tun_tx_queue_len_error);
OPENVPN_EXCEPTION(tun_ifconfig_error);
struct NetlinkLinkSet : public Action
{
typedef RCPtr<NetlinkLinkSet> Ptr;
NetlinkLinkSet() {}
NetlinkLinkSet(std::string dev_arg, bool up_arg, int mtu_arg)
: dev(dev_arg),
up(up_arg),
mtu(mtu_arg)
{
}
NetlinkLinkSet* copy() const
{
NetlinkLinkSet *ret = new NetlinkLinkSet;
ret->dev = dev;
ret->up = up;
ret->mtu = mtu;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkLinkSet with no interface" << std::endl;
return;
}
ret = SITNL::net_iface_mtu_set(dev, mtu);
if (ret)
{
os << "Error while executing NetlinkLinkSet " << dev << " mtu " << mtu
<< ": " << ret << std::endl;
}
ret = SITNL::net_iface_up(dev, up);
if (ret)
{
os << "Error while executing NetlinkLinkSet " << dev << " up " << up
<< ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
std::ostringstream os;
os << "netlink iface " << dev << " link set " << up << " mtu " << mtu;
return os.str();
}
std::string dev;
bool up;
int mtu;
};
struct NetlinkAddr4 : public Action
{
typedef RCPtr<NetlinkAddr4> Ptr;
NetlinkAddr4() {}
NetlinkAddr4(std::string dev_arg, IPv4::Addr& addr_arg, int prefixlen_arg,
IPv4::Addr& broadcast_arg, bool add_arg)
: dev(dev_arg),
addr(addr_arg),
prefixlen(prefixlen_arg),
broadcast(broadcast_arg),
add(add_arg)
{
}
NetlinkAddr4* copy() const
{
NetlinkAddr4 *ret = new NetlinkAddr4;
ret->dev = dev;
ret->addr = addr;
ret->prefixlen = prefixlen;
ret->broadcast = broadcast;
ret->add = add;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkAddr4 with no interface" << std::endl;
return;
}
if (add)
{
ret = SITNL::net_addr_add(dev, addr, prefixlen, broadcast);
}
else
{
ret = SITNL::net_addr_del(dev, addr, prefixlen);
}
if (ret)
{
os << "Error while executing NetlinkAddr4(add: " << add << ") "
<< dev << ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
std::ostringstream os;
os << "netlink iface " << dev << " " << (add ? "add" : "del") << " "
<< addr.to_string() << "/" << prefixlen << " broadcast "
<< broadcast.to_string();
return os.str();
}
std::string dev;
IPv4::Addr addr;
int prefixlen;
IPv4::Addr broadcast;
bool add;
};
struct NetlinkAddr6 : public Action
{
typedef RCPtr<NetlinkAddr6> Ptr;
NetlinkAddr6() {}
NetlinkAddr6(std::string dev_arg, IPv6::Addr& addr_arg, int prefixlen_arg,
bool add_arg)
: dev(dev_arg),
addr(addr_arg),
prefixlen(prefixlen_arg),
add(add_arg)
{
}
NetlinkAddr6* copy() const
{
NetlinkAddr6 *ret = new NetlinkAddr6;
ret->dev = dev;
ret->addr = addr;
ret->prefixlen = prefixlen;
ret->add = add;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkAddr6 with no interface" << std::endl;
return;
}
if (add)
{
ret = SITNL::net_addr_add(dev, addr, prefixlen);
}
else
{
ret = SITNL::net_addr_del(dev, addr, prefixlen);
}
if (ret)
{
os << "Error while executing NetlinkAddr6(add: " << add << ") "
<< dev << ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
std::ostringstream os;
os << "netlink iface " << dev << " " << (add ? "add" : "del") << " "
<< addr.to_string() << "/" << prefixlen;
return os.str();
}
std::string dev;
IPv6::Addr addr;
int prefixlen;
bool add;
};
struct NetlinkAddr4PtP : public Action
{
typedef RCPtr<NetlinkAddr4PtP> Ptr;
NetlinkAddr4PtP() {}
NetlinkAddr4PtP(std::string dev_arg, IPv4::Addr local_arg,
IPv4::Addr remote_arg, bool add_arg)
: dev(dev_arg),
local(local_arg),
remote(remote_arg),
add(add_arg)
{
}
NetlinkAddr4PtP* copy() const
{
NetlinkAddr4PtP *ret = new NetlinkAddr4PtP;
ret->dev = dev;
ret->local = local;
ret->remote = remote;
ret->add = add;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkAddr4PtP with no interface" << std::endl;
return;
}
if (add)
{
ret = SITNL::net_addr_ptp_add(dev, local, remote);
}
else
{
ret = SITNL::net_addr_ptp_del(dev, local, remote);
}
if (ret)
{
os << "Error while executing NetlinkAddr4PtP(add: " << add << ") "
<< dev << ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
return "netlink iface " + dev + " " + (add ? "add" : "del") + " ptp "
+ local.to_string() + " remote " + remote.to_string();
}
std::string dev;
IPv4::Addr local;
IPv4::Addr remote;
bool add;
};
struct NetlinkRoute4 : public Action
{
typedef RCPtr<NetlinkRoute4> Ptr;
NetlinkRoute4() {}
NetlinkRoute4(IPv4::Addr& dst_arg, int prefixlen_arg, IPv4::Addr& gw_arg,
std::string dev_arg, bool add_arg)
: route(dst_arg, prefixlen_arg),
gw(gw_arg),
dev(dev_arg),
add(add_arg)
{
}
NetlinkRoute4* copy() const
{
NetlinkRoute4 *ret = new NetlinkRoute4;
ret->route = route;
ret->gw = gw;
ret->dev = dev;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkRoute4 with no interface" << std::endl;
return;
}
if (add)
{
ret = SITNL::net_route_add(route, gw, dev, 0, 0);
}
else
{
ret = SITNL::net_route_del(route, gw, dev, 0, 0);
}
if (ret)
{
os << "Error while executing NetlinkRoute4(add: " << add << ") "
<< dev << ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
std::ostringstream os;
os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " "
<< route << " via " << gw.to_string();
return os.str();
}
IP::Route4 route;
IPv4::Addr gw;
std::string dev;
bool add;
};
struct NetlinkRoute6 : public Action
{
typedef RCPtr<NetlinkRoute6> Ptr;
NetlinkRoute6() {}
NetlinkRoute6(IPv6::Addr& dst_arg, int prefixlen_arg, IPv6::Addr& gw_arg,
std::string dev_arg, bool add_arg)
: route(dst_arg, prefixlen_arg),
gw(gw_arg),
dev(dev_arg),
add(add_arg)
{
}
NetlinkRoute6* copy() const
{
NetlinkRoute6 *ret = new NetlinkRoute6;
ret->route = route;
ret->gw = gw;
ret->dev = dev;
return ret;
}
virtual void execute(std::ostream& os) override
{
int ret;
if (dev.empty())
{
os << "Error: can't call NetlinkRoute6 with no interface" << std::endl;
return;
}
if (add)
{
ret = SITNL::net_route_add(route, gw, dev, 0, 0);
}
else
{
ret = SITNL::net_route_del(route, gw, dev, 0, 0);
}
if (ret)
{
os << "Error while executing NetlinkRoute6(add: " << add << ") "
<< dev << ": " << ret << std::endl;
}
}
virtual std::string to_string() const override
{
std::ostringstream os;
os << "netlink route " << (add ? "add" : "del") << " dev " << dev << " "
<< route << " via " << gw.to_string();
return os.str();
}
IP::Route6 route;
IPv6::Addr gw;
std::string dev;
bool add;
};
enum { // add_del_route flags
R_IPv6=(1<<0),
R_ADD_SYS=(1<<1),
R_ADD_DCO=(1<<2),
R_ADD_ALL=R_ADD_SYS|R_ADD_DCO,
};
/*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr)
{
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO);
parse_hex(v, hexaddr);
if (v.size() != 4)
throw tun_linux_error("bad hex address");
IPv4::Addr ret = IPv4::Addr::from_bytes(v.data());
return IP::Addr::from_ipv4(ret);
}*/
inline void add_del_route(const std::string& addr_str,
const int prefix_len,
const std::string& gateway_str,
const std::string& dev,
const unsigned int flags,
std::vector<IP::Route>* rtvec,
Action::Ptr& create,
Action::Ptr& destroy)
{
if (flags & R_IPv6)
{
const IPv6::Addr addr = IPv6::Addr::from_string(addr_str);
const IPv6::Addr netmask = IPv6::Addr::netmask_from_prefix_len(prefix_len);
const IPv6::Addr net = addr & netmask;
if (flags & R_ADD_SYS)
{
// ip route add 2001:db8:1::/48 via 2001:db8:1::1
NetlinkRoute6::Ptr add(new NetlinkRoute6);
add->route.addr = net;
add->route.prefix_len = prefix_len;
add->gw = IPv6::Addr::from_string(gateway_str);
add->dev = dev;
add->add = true;
create = add;
// for the destroy command, copy the add command but replace "add" with "delete"
NetlinkRoute6::Ptr del(add->copy());
del->add = false;
destroy = del;
}
if (rtvec && (flags & R_ADD_DCO))
rtvec->emplace_back(IP::Addr::from_ipv6(net), prefix_len);
}
else
{
const IPv4::Addr addr = IPv4::Addr::from_string(addr_str);
const IPv4::Addr netmask = IPv4::Addr::netmask_from_prefix_len(prefix_len);
const IPv4::Addr net = addr & netmask;
if (flags & R_ADD_SYS)
{
// ip route add 192.0.2.128/25 via 192.0.2.1
NetlinkRoute4::Ptr add(new NetlinkRoute4);
add->route.addr = net;
add->route.prefix_len = prefix_len;
add->gw = IPv4::Addr::from_string(gateway_str);
add->dev = dev;
add->add = true;
create = add;
// for the destroy command, copy the add command but replace "add" with "delete"
NetlinkRoute4::Ptr del(add->copy());
del->add = false;
destroy = del;
}
if (rtvec && (flags & R_ADD_DCO))
rtvec->emplace_back(IP::Addr::from_ipv4(net), prefix_len);
}
}
inline void add_del_route(const std::string& addr_str,
const int prefix_len,
const std::string& gateway_str,
const std::string& dev,
const unsigned int flags,// add interface route to rtvec if defined
std::vector<IP::Route>* rtvec,
ActionList& create,
ActionList& destroy)
{
Action::Ptr c, d;
add_del_route(addr_str, prefix_len, gateway_str, dev, flags, rtvec, c, d);
create.add(c);
destroy.add(d);
}
inline void iface_up(const std::string& iface_name,
const int mtu,
ActionList& create,
ActionList& destroy)
{
{
NetlinkLinkSet::Ptr add(new NetlinkLinkSet);
add->dev = iface_name;
add->up = true;
add->mtu = mtu;
create.add(add);
// for the destroy command, copy the add command but replace "up" with "down"
NetlinkLinkSet::Ptr del(add->copy());
del->up = false;
destroy.add(del);
}
}
inline void iface_config(const std::string& iface_name,
int unit,
const TunBuilderCapture& pull,
std::vector<IP::Route>* rtvec,
ActionList& create,
ActionList& destroy)
{
// set local4 and local6 to point to IPv4/6 route configurations
const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4();
const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6();
// Set IPv4 Interface
if (local4)
{
NetlinkAddr4::Ptr add(new NetlinkAddr4);
add->addr = IPv4::Addr::from_string(local4->address);
add->prefixlen = local4->prefix_length;
add->broadcast = IPv4::Addr::from_string(local4->address)
| ~IPv4::Addr::netmask_from_prefix_len(local4->prefix_length);
add->dev = iface_name;
add->add = true;
// if (unit >= 0)
// {
// add->argv.push_back("label");
// add->argv.push_back(iface_name + ':' + openvpn::to_string(unit));
// }
create.add(add);
// for the destroy command, copy the add command but replace "add" with "delete"
NetlinkAddr4::Ptr del(add->copy());
del->add = false;
destroy.add(del);
// add interface route to rtvec if defined
add_del_route(local4->address, local4->prefix_length, local4->address, iface_name, R_ADD_DCO, rtvec, create, destroy);
}
// Set IPv6 Interface
if (local6 && !pull.block_ipv6)
{
NetlinkAddr6::Ptr add(new NetlinkAddr6);
add->addr = IPv6::Addr::from_string(local6->address);
add->prefixlen = local6->prefix_length;
add->dev = iface_name;
add->add = true;
create.add(add);
// for the destroy command, copy the add command but replace "add" with "delete"
NetlinkAddr6::Ptr del(add->copy());
del->add = false;
destroy.add(del);
// add interface route to rtvec if defined
add_del_route(local6->address, local6->prefix_length, local6->address, iface_name, R_ADD_DCO|R_IPv6, rtvec, create, destroy);
}
}
inline void tun_config(const std::string& iface_name,
const TunBuilderCapture& pull,
std::vector<IP::Route>* rtvec,
ActionList& create,
ActionList& destroy)
{
const LinuxGW46Netlink gw;
// set local4 and local6 to point to IPv4/6 route configurations
const TunBuilderCapture::RouteAddress* local4 = pull.vpn_ipv4();
const TunBuilderCapture::RouteAddress* local6 = pull.vpn_ipv6();
// configure interface
iface_up(iface_name, pull.mtu, create, destroy);
iface_config(iface_name, -1, pull, rtvec, create, destroy);
// Process Routes
{
for (const auto &route : pull.add_routes)
{
if (route.ipv6)
{
if (!pull.block_ipv6)
add_del_route(route.address, route.prefix_length, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
}
else
{
if (local4 && !local4->gateway.empty())
add_del_route(route.address, route.prefix_length, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
else
OPENVPN_LOG("ERROR: IPv4 route pushed without IPv4 ifconfig and/or route-gateway");
}
}
}
// Process exclude routes
{
for (const auto &route : pull.exclude_routes)
{
if (route.ipv6)
{
OPENVPN_LOG("NOTE: exclude IPv6 routes not supported yet"); // fixme
}
else
{
if (gw.v4.defined())
add_del_route(route.address, route.prefix_length, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy);
else
OPENVPN_LOG("NOTE: cannot determine gateway for exclude IPv4 routes");
}
}
}
// Process IPv4 redirect-gateway
if (pull.reroute_gw.ipv4)
{
// add bypass route
if (!pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL))
add_del_route(pull.remote_address.address, 32, gw.v4.addr().to_string(), gw.v4.dev(), R_ADD_SYS, rtvec, create, destroy);
add_del_route("0.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
add_del_route("128.0.0.0", 1, local4->gateway, iface_name, R_ADD_ALL, rtvec, create, destroy);
}
// Process IPv6 redirect-gateway
if (pull.reroute_gw.ipv6 && !pull.block_ipv6)
{
// add bypass route
if (pull.remote_address.ipv6 && !(pull.reroute_gw.flags & RedirectGatewayFlags::RG_LOCAL))
add_del_route(pull.remote_address.address, 128, gw.v6.addr().to_string(), gw.v6.dev(), R_ADD_SYS|R_IPv6, rtvec, create, destroy);
add_del_route("0000::", 1, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
add_del_route("8000::", 1, local6->gateway, iface_name, R_ADD_ALL|R_IPv6, rtvec, create, destroy);
}
// fixme -- Process block-ipv6
// fixme -- Handle pushed DNS servers
}
class Setup : public TunBuilderSetup::Base
{
public:
typedef RCPtr<Setup> Ptr;
struct Config : public TunBuilderSetup::Config
{
std::string iface_name;
Layer layer; // OSI layer
std::string dev_name;
int txqueuelen;
#ifdef HAVE_JSON
virtual Json::Value to_json() override
{
Json::Value root(Json::objectValue);
root["iface_name"] = Json::Value(iface_name);
root["layer"] = Json::Value(layer.str());
root["dev_name"] = Json::Value(dev_name);
root["txqueuelen"] = Json::Value(txqueuelen);
return root;
};
virtual void from_json(const Json::Value& root, const std::string& title) override
{
json::assert_dict(root, title);
json::to_string(root, iface_name, "iface_name", title);
layer = Layer::from_str(json::get_string(root, "layer", title));
json::to_string(root, dev_name, "dev_name", title);
json::to_int(root, txqueuelen, "txqueuelen", title);
}
#endif
};
virtual void destroy(std::ostream &os) override
{
// remove added routes
if (remove_cmds)
remove_cmds->execute(std::cout);
}
virtual int establish(const TunBuilderCapture& pull, // defined by TunBuilderSetup::Base
TunBuilderSetup::Config* config,
Stop* stop,
std::ostream& os) override
{
// get configuration
Config *conf = dynamic_cast<Config *>(config);
if (!conf)
throw tun_linux_error("missing config");
static const char node[] = "/dev/net/tun";
ScopedFD fd(open(node, O_RDWR));
if (!fd.defined())
OPENVPN_THROW(tun_open_error, "error opening tun device " << node << ": " << errinfo(errno));
struct ifreq ifr;
std::memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_ONE_QUEUE;
ifr.ifr_flags |= IFF_NO_PI;
if (conf->layer() == Layer::OSI_LAYER_3)
ifr.ifr_flags |= IFF_TUN;
else if (conf->layer() == Layer::OSI_LAYER_2)
ifr.ifr_flags |= IFF_TAP;
else
throw tun_layer_error("unknown OSI layer");
open_unit(conf->dev_name, ifr, fd);
if (fcntl (fd(), F_SETFL, O_NONBLOCK) < 0)
throw tun_fcntl_error(errinfo(errno));
// Set the TX send queue size
if (conf->txqueuelen)
{
struct ifreq netifr;
ScopedFD ctl_fd(socket (AF_INET, SOCK_DGRAM, 0));
if (ctl_fd.defined())
{
std::memset(&netifr, 0, sizeof(netifr));
strcpy (netifr.ifr_name, ifr.ifr_name);
netifr.ifr_qlen = conf->txqueuelen;
if (ioctl (ctl_fd(), SIOCSIFTXQLEN, (void *) &netifr) < 0)
throw tun_tx_queue_len_error(errinfo(errno));
}
else
throw tun_tx_queue_len_error(errinfo(errno));
}
conf->iface_name = ifr.ifr_name;
ActionList::Ptr add_cmds = new ActionList();
remove_cmds.reset(new ActionListReversed()); // remove commands executed in reversed order
// configure tun properties
tun_config(ifr.ifr_name, pull, nullptr, *add_cmds, *remove_cmds);
// execute commands to bring up interface
add_cmds->execute(std::cout);
return fd.release();
}
private:
void open_unit(const std::string& name, struct ifreq& ifr, ScopedFD& fd)
{
if (!name.empty())
{
const int max_units = 256;
for (int unit = 0; unit < max_units; ++unit)
{
std::string n = name;
if (unit)
n += openvpn::to_string(unit);
if (n.length() < IFNAMSIZ)
::strcpy (ifr.ifr_name, n.c_str());
else
throw tun_name_error();
if (ioctl (fd(), TUNSETIFF, (void *) &ifr) == 0)
return;
}
const int eno = errno;
OPENVPN_THROW(tun_ioctl_error, "failed to open tun device '" << name << "' after trying " << max_units << " units : " << errinfo(eno));
}
else
{
if (ioctl (fd(), TUNSETIFF, (void *) &ifr) < 0)
{
const int eno = errno;
OPENVPN_THROW(tun_ioctl_error, "failed to open tun device '" << name << "' : " << errinfo(eno));
}
}
}
ActionListReversed::Ptr remove_cmds;
};
}
} // namespace openvpn

View File

@@ -364,7 +364,7 @@ namespace openvpn {
#endif
};
virtual void destroy(std::ostream &os)
virtual void destroy(std::ostream &os) override
{
// remove added routes
if (remove_cmds)

View File

@@ -17,7 +17,7 @@ cd $DEP_DIR
rm -rf boost
mkdir boost
export LINK_MODE=static
export TARGETS="android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg"
export TARGETS="android-a8a android-a8a-dbg android-a7a android-a7a-dbg"
export SDK_PATH_SCRIPT=$O3/core/vars/android-sdk-path
$O3/core/deps/boost/build-boost
exit 0

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf lzo
mkdir lzo
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/lzo/build-lzo
done

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf minicrypto
mkdir minicrypto
for target in android android-dbg android-a7a android-a7a-dbg ; do
for target in android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/minicrypto/build-minicrypto
done

View File

@@ -18,7 +18,7 @@ mini=0
rm -rf polarssl
mkdir polarssl
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
VERBOSE=1 TARGET=$target CMAKE_TARGET=android USE_MINICRYPTO=$mini MINICRYPTO_DIR=$(pwd)/minicrypto/minicrypto-$target $O3/core/deps/polarssl/build-polarssl
mv polarssl-$target polarssl/

View File

@@ -15,31 +15,28 @@ fi
if [ -d "$SDK" ]; then
echo "Android SDK already exists at $SDK. Doing only update"
yes | $SDK/tools/bin/sdkmanager --licenses
$SDK/tools/bin/sdkmanager --update
exit 0
else
. $O3/core/deps/functions.sh
FNAME=sdk-tools-linux-3859397.zip
URL=https://dl.google.com/android/repository/${FNAME}
CSUM=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
download
cd $DEP_DIR
rm -rf android-sdk
mkdir android-sdk
. $O3/core/vars/android-sdk-path
cd $SDK
unzip $DL/$FNAME
fi
. $O3/core/deps/functions.sh
FNAME=sdk-tools-linux-3859397.zip
URL=https://dl.google.com/android/repository/${FNAME}
CSUM=444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0
download
cd $DEP_DIR
rm -rf android-sdk
mkdir android-sdk
. $O3/core/vars/android-sdk-path
cd $SDK
unzip $DL/$FNAME
yes | $SDK/tools/bin/sdkmanager --licenses
$SDK/tools/bin/sdkmanager --update
$SDK/tools/bin/sdkmanager 'build-tools;26.0.2' \
$SDK/tools/bin/sdkmanager --install 'build-tools;26.0.2' \
'ndk-bundle' \
'extras;android;m2repository' \
'patcher;v4' \

View File

@@ -15,7 +15,7 @@ cd $DEP_DIR
rm -rf snappy
mkdir snappy
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg android android-dbg ; do
for target in android-a8a android-a8a-dbg android-a7a android-a7a-dbg ; do
echo '***************' TARGET $target
TARGET=$target $O3/core/deps/snappy/build-snappy
done

View File

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

View File

@@ -242,8 +242,12 @@ fi
# Cityhash
if [ "$CITY" = "1" ]; then
LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib"
CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include"
if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/lib" ]; then
LIBDIRS="$LIBDIRS -L$DEP_DIR/cityhash/cityhash-$PLATFORM/lib"
fi
if [ -d "$DEP_DIR/cityhash/cityhash-$PLATFORM/include" ]; then
CPPFLAGS="$CPPFLAGS -I$DEP_DIR/cityhash/cityhash-$PLATFORM/include"
fi
LIBS="$LIBS -lcityhash"
CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH"
fi

51
scripts/update-copyright Executable file
View File

@@ -0,0 +1,51 @@
#!/bin/sh
# update-copyright - Simple tool to update the Copyright lines
# in all files checked into git
#
# Copyright (C) 2018 OpenVPN Inc
# Copyright (C) 2018 David Sommerseth <davids@openvpn.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License Version 3
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program in the COPYING file.
# If not, see <http://www.gnu.org/licenses/>.
#
# Basic shell sanity
set -eu
# Simple argument control
if [ $# -ne 1 ]; then
echo "Usage: $0 <New Copyright Year>"
exit 1
fi
# Only update Copyright lines with these owners
# The 'or' operator is GNU sed specific, and must be \|
UPDATE_COPYRIGHT_LINES="OpenVPN Inc\|@openvpn\.net\\|unstable\.cc\|gmail\.com\|@fox-it\.com"
COPY_YEAR="$1"
cd "$(git rev-parse --show-toplevel)"
for file in $(git ls-files | grep -v deps/);
do
echo -n "Updating $file ..."
# The first sed operation covers 20xx-20yy copyright lines,
# The second sed operation changes 20xx -> 20xx-20yy
sed -e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) 20..-\)\(20..\)[[:blank:]]\+/\1$COPY_YEAR /" \
-e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) \)\(20..\)[[:blank:]]\+/\1\2-$COPY_YEAR /" \
-e "/$UPDATE_COPYRIGHT_LINES/s/\(Copyright (C) $COPY_YEAR\)\(-$COPY_YEAR\)[[:blank:]]\+/\1 /" \
-i $file
echo " Done"
done
echo
echo "** All files updated with $COPY_YEAR as the ending copyright year"
echo
exit 0

View File

@@ -80,6 +80,10 @@
#include <openvpn/win/console.hpp>
#endif
#ifdef USE_NETCFG
#include "client/core-client-netcfg.hpp"
#endif
using namespace openvpn;
namespace {
@@ -141,9 +145,10 @@ public:
#endif
private:
virtual bool socket_protect(int socket) override
bool socket_protect(int socket, std::string remote, bool ipv6) override
{
std::cout << "*** socket_protect " << socket << std::endl;
std::cout << "*** socket_protect " << socket << " "
<< remote << std::endl;
return true;
}
@@ -910,7 +915,13 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
}
else
{
#if defined(USE_NETCFG)
DBus conn(G_BUS_TYPE_SYSTEM);
conn.Connect();
NetCfgTunBuilder<Client> client(conn.GetConnection());
#else
Client client;
#endif
const ClientAPI::EvalConfig eval = client.eval_config(config);
if (eval.error)
OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message);

View File

@@ -15,6 +15,7 @@ GCC_EXTRA="$GCC_EXTRA -DOPENVPN_SHOW_SESSION_TOKEN"
[ "$BS64" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_BS64_DATA_LIMIT=2500000"
[ "$ROVER" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_REMOTE_OVERRIDE"
[ "$TLS" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_TLS_LINK"
[ "$SITNL" = "1" ] && GCC_EXTRA="$GCC_EXTRA -DOPENVPN_USE_SITNL"
if [ "$AGENT" = "1" ]; then
GCC_EXTRA="$GCC_EXTRA -DOPENVPN_COMMAND_AGENT"
fi
@@ -23,9 +24,9 @@ export GCC_EXTRA
# determine platform
if [ "$(uname)" == "Darwin" ]; then
export PROF=osx64
export PROF=${PROF:-osx64}
elif [ "$(uname)" == "Linux" ]; then
export PROF=linux
export PROF=${PROF:-linux}
else
echo this script only knows how to build on Mac OS or Linux
fi

View File

@@ -41,7 +41,8 @@
#if !defined(USE_TLS_AUTH) && !defined(USE_TLS_CRYPT)
//#define USE_TLS_AUTH
#define USE_TLS_CRYPT
//#define USE_TLS_CRYPT
#define USE_TLS_CRYPT_V2
#endif
#define OPENVPN_INSTRUMENTATION
@@ -834,6 +835,8 @@ int test(const int thread_num)
const std::string server_key = read_text("server.key");
const std::string dh_pem = read_text("dh.pem");
const std::string tls_auth_key = read_text("tls-auth.key");
const std::string tls_crypt_v2_server_key = read_text("tls-crypt-v2-server.key");
const std::string tls_crypt_v2_client_key = read_text("tls-crypt-v2-client.key");
// client config
ClientSSLAPI::Config::Ptr cc(new ClientSSLAPI::Config());
@@ -888,6 +891,17 @@ int test(const int thread_num)
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
cp->tls_key.parse(tls_auth_key);
cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
#endif
#ifdef USE_TLS_CRYPT_V2
cp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
cp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
{
TLSCryptV2ClientKey tls_crypt_v2_key(cp->tls_crypt_context);
tls_crypt_v2_key.parse(tls_crypt_v2_client_key);
tls_crypt_v2_key.extract_key(cp->tls_key);
tls_crypt_v2_key.extract_wkc(cp->wkc);
}
cp->tls_crypt_v2 = true;
#endif
cp->reliable_window = 4;
cp->max_ack_list = 4;
@@ -959,10 +973,21 @@ int test(const int thread_num)
sp->set_tls_auth_digest(CryptoAlgs::lookup(PROTO_DIGEST));
sp->key_direction = 1;
#endif
#ifdef USE_TLS_CRYPT
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ServerCryptoAPI>());
#if defined(USE_TLS_CRYPT)
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
sp->tls_key.parse(tls_auth_key);
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
#endif
#ifdef USE_TLS_CRYPT_V2
sp->tls_crypt_factory.reset(new CryptoTLSCryptFactory<ClientCryptoAPI>());
{
TLSCryptV2ServerKey tls_crypt_v2_key;
tls_crypt_v2_key.parse(tls_crypt_v2_server_key);
tls_crypt_v2_key.extract_key(sp->tls_key);
}
sp->set_tls_crypt_algs(CryptoAlgs::lookup("SHA256"), CryptoAlgs::lookup("AES-256-CTR"));
sp->tls_crypt_metadata_factory.reset(new CryptoTLSCryptMetadataFactory());
sp->tls_crypt_v2 = true;
#endif
sp->reliable_window = 4;
sp->max_ack_list = 4;

View File

@@ -0,0 +1,14 @@
-----BEGIN OpenVPN tls-crypt-v2 client key-----
fxgWlYpYT1H8ZCW3/139Ip6WSAa2QQZUu64N/x3g7RzhYuaInPRpP9GLpeDpj/PP
MOa0LuvbIr9Wm6V4+WUO+R8hOdfIMwtBlRleMDedFNRD5h1DCpoDdpgr5CxaPyqO
H6eCvNP7POmqdGJyo9L6H9ndyetQp4r/8wXeYWSkcJKsIJsmyBqRzuODTENGYCqG
FN3+XcUrEMYUyvb/c8NqDVQ6xpwc9+6N7840encSMZPYCq6o8J1QXZJ8sMoBEPa1
gVtLCsPXp2oTs1h82NBpxO8BNPNFz1xIG+2Zy1NpU8PONnr0rtCRPNU7ejsG+p2I
vRDt3VOf+3aD2eVFesR4NAWYTZlxg3eLG4zD/xSiGblBltbB/7qGPxgK6WOP2XD/
V0Yh+TruX2vo4xjEXqV1umTx9K8u6nvaC8uv/72NsvPWkuAOEpY6qpDrqiya+zod
zjrlKdLmftaTEMGURDIjooNygFOAania7UhLWOjhnzZFntLHoYmskF0C7om4CqPR
dhf1OuyaD436yQVdt3t/8sjBGuY4hQZ3PuMKDEsHEzmq8bYwfmDf3U8IsK39NbXO
Bh7Q3Gxxy0vTP2TRsGUbePh5ZveVtCJGe79tjtveLdEVdh+TsMB2xo/ZLFfjDPOx
6xvj5xKQtyou5YawuniHn5nrDWbyARQDTmVl7a5w5HvK3SbuVDrJsuLiRohfKyah
M17SAY5reFev6+piR+zT64zwTYdU20i28gEr
-----END OpenVPN tls-crypt-v2 client key-----

View File

@@ -0,0 +1,5 @@
-----BEGIN OpenVPN tls-crypt-v2 server key-----
hn6VWraZG0o64iPI7faGYkwTMajjqhXqG2kC1X19jCl+aXhWPSgmDbRCT/pSfjLZ
a2pKXP6DGdi3nuINKuPw4655AcuMaBe4b45+zJz5xk92NnNosLaTsanXtjfBNOK5
S/M1f4cLZViVsJTDSMcINK/RCclWVK+IFi//CThZQM8=
-----END OpenVPN tls-crypt-v2 server key-----

View File

@@ -1,143 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid>
<RootNamespace>unittests</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="test_log.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{18446924-20CC-4EB7-B639-A76C1422E5C2}</ProjectGuid>
<RootNamespace>unittests</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Debug\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_CORE);$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_TAP_WINDOWS)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(GTEST_ROOT)\msvc\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_BUILD)\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\include;$(OVPN3_ROOT)\deps\amd64\lz4\lib;$(GTEST_ROOT)\googletest\include;$(OVPN3_ROOT)\core;$(OVPN3_ROOT)\deps\amd64\asio\asio\include;$(OVPN3_ROOT)\deps\amd64\tap-windows\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;OPENVPN_FORCE_TUN_NULL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>lz4.lib;mbedtls.lib;Iphlpapi.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OVPN3_ROOT)\deps\amd64\mbedtls\library;$(GTEST_ROOT)\googlemock\gtest\Release\;%(AdditionalLibraryDirectories);$(OVPN3_ROOT)\deps\amd64\lz4\lib</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="test_log.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,15 +0,0 @@
[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android
export PLATFORM=android
export ABI=armeabi
export DEBUG_BUILD=0
export OTHER_COMPILER_FLAGS=""
export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm
export PLATFORM_FLAGS="-march=armv5te --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"
[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH"
export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH"

View File

@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm
export PLATFORM_FLAGS="-D__LP32__ -D__ANDROID_API__=14 -march=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot"
export PLATFORM_FLAGS="-D__LP32__ -march=armv7-a -mthumb -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"

View File

@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm64
export PLATFORM_FLAGS="-D__ANDROID_API__=21 -march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot"
export PLATFORM_FLAGS="-march=armv8-a -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/aarch64-linux-android-g++"
export GCC_CMD="$TC/bin/aarch64-linux-android-gcc"

View File

@@ -1,15 +0,0 @@
[ -z "$DEP_DIR" ] && export DEP_DIR=$HOME/src/android
export PLATFORM=android-dbg
export ABI=armeabi
export DEBUG_BUILD=1
export OTHER_COMPILER_FLAGS="-g"
export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O0"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-arm
export PLATFORM_FLAGS="-march=armv5te --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/arm-linux-androideabi-g++"
export GCC_CMD="$TC/bin/arm-linux-androideabi-gcc"
[ -z "$VARS_SAVE_PATH" ] && VARS_SAVE_PATH="$PATH"
export PATH="$TC/bin:$TC/arm-linux-androideabi/bin:$VARS_SAVE_PATH"

View File

@@ -7,7 +7,7 @@ export CXX_COMPILER_FLAGS="-std=c++1y"
export LIB_OPT_LEVEL="-O3"
export LIB_FPIC="-fPIC"
export TC=$DEP_DIR/tc-x86
export PLATFORM_FLAGS="-D__LP32__ -D__ANDROID_API__=14 -march=i686 -fomit-frame-pointer --sysroot=$TC/sysroot"
export PLATFORM_FLAGS="-D__LP32__ -march=i686 -fomit-frame-pointer --sysroot=$TC/sysroot"
export GPP_CMD="$TC/bin/i686-linux-android-g++"
export GCC_CMD="$TC/bin/i686-linux-android-gcc"

View File

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

View File

@@ -1,14 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
@@ -18,9 +10,6 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test\ovpncli\cli.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\client\ovpncli.hpp" />
<ClInclude Include="..\openvpn\addr\addrlist.hpp" />
@@ -31,6 +20,8 @@
<ClInclude Include="..\openvpn\addr\ipv6.hpp" />
<ClInclude Include="..\openvpn\addr\macaddr.hpp" />
<ClInclude Include="..\openvpn\addr\pool.hpp" />
<ClInclude Include="..\openvpn\addr\quoteip.hpp" />
<ClInclude Include="..\openvpn\addr\randaddr.hpp" />
<ClInclude Include="..\openvpn\addr\range.hpp" />
<ClInclude Include="..\openvpn\addr\regex.hpp" />
<ClInclude Include="..\openvpn\addr\route.hpp" />
@@ -62,6 +53,7 @@
<ClInclude Include="..\openvpn\asio\asiocontext.hpp" />
<ClInclude Include="..\openvpn\asio\asioerr.hpp" />
<ClInclude Include="..\openvpn\asio\asiopolysock.hpp" />
<ClInclude Include="..\openvpn\asio\asioresolverres.hpp" />
<ClInclude Include="..\openvpn\asio\asiosignal.hpp" />
<ClInclude Include="..\openvpn\asio\asiostop.hpp" />
<ClInclude Include="..\openvpn\asio\asiowork.hpp" />
@@ -81,6 +73,7 @@
<ClInclude Include="..\openvpn\buffer\bufread.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstr.hpp" />
<ClInclude Include="..\openvpn\buffer\bufstream.hpp" />
<ClInclude Include="..\openvpn\buffer\lz4.hpp" />
<ClInclude Include="..\openvpn\buffer\memq.hpp" />
<ClInclude Include="..\openvpn\buffer\safestr.hpp" />
<ClInclude Include="..\openvpn\buffer\zlib.hpp" />
@@ -101,12 +94,14 @@
<ClInclude Include="..\openvpn\common\abort.hpp" />
<ClInclude Include="..\openvpn\common\action.hpp" />
<ClInclude Include="..\openvpn\common\actionthread.hpp" />
<ClInclude Include="..\openvpn\common\appversion.hpp" />
<ClInclude Include="..\openvpn\common\arch.hpp" />
<ClInclude Include="..\openvpn\common\argv.hpp" />
<ClInclude Include="..\openvpn\common\arraysize.hpp" />
<ClInclude Include="..\openvpn\common\asyncsleep.hpp" />
<ClInclude Include="..\openvpn\common\autoreset.hpp" />
<ClInclude Include="..\openvpn\common\base64.hpp" />
<ClInclude Include="..\openvpn\common\bigmutex.hpp" />
<ClInclude Include="..\openvpn\common\binprefix.hpp" />
<ClInclude Include="..\openvpn\common\circ_list.hpp" />
<ClInclude Include="..\openvpn\common\cleanup.hpp" />
@@ -134,17 +129,19 @@
<ClInclude Include="..\openvpn\common\hostlist.hpp" />
<ClInclude Include="..\openvpn\common\hostname.hpp" />
<ClInclude Include="..\openvpn\common\hostport.hpp" />
<ClInclude Include="..\openvpn\common\inotify.hpp" />
<ClInclude Include="..\openvpn\common\jsonlib.hpp" />
<ClInclude Include="..\openvpn\common\lex.hpp" />
<ClInclude Include="..\openvpn\common\likely.hpp" />
<ClInclude Include="..\openvpn\common\link.hpp" />
<ClInclude Include="..\openvpn\common\logrotate.hpp" />
<ClInclude Include="..\openvpn\common\memneq.hpp" />
<ClInclude Include="..\openvpn\common\mode.hpp" />
<ClInclude Include="..\openvpn\common\modstat.hpp" />
<ClInclude Include="..\openvpn\common\msgwin.hpp" />
<ClInclude Include="..\openvpn\common\number.hpp" />
<ClInclude Include="..\openvpn\common\olong.hpp" />
<ClInclude Include="..\openvpn\common\options.hpp" />
<ClInclude Include="..\openvpn\common\option_error.hpp" />
<ClInclude Include="..\openvpn\common\ostream.hpp" />
<ClInclude Include="..\openvpn\common\path.hpp" />
<ClInclude Include="..\openvpn\common\peercred.hpp" />
@@ -182,6 +179,7 @@
<ClInclude Include="..\openvpn\common\usecount.hpp" />
<ClInclude Include="..\openvpn\common\usergroup.hpp" />
<ClInclude Include="..\openvpn\common\userpass.hpp" />
<ClInclude Include="..\openvpn\common\valgrind.hpp" />
<ClInclude Include="..\openvpn\common\version.hpp" />
<ClInclude Include="..\openvpn\common\waitbarrier.hpp" />
<ClInclude Include="..\openvpn\common\write.hpp" />
@@ -210,6 +208,9 @@
<ClInclude Include="..\openvpn\crypto\packet_id.hpp" />
<ClInclude Include="..\openvpn\crypto\selftest.hpp" />
<ClInclude Include="..\openvpn\crypto\static_key.hpp" />
<ClInclude Include="..\openvpn\crypto\tls_crypt.hpp" />
<ClInclude Include="..\openvpn\dco\dcocli.hpp" />
<ClInclude Include="..\openvpn\dco\ipcollbase.hpp" />
<ClInclude Include="..\openvpn\error\error.hpp" />
<ClInclude Include="..\openvpn\error\excode.hpp" />
<ClInclude Include="..\openvpn\frame\frame.hpp" />
@@ -226,6 +227,7 @@
<ClInclude Include="..\openvpn\http\urlencode.hpp" />
<ClInclude Include="..\openvpn\http\urlparm.hpp" />
<ClInclude Include="..\openvpn\http\urlparse.hpp" />
<ClInclude Include="..\openvpn\http\validate_uri.hpp" />
<ClInclude Include="..\openvpn\http\webexcept.hpp" />
<ClInclude Include="..\openvpn\init\cryptoinit.hpp" />
<ClInclude Include="..\openvpn\init\engineinit.hpp" />
@@ -233,14 +235,27 @@
<ClInclude Include="..\openvpn\io\io.hpp" />
<ClInclude Include="..\openvpn\ip\dhcp.hpp" />
<ClInclude Include="..\openvpn\ip\eth.hpp" />
<ClInclude Include="..\openvpn\ip\icmp.hpp" />
<ClInclude Include="..\openvpn\ip\ip.hpp" />
<ClInclude Include="..\openvpn\ip\icmp4.hpp" />
<ClInclude Include="..\openvpn\ip\icmp6.hpp" />
<ClInclude Include="..\openvpn\ip\ip4.hpp" />
<ClInclude Include="..\openvpn\ip\ip6.hpp" />
<ClInclude Include="..\openvpn\ip\ipcommon.hpp" />
<ClInclude Include="..\openvpn\ip\tcp.hpp" />
<ClInclude Include="..\openvpn\ip\udp.hpp" />
<ClInclude Include="..\openvpn\kovpn\kocrypto.hpp" />
<ClInclude Include="..\openvpn\kovpn\kodev.hpp" />
<ClInclude Include="..\openvpn\kovpn\korekey.hpp" />
<ClInclude Include="..\openvpn\kovpn\koroute.hpp" />
<ClInclude Include="..\openvpn\kovpn\kostats.hpp" />
<ClInclude Include="..\openvpn\kovpn\kovpn.hpp" />
<ClInclude Include="..\openvpn\legal\copyright.hpp" />
<ClInclude Include="..\openvpn\linux\core.hpp" />
<ClInclude Include="..\openvpn\linux\daemon_alive.hpp" />
<ClInclude Include="..\openvpn\linux\procfs.hpp" />
<ClInclude Include="..\openvpn\log\logbase.hpp" />
<ClInclude Include="..\openvpn\log\logbasesimple.hpp" />
<ClInclude Include="..\openvpn\log\logbasesimplemac.hpp" />
<ClInclude Include="..\openvpn\log\logdatetime.hpp" />
<ClInclude Include="..\openvpn\log\lognull.hpp" />
<ClInclude Include="..\openvpn\log\logperiod.hpp" />
<ClInclude Include="..\openvpn\log\logsimple.hpp" />
@@ -298,6 +313,7 @@
<ClInclude Include="..\openvpn\proxy\proxyauth.hpp" />
<ClInclude Include="..\openvpn\random\devurand.hpp" />
<ClInclude Include="..\openvpn\random\mtrandapi.hpp" />
<ClInclude Include="..\openvpn\random\rand2.hpp" />
<ClInclude Include="..\openvpn\random\randapi.hpp" />
<ClInclude Include="..\openvpn\random\randbytestore.hpp" />
<ClInclude Include="..\openvpn\reliable\relack.hpp" />
@@ -325,6 +341,7 @@
<ClInclude Include="..\openvpn\ssl\sslapi.hpp" />
<ClInclude Include="..\openvpn\ssl\sslchoose.hpp" />
<ClInclude Include="..\openvpn\ssl\sslconsts.hpp" />
<ClInclude Include="..\openvpn\ssl\ssllog.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsprf.hpp" />
<ClInclude Include="..\openvpn\ssl\tlsver.hpp" />
<ClInclude Include="..\openvpn\ssl\tls_cert_profile.hpp" />
@@ -332,9 +349,12 @@
<ClInclude Include="..\openvpn\time\asiotimer.hpp" />
<ClInclude Include="..\openvpn\time\coarsetime.hpp" />
<ClInclude Include="..\openvpn\time\durhelper.hpp" />
<ClInclude Include="..\openvpn\time\epoch.hpp" />
<ClInclude Include="..\openvpn\time\time.hpp" />
<ClInclude Include="..\openvpn\time\timestr.hpp" />
<ClInclude Include="..\openvpn\transport\altproxy.hpp" />
<ClInclude Include="..\openvpn\transport\client\extern\config.hpp" />
<ClInclude Include="..\openvpn\transport\client\extern\fw.hpp" />
<ClInclude Include="..\openvpn\transport\client\httpcli.hpp" />
<ClInclude Include="..\openvpn\transport\client\relay.hpp" />
<ClInclude Include="..\openvpn\transport\client\tcpcli.hpp" />
@@ -342,6 +362,7 @@
<ClInclude Include="..\openvpn\transport\client\udpcli.hpp" />
<ClInclude Include="..\openvpn\transport\dco.hpp" />
<ClInclude Include="..\openvpn\transport\gremlin.hpp" />
<ClInclude Include="..\openvpn\transport\mssfix.hpp" />
<ClInclude Include="..\openvpn\transport\mutate.hpp" />
<ClInclude Include="..\openvpn\transport\pktstream.hpp" />
<ClInclude Include="..\openvpn\transport\protocol.hpp" />
@@ -349,6 +370,8 @@
<ClInclude Include="..\openvpn\transport\server\transbase.hpp" />
<ClInclude Include="..\openvpn\transport\socket_protect.hpp" />
<ClInclude Include="..\openvpn\transport\tcplink.hpp" />
<ClInclude Include="..\openvpn\transport\tcplinkbase.hpp" />
<ClInclude Include="..\openvpn\transport\tcplinkcommon.hpp" />
<ClInclude Include="..\openvpn\transport\udplink.hpp" />
<ClInclude Include="..\openvpn\tun\builder\base.hpp" />
<ClInclude Include="..\openvpn\tun\builder\capture.hpp" />
@@ -365,13 +388,15 @@
<ClInclude Include="..\openvpn\tun\ipv6_setting.hpp" />
<ClInclude Include="..\openvpn\tun\layer.hpp" />
<ClInclude Include="..\openvpn\tun\linux\client\tuncli.hpp" />
<ClInclude Include="..\openvpn\tun\linux\tun.hpp" />
<ClInclude Include="..\openvpn\tun\linux\client\tunsetup.hpp" />
<ClInclude Include="..\openvpn\tun\mac\client\tuncli.hpp" />
<ClInclude Include="..\openvpn\tun\mac\client\tunsetup.hpp" />
<ClInclude Include="..\openvpn\tun\mac\dsdict.hpp" />
<ClInclude Include="..\openvpn\tun\mac\gwv4.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macdns_watchdog.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macgw.hpp" />
<ClInclude Include="..\openvpn\tun\mac\macproxy.hpp" />
<ClInclude Include="..\openvpn\tun\mac\tunutil.hpp" />
<ClInclude Include="..\openvpn\tun\mac\utun.hpp" />
<ClInclude Include="..\openvpn\tun\persist\tunpersist.hpp" />
@@ -402,30 +427,20 @@
<ClInclude Include="..\openvpn\win\unicode.hpp" />
<ClInclude Include="..\openvpn\win\winerr.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test\ovpncli\cli.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1F891260-2039-494F-9777-EC5166AF31BC}</ProjectGuid>
<RootNamespace>ovpn3core</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectName>cli</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
@@ -442,21 +457,6 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
@@ -476,24 +476,6 @@
<ShowProgress>NotSet</ShowProgress>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NOMINMAX;_WIN32_WINNT=0x0600;USE_ASIO;ASIO_STANDALONE;USE_MBEDTLS;HAVE_LZ4;TAP_WIN_COMPONENT_ID=tap0901;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(OVPN3_BUILD)\amd64\mbedtls\include;$(OVPN3_TAP_WINDOWS)\src;$(OVPN3_BUILD)\amd64\asio\asio\include;$(OVPN3_BUILD)\amd64\lz4\lib;$(OVPN3_CORE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(OVPN3_BUILD)\amd64\mbedtls\library;$(OVPN3_BUILD)\amd64\lz4\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>lz4.lib;mbedtls.lib;fwpuclnt.lib;ws2_32.lib;crypt32.lib;iphlpapi.lib;winmm.lib;advapi32.lib;wininet.lib;shell32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>TurnOffAllWarnings</WarningLevel>

View File

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