2014-07-21 05:22:06 +02:00
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
2012-08-24 23:13:42 +02:00
//
2020-03-04 20:48:54 +01:00
// Copyright (C) 2012-2020 OpenVPN Inc.
2012-08-24 23:13:42 +02:00
//
2014-07-21 05:22:06 +02:00
// This program is free software: you can redistribute it and/or modify
2017-12-21 21:42:20 +01:00
// it under the terms of the GNU Affero General Public License Version 3
2014-07-21 05:22:06 +02:00
// as published by the Free Software Foundation.
2012-08-24 23:13:42 +02:00
//
2014-07-21 05:22:06 +02:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2017-12-21 21:42:20 +01:00
// GNU Affero General Public License for more details.
2014-07-21 05:22:06 +02:00
//
2017-12-21 21:42:20 +01:00
// You should have received a copy of the GNU Affero General Public License
2014-07-21 05:22:06 +02:00
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
2012-08-24 23:13:42 +02:00
2012-02-04 11:24:54 +01:00
# ifndef OPENVPN_CLIENT_CLIPROTO_H
# define OPENVPN_CLIENT_CLIPROTO_H
2012-11-23 07:18:43 +01:00
// This is a middle-layer object in the OpenVPN client protocol stack.
// It is above the general OpenVPN protocol implementation in
2014-10-20 20:55:58 +02:00
// class ProtoContext but below the top
2012-11-23 07:18:43 +01:00
// level object in a client connect (ClientConnect). See ClientConnect for
// a fuller description of the full client stack.
//
// This layer deals with setting up an OpenVPN client connection:
//
// 1. handles creation of transport-layer handler via TransportClientFactory
// 2. handles creation of tun-layer handler via TunClientFactory
// 3. handles sending PUSH_REQUEST to server and processing reply of server-pushed options
2014-10-20 20:55:58 +02:00
// 4. manages the underlying OpenVPN protocol object (class ProtoContext)
2012-11-23 07:18:43 +01:00
// 5. handles timers on behalf of the underlying OpenVPN protocol object
// 6. acts as an exception dispatcher for errors occuring in any of the underlying layers
2012-02-06 21:39:10 +01:00
# include <string>
# include <vector>
2016-08-17 23:23:26 +02:00
# include <memory>
2014-08-18 06:25:26 +02:00
# include <algorithm> // for std::min
2015-04-24 01:55:07 +02:00
# include <cstdint> // for std::uint...
2012-02-06 21:39:10 +01:00
2017-03-30 23:10:56 +02:00
# include <openvpn/io/io.hpp>
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
# include <openvpn/common/rc.hpp>
2015-05-17 21:17:24 +02:00
# include <openvpn/common/count.hpp>
2015-06-05 03:22:59 +02:00
# include <openvpn/common/string.hpp>
2016-01-27 09:32:48 +01:00
# include <openvpn/common/base64.hpp>
2019-01-15 10:23:02 +01:00
# include <openvpn/ip/ptb.hpp>
2012-02-04 11:24:54 +01:00
# include <openvpn/tun/client/tunbase.hpp>
# include <openvpn/transport/client/transbase.hpp>
2016-11-20 21:06:35 +01:00
# include <openvpn/transport/client/relay.hpp>
2012-02-04 11:24:54 +01:00
# include <openvpn/options/continuation.hpp>
2012-03-08 11:30:43 +01:00
# include <openvpn/options/sanitize.hpp>
2012-02-04 11:24:54 +01:00
# include <openvpn/client/clievent.hpp>
2012-02-28 00:00:29 +01:00
# include <openvpn/client/clicreds.hpp>
2012-11-12 02:52:03 +01:00
# include <openvpn/client/cliconstants.hpp>
2012-11-26 02:51:24 +01:00
# include <openvpn/client/clihalt.hpp>
2021-02-04 04:22:17 +01:00
# include <openvpn/client/optfilt.hpp>
2012-02-04 11:24:54 +01:00
# include <openvpn/time/asiotimer.hpp>
# include <openvpn/time/coarsetime.hpp>
2015-01-08 23:30:58 +01:00
# include <openvpn/time/durhelper.hpp>
2012-11-14 17:41:33 +01:00
# include <openvpn/error/excode.hpp>
2012-02-04 11:24:54 +01:00
# include <openvpn/ssl/proto.hpp>
# ifdef OPENVPN_DEBUG_CLIPROTO
# define OPENVPN_LOG_CLIPROTO(x) OPENVPN_LOG(x)
# else
# define OPENVPN_LOG_CLIPROTO(x)
# endif
namespace openvpn {
2012-02-06 21:39:10 +01:00
namespace ClientProto {
2012-02-04 11:24:54 +01:00
2012-02-07 12:37:35 +01:00
struct NotifyCallback {
2012-02-06 21:39:10 +01:00
virtual void client_proto_terminate ( ) = 0 ;
2012-02-07 12:37:35 +01:00
virtual void client_proto_connected ( ) { }
2020-09-25 14:44:05 +02:00
virtual void client_proto_auth_pending_timeout ( int timeout ) { }
2021-09-16 02:07:21 +02:00
virtual void client_proto_renegotiated ( ) { }
2012-02-06 09:28:05 +01:00
} ;
2014-10-20 20:55:58 +02:00
class Session : ProtoContext ,
2014-08-14 19:18:53 +02:00
TransportClientParent ,
TunClientParent ,
public RC < thread_unsafe_refcount >
2012-02-04 11:24:54 +01:00
{
2014-10-20 20:55:58 +02:00
typedef ProtoContext Base ;
2014-10-20 21:01:40 +02:00
typedef Base : : PacketType PacketType ;
2012-02-06 21:39:10 +01:00
using Base : : now ;
2012-09-06 00:03:26 +02:00
using Base : : stat ;
2012-02-06 21:39:10 +01:00
public :
2015-05-18 05:26:53 +02:00
typedef RCPtr < Session > Ptr ;
2014-10-20 21:01:40 +02:00
typedef Base : : Config ProtoConfig ;
2012-02-06 21:39:10 +01:00
OPENVPN_EXCEPTION ( client_exception ) ;
2012-03-31 18:08:20 +02:00
OPENVPN_EXCEPTION ( client_halt_restart ) ;
2012-02-06 21:39:10 +01:00
OPENVPN_EXCEPTION ( tun_exception ) ;
OPENVPN_EXCEPTION ( transport_exception ) ;
2012-02-19 02:36:50 +01:00
OPENVPN_EXCEPTION ( max_pushed_options_exceeded ) ;
2012-02-06 21:39:10 +01:00
OPENVPN_SIMPLE_EXCEPTION ( session_invalidated ) ;
2012-02-07 12:37:35 +01:00
OPENVPN_SIMPLE_EXCEPTION ( authentication_failed ) ;
2013-05-25 03:19:50 +02:00
OPENVPN_SIMPLE_EXCEPTION ( inactive_timer_expired ) ;
2016-11-20 21:06:35 +01:00
OPENVPN_SIMPLE_EXCEPTION ( relay_event ) ;
2012-02-06 21:39:10 +01:00
2012-10-24 08:38:20 +02:00
OPENVPN_EXCEPTION ( proxy_exception ) ;
2012-02-06 21:39:10 +01:00
struct Config : public RC < thread_unsafe_refcount >
{
2015-05-18 05:26:53 +02:00
typedef RCPtr < Config > Ptr ;
2012-02-06 21:39:10 +01:00
2012-02-19 02:36:50 +01:00
Config ( )
2012-11-12 02:52:03 +01:00
: pushed_options_limit ( " server-pushed options data too large " ,
ProfileParseLimits : : MAX_PUSH_SIZE ,
ProfileParseLimits : : OPT_OVERHEAD ,
ProfileParseLimits : : TERM_OVERHEAD ,
2012-11-14 03:35:50 +01:00
0 ,
2016-03-28 08:24:01 +02:00
ProfileParseLimits : : MAX_DIRECTIVE_SIZE )
2012-02-19 02:36:50 +01:00
{ }
2014-10-20 21:01:40 +02:00
ProtoConfig : : Ptr proto_context_config ;
2012-09-08 03:36:54 +02:00
ProtoContextOptions : : Ptr proto_context_options ;
2012-10-03 11:03:02 +02:00
PushOptionsBase : : Ptr push_base ;
2012-02-06 21:39:10 +01:00
TransportClientFactory : : Ptr transport_factory ;
TunClientFactory : : Ptr tun_factory ;
SessionStats : : Ptr cli_stats ;
ClientEvent : : Queue : : Ptr cli_events ;
2012-02-28 00:00:29 +01:00
ClientCreds : : Ptr creds ;
2012-11-12 02:52:03 +01:00
OptionList : : Limits pushed_options_limit ;
2013-03-14 03:54:58 +01:00
OptionList : : FilterBase : : Ptr pushed_options_filter ;
2016-03-28 08:24:01 +02:00
unsigned int tcp_queue_limit = 0 ;
bool echo = false ;
2016-05-11 01:53:09 +02:00
bool info = false ;
2016-06-29 08:57:24 +02:00
bool autologin_sessions = false ;
2012-02-06 21:39:10 +01:00
} ;
2017-03-30 23:10:56 +02:00
Session ( openvpn_io : : io_context & io_context_arg ,
2012-02-06 21:39:10 +01:00
const Config & config ,
2012-02-07 12:37:35 +01:00
NotifyCallback * notify_callback_arg )
2012-02-06 21:39:10 +01:00
: Base ( config . proto_context_config , config . cli_stats ) ,
2015-06-30 08:05:37 +02:00
io_context ( io_context_arg ) ,
2012-02-06 21:39:10 +01:00
transport_factory ( config . transport_factory ) ,
tun_factory ( config . tun_factory ) ,
2015-10-19 08:32:13 +02:00
tcp_queue_limit ( config . tcp_queue_limit ) ,
2012-02-07 12:37:35 +01:00
notify_callback ( notify_callback_arg ) ,
2015-06-30 08:05:37 +02:00
housekeeping_timer ( io_context_arg ) ,
push_request_timer ( io_context_arg ) ,
2012-10-03 11:03:02 +02:00
received_options ( config . push_base ) ,
2012-02-28 00:00:29 +01:00
creds ( config . creds ) ,
2012-09-08 03:36:54 +02:00
proto_context_options ( config . proto_context_options ) ,
2012-10-31 15:46:40 +01:00
cli_stats ( config . cli_stats ) ,
2012-02-07 12:37:35 +01:00
cli_events ( config . cli_events ) ,
2016-03-28 08:31:35 +02:00
echo ( config . echo ) ,
2016-05-11 01:53:09 +02:00
info ( config . info ) ,
2016-06-29 08:57:24 +02:00
autologin_sessions ( config . autologin_sessions ) ,
2013-03-14 03:54:58 +01:00
pushed_options_limit ( config . pushed_options_limit ) ,
2013-05-25 03:19:50 +02:00
pushed_options_filter ( config . pushed_options_filter ) ,
2016-08-17 23:23:26 +02:00
inactive_timer ( io_context_arg ) ,
info_hold_timer ( io_context_arg )
2012-02-06 21:39:10 +01:00
{
2012-02-04 11:24:54 +01:00
# ifdef OPENVPN_PACKET_LOG
2012-02-06 21:39:10 +01:00
packet_log . open ( OPENVPN_PACKET_LOG , std : : ios : : binary ) ;
if ( ! packet_log )
OPENVPN_THROW ( open_file_error , " cannot open packet log for output: " < < OPENVPN_PACKET_LOG ) ;
2012-02-04 11:24:54 +01:00
# endif
2012-02-16 21:46:38 +01:00
Base : : update_now ( ) ;
Base : : reset ( ) ;
2012-09-15 08:56:18 +02:00
//Base::enable_strict_openvpn_2x();
2016-08-17 23:23:26 +02:00
info_hold . reset ( new std : : vector < ClientEvent : : Base : : Ptr > ( ) ) ;
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
bool first_packet_received ( ) const { return first_packet_received_ ; }
2012-02-06 09:28:05 +01:00
2012-02-06 21:39:10 +01:00
void start ( )
{
2012-02-07 12:37:35 +01:00
if ( ! halt )
{
2012-02-07 21:52:40 +01:00
Base : : update_now ( ) ;
2012-02-07 12:37:35 +01:00
// coarse wakeup range
housekeeping_schedule . init ( Time : : Duration : : binary_ms ( 512 ) , Time : : Duration : : binary_ms ( 1024 ) ) ;
2012-02-04 11:24:54 +01:00
2012-02-07 12:37:35 +01:00
// initialize transport-layer packet handler
2016-11-20 21:06:35 +01:00
transport = transport_factory - > new_transport_client_obj ( io_context , this ) ;
2015-10-19 08:32:13 +02:00
transport_has_send_queue = transport - > transport_has_send_queue ( ) ;
2016-11-20 21:06:35 +01:00
if ( transport_factory - > is_relay ( ) )
transport_connecting ( ) ;
else
transport - > transport_start ( ) ;
2012-02-07 12:37:35 +01:00
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2016-11-20 21:06:35 +01:00
TransportClientFactory : : Ptr transport_factory_relay ( )
{
TransportClient : : Ptr tc ( new TransportRelayFactory : : TransportClientNull ( transport . get ( ) ) ) ;
tc . swap ( transport ) ;
return new TransportRelayFactory ( io_context , std : : move ( tc ) , this ) ;
}
void transport_factory_override ( TransportClientFactory : : Ptr factory )
{
transport_factory = std : : move ( factory ) ;
}
2012-02-27 09:16:27 +01:00
void send_explicit_exit_notify ( )
{
if ( ! halt )
Base : : send_explicit_exit_notify ( ) ;
}
2014-08-25 07:09:16 +02:00
void tun_set_disconnect ( )
{
if ( tun )
tun - > set_disconnect ( ) ;
}
2016-12-08 23:23:01 +01:00
void post_cc_msg ( const std : : string & msg )
{
Base : : update_now ( ) ;
Base : : write_control_string ( msg ) ;
Base : : flush ( true ) ;
set_housekeeping_timer ( ) ;
}
2012-02-06 21:39:10 +01:00
void stop ( const bool call_terminate_callback )
{
2012-02-07 12:37:35 +01:00
if ( ! halt )
2012-02-06 21:39:10 +01:00
{
2012-02-07 12:37:35 +01:00
halt = true ;
2012-02-06 21:39:10 +01:00
housekeeping_timer . cancel ( ) ;
push_request_timer . cancel ( ) ;
2013-05-25 03:19:50 +02:00
inactive_timer . cancel ( ) ;
2016-08-17 23:23:26 +02:00
info_hold_timer . cancel ( ) ;
2014-08-25 07:09:16 +02:00
if ( notify_callback & & call_terminate_callback )
notify_callback - > client_proto_terminate ( ) ;
2012-02-06 21:39:10 +01:00
if ( tun )
2014-08-25 07:09:16 +02:00
tun - > stop ( ) ; // call after client_proto_terminate() so it can call back to tun_set_disconnect
2012-02-06 21:39:10 +01:00
if ( transport )
transport - > stop ( ) ;
}
}
2012-02-04 11:24:54 +01:00
2017-03-30 23:10:56 +02:00
void stop_on_signal ( const openvpn_io : : error_code & error , int signal_number )
2012-02-07 12:37:35 +01:00
{
stop ( true ) ;
}
2016-09-02 20:52:21 +02:00
bool reached_connected_state ( ) const { return bool ( connected_ ) ; }
2012-02-07 12:37:35 +01:00
2014-08-22 23:32:35 +02:00
// If fatal() returns something other than Error::UNDEF, it
// is intended to flag the higher levels (cliconnect.hpp)
// that special handling is required. This handling might include
// considering the error to be fatal and stopping future connect
// retries, or emitting a special event. See cliconnect.hpp
// for actual implementation.
2012-02-19 02:36:50 +01:00
Error : : Type fatal ( ) const { return fatal_ ; }
const std : : string & fatal_reason ( ) const { return fatal_reason_ ; }
2012-02-15 19:19:34 +01:00
2012-02-06 21:39:10 +01:00
virtual ~ Session ( )
{
stop ( false ) ;
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
private :
2021-09-17 19:53:49 +02:00
bool transport_is_openvpn_protocol ( ) override
2015-05-06 09:20:00 +02:00
{
return true ;
}
2012-02-06 21:39:10 +01:00
// transport obj calls here with incoming packets
2021-09-17 19:53:49 +02:00
void transport_recv ( BufferAllocated & buf ) override
2012-02-06 21:39:10 +01:00
{
try {
2012-09-15 08:56:18 +02:00
OPENVPN_LOG_CLIPROTO ( " Transport RECV " < < server_endpoint_render ( ) < < ' ' < < Base : : dump_packet ( buf ) ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// update current time
Base : : update_now ( ) ;
2012-02-04 11:24:54 +01:00
2012-09-06 00:03:26 +02:00
// update last packet received
stat ( ) . update_last_packet_received ( now ( ) ) ;
2012-02-06 21:39:10 +01:00
// log connecting event (only on first packet received)
if ( ! first_packet_received_ )
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Connecting ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-02-06 21:39:10 +01:00
first_packet_received_ = true ;
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// get packet type
2014-10-20 21:01:40 +02:00
Base : : PacketType pt = Base : : packet_type ( buf ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// process packet
2013-05-22 06:56:48 +02:00
if ( pt . is_data ( ) )
2012-02-06 21:39:10 +01:00
{
// data packet
Base : : data_decrypt ( pt , buf ) ;
if ( buf . size ( ) )
{
2012-02-04 11:24:54 +01:00
# ifdef OPENVPN_PACKET_LOG
2012-02-06 21:39:10 +01:00
log_packet ( buf , false ) ;
2012-02-04 11:24:54 +01:00
# endif
2012-02-06 21:39:10 +01:00
// make packet appear as incoming on tun interface
2013-05-22 06:56:48 +02:00
if ( tun )
{
OPENVPN_LOG_CLIPROTO ( " TUN send, size= " < < buf . size ( ) ) ;
tun - > tun_send ( buf ) ;
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// do a lightweight flush
Base : : flush ( false ) ;
}
else if ( pt . is_control ( ) )
{
// control packet
2016-05-10 21:02:11 +02:00
Base : : control_net_recv ( pt , std : : move ( buf ) ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// do a full flush
Base : : flush ( true ) ;
}
2016-09-01 23:19:00 +02:00
else
cli_stats - > error ( Error : : KEY_STATE_ERROR ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// schedule housekeeping wakeup
set_housekeeping_timer ( ) ;
2012-02-04 11:24:54 +01:00
}
2012-10-31 15:46:40 +01:00
catch ( const ExceptionCode & e )
{
2012-11-12 02:52:03 +01:00
if ( e . code_defined ( ) )
{
if ( e . fatal ( ) )
transport_error ( ( Error : : Type ) e . code ( ) , e . what ( ) ) ;
else
cli_stats - > error ( ( Error : : Type ) e . code ( ) ) ;
}
2012-10-31 15:46:40 +01:00
else
2012-11-14 17:41:33 +01:00
process_exception ( e , " transport_recv_excode " ) ;
}
catch ( const std : : exception & e )
{
process_exception ( e , " transport_recv " ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void transport_needs_send ( ) override
2015-05-06 09:20:00 +02:00
{
}
2012-02-06 21:39:10 +01:00
// tun i/o driver calls here with incoming packets
2021-09-17 19:53:49 +02:00
void tun_recv ( BufferAllocated & buf ) override
2012-02-06 21:39:10 +01:00
{
try {
OPENVPN_LOG_CLIPROTO ( " TUN recv, size= " < < buf . size ( ) ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// update current time
Base : : update_now ( ) ;
2012-02-04 11:24:54 +01:00
2015-10-19 08:32:13 +02:00
// log packet
2012-02-04 11:24:54 +01:00
# ifdef OPENVPN_PACKET_LOG
2012-02-06 21:39:10 +01:00
log_packet ( buf , true ) ;
2012-02-04 11:24:54 +01:00
# endif
2015-10-19 08:32:13 +02:00
// if transport layer has an output queue, check if it's full
if ( transport_has_send_queue )
{
if ( transport - > transport_send_queue_size ( ) > tcp_queue_limit )
{
buf . reset_size ( ) ; // queue full, drop packet
cli_stats - > error ( Error : : TCP_OVERFLOW ) ;
}
}
// encrypt packet
2012-02-06 21:39:10 +01:00
if ( buf . size ( ) )
{
2019-01-15 10:23:02 +01:00
const ProtoContext : : Config & c = Base : : conf ( ) ;
if ( c . mss_inter > 0 & & buf . size ( ) > c . mss_inter )
{
Ptb : : generate_icmp_ptb ( buf , c . mss_inter ) ;
tun - > tun_send ( buf ) ;
}
else
2015-10-19 08:32:13 +02:00
{
2019-01-15 10:23:02 +01:00
Base : : data_encrypt ( buf ) ;
if ( buf . size ( ) )
{
// send packet via transport to destination
OPENVPN_LOG_CLIPROTO ( " Transport SEND " < < server_endpoint_render ( ) < < ' ' < < Base : : dump_packet ( buf ) ) ;
if ( transport - > transport_send ( buf ) )
Base : : update_last_sent ( ) ;
else if ( halt )
return ;
}
2015-10-19 08:32:13 +02:00
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// do a lightweight flush
Base : : flush ( false ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// schedule housekeeping wakeup
set_housekeeping_timer ( ) ;
2012-02-04 11:24:54 +01:00
}
2012-02-17 20:28:44 +01:00
catch ( const std : : exception & e )
2012-02-06 21:39:10 +01:00
{
2012-07-01 17:37:46 +02:00
process_exception ( e , " tun_recv " ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2016-07-13 07:15:35 +02:00
// Return true if keepalive parameter(s) are enabled.
2021-09-17 19:53:49 +02:00
bool is_keepalive_enabled ( ) const override
2016-07-13 07:15:35 +02:00
{
return Base : : is_keepalive_enabled ( ) ;
}
2015-06-17 09:48:33 +02:00
// Disable keepalive for rest of session, but fetch
// the keepalive parameters (in seconds).
2021-09-17 19:53:49 +02:00
void disable_keepalive ( unsigned int & keepalive_ping ,
unsigned int & keepalive_timeout ) override
2015-06-17 09:48:33 +02:00
{
Base : : disable_keepalive ( keepalive_ping , keepalive_timeout ) ;
}
2021-09-17 19:53:49 +02:00
void transport_pre_resolve ( ) override
2012-02-06 21:39:10 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Resolve ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-02-04 11:24:54 +01:00
}
2012-02-06 21:39:10 +01:00
std : : string server_endpoint_render ( )
{
std : : string server_host , server_port , server_proto , server_ip ;
transport - > server_endpoint_info ( server_host , server_port , server_proto , server_ip ) ;
std : : ostringstream out ;
2016-02-04 23:48:33 +01:00
out < < ' [ ' < < server_host < < " ]: " < < server_port < < " ( " < < server_ip < < " ) via " < < server_proto ;
2012-02-06 21:39:10 +01:00
return out . str ( ) ;
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void transport_wait_proxy ( ) override
2012-10-31 19:54:02 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : WaitProxy ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-10-31 19:54:02 +01:00
}
2021-09-17 19:53:49 +02:00
void transport_wait ( ) override
2012-10-31 19:54:02 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Wait ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-10-31 19:54:02 +01:00
}
2021-09-17 19:53:49 +02:00
void transport_connecting ( ) override
2012-02-06 21:39:10 +01:00
{
try {
OPENVPN_LOG ( " Connecting to " < < server_endpoint_render ( ) ) ;
2016-11-20 21:06:35 +01:00
Base : : set_protocol ( transport - > transport_protocol ( ) ) ;
2012-02-06 21:39:10 +01:00
Base : : start ( ) ;
Base : : flush ( true ) ;
set_housekeeping_timer ( ) ;
2012-02-04 11:24:54 +01:00
}
2012-02-17 20:28:44 +01:00
catch ( const std : : exception & e )
2012-02-06 21:39:10 +01:00
{
2012-07-01 17:37:46 +02:00
process_exception ( e , " transport_connecting " ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void transport_error ( const Error : : Type fatal_err , const std : : string & err_text ) override
2012-10-24 08:38:20 +02:00
{
2012-10-24 11:32:15 +02:00
if ( fatal_err ! = Error : : UNDEF )
{
fatal_ = fatal_err ;
fatal_reason_ = err_text ;
}
2012-10-24 08:38:20 +02:00
if ( notify_callback )
{
2012-10-24 11:32:15 +02:00
OPENVPN_LOG ( " Transport Error: " < < err_text ) ;
2012-10-24 08:38:20 +02:00
stop ( true ) ;
}
else
2012-10-24 11:32:15 +02:00
throw transport_exception ( err_text ) ;
2012-10-24 08:38:20 +02:00
}
2021-09-17 19:53:49 +02:00
void proxy_error ( const Error : : Type fatal_err , const std : : string & err_text ) override
2012-02-06 21:39:10 +01:00
{
2012-10-24 11:32:15 +02:00
if ( fatal_err ! = Error : : UNDEF )
{
fatal_ = fatal_err ;
fatal_reason_ = err_text ;
}
2012-02-07 12:37:35 +01:00
if ( notify_callback )
2012-02-06 21:39:10 +01:00
{
2012-10-24 11:32:15 +02:00
OPENVPN_LOG ( " Proxy Error: " < < err_text ) ;
2012-02-06 21:39:10 +01:00
stop ( true ) ;
}
else
2012-10-24 11:32:15 +02:00
throw proxy_exception ( err_text ) ;
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
void extract_auth_token ( const OptionList & opt )
{
2016-02-04 19:31:08 +01:00
std : : string username ;
2016-01-27 09:32:48 +01:00
// auth-token-user
{
const Option * o = opt . get_ptr ( " auth-token-user " ) ;
if ( o )
2019-07-27 00:58:16 +02:00
username = base64 - > decode ( o - > get ( 1 , 340 ) ) ; // 255 chars after base64 decode
2016-01-27 09:32:48 +01:00
}
// auth-token
{
// if auth-token is present, use it as the password for future renegotiations
const Option * o = opt . get_ptr ( " auth-token " ) ;
if ( o )
{
const std : : string & sess_id = o - > get ( 1 , 256 ) ;
if ( creds )
{
2016-02-04 19:31:08 +01:00
if ( ! username . empty ( ) )
OPENVPN_LOG ( " Session user: " < < username ) ;
2012-03-08 11:30:43 +01:00
# ifdef OPENVPN_SHOW_SESSION_TOKEN
2016-01-27 09:32:48 +01:00
OPENVPN_LOG ( " Session token: " < < sess_id ) ;
2012-03-08 11:30:43 +01:00
# else
2016-01-27 09:32:48 +01:00
OPENVPN_LOG ( " Session token: [redacted] " ) ;
2012-03-08 11:30:43 +01:00
# endif
2021-08-11 14:43:28 +02:00
autologin_sessions = true ;
conf ( ) . set_xmit_creds ( true ) ;
creds - > set_replace_password_with_session_id ( true ) ;
2016-02-04 19:31:08 +01:00
creds - > set_session_id ( username , sess_id ) ;
2016-01-27 09:32:48 +01:00
}
}
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// proto base class calls here for control channel network sends
2021-09-17 19:53:49 +02:00
void control_net_send ( const Buffer & net_buf ) override
2012-02-06 21:39:10 +01:00
{
2012-09-15 08:56:18 +02:00
OPENVPN_LOG_CLIPROTO ( " Transport SEND " < < server_endpoint_render ( ) < < ' ' < < Base : : dump_packet ( net_buf ) ) ;
2012-02-06 21:39:10 +01:00
if ( transport - > transport_send_const ( net_buf ) )
Base : : update_last_sent ( ) ;
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
// proto base class calls here for app-level control-channel messages received
2021-09-17 19:53:49 +02:00
void control_recv ( BufferPtr & & app_bp ) override
2012-02-06 21:39:10 +01:00
{
2012-11-14 03:35:50 +01:00
const std : : string msg = Unicode : : utf8_printable ( Base : : template read_control_string < std : : string > ( * app_bp ) ,
2016-05-11 01:53:09 +02:00
Unicode : : UTF8_FILTER | Unicode : : UTF8_PASS_FMT ) ;
2012-11-14 03:35:50 +01:00
2012-10-03 11:03:02 +02:00
//OPENVPN_LOG("SERVER: " << sanitize_control_message(msg));
2012-11-12 02:52:03 +01:00
2015-06-05 03:22:59 +02:00
if ( ! received_options . complete ( ) & & string : : starts_with ( msg , " PUSH_REPLY, " ) )
2012-02-06 21:39:10 +01:00
{
// parse the received options
2021-02-04 04:22:17 +01:00
auto pushed_options_list = OptionList : : parse_from_csv_static ( msg . substr ( 11 ) , & pushed_options_limit ) ;
try
{
received_options . add ( pushed_options_list , pushed_options_filter . get ( ) ) ;
}
catch ( const Option : : RejectedException & e )
{
ClientHalt ch ( " RESTART,rejected pushed option: " + e . err ( ) , true ) ;
process_halt_restart ( ch ) ;
}
2012-02-06 21:39:10 +01:00
if ( received_options . complete ( ) )
{
// show options
2013-06-10 02:42:19 +02:00
OPENVPN_LOG ( " OPTIONS: " < < std : : endl < < render_options_sanitized ( received_options , Option : : RENDER_PASS_FMT | Option : : RENDER_NUMBER | Option : : RENDER_BRACKET ) ) ;
2012-02-04 11:24:54 +01:00
2016-11-20 21:06:35 +01:00
// relay servers are not allowed to establish a tunnel with us
if ( Base : : conf ( ) . relay_mode )
{
tun_error ( Error : : RELAY_ERROR , " tunnel not permitted to relay server " ) ;
return ;
}
2016-03-28 08:31:35 +02:00
// process "echo" directives
if ( echo )
process_echo ( received_options ) ;
2012-02-06 21:39:10 +01:00
// process auth-token
extract_auth_token ( received_options ) ;
2012-02-04 11:24:54 +01:00
2021-09-15 13:39:02 +02:00
// process pushed transport options
transport_factory - > process_push ( received_options ) ;
2020-08-13 15:47:42 +02:00
// modify proto config (cipher, auth, key-derivation and compression methods)
2012-09-08 03:36:54 +02:00
Base : : process_push ( received_options , * proto_context_options ) ;
2012-02-04 11:24:54 +01:00
2015-06-17 09:48:33 +02:00
// initialize tun/routing
2015-06-30 08:05:37 +02:00
tun = tun_factory - > new_tun_client_obj ( io_context , * this , transport . get ( ) ) ;
2015-06-17 09:48:33 +02:00
tun - > tun_start ( received_options , * transport , Base : : dc_settings ( ) ) ;
2016-09-02 20:52:21 +02:00
// we should be connected at this point
if ( ! connected_ )
throw tun_exception ( " not connected " ) ;
2015-06-17 09:48:33 +02:00
// initialize data channel after pushed options have been processed
Base : : init_data_channel ( ) ;
2014-12-21 18:32:37 +01:00
// Allow ProtoContext to suggest an alignment adjustment
// hint for transport layer.
transport - > reset_align_adjust ( Base : : align_adjust_hint ( ) ) ;
2013-05-25 03:19:50 +02:00
// process "inactive" directive
2015-06-17 09:48:33 +02:00
process_inactive ( received_options ) ;
2016-09-02 20:52:21 +02:00
// tell parent that we are connected
if ( notify_callback )
notify_callback - > client_proto_connected ( ) ;
// start info-hold timer
schedule_info_hold_callback ( ) ;
// send the Connected event
cli_events - > add_event ( connected_ ) ;
2019-09-17 22:52:31 +02:00
2020-09-15 14:12:09 +02:00
// check for proto options
check_proto_warnings ( ) ;
2012-02-06 21:39:10 +01:00
}
else
OPENVPN_LOG ( " Options continuation... " ) ;
}
2018-12-05 23:24:54 +01:00
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 ) ;
}
2015-06-05 03:22:59 +02:00
else if ( string : : starts_with ( msg , " AUTH_FAILED " ) )
2012-02-06 21:39:10 +01:00
{
2013-01-25 03:34:20 +01:00
std : : string reason ;
std : : string log_reason ;
// get reason (if it exists) for authentication failure
2012-02-15 19:19:34 +01:00
if ( msg . length ( ) > = 13 )
2015-06-05 03:22:59 +02:00
reason = string : : trim_left_copy ( std : : string ( msg , 12 ) ) ;
2013-01-25 03:34:20 +01:00
// If session token problem (such as expiration), and we have a cached
// password, retry with it. Otherwise, fail without retry.
2015-06-05 03:22:59 +02:00
if ( string : : starts_with ( reason , " SESSION: " )
2021-08-11 22:55:22 +02:00
& & ( ( creds & & creds - > reset_to_cached_password ( ) )
2021-08-10 14:44:12 +02:00
| | autologin_sessions ) )
2013-01-25 03:34:20 +01:00
{
log_reason = " SESSION_AUTH_FAILED " ;
}
else
{
fatal_ = Error : : AUTH_FAILED ;
fatal_reason_ = reason ;
log_reason = " AUTH_FAILED " ;
}
2012-02-07 12:37:35 +01:00
if ( notify_callback )
2012-02-06 21:39:10 +01:00
{
2013-01-25 03:34:20 +01:00
OPENVPN_LOG ( log_reason ) ;
2012-02-06 21:39:10 +01:00
stop ( true ) ;
}
else
2012-02-07 12:37:35 +01:00
throw authentication_failed ( ) ;
2012-02-06 21:39:10 +01:00
}
2012-03-31 18:08:20 +02:00
else if ( ClientHalt : : match ( msg ) )
{
2016-05-05 08:22:09 +02:00
const ClientHalt ch ( msg , true ) ;
2012-03-31 18:08:20 +02:00
process_halt_restart ( ch ) ;
}
2016-05-11 01:53:09 +02:00
else if ( info & & string : : starts_with ( msg , " INFO, " ) )
{
2016-08-17 23:23:26 +02:00
// Buffer INFO messages received near Connected event to fire
// one second after Connected event, to reduce the chance of
// race conditions in the client app, if the INFO event
// triggers the client app to perform an operation that
// requires the VPN tunnel to be ready.
2016-05-11 01:53:09 +02:00
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Info ( msg . substr ( 5 ) ) ;
2016-08-17 23:23:26 +02:00
if ( info_hold )
info_hold - > push_back ( std : : move ( ev ) ) ;
else
cli_events - > add_event ( std : : move ( ev ) ) ;
2016-05-11 01:53:09 +02:00
}
2018-04-12 22:32:14 +02:00
else if ( info & & string : : starts_with ( msg , " INFO_PRE, " ) )
{
// INFO_PRE is like INFO but it is never buffered
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Info ( msg . substr ( 9 ) ) ;
cli_events - > add_event ( std : : move ( ev ) ) ;
}
2020-09-25 14:44:05 +02:00
else if ( msg = = " AUTH_PENDING " | | string : : starts_with ( msg , " AUTH_PENDING, " ) )
2018-04-12 22:32:14 +02:00
{
// AUTH_PENDING indicates an out-of-band authentication step must
// be performed before the server will send the PUSH_REPLY message.
if ( ! auth_pending )
{
auth_pending = true ;
2020-09-25 14:44:05 +02:00
std : : string key_words ;
unsigned int timeout = 0 ;
if ( string : : starts_with ( msg , " AUTH_PENDING, " ) )
{
key_words = msg . substr ( : : strlen ( " AUTH_PENDING, " ) ) ;
auto opts = OptionList : : parse_from_csv_static ( key_words , nullptr ) ;
std : : string timeout_str = opts . get_optional ( " timeout " , 1 , 20 ) ;
if ( timeout_str ! = " " )
{
try
{
timeout = std : : stoul ( timeout_str ) ;
// Cap the timeout to end well before renegotiation starts
timeout = std : : min ( timeout , static_cast < decltype ( timeout ) > ( conf ( ) . renegotiate . to_seconds ( ) / 2 ) ) ;
}
catch ( const std : : logic_error & e )
{
OPENVPN_LOG ( " could not parse AUTH_PENDING timeout: " < < timeout_str ) ;
}
}
}
if ( notify_callback & & timeout > 0 )
{
notify_callback - > client_proto_auth_pending_timeout ( timeout ) ;
}
ClientEvent : : Base : : Ptr ev = new ClientEvent : : AuthPending ( timeout , key_words ) ;
2018-04-12 22:32:14 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
}
}
2016-11-20 21:06:35 +01:00
else if ( msg = = " RELAY " )
{
if ( Base : : conf ( ) . relay_mode )
{
fatal_ = Error : : RELAY ;
fatal_reason_ = " " ;
}
else
{
fatal_ = Error : : RELAY_ERROR ;
fatal_reason_ = " not in relay mode " ;
}
if ( notify_callback )
{
OPENVPN_LOG ( Error : : name ( fatal_ ) < < ' ' < < fatal_reason_ ) ;
stop ( true ) ;
}
else
throw relay_event ( ) ;
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void tun_pre_tun_config ( ) override
2012-02-06 21:39:10 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : AssignIP ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void tun_pre_route_config ( ) override
2012-02-06 21:39:10 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : AddRoutes ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void tun_connected ( ) override
2012-02-06 21:39:10 +01:00
{
OPENVPN_LOG ( " Connected via " + tun - > tun_name ( ) ) ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
ClientEvent : : Connected : : Ptr ev = new ClientEvent : : Connected ( ) ;
2012-02-28 00:00:29 +01:00
if ( creds )
2012-03-01 09:11:00 +01:00
ev - > user = creds - > get_username ( ) ;
2012-02-06 21:39:10 +01:00
transport - > server_endpoint_info ( ev - > server_host , ev - > server_port , ev - > server_proto , ev - > server_ip ) ;
2012-10-03 11:03:02 +02:00
ev - > vpn_ip4 = tun - > vpn_ip4 ( ) ;
ev - > vpn_ip6 = tun - > vpn_ip6 ( ) ;
2016-06-27 06:23:08 +02:00
ev - > vpn_gw4 = tun - > vpn_gw4 ( ) ;
ev - > vpn_gw6 = tun - > vpn_gw6 ( ) ;
2012-10-03 11:03:02 +02:00
try {
2012-11-14 03:35:50 +01:00
std : : string client_ip = received_options . get_optional ( " client-ip " , 1 , 256 ) ;
2012-10-07 10:57:41 +02:00
if ( ! client_ip . empty ( ) )
ev - > client_ip = IP : : Addr : : validate ( client_ip , " client-ip " ) ;
2012-10-03 11:03:02 +02:00
}
catch ( const std : : exception & e )
{
2018-03-07 23:59:07 +01:00
OPENVPN_LOG ( " exception parsing client-ip: " < < e . what ( ) ) ;
2012-10-03 11:03:02 +02:00
}
2012-02-06 21:39:10 +01:00
ev - > tun_name = tun - > tun_name ( ) ;
2016-09-02 20:52:21 +02:00
connected_ = std : : move ( ev ) ;
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
2021-09-17 19:53:49 +02:00
void tun_error ( const Error : : Type fatal_err , const std : : string & err_text ) override
2012-02-06 21:39:10 +01:00
{
2019-06-18 00:14:43 +02:00
if ( fatal_err = = Error : : TUN_HALT )
send_explicit_exit_notify ( ) ;
2012-10-24 11:32:15 +02:00
if ( fatal_err ! = Error : : UNDEF )
{
fatal_ = fatal_err ;
fatal_reason_ = err_text ;
}
2012-02-07 12:37:35 +01:00
if ( notify_callback )
2012-02-04 11:24:54 +01:00
{
2012-10-24 11:32:15 +02:00
OPENVPN_LOG ( " TUN Error: " < < err_text ) ;
2012-02-06 21:39:10 +01:00
stop ( true ) ;
2012-02-04 11:24:54 +01:00
}
2012-02-06 21:39:10 +01:00
else
2012-10-24 11:32:15 +02:00
throw tun_exception ( err_text ) ;
2012-02-04 11:24:54 +01:00
}
2012-02-06 21:39:10 +01:00
// proto base class calls here to get auth credentials
2021-09-17 19:53:49 +02:00
void client_auth ( Buffer & buf ) override
2012-02-06 21:39:10 +01:00
{
2016-11-20 21:06:35 +01:00
// we never send creds to a relay server
if ( creds & & ! Base : : conf ( ) . relay_mode )
2012-02-28 00:00:29 +01:00
{
2014-01-08 05:32:37 +01:00
OPENVPN_LOG ( " Creds: " < < creds - > auth_info ( ) ) ;
2012-03-01 09:11:00 +01:00
Base : : write_auth_string ( creds - > get_username ( ) , buf ) ;
2021-08-12 15:56:06 +02:00
# ifdef OPENVPN_DISABLE_AUTH_TOKEN // debugging only
if ( creds - > session_id_defined ( ) )
{
OPENVPN_LOG ( " NOTE: not sending auth-token " ) ;
Base : : write_empty_string ( buf ) ;
}
else
# endif
{
Base : : write_auth_string ( creds - > get_password ( ) , buf ) ;
}
2012-02-28 00:00:29 +01:00
}
else
{
2014-01-08 05:32:37 +01:00
OPENVPN_LOG ( " Creds: None " ) ;
2012-02-28 00:00:29 +01:00
Base : : write_empty_string ( buf ) ; // username
Base : : write_empty_string ( buf ) ; // password
}
2012-02-06 21:39:10 +01:00
}
2014-08-18 06:25:26 +02:00
void send_push_request_callback ( const Time : : Duration & dur ,
2017-03-30 23:10:56 +02:00
const openvpn_io : : error_code & e )
2012-02-06 21:39:10 +01:00
{
try {
2012-02-07 21:52:40 +01:00
if ( ! e & & ! halt & & ! received_options . partial ( ) )
2012-02-06 21:39:10 +01:00
{
Base : : update_now ( ) ;
if ( ! sent_push_request )
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : GetConfig ( ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2012-02-06 21:39:10 +01:00
sent_push_request = true ;
}
OPENVPN_LOG ( " Sending PUSH_REQUEST to server... " ) ;
Base : : write_control_string ( std : : string ( " PUSH_REQUEST " ) ) ;
Base : : flush ( true ) ;
set_housekeeping_timer ( ) ;
2014-08-18 06:25:26 +02:00
{
2018-04-12 22:32:14 +02:00
if ( auth_pending )
{
// With auth_pending, we can dial back the PUSH_REQUEST
// frequency, but we still need back-and-forth network
// activity to avoid an inactivity timeout, since the crypto
// layer (and hence keepalive ping) is not initialized until
// we receive the PUSH_REPLY from the server.
schedule_push_request_callback ( Time : : Duration : : seconds ( 8 ) ) ;
}
else
{
// step function with ceiling: 1 sec, 2 secs, 3 secs, 3, 3, ...
const Time : : Duration newdur = std : : min ( dur + Time : : Duration : : seconds ( 1 ) ,
Time : : Duration : : seconds ( 3 ) ) ;
schedule_push_request_callback ( newdur ) ;
}
2014-08-18 06:25:26 +02:00
}
2012-02-06 21:39:10 +01:00
}
2012-02-04 11:24:54 +01:00
}
2012-02-17 20:28:44 +01:00
catch ( const std : : exception & e )
2012-02-06 21:39:10 +01:00
{
2012-07-01 17:37:46 +02:00
process_exception ( e , " send_push_request_callback " ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2014-08-18 06:25:26 +02:00
void schedule_push_request_callback ( const Time : : Duration & dur )
2012-02-06 21:39:10 +01:00
{
if ( ! received_options . partial ( ) )
{
2017-04-12 22:01:11 +02:00
push_request_timer . expires_after ( dur ) ;
2017-03-30 23:10:56 +02:00
push_request_timer . async_wait ( [ self = Ptr ( this ) , dur ] ( const openvpn_io : : error_code & error )
2015-06-25 21:59:12 +02:00
{
2018-03-23 15:23:45 +01:00
OPENVPN_ASYNC_HANDLER ;
2015-06-25 21:59:12 +02:00
self - > send_push_request_callback ( dur , error ) ;
} ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2017-12-06 09:04:02 +01:00
// react to any tls warning triggered during the tls-handshake
virtual void check_tls_warnings ( )
{
uint32_t tls_warnings = get_tls_warnings ( ) ;
if ( tls_warnings & SSLAPI : : TLS_WARN_SIG_MD5 )
2018-02-28 10:07:43 +01:00
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Warn ( " TLS: received certificate signed with MD5. Please inform your admin to upgrade to a stronger algorithm. Support for MD5 will be dropped at end of Apr 2018 " ) ;
cli_events - > add_event ( std : : move ( ev ) ) ;
}
2020-09-15 14:12:09 +02:00
if ( tls_warnings & SSLAPI : : TLS_WARN_SIG_SHA1 )
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Warn ( " TLS: received certificate signed with SHA1. Please inform your admin to upgrade to a stronger algorithm. Support for SHA1 signatures will be dropped in the future " ) ;
cli_events - > add_event ( std : : move ( ev ) ) ;
}
}
void check_proto_warnings ( )
{
if ( uses_bs64_cipher ( ) )
{
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Warn ( " Proto: Using a 64-bit block cipher that is vulnerable to the SWEET32 attack. Please inform your admin to upgrade to a stronger algorithm. Support for 64-bit block cipher will be dropped in the future. " ) ;
cli_events - > add_event ( std : : move ( ev ) ) ;
}
// Issue an event if compression is enabled
CompressContext : : Type comp_type = Base : : conf ( ) . comp_ctx . type ( ) ;
if ( comp_type ! = CompressContext : : NONE
& & ! CompressContext : : is_any_stub ( comp_type ) )
{
std : : ostringstream msg ;
msg < < ( proto_context_options - > is_comp_asym ( )
? " Asymmetric compression enabled. Server may send compressed data. "
: " Compression enabled. " ) ;
msg < < " This may be a potential security issue. " ;
ClientEvent : : Base : : Ptr ev = new ClientEvent : : CompressionEnabled ( msg . str ( ) ) ;
cli_events - > add_event ( std : : move ( ev ) ) ;
}
2017-12-06 09:04:02 +01:00
}
2021-09-16 02:07:21 +02:00
// base class calls here when session transitions to ACTIVE state
void active ( bool primary ) override
2012-02-06 21:39:10 +01:00
{
2021-09-16 02:07:21 +02:00
if ( primary )
{
OPENVPN_LOG ( " Session is ACTIVE " ) ;
check_tls_warnings ( ) ;
schedule_push_request_callback ( Time : : Duration : : seconds ( 0 ) ) ;
}
else if ( notify_callback )
notify_callback - > client_proto_renegotiated ( ) ;
2012-02-06 21:39:10 +01:00
}
2017-03-30 23:10:56 +02:00
void housekeeping_callback ( const openvpn_io : : error_code & e )
2012-02-06 21:39:10 +01:00
{
try {
2012-02-07 21:52:40 +01:00
if ( ! e & & ! halt )
2012-02-06 21:39:10 +01:00
{
// update current time
Base : : update_now ( ) ;
housekeeping_schedule . reset ( ) ;
Base : : housekeeping ( ) ;
if ( Base : : invalidated ( ) )
{
2012-02-07 12:37:35 +01:00
if ( notify_callback )
2012-02-06 21:39:10 +01:00
{
2013-05-22 09:46:52 +02:00
OPENVPN_LOG ( " Session invalidated: " < < Error : : name ( Base : : invalidation_reason ( ) ) ) ;
2012-02-06 21:39:10 +01:00
stop ( true ) ;
}
else
throw session_invalidated ( ) ;
}
set_housekeeping_timer ( ) ;
}
}
2012-02-17 20:28:44 +01:00
catch ( const std : : exception & e )
2012-02-04 11:24:54 +01:00
{
2012-07-01 17:37:46 +02:00
process_exception ( e , " housekeeping_callback " ) ;
2012-02-06 21:39:10 +01:00
}
}
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
void set_housekeeping_timer ( )
{
2015-04-07 07:00:48 +02:00
if ( halt )
return ;
2012-02-06 21:39:10 +01:00
Time next = Base : : next_housekeeping ( ) ;
if ( ! housekeeping_schedule . similar ( next ) )
{
if ( ! next . is_infinite ( ) )
{
next . max ( now ( ) ) ;
housekeeping_schedule . reset ( next ) ;
housekeeping_timer . expires_at ( next ) ;
2017-03-30 23:10:56 +02:00
housekeeping_timer . async_wait ( [ self = Ptr ( this ) ] ( const openvpn_io : : error_code & error )
2015-06-25 21:59:12 +02:00
{
2018-03-23 15:23:45 +01:00
OPENVPN_ASYNC_HANDLER ;
2015-06-25 21:59:12 +02:00
self - > housekeeping_callback ( error ) ;
} ) ;
2012-02-06 21:39:10 +01:00
}
else
2012-02-04 11:24:54 +01:00
{
2012-02-06 21:39:10 +01:00
housekeeping_timer . cancel ( ) ;
2017-10-20 23:17:23 +02:00
housekeeping_schedule . reset ( ) ;
2012-02-04 11:24:54 +01:00
}
}
}
2015-06-17 09:48:33 +02:00
void process_inactive ( const OptionList & opt )
2013-05-25 03:19:50 +02:00
{
try {
2016-09-01 23:19:00 +02:00
const Option * o = load_duration_parm ( inactive_duration , " inactive " , opt , 1 , false , false ) ;
2013-05-25 03:19:50 +02:00
if ( o )
{
if ( o - > size ( ) > = 3 )
inactive_bytes = parse_number_throw < unsigned int > ( o - > get ( 2 , 16 ) , " inactive bytes " ) ;
schedule_inactive_timer ( ) ;
}
}
catch ( const std : : exception & e )
{
2018-03-07 23:59:07 +01:00
OPENVPN_LOG ( " exception parsing inactive: " < < e . what ( ) ) ;
2013-05-25 03:19:50 +02:00
}
}
void schedule_inactive_timer ( )
{
2017-04-12 22:01:11 +02:00
inactive_timer . expires_after ( inactive_duration ) ;
2017-03-30 23:10:56 +02:00
inactive_timer . async_wait ( [ self = Ptr ( this ) ] ( const openvpn_io : : error_code & error )
2015-06-25 21:59:12 +02:00
{
2018-03-23 15:23:45 +01:00
OPENVPN_ASYNC_HANDLER ;
2015-06-25 21:59:12 +02:00
self - > inactive_callback ( error ) ;
} ) ;
2013-05-25 03:19:50 +02:00
}
2017-03-30 23:10:56 +02:00
void inactive_callback ( const openvpn_io : : error_code & e ) // fixme for DCO
2013-05-25 03:19:50 +02:00
{
try {
if ( ! e & & ! halt )
{
// update current time
Base : : update_now ( ) ;
const count_t sample = cli_stats - > get_stat ( SessionStats : : TUN_BYTES_IN ) + cli_stats - > get_stat ( SessionStats : : TUN_BYTES_OUT ) ;
const count_t delta = sample - inactive_last_sample ;
//OPENVPN_LOG("*** INACTIVE SAMPLE " << delta << ' ' << inactive_bytes);
if ( delta < = count_t ( inactive_bytes ) )
{
fatal_ = Error : : INACTIVE_TIMEOUT ;
send_explicit_exit_notify ( ) ;
if ( notify_callback )
{
OPENVPN_LOG ( " inactive timer expired " ) ;
stop ( true ) ;
}
else
throw inactive_timer_expired ( ) ;
}
else
{
inactive_last_sample = sample ;
schedule_inactive_timer ( ) ;
}
}
}
catch ( const std : : exception & e )
{
process_exception ( e , " inactive_callback " ) ;
}
}
2016-03-28 08:31:35 +02:00
void process_echo ( const OptionList & opt )
{
OptionList : : IndexMap : : const_iterator echo_opt = opt . map ( ) . find ( " echo " ) ;
if ( echo_opt ! = opt . map ( ) . end ( ) )
{
for ( OptionList : : IndexList : : const_iterator i = echo_opt - > second . begin ( ) ; i ! = echo_opt - > second . end ( ) ; + + i )
{
const Option & o = opt [ * i ] ;
o . touch ( ) ;
const std : : string & value = o . get ( 1 , 512 ) ;
ClientEvent : : Base : : Ptr ev = new ClientEvent : : Echo ( value ) ;
2016-05-11 05:26:34 +02:00
cli_events - > add_event ( std : : move ( ev ) ) ;
2016-03-28 08:31:35 +02:00
}
}
}
2012-07-01 17:37:46 +02:00
void process_exception ( const std : : exception & e , const char * method_name )
2012-02-06 21:39:10 +01:00
{
2012-02-07 12:37:35 +01:00
if ( notify_callback )
2012-02-06 21:39:10 +01:00
{
2012-07-01 17:37:46 +02:00
OPENVPN_LOG ( " Client exception in " < < method_name < < " : " < < e . what ( ) ) ;
2012-02-06 21:39:10 +01:00
stop ( true ) ;
}
else
throw client_exception ( e . what ( ) ) ;
}
2012-02-04 11:24:54 +01:00
2012-03-31 18:08:20 +02:00
void process_halt_restart ( const ClientHalt & ch )
{
2014-01-08 05:32:37 +01:00
if ( ! ch . psid ( ) & & creds )
2019-01-02 21:58:08 +01:00
creds - > purge_session_id ( ) ;
2014-01-08 05:32:37 +01:00
if ( ch . restart ( ) )
2012-03-31 18:08:20 +02:00
fatal_ = Error : : CLIENT_RESTART ;
else
fatal_ = Error : : CLIENT_HALT ;
fatal_reason_ = ch . reason ( ) ;
if ( notify_callback )
{
OPENVPN_LOG ( " Client halt/restart: " < < ch . render ( ) ) ;
stop ( true ) ;
}
else
throw client_halt_restart ( ch . render ( ) ) ;
}
2016-08-17 23:23:26 +02:00
void schedule_info_hold_callback ( )
{
2016-09-02 20:52:21 +02:00
Base : : update_now ( ) ;
2017-04-12 22:01:11 +02:00
info_hold_timer . expires_after ( Time : : Duration : : seconds ( 1 ) ) ;
2017-03-30 23:10:56 +02:00
info_hold_timer . async_wait ( [ self = Ptr ( this ) ] ( const openvpn_io : : error_code & error )
2016-08-17 23:23:26 +02:00
{
2018-03-23 15:23:45 +01:00
OPENVPN_ASYNC_HANDLER ;
2016-08-17 23:23:26 +02:00
self - > info_hold_callback ( error ) ;
} ) ;
}
2017-03-30 23:10:56 +02:00
void info_hold_callback ( const openvpn_io : : error_code & e )
2016-08-17 23:23:26 +02:00
{
try {
if ( ! e & & ! halt )
{
Base : : update_now ( ) ;
if ( info_hold )
{
for ( auto & ev : * info_hold )
cli_events - > add_event ( std : : move ( ev ) ) ;
info_hold . reset ( ) ;
}
}
}
catch ( const std : : exception & e )
{
process_exception ( e , " info_hold_callback " ) ;
}
}
2012-02-06 21:39:10 +01:00
# ifdef OPENVPN_PACKET_LOG
void log_packet ( const Buffer & buf , const bool out )
{
if ( buf . size ( ) )
{
2015-04-24 01:55:07 +02:00
std : : uint16_t len = buf . size ( ) & 0x7FFF ;
2012-02-06 21:39:10 +01:00
if ( out )
len | = 0x8000 ;
packet_log . write ( ( const char * ) & len , sizeof ( len ) ) ;
packet_log . write ( ( const char * ) buf . c_data ( ) , buf . size ( ) ) ;
}
}
# endif
2012-02-04 11:24:54 +01:00
2017-03-30 23:10:56 +02:00
openvpn_io : : io_context & io_context ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
TransportClientFactory : : Ptr transport_factory ;
TransportClient : : Ptr transport ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
TunClientFactory : : Ptr tun_factory ;
TunClient : : Ptr tun ;
2012-02-04 11:24:54 +01:00
2015-10-19 08:32:13 +02:00
unsigned int tcp_queue_limit ;
2016-08-17 22:30:22 +02:00
bool transport_has_send_queue = false ;
2015-10-19 08:32:13 +02:00
2012-02-07 12:37:35 +01:00
NotifyCallback * notify_callback ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
CoarseTime housekeeping_schedule ;
AsioTimer housekeeping_timer ;
AsioTimer push_request_timer ;
2016-08-17 22:30:22 +02:00
bool halt = false ;
2012-02-04 11:24:54 +01:00
2012-02-06 21:39:10 +01:00
OptionListContinuation received_options ;
2012-02-04 11:24:54 +01:00
2012-02-28 00:00:29 +01:00
ClientCreds : : Ptr creds ;
2012-02-04 11:24:54 +01:00
2012-09-08 03:36:54 +02:00
ProtoContextOptions : : Ptr proto_context_options ;
2012-09-05 03:09:34 +02:00
2016-08-17 22:30:22 +02:00
bool first_packet_received_ = false ;
bool sent_push_request = false ;
2018-04-12 22:32:14 +02:00
bool auth_pending = false ;
2012-10-31 15:46:40 +01:00
SessionStats : : Ptr cli_stats ;
2012-02-06 21:39:10 +01:00
ClientEvent : : Queue : : Ptr cli_events ;
2012-02-04 11:24:54 +01:00
2016-09-02 20:52:21 +02:00
ClientEvent : : Connected : : Ptr connected_ ;
2012-02-19 02:36:50 +01:00
2016-03-28 08:31:35 +02:00
bool echo ;
2016-05-11 01:53:09 +02:00
bool info ;
2016-06-29 08:57:24 +02:00
bool autologin_sessions ;
2016-03-28 08:31:35 +02:00
2016-08-17 22:30:22 +02:00
Error : : Type fatal_ = Error : : UNDEF ;
2012-02-19 02:36:50 +01:00
std : : string fatal_reason_ ;
2012-11-12 02:52:03 +01:00
OptionList : : Limits pushed_options_limit ;
2013-03-14 03:54:58 +01:00
OptionList : : FilterBase : : Ptr pushed_options_filter ;
2012-02-07 12:37:35 +01:00
2013-05-25 03:19:50 +02:00
AsioTimer inactive_timer ;
Time : : Duration inactive_duration ;
2016-08-17 22:30:22 +02:00
unsigned int inactive_bytes = 0 ;
count_t inactive_last_sample = 0 ;
2013-05-25 03:19:50 +02:00
2016-08-17 23:23:26 +02:00
std : : unique_ptr < std : : vector < ClientEvent : : Base : : Ptr > > info_hold ;
AsioTimer info_hold_timer ;
2012-02-04 11:24:54 +01:00
# ifdef OPENVPN_PACKET_LOG
2012-02-06 21:39:10 +01:00
std : : ofstream packet_log ;
2012-02-04 11:24:54 +01:00
# endif
2012-02-06 21:39:10 +01:00
} ;
}
2012-02-04 11:24:54 +01:00
}
# endif