Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'

This commit is contained in:
Sergey Abramchuk
2020-02-24 14:43:11 +03:00
655 changed files with 146468 additions and 0 deletions
@@ -0,0 +1,99 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
// Asio TCP socket that can be configured so that open() method
// always prebinds the socket to a given local address. Useful
// for TCP clients.
#ifndef OPENVPN_ASIO_ASIOBOUNDSOCK_H
#define OPENVPN_ASIO_ASIOBOUNDSOCK_H
#include <openvpn/io/io.hpp>
#include <openvpn/addr/ip.hpp>
#include <openvpn/common/extern.hpp>
#include <openvpn/common/to_string.hpp>
namespace openvpn {
namespace AsioBoundSocket {
typedef openvpn_io::basic_stream_socket<openvpn_io::ip::tcp> SocketBase;
class Socket : public SocketBase
{
public:
explicit Socket(openvpn_io::io_context& io_context)
: SocketBase(io_context)
{
}
// if port 0, kernel will dynamically allocate free port
void bind_local(const IP::Addr& addr, const unsigned short port=0)
{
bind_local_addr = addr;
bind_local_port = port;
}
std::string to_string() const
{
std::string ret;
ret.reserve(64);
if (bind_local_addr.defined())
{
ret += "local=[";
ret += bind_local_addr.to_string();
ret += "]:";
ret += openvpn::to_string(bind_local_port);
}
try {
const std::string re = openvpn::to_string(remote_endpoint());
if (!ret.empty())
ret += ' ';
ret += "remote=";
ret += re;
}
catch (const std::exception& e)
{
}
return ret;
}
protected:
virtual void async_connect_post_open(const protocol_type& protocol, openvpn_io::error_code& ec) override
{
if (bind_local_addr.defined())
{
set_option(openvpn_io::socket_base::reuse_address(true), ec);
if (ec)
return;
bind(openvpn_io::ip::tcp::endpoint(bind_local_addr.to_asio(), bind_local_port), ec);
}
}
private:
IP::Addr bind_local_addr;
unsigned short bind_local_port = 0;
};
}
}
#endif
@@ -0,0 +1,51 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
#ifndef OPENVPN_ASIO_ASIOCONTEXT_H
#define OPENVPN_ASIO_ASIOCONTEXT_H
#include <vector>
#include <memory>
#include <mutex>
#include <openvpn/io/io.hpp>
namespace openvpn {
class AsioContextStore
{
public:
openvpn_io::io_context& new_context(int concurrency_hint)
{
openvpn_io::io_context* ioc = new openvpn_io::io_context(concurrency_hint);
{
std::lock_guard<std::mutex> lock(mutex);
contexts.emplace_back(ioc);
}
return *ioc;
}
private:
std::mutex mutex;
std::vector<std::unique_ptr<openvpn_io::io_context>> contexts;
};
}
#endif
+41
View File
@@ -0,0 +1,41 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
#ifndef OPENVPN_ASIO_ASIOERR_H
#define OPENVPN_ASIO_ASIOERR_H
#include <string>
#include <openvpn/io/io.hpp> // was: #include <asio/error_code.hpp>
namespace openvpn {
// returns a string describing an i/o error code
template <typename ErrorCode>
inline std::string errinfo(ErrorCode err)
{
openvpn_io::error_code e(err, openvpn_io::system_category());
return e.message();
}
}
#endif
@@ -0,0 +1,377 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
// Asio polymorphic socket for handling TCP
// and unix domain sockets.
#ifndef OPENVPN_ASIO_ASIOPOLYSOCK_H
#define OPENVPN_ASIO_ASIOPOLYSOCK_H
#include <openvpn/io/io.hpp>
#include <openvpn/common/platform.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/common/function.hpp>
#include <openvpn/common/to_string.hpp>
#include <openvpn/common/sockopt.hpp>
#include <openvpn/addr/ip.hpp>
#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
#include <openvpn/asio/alt_routing.hpp>
#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND)
#include <openvpn/asio/asioboundsock.hpp>
#endif
#ifdef ASIO_HAS_LOCAL_SOCKETS
#include <openvpn/common/peercred.hpp>
#endif
namespace openvpn {
namespace AsioPolySock {
// for shutdown()
enum ShutdownFlags {
SHUTDOWN_SEND = (1<<0),
SHUTDOWN_RECV = (1<<1),
};
class Base : public RC<thread_unsafe_refcount>
{
public:
typedef RCPtr<Base> Ptr;
virtual void async_send(const openvpn_io::const_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) = 0;
virtual void async_receive(const openvpn_io::mutable_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) = 0;
virtual std::string remote_endpoint_str() const = 0;
virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const = 0;
virtual void non_blocking(const bool state) = 0;
virtual void close() = 0;
virtual void shutdown(const unsigned int flags) {}
virtual void tcp_nodelay() {}
virtual void set_cloexec() {}
virtual int native_handle()
{
return -1;
}
#ifdef ASIO_HAS_LOCAL_SOCKETS
virtual bool peercreds(SockOpt::Creds& cr)
{
return false;
}
#endif
#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
virtual bool alt_routing_enabled()
{
return false;
}
#endif
virtual bool is_open() const = 0;
virtual bool is_local() const = 0;
size_t index() const { return index_; }
protected:
Base(const size_t index)
: index_(index)
{
}
private:
size_t index_;
};
struct TCP : public Base
{
typedef RCPtr<TCP> Ptr;
TCP(openvpn_io::io_context& io_context,
const size_t index)
: Base(index),
socket(io_context)
{
}
virtual void async_send(const openvpn_io::const_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
socket.async_send(buf, std::move(callback));
}
virtual void async_receive(const openvpn_io::mutable_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
socket.async_receive(buf, std::move(callback));
}
#if !defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
virtual std::string remote_endpoint_str() const override
{
try {
return "TCP " + openvpn::to_string(socket.remote_endpoint());
}
catch (const std::exception&)
{
return "TCP";
}
}
#endif
virtual bool remote_ip_port(IP::Addr& addr, unsigned int& port) const override
{
try {
addr = IP::Addr::from_asio(socket.remote_endpoint().address());
port = socket.remote_endpoint().port();
return true;
}
catch (const std::exception&)
{
return false;
}
}
virtual void non_blocking(const bool state) override
{
socket.non_blocking(state);
}
virtual void tcp_nodelay() override
{
socket.set_option(openvpn_io::ip::tcp::no_delay(true));
}
#if !defined(OPENVPN_PLATFORM_WIN)
virtual void set_cloexec() override
{
const int fd = socket.native_handle();
if (fd >= 0)
SockOpt::set_cloexec(fd);
}
#endif
virtual void shutdown(const unsigned int flags) override
{
if (flags & SHUTDOWN_SEND)
socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send);
else if (flags & SHUTDOWN_RECV)
socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive);
}
virtual void close() override
{
socket.close();
}
virtual bool is_open() const override
{
return socket.is_open();
}
virtual bool is_local() const override
{
return false;
}
virtual int native_handle() override
{
return socket.native_handle();
}
#if defined(OPENVPN_POLYSOCK_SUPPORTS_ALT_ROUTING)
virtual std::string remote_endpoint_str() const override
{
const char *proto = (socket.alt_routing_enabled() ? "TCP ALT " : "TCP ");
return proto + socket.to_string();
}
virtual bool alt_routing_enabled() override
{
return socket.alt_routing_enabled();
}
AltRouting::Socket socket;
#elif defined(OPENVPN_POLYSOCK_SUPPORTS_BIND)
AsioBoundSocket::Socket socket;
#else
openvpn_io::ip::tcp::socket socket;
#endif
};
#ifdef ASIO_HAS_LOCAL_SOCKETS
struct Unix : public Base
{
typedef RCPtr<Unix> Ptr;
Unix(openvpn_io::io_context& io_context,
const size_t index)
: Base(index),
socket(io_context)
{
}
virtual void async_send(const openvpn_io::const_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
socket.async_send(buf, std::move(callback));
}
virtual void async_receive(const openvpn_io::mutable_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
socket.async_receive(buf, std::move(callback));
}
virtual std::string remote_endpoint_str() const override
{
return "LOCAL";
}
virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override
{
return false;
}
virtual void non_blocking(const bool state) override
{
socket.non_blocking(state);
}
virtual bool peercreds(SockOpt::Creds& cr) override
{
return SockOpt::peercreds(socket.native_handle(), cr);
}
virtual void set_cloexec() override
{
const int fd = socket.native_handle();
if (fd >= 0)
SockOpt::set_cloexec(fd);
}
#if !defined(OPENVPN_PLATFORM_MAC)
// shutdown() throws "socket is not connected" exception
// on macos if another side has called close() - this behavior
// breaks communication with agent, and hence disabled
virtual void shutdown(const unsigned int flags) override
{
if (flags & SHUTDOWN_SEND)
socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_send);
else if (flags & SHUTDOWN_RECV)
socket.shutdown(openvpn_io::ip::tcp::socket::shutdown_receive);
}
#endif
virtual void close() override
{
socket.close();
}
virtual bool is_open() const override
{
return socket.is_open();
}
virtual bool is_local() const override
{
return true;
}
virtual int native_handle() override
{
return socket.native_handle();
}
openvpn_io::local::stream_protocol::socket socket;
};
#endif
#if defined(OPENVPN_PLATFORM_WIN)
struct NamedPipe : public Base
{
typedef RCPtr<NamedPipe> Ptr;
NamedPipe(openvpn_io::windows::stream_handle&& handle_arg,
const size_t index)
: Base(index),
handle(std::move(handle_arg))
{
}
virtual void async_send(const openvpn_io::const_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
handle.async_write_some(buf, std::move(callback));
}
virtual void async_receive(const openvpn_io::mutable_buffer& buf,
Function<void(const openvpn_io::error_code&, const size_t)>&& callback) override
{
handle.async_read_some(buf, std::move(callback));
}
virtual std::string remote_endpoint_str() const override
{
return "NAMED_PIPE";
}
virtual bool remote_ip_port(IP::Addr&, unsigned int&) const override
{
return false;
}
virtual void non_blocking(const bool state) override
{
}
virtual void close() override
{
handle.close();
}
virtual bool is_open() const override
{
return handle.is_open();
}
virtual bool is_local() const override
{
return true;
}
openvpn_io::windows::stream_handle handle;
};
#endif
}
}
#endif
@@ -0,0 +1,49 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012-2017 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <string>
#include <openvpn/common/to_string.hpp>
namespace openvpn {
template <class EPRANGE>
inline std::string asio_resolver_results_to_string(const EPRANGE& endpoint_range)
{
std::string ret;
ret.reserve(64);
bool first = true;
for (const auto &i : endpoint_range)
{
if (!first)
ret += ' ';
ret += '[';
ret += openvpn::to_string(i.endpoint().address());
ret += "]:";
ret += openvpn::to_string(i.endpoint().port());
first = false;
}
return ret;
}
}
@@ -0,0 +1,104 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
// A simple class that allows an arbitrary set of posix signals to be
// associated with an Asio handler.
#ifndef OPENVPN_ASIO_ASIOSIGNAL_H
#define OPENVPN_ASIO_ASIOSIGNAL_H
#include <openvpn/io/io.hpp>
#include <openvpn/common/platform.hpp>
#include <openvpn/common/rc.hpp>
namespace openvpn {
class ASIOSignals : public RC<thread_safe_refcount>
{
public:
typedef RCPtr<ASIOSignals> Ptr;
ASIOSignals(openvpn_io::io_context& io_context)
: halt(false), signals_(io_context) {}
enum {
S_SIGINT = (1<<0),
S_SIGTERM = (1<<1),
#ifndef OPENVPN_PLATFORM_WIN
S_SIGQUIT = (1<<2),
S_SIGHUP = (1<<3),
S_SIGUSR1 = (1<<4),
S_SIGUSR2 = (1<<5),
#endif
};
template <typename SignalHandler>
void register_signals(SignalHandler stop_handler, unsigned int sigmask = (S_SIGINT|S_SIGTERM))
{
if (sigmask & S_SIGINT)
signals_.add(SIGINT);
if (sigmask & S_SIGTERM)
signals_.add(SIGTERM);
#ifndef OPENVPN_PLATFORM_WIN
if (sigmask & S_SIGQUIT)
signals_.add(SIGQUIT);
if (sigmask & S_SIGHUP)
signals_.add(SIGHUP);
if (sigmask & S_SIGUSR1)
signals_.add(SIGUSR1);
if (sigmask & S_SIGUSR2)
signals_.add(SIGUSR2);
#endif
signals_.async_wait(stop_handler);
}
template <typename SignalHandler>
void register_signals_all(SignalHandler stop_handler)
{
register_signals(stop_handler,
S_SIGINT
| S_SIGTERM
#ifndef OPENVPN_PLATFORM_WIN
| S_SIGHUP
| S_SIGUSR1
| S_SIGUSR2
#endif
);
}
void cancel()
{
if (!halt)
{
halt = true;
signals_.cancel();
}
}
private:
bool halt;
openvpn_io::signal_set signals_;
};
}
#endif
@@ -0,0 +1,52 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
#ifndef OPENVPN_ASIO_ASIOSTOP_H
#define OPENVPN_ASIO_ASIOSTOP_H
#include <openvpn/io/io.hpp>
#include <openvpn/common/stop.hpp>
namespace openvpn {
class AsioStopScope : public Stop::Scope
{
public:
AsioStopScope(openvpn_io::io_context& io_context,
Stop* stop,
std::function<void()>&& method)
: Stop::Scope(stop, post_method(io_context, std::move(method)))
{
}
private:
static std::function<void()> post_method(openvpn_io::io_context& io_context, std::function<void()>&& method)
{
return [&io_context, method=std::move(method)]()
{
openvpn_io::post(io_context, std::move(method));
};
}
};
}
#endif
@@ -0,0 +1,44 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
// A null Asio unit of work, that prevents the Asio event loop from
// exiting.
#ifndef OPENVPN_ASIO_ASIOWORK_H
#define OPENVPN_ASIO_ASIOWORK_H
#include <openvpn/io/io.hpp>
namespace openvpn {
class AsioWork
{
public:
AsioWork(openvpn_io::io_context& io_context)
: work(openvpn_io::make_work_guard(io_context))
{
}
private:
openvpn_io::executor_work_guard<openvpn_io::io_context::executor_type> work;
};
}
#endif
@@ -0,0 +1,108 @@
// OpenVPN -- An application to securely tunnel IP networks
// over 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/>.
// A scoped Asio stream that is automatically closed by its destructor.
#ifndef OPENVPN_ASIO_SCOPED_ASIO_STREAM_H
#define OPENVPN_ASIO_SCOPED_ASIO_STREAM_H
#include <openvpn/common/size.hpp>
namespace openvpn {
template <typename STREAM>
class ScopedAsioStream
{
ScopedAsioStream(const ScopedAsioStream&) = delete;
ScopedAsioStream& operator=(const ScopedAsioStream&) = delete;
public:
typedef STREAM* base_type;
ScopedAsioStream() : obj_(undefined()) {}
explicit ScopedAsioStream(STREAM *obj)
: obj_(obj) {}
static STREAM* undefined() { return nullptr; }
STREAM* release()
{
STREAM* ret = obj_;
obj_ = nullptr;
//OPENVPN_LOG("**** SAS RELEASE=" << ret);
return ret;
}
static bool defined_static(STREAM* obj)
{
return obj != nullptr;
}
bool defined() const
{
return defined_static(obj_);
}
STREAM* operator()() const
{
return obj_;
}
void reset(STREAM* obj)
{
close();
obj_ = obj;
//OPENVPN_LOG("**** SAS RESET=" << obj_);
}
// unusual semantics: replace obj without closing it first
void replace(STREAM* obj)
{
//OPENVPN_LOG("**** SAS REPLACE " << obj_ << " -> " << obj);
obj_ = obj;
}
// return false if close error
bool close()
{
if (defined())
{
//OPENVPN_LOG("**** SAS CLOSE obj=" << obj_);
delete obj_;
obj_ = nullptr;
}
return true;
}
~ScopedAsioStream()
{
//OPENVPN_LOG("**** SAS DESTRUCTOR");
close();
}
private:
STREAM* obj_;
};
} // namespace openvpn
#endif