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