From 147bc1a10680c855ea670e2c2db94c909b1aed88 Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Tue, 5 Jul 2022 01:48:49 -0400 Subject: [PATCH] Parse the config file for management i/f params - Parse the management interface address and password from the config file - Hide the status Window by default for persistent connections --- their startup is automated and may distract the user otherwise. The user can use the menu to review status when required. - Seed srand() using threadId instead of time. Although we use rand() only for cosmetics, the latter is almost never unique among threads when multiple connections can get started in a succession with this patch set. Signed-off-by: Selva Nair --- misc.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ misc.h | 11 +++++++ openvpn.c | 16 ++-------- 3 files changed, 101 insertions(+), 14 deletions(-) diff --git a/misc.c b/misc.c index 154ae75..0d4d48f 100644 --- a/misc.c +++ b/misc.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "localization.h" #include "options.h" @@ -40,6 +42,7 @@ #include "openvpn_config.h" #include "openvpn-gui-res.h" #include "tray.h" +#include "config_parser.h" /* * Helper function to do base64 conversion through CryptoAPI @@ -824,3 +827,88 @@ out: WSACleanup(); return ret; } + +/* Parse the management address and password + * from a config file. Results are returned + * in c->manage.skaddr and c->magage.password. + * Returns false on parse error, or if address + * not found. Password not found is not an error. + */ +BOOL +ParseManagementAddress(connection_t *c) +{ + BOOL ret = true; + wchar_t *pw_file = NULL; + wchar_t *workdir = c->config_dir; + wchar_t config_path[MAX_PATH]; + wchar_t pw_path[MAX_PATH] = L""; + + _sntprintf_0(config_path, L"%ls\\%ls", c->config_dir, c->config_file); + + config_entry_t *head = config_parse(config_path); + config_entry_t *l = head; + + if (!head) + { + return false; + } + + SOCKADDR_IN *addr = &c->manage.skaddr; + addr->sin_port = 0; + + while (l) + { + if (l->ntokens >= 3 && !wcscmp(l->tokens[0], L"management")) + { + /* we require the address to be a numerical ipv4 address -- e.g., 127.0.0.1*/ + if (InetPtonW(AF_INET, l->tokens[1], &addr->sin_addr) != 1) + { + config_list_free(head); + return false; + } + + addr->sin_port = htons(_wtoi(l->tokens[2])); + pw_file = l->tokens[3]; /* may be null */ + } + else if (l->ntokens >= 2 && !wcscmp(l->tokens[0], L"cd")) + { + workdir = l->tokens[1]; + } + l = l->next; + } + + ret = (addr->sin_port != 0); + + if (ret && pw_file) + { + if (PathIsRelativeW(pw_file)) + { + _sntprintf_0(pw_path, L"%ls\\%ls", workdir, pw_file); + } + else + { + wcsncpy_s(pw_path, MAX_PATH, pw_file, _TRUNCATE); + } + + FILE *fp = _wfopen(pw_path, L"r"); + if (!fp + || !fgets(c->manage.password, sizeof(c->manage.password), fp)) + { + /* This may be normal as not all users may be given access to this secret */ + ret = false; + } + + StrTrimA(c->manage.password, "\n\r"); + + if (fp) + { + fclose(fp); + } + } + config_list_free(head); + + PrintDebug(L"ParseManagementAddress: host = %hs port = %d passwd_file = %s", + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port), pw_path); + + return ret; +} diff --git a/misc.h b/misc.h index 5039ce3..0af3114 100644 --- a/misc.h +++ b/misc.h @@ -98,4 +98,15 @@ char *escape_string(const char *str); */ BOOL find_free_tcp_port(SOCKADDR_IN *addr); +/** + * Parse the config file of a connection profile for + * Managegment address and password. + * @param c : Pointer to connection profile + * On return c->manage.skaddr and c->manage.password + * are populated. + * @returns true on success false on error. + * Password not specified in the config file is not an error. + */ +BOOL ParseManagementAddress(connection_t *c); + #endif diff --git a/openvpn.c b/openvpn.c index 8410a1c..bab809d 100644 --- a/openvpn.c +++ b/openvpn.c @@ -1778,18 +1778,6 @@ OnNeedStr (connection_t *c, UNUSED char *msg) WriteStatusLog (c, L"GUI> ", L"Error: Received NEED-STR message -- not implemented", false); } -/* Parse the management port and password of a - * a running daemon -- useful when the daemon is externally - * started (persistent) and we need to use the cached - * management interface address parameters to connect to it. - */ -static BOOL -ParseManagementAddress(connection_t *c) -{ - /* Not implemented */ - return false; -} - /* Stop the connection -- this sets the daemon to exit if * started by us, else instructs the daemon to disconnect and * and wait. @@ -2076,7 +2064,7 @@ ThreadOpenVPNStatus(void *p) HANDLE wait_event; CLEAR (msg); - srand(time(NULL)); + srand(c->threadId); /* Cut of extention from config filename. */ _tcsncpy(conn_name, c->config_file, _countof(conn_name)); @@ -2118,7 +2106,7 @@ ThreadOpenVPNStatus(void *p) wait_event = c->hProcess; } - if (o.silent_connection == 0) + if (o.silent_connection == 0 && (c->flags & FLAG_DAEMON_PERSISTENT) == 0) ShowWindow(c->hwndStatus, SW_SHOW); /* Load echo msg histroy from registry */