OpenVPN 3 Core Library
Loading...
Searching...
No Matches
cliproto.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#ifndef OPENVPN_CLIENT_CLIPROTO_H
13#define OPENVPN_CLIENT_CLIPROTO_H
14
15// This is a middle-layer object in the OpenVPN client protocol stack.
16// It is above the general OpenVPN protocol implementation in
17// class ProtoContext but below the top
18// level object in a client connect (ClientConnect). See ClientConnect for
19// a fuller description of the full client stack.
20//
21// This layer deals with setting up an OpenVPN client connection:
22//
23// 1. handles creation of transport-layer handler via TransportClientFactory
24// 2. handles creation of tun-layer handler via TunClientFactory
25// 3. handles sending PUSH_REQUEST to server and processing reply of server-pushed options
26// 4. manages the underlying OpenVPN protocol object (class ProtoContext)
27// 5. handles timers on behalf of the underlying OpenVPN protocol object
28// 6. acts as an exception dispatcher for errors occuring in any of the underlying layers
29
30#include <string>
31#include <vector>
32#include <memory>
33#include <algorithm> // for std::min
34#include <cstdint> // for std::uint...
35using namespace std::chrono_literals;
36
37#include <openvpn/io/io.hpp>
38
39#include <openvpn/common/rc.hpp>
44#include <openvpn/ip/ptb.hpp>
60
61#include <openvpn/ssl/proto.hpp>
63
64#ifdef OPENVPN_DEBUG_CLIPROTO
65#define OPENVPN_LOG_CLIPROTO(x) OPENVPN_LOG(x)
66#else
67#define OPENVPN_LOG_CLIPROTO(x)
68#endif
69
71
73
75{
76 virtual ~NotifyCallback() = default;
77
78 virtual void client_proto_terminate() = 0;
80 {
81 }
82 virtual void client_proto_auth_pending_timeout(int timeout)
83 {
84 }
86 {
87 }
88};
89
93 public RC<thread_unsafe_refcount>
94{
95 static inline const std::string certcheckProto = "cck1";
96
97 public:
99
100 OPENVPN_EXCEPTION(client_exception);
101 OPENVPN_EXCEPTION(client_halt_restart);
102 OPENVPN_EXCEPTION(tun_exception);
103 OPENVPN_EXCEPTION(transport_exception);
104 OPENVPN_EXCEPTION(max_pushed_options_exceeded);
105 OPENVPN_SIMPLE_EXCEPTION(session_invalidated);
106 OPENVPN_SIMPLE_EXCEPTION(authentication_failed);
107 OPENVPN_SIMPLE_EXCEPTION(inactive_timer_expired);
109
110 OPENVPN_EXCEPTION(proxy_exception);
111
112 struct Config : public RC<thread_unsafe_refcount>
113 {
115
117 : pushed_options_limit("server-pushed options data too large",
118 ProfileParseLimits::MAX_PUSH_SIZE,
119 ProfileParseLimits::OPT_OVERHEAD,
120 ProfileParseLimits::TERM_OVERHEAD,
121 0,
122 ProfileParseLimits::MAX_DIRECTIVE_SIZE)
123 {
124 }
125
136 unsigned int tcp_queue_limit = 0;
137 bool echo = false;
138 bool info = false;
139 bool autologin_sessions = false;
140 };
141
142 Session(openvpn_io::io_context &io_context_arg,
143 const Config &config,
144 NotifyCallback *notify_callback_arg)
145 : proto_context(this, config.proto_context_config, config.cli_stats),
146 io_context(io_context_arg),
150 notify_callback(notify_callback_arg),
151 housekeeping_timer(io_context_arg),
152 push_request_timer(io_context_arg),
153 received_options(config.push_base),
162 inactive_timer(io_context_arg),
163 info_hold_timer(io_context_arg)
164 {
165#ifdef OPENVPN_PACKET_LOG
166 packet_log.open(OPENVPN_PACKET_LOG, std::ios::binary);
167 if (!packet_log)
168 OPENVPN_THROW(open_file_error, "cannot open packet log for output: " << OPENVPN_PACKET_LOG);
169#endif
172 // proto_context.enable_strict_openvpn_2x();
173
174 info_hold.reset(new std::vector<ClientEvent::Base::Ptr>());
175 }
176
178 {
180 }
181
182 void start()
183 {
184 if (!halt)
185 {
187
188 // coarse wakeup range
189 housekeeping_schedule.init(Time::Duration::binary_ms(512), Time::Duration::binary_ms(1024));
190
191 // initialize transport-layer packet handler
196 else
198 }
199 }
200
207
209 {
210 transport_factory = std::move(factory);
211 }
212
218
220 {
221 if (tun)
223 }
224
231 void validate_and_post_cc_msg(const std::string &msg)
232 {
234 {
235 ClientEvent::Base::Ptr ev = new ClientEvent::UnsupportedFeature{"Invalid chars in control message", "Control channel message with invalid characters not allowed to be send with post_cc_msg", false};
236 cli_events->add_event(std::move(ev));
237 return;
238 }
240 }
241
248 void post_cc_msg(const std::string &msg)
249 {
252 proto_context.flush(true);
254 }
255
256 void post_app_control_message(const std::string proto, const std::string message)
257 {
259 {
260 ClientEvent::Base::Ptr ev = new ClientEvent::UnsupportedFeature{"missing acc protocol support", "server has not announced support of this custom app control protocol", false};
261 cli_events->add_event(std::move(ev));
262 return;
263 }
264
265 for (auto fragment : proto_context.conf().app_control_config.format_message(proto, message))
266 post_cc_msg(std::move(fragment));
267 }
268
269 void stop(const bool call_terminate_callback)
270 {
271 if (!halt)
272 {
273 halt = true;
274 housekeeping_timer.cancel();
275 push_request_timer.cancel();
276
277 out_tun_callback_.reset();
278 in_tun_callback_.reset();
279 inactive_timer.cancel();
280
281 info_hold_timer.cancel();
282 if (notify_callback && call_terminate_callback)
284 if (tun)
285 tun->stop(); // call after client_proto_terminate() so it can call back to tun_set_disconnect
286 if (transport)
287 transport->stop();
288 }
289 }
290
291 void stop_on_signal(const openvpn_io::error_code &error, int signal_number)
292 {
293 stop(true);
294 }
295
297 {
298 return bool(connected_);
299 }
300
301 // If fatal() returns something other than Error::UNDEF, it
302 // is intended to flag the higher levels (cliconnect.hpp)
303 // that special handling is required. This handling might include
304 // considering the error to be fatal and stopping future connect
305 // retries, or emitting a special event. See cliconnect.hpp
306 // for actual implementation.
308 {
309 return fatal_;
310 }
311 const std::string &fatal_reason() const
312 {
313 return fatal_reason_;
314 }
315
316 // Getters for values which could potentially be modified by
317 // a server's AUTH_FAILED,TEMP response flags
319 {
320 return temp_fail_advance_;
321 }
322 std::chrono::milliseconds reconnect_delay() const
323 {
324 return temp_fail_backoff_;
325 }
326
333 void start_acc_certcheck(SSLLib::SSLAPI::Config::Ptr config)
334 {
335 certcheck_hs.reset(std::move(config));
336 do_acc_certcheck(std::string(""));
337 }
338
339 virtual ~Session()
340 {
341 stop(false);
342 }
343
344 private:
346 {
347 return true;
348 }
349
350 // transport obj calls here with incoming packets
351 void transport_recv(BufferAllocated &buf) override
352 {
353 try
354 {
355 OPENVPN_LOG_CLIPROTO("Transport RECV " << server_endpoint_render() << ' ' << proto_context.dump_packet(buf));
356
357 // update current time
359
360 // update last packet received
362
363 // log connecting event (only on first packet received)
365 {
367 cli_events->add_event(std::move(ev));
369 }
370
371 // get packet type
373
374 // process packet
375 if (pt.is_data())
376 {
377 // data packet
379 if (buf.size())
380 {
381#ifdef OPENVPN_PACKET_LOG
382 log_packet(buf, false);
383#endif
384 // make packet appear as incoming on tun interface
385 if (tun)
386 {
387 OPENVPN_LOG_CLIPROTO("TUN send, size=" << buf.size());
388 tun->tun_send(buf);
389 }
390 }
391
392 // do a lightweight flush
393 proto_context.flush(false);
394 }
395 else if (pt.is_control())
396 {
397 // control packet
398 proto_context.control_net_recv(pt, std::move(buf));
399
400 // do a full flush
401 proto_context.flush(true);
402 }
403 else
405
406 // schedule housekeeping wakeup
408 }
409 catch (const ExceptionCode &e)
410 {
411 if (e.code_defined())
412 {
413 if (e.fatal())
414 transport_error((Error::Type)e.code(), e.what());
415 else
417 }
418 else
419 process_exception(e, "transport_recv_excode");
420 }
421 catch (const std::exception &e)
422 {
423 process_exception(e, "transport_recv");
424 }
425 }
426
427 void transport_needs_send() override
428 {
429 }
430
431 // tun i/o driver calls here with incoming packets
432 void tun_recv(BufferAllocated &buf) override
433 {
434 try
435 {
436 OPENVPN_LOG_CLIPROTO("TUN recv, size=" << buf.size());
437
438 // update current time
440
441 // log packet
442#ifdef OPENVPN_PACKET_LOG
443 log_packet(buf, true);
444#endif
445
446 // if transport layer has an output queue, check if it's full
448 {
450 {
451 buf.reset_size(); // queue full, drop packet
453 }
454 }
455
456 // encrypt packet
457 if (buf.size())
458 {
460
461 bool df = true;
462
463 if (IPCommon::version(buf[0]) == IPCommon::IPv4 && buf.size() >= sizeof(struct IPv4Header))
464 {
465 df = IPv4Header::is_df_set(buf.c_data());
466 }
467
468 // when calculating mss, we take IPv4 and TCP headers into account
469 // here we need to add it back since we check the whole IP packet size, not just TCP payload
470 constexpr size_t MinTcpHeader = 20;
471 constexpr size_t MinIpHeader = 20;
472 size_t mss_no_tcp_ip_encap = c.mss_fix + (MinTcpHeader + MinIpHeader);
473
474 if (df && c.mss_fix > 0 && buf.size() > mss_no_tcp_ip_encap)
475 {
476 Ptb::generate_icmp_ptb(buf, clamp_to_typerange<unsigned short>(mss_no_tcp_ip_encap));
477 tun->tun_send(buf);
478 }
479 else
480 {
482 if (buf.size())
483 {
484 // send packet via transport to destination
485 OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << proto_context.dump_packet(buf));
486 if (transport->transport_send(buf))
488 else if (halt)
489 return;
490 }
491 }
492 }
493
494 // do a lightweight flush
495 proto_context.flush(false);
496
497 // schedule housekeeping wakeup
499 }
500 catch (const std::exception &e)
501 {
502 process_exception(e, "tun_recv");
503 }
504 }
505
506 // Return true if keepalive parameter(s) are enabled.
507 bool is_keepalive_enabled() const override
508 {
510 }
511
512 // Disable keepalive for rest of session, but fetch
513 // the keepalive parameters (in seconds).
514 void disable_keepalive(unsigned int &keepalive_ping,
515 unsigned int &keepalive_timeout) override
516 {
517 proto_context.disable_keepalive(keepalive_ping, keepalive_timeout);
518 }
519
520 void transport_pre_resolve() override
521 {
523 cli_events->add_event(std::move(ev));
524 }
525
527 {
528 std::string server_host, server_port, server_proto, server_ip;
529 transport->server_endpoint_info(server_host, server_port, server_proto, server_ip);
530 std::ostringstream out;
531 out << '[' << server_host << "]:" << server_port << " (" << server_ip << ") via " << server_proto;
532 return out.str();
533 }
534
535 void transport_wait_proxy() override
536 {
538 cli_events->add_event(std::move(ev));
539 }
540
541 void transport_wait() override
542 {
544 cli_events->add_event(std::move(ev));
545 }
546
547 void transport_connecting() override
548 {
549 try
550 {
552 OPENVPN_LOG("Connecting to " << server_endpoint_render());
555 proto_context.flush(true);
557 }
558 catch (const std::exception &e)
559 {
560 process_exception(e, "transport_connecting");
561 }
562 }
563
564 void transport_error(const Error::Type fatal_err, const std::string &err_text) override
565 {
566 if (fatal_err != Error::UNDEF)
567 {
568 fatal_ = fatal_err;
569 fatal_reason_ = err_text;
570 }
571 if (notify_callback)
572 {
573 OPENVPN_LOG("Transport Error: " << err_text);
574 stop(true);
575 }
576 else
577 throw transport_exception(err_text);
578 }
579
580 void proxy_error(const Error::Type fatal_err, const std::string &err_text) override
581 {
582 if (fatal_err != Error::UNDEF)
583 {
584 fatal_ = fatal_err;
585 fatal_reason_ = err_text;
586 }
587 if (notify_callback)
588 {
589 OPENVPN_LOG("Proxy Error: " << err_text);
590 stop(true);
591 }
592 else
593 throw proxy_exception(err_text);
594 }
595
597 {
598 std::string username;
599
600 // auth-token-user
601 {
602 const Option *o = opt.get_ptr("auth-token-user");
603 if (o)
604 username = base64->decode(o->get(1, 340)); // 255 chars after base64 decode
605 }
606
607 // auth-token
608 {
609 // if auth-token is present, use it as the password for future renegotiations
610 const Option *o = opt.get_ptr("auth-token");
611 if (o)
612 {
613 const std::string &sess_id = o->get(1, 256);
614 if (creds)
615 {
616 if (!username.empty())
617 OPENVPN_LOG("Session user: " << username);
618#ifdef OPENVPN_SHOW_SESSION_TOKEN
619 OPENVPN_LOG("Session token: " << sess_id);
620#else
621 OPENVPN_LOG("Session token: [redacted]");
622#endif
624 creds->set_session_id(username, sess_id);
625 }
626 }
627 }
628 }
629
651 std::string parse_auth_failed_temp(const std::string &msg)
652 {
653 if (msg.empty())
654 return msg;
655
656 // Reset to default values
657 temp_fail_backoff_ = 0ms;
659
660 std::string::size_type reason_idx = 0;
661 auto endofflags = msg.find(']');
662 if (msg.at(0) == '[' && endofflags != std::string::npos)
663 {
664 reason_idx = ++endofflags;
665 auto flags = string::split(std::string{msg, 1, endofflags - 2}, ',');
666 for (const auto &flag : flags)
667 {
668 std::string key;
669 std::string value;
670 std::istringstream f(flag);
671
672 f >> key >> value;
673 if (f.fail())
674 {
675 OPENVPN_LOG("invalid AUTH_FAILED,TEMP flag: " << flag);
676 continue;
677 }
678
679 if (key == "backoff")
680 {
681 int timeout;
682 if (!parse_number(value, timeout))
683 {
684 OPENVPN_LOG("invalid AUTH_FAILED,TEMP flag: " << flag);
685 }
686 temp_fail_backoff_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::seconds{timeout});
687 }
688 else if (key == "advance")
689 {
690 if (value == "no")
691 {
693 }
694 else if (value == "addr")
695 {
697 }
698 else if (value == "remote")
699 {
701 }
702 else
703 {
704 OPENVPN_LOG("unknown AUTH_FAILED,TEMP flag: " << flag);
705 }
706 }
707 else
708 {
709 OPENVPN_LOG("unknown AUTH_FAILED,TEMP flag: " << flag);
710 }
711 }
712 }
713
714 if (reason_idx >= msg.size() || msg[reason_idx] != ':')
715 return "";
716
717 // skip leading colon
718 return msg.substr(reason_idx + 1);
719 }
720
721 // proto base class calls here for control channel network sends
722 void control_net_send(const Buffer &net_buf) override
723 {
724 OPENVPN_LOG_CLIPROTO("Transport SEND " << server_endpoint_render() << ' ' << proto_context.dump_packet(net_buf));
725 if (transport->transport_send_const(net_buf))
727 }
728
729 void recv_auth_failed(const std::string &msg)
730 {
731 std::string reason;
732 std::string log_reason;
733
734 // get reason (if it exists) for authentication failure
735 if (msg.length() >= 13)
736 reason = string::trim_left_copy(std::string(msg, 12));
737
738 if (string::starts_with(reason, "TEMP"))
739 {
740 log_reason = "AUTH_FAILED_TEMP:" + parse_auth_failed_temp(std::string(reason, 4));
741 }
742 else
743 {
744 bool password_defined = false;
745 bool session_id_defined = false;
746 if (creds)
747 {
748 password_defined = creds->password_defined();
749 session_id_defined = creds->session_id_defined();
750
751 // authentication failure, purge auth-token
753 }
754
755 // do we have a session-id?
756 if (session_id_defined)
757 {
758 bool reconnect = false;
759
760 // if there was an OOB auth (server pushed AUTH_PENDING) throw a fatal error since we need a user input
762 {
763 // reconnect if we have a password OR password is not needed
764 if (!creds->password_needed() || password_defined)
765 {
766 reconnect = true;
767 }
768 }
769
770 OPENVPN_LOG("need_user_interaction: " << creds->need_user_interaction() << ", pw_needed: " << creds->password_needed() << ", pw_defined: " << password_defined << ", reconnect: " << reconnect);
771
772 if (reconnect)
773 {
774 log_reason = "SESSION_AUTH_FAILED";
775 }
776 else
777 {
778 // we don't have a password and we need a user input, throw a fatal error and let the client to re-authenticate
780 fatal_reason_ = reason;
781 log_reason = "SESSION_EXPIRED";
782 }
783 }
784 else
785 {
786 // no session-id, throw fatal error
788 fatal_reason_ = reason;
789 log_reason = "AUTH_FAILED";
790 }
791 }
792
793 if (notify_callback)
794 {
795 OPENVPN_LOG(log_reason);
796 stop(true);
797 }
798 else
799 throw authentication_failed();
800 }
801
802 void recv_auth_pending(const std::string &msg)
803 {
804 // AUTH_PENDING indicates an out-of-band authentication step must
805 // be performed before the server will send the PUSH_REPLY message.
806 if (!auth_pending)
807 {
808 auth_pending = true;
809 std::string key_words;
810
811 unsigned int timeout = 0;
812
813 if (string::starts_with(msg, "AUTH_PENDING,"))
814 {
815 key_words = msg.substr(strlen("AUTH_PENDING,"));
816 auto opts = OptionList::parse_from_csv_static(key_words, nullptr);
817 std::string timeout_str = opts.get_optional("timeout", 1, 20);
818 if (timeout_str != "")
819 {
820 try
821 {
822 timeout = clamp_to_typerange<unsigned int>(std::stoul(timeout_str));
823 // Cap the timeout to end well before renegotiation starts
824 timeout = std::min(timeout, static_cast<decltype(timeout)>(proto_context.conf().renegotiate.to_seconds() / 2));
825 }
826 catch (const std::logic_error &)
827 {
828 OPENVPN_LOG("could not parse AUTH_PENDING timeout: " << timeout_str);
829 }
830 }
831 }
832
833 if (notify_callback && timeout > 0)
834 {
836 }
837
838 ClientEvent::Base::Ptr ev = new ClientEvent::AuthPending(timeout, std::move(key_words));
839 cli_events->add_event(std::move(ev));
840 }
841 }
842
844 {
846 {
848 fatal_reason_ = "";
849 }
850 else
851 {
853 fatal_reason_ = "not in relay mode";
854 }
855 if (notify_callback)
856 {
858 stop(true);
859 }
860 else
861 throw relay_event();
862 }
863
864 void recv_info(const std::string &msg, bool info_pre)
865 {
866 // Buffer INFO messages received near Connected event to fire
867 // one second after Connected event, to reduce the chance of
868 // race conditions in the client app, if the INFO event
869 // triggers the client app to perform an operation that
870 // requires the VPN tunnel to be ready.
871 std::string info_msg;
872
873 if (info_pre)
874 info_msg = msg.substr(std::string_view{"INFO_PRE,"}.length());
875 else
876 info_msg = msg.substr(std::string_view{"INFO,"}.length());
877
878 if (string::starts_with(info_msg, "ACC:"))
879 {
880 // We want this to be parsed exactly like the custom-control option.
881 // That means we replace ACC: with custom-control for the parser.
882 auto acc_options = OptionList::parse_from_csv_static("custom-control " + info_msg.substr(std::strlen("ACC:")), &pushed_options_limit);
884 // check if we need to notify about ACC protocols
886 }
887 else
888 {
889 if ((string::starts_with(info_msg, "WEB_AUTH:") || string::starts_with(info_msg, "CR_TEXT:")) && creds)
890 {
892 }
893
894 ClientEvent::Info::Ptr ev = new ClientEvent::Info(std::move(info_msg));
895
896 // INFO_PRE is like INFO but it is never buffered
897 if (info_hold && !info_pre)
898 info_hold->push_back(std::move(ev));
899 else
900 cli_events->add_event(std::move(ev));
901 }
902 }
903
909 void recv_push_update(const std::string &msg)
910 {
912
913 // parse the received options
914 auto opt_str = msg.substr(strlen("PUSH_UPDATE,"));
916
918
920 {
921 // show options
922 OPENVPN_LOG("PUSH UPDATE:\n"
924
925 // Merge local and pushed options
927
928 if (tun)
929 {
931 }
932 }
933 }
934
935 // proto base class calls here for app-level control-channel messages received
936 void control_recv(BufferPtr &&app_bp) override
937 {
938 const std::string msg = ProtoContext::read_control_string<std::string>(*app_bp);
940 {
941 OPENVPN_LOG("Control channel message with invalid characters received, ignoring message");
942 return;
943 }
944
945 // OPENVPN_LOG("SERVER: " << sanitize_control_message(msg));
946
947 if (string::starts_with(msg, "PUSH_REPLY,"))
948 {
950 }
951 else if (string::starts_with(msg, "AUTH_FAILED"))
952 {
954 }
955 else if (ClientHalt::match(msg))
956 {
958 }
959 else if (info && string::starts_with(msg, "INFO,"))
960 {
961 recv_info(msg, false);
962 }
963 else if (info && string::starts_with(msg, "INFO_PRE,"))
964 {
965 recv_info(msg, true);
966 }
967 else if (msg == "AUTH_PENDING" || string::starts_with(msg, "AUTH_PENDING,"))
968 {
970 }
971 else if (msg == "RELAY")
972 {
973 recv_relay();
974 }
975 else if (string::starts_with(msg, "ACC,"))
976 {
978 }
979 else if (string::starts_with(msg, "PUSH_UPDATE,"))
980 {
982 }
983 }
984
994 void recv_custom_control_message(const std::string msg)
995 {
997 if (!fullmessage)
998 return;
999
1000 auto [proto, app_proto_msg] = proto_context.conf().app_control_recv.get_message();
1001
1002 if (proto == certcheckProto) // handle this built-in ACC internal protocol intrinsically
1003 {
1004 do_acc_certcheck(app_proto_msg);
1005 }
1007 {
1008 ClientEvent::Base::Ptr ev = new ClientEvent::AppCustomControlMessage(std::move(proto), std::move(app_proto_msg));
1009 cli_events->add_event(std::move(ev));
1010 }
1011 else
1012 {
1013 OPENVPN_LOG("App custom control message with unsupported protocol [" + proto + "] received");
1014 }
1015 }
1021 void do_acc_certcheck(const std::string &msg_str)
1022 {
1023 AccHandshaker::MsgT reply = std::nullopt;
1024 AccHandshaker::MsgT msg = std::nullopt;
1025
1026 if (msg_str.empty() == false)
1027 msg = msg_str;
1028
1029 try
1030 {
1031 do
1032 {
1033 reply = certcheck_hs.process_msg(msg);
1034
1035 if (reply)
1036 {
1038 }
1039 msg = std::nullopt;
1040 } while (reply);
1041 }
1042 catch (std::exception &ex)
1043 {
1044 OPENVPN_LOG("App custom control cert check exception: " << ex.what());
1045 }
1046 }
1047
1049 {
1051 {
1052 // Signal support for supported protocols
1054 cli_events->add_event(std::move(ev));
1055 }
1056 }
1057
1058 void recv_push_reply(const std::string &msg)
1059 {
1061 {
1062 // parse the received options
1063 auto pushed_options_list = OptionList::parse_from_csv_static(msg.substr(11), &pushed_options_limit);
1064 try
1065 {
1066 received_options.add(pushed_options_list, pushed_options_filter.get());
1067 }
1068 catch (const Option::RejectedException &e)
1069 {
1070 recv_halt_restart("RESTART,rejected pushed option: " + e.err());
1071 }
1073 {
1074 // show options
1075 OPENVPN_LOG("OPTIONS:" << std::endl
1077
1078 // relay servers are not allowed to establish a tunnel with us
1080 {
1081 tun_error(Error::RELAY_ERROR, "tunnel not permitted to relay server");
1082 return;
1083 }
1084
1085 // Merge local and pushed options
1087
1088 // process "echo" directives
1089 if (echo)
1091
1092 // process auth-token
1094
1095 // process pushed transport options
1097
1098 // modify proto config (cipher, auth, key-derivation and compression methods)
1100
1101 // process pushed auth-nocache
1103 {
1105 }
1106
1107 // initialize tun/routing
1110
1111 // we should be connected at this point
1112 if (!connected_)
1113 throw tun_exception("not connected");
1114
1115 // Propagate tun-mtu back, it might have been overwritten by a pushed tun-mtu option
1117
1118 // initialize data channel after pushed options have been processed
1120
1121 // we got pushed options and initializated crypto - now we can push mss to dco
1123
1124 // Allow ProtoContext to suggest an alignment adjustment
1125 // hint for transport layer.
1127
1128 // process "inactive" directive
1130
1131 // tell parent that we are connected
1132 if (notify_callback)
1134
1135 // start info-hold timer
1137
1138 // send the Connected event
1139 cli_events->add_event(connected_);
1140
1141 // send an event for custom app control if present
1143
1144 // check for proto options
1146 }
1147 else
1148 OPENVPN_LOG("Options continuation...");
1149 }
1150 else if (received_options.complete())
1151 {
1152 // We got a PUSH REPLY in the middle of a session. Ignore it apart from
1153 // updating the auth-token if included in the push reply
1154 auto opts = OptionList::parse_from_csv_static(msg.substr(11), nullptr);
1155 extract_auth_token(opts);
1156 }
1157 }
1158
1159 void tun_pre_tun_config() override
1160 {
1162 cli_events->add_event(std::move(ev));
1163 }
1164
1165 void tun_pre_route_config() override
1166 {
1168 cli_events->add_event(std::move(ev));
1169 }
1170
1172 {
1173 cli_events->add_event(std::move(ev));
1174 }
1175
1176 void tun_connected() override
1177 {
1178 OPENVPN_LOG("Connected via " + tun->tun_name());
1179
1181 if (creds)
1182 ev->user = creds->get_username();
1183 transport->server_endpoint_info(ev->server_host, ev->server_port, ev->server_proto, ev->server_ip);
1184 ev->vpn_ip4 = tun->vpn_ip4();
1185 ev->vpn_ip6 = tun->vpn_ip6();
1186 ev->vpn_gw4 = tun->vpn_gw4();
1187 ev->vpn_gw6 = tun->vpn_gw6();
1188 if (tun->vpn_mtu())
1189 {
1190 ev->vpn_mtu = std::to_string(tun->vpn_mtu());
1191 }
1192 else
1193 {
1194 ev->vpn_mtu = "(default)";
1195 }
1196
1197 try
1198 {
1199 std::string client_ip = received_options.get_optional("client-ip", 1, 256);
1200 if (!client_ip.empty())
1201 ev->client_ip = IP::Addr::validate(client_ip, "client-ip");
1202 }
1203 catch (const std::exception &e)
1204 {
1205 OPENVPN_LOG("exception parsing client-ip: " << e.what());
1206 }
1207 ev->tun_name = tun->tun_name();
1208 connected_ = std::move(ev);
1209 }
1210
1211 void tun_error(const Error::Type fatal_err, const std::string &err_text) override
1212 {
1213 if (fatal_err == Error::TUN_HALT)
1215 if (fatal_err != Error::UNDEF)
1216 {
1217 fatal_ = fatal_err;
1218 fatal_reason_ = err_text;
1219 }
1220 if (notify_callback)
1221 {
1222 OPENVPN_LOG("TUN Error: " << err_text);
1223 stop(true);
1224 }
1225 else
1226 throw tun_exception(err_text);
1227 }
1228
1229 // proto base class calls here to get auth credentials
1230 void client_auth(Buffer &buf) override
1231 {
1232 // we never send creds to a relay server
1234 {
1235 OPENVPN_LOG("Creds: " << creds->auth_info());
1237 {
1238 throw ErrorCode(Error::NEED_CREDS, true, "missing password");
1239 }
1241#ifdef OPENVPN_DISABLE_AUTH_TOKEN // debugging only
1243 {
1244 OPENVPN_LOG("NOTE: not sending auth-token");
1246 }
1247 else
1248#endif
1249 {
1251 }
1252
1253 // save username for auth-token, which might be pushed later
1255
1257 {
1259 }
1260 }
1261 else
1262 {
1263 OPENVPN_LOG("Creds: None");
1264 write_empty_string(buf); // username
1265 write_empty_string(buf); // password
1266 }
1267 }
1268
1269 void send_push_request_callback(const Time::Duration &dur,
1270 const openvpn_io::error_code &e)
1271 {
1272 try
1273 {
1274 if (!e && !halt && !received_options.partial())
1275 {
1277 if (!sent_push_request)
1278 {
1280 cli_events->add_event(std::move(ev));
1281 sent_push_request = true;
1282 }
1283 OPENVPN_LOG("Sending PUSH_REQUEST to server...");
1284 proto_context.write_control_string(std::string("PUSH_REQUEST"));
1285 proto_context.flush(true);
1287
1288 {
1289 if (auth_pending)
1290 {
1291 // With auth_pending, we can dial back the PUSH_REQUEST
1292 // frequency, but we still need back-and-forth network
1293 // activity to avoid an inactivity timeout, since the crypto
1294 // layer (and hence keepalive ping) is not initialized until
1295 // we receive the PUSH_REPLY from the server.
1296 schedule_push_request_callback(Time::Duration::seconds(8));
1297 }
1298 else
1299 {
1300 // step function with ceiling: 1 sec, 2 secs, 3 secs, 3, 3, ...
1301 const Time::Duration newdur = std::min(dur + Time::Duration::seconds(1),
1302 Time::Duration::seconds(3));
1304 }
1305 }
1306 }
1307 }
1308 catch (const std::exception &e)
1309 {
1310 process_exception(e, "send_push_request_callback");
1311 }
1312 }
1313
1314 void schedule_push_request_callback(const Time::Duration &dur)
1315 {
1317 {
1319 push_request_timer.async_wait([self = Ptr(this), dur](const openvpn_io::error_code &error)
1320 {
1322 self->send_push_request_callback(dur, error); });
1323 }
1324 }
1325
1326 // react to any tls warning triggered during the tls-handshake
1327 virtual void check_tls_warnings()
1328 {
1329 uint32_t tls_warnings = proto_context.get_tls_warnings();
1330
1331 if (tls_warnings & SSLAPI::TLS_WARN_SIG_MD5)
1332 {
1333 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 in the near future");
1334 cli_events->add_event(std::move(ev));
1335 }
1336
1337 if (tls_warnings & SSLAPI::TLS_WARN_SIG_SHA1)
1338 {
1339 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");
1340 cli_events->add_event(std::move(ev));
1341 }
1342 }
1343
1345 {
1347 {
1348 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.");
1349 cli_events->add_event(std::move(ev));
1350 }
1351
1353
1354 // abort connection if compression is pushed and its support is unannounced
1355 if (comp_type != CompressContext::COMP_STUBv2
1356 && comp_type != CompressContext::NONE
1358 {
1359 throw ErrorCode(Error::COMPRESS_ERROR, true, "server pushed compression "
1360 "settings that are not allowed and will result "
1361 "in a non-working connection. ");
1362 }
1363
1364 // Issue an event if compression is enabled
1365 if (comp_type != CompressContext::NONE
1366 && !CompressContext::is_any_stub(comp_type))
1367 {
1368 std::ostringstream msg;
1370 ? "Asymmetric compression enabled. Server may send compressed data."
1371 : "Compression enabled.");
1372 msg << " This may be a potential security issue.";
1374 cli_events->add_event(std::move(ev));
1375 }
1376 }
1377
1378 // base class calls here when session transitions to ACTIVE state
1379 void active(bool primary) override
1380 {
1381 if (primary)
1382 {
1383 OPENVPN_LOG("Session is ACTIVE");
1385 schedule_push_request_callback(Time::Duration::seconds(0));
1386 }
1387 else if (notify_callback)
1389 }
1390
1391 bool supports_proto_v3() override
1392 {
1394 }
1395
1396 void housekeeping_callback(const openvpn_io::error_code &e)
1397 {
1398 try
1399 {
1400 if (!e && !halt)
1401 {
1402 // update current time
1404
1408 {
1409 if (notify_callback)
1410 {
1411 OPENVPN_LOG("Session invalidated: " << Error::name(proto_context.invalidation_reason()));
1412 stop(true);
1413 }
1414 else
1415 throw session_invalidated();
1416 }
1418 }
1419 }
1420 catch (const std::exception &e)
1421 {
1422 process_exception(e, "housekeeping_callback");
1423 }
1424 }
1425
1427 {
1428 if (halt)
1429 return;
1430
1432 if (!housekeeping_schedule.similar(next))
1433 {
1434 if (!next.is_infinite())
1435 {
1436 next.max(proto_context.now());
1439 housekeeping_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1440 {
1442 self->housekeeping_callback(error); });
1443 }
1444 else
1445 {
1446 housekeeping_timer.cancel();
1448 }
1449 }
1450 }
1455 void set_cc_handshake_config(SSLLib::SSLAPI::Config::Ptr cfg)
1456 {
1457 certcheck_hs.reset(cfg);
1458 }
1459
1461 {
1462 try
1463 {
1464 const Option *o = load_duration_parm(inactive_duration, "inactive", opt, 1, false, false);
1465 if (o)
1466 {
1467 if (o->size() >= 3)
1468 inactivity_minimum_bytes = parse_number_throw<unsigned int>(o->get(2, 16), "inactive bytes");
1469
1472 [self = Ptr(this)](const count_t value)
1473 { self->reset_inactive_timer(value); });
1474
1477 [self = Ptr(this)](const count_t value)
1478 { self->reset_inactive_timer(value); });
1479
1481 }
1482 }
1483 catch (const std::exception &e)
1484 {
1485 OPENVPN_LOG("exception parsing inactive: " << e.what());
1486 }
1487 }
1488
1490 {
1492 inactive_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1493 {
1495 self->inactive_callback(error); });
1496 }
1497
1498 void reset_inactive_timer(const count_t bytes_count)
1499 {
1500 // Ensure that it's called within the io_context in case it needs to be invoked from a separate thread.
1501 openvpn_io::post(io_context, [self = Ptr(this), bytes_count]()
1502 {
1504
1505 self->inactivity_bytes += bytes_count;
1506 if (self->inactivity_bytes >= self->inactivity_minimum_bytes)
1507 {
1508 // OPENVPN_LOG("reset_inactive_timer: " << self->inactivity_bytes);
1509 self->inactivity_bytes = 0;
1510 self->schedule_inactive_timer();
1511 } });
1512 }
1513
1514 void inactive_callback(const openvpn_io::error_code &e) // fixme for DCO
1515 {
1516 try
1517 {
1518 if (!e && !halt)
1519 {
1520 // In non-DCO case, inactivity timeout is reset on data channel activity,
1521 // so this function is only called on timeout.
1522 //
1523 // With DCO, OpenVPN doesn't see data channel packets, so we have to
1524 // change the logic and check kernel counters here, either stopping or
1525 // rearming the timer if there is sufficient traffic.
1526 if (cli_stats->dco_update())
1527 {
1529 auto delta = sample - inactive_last_sample;
1530 if (delta >= inactivity_minimum_bytes)
1531 {
1532 inactive_last_sample = sample;
1534 return;
1535 }
1536 }
1537
1540 if (notify_callback)
1541 {
1542 OPENVPN_LOG("inactive timer expired");
1543 stop(true);
1544 }
1545 else
1546 throw inactive_timer_expired();
1547 }
1548 }
1549 catch (const std::exception &e)
1550 {
1551 process_exception(e, "inactive_callback");
1552 }
1553 }
1554
1555 void process_echo(const OptionList &opt)
1556 {
1557 OptionList::IndexMap::const_iterator echo_opt = opt.map().find("echo");
1558 if (echo_opt != opt.map().end())
1559 {
1560 for (OptionList::IndexList::const_iterator i = echo_opt->second.begin(); i != echo_opt->second.end(); ++i)
1561 {
1562 const Option &o = opt[*i];
1563 o.touch();
1564 const std::string &value = o.get(1, 512);
1566 cli_events->add_event(std::move(ev));
1567 }
1568 }
1569 }
1570
1571 void process_exception(const std::exception &e, const char *method_name)
1572 {
1573 if (notify_callback)
1574 {
1575 OPENVPN_LOG("Client exception in " << method_name << ": " << e.what());
1576 stop(true);
1577 }
1578 else
1579 throw client_exception(e.what());
1580 }
1581
1582 void recv_halt_restart(const std::string &msg)
1583 {
1584 const ClientHalt ch(msg, true);
1585 if (!ch.psid() && creds)
1587 if (ch.restart())
1589 else
1591 fatal_reason_ = ch.reason();
1592 if (notify_callback)
1593 {
1594 OPENVPN_LOG("Client halt/restart: " << ch.render());
1595 stop(true);
1596 }
1597 else
1598 throw client_halt_restart(ch.render());
1599 }
1600
1602 {
1604 info_hold_timer.expires_after(Time::Duration::seconds(1));
1605 info_hold_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1606 {
1608 self->info_hold_callback(error); });
1609 }
1610
1611 void info_hold_callback(const openvpn_io::error_code &e)
1612 {
1613 try
1614 {
1615 if (!e && !halt)
1616 {
1618 if (info_hold)
1619 {
1620 for (auto &ev : *info_hold)
1621 cli_events->add_event(std::move(ev));
1622 info_hold.reset();
1623 }
1624 }
1625 }
1626 catch (const std::exception &exc)
1627 {
1628 process_exception(exc, "info_hold_callback");
1629 }
1630 }
1631
1632#ifdef OPENVPN_PACKET_LOG
1633 void log_packet(const Buffer &buf, const bool out)
1634 {
1635 if (buf.size())
1636 {
1637 std::uint16_t len = buf.size() & 0x7FFF;
1638 if (out)
1639 len |= 0x8000;
1640 packet_log.write((const char *)&len, sizeof(len));
1641 packet_log.write((const char *)buf.c_data(), buf.size());
1642 }
1643 }
1644#endif
1645
1647
1648 openvpn_io::io_context &io_context;
1649
1652
1655
1656 unsigned int tcp_queue_limit;
1658
1660
1664 bool halt = false;
1665
1667
1669
1671
1673 bool sent_push_request = false;
1674 bool auth_pending = false;
1675
1678
1680
1681 bool echo;
1682 bool info;
1683
1685 std::string fatal_reason_;
1686
1690
1692 Time::Duration inactive_duration;
1693
1696 std::uint64_t inactivity_bytes = 0;
1697 std::shared_ptr<SessionStats::inc_callback_t> out_tun_callback_;
1698 std::shared_ptr<SessionStats::inc_callback_t> in_tun_callback_;
1699
1700 std::unique_ptr<std::vector<ClientEvent::Base::Ptr>> info_hold;
1702
1703 // AUTH_FAILED,TEMP flag values
1704 std::chrono::milliseconds temp_fail_backoff_{0};
1706
1707 // Client side certcheck
1709
1710#ifdef OPENVPN_PACKET_LOG
1711 std::ofstream packet_log;
1712#endif
1713};
1714} // namespace openvpn::ClientProto
1715
1716#endif
#define OPENVPN_ASYNC_HANDLER
Definition bigmutex.hpp:36
bool receive_message(const std::string &msg)
std::pair< std::string, std::string > get_message()
std::size_t expires_at(const Time &t)
Definition asiotimer.hpp:64
std::size_t expires_after(const Time::Duration &d)
Definition asiotimer.hpp:69
size_t decode(void *data, size_t len, const std::string &str) const
Definition base64.hpp:186
bool password_defined() const
Definition clicreds.hpp:135
std::string get_password() const
Definition clicreds.hpp:105
bool password_needed() const
Definition clicreds.hpp:187
std::string auth_info() const
Definition clicreds.hpp:192
void set_need_user_interaction()
Definition clicreds.hpp:177
bool need_user_interaction() const
Definition clicreds.hpp:182
void set_session_id(const std::string &user, const std::string &sess_id)
Definition clicreds.hpp:76
std::string get_username() const
Definition clicreds.hpp:95
bool session_id_defined() const
Definition clicreds.hpp:150
void save_username_for_session_id()
Definition clicreds.hpp:169
bool restart() const
Definition clihalt.hpp:72
std::string render() const
Definition clihalt.hpp:89
static bool match(const std::string &msg)
Definition clihalt.hpp:64
const std::string & reason() const
Definition clihalt.hpp:84
bool psid() const
Definition clihalt.hpp:78
OPENVPN_EXCEPTION(transport_exception)
void recv_info(const std::string &msg, bool info_pre)
Definition cliproto.hpp:864
void stop_on_signal(const openvpn_io::error_code &error, int signal_number)
Definition cliproto.hpp:291
std::string parse_auth_failed_temp(const std::string &msg)
Definition cliproto.hpp:651
void recv_custom_control_message(const std::string msg)
receive, validate, and dispatch ACC messages
Definition cliproto.hpp:994
void info_hold_callback(const openvpn_io::error_code &e)
std::unique_ptr< std::vector< ClientEvent::Base::Ptr > > info_hold
bool transport_is_openvpn_protocol() override
Definition cliproto.hpp:345
void control_recv(BufferPtr &&app_bp) override
Definition cliproto.hpp:936
void transport_recv(BufferAllocated &buf) override
Definition cliproto.hpp:351
void reset_inactive_timer(const count_t bytes_count)
void active(bool primary) override
Called when KeyContext transitions to ACTIVE state.
void recv_halt_restart(const std::string &msg)
static const std::string certcheckProto
Definition cliproto.hpp:95
openvpn_io::io_context & io_context
void housekeeping_callback(const openvpn_io::error_code &e)
void transport_wait() override
Definition cliproto.hpp:541
void start_acc_certcheck(SSLLib::SSLAPI::Config::Ptr config)
Start up the cert check handshake using the given certs and key.
Definition cliproto.hpp:333
TransportClient::Ptr transport
void schedule_push_request_callback(const Time::Duration &dur)
void recv_push_update(const std::string &msg)
Handles incoming PUSH_UPDATE message.
Definition cliproto.hpp:909
void control_net_send(const Buffer &net_buf) override
Definition cliproto.hpp:722
const std::string & fatal_reason() const
Definition cliproto.hpp:311
void tun_error(const Error::Type fatal_err, const std::string &err_text) override
TransportClientFactory::Ptr transport_factory_relay()
Definition cliproto.hpp:201
NotifyCallback * notify_callback
virtual void check_tls_warnings()
OptionList::Limits pushed_options_limit
void post_cc_msg(const std::string &msg)
Definition cliproto.hpp:248
Session(openvpn_io::io_context &io_context_arg, const Config &config, NotifyCallback *notify_callback_arg)
Definition cliproto.hpp:142
PushOptionsMerger::Ptr pushed_options_merger
RemoteList::Advance advance_type() const
Definition cliproto.hpp:318
void inactive_callback(const openvpn_io::error_code &e)
void transport_wait_proxy() override
Definition cliproto.hpp:535
void disable_keepalive(unsigned int &keepalive_ping, unsigned int &keepalive_timeout) override
Definition cliproto.hpp:514
void transport_factory_override(TransportClientFactory::Ptr factory)
Definition cliproto.hpp:208
void send_push_request_callback(const Time::Duration &dur, const openvpn_io::error_code &e)
OPENVPN_EXCEPTION(client_exception)
void tun_recv(BufferAllocated &buf) override
Definition cliproto.hpp:432
OptionList::FilterBase::Ptr pushed_options_filter
void tun_pre_tun_config() override
void tun_event(ClientEvent::Base::Ptr ev) override
OPENVPN_SIMPLE_EXCEPTION(session_invalidated)
ClientEvent::Connected::Ptr connected_
ProtoContextCompressionOptions::Ptr proto_context_options
unsigned int inactivity_minimum_bytes
void transport_pre_resolve() override
Definition cliproto.hpp:520
OPENVPN_EXCEPTION(max_pushed_options_exceeded)
void proxy_error(const Error::Type fatal_err, const std::string &err_text) override
Definition cliproto.hpp:580
OPENVPN_EXCEPTION(proxy_exception)
void recv_auth_failed(const std::string &msg)
Definition cliproto.hpp:729
SessionStats::Ptr cli_stats
void stop(const bool call_terminate_callback)
Definition cliproto.hpp:269
void tun_pre_route_config() override
bool supports_proto_v3() override
void recv_auth_pending(const std::string &msg)
Definition cliproto.hpp:802
OptionListContinuation received_options
void do_acc_certcheck(const std::string &msg_str)
Handles the ACC certcheck TLS handshake data exchange.
void transport_error(const Error::Type fatal_err, const std::string &err_text) override
Definition cliproto.hpp:564
void client_auth(Buffer &buf) override
void transport_needs_send() override
Definition cliproto.hpp:427
std::chrono::milliseconds reconnect_delay() const
Definition cliproto.hpp:322
void recv_push_reply(const std::string &msg)
void validate_and_post_cc_msg(const std::string &msg)
Definition cliproto.hpp:231
void process_inactive(const OptionList &opt)
void extract_auth_token(const OptionList &opt)
Definition cliproto.hpp:596
void transport_connecting() override
Definition cliproto.hpp:547
OPENVPN_EXCEPTION(tun_exception)
ClientEvent::Queue::Ptr cli_events
OPENVPN_SIMPLE_EXCEPTION(relay_event)
TunClientFactory::Ptr tun_factory
void process_exception(const std::exception &e, const char *method_name)
void process_echo(const OptionList &opt)
bool reached_connected_state() const
Definition cliproto.hpp:296
RemoteList::Advance temp_fail_advance_
std::string server_endpoint_render()
Definition cliproto.hpp:526
void post_app_control_message(const std::string proto, const std::string message)
Definition cliproto.hpp:256
OPENVPN_EXCEPTION(client_halt_restart)
OPENVPN_SIMPLE_EXCEPTION(inactive_timer_expired)
bool is_keepalive_enabled() const override
Definition cliproto.hpp:507
void set_cc_handshake_config(SSLLib::SSLAPI::Config::Ptr cfg)
Set the cc handshake config object.
std::shared_ptr< SessionStats::inc_callback_t > in_tun_callback_
Error::Type fatal() const
Definition cliproto.hpp:307
std::chrono::milliseconds temp_fail_backoff_
OPENVPN_SIMPLE_EXCEPTION(authentication_failed)
std::shared_ptr< SessionStats::inc_callback_t > out_tun_callback_
TransportClientFactory::Ptr transport_factory
bool similar(const Time &t) const
void init(const Time::Duration &pre, const Time::Duration &post)
void reset(const Time &t)
static bool is_any_stub(const Type t)
Definition compress.hpp:510
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1177
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1225
void reset_size()
Resets the size of the buffer to zero.
Definition buffer.hpp:1153
bool fatal() const
Definition excode.hpp:58
Error::Type code() const
Definition excode.hpp:54
bool code_defined() const
Definition excode.hpp:63
static std::string validate(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:131
void reset_completion()
Resets completion flag. Intended to use by PUSH_UPDATE.
void finalize(const PushOptionsMerger::Ptr merger)
void add(const OptionList &other, OptionList::FilterBase *filt, bool push_update=false)
std::string get_optional(const std::string &name, size_t index, const size_t max_len) const
Definition options.hpp:1342
const IndexMap & map() const
Definition options.hpp:1562
static OptionList parse_from_csv_static(const std::string &str, Limits *lim)
Definition options.hpp:844
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
void touch(bool lightly=false) const
Definition options.hpp:385
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:187
size_t size() const
Definition options.hpp:327
static void write_empty_string(Buffer &buf)
Definition proto.hpp:190
void build_connect_time_peer_info_string(TransportClient::Ptr transport)
Definition proto.hpp:1093
AppControlMessageReceiver app_control_recv
Definition proto.hpp:441
void set_xmit_creds(const bool xmit_creds_arg)
Definition proto.hpp:1012
AppControlMessageConfig app_control_config
Definition proto.hpp:440
void parse_custom_app_control(const OptionList &opt)
Definition proto.hpp:728
uint32_t get_tls_warnings() const
Definition proto.hpp:3910
void send_explicit_exit_notify()
Definition proto.hpp:4289
const Time & now() const
Definition proto.hpp:4430
CryptoDCSettings & dc_settings()
Definition proto.hpp:4412
void flush(const bool control_channel)
Definition proto.hpp:4149
bool uses_bs64_cipher() const
Definition proto.hpp:3919
PacketType packet_type(const Buffer &buf)
Definition proto.hpp:4110
void data_encrypt(BufferAllocated &in_out)
Definition proto.hpp:4244
bool is_keepalive_enabled() const
Definition proto.hpp:4377
void process_push(const OptionList &opt, const ProtoContextCompressionOptions &pco)
Definition proto.hpp:4361
static void write_auth_string(const S &str, Buffer &buf)
Definition proto.hpp:1535
void set_protocol(const Protocol &p)
Definition proto.hpp:4085
size_t align_adjust_hint() const
Definition proto.hpp:4371
SessionStats & stat() const
Definition proto.hpp:4488
std::string dump_packet(const Buffer &buf)
Definition proto.hpp:1419
static void write_empty_string(Buffer &buf)
Definition proto.hpp:1569
static void write_control_string(const S &str, Buffer &buf)
Definition proto.hpp:1562
bool data_decrypt(const PacketType &type, BufferAllocated &in_out)
Definition proto.hpp:4254
void disable_keepalive(unsigned int &keepalive_ping, unsigned int &keepalive_timeout)
Definition proto.hpp:4385
Error::Type invalidation_reason() const
Definition proto.hpp:4341
Time next_housekeeping() const
Definition proto.hpp:4187
bool control_net_recv(const PacketType &type, BufferAllocated &&net_buf)
Definition proto.hpp:4224
bool invalidated() const
Definition proto.hpp:4335
void reset(const ProtoSessionID cookie_psid=ProtoSessionID())
Resets ProtoContext *this to it's initial state.
Definition proto.hpp:3993
void start(const ProtoSessionID cookie_psid=ProtoSessionID())
Initialize the state machine and start protocol negotiation.
Definition proto.hpp:4123
const ProtoConfig & conf() const
Definition proto.hpp:4474
static void generate_icmp_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
Definition ptb.hpp:30
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
void swap(RCPtr &rhs) noexcept
swaps the contents of two RCPtr<T>
Definition rc.hpp:311
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
virtual void error(const size_t type, const std::string *text=nullptr)
std::shared_ptr< inc_callback_t > set_inc_callback(Stats stat, inc_callback_t callback)
Sets a callback to be triggered upon increment of stats.
void update_last_packet_received(const Time &now)
count_t get_stat(const size_t type) const
void max(const TimeType &t)
Definition time.hpp:348
bool is_infinite() const
Definition time.hpp:269
#define OPENVPN_LOG_CLIPROTO(x)
Definition cliproto.hpp:67
#define OPENVPN_THROW(exc, stuff)
#define OPENVPN_LOG(args)
const char * name(const size_t type)
Definition error.hpp:117
unsigned int version(const std::uint8_t version_len_prio)
Definition ipcommon.hpp:35
bool is_valid_utf8(const STRING &str, const size_t max_len_flags=0)
Definition unicode.hpp:75
OutT clamp_to_typerange(InT inVal)
Clamps the input value to the legal range for the output type.
auto join(const T &strings, const typename T::value_type &delim, const bool tail=false)
Definition string.hpp:521
bool starts_with(const STRING &str, const std::string &prefix)
Definition string.hpp:79
std::vector< T > split(const T &str, const typename T::value_type sep, const int maxsplit=-1)
Definition string.hpp:492
std::string trim_left_copy(const std::string &str)
Definition string.hpp:549
const Option * load_duration_parm(Time::Duration &dur, const std::string &name, const OptionList &opt, const unsigned int min_value, const bool x2, const bool allow_ms)
Definition durhelper.hpp:41
std::string render_options_sanitized(const OptionList &opt, const unsigned int render_flags)
Definition sanitize.hpp:25
const Base64 * base64
Definition base64.hpp:299
bool parse_number(const char *str, T &retval, const bool nondigit_term=false)
Definition number.hpp:34
long long count_t
Definition count.hpp:16
defines a class that handles SSL/TLS handshaking
std::optional< std::string > MsgT
MsgT process_msg(const MsgT &msg)
Incrementally process the CLIENT HELLO / SERVER HELLO exchange.
void reset(SSLLib::SSLAPI::Config::Ptr cfg)
Re-init the handshaker.
bool supports_protocol(const std::string &protocol)
std::vector< std::string > supported_protocols
List of supported protocols.
std::vector< std::string > format_message(const std::string &protocol, const std::string &message)
Format a protocol string and a message into a properly packed series of message fragments.
virtual void client_proto_auth_pending_timeout(int timeout)
Definition cliproto.hpp:82
TunClientFactory::Ptr tun_factory
Definition cliproto.hpp:130
ClientEvent::Queue::Ptr cli_events
Definition cliproto.hpp:132
TransportClientFactory::Ptr transport_factory
Definition cliproto.hpp:129
OptionList::FilterBase::Ptr pushed_options_filter
Definition cliproto.hpp:135
OptionList::Limits pushed_options_limit
Definition cliproto.hpp:134
ProtoContextCompressionOptions::Ptr proto_context_options
Definition cliproto.hpp:127
ProtoContext::ProtoConfig::Ptr proto_context_config
Definition cliproto.hpp:126
static bool is_df_set(const unsigned char *data)
Definition ip4.hpp:36
virtual TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context, TransportClientParent *parent)=0
virtual void process_push(const OptionList &)
virtual void reset_align_adjust(const size_t align_adjust)=0
virtual void transport_start()=0
virtual bool transport_send_const(const Buffer &buf)=0
virtual size_t transport_send_queue_size()=0
virtual bool transport_has_send_queue()=0
virtual bool transport_send(BufferAllocated &buf)=0
virtual void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const =0
virtual void stop()=0
virtual Protocol transport_protocol() const =0
virtual bool supports_proto_v3()=0
virtual TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context, TunClientParent &parent, TransportClient *transcli)=0
virtual std::string vpn_gw6() const
Definition tunbase.hpp:48
virtual std::string vpn_ip4() const =0
virtual std::string tun_name() const =0
virtual void stop()=0
virtual int vpn_mtu() const =0
virtual void adjust_mss(int mss)
Definition tunbase.hpp:55
virtual void apply_push_update(const OptionList &opt, TransportClient &cli)
Notifies tun client about received PUSH_UPDATE control channel message.
Definition tunbase.hpp:68
virtual void set_disconnect()=0
virtual void tun_start(const OptionList &, TransportClient &, CryptoDCSettings &)=0
virtual std::string vpn_gw4() const
Definition tunbase.hpp:44
virtual bool tun_send(BufferAllocated &buf)=0
virtual std::string vpn_ip6() const =0
reroute_gw flags
static const char config[]
static std::stringstream out
Definition test_path.cpp:10
const char message[]
#define msg(flags,...)