14#define OMI_VERSION "1.0.0"
22#include <condition_variable>
25#define OPENVPN_CORE_API_VISIBILITY_HIDDEN
48 +
" [" SSL_LIB_NAME
"] - server starting";
62 bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote,
bool ipv6)
override
88 opt(std::move(opt_arg)),
119 exit_event.async_wait([self =
Ptr(
this)](
const openvpn_io::error_code &error)
188 signreq.
error =
true;
189 signreq.
errorText =
"External PKI OMI: stop";
195 std::unique_lock<std::mutex> lock(
epki_mutex);
200 catch (
const std::exception &e)
204 signreq.
error =
true;
205 signreq.
errorText = std::string(
"External PKI OMI: ") + e.what();
217 send(
">RSA_SIGN:" + sr +
"\r\n");
224 for (
auto &line : cmd.
extra)
242 send(
"ERROR: unsolicited rsa-sig command\r\n");
246 send(
"SUCCESS: rsa-sig command succeeded\r\n");
252 if (arg0 ==
"rsa-sig")
273 if (arg0 ==
"remote")
278 else if (arg0 ==
"rsa-sig")
295 send(
"ERROR: unknown command, enter 'help' for more options\r\n");
306 std::vector<ClientAPI::KeyValue>
ret;
307 OptionList::IndexMap::const_iterator se =
opt.
map().find(
"setenv");
308 if (se !=
opt.
map().end())
310 for (OptionList::IndexList::const_iterator i = se->second.begin(); i != se->second.end(); ++i)
314 const std::string &k = o.
get(1, 64);
317 const std::string &v = o.
get(2, 256);
318 ret.emplace_back(k, v);
344 config->tunPersist =
true;
345 config->googleDnsFallback =
true;
346 config->autologinSessions =
true;
347 config->compressionMode =
"yes";
353 config->externalPkiAlias =
"EPKI";
378 catch (
const std::exception &e)
386 const bool password_only,
387 const std::string &static_challenge,
388 const bool static_challenge_echo)
394 std::string notify =
">PASSWORD:Need '" + type +
"' ";
396 notify +=
"password";
398 notify +=
"username/password";
401 if (!static_challenge.empty())
404 if (static_challenge_echo)
409 notify += static_challenge;
418 return arg0 ==
"username" || arg0 ==
"password";
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);
428 send(
"ERROR: no " + up +
" is currently needed at this time\r\n");
431 bool changed =
false;
432 if (up ==
"username")
437 else if (up ==
"password")
443 send(
"SUCCESS: '" +
auth_type +
"' " + up +
" entered, but not yet verified\r\n");
471 catch (
const ChallengeResponse::dynamic_challenge_parse_error &)
477 else if (type ==
"Auth")
480 creds->username = username;
483 else if (type ==
"HTTP Proxy")
487 config->proxyUsername = username;
497 send(
">REMOTE:" +
host +
',' +
port +
',' + proto +
"\r\n");
505 send(
"ERROR: no pending remote query\r\n");
513 const std::string type = o.
get(1, 16);
520 else if (type ==
"ACCEPT")
526 send(
"ERROR: remote type must be MOD or ACCEPT\r\n");
530 send(
"SUCCESS: remote command succeeded\r\n");
550 self->report_bytecount(); });
582 if (creds_status.
error)
590 thread.reset(
new std::thread([
this]()
593 catch (
const std::exception &e)
602 openvpn_io::detail::signal_blocker signal_blocker;
609 error =
"connect error: ";
618 catch (
const std::exception &e)
620 error =
"connect thread exception: ";
630 ev.
name =
"CLIENT_EXCEPTION";
643 catch (
const std::exception &)
676 std::cerr << fe << std::endl;
704 self->state_line(
gen_state_msg(
false,
"RECONNECTING", reason));
734 const time_t now = ::time(NULL);
736 if (ev.
name ==
"CONNECTED" && ci)
739 evstr +=
',' + ev.
info +
",,";
744 static std::string
gen_state_msg(
const bool prefix, std::string name, std::string info)
747 ev.
name = std::move(name);
748 ev.
info = std::move(info);
762 if (!ev.
info.empty())
768 li.
text +=
" [FATAL-ERR]";
782 if (ev.
name ==
"DYNAMIC_CHALLENGE")
792 std::string
msg =
">PASSWORD:Verification Failed: 'Auth'";
793 if (!ev.
info.empty())
812 else if (ev.
name ==
"CLIENT_HALT")
814 std::string reason = ev.
info;
816 reason =
"client was disconnected from server";
817 send(
">NOTIFY:info,server-pushed-halt," + reason +
"\r\n");
822 else if (ev.
name ==
"CLIENT_RESTART")
825 std::string reason = ev.
info;
827 reason =
"server requested a client reconnect";
833 else if (ev.
name ==
"RECONNECTING")
836 if (nev.
info.empty())
850 else if (ev.
name ==
"DISCONNECTED")
858 std::string reason = ev.
name;
859 if (!ev.
info.empty())
868 else if (ev.
name ==
"ECHO")
873 else if (ev.
name ==
"CONNECTED")
900 std::string
out =
">UPDOWN:" + state +
"\r\n";
901 out +=
">UPDOWN:ENV,END\r\n";
916 void signal(
const openvpn_io::error_code &error,
int signum)
927#if !defined(OPENVPN_PLATFORM_WIN)
940 { self->signal(error, signal_number); });
948 std::unique_ptr<ClientAPI::Config>
config;
949 std::unique_ptr<ClientAPI::ProvideCreds>
creds;
1013 if (ev.
name ==
"CONNECTED")
1045 openvpn_io::io_context io_context(1);
1046 bool io_context_run_called =
false;
1053 omi.
reset(
new OMI(io_context, std::move(opt)));
1055 io_context_run_called =
true;
1059 catch (
const std::exception &e)
1063 if (io_context_run_called)
1065 std::cerr <<
"openvpn: run loop exception: " << e.what() << std::endl;
1084 std::cout <<
"Usage: openvpn [args...]" << std::endl;
1088 catch (
const std::exception &e)
1090 std::cerr <<
"openvpn: " << e.what() << std::endl;
bool pause_on_connection_timeout() override
void log(ClientAPI_LogInfo loginfo)
void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &event) override
void event(ClientAPI_Event event)
void external_pki_cert_request(ClientAPI_ExternalPKICertRequest req)
bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, bool ipv6) override
void external_pki_sign_request(ClientAPI_ExternalPKISignRequest req)
std::string auth_password
std::vector< ClientAPI::KeyValue > get_peer_info() const
std::unique_ptr< std::thread > thread
void query_username_password(const std::string &type, const bool password_only, const std::string &static_challenge, const bool static_challenge_echo)
AsioTimerSafe bytecount_timer
void process_remote_cmd(const Option &o)
void start_connection_thread()
std::unique_ptr< ClientAPI::Config > config
std::string reconnect_reason
void set_final_error(const std::string &err)
bool omi_command_is_multiline(const std::string &arg0, const Option &o) override
std::string exit_event_name
void query_remote(const std::string &host, const std::string &port, const std::string &proto)
std::string get_final_error()
void process_auth_cmd(const Option &o)
void event_msg(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo *ci)
OMI(openvpn_io::io_context &io_context, OptionList opt_arg)
bool management_query_remote
bool management_external_key
void provide_username_password(const std::string &type, const std::string &username, const std::string &password)
bool management_query_passwords
void log_msg(const ClientAPI::LogInfo &msg)
std::condition_variable epki_cv
bool omi_command_in(const std::string &arg0, const Command &cmd) override
std::unique_ptr< Client > client
void signal(const openvpn_io::error_code &error, int signum)
void log(const ClientAPI::LogInfo &msg) override
bool omi_is_sighup_implemented() override
void omi_sigterm() override
std::string proto_override
void deferred_reconnect(const unsigned int seconds, const std::string &reason)
std::string auth_username
void event(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo &ci)
void omi_start_connection() override
void schedule_bytecount_timer()
std::unique_ptr< ClientAPI::ProvideCreds > creds
void event(const ClientAPI::Event &ev)
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest &signreq)
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest &certreq)
virtual void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &event)
void omi_sighup() override
ClientAPI::ExternalPKISignRequest * epki_signreq
bool is_auth_cmd(const std::string &arg0) const
void omi_done(const bool eof) override
static std::string event_format(const ClientAPI::Event &ev, const ClientAPI::ConnectionInfo *ci)
std::string http_proxy_port
void emit_up_down(const std::string &state)
openvpn_io::windows::object_handle AsioEvent
void epki_sign_reply(const Command &cmd)
std::string http_proxy_host
std::string remote_override
AsioTimerSafe reconnect_timer
static std::string gen_state_msg(const bool prefix, std::string name, std::string info)
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
EvalConfig eval_config(const Config &config)
ConnectionInfo connection_info()
bool is_errors_to_stderr() const
void log_setup(const LogFn &log)
unsigned int get_bytecount() const
void start(const OptionList &opt)
void state_line(const std::string &line)
void log_full(const std::string &text)
static std::string get_config(const OptionList &opt)
openvpn_io::io_context & io_context
void echo_line(const std::string &line)
static OptionList parse_from_argv_static(const std::vector< std::string > &argv)
std::string get_optional(const std::string &name, size_t index, const size_t max_len) const
const IndexMap & map() const
T get_num(const std::string &name, const size_t idx, const T default_value) const
const Option * get_ptr(const std::string &name) const
std::string get_default(const std::string &name, size_t index, const size_t max_len, const std::string &default_value) const
bool exists(const std::string &name) const
std::string get_optional(const size_t index, const size_t max_len) const
void touch(bool lightly=false) const
const std::string & get(const size_t index, const size_t max_len) const
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
static void delete_rules(DWORD process_id)
Remove our NRPT rules from the registry.
#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)
bool starts_with(const STRING &str, const std::string &prefix)
std::string add_trailing_crlf_copy(std::string str)
std::string trim_crlf_copy(std::string str)
std::string to_string(const T &t)
Convert a value to a string.
std::string platform_string()
int main(int argc, char *argv[])
std::string log_version()
Struct containing configuration details parsed from an OpenVPN configuration file.
std::string staticChallenge
std::string windowsDriver
Scoped RAII for the global_log pointer.
std::vector< std::string > extra
static std::stringstream out