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 ev->vpn_interface_index = tun->vpn_interface_index();
1197
1198 try
1199 {
1200 std::string client_ip = received_options.get_optional("client-ip", 1, 256);
1201 if (!client_ip.empty())
1202 ev->client_ip = IP::Addr::validate(client_ip, "client-ip");
1203 }
1204 catch (const std::exception &e)
1205 {
1206 OPENVPN_LOG("exception parsing client-ip: " << e.what());
1207 }
1208 ev->tun_name = tun->tun_name();
1209 connected_ = std::move(ev);
1210 }
1211
1212 void tun_error(const Error::Type fatal_err, const std::string &err_text) override
1213 {
1214 if (fatal_err == Error::TUN_HALT)
1216 if (fatal_err != Error::UNDEF)
1217 {
1218 fatal_ = fatal_err;
1219 fatal_reason_ = err_text;
1220 }
1221 if (notify_callback)
1222 {
1223 OPENVPN_LOG("TUN Error: " << err_text);
1224 stop(true);
1225 }
1226 else
1227 throw tun_exception(err_text);
1228 }
1229
1230 // proto base class calls here to get auth credentials
1231 void client_auth(Buffer &buf) override
1232 {
1233 // we never send creds to a relay server
1235 {
1236 OPENVPN_LOG("Creds: " << creds->auth_info());
1238 {
1239 throw ErrorCode(Error::NEED_CREDS, true, "missing password");
1240 }
1242#ifdef OPENVPN_DISABLE_AUTH_TOKEN // debugging only
1244 {
1245 OPENVPN_LOG("NOTE: not sending auth-token");
1247 }
1248 else
1249#endif
1250 {
1252 }
1253
1254 // save username for auth-token, which might be pushed later
1256
1258 {
1260 }
1261 }
1262 else
1263 {
1264 OPENVPN_LOG("Creds: None");
1265 write_empty_string(buf); // username
1266 write_empty_string(buf); // password
1267 }
1268 }
1269
1270 void send_push_request_callback(const Time::Duration &dur,
1271 const openvpn_io::error_code &e)
1272 {
1273 try
1274 {
1275 if (!e && !halt && !received_options.partial())
1276 {
1278 if (!sent_push_request)
1279 {
1281 cli_events->add_event(std::move(ev));
1282 sent_push_request = true;
1283 }
1284 OPENVPN_LOG("Sending PUSH_REQUEST to server...");
1285 proto_context.write_control_string(std::string("PUSH_REQUEST"));
1286 proto_context.flush(true);
1288
1289 {
1290 if (auth_pending)
1291 {
1292 // With auth_pending, we can dial back the PUSH_REQUEST
1293 // frequency, but we still need back-and-forth network
1294 // activity to avoid an inactivity timeout, since the crypto
1295 // layer (and hence keepalive ping) is not initialized until
1296 // we receive the PUSH_REPLY from the server.
1297 schedule_push_request_callback(Time::Duration::seconds(8));
1298 }
1299 else
1300 {
1301 // step function with ceiling: 1 sec, 2 secs, 3 secs, 3, 3, ...
1302 const Time::Duration newdur = std::min(dur + Time::Duration::seconds(1),
1303 Time::Duration::seconds(3));
1305 }
1306 }
1307 }
1308 }
1309 catch (const std::exception &e)
1310 {
1311 process_exception(e, "send_push_request_callback");
1312 }
1313 }
1314
1315 void schedule_push_request_callback(const Time::Duration &dur)
1316 {
1318 {
1320 push_request_timer.async_wait([self = Ptr(this), dur](const openvpn_io::error_code &error)
1321 {
1323 self->send_push_request_callback(dur, error); });
1324 }
1325 }
1326
1327 // react to any tls warning triggered during the tls-handshake
1328 virtual void check_tls_warnings()
1329 {
1330 uint32_t tls_warnings = proto_context.get_tls_warnings();
1331
1332 if (tls_warnings & SSLAPI::TLS_WARN_SIG_MD5)
1333 {
1334 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");
1335 cli_events->add_event(std::move(ev));
1336 }
1337
1338 if (tls_warnings & SSLAPI::TLS_WARN_SIG_SHA1)
1339 {
1340 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");
1341 cli_events->add_event(std::move(ev));
1342 }
1343 }
1344
1346 {
1348 {
1349 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.");
1350 cli_events->add_event(std::move(ev));
1351 }
1352
1354
1355 // abort connection if compression is pushed and its support is unannounced
1356 if (comp_type != CompressContext::COMP_STUBv2
1357 && comp_type != CompressContext::NONE
1359 {
1360 throw ErrorCode(Error::COMPRESS_ERROR, true, "server pushed compression "
1361 "settings that are not allowed and will result "
1362 "in a non-working connection. ");
1363 }
1364
1365 // Issue an event if compression is enabled
1366 if (comp_type != CompressContext::NONE
1367 && !CompressContext::is_any_stub(comp_type))
1368 {
1369 std::ostringstream msg;
1371 ? "Asymmetric compression enabled. Server may send compressed data."
1372 : "Compression enabled.");
1373 msg << " This may be a potential security issue.";
1375 cli_events->add_event(std::move(ev));
1376 }
1377 }
1378
1379 // base class calls here when session transitions to ACTIVE state
1380 void active(bool primary) override
1381 {
1382 if (primary)
1383 {
1384 OPENVPN_LOG("Session is ACTIVE");
1386 schedule_push_request_callback(Time::Duration::seconds(0));
1387 }
1388 else if (notify_callback)
1390 }
1391
1392 bool supports_epoch_data() override
1393 {
1395 }
1396
1397 void housekeeping_callback(const openvpn_io::error_code &e)
1398 {
1399 try
1400 {
1401 if (!e && !halt)
1402 {
1403 // update current time
1405
1409 {
1410 if (notify_callback)
1411 {
1412 OPENVPN_LOG("Session invalidated: " << Error::name(proto_context.invalidation_reason()));
1413 stop(true);
1414 }
1415 else
1416 throw session_invalidated();
1417 }
1419 }
1420 }
1421 catch (const std::exception &e)
1422 {
1423 process_exception(e, "housekeeping_callback");
1424 }
1425 }
1426
1428 {
1429 if (halt)
1430 return;
1431
1433 if (!housekeeping_schedule.similar(next))
1434 {
1435 if (!next.is_infinite())
1436 {
1437 next.max(proto_context.now());
1440 housekeeping_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1441 {
1443 self->housekeeping_callback(error); });
1444 }
1445 else
1446 {
1447 housekeeping_timer.cancel();
1449 }
1450 }
1451 }
1456 void set_cc_handshake_config(SSLLib::SSLAPI::Config::Ptr cfg)
1457 {
1458 certcheck_hs.reset(cfg);
1459 }
1460
1462 {
1463 try
1464 {
1465 const Option *o = load_duration_parm(inactive_duration, "inactive", opt, 1, false, false);
1466 if (o)
1467 {
1468 if (o->size() >= 3)
1469 inactivity_minimum_bytes = parse_number_throw<unsigned int>(o->get(2, 16), "inactive bytes");
1470
1473 [self = Ptr(this)](const count_t value)
1474 { self->reset_inactive_timer(value); });
1475
1478 [self = Ptr(this)](const count_t value)
1479 { self->reset_inactive_timer(value); });
1480
1482 }
1483 }
1484 catch (const std::exception &e)
1485 {
1486 OPENVPN_LOG("exception parsing inactive: " << e.what());
1487 }
1488 }
1489
1491 {
1493 inactive_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1494 {
1496 self->inactive_callback(error); });
1497 }
1498
1499 void reset_inactive_timer(const count_t bytes_count)
1500 {
1501 // Ensure that it's called within the io_context in case it needs to be invoked from a separate thread.
1502 openvpn_io::post(io_context, [self = Ptr(this), bytes_count]()
1503 {
1505
1506 self->inactivity_bytes += bytes_count;
1507 if (self->inactivity_bytes >= self->inactivity_minimum_bytes)
1508 {
1509 // OPENVPN_LOG("reset_inactive_timer: " << self->inactivity_bytes);
1510 self->inactivity_bytes = 0;
1511 self->schedule_inactive_timer();
1512 } });
1513 }
1514
1515 void inactive_callback(const openvpn_io::error_code &e) // fixme for DCO
1516 {
1517 try
1518 {
1519 if (!e && !halt)
1520 {
1521 // In non-DCO case, inactivity timeout is reset on data channel activity,
1522 // so this function is only called on timeout.
1523 //
1524 // With DCO, OpenVPN doesn't see data channel packets, so we have to
1525 // change the logic and check kernel counters here, either stopping or
1526 // rearming the timer if there is sufficient traffic.
1527 if (cli_stats->dco_update())
1528 {
1530 auto delta = sample - inactive_last_sample;
1531 if (delta >= inactivity_minimum_bytes)
1532 {
1533 inactive_last_sample = sample;
1535 return;
1536 }
1537 }
1538
1541 if (notify_callback)
1542 {
1543 OPENVPN_LOG("inactive timer expired");
1544 stop(true);
1545 }
1546 else
1547 throw inactive_timer_expired();
1548 }
1549 }
1550 catch (const std::exception &e)
1551 {
1552 process_exception(e, "inactive_callback");
1553 }
1554 }
1555
1556 void process_echo(const OptionList &opt)
1557 {
1558 OptionList::IndexMap::const_iterator echo_opt = opt.map().find("echo");
1559 if (echo_opt != opt.map().end())
1560 {
1561 for (OptionList::IndexList::const_iterator i = echo_opt->second.begin(); i != echo_opt->second.end(); ++i)
1562 {
1563 const Option &o = opt[*i];
1564 o.touch();
1565 const std::string &value = o.get(1, 512);
1567 cli_events->add_event(std::move(ev));
1568 }
1569 }
1570 }
1571
1572 void process_exception(const std::exception &e, const char *method_name)
1573 {
1574 if (notify_callback)
1575 {
1576 OPENVPN_LOG("Client exception in " << method_name << ": " << e.what());
1577 stop(true);
1578 }
1579 else
1580 throw client_exception(e.what());
1581 }
1582
1583 void recv_halt_restart(const std::string &msg)
1584 {
1585 const ClientHalt ch(msg, true);
1586 if (!ch.psid() && creds)
1588 if (ch.restart())
1590 else
1592 fatal_reason_ = ch.reason();
1593 if (notify_callback)
1594 {
1595 OPENVPN_LOG("Client halt/restart: " << ch.render());
1596 stop(true);
1597 }
1598 else
1599 throw client_halt_restart(ch.render());
1600 }
1601
1603 {
1605 info_hold_timer.expires_after(Time::Duration::seconds(1));
1606 info_hold_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
1607 {
1609 self->info_hold_callback(error); });
1610 }
1611
1612 void info_hold_callback(const openvpn_io::error_code &e)
1613 {
1614 try
1615 {
1616 if (!e && !halt)
1617 {
1619 if (info_hold)
1620 {
1621 for (auto &ev : *info_hold)
1622 cli_events->add_event(std::move(ev));
1623 info_hold.reset();
1624 }
1625 }
1626 }
1627 catch (const std::exception &exc)
1628 {
1629 process_exception(exc, "info_hold_callback");
1630 }
1631 }
1632
1633#ifdef OPENVPN_PACKET_LOG
1634 void log_packet(const Buffer &buf, const bool out)
1635 {
1636 if (buf.size())
1637 {
1638 std::uint16_t len = buf.size() & 0x7FFF;
1639 if (out)
1640 len |= 0x8000;
1641 packet_log.write((const char *)&len, sizeof(len));
1642 packet_log.write((const char *)buf.c_data(), buf.size());
1643 }
1644 }
1645#endif
1646
1648
1649 openvpn_io::io_context &io_context;
1650
1653
1656
1657 unsigned int tcp_queue_limit;
1659
1661
1665 bool halt = false;
1666
1668
1670
1672
1674 bool sent_push_request = false;
1675 bool auth_pending = false;
1676
1679
1681
1682 bool echo;
1683 bool info;
1684
1686 std::string fatal_reason_;
1687
1691
1693 Time::Duration inactive_duration;
1694
1697 std::uint64_t inactivity_bytes = 0;
1698 std::shared_ptr<SessionStats::inc_callback_t> out_tun_callback_;
1699 std::shared_ptr<SessionStats::inc_callback_t> in_tun_callback_;
1700
1701 std::unique_ptr<std::vector<ClientEvent::Base::Ptr>> info_hold;
1703
1704 // AUTH_FAILED,TEMP flag values
1705 std::chrono::milliseconds temp_fail_backoff_{0};
1707
1708 // Client side certcheck
1710
1711#ifdef OPENVPN_PACKET_LOG
1712 std::ofstream packet_log;
1713#endif
1714};
1715} // namespace openvpn::ClientProto
1716
1717#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
bool supports_epoch_data() override
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
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:1194
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1242
void reset_size()
Resets the size of the buffer to zero.
Definition buffer.hpp:1170
bool fatal() const
Definition excode.hpp:51
Error::Type code() const
Definition excode.hpp:47
bool code_defined() const
Definition excode.hpp:56
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 TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context, TunClientParent &parent, TransportClient *transcli)=0
virtual bool supports_epoch_data()=0
virtual std::string vpn_gw6() const
Definition tunbase.hpp:50
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:57
virtual void apply_push_update(const OptionList &opt, TransportClient &cli)
Notifies tun client about received PUSH_UPDATE control channel message.
Definition tunbase.hpp:70
virtual std::uint32_t vpn_interface_index() const
Definition tunbase.hpp:72
virtual void set_disconnect()=0
virtual void tun_start(const OptionList &, TransportClient &, CryptoDCSettings &)=0
virtual std::string vpn_gw4() const
Definition tunbase.hpp:46
virtual bool tun_send(BufferAllocated &buf)=0
virtual std::string vpn_ip6() const =0
reroute_gw flags
auto f(const Thing1 t)
static const char config[]
static std::stringstream out
Definition test_path.cpp:10
const char message[]
#define msg(flags,...)