From 477c61ff8314c4506dde48e8b66e4b490e52023b Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Mon, 4 Jul 2022 22:57:40 -0400 Subject: [PATCH] Parse config-auto directory for persistent connections - Parse the config-auto folder used by automatic service and mark these profiles as persistent. - These connections are marked as auto_connect to try attaching to them at start up with periodic retry in case the daemon or service are restarted. Signed-off-by: Selva Nair --- main.c | 35 +++++++++++++++++++++++++++++++++++ openvpn.c | 5 +++++ openvpn_config.c | 31 ++++++++++++++++++++++++------- options.c | 2 ++ options.h | 2 ++ registry.c | 12 ++++++++++++ 6 files changed, 80 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index 8493e7d..bde0385 100644 --- a/main.c +++ b/main.c @@ -505,6 +505,38 @@ HandleCopyDataMessage(const COPYDATASTRUCT *copy_data) return TRUE; /* indicate we handled the message */ } +/* If automatic service is running, check whether we are + * attached to the management i/f of persistent daemons + * and re-attach if necessary. The timer is reset to + * call this routine again after a delay. Periodic check + * is required as we get detached if the daemon gets restarted + * by the service or we do a disconnect. + */ +static void CALLBACK +ManagePersistent(HWND hwnd, UINT UNUSED msg, UINT_PTR id, DWORD UNUSED now) +{ + CheckServiceStatus(false); + if (o.service_state == service_connected) + { + for (int i = 0; i < o.num_configs; i++) + { + if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT + && o.conn[i].auto_connect + && o.conn[i].state == disconnected) + { + /* disable auto-connect to avoid repeated re-connect + * after unrecoverable errors. Re-enabled on successful + * connect. + */ + o.conn[i].auto_connect = false; + StartOpenVPN(&o.conn[i]); /* attach to the management i/f */ + } + } + } + /* schedule to call again after 10 sec */ + SetTimer(hwnd, id, 10000, ManagePersistent); +} + /* This function is called by the Windows function DispatchMessage() */ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -550,6 +582,9 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM SendMessage(hwnd, WM_CLOSE, 0, 0); break; } + /* A timer to periodically tend to persistent connections */ + SetTimer(hwnd, 0, 10000, ManagePersistent); + break; case WM_NOTIFYICONTRAY: diff --git a/openvpn.c b/openvpn.c index c11d542..8410a1c 100644 --- a/openvpn.c +++ b/openvpn.c @@ -124,6 +124,11 @@ OnReady(connection_t *c, UNUSED char *msg) /* ask for the current state, especially useful when the daemon was prestarted */ ManagementCommand(c, "state", OnStateChange, regular); + + if (c->flags & FLAG_DAEMON_PERSISTENT) /* find the current state */ + { + c->auto_connect = true; + } } diff --git a/openvpn_config.c b/openvpn_config.c index 44bab15..1b49404 100644 --- a/openvpn_config.c +++ b/openvpn_config.c @@ -110,6 +110,13 @@ AddConfigFileToList(int config, const TCHAR *filename, const TCHAR *config_dir) if (CheckKeyFileWriteAccess (c)) c->flags |= FLAG_ALLOW_CHANGE_PASSPHRASE; #endif + if (wcsstr(config_dir, o.config_auto_dir)) + { + c->flags |= FLAG_DAEMON_PERSISTENT; + _sntprintf_0(c->log_path, _T("%ls\\%ls.log"), o.global_log_dir, c->config_name); + /* set to auto-connect -- this attempts to attach to them on startup */ + c->auto_connect = true; + } /* Check if connection should be autostarted */ for (i = 0; i < o.num_auto_connect; ++i) @@ -402,7 +409,7 @@ BuildFileList() static bool issue_warnings = true; int recurse_depth = 20; /* maximum number of levels below config_dir to recurse into */ int flags = 0; - int root = 0; + int root0 = 0; int max_configs = (1<<16) - o.mgmt_port_offset; if (o.silent_connection) @@ -418,22 +425,32 @@ BuildFileList() o.num_configs = 0; o.num_groups = 0; flags |= FLAG_ADD_CONFIG_GROUPS; - root = NewConfigGroup(L"ROOT", -1, flags); /* -1 indicates no parent */ + root0 = NewConfigGroup(L"ROOT", -1, flags); /* -1 indicates no parent */ } else - root = 0; + root0 = 0; if (issue_warnings) { flags |= FLAG_WARN_DUPLICATES | FLAG_WARN_MAX_CONFIGS; } - BuildFileList0 (o.config_dir, recurse_depth, root, flags); - - root = NewConfigGroup(L"System Profiles", root, flags); + BuildFileList0 (o.config_dir, recurse_depth, root0, flags); + int root1 = NewConfigGroup(L"System Profiles", root0, flags); if (!IsSamePath(o.global_config_dir, o.config_dir)) - BuildFileList0 (o.global_config_dir, recurse_depth, root, flags); + { + BuildFileList0 (o.global_config_dir, recurse_depth, root1, flags); + } + + if (o.service_state == service_connected) + { + root1 = NewConfigGroup(L"Persistent Profiles", root0, flags); + if (!IsSamePath(o.config_auto_dir, o.config_dir)) + { + BuildFileList0 (o.config_auto_dir, recurse_depth, root1, flags); + } + } if (o.num_configs == 0 && issue_warnings) ShowLocalizedMsg(IDS_NFO_NO_CONFIGS, o.config_dir, o.global_config_dir); diff --git a/options.c b/options.c index 52cd72d..a1225d6 100644 --- a/options.c +++ b/options.c @@ -75,6 +75,8 @@ ExpandOptions (void) { ExpandString (o.exe_path, _countof(o.exe_path)); ExpandString (o.config_dir, _countof(o.config_dir)); + ExpandString (o.global_config_dir, _countof(o.global_config_dir)); + ExpandString (o.config_auto_dir, _countof(o.config_auto_dir)); ExpandString (o.log_dir, _countof(o.log_dir)); ExpandString (o.editor, _countof(o.editor)); ExpandString (o.log_viewer, _countof(o.log_viewer)); diff --git a/options.h b/options.h index 5ac25c7..6d2da0e 100644 --- a/options.h +++ b/options.h @@ -193,6 +193,8 @@ typedef struct { TCHAR exe_path[MAX_PATH]; TCHAR install_path[MAX_PATH]; TCHAR global_config_dir[MAX_PATH]; + TCHAR config_auto_dir[MAX_PATH]; + TCHAR global_log_dir[MAX_PATH]; TCHAR priority_string[64]; TCHAR ovpn_admin_group[MAX_NAME]; DWORD disable_save_passwords; diff --git a/registry.c b/registry.c index 12a6d7f..836e4b3 100644 --- a/registry.c +++ b/registry.c @@ -118,6 +118,18 @@ GetGlobalRegistryKeys() _sntprintf_0(o.global_config_dir, _T("%lsconfig"), o.install_path); } + if (!regkey || !GetRegistryValue(regkey, _T("autostart_config_dir"), o.config_auto_dir, _countof(o.config_auto_dir))) + { + /* use default = openvpnpath\config-auto */ + _sntprintf_0(o.config_auto_dir, L"%lsconfig-auto", o.install_path); + } + + if (!regkey || !GetRegistryValue(regkey, _T("log_dir"), o.global_log_dir, _countof(o.global_log_dir))) + { + /* use default = openvpnpath\log */ + _sntprintf_0(o.global_log_dir, L"%lslog", o.install_path); + } + if (!regkey || !GetRegistryValue(regkey, _T("ovpn_admin_group"), o.ovpn_admin_group, _countof(o.ovpn_admin_group))) { _tcsncpy(o.ovpn_admin_group, OVPN_ADMIN_GROUP, _countof(o.ovpn_admin_group)-1);