mirror of https://github.com/OpenVPN/openvpn-gui
Handle interactive service policy restrictions
When a connection is attempted using a config in a location that would fail, offer an option to add the user to the "OpenVPN Administrators" group. This is done using shell-execute which will show a UAC prompt for elevation. If it fails (due to user chooses NO or the UAC dialog fails) the connection is not started. v2 Changes - Rebase to master - Automaticlaly add the admin group if it doesn't exist - Allow unicode strings in debug output - Use domain\username to identify user - Fix the PrintDebug macro Minor changes based on user feedback - Bring the window back to foreground after UAC prompt completion - Show a message if another connection is tried during authorization - Do not add user to ovpn_admin_group if it is same as the built-in admin group Signed-off-by: Selva Nair <selva.nair@gmail.com>pull/26/head
parent
f1ce93e5d5
commit
43d0ef3a5a
|
@ -88,6 +88,7 @@ openvpn_gui_SOURCES = \
|
|||
misc.c misc.h \
|
||||
openvpn_config.c \
|
||||
openvpn_config.h \
|
||||
access.c access.h \
|
||||
chartable.h \
|
||||
openvpn-gui-res.h
|
||||
|
||||
|
@ -99,7 +100,9 @@ openvpn_gui_LDADD = \
|
|||
-lcomctl32 \
|
||||
-lwinhttp \
|
||||
-lwtsapi32 \
|
||||
-lcrypt32
|
||||
-lcrypt32 \
|
||||
-lnetapi32 \
|
||||
-lsecur32
|
||||
|
||||
openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h
|
||||
$(RCCOMPILE) -i $< -o $@
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN.
|
||||
*
|
||||
* Copyright (C) 2016 Selva Nair <selva.nair@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef SECURITY_WIN32
|
||||
#define SECURITY_WIN32
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <lm.h>
|
||||
#include <stdlib.h>
|
||||
#include <security.h>
|
||||
#include "main.h"
|
||||
#include "options.h"
|
||||
#include "service.h"
|
||||
#include "localization.h"
|
||||
#include "openvpn-gui-res.h"
|
||||
|
||||
extern options_t o;
|
||||
|
||||
#define MAX_UNAME_LEN (UNLEN + DNLEN + 2) /* UNLEN, DNLEN from lmcons.h +2 for '\' and NULL */
|
||||
|
||||
/*
|
||||
* Check whether current user is a member of specified groups
|
||||
*/
|
||||
static BOOL
|
||||
CheckGroupMember(DWORD count, WCHAR *grp[])
|
||||
{
|
||||
LOCALGROUP_USERS_INFO_0 *groups = NULL;
|
||||
DWORD nread, nmax, err;
|
||||
WCHAR username[MAX_UNAME_LEN];
|
||||
DWORD size;
|
||||
DWORD i, j;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
size = _countof (username);
|
||||
/* get username in domain\user format */
|
||||
if (!GetUserNameExW (NameSamCompatible, username, &size))
|
||||
return FALSE;
|
||||
#ifdef DEBUG
|
||||
PrintDebug(L"Username: \"%s\"", username);
|
||||
#endif
|
||||
|
||||
/* Get an array of groups the user is member of */
|
||||
err = NetUserGetLocalGroups (NULL, username, 0, LG_INCLUDE_INDIRECT,
|
||||
(LPBYTE *) &groups, MAX_PREFERRED_LENGTH, &nread, &nmax);
|
||||
if (err && err != ERROR_MORE_DATA)
|
||||
goto out;
|
||||
|
||||
/* Check if user's groups include any of the admin groups */
|
||||
for (i = 0; i < nread; i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PrintDebug(L"user in group %d: %s", i, groups[i].lgrui0_name);
|
||||
#endif
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
if (wcscmp (groups[i].lgrui0_name, grp[j]) == 0)
|
||||
{
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
PrintDebug(L"User is %s in an authorized gtoup", ret? L"" : L"not");
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (groups)
|
||||
NetApiBufferFree (groups);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run a command as admin using shell execute and return the exit code.
|
||||
* If the command fails to execute, the return value is (DWORD) -1.
|
||||
*/
|
||||
static DWORD
|
||||
RunAsAdmin(const WCHAR *cmd, const WCHAR *params)
|
||||
{
|
||||
SHELLEXECUTEINFO shinfo;
|
||||
DWORD status = -1;
|
||||
|
||||
CLEAR (shinfo);
|
||||
shinfo.cbSize = sizeof(shinfo);
|
||||
shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
shinfo.hwnd = NULL;
|
||||
shinfo.lpVerb = L"runas";
|
||||
shinfo.lpFile = cmd;
|
||||
shinfo.lpDirectory = NULL;
|
||||
shinfo.nShow = SW_HIDE;
|
||||
shinfo.lpParameters = params;
|
||||
|
||||
if (ShellExecuteEx(&shinfo) && shinfo.hProcess)
|
||||
{
|
||||
WaitForSingleObject(shinfo.hProcess, INFINITE);
|
||||
GetExitCodeProcess(shinfo.hProcess, &status);
|
||||
CloseHandle(shinfo.hProcess);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Administrators group may be localized or renamed by admins.
|
||||
* Get the local name of the group using the SID.
|
||||
*/
|
||||
static BOOL
|
||||
GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen)
|
||||
{
|
||||
BOOL b = FALSE;
|
||||
PSID admin_sid = NULL;
|
||||
DWORD sid_size = SECURITY_MAX_SID_SIZE;
|
||||
SID_NAME_USE su;
|
||||
|
||||
WCHAR domain[MAX_NAME];
|
||||
DWORD dlen = _countof(domain);
|
||||
|
||||
admin_sid = malloc(sid_size);
|
||||
if (!admin_sid)
|
||||
return FALSE;
|
||||
|
||||
b = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid,
|
||||
&sid_size);
|
||||
if(b)
|
||||
{
|
||||
b = LookupAccountSidW(NULL, admin_sid, name, &nlen, domain, &dlen, &su);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
PrintDebug (L"builtin admin group name = %s", name);
|
||||
#endif
|
||||
|
||||
free (admin_sid);
|
||||
|
||||
return b;
|
||||
}
|
||||
/*
|
||||
* Add current user to the specified group. Uses RunAsAdmin to elevate.
|
||||
*/
|
||||
static BOOL
|
||||
AddUserToGroup (const WCHAR *group)
|
||||
{
|
||||
WCHAR username[MAX_UNAME_LEN];
|
||||
WCHAR cmd[MAX_PATH] = L"C:\\windows\\system32\\cmd.exe";
|
||||
WCHAR netcmd[MAX_PATH] = L"C:\\windows\\system32\\net.exe";
|
||||
WCHAR syspath[MAX_PATH];
|
||||
WCHAR *params = NULL;
|
||||
|
||||
/* command: cmd.exe, params: /c net.exe group /add & net.exe group user /add */
|
||||
const WCHAR *fmt = L"/c %s localgroup \"%s\" /add & %s localgroup \"%s\" \"%s\" /add";
|
||||
DWORD size;
|
||||
DWORD status;
|
||||
BOOL retval = FALSE;
|
||||
|
||||
size = _countof(username);
|
||||
if (!GetUserNameExW (NameSamCompatible, username, &size))
|
||||
return retval;
|
||||
|
||||
size = _countof(syspath);
|
||||
if (GetSystemDirectory (syspath, size))
|
||||
{
|
||||
syspath[size-1] = L'\0';
|
||||
size = _countof(cmd);
|
||||
_snwprintf(cmd, size, L"%s\\%s", syspath, L"cmd.exe");
|
||||
cmd[size-1] = L'\0';
|
||||
size = _countof(netcmd);
|
||||
_snwprintf(netcmd, size, L"%s\\%s", syspath, L"net.exe");
|
||||
netcmd[size-1] = L'\0';
|
||||
}
|
||||
size = (wcslen(fmt) + wcslen(username) + 2*wcslen(group) + 2*wcslen(netcmd)+ 1);
|
||||
if ((params = malloc (size*sizeof(WCHAR))) == NULL)
|
||||
return retval;
|
||||
|
||||
_snwprintf(params, size, fmt, netcmd, group, netcmd, group, username);
|
||||
params[size-1] = L'\0';
|
||||
|
||||
status = RunAsAdmin (cmd, params);
|
||||
if (status == 0)
|
||||
retval = TRUE;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (status == (DWORD) -1)
|
||||
PrintDebug(L"RunAsAdmin: failed to execute the command [%s %s] : error = 0x%x",
|
||||
cmd, params, GetLastError());
|
||||
else if (status)
|
||||
PrintDebug(L"RunAsAdmin: command [%s %s] returned exit_code = %lu",
|
||||
cmd, params, status);
|
||||
#endif
|
||||
|
||||
free (params);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the config location is authorized for startup through
|
||||
* interactive service. Either the user be a member of the specified groups,
|
||||
* or the config_dir be inside the global_config_dir
|
||||
*/
|
||||
static BOOL
|
||||
CheckConfigPath (const WCHAR *config_dir, DWORD ngrp, WCHAR *admin_group[])
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
int size = wcslen(o.global_config_dir);
|
||||
|
||||
/* if interactive service is not running, no access control: return TRUE */
|
||||
if (!CheckIServiceStatus(FALSE))
|
||||
ret = TRUE;
|
||||
|
||||
/* if config is from the global location allow it */
|
||||
else if ( wcsncmp(config_dir, o.global_config_dir, size) == 0 &&
|
||||
wcsstr(config_dir + size, L"..") == NULL
|
||||
)
|
||||
ret = TRUE;
|
||||
|
||||
/* check user is in an authorized group */
|
||||
else
|
||||
{
|
||||
if (CheckGroupMember(ngrp, admin_group))
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If config_dir for a connection is not in an authorized location,
|
||||
* show a dialog to add the user to the ovpn_admin_group.
|
||||
*/
|
||||
BOOL
|
||||
AuthorizeConfig(const connection_t *c)
|
||||
{
|
||||
DWORD res;
|
||||
BOOL retval = FALSE;
|
||||
WCHAR *admin_group[2];
|
||||
WCHAR sysadmin_group[MAX_NAME];
|
||||
|
||||
if (GetBuiltinAdminGroupName(sysadmin_group, _countof(sysadmin_group)))
|
||||
admin_group[0] = sysadmin_group;
|
||||
else
|
||||
admin_group[0] = L"Administrators";
|
||||
|
||||
/* assuming TCHAR == WCHAR as we do not support non-unicode build */
|
||||
admin_group[1] = o.ovpn_admin_group;
|
||||
|
||||
#ifdef DEBUG
|
||||
PrintDebug (L"admin groups: %s, %s", admin_group[0], admin_group[1]);
|
||||
#endif
|
||||
|
||||
if (CheckConfigPath(c->config_dir, 2, admin_group))
|
||||
return TRUE;
|
||||
/* do not attempt to add user to sysadmin_group or a no-name group */
|
||||
else if ( wcscmp(sysadmin_group, o.ovpn_admin_group) == 0 ||
|
||||
wcslen(o.ovpn_admin_group) == 0 ||
|
||||
!o.netcmd_semaphore )
|
||||
{
|
||||
ShowLocalizedMsg(IDS_ERR_CONFIG_NOT_AUTHORIZED, c->config_name, sysadmin_group);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject (o.netcmd_semaphore, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
/* Could not lock semaphore -- auth dialog already running? */
|
||||
ShowLocalizedMsg(IDS_NFO_CONFIG_AUTH_PENDING, c->config_name, admin_group[1]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* semaphore locked -- relase before return */
|
||||
|
||||
res = ShowLocalizedMsgEx(MB_YESNO|MB_ICONWARNING, TEXT(PACKAGE_NAME),
|
||||
IDS_ERR_CONFIG_TRY_AUTHORIZE, c->config_name,
|
||||
o.ovpn_admin_group);
|
||||
if (res == IDYES)
|
||||
{
|
||||
AddUserToGroup (o.ovpn_admin_group);
|
||||
/*
|
||||
* Check the success of above by testing the config path again.
|
||||
*/
|
||||
if (CheckConfigPath(c->config_dir, 2, admin_group))
|
||||
retval = TRUE;
|
||||
else
|
||||
ShowLocalizedMsg(IDS_ERR_ADD_USER_TO_ADMIN_GROUP, o.ovpn_admin_group);
|
||||
SetForegroundWindow (o.hWnd);
|
||||
}
|
||||
ReleaseSemaphore (o.netcmd_semaphore, 1, NULL);
|
||||
|
||||
return retval;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* This file is a part of OpenVPN-GUI -- A Windows GUI for OpenVPN.
|
||||
*
|
||||
* Copyright (C) 2016 Selva Nair <selva.nair@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef ACCESS_H
|
||||
#define ACCESS_H
|
||||
|
||||
#include "options.h"
|
||||
|
||||
BOOL AuthorizeConfig (const connection_t *c);
|
||||
|
||||
#endif
|
8
main.c
8
main.c
|
@ -23,6 +23,10 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if !defined (UNICODE)
|
||||
#error UNICODE and _UNICODE must be defined. This version only supports unicode builds.
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <wtsapi32.h>
|
||||
|
@ -120,7 +124,7 @@ int WINAPI _tWinMain (HINSTANCE hThisInstance,
|
|||
|
||||
#ifdef DEBUG
|
||||
/* Open debug file for output */
|
||||
if (!(o.debug_fp = fopen(DEBUG_FILE, "w")))
|
||||
if (!(o.debug_fp = _wfopen(DEBUG_FILE, L"a+,ccs=UTF-8")))
|
||||
{
|
||||
/* can't open debug file */
|
||||
ShowLocalizedMsg(IDS_ERR_OPEN_DEBUG_FILE, DEBUG_FILE);
|
||||
|
@ -183,7 +187,7 @@ int WINAPI _tWinMain (HINSTANCE hThisInstance,
|
|||
}
|
||||
|
||||
if (!IsUserAdmin())
|
||||
CheckIServiceStatus();
|
||||
CheckIServiceStatus(TRUE);
|
||||
|
||||
BuildFileList();
|
||||
if (!VerifyAutoConnections()) {
|
||||
|
|
9
main.h
9
main.h
|
@ -29,7 +29,7 @@
|
|||
|
||||
/* Define this to enable DEBUG build */
|
||||
//#define DEBUG
|
||||
#define DEBUG_FILE "c:\\openvpngui_debug.txt"
|
||||
#define DEBUG_FILE L"C:\\windows\\temp\\openvpngui_debug.txt"
|
||||
|
||||
/* Define this to disable Change Password support */
|
||||
//#define DISABLE_CHANGE_PASSWORD
|
||||
|
@ -44,7 +44,8 @@
|
|||
#define MAX_LOG_LINES 500 /* Max number of lines in LogWindow */
|
||||
#define DEL_LOG_LINES 10 /* Number of lines to delete from LogWindow */
|
||||
|
||||
|
||||
/* Authorized group who can use any options and config locations */
|
||||
#define OVPN_ADMIN_GROUP TEXT("OpenVPN Administrators") /* May be reset in registry */
|
||||
|
||||
/* bool definitions */
|
||||
#define bool int
|
||||
|
@ -103,11 +104,11 @@ __snprintf_0(char *buf, size_t size, char *format, ...)
|
|||
#ifdef DEBUG
|
||||
/* Print Debug Message */
|
||||
#define PrintDebug(...) \
|
||||
{ \
|
||||
do { \
|
||||
TCHAR x_msg[256]; \
|
||||
_sntprintf_0(x_msg, __VA_ARGS__); \
|
||||
PrintDebugMsg(x_msg); \
|
||||
}
|
||||
} while(0)
|
||||
|
||||
void PrintDebugMsg(TCHAR *msg);
|
||||
#endif
|
||||
|
|
16
misc.c
16
misc.c
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "options.h"
|
||||
#include "manage.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
|
@ -322,3 +323,18 @@ BOOL IsUserAdmin(VOID)
|
|||
|
||||
return(b);
|
||||
}
|
||||
|
||||
HANDLE
|
||||
InitSemaphore (void)
|
||||
{
|
||||
HANDLE semaphore = NULL;
|
||||
semaphore = CreateSemaphore (NULL, 1, 1, NULL);
|
||||
if (!semaphore)
|
||||
{
|
||||
MessageBoxW (NULL, L"PACKAGE_NAME", L"Error creating semaphore", MB_OK);
|
||||
#ifdef DEBUG
|
||||
PrintDebug (L"InitSemaphore: CreateSemaphore failed [error = %lu]", GetLastError());
|
||||
#endif
|
||||
}
|
||||
return semaphore;
|
||||
}
|
||||
|
|
|
@ -164,6 +164,10 @@
|
|||
#define IDS_ERR_CONFIG_EXIST 1251
|
||||
#define IDS_NFO_CONN_TIMEOUT 1252
|
||||
#define IDS_NFO_NO_CONFIGS 1253
|
||||
#define IDS_ERR_CONFIG_NOT_AUTHORIZED 1254
|
||||
#define IDS_ERR_CONFIG_TRY_AUTHORIZE 1255
|
||||
#define IDS_NFO_CONFIG_AUTH_PENDING 1256
|
||||
#define IDS_ERR_ADD_USER_TO_ADMIN_GROUP 1257
|
||||
|
||||
/* Program Startup Related */
|
||||
#define IDS_ERR_OPEN_DEBUG_FILE 1301
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "passphrase.h"
|
||||
#include "localization.h"
|
||||
#include "misc.h"
|
||||
#include "access.h"
|
||||
|
||||
#define WM_OVPN_STOP (WM_APP + 10)
|
||||
#define WM_OVPN_SUSPEND (WM_APP + 11)
|
||||
|
@ -747,6 +748,13 @@ StartOpenVPN(connection_t *c)
|
|||
DWORD size = _tcslen(c->config_dir) + _tcslen(options) + sizeof(c->manage.password) + 3;
|
||||
TCHAR startup_info[1024];
|
||||
DWORD dwMode = PIPE_READMODE_MESSAGE;
|
||||
|
||||
if ( !AuthorizeConfig(c))
|
||||
{
|
||||
CloseHandle(c->exit_event);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!SetNamedPipeHandleState(service, &dwMode, NULL, NULL))
|
||||
{
|
||||
ShowLocalizedMsg (IDS_ERR_ACCESS_SERVICE_PIPE);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "main.h"
|
||||
#include "openvpn-gui-res.h"
|
||||
#include "localization.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define streq(x, y) (_tcscmp((x), (y)) == 0)
|
||||
|
||||
|
@ -210,6 +211,7 @@ void
|
|||
InitOptions(options_t *opt)
|
||||
{
|
||||
CLEAR(*opt);
|
||||
opt->netcmd_semaphore = InitSemaphore ();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,9 +29,12 @@ typedef struct connection connection_t;
|
|||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <lmcons.h>
|
||||
|
||||
#include "manage.h"
|
||||
|
||||
#define MAX_NAME (UNLEN + 1)
|
||||
|
||||
/*
|
||||
* Maximum number of parameters associated with an option,
|
||||
* including the option name itself.
|
||||
|
@ -145,6 +148,7 @@ typedef struct {
|
|||
TCHAR connectscript_timeout_string[4];
|
||||
TCHAR disconnectscript_timeout_string[4];
|
||||
TCHAR preconnectscript_timeout_string[4];
|
||||
TCHAR ovpn_admin_group[MAX_NAME];
|
||||
|
||||
#ifdef DEBUG
|
||||
FILE *debug_fp;
|
||||
|
@ -153,6 +157,7 @@ typedef struct {
|
|||
HWND hWnd;
|
||||
HINSTANCE hInstance;
|
||||
BOOL session_locked;
|
||||
HANDLE netcmd_semaphore;
|
||||
} options_t;
|
||||
|
||||
void InitOptions(options_t *);
|
||||
|
|
|
@ -68,6 +68,7 @@ GetRegistryKeys()
|
|||
{
|
||||
/* error reading registry value */
|
||||
ShowLocalizedMsg(IDS_ERR_READING_REGISTRY);
|
||||
RegCloseKey(regkey);
|
||||
return(false);
|
||||
}
|
||||
if (openvpn_path[_tcslen(openvpn_path) - 1] != _T('\\'))
|
||||
|
@ -79,6 +80,11 @@ GetRegistryKeys()
|
|||
/* use default = openvpnpath\config */
|
||||
_sntprintf_0(o.global_config_dir, _T("%sconfig"), openvpn_path);
|
||||
}
|
||||
if (!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));
|
||||
}
|
||||
RegCloseKey(regkey);
|
||||
|
||||
/* config_dir in user's profile by default */
|
||||
_sntprintf_0(temp_path, _T("%s\\OpenVPN\\config"), profile_dir);
|
||||
|
|
|
@ -202,6 +202,16 @@ BEGIN
|
|||
/* OpenVPN */
|
||||
IDS_ERR_MANY_CONFIGS "OpenVPN GUI does not support more than %d configs. Please contact the author if you have the need for more."
|
||||
IDS_NFO_NO_CONFIGS "No readable connection profiles (config files) found"
|
||||
IDS_ERR_CONFIG_NOT_AUTHORIZED "Starting this connection (%s) requires membership in\n"\
|
||||
"""%s"" group. Contact your system administrator.\n"
|
||||
IDS_ERR_CONFIG_TRY_AUTHORIZE "Starting this connection (%s) requires membership in\n"\
|
||||
"""%s"" group.\n\n"\
|
||||
"Do you want to add yourself to this group?\n"\
|
||||
"This action may prompt for administrtaive password or consent."
|
||||
IDS_NFO_CONFIG_AUTH_PENDING "Starting this connection (%s) requires membership in\n"\
|
||||
"""%s"" group.\n\n"\
|
||||
"Please complete the previous authorization dialog."
|
||||
IDS_ERR_ADD_USER_TO_ADMIN_GROUP "Adding the user to ""%s"" group failed."
|
||||
IDS_ERR_ONE_CONN_OLD_VER "You can only have one connection running at the same time when using an older version on OpenVPN than 2.0-beta6."
|
||||
IDS_ERR_STOP_SERV_OLD_VER "You cannot use OpenVPN GUI to start a connection while the OpenVPN Service is running (with OpenVPN 1.5/1.6). Stop OpenVPN Service first if you want to use OpenVPN GUI."
|
||||
IDS_ERR_CREATE_EVENT "CreateEvent failed on exit event: %s"
|
||||
|
|
|
@ -242,7 +242,7 @@ int MyReStartService()
|
|||
}
|
||||
|
||||
bool
|
||||
CheckIServiceStatus()
|
||||
CheckIServiceStatus(BOOL warn)
|
||||
{
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
|
@ -260,7 +260,8 @@ CheckIServiceStatus()
|
|||
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
|
||||
{
|
||||
/* warn that iservice is not installed */
|
||||
ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE);
|
||||
if (warn)
|
||||
ShowLocalizedMsg(IDS_ERR_INSTALL_ISERVICE);
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
@ -270,7 +271,8 @@ CheckIServiceStatus()
|
|||
if (ssStatus.dwCurrentState != SERVICE_RUNNING)
|
||||
{
|
||||
/* warn that iservice is not started */
|
||||
ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE);
|
||||
if (warn)
|
||||
ShowLocalizedMsg(IDS_ERR_NOTSTARTED_ISERVICE);
|
||||
return(false);
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue