OpenVPN 3 Core Library
Loading...
Searching...
No Matches
openvpn.cpp
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// OpenVPN 3 client with Management Interface
13
14#define OMI_VERSION "1.0.0"
15
16#include <string>
17#include <vector>
18#include <thread>
19#include <memory>
20#include <utility>
21#include <mutex>
22#include <condition_variable>
23
24// don't export core symbols
25#define OPENVPN_CORE_API_VISIBILITY_HIDDEN
26
27// should be included before other openvpn includes,
28// with the exception of openvpn/log includes
29#include <client/ovpncli.cpp>
30
41#include <openvpn/omi/omi.hpp>
42
43using namespace openvpn;
44
45std::string log_version()
46{
47 return platform_string("OpenVPN Management Interface", OMI_VERSION)
48 + " [" SSL_LIB_NAME "] - server starting";
49}
50
51class OMI;
52
54{
55 public:
56 Client(OMI *omi)
57 : parent(omi)
58 {
59 }
60
61 private:
62 bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, bool ipv6) override
63 {
64 return true;
65 }
66
68 {
69 return false;
70 }
71
72 void event(const ClientAPI::Event &ev) override;
73 void log(const ClientAPI::LogInfo &msg) override;
77
79};
80
81class OMI : public OMICore, public ClientAPI::LogReceiver
82{
83 public:
84 typedef RCPtr<OMI> Ptr;
85
86 OMI(openvpn_io::io_context &io_context, OptionList opt_arg)
88 opt(std::move(opt_arg)),
92 log_context(this)
93 {
96 }
97
98 void start()
99 {
101
103
104 // command line options
105 connection_timeout = opt.get_num<decltype(connection_timeout)>("connection-timeout", 1, 30);
106 management_query_passwords = opt.exists("management-query-passwords");
107 auth_nocache = opt.exists("auth-nocache");
108 management_external_key = opt.exists("management-external-key");
109 proto_override = opt.get_default("proto-force", 1, 16, "adaptive");
110 remote_override = opt.get_optional("remote-override", 1, 256);
111 management_up_down = opt.exists("management-up-down");
112 management_query_remote = opt.exists("management-query-remote");
113 exit_event_name = opt.get_optional("exit-event-name", 1, 256);
114
115 // passed by OpenVPN GUI to trigger exit
116 if (!exit_event_name.empty())
117 {
118 exit_event.assign(::CreateEvent(NULL, FALSE, FALSE, exit_event_name.c_str()));
119 exit_event.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
120 {
121 if (error)
122 return;
123 self->stop(); });
124 }
125
126 // http-proxy-override
127 {
128 const Option *o = opt.get_ptr("http-proxy-override");
129 if (o)
130 {
131 http_proxy_host = o->get(1, 128);
132 http_proxy_port = o->get(2, 16);
133 }
134 }
135
136 // begin listening/connecting on OMI port
138 }
139
140 void log(const ClientAPI::LogInfo &msg) override
141 {
142 openvpn_io::post(io_context, [this, msg]()
143 { log_msg(msg); });
144 }
145
146 void event(const ClientAPI::Event &ev)
147 {
148 openvpn_io::post(io_context, [this, ev]()
149 { event_msg(ev, nullptr); });
150 }
151
153 {
154 openvpn_io::post(io_context, [this, ev, ci]()
155 { event_msg(ev, &ci); });
156 }
157
159 {
160 // not currently supported, <cert> must be in config
161 }
162
164 {
165 // ignored
166 }
167
169 {
170 try
171 {
172 // publish signreq to main thread
173 {
174 std::lock_guard<std::mutex> lock(epki_mutex);
175 epki_signreq = &signreq;
176 }
177
178 // message main thread that signreq is published and pending
179 openvpn_io::post(io_context, [this]()
180 { epki_sign_request(); });
181
182 // allow asynchronous stop
183 Stop::Scope stop_scope(&async_stop, [this, &signreq]()
184 {
185 {
186 std::lock_guard<std::mutex> lock(epki_mutex);
187 epki_signreq = nullptr;
188 signreq.error = true;
189 signreq.errorText = "External PKI OMI: stop";
190 }
191 epki_cv.notify_all(); });
192
193 // wait for main thread to signal readiness by nulling epki_signreq ptr
194 {
195 std::unique_lock<std::mutex> lock(epki_mutex);
196 epki_cv.wait(lock, [this]()
197 { return epki_signreq == nullptr; });
198 }
199 }
200 catch (const std::exception &e)
201 {
202 std::lock_guard<std::mutex> lock(epki_mutex);
203 epki_signreq = nullptr;
204 signreq.error = true;
205 signreq.errorText = std::string("External PKI OMI: ") + e.what();
206 }
207 }
208
210 {
211 std::string sr;
212 {
213 std::lock_guard<std::mutex> lock(epki_mutex);
214 if (epki_signreq)
215 sr = epki_signreq->data;
216 }
217 send(">RSA_SIGN:" + sr + "\r\n");
218 }
219
220 void epki_sign_reply(const Command &cmd)
221 {
222 // get base64 signature from command
223 std::string sig64;
224 for (auto &line : cmd.extra)
225 {
226 sig64 += line;
227 }
228
229 // commit to connection thread
230 bool fail = false;
231 {
232 std::lock_guard<std::mutex> lock(epki_mutex);
233 if (epki_signreq)
234 {
235 epki_signreq->sig = sig64;
236 epki_signreq = nullptr;
237 }
238 else
239 fail = true;
240 }
241 if (fail)
242 send("ERROR: unsolicited rsa-sig command\r\n");
243 else
244 {
245 epki_cv.notify_all();
246 send("SUCCESS: rsa-sig command succeeded\r\n");
247 }
248 }
249
250 bool omi_command_is_multiline(const std::string &arg0, const Option &o) override
251 {
252 if (arg0 == "rsa-sig")
253 return true;
254 return false;
255 }
256
257 private:
258 bool omi_command_in(const std::string &arg0, const Command &cmd) override
259 {
260 switch (arg0.at(0))
261 {
262 case 'p':
263 {
264 if (is_auth_cmd(arg0))
265 {
267 return false;
268 }
269 break;
270 }
271 case 'r':
272 {
273 if (arg0 == "remote")
274 {
276 return false;
277 }
278 else if (arg0 == "rsa-sig")
279 {
280 epki_sign_reply(cmd);
281 return false;
282 }
283 break;
284 }
285 case 'u':
286 {
287 if (is_auth_cmd(arg0))
288 {
290 return false;
291 }
292 break;
293 }
294 }
295 send("ERROR: unknown command, enter 'help' for more options\r\n");
296 return false;
297 }
298
299 void omi_done(const bool eof) override
300 {
301 // OPENVPN_LOG("OMI DONE eof=" << eof);
302 }
303
304 std::vector<ClientAPI::KeyValue> get_peer_info() const
305 {
306 std::vector<ClientAPI::KeyValue> ret;
307 OptionList::IndexMap::const_iterator se = opt.map().find("setenv");
308 if (se != opt.map().end())
309 {
310 for (OptionList::IndexList::const_iterator i = se->second.begin(); i != se->second.end(); ++i)
311 {
312 const Option &o = opt[*i];
313 o.touch();
314 const std::string &k = o.get(1, 64);
315 if (string::starts_with(k, "IV_") || string::starts_with(k, "UV_"))
316 {
317 const std::string &v = o.get(2, 256);
318 ret.emplace_back(k, v);
319 }
320 }
321 }
322 return ret;
323 }
324
325 void omi_start_connection() override
326 {
327 try
328 {
329 // OPENVPN_LOG("OMI START CONNECTION");
330
331 // reset state
333 reconnect_reason = "";
334
335 if (!config)
336 {
337 config.reset(new ClientAPI::Config);
338 config->guiVersion = "ovpnmi " OMI_VERSION;
339 config->content = get_config(opt);
340 config->peerInfo = get_peer_info();
341 config->connTimeout = connection_timeout;
342 config->protoOverride = proto_override;
343 config->serverOverride = remote_override;
344 config->tunPersist = true;
345 config->googleDnsFallback = true;
346 config->autologinSessions = true;
347 config->compressionMode = "yes";
348 config->proxyHost = http_proxy_host;
349 config->proxyPort = http_proxy_port;
350 config->echo = true;
351
353 config->externalPkiAlias = "EPKI"; // dummy alias
354
355 did_query_remote = false;
356 }
357
359 const ClientAPI::EvalConfig eval = clihelper.eval_config(*config);
360 if (eval.error)
361 OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message);
362
363 autologin = eval.autologin;
364
365 // for compatibility with openvpn2
366 if (eval.windowsDriver == "wintun")
367 config->wintun = true;
368
371 else if (proxy_need_creds)
372 query_username_password("HTTP Proxy", false, "", false);
375 else
377 }
378 catch (const std::exception &e)
379 {
380 set_final_error(e.what());
381 stop();
382 }
383 }
384
385 void query_username_password(const std::string &type,
386 const bool password_only,
387 const std::string &static_challenge,
388 const bool static_challenge_echo)
389 {
391 auth_type = type;
392 auth_password_only = password_only;
393
394 std::string notify = ">PASSWORD:Need '" + type + "' ";
395 if (password_only)
396 notify += "password";
397 else
398 notify += "username/password";
399
400 // static challenge
401 if (!static_challenge.empty())
402 {
403 notify += " SC:";
404 if (static_challenge_echo)
405 notify += '1';
406 else
407 notify += '0';
408 notify += ',';
409 notify += static_challenge;
410 }
411
412 notify += "\r\n";
413 send(notify);
414 }
415
416 bool is_auth_cmd(const std::string &arg0) const
417 {
418 return arg0 == "username" || arg0 == "password";
419 }
420
422 {
423 const std::string up = o.get(0, 0);
424 const std::string type = o.get(1, 64);
425 const std::string cred = o.get(2, 512);
426 if (auth_type.empty() || type != auth_type || (up == "username" && auth_password_only))
427 {
428 send("ERROR: no " + up + " is currently needed at this time\r\n");
429 return;
430 }
431 bool changed = false;
432 if (up == "username")
433 {
434 auth_username = cred;
435 changed = true;
436 }
437 else if (up == "password")
438 {
439 auth_password = cred;
440 changed = true;
441 }
442 if (changed)
443 send("SUCCESS: '" + auth_type + "' " + up + " entered, but not yet verified\r\n");
444 if ((!auth_username.empty() || auth_password_only) && !auth_password.empty())
445 {
448 }
449 }
450
452 {
453 auth_type = "";
454 auth_password_only = false;
455 auth_username = "";
456 auth_password = "";
457 }
458
459 void provide_username_password(const std::string &type, const std::string &username, const std::string &password)
460 {
461 if (!dc_cookie.empty())
462 {
464 creds->dynamicChallengeCookie = dc_cookie;
465 try
466 {
467 // response could be whole challenge string in case of connect 2.x
469 creds->response = std::string{cr.get_challenge_text()};
470 }
471 catch (const ChallengeResponse::dynamic_challenge_parse_error &)
472 {
473 // response contains only challenge text
474 creds->response = auth_password;
475 }
476 }
477 else if (type == "Auth")
478 {
480 creds->username = username;
481 creds->password = password;
482 }
483 else if (type == "HTTP Proxy")
484 {
485 if (config)
486 {
487 config->proxyUsername = username;
488 config->proxyPassword = password;
489 }
490 proxy_need_creds = false;
491 }
493 }
494
495 void query_remote(const std::string &host, const std::string &port, const std::string &proto)
496 {
497 send(">REMOTE:" + host + ',' + port + ',' + proto + "\r\n");
498 remote_pending = true;
499 }
500
502 {
503 if (!remote_pending)
504 {
505 send("ERROR: no pending remote query\r\n");
506 return;
507 }
508
509 std::string host;
510 std::string port;
511 bool mod = false;
512
513 const std::string type = o.get(1, 16);
514 if (type == "MOD")
515 {
516 host = o.get(2, 256);
517 port = o.get_optional(3, 16);
518 mod = true;
519 }
520 else if (type == "ACCEPT")
521 {
522 ;
523 }
524 else
525 {
526 send("ERROR: remote type must be MOD or ACCEPT\r\n");
527 return;
528 }
529
530 send("SUCCESS: remote command succeeded\r\n");
531 remote_pending = false;
532
533 if (mod && config)
534 {
535 config->serverOverride = host;
536 // fixme -- override port
537 }
538 did_query_remote = true;
540 }
541
543 {
544 if (get_bytecount())
545 {
546 bytecount_timer.expires_after(Time::Duration::seconds(get_bytecount()));
547 bytecount_timer.async_wait([self = Ptr(this)](const openvpn_io::error_code &error)
548 {
549 if (!error)
550 self->report_bytecount(); });
551 }
552 else
554 }
555
557 {
558 if (client && get_bytecount())
559 {
560 const ClientAPI::TransportStats ts = client->transport_stats();
561 send(">BYTECOUNT:" + openvpn::to_string(ts.bytesIn) + ',' + openvpn::to_string(ts.bytesOut) + "\r\n");
562 }
564 }
565
567 {
568 try
569 {
570 // reset client instance
571 client.reset(new Client(this));
572
573 // evaluate config
574 const ClientAPI::EvalConfig eval = client->eval_config(*config);
575 if (eval.error)
576 OPENVPN_THROW_EXCEPTION("eval config error: " << eval.message);
577
578 // add credentials, if available
579 if (creds)
580 {
581 const ClientAPI::Status creds_status = client->provide_creds(*creds);
582 if (creds_status.error)
583 OPENVPN_THROW_EXCEPTION("creds error: " << creds_status.message);
584 }
585
586 // bytecount
588
589 // start connection thread
590 thread.reset(new std::thread([this]()
591 { connection_thread(); }));
592 }
593 catch (const std::exception &e)
594 {
595 set_final_error(e.what());
596 stop();
597 }
598 }
599
601 {
602 openvpn_io::detail::signal_blocker signal_blocker; // signals should be handled by parent thread
603 std::string error;
604 try
605 {
606 const ClientAPI::Status cs = client->connect();
607 if (cs.error)
608 {
609 error = "connect error: ";
610 if (!cs.status.empty())
611 {
612 error += cs.status;
613 error += ": ";
614 }
615 error += cs.message;
616 }
617 }
618 catch (const std::exception &e)
619 {
620 error = "connect thread exception: ";
621 error += e.what();
622 }
623
624 // generate an internal event for client exceptions
625 if (!error.empty())
626 {
628 ev.error = true;
629 ev.fatal = true;
630 ev.name = "CLIENT_EXCEPTION";
631 ev.info = error;
632 event(ev);
633 }
634 }
635
637 {
638 try
639 {
640 if (thread)
641 thread->join(); // may throw if thread has already exited
642 }
643 catch (const std::exception &)
644 {
645 }
646 }
647
648 bool omi_stop() override
649 {
650 bool ret = false;
651
652 // in case connect thread is blocking in external_pki_sign_request
654
655 // cancel wait on exit_event
656 if (exit_event.is_open())
657 exit_event.cancel();
658
659 // stop timers
662
663 // stop the client
664 if (client)
665 client->stop();
666
667 // wait for client thread to exit
668 join_thread();
669
670 // if there's a final error, dump to management interface
671 const std::string fe = get_final_error();
672 if (!fe.empty())
673 {
676 std::cerr << fe << std::endl;
677 OPENVPN_LOG_STRING(fe + '\n');
678 ret = true;
679 }
680
681 // cancel signals
682 if (signals)
683 signals->cancel();
684
685 return ret;
686 }
687
688 void retry()
689 {
690 // wait for client thread to exit
691 join_thread();
692
693 // restart connection
695 }
696
697 void deferred_reconnect(const unsigned int seconds, const std::string &reason)
698 {
699 reconnect_timer.expires_after(Time::Duration::seconds(seconds));
700 reconnect_timer.async_wait([self = Ptr(this), reason](const openvpn_io::error_code &error)
701 {
702 if (!error)
703 {
704 self->state_line(gen_state_msg(false, "RECONNECTING", reason));
705 self->retry();
706 } });
707 }
708
709 void omi_sigterm() override
710 {
711 if (client)
712 set_final_error(gen_state_msg(true, "EXITING", "exit-with-notification"));
713 stop();
714 }
715
717 {
718 return true;
719 }
720
721 void omi_sighup() override
722 {
723 if (client)
724 client->reconnect(1);
725 }
726
728 {
729 log_full(msg.text);
730 }
731
732 static std::string event_format(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo *ci)
733 {
734 const time_t now = ::time(NULL);
735 std::string evstr = openvpn::to_string(now) + ',' + ev.name;
736 if (ev.name == "CONNECTED" && ci)
737 evstr += ",SUCCESS," + ci->vpnIp4 + ',' + ci->serverIp + ',' + ci->serverPort + ",,," + ci->vpnIp6;
738 else
739 evstr += ',' + ev.info + ",,";
740 evstr += "\r\n";
741 return evstr;
742 }
743
744 static std::string gen_state_msg(const bool prefix, std::string name, std::string info)
745 {
747 ev.name = std::move(name);
748 ev.info = std::move(info);
749 std::string ret;
750 if (prefix)
751 ret = ">STATE:";
752 ret += event_format(ev, nullptr);
753 return ret;
754 }
755
757 {
758 // log events (even if in stopping state)
759 {
761 li.text = ev.name;
762 if (!ev.info.empty())
763 {
764 li.text += " : ";
765 li.text += ev.info;
766 }
767 if (ev.fatal)
768 li.text += " [FATAL-ERR]";
769 else if (ev.error)
770 li.text += " [ERR]";
771 li.text += '\n';
772 log_msg(li);
773 }
774
775 // if we are in a stopping state, don't process the event
776 if (is_stopping())
777 return;
778
779 // process events
780 if ((ev.name == "AUTH_FAILED" || ev.name == "DYNAMIC_CHALLENGE") && management_query_passwords)
781 {
782 if (ev.name == "DYNAMIC_CHALLENGE")
783 {
784 dc_cookie = ev.info;
785 }
786 else
787 {
788 dc_cookie = "";
789 }
790
791 // handle auth failures
792 std::string msg = ">PASSWORD:Verification Failed: 'Auth'";
793 if (!ev.info.empty())
794 msg += " ['" + ev.info + "']";
795 msg += "\r\n";
796 send(msg);
797
798 // reset query state
799 creds.reset();
800 did_query_remote = false;
801
802 // exit/reconnect
803 if (autologin)
804 {
805 set_final_error(">FATAL: auth-failure: " + ev.info + "\r\n");
806 stop();
807 }
808 else
809 deferred_reconnect(1, "auth-failure");
810 }
811
812 else if (ev.name == "CLIENT_HALT")
813 {
814 std::string reason = ev.info;
815 if (reason.empty())
816 reason = "client was disconnected from server";
817 send(">NOTIFY:info,server-pushed-halt," + reason + "\r\n");
818 set_final_error(gen_state_msg(true, "EXITING", "exit-with-notification"));
819 stop();
820 }
821
822 else if (ev.name == "CLIENT_RESTART")
823 {
824 // fixme -- handle PSID
825 std::string reason = ev.info;
826 if (reason.empty())
827 reason = "server requested a client reconnect";
828 reconnect_reason = "server-pushed-connection-reset";
829 send(">NOTIFY:info," + reconnect_reason + ',' + reason + "\r\n");
830 omi_sighup();
831 }
832
833 else if (ev.name == "RECONNECTING")
834 {
835 ClientAPI::Event nev(ev);
836 if (nev.info.empty())
838 reconnect_reason = "";
839 state_line(event_format(nev, nullptr));
840 }
841
842 else if (ev.name == "PROXY_NEED_CREDS" && management_query_passwords)
843 {
844 // need proxy credentials, retry
845 proxy_need_creds = true;
846 state_line(event_format(ev, nullptr));
847 retry();
848 }
849
850 else if (ev.name == "DISCONNECTED")
851 {
852 // for now, we ignore DISCONNECTED messages
853 }
854
855 else if (ev.fatal)
856 {
857 // this event is a fatal error
858 std::string reason = ev.name;
859 if (!ev.info.empty())
860 {
861 reason += ": ";
862 reason += ev.info;
863 }
864 set_final_error(">FATAL:" + reason + "\r\n");
865 stop();
866 }
867
868 else if (ev.name == "ECHO")
869 {
870 echo_line(openvpn::to_string(::time(NULL)) + ',' + ev.info + "\r\n");
871 }
872
873 else if (ev.name == "CONNECTED")
874 {
875 // generate >UPDOWN: event
877 emit_up_down("UP");
878
879 // reset pre-connection state
880 creds.reset();
881 reconnect_reason = "";
882
883 // generate a TCP_CONNECT event if TCP connection
884 if (ci && string::starts_with(ci->serverProto, "TCP"))
885 state_line(gen_state_msg(false, "TCP_CONNECT", ""));
886
887 // push the event string to state notification/history
888 state_line(event_format(ev, ci));
889 }
890
891 else
892 {
893 // push the event string to state notification/history
894 state_line(event_format(ev, ci));
895 }
896 }
897
898 void emit_up_down(const std::string &state)
899 {
900 std::string out = ">UPDOWN:" + state + "\r\n";
901 out += ">UPDOWN:ENV,END\r\n";
902 send(out);
903 }
904
905 void set_final_error(const std::string &err)
906 {
907 if (!err.empty())
909 }
910
911 std::string get_final_error()
912 {
913 return final_error;
914 }
915
916 void signal(const openvpn_io::error_code &error, int signum)
917 {
918 if (!error && !is_stopping())
919 {
920 OPENVPN_LOG("ASIO SIGNAL " << signum);
921 switch (signum)
922 {
923 case SIGINT:
924 case SIGTERM:
925 omi_sigterm();
926 break;
927#if !defined(OPENVPN_PLATFORM_WIN)
928 case SIGHUP:
929 omi_sighup();
930 signal_rearm();
931 break;
932#endif
933 }
934 }
935 }
936
938 {
939 signals->register_signals_all([self = Ptr(this)](const openvpn_io::error_code &error, int signal_number)
940 { self->signal(error, signal_number); });
941 }
942
943 // options
945
946 // general
947 std::unique_ptr<Client> client;
948 std::unique_ptr<ClientAPI::Config> config;
949 std::unique_ptr<ClientAPI::ProvideCreds> creds;
950 std::unique_ptr<std::thread> thread;
951 std::string final_error;
953
954 // timeout
956
957 // auth
959 bool auth_nocache = false;
960 std::string auth_type;
961 bool auth_password_only = false;
962 std::string auth_username;
963 std::string auth_password;
964 std::string dc_cookie;
965
966 // remote override
968 bool did_query_remote = false;
969 bool remote_pending = false;
970 std::string remote_override;
971
972 // protocol override (udp/tcp)
973 std::string proto_override;
974
975 // proxy
976 std::string http_proxy_host;
977 std::string http_proxy_port;
978 bool proxy_need_creds = false;
979
980 // reconnections
981 std::string reconnect_reason;
982
983 // reconnect
985
986 // bytecount
988
989 // external PKI
991 std::mutex epki_mutex;
992 std::condition_variable epki_cv;
993 ClientAPI::ExternalPKISignRequest *epki_signreq = nullptr; // protected by epki_mutex
994
995 // up/down
996 bool management_up_down = false;
997
998 // autologin
999 bool autologin = false;
1000
1001 // signals
1003
1004 typedef openvpn_io::windows::object_handle AsioEvent;
1006 std::string exit_event_name;
1007
1008 Log::Context log_context; // should be initialized last
1009};
1010
1012{
1013 if (ev.name == "CONNECTED")
1014 {
1016 parent->event(ev, ci);
1017 }
1018 else
1019 parent->event(ev);
1020}
1021
1023{
1024 parent->log(msg);
1025}
1026
1031
1036
1041
1042
1044{
1045 openvpn_io::io_context io_context(1);
1046 bool io_context_run_called = false;
1047 int ret = 0;
1048 OMI::Ptr omi;
1049
1050 try
1051 {
1052 TunWin::NRPT::delete_rules(0); // delete stale NRPT rules
1053 omi.reset(new OMI(io_context, std::move(opt)));
1054 omi->start();
1055 io_context_run_called = true;
1056 io_context.run();
1057 omi->stop();
1058 }
1059 catch (const std::exception &e)
1060 {
1061 if (omi)
1062 omi->stop();
1063 if (io_context_run_called)
1064 io_context.poll(); // execute completion handlers,
1065 std::cerr << "openvpn: run loop exception: " << e.what() << std::endl;
1066 ret = 1;
1067 }
1068 return ret;
1069}
1070
1071int main(int argc, char *argv[])
1072{
1073 int ret = 0;
1074
1075 try
1076 {
1077 if (argc >= 2)
1078 {
1080 }
1081 else
1082 {
1083 std::cout << log_version() << std::endl;
1084 std::cout << "Usage: openvpn [args...]" << std::endl;
1085 ret = 2;
1086 }
1087 }
1088 catch (const std::exception &e)
1089 {
1090 std::cerr << "openvpn: " << e.what() << std::endl;
1091 ret = 1;
1092 }
1093 return ret;
1094}
bool pause_on_connection_timeout() override
Definition openvpn.cpp:67
void log(ClientAPI_LogInfo loginfo)
Definition Client.java:106
void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &event) override
Definition openvpn.cpp:1037
void event(ClientAPI_Event event)
Definition Client.java:84
void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req)
Definition Client.java:93
bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, bool ipv6) override
Definition openvpn.cpp:62
void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req)
Definition Client.java:100
Client(OMI *omi)
Definition openvpn.cpp:56
OMI * parent
Definition openvpn.cpp:78
void epki_sign_request()
Definition openvpn.cpp:209
std::string auth_password
Definition openvpn.cpp:963
bool did_query_remote
Definition openvpn.cpp:968
std::vector< ClientAPI::KeyValue > get_peer_info() const
Definition openvpn.cpp:304
std::unique_ptr< std::thread > thread
Definition openvpn.cpp:950
void query_username_password(const std::string &type, const bool password_only, const std::string &static_challenge, const bool static_challenge_echo)
Definition openvpn.cpp:385
AsioTimerSafe bytecount_timer
Definition openvpn.cpp:987
void process_remote_cmd(const Option &o)
Definition openvpn.cpp:501
void start_connection_thread()
Definition openvpn.cpp:566
void signal_rearm()
Definition openvpn.cpp:937
bool management_up_down
Definition openvpn.cpp:996
std::unique_ptr< ClientAPI::Config > config
Definition openvpn.cpp:948
ASIOSignals::Ptr signals
Definition openvpn.cpp:1002
void start()
Definition openvpn.cpp:98
AsioEvent exit_event
Definition openvpn.cpp:1005
std::string reconnect_reason
Definition openvpn.cpp:981
void report_bytecount()
Definition openvpn.cpp:556
void set_final_error(const std::string &err)
Definition openvpn.cpp:905
void join_thread()
Definition openvpn.cpp:636
bool omi_command_is_multiline(const std::string &arg0, const Option &o) override
Definition openvpn.cpp:250
std::string exit_event_name
Definition openvpn.cpp:1006
void query_remote(const std::string &host, const std::string &port, const std::string &proto)
Definition openvpn.cpp:495
void retry()
Definition openvpn.cpp:688
OptionList opt
Definition openvpn.cpp:944
std::string get_final_error()
Definition openvpn.cpp:911
void process_auth_cmd(const Option &o)
Definition openvpn.cpp:421
void event_msg(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo *ci)
Definition openvpn.cpp:756
OMI(openvpn_io::io_context &io_context, OptionList opt_arg)
Definition openvpn.cpp:86
bool management_query_remote
Definition openvpn.cpp:967
void connection_thread()
Definition openvpn.cpp:600
std::mutex epki_mutex
Definition openvpn.cpp:991
bool management_external_key
Definition openvpn.cpp:990
Stop async_stop
Definition openvpn.cpp:952
void provide_username_password(const std::string &type, const std::string &username, const std::string &password)
Definition openvpn.cpp:459
bool management_query_passwords
Definition openvpn.cpp:958
void log_msg(const ClientAPI::LogInfo &msg)
Definition openvpn.cpp:727
std::condition_variable epki_cv
Definition openvpn.cpp:992
std::string dc_cookie
Definition openvpn.cpp:964
bool omi_command_in(const std::string &arg0, const Command &cmd) override
Definition openvpn.cpp:258
bool auth_nocache
Definition openvpn.cpp:959
std::unique_ptr< Client > client
Definition openvpn.cpp:947
void signal(const openvpn_io::error_code &error, int signum)
Definition openvpn.cpp:916
void log(const ClientAPI::LogInfo &msg) override
Definition openvpn.cpp:140
bool omi_is_sighup_implemented() override
Definition openvpn.cpp:716
void omi_sigterm() override
Definition openvpn.cpp:709
std::string proto_override
Definition openvpn.cpp:973
void deferred_reconnect(const unsigned int seconds, const std::string &reason)
Definition openvpn.cpp:697
std::string auth_username
Definition openvpn.cpp:962
void event(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo &ci)
Definition openvpn.cpp:152
bool omi_stop() override
Definition openvpn.cpp:648
bool auth_password_only
Definition openvpn.cpp:961
void omi_start_connection() override
Definition openvpn.cpp:325
void schedule_bytecount_timer()
Definition openvpn.cpp:542
std::unique_ptr< ClientAPI::ProvideCreds > creds
Definition openvpn.cpp:949
void event(const ClientAPI::Event &ev)
Definition openvpn.cpp:146
void reset_auth_cmd()
Definition openvpn.cpp:451
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest &signreq)
Definition openvpn.cpp:168
Log::Context log_context
Definition openvpn.cpp:1008
bool proxy_need_creds
Definition openvpn.cpp:978
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest &certreq)
Definition openvpn.cpp:158
std::string final_error
Definition openvpn.cpp:951
virtual void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &event)
Definition openvpn.cpp:163
void omi_sighup() override
Definition openvpn.cpp:721
ClientAPI::ExternalPKISignRequest * epki_signreq
Definition openvpn.cpp:993
bool is_auth_cmd(const std::string &arg0) const
Definition openvpn.cpp:416
void omi_done(const bool eof) override
Definition openvpn.cpp:299
static std::string event_format(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo *ci)
Definition openvpn.cpp:732
bool autologin
Definition openvpn.cpp:999
std::string http_proxy_port
Definition openvpn.cpp:977
RCPtr< OMI > Ptr
Definition openvpn.cpp:84
void emit_up_down(const std::string &state)
Definition openvpn.cpp:898
openvpn_io::windows::object_handle AsioEvent
Definition openvpn.cpp:1004
bool remote_pending
Definition openvpn.cpp:969
void epki_sign_reply(const Command &cmd)
Definition openvpn.cpp:220
std::string http_proxy_host
Definition openvpn.cpp:976
int connection_timeout
Definition openvpn.cpp:955
std::string remote_override
Definition openvpn.cpp:970
AsioTimerSafe reconnect_timer
Definition openvpn.cpp:984
std::string auth_type
Definition openvpn.cpp:960
static std::string gen_state_msg(const bool prefix, std::string name, std::string info)
Definition openvpn.cpp:744
void register_signals_all(SignalHandler stop_handler)
std::size_t expires_after(const Time::Duration &d)
void async_wait(F &&func)
const std::string & get_challenge_text() const
Definition cr.hpp:223
EvalConfig eval_config(const Config &config)
Definition ovpncli.cpp:761
bool is_errors_to_stderr() const
Definition omi.hpp:394
bool is_stopping() const
Definition omi.hpp:399
void log_setup(const LogFn &log)
Definition omi.hpp:226
unsigned int get_bytecount() const
Definition omi.hpp:404
std::string password
Definition omi.hpp:1041
void start(const OptionList &opt)
Definition omi.hpp:251
void state_line(const std::string &line)
Definition omi.hpp:382
void log_full(const std::string &text)
Definition omi.hpp:357
void send(BufferPtr buf)
Definition omi.hpp:327
static std::string get_config(const OptionList &opt)
Definition omi.hpp:244
openvpn_io::io_context & io_context
Definition omi.hpp:425
void echo_line(const std::string &line)
Definition omi.hpp:388
void stop()
Definition omi.hpp:73
static OptionList parse_from_argv_static(const std::vector< std::string > &argv)
Definition options.hpp:875
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
T get_num(const std::string &name, const size_t idx, const T default_value) const
Definition options.hpp:1416
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
std::string get_default(const std::string &name, size_t index, const size_t max_len, const std::string &default_value) const
Definition options.hpp:1387
bool exists(const std::string &name) const
Definition options.hpp:1325
std::string get_optional(const size_t index, const size_t max_len) const
Definition options.hpp:194
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
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
void stop()
Definition stop.hpp:85
static void delete_rules(DWORD process_id)
Remove our NRPT rules from the registry.
Definition nrpt.hpp:157
#define OPENVPN_THROW_EXCEPTION(stuff)
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
std::vector< std::string > from_argv(int argc, char *argv[], const bool skip_first)
Definition string.hpp:541
bool starts_with(const STRING &str, const std::string &prefix)
Definition string.hpp:79
std::string add_trailing_crlf_copy(std::string str)
Definition string.hpp:207
std::string trim_crlf_copy(std::string str)
Definition string.hpp:231
std::string to_string(const T &t)
Convert a value to a string.
Definition to_string.hpp:45
std::string platform_string()
int main(int argc, char *argv[])
Definition openvpn.cpp:1071
std::string log_version()
Definition openvpn.cpp:45
int run(OptionList opt)
Definition openvpn.cpp:1043
#define OMI_VERSION
Definition openvpn.cpp:14
Struct containing configuration details parsed from an OpenVPN configuration file.
Definition ovpncli.hpp:56
Scoped RAII for the global_log pointer.
std::vector< std::string > extra
Definition omi.hpp:96
proxy_host_port port
remote_address ipv6
proxy_host_port host
std::string ret
static std::stringstream out
Definition test_path.cpp:10
#define msg(flags,...)