Data channel packet ids (in the formats that OpenVPN 3.x supports)
are plain 32 or 64 bit ids while control channel is a 32 bit time + 32
bit counter id. Seperate these more clearly and let CBC mode use the
same Packet ID implementation that AEAD mode uses.
Also add more unit tests related to data channel tests packets by
adapting the control channel test where applicable and add a few more
related to packet id wrapping
Signed-off-by: Arne Schwabe <arne@openvpn.net>
This mode is only relevant for old OpenVPN 2.3.x clients in CBC mode
ciphers when using kovpn. Remove the mode from PID control and move
logic to kovpn key logic.
Signed-off-by: Arne Schwabe <arne@openvpn.net>
Rename BufferAllocated --> BufferAllocatedRc
Buffer: split RC from BufferAllocated
Also make changes as needed where BufferAllocated is used
Buffer: Split allocation flags into own struct
Leaving flags in template causes each alias to have identical flags
by different names, which requires each type to pointlessly use
the nested name.
Make RC: Clean up headers buffer.hpp, make_rc.hpp
Signed-off-by: Charlie Vigue <charlie.vigue@openvpn.com>
Split the implementation of the packet counter for normal packet ID
that includes the "weird" long format for long 64 bit packet ids used
in tls-auth and tls-crypt and a simplified implementation for AEAD that
only does 32 bit and 64 bit flat counters.
Signed-off-by: Arne Schwabe <arne@openvpn.net>
Instead of passing around a number of individual argument, use a data
holder class to describe all the settings. This will also allow adding
more data channel parameters in the future (tag location, 64 bit IV)
easier. This has a slight cost of something passing more parameters
than needed.
Signed-off-by: Arne Schwabe <arne@openvpn.net>
In the code base three different syntaxes for overriding virtual member
functions could be found:
1) virtual ... override
2) virtual ...
3) ... override
This converts all of them to the third syntax, as recommended by the ISO
C++ core guidelines in C.128
Signed-off-by: Heiko Hund <heiko@openvpn.net>
The code in dco/dcocli.hpp used #if ENABLE_KOVPN, which will
fail on newer compilers if the macro is defined in a source
file. Compilers may not complain if the macro is defined on
the command line, via -D.
This type of checks should use either #ifdef or #if defined(...).
The #if conditional expects a boolean expression.
Since these code blocks also depended on #elif (also expects
a boolean expression , the defined(...) approach was chosen
throughout this file.
Signed-off-by: David Sommerseth <davids@openvpn.net>
- Used static_cast instead of direct type conversions in places where
it's safe
- Used numeric_cast where failure is possible
- Changed types of arguments and locals when practical
Signed-off-by: Charlie Vigue <charlie.vigue@openvpn.com>
With ovpn-co-v2 logic, control packets do not flow through netlink
anymore but they are sent directly via the transport socket.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
In order to avoid a useless dependency on the ovpn-dco tree, directly
include the ovpn_dco_linuc.h UAPI header in the codebase.
This is the only external requirement to build core with DCO support.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
Instead if displaying resolved family address (v4/v6),
display the one which is configured - either in ovpn profile
or config override options.
This is already the case for TCP.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
When parsing config, check DCO compatibility. Following
options break DCO compatibility:
- http-proxy
- compress
- comp-lzo
Same for config settings:
- non-preferred-algorithms
- legacy-algorithms
- proxyHost
DCO compatibility could be checked with
- bool EvalConfig::dcoCompatible
- std::string dcoIncompatibilityReason
If client nevertheless tries to connect, an exception
will be thrown:
connect error: option_error: dco_compatibility: config/options are not
compatible with dco
Fixes OVPN3-960.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This was introduced in commit
613aa6bf ("Win: support for local DNS resolvers")
but got removed by mistake in commit
fd065596 ("Merge release of OpenVPN Core library 3.6.4 to master")
Besides, this never worked for DCO, so fix that too.
Fixes OVPN3-964.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Make DCOTransportSource aware of tun stats.
Implemenent DCOTransportSource interface. Withing
stats delta callback, fetch peer stats and return delta
between last and current stats (same as in DCO Linux).
Fixes OVPN3-947.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
The same behavior is implemented in openvpn2
and openvpn3 non-dco cases.
This also fixes some reconnect issues to
openvpn2 server.
Fixes OVPN3-949.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This call is required to add bypass route, which
is required when client reconnects with seamless tunnel.
Fixes OVPN3-948
Signed-off-by: Lev Stipakov <lev@openvpn.net>
When agent-enabled client disconnects, it signals
destroy_tun event, which signals to agent that tun
has to be teared down. For dco-win, event handle is passed
to agent with /tun-open request.
Before sending /establish request, client closes previous
tun instance. Closing tun involves signaling destroy_tun event.
Event handle is closed after signaling, and here we have a problem:
- client calls /tun-open and passes event handle to agent
- client calls /establish, and before that it signals destroy_tun
event, which handle is now closed
- at some point client disconnects and signals tun_destroy event
Since event was already signaled and its handle is closed, nothing
happens and agent doesn't tear tun down. As a consequence, DNS
resolution might not work if DNS is overriden by VPN.
When client exits, agent tears tun down by failsafe logic. This doesn't
work for Connect client, which obviously doesn't exit on disconnect.
Fix this problem by avoiding signaling event between /tun-open
and /establish requests. This is done by not adding tun_setup
destructor (which signals event) to tun_persist right after /tun-open
call. There is nothing to tear down at that point yet since tun is
opened later by /establish call.
As a downside of this approach, we lose callback in client code
if agent process dies in between /tun-setup and /establish. This is
not a big problem IMO and can be fixed later.
In addition to that, send destroy_tun event also in /establish
request when using dco. This is needed to cover persist-tun case
when we reconnect and get new tun options. In this case we instantiate
new tun_setup instance, but don't call /tun-open since we keep tun
handle. Hence we have to pass destroy_tun event via /establish request.
Fixes https://github.com/OpenVPN/openvpn3/issues/257
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This is the result after running 'clang-format -i' on all C++ files and
headers, with the defined formatting rules in .clang-format.
Only the openvpn/common/unicode-impl.hpp has been excluded, as that is
mostly a copy of an external project.
Signed-off-by: David Sommerseth <davids@openvpn.net>
Commit ae99307 ("tun: add persis-tun support for dco-win")
broke handling of premature exit of agent process. Introduced
"tun_persist->close_destructor()" call in "tun_start() " also closes
agent process handle within WinCommandAgent,
which triggers fail handler (without error code).
Fix by "re-arming" fail handler after "close_destructor()"
call in "tun_start()".
Signed-off-by: Lev Stipakov <lev@openvpn.net>
parent->transport_connecting() might trigger stop(),
reset device handle and set halt to true if TCP server
is down. In this case we should not queue read.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add DcoTunPersist object to DCO::TunConfig.
DcoTunPersist stores:
- device handle
- tun settings
- adapter index/name
- pointer to TunSetup object, which itself
stores commands to undo tun settings
When intializing client options, instantiate DcoTunPersist
object within the scope of ClientConfig, which serves as
transport and tun factory for dco. Indicate that "sock" object
(device handle) should be preserved - not replaced when persisting
tun settings.
When establishing dco-win connection in OvpnDcoWinClient,
either use tun_persist created above (if persistance is enabled)
or instantiate it in-place (no persistance).
If nothing is stored in tun_persist (means this is first
connection or reconnect without persistance), acquire device
handle from tun_setup, wrap it into ASIO's basic_stream_handle
and store it in OvpnDcoWinClient - no need to persist it yet.
When starting tun, check if persisted tun session matches
to-be-created session. If no - clear previous tun settings,
set up tun and persist tun state. If device handle is already
stored in tun_persist, it won't be replaced.
On tun stop, send DEL_PEER command, which deletes peer
from the driver but keeps adapter in connected state. Then
close locally stored ASIO handle and reset tun_persist.
In case of "short term persistance" this will undo tun settings
and close device handle. For long term persistence, tun_persist
is also stored in ClientConfig and handle won't be closed yet.
In case of disconnect, ClientConfig::finalize(disconnect=true)
is called, which resets tun_persist, which in turn
undoes tun settings and closes device handle.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
OpenVPN 3.x has the same approach/problem for buffer allocation for the
tunnel packets that OpenVPN 2.x uses. Buffers are allocated very early
in the setup, so resizing/reacting to different frame sizes is not
really possible without major refactoring.
Therefore we use the same approach as with OpenVPN 2.x and allow a
MTU of up to 1600 by default and require setting tun-mtu-max in the
configuration file to allow larger values and allocate larger buffers.
Signed-off-by: Arne Schwabe <arne@openvpn.net>
DCO device is "exclusive" device, meaning that only one app at the time can access it
and device is considered opened until pending IO is complete.
start_impl_() might be called on reconnect, in the same stack with closing device handle.
Closing handle also triggers completion of pending IO, such as async read. However this happens
in the next iteration of ASIO even loop. Therefore we defer opening DCO device
(i.e. calling start_impl_) to let ASIO complete pending IO.
Note that this is not required when async resolve is performed, since this implies deferring.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Probe cipher support in runtime (works in Windows Server 2022 and Windows 11)
and add it to the list of allowed ciphers.
White on it, add missing halt check in dco-win client code.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Set keepalive parameters and start vpn on "tun start" event,
which seems like a more logical place comparison to "primary key ready" event.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add support for default mssfix, which is calculated
based on upper bound value 1492 minus payload and
encapculation overhead.
Payload overhead includes:
- compression byte (except for V2, which doesn't add overhead)
- pktid (in CBC)
- IPv4 and TCP headers
Encapculation overhead:
- crypto overhead (for AEAD 16 bytes auth tag, 4 bytes pktid, 4 bytes opcode/peer-id = 24)
- 2 bytes packet size for TCP transport
Also for CBC we must take padding [1..blocksize] into account.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Add missing halt etc checks.
Replace dco_error with fatal exception ErrorCode(TUN_SETUP_FAILED).
IOCTL commands are not expected to fail and of they do, threat it as fatal error.
Signed-off-by: Lev Stipakov <lev@openvpn.net>
This change replaces the boolean add_bypass_routes with a new
flags parameter -- set the TunConfigFlags::ADD_BYPASS_ROUTES
flag to achieve the same functionality.
We also add some new flags for finer-grained control over
actions taken by tun_config:
* TunConfigFlags::DISABLE_IFACE_UP -- disable bringing the interface up
* TunConfigFlags::DISABLE_REROUTE_GW -- disable redirect-gateway
Signed-off-by: James Yonan <james@openvpn.net>
While using GeNLImpl::available() for ovpn-dco works, it requires more
privileges than currently granted by SElinux for openvpn3-linux to work.
Instead of extending the privileges, add method tun_builder_dco_available()
to the TUN builder API, so that the check can be done context sensitive
by the client.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
Take option value if pushed for the next round of remote address
caching.
Since the push replies are processed in Session, we need to extend the
transport slightly to process pushed options. There was no need so far,
since transport options are used before the session starts. The remote
cache timeout is currently the only exception to this rule.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
DCO only supports a limited set of ciphers, currently it is
discovered quite late if a unsupported algorithm is configured
(or pushed).
This introduces CryptoAlgs::allow_dc_algs() with which the
supported set of data channel algorithms can be specified.
The DCO code makes use of this, at the time a new_controller()
is created.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
The DCO component now implements the SessionStats::DCOTransportSource interface.
This interface is already used by ovpncli.cpp to retrieve the peer stats
from DCO.
With this patch, also the OvpnDcoCli object can be used to retrieve the
peer stats from kernel space.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
After invoking the get_peer() API, let the DCOClient component
extract the statistics and store them locally.
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
If DCO support is compiled in, detect if it is available (i.e. Windows driver
or Linux kernel module is loaded) and then use it, if it is.
This changes the default configuration for DCO from off to on, so users of
the library need to set ClientAPI::Config::dco to false in case they do not
want to use dco for a connection.
The change is also reflected in the reference client "ovpncli". If DCO is
enabled in a build, it will detect and use it. The previously available
"ovpncliovpndco" and "ovpncliovpndcowin" clients have thus been removed.
Signed-off-by: Heiko Hund <heiko@openvpn.net>
The TunBuilder implementation needs to know which peer to send the
control packet to and for this reason the ovpndcocli component is now
prepending the data with 4 bytes representing the peer-id of the
destination.
Since this approach is incompatible with sending a const Buffer (as it
cannot be modified), send() has to allocate a temporary buffer for the
purpose.
While at it, make transport_send(Buffer) obsolete, as ovpndcocli
is not expected to handle data packets (sent as non-const).
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>