OpenVPN 3 Core Library
Loading...
Searching...
No Matches
omi.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#pragma once
13
14#include <string>
15#include <sstream>
16#include <vector>
17#include <deque>
18#include <memory>
19#include <utility>
20#include <algorithm>
21
25#include <openvpn/common/rc.hpp>
35
36// include acceptors for different protocols
39#ifdef ASIO_HAS_LOCAL_SOCKETS
41#endif
42
43#if defined(OPENVPN_PLATFORM_WIN)
45#else
47#endif
48
49namespace openvpn {
51{
52 public:
54
55 struct LogFn
56 {
57 LogFn(const OptionList &opt)
58 {
59 fn = opt.get_optional("log", 1, 256);
60 if (fn.empty())
61 {
62 fn = opt.get_optional("log-append", 1, 256);
63 append = true;
64 }
65 errors_to_stderr = opt.exists("errors-to-stderr");
66 }
67
68 std::string fn;
69 bool append = false;
70 bool errors_to_stderr = false;
71 };
72
73 void stop()
74 {
75 if (stop_called)
76 return;
77 stop_called = true;
78
79 asio_work.reset();
80
81 // close acceptor
82 if (acceptor)
83 acceptor->close();
84
85 // Call derived class stop method and close OMI socket,
86 // but if omi_stop() returns true, wait for content_out
87 // to be flushed to OMI socket before closing it.
88 if (!omi_stop() || content_out.empty())
89 stop_omi_client(false, 250);
90 }
91
92 protected:
93 struct Command
94 {
96 std::vector<std::string> extra;
97 bool valid_utf8 = false;
98
99 std::string to_string() const
100 {
101 std::ostringstream os;
103 if (!valid_utf8)
104 os << " >>>!UTF8";
105 os << '\n';
106 for (auto &line : extra)
107 os << line << '\n';
108 return os.str();
109 }
110 };
111
113 {
114 public:
115 History(const std::string &type_arg,
116 const size_t max_size_arg)
117 : type(type_arg),
118 max_size(max_size_arg)
119 {
120 }
121
122 bool is_cmd(const Option &o) const
123 {
124 return o.get_optional(0, 0) == type;
125 }
126
127 std::string process_cmd(const Option &o)
128 {
129 try
130 {
131 const std::string arg1 = o.get_default(1, 16, "1");
132 if (arg1 == "on")
133 {
134 const std::string arg2 = o.get_optional(2, 16);
135 real_time = true;
136 std::string ret = real_time_status();
137 if (arg2 == "all")
138 ret += show(hist.size());
139 else if (!arg2.empty())
140 return error();
141 return ret;
142 }
143 else if (arg1 == "all")
144 {
145 return show(hist.size());
146 }
147 else if (arg1 == "off")
148 {
149 real_time = false;
150 return real_time_status();
151 }
152 else
153 {
154 unsigned int n;
155 if (parse_number(arg1, n))
156 return show(n);
157 else
158 return error();
159 }
160 }
161 catch (const option_error &)
162 {
163 return error();
164 }
165 catch (const std::exception &e)
166 {
167 return "ERROR: " + type + " processing error: " + e.what() + "\r\n";
168 }
169 }
170
171 std::string notify(const std::string &msg)
172 {
173 hist.push_front(msg);
174 while (hist.size() > max_size)
175 hist.pop_back();
176 if (real_time)
177 return notify_prefix() + msg;
178 else
179 return std::string();
180 }
181
182 private:
183 std::string show(size_t n) const
184 {
185 std::string ret = "";
186 n = std::min(n, hist.size());
187 for (size_t i = 0; i < n; ++i)
188 ret += hist[n - i - 1];
189 ret += "END\r\n";
190 return ret;
191 }
192
193 std::string notify_prefix() const
194 {
195 return ">" + string::to_upper_copy(type) + ":";
196 }
197
198 std::string real_time_status() const
199 {
200 std::string ret = "SUCCESS: real-time " + type + " notification set to ";
201 if (real_time)
202 ret += "ON";
203 else
204 ret += "OFF";
205 ret += "\r\n";
206 return ret;
207 }
208
209 std::string error() const
210 {
211 return "ERROR: " + type + " parameter must be 'on' or 'off' or some number n or 'all'\r\n";
212 }
213
214 std::string type;
215 size_t max_size;
216 bool real_time = false;
217 std::deque<std::string> hist;
218 };
219
220 OMICore(openvpn_io::io_context &io_context_arg)
221 : io_context(io_context_arg),
222 stop_timer(io_context_arg)
223 {
224 }
225
226 void log_setup(const LogFn &log)
227 {
228 if (!log.fn.empty())
229 {
230#if defined(OPENVPN_PLATFORM_WIN)
231 log_handle = Win::LogUtil::create_file(log.fn, "", log.append);
232#else
233 RedirectStd redir("",
234 log.fn,
237 false);
238 redir.redirect();
239#endif
240 }
241 errors_to_stderr = log.errors_to_stderr;
242 }
243
244 static std::string get_config(const OptionList &opt)
245 {
246 // get config file
247 const std::string config_fn = opt.get("config", 1, 256);
248 return read_config(config_fn);
249 }
250
251 void start(const OptionList &opt)
252 {
253 const Option &o = opt.get("management");
254 const std::string addr = o.get(1, 256);
255 const std::string port = o.get(2, 16);
256 const std::string password_file = o.get_optional(3, 256);
257
258 if (password_file == "stdin")
259 {
260 password_defined = true;
261 std::cout << "Enter Management Password:";
262 std::cin >> password;
263 }
264
265 hold_flag = opt.exists("management-hold");
266
267 // management-queue-limit low_water high_water
268 {
269 const Option *o = opt.get_ptr("management-queue-limit");
270 if (o)
271 {
272 const size_t low_water = o->get_num<size_t>(1, 0, 0, 1000000);
273 const size_t high_water = o->get_num<size_t>(2, 0, 0, 1000000);
274 content_out_throttle.reset(new BufferThrottle(low_water, high_water));
275 }
276 }
277
278 // management-client-user root
279 {
280 const Option *o = opt.get_ptr("management-client-user");
281 if (o)
282 {
283 if (o->get(1, 64) == "root")
285 else
286 throw Exception("only --management-client-user root supported");
287 }
288 }
289
290 if (opt.exists("management-client"))
291 {
292 if (port == "unix")
293 {
294 OPENVPN_LOG("OMI Connecting to " << addr << " [unix]");
295 connect_unix(addr);
296 }
297 else
298 {
299 OPENVPN_LOG("OMI Connecting to [" << addr << "]:" << port << " [tcp]");
300 connect_tcp(addr, port);
301 }
302 }
303 else
304 {
305 if (port == "unix")
306 {
307 OPENVPN_LOG("OMI Listening on " << addr << " [unix]");
308 listen_unix(addr);
309 }
310 else
311 {
312 OPENVPN_LOG("OMI Listening on [" << addr << "]:" << port << " [tcp]");
313 listen_tcp(addr, port);
314 }
315 }
316
317 // don't exit Asio event loop until AsioWork object is deleted
318 asio_work.reset(new AsioWork(io_context));
319 }
320
326
327 void send(BufferPtr buf)
328 {
329 if (!is_sock_open())
330 return;
331 content_out.push_back(std::move(buf));
333 content_out_throttle->size_change(content_out.size());
334 if (content_out.size() == 1) // send operation not currently active?
335 queue_send();
336 }
337
338 void send(const std::string &str)
339 {
340 if (!str.empty())
342 }
343
344 bool send_ready() const
345 {
347 return content_out_throttle->ready();
348 else
349 return true;
350 }
351
353 {
354 process_recv();
355 }
356
357 void log_full(const std::string &text) // logs to OMI buffer and log file
358 {
359 const time_t now = ::time(NULL);
360 const std::string textcrlf = string::unix2dos(text, true);
361 log_line(openvpn::to_string(now) + ",," + textcrlf);
362#if defined(OPENVPN_PLATFORM_WIN)
363 if (log_handle.defined())
364 Win::LogUtil::log(log_handle(), date_time(now) + ' ' + textcrlf);
365 else
366#endif
367 std::cout << date_time(now) << ' ' << text << std::flush;
368 }
369
370 void log_timestamp(const time_t timestamp, const std::string &text) // logs to OMI buffer only
371 {
372 const std::string textcrlf = string::unix2dos(text, true);
373 log_line(openvpn::to_string(timestamp) + ",," + textcrlf);
374 }
375
376 void log_line(const std::string &line) // logs to OMI buffer only
377 {
378 if (!stop_called)
379 send(hist_log.notify(line));
380 }
381
382 void state_line(const std::string &line)
383 {
384 if (!stop_called)
385 send(hist_state.notify(line));
386 }
387
388 void echo_line(const std::string &line)
389 {
390 if (!stop_called)
391 send(hist_echo.notify(line));
392 }
393
395 {
396 return errors_to_stderr;
397 }
398
399 bool is_stopping() const
400 {
401 return stop_called;
402 }
403
404 unsigned int get_bytecount() const
405 {
406 return bytecount;
407 }
408
409 virtual bool omi_command_is_multiline(const std::string &arg0, const Option &option) = 0;
410 virtual bool omi_command_in(const std::string &arg0, const Command &cmd) = 0;
411 virtual void omi_start_connection() = 0;
412 virtual void omi_done(const bool eof) = 0;
413 virtual void omi_sigterm() = 0;
414 virtual bool omi_stop() = 0;
415
417 {
418 return false;
419 }
420
421 virtual void omi_sighup()
422 {
423 }
424
425 openvpn_io::io_context &io_context;
426
427 private:
429
431 {
432 public:
433 BufferThrottle(const size_t low_water_arg,
434 const size_t high_water_arg)
435 : low_water(low_water_arg),
436 high_water(high_water_arg)
437 {
438 if (low_water > high_water)
439 throw Exception("bad management-queue-limit values");
440 }
441
442 void size_change(const size_t size)
443 {
444 if (ready_)
445 {
446 if (size > high_water)
447 ready_ = false;
448 }
449 else
450 {
451 if (size <= low_water)
452 ready_ = true;
453 }
454 }
455
456 bool ready() const
457 {
458 return ready_;
459 }
460
461 private:
462 const size_t low_water;
463 const size_t high_water;
464 volatile bool ready_ = true;
465 };
466
467 bool command_in(std::unique_ptr<Command> cmd)
468 {
469 try
470 {
471 const std::string arg0 = cmd->option.get_optional(0, 64);
472 if (arg0.empty())
473 return false;
474 if (!cmd->valid_utf8)
475 throw Exception("invalid UTF8");
476 switch (arg0[0])
477 {
478 case 'b':
479 {
480 if (arg0 == "bytecount")
481 {
482 process_bytecount_cmd(cmd->option);
483 return false;
484 }
485 break;
486 }
487 case 'e':
488 {
489 if (hist_echo.is_cmd(cmd->option))
490 {
491 send(hist_echo.process_cmd(cmd->option));
492 return false;
493 }
494 if (arg0 == "exit")
495 {
496 conditional_stop(true);
497 return false;
498 }
499 break;
500 }
501 case 'h':
502 {
503 if (is_hold_cmd(cmd->option))
504 {
505 bool release = false;
506 send(hold_cmd(cmd->option, release));
507 if (release)
508 hold_release();
509 return false;
510 }
511 break;
512 }
513 case 'l':
514 {
515 if (hist_log.is_cmd(cmd->option))
516 {
517 send(hist_log.process_cmd(cmd->option));
518 return false;
519 }
520 break;
521 }
522 case 'q':
523 {
524 if (arg0 == "quit")
525 {
526 conditional_stop(true);
527 return false;
528 }
529 break;
530 }
531 case 's':
532 {
533 if (hist_state.is_cmd(cmd->option))
534 {
535 send(hist_state.process_cmd(cmd->option));
536 return false;
537 }
538 if (arg0 == "signal")
539 {
540 process_signal_cmd(cmd->option);
541 return false;
542 }
543 break;
544 }
545 }
546 return omi_command_in(arg0, *cmd);
547 }
548 catch (const std::exception &e)
549 {
550 std::string err_ref = "option";
551 if (cmd)
552 err_ref = cmd->option.err_ref();
553 send("ERROR: error processing " + err_ref + " : " + e.what() + "\r\n");
554 }
555 return false;
556 }
557
558 bool is_hold_cmd(const Option &o) const
559 {
560 return o.get_optional(0, 0) == "hold";
561 }
562
563 std::string hold_cmd(const Option &o, bool &release)
564 {
565 try
566 {
567 const std::string arg1 = o.get_optional(1, 16);
568 if (arg1.empty())
569 {
570 if (hold_flag)
571 return "SUCCESS: hold=1\r\n";
572 else
573 return "SUCCESS: hold=0\r\n";
574 }
575 else if (arg1 == "on")
576 {
577 hold_flag = true;
578 return "SUCCESS: hold flag set to ON\r\n";
579 }
580 else if (arg1 == "off")
581 {
582 hold_flag = false;
583 return "SUCCESS: hold flag set to OFF\r\n";
584 }
585 else if (arg1 == "release")
586 {
587 release = true;
588 return "SUCCESS: hold release succeeded\r\n";
589 }
590 }
591 catch (const option_error &)
592 {
593 }
594 return "ERROR: bad hold command parameter\r\n";
595 }
596
598 {
599 hold_wait = true;
600 if (hold_flag)
601 send(">HOLD:Waiting for hold release\r\n");
602 else
603 hold_release();
604 }
605
607 {
608 if (hold_wait)
609 {
610 hold_wait = false;
612 }
613 }
614
616 {
617 bytecount = o.get_num<decltype(bytecount)>(1, 0, 0, 86400);
618 send("SUCCESS: bytecount interval changed\r\n");
619 }
620
622 {
623 const std::string type = o.get(1, 16);
624 if (type == "SIGTERM")
625 {
626 send("SUCCESS: signal SIGTERM thrown\r\n");
627 omi_sigterm();
628 }
629 else if (type == "SIGHUP" && omi_is_sighup_implemented())
630 {
631 send("SUCCESS: signal SIGHUP thrown\r\n");
632 omi_sighup();
633 }
634 else
635 send("ERROR: signal not supported\r\n");
636 }
637
639 {
640 const std::string arg0 = o.get_optional(0, 64);
641 if (arg0.empty())
642 return false;
643 return omi_command_is_multiline(arg0, o);
644 }
645
646 bool is_sock_open() const
647 {
648 return socket && socket->is_open();
649 }
650
651 void conditional_stop(const bool eof)
652 {
653 if (acceptor || stop_called)
654 stop_omi_client(eof, 250);
655 else
656 stop(); // if running in management-client mode, do a full stop
657 }
658
659 void stop_omi_client(const bool eof, const unsigned int milliseconds)
660 {
661 stop_timer.expires_after(Time::Duration::milliseconds(milliseconds));
662 stop_timer.async_wait([self = Ptr(this), eof](const openvpn_io::error_code &error)
663 {
664 if (!error)
665 self->stop_omi_client(eof); });
666 }
667
668 void stop_omi_client(const bool eof)
669 {
671 const bool is_open = is_sock_open();
672 if (is_open)
673 socket->close();
674 content_out.clear();
676 content_out_throttle->size_change(content_out.size());
677 in_partial.clear();
678 if (is_open)
679 omi_done(eof);
680 }
681
683 {
684 send(">INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info\r\n");
685 }
686
688 {
689 send("ENTER PASSWORD:");
690 }
691
693 {
694 send("SUCCESS: password is correct\r\n");
695 }
696
698 {
700 {
701 if (password == in_partial)
702 {
703 password_verified = true;
706 hold_cycle();
707 }
708 else
709 {
710 // wrong password, kick the client
711 stop_omi_client(false, 250);
712 }
713 return true;
714 }
715
716 return false;
717 }
718
719 bool process_in_line() // process incoming line in in_partial
720 {
721 bool ret = false;
722 const bool utf8 = Unicode::is_valid_utf8(in_partial);
724
725 if (process_password())
726 return false;
727
728 if (multiline)
729 {
730 if (!command)
731 throw omi_error("process_in_line: internal error");
732 if (in_partial == "END")
733 {
734 ret = command_in(std::move(command));
735 command.reset();
736 multiline = false;
737 }
738 else
739 {
740 if (!utf8)
741 command->valid_utf8 = false;
742 command->extra.push_back(std::move(in_partial));
743 }
744 }
745 else
746 {
747 command.reset(new Command);
749 command->valid_utf8 = utf8;
751 if (!multiline)
752 {
753 ret = command_in(std::move(command));
754 command.reset();
755 }
756 }
757 return ret;
758 }
759
760 static std::string read_config(const std::string &fn)
761 {
762 if (fn == "stdin")
763 return read_stdin();
764 else
765 return read_text_utf8(fn);
766 }
767
768 void listen_tcp(const std::string &addr, const std::string &port)
769 {
770 // init TCP acceptor
772
773 // parse address/port of local endpoint
774 const IP::Addr ip_addr = IP::Addr::from_string(addr);
775 a->local_endpoint.address(ip_addr.to_asio());
776 a->local_endpoint.port(HostPort::parse_port(port, "OMI TCP listen"));
777
778 // open socket
779 a->acceptor.open(a->local_endpoint.protocol());
780
781 // set options
782 a->set_socket_options(0);
783
784 // bind to local address
785 a->acceptor.bind(a->local_endpoint);
786
787 // listen for incoming client connections
788 a->acceptor.listen();
789
790 // save acceptor
791 acceptor = a;
792
793 // dispatch accepts to handle_except()
794 queue_accept();
795 }
796
797 void listen_unix(const std::string &socket_path)
798 {
799#ifdef ASIO_HAS_LOCAL_SOCKETS
800 // init unix socket acceptor
802
803 // set endpoint
804 a->pre_listen(socket_path);
805 a->local_endpoint.path(socket_path);
806
807 // open socket
808 a->acceptor.open(a->local_endpoint.protocol());
809
810 // bind to local address
811 a->acceptor.bind(a->local_endpoint);
812
813 // set socket permissions in filesystem
814 a->set_socket_permissions(socket_path, 0777);
815
816 // listen for incoming client connections
817 a->acceptor.listen();
818
819 // save acceptor
820 acceptor = a;
821
822 // dispatch accepts to handle_except()
823 queue_accept();
824#else
825 throw Exception("unix sockets not supported on this platform");
826#endif
827 }
828
830 {
831 if (acceptor)
832 acceptor->async_accept(this, 0, io_context);
833 }
834
836 {
837#ifdef ASIO_HAS_LOCAL_SOCKETS
839 if (management_client_root && sock.peercreds(cr))
840 {
841 if (!cr.root_uid())
842 throw Exception("peer must be root");
843 }
844#endif
845 }
846
847 // despite its name, this method handles both accept and connect events
848 void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) override
849 {
850 if (stop_called)
851 return;
852
853 try
854 {
855 if (error)
856 throw Exception("accept/connect failed: " + error.message());
857 if (is_sock_open())
858 throw Exception("client already connected");
859
860 verify_sock_peer(*sock);
861
862 sock->non_blocking(true);
863 sock->set_cloexec();
864 socket = std::move(sock);
865
866 password_verified = false;
867
870 else
872
873 queue_recv();
874
875 if (!password_defined)
876 hold_cycle();
877 }
878 catch (const std::exception &e)
879 {
880 const std::string msg = "exception in accept/connect handler: " + std::string(e.what()) + '\n';
882 std::cerr << msg << std::flush;
884 }
885 queue_accept();
886 }
887
888 void connect_tcp(const std::string &addr, const std::string &port)
889 {
890 openvpn_io::ip::tcp::endpoint ep(IP::Addr::from_string(addr).to_asio(),
891 HostPort::parse_port(port, "OMI TCP connect"));
894 s->socket.async_connect(ep,
895 [self = Ptr(this), sock](const openvpn_io::error_code &error) mutable
896 {
897 // this is a connect, but we reuse the accept method
898 self->handle_accept(std::move(sock), error);
899 });
900 }
901
902 void connect_unix(const std::string &socket_path)
903 {
904#ifdef ASIO_HAS_LOCAL_SOCKETS
905 openvpn_io::local::stream_protocol::endpoint ep(socket_path);
906 AsioPolySock::Unix *s = new AsioPolySock::Unix(io_context, 0);
908 s->socket.async_connect(ep,
909 [self = Ptr(this), sock](const openvpn_io::error_code &error) mutable
910 {
911 // this is a connect, but we reuse the accept method
912 self->handle_accept(std::move(sock), error);
913 });
914#else
915 throw Exception("unix sockets not supported on this platform");
916#endif
917 }
918
920 {
921 if (!is_sock_open() || recv_queued)
922 return;
924 socket->async_receive(buf->mutable_buffer_clamp(),
925 [self = Ptr(this), sock = socket, buf](const openvpn_io::error_code &error, const size_t bytes_recvd)
926 {
927 self->handle_recv(error, bytes_recvd, std::move(buf), sock.get());
928 });
929 recv_queued = true;
930 }
931
932 void handle_recv(const openvpn_io::error_code &error,
933 const size_t bytes_recvd,
934 BufferPtr buf,
935 const AsioPolySock::Base *queued_socket)
936 {
937 recv_queued = false;
938 if (!is_sock_open() || socket.get() != queued_socket)
939 return;
940 if (error)
941 {
942 const bool eof = (error == openvpn_io::error::eof);
943 if (!eof)
944 OPENVPN_LOG("client socket recv error: " << error.message());
945 conditional_stop(eof);
946 return;
947 }
948 buf->set_size(bytes_recvd);
949 in_buf = std::move(buf);
950 process_recv();
951 }
952
954 {
955 while (in_buf->size())
956 {
957 const char c = (char)in_buf->pop_front();
958 in_partial += c;
959 if (c == '\n')
960 {
961 bool defer = false;
962 try
963 {
964 defer = process_in_line();
965 }
966 catch (const std::exception &e)
967 {
968 send("ERROR: in OMI command: " + std::string(e.what()) + "\r\n");
969 }
970 in_partial.clear();
971 if (defer)
972 return;
973 }
974 }
975
976 queue_recv();
977 }
978
980 {
981 if (!is_sock_open())
982 return;
983 auto &buf = *content_out.front();
984 socket->async_send(buf.const_buffer_clamp(),
985 [self = Ptr(this), sock = socket](const openvpn_io::error_code &error, const size_t bytes_sent)
986 {
987 self->handle_send(error, bytes_sent, sock.get());
988 });
989 }
990
991 void handle_send(const openvpn_io::error_code &error,
992 const size_t bytes_sent,
993 const AsioPolySock::Base *queued_socket)
994 {
995 if (!is_sock_open() || socket.get() != queued_socket)
996 return;
997
998 if (error)
999 {
1000 OPENVPN_LOG("client socket send error: " << error.message());
1001 conditional_stop(false);
1002 return;
1003 }
1004
1005 BufferPtr buf = content_out.front();
1006 if (bytes_sent == buf->size())
1007 {
1008 content_out.pop_front();
1010 content_out_throttle->size_change(content_out.size());
1011 }
1012 else if (bytes_sent < buf->size())
1013 buf->advance(bytes_sent);
1014 else
1015 {
1016 OPENVPN_LOG("client socket unexpected send size: " << bytes_sent << '/' << buf->size());
1017 conditional_stop(false);
1018 return;
1019 }
1020
1021 if (!content_out.empty())
1022 queue_send();
1023 else if (stop_called)
1024 conditional_stop(false);
1025 }
1026
1027 // I/O
1030 std::unique_ptr<AsioWork> asio_work;
1031 std::deque<BufferPtr> content_out;
1032 std::string in_partial;
1033 std::unique_ptr<Command> command;
1036 bool multiline = false;
1037 bool errors_to_stderr = false;
1038 bool recv_queued = false;
1039 bool password_defined = false;
1040 bool password_verified = false;
1041 std::string password;
1042
1043 // stopping
1044 volatile bool stop_called = false;
1046
1047 // hold
1048 bool hold_wait = false;
1049 bool hold_flag = false;
1050
1051 // bandwidth stats
1052 unsigned int bytecount = 0;
1053
1054 // histories
1055 History hist_log{"log", 100};
1056 History hist_state{"state", 100};
1057 History hist_echo{"echo", 100};
1058
1059 // throttling
1060 std::unique_ptr<BufferThrottle> content_out_throttle;
1061
1062#if defined(OPENVPN_PLATFORM_WIN)
1063 Win::ScopedHANDLE log_handle;
1064#endif
1065};
1066} // namespace openvpn
std::size_t expires_after(const Time::Duration &d)
void async_wait(F &&func)
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:105
openvpn_io::ip::address to_asio() const
Definition ip.hpp:594
BufferThrottle(const size_t low_water_arg, const size_t high_water_arg)
Definition omi.hpp:433
void size_change(const size_t size)
Definition omi.hpp:442
bool is_cmd(const Option &o) const
Definition omi.hpp:122
std::string notify(const std::string &msg)
Definition omi.hpp:171
History(const std::string &type_arg, const size_t max_size_arg)
Definition omi.hpp:115
std::string real_time_status() const
Definition omi.hpp:198
std::string show(size_t n) const
Definition omi.hpp:183
std::string error() const
Definition omi.hpp:209
std::deque< std::string > hist
Definition omi.hpp:217
std::string process_cmd(const Option &o)
Definition omi.hpp:127
std::string notify_prefix() const
Definition omi.hpp:193
AsioTimerSafe stop_timer
Definition omi.hpp:1045
virtual void omi_start_connection()=0
bool password_defined
Definition omi.hpp:1039
void send_password_prompt()
Definition omi.hpp:687
bool is_errors_to_stderr() const
Definition omi.hpp:394
void listen_unix(const std::string &socket_path)
Definition omi.hpp:797
virtual void omi_sigterm()=0
void queue_accept()
Definition omi.hpp:829
OPENVPN_EXCEPTION(omi_error)
RCPtr< OMICore > Ptr
Definition omi.hpp:428
void verify_sock_peer(AsioPolySock::Base &sock)
Definition omi.hpp:835
bool is_stopping() const
Definition omi.hpp:399
virtual void omi_sighup()
Definition omi.hpp:421
void log_setup(const LogFn &log)
Definition omi.hpp:226
unsigned int bytecount
Definition omi.hpp:1052
BufferPtr in_buf
Definition omi.hpp:1034
unsigned int get_bytecount() const
Definition omi.hpp:404
bool command_is_multiline(const Option &o)
Definition omi.hpp:638
AsioPolySock::Base::Ptr socket
Definition omi.hpp:1029
void queue_recv()
Definition omi.hpp:919
void async_done()
Definition omi.hpp:352
void listen_tcp(const std::string &addr, const std::string &port)
Definition omi.hpp:768
std::string password
Definition omi.hpp:1041
void connect_tcp(const std::string &addr, const std::string &port)
Definition omi.hpp:888
void send_password_correct()
Definition omi.hpp:692
void start(const OptionList &opt)
Definition omi.hpp:251
void state_line(const std::string &line)
Definition omi.hpp:382
OMICore(openvpn_io::io_context &io_context_arg)
Definition omi.hpp:220
bool errors_to_stderr
Definition omi.hpp:1037
std::string in_partial
Definition omi.hpp:1032
void log_full(const std::string &text)
Definition omi.hpp:357
void send_title_message()
Definition omi.hpp:682
void send(const std::string &str)
Definition omi.hpp:338
virtual bool omi_command_in(const std::string &arg0, const Command &cmd)=0
void start_connection_if_not_hold()
Definition omi.hpp:321
std::unique_ptr< BufferThrottle > content_out_throttle
Definition omi.hpp:1060
void handle_accept(AsioPolySock::Base::Ptr sock, const openvpn_io::error_code &error) override
Definition omi.hpp:848
void process_signal_cmd(const Option &o)
Definition omi.hpp:621
virtual bool omi_command_is_multiline(const std::string &arg0, const Option &option)=0
bool is_hold_cmd(const Option &o) const
Definition omi.hpp:558
virtual bool omi_is_sighup_implemented()
Definition omi.hpp:416
History hist_state
Definition omi.hpp:1056
bool process_in_line()
Definition omi.hpp:719
void send(BufferPtr buf)
Definition omi.hpp:327
bool command_in(std::unique_ptr< Command > cmd)
Definition omi.hpp:467
static std::string get_config(const OptionList &opt)
Definition omi.hpp:244
std::deque< BufferPtr > content_out
Definition omi.hpp:1031
volatile bool stop_called
Definition omi.hpp:1044
openvpn_io::io_context & io_context
Definition omi.hpp:425
virtual void omi_done(const bool eof)=0
bool is_sock_open() const
Definition omi.hpp:646
void log_timestamp(const time_t timestamp, const std::string &text)
Definition omi.hpp:370
bool password_verified
Definition omi.hpp:1040
void conditional_stop(const bool eof)
Definition omi.hpp:651
bool management_client_root
Definition omi.hpp:1035
void handle_recv(const openvpn_io::error_code &error, const size_t bytes_recvd, BufferPtr buf, const AsioPolySock::Base *queued_socket)
Definition omi.hpp:932
void hold_cycle()
Definition omi.hpp:597
std::string hold_cmd(const Option &o, bool &release)
Definition omi.hpp:563
void process_bytecount_cmd(const Option &o)
Definition omi.hpp:615
bool send_ready() const
Definition omi.hpp:344
void stop_omi_client(const bool eof)
Definition omi.hpp:668
void echo_line(const std::string &line)
Definition omi.hpp:388
static std::string read_config(const std::string &fn)
Definition omi.hpp:760
History hist_log
Definition omi.hpp:1055
std::unique_ptr< Command > command
Definition omi.hpp:1033
void queue_send()
Definition omi.hpp:979
virtual bool omi_stop()=0
History hist_echo
Definition omi.hpp:1057
std::unique_ptr< AsioWork > asio_work
Definition omi.hpp:1030
void log_line(const std::string &line)
Definition omi.hpp:376
void stop_omi_client(const bool eof, const unsigned int milliseconds)
Definition omi.hpp:659
void connect_unix(const std::string &socket_path)
Definition omi.hpp:902
void hold_release()
Definition omi.hpp:606
Acceptor::Base::Ptr acceptor
Definition omi.hpp:1028
bool process_password()
Definition omi.hpp:697
void process_recv()
Definition omi.hpp:953
void stop()
Definition omi.hpp:73
void handle_send(const openvpn_io::error_code &error, const size_t bytes_sent, const AsioPolySock::Base *queued_socket)
Definition omi.hpp:991
std::string get_optional(const std::string &name, size_t index, const size_t max_len) const
Definition options.hpp:1342
static Option parse_option_from_line(const std::string &line, Limits *lim)
Definition options.hpp:979
const Option & get(const std::string &name) const
Definition options.hpp:1254
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
bool exists(const std::string &name) const
Definition options.hpp:1325
std::string get_default(const size_t index, const size_t max_len, const std::string &default_value) const
Definition options.hpp:203
std::string get_optional(const size_t index, const size_t max_len) const
Definition options.hpp:194
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:187
T get_num(const size_t idx) const
Definition options.hpp:222
std::string render(const unsigned int flags) const
Definition options.hpp:264
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
static Ptr Create(ArgsT &&...args)
Creates a new instance of RcEnable with the given arguments.
Definition make_rc.hpp:43
static constexpr int FLAGS_OVERWRITE
Definition redir.hpp:119
static constexpr mode_t MODE_ALL
Definition redir.hpp:124
static constexpr int FLAGS_APPEND
Definition redir.hpp:120
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
unsigned short parse_port(const std::string &port, const std::string &title)
Definition hostport.hpp:46
bool is_valid_utf8(const STRING &str, const size_t max_len_flags=0)
Definition unicode.hpp:75
void log(const HANDLE file, const std::string &str)
Definition logutil.hpp:27
ScopedHANDLE create_file(const std::string &fn, const std::string &sddl_string, bool append)
Definition logutil.hpp:34
void trim_crlf(STRING &str)
Definition string.hpp:224
std::string unix2dos(const std::string &str, const bool force_eol=false)
Definition string.hpp:469
std::string to_upper_copy(const std::string &str)
Definition string.hpp:577
std::string read_text_utf8(const std::string &filename, const std::uint64_t max_size=0)
Definition file.hpp:136
std::string to_string(const T &t)
Convert a value to a string.
Definition to_string.hpp:45
std::string read_stdin()
Definition file.hpp:160
bool parse_number(const char *str, T &retval, const bool nondigit_term=false)
Definition number.hpp:34
BufferPtr buf_from_string(const std::string &str)
Definition bufstr.hpp:46
std::string date_time()
Definition timestr.hpp:139
openvpn_io::ip::tcp::socket socket
std::string to_string() const
Definition omi.hpp:99
std::vector< std::string > extra
Definition omi.hpp:96
std::string fn
Definition omi.hpp:68
LogFn(const OptionList &opt)
Definition omi.hpp:57
void redirect() noexcept override
Definition redir.hpp:47
bool root_uid() const
Definition peercred.hpp:42
proxy_host_port port
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string ret
std::ostringstream os
#define msg(flags,...)