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