Register/unregister trusted custom dialer DLL when installing/uninstalling service
PATCH v2 1/1 Register/unregister trusted custom dialer DLL when installing/uninstalling service
Add copyright notice as required where Microsoft has contributed code
Signed-off-by Kevin Kane <[email protected]...>
--- src/openvpnserv/service.c | 241 +++++++++++++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 19 deletions(-)
src/openvpnserv/service.c +222 -19
@@ -6,6 +6,7 @@* * Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. * 2013 Heiko Hund <[email protected]...> +* Portions Copyright (C) 2018 Microsoft Corporation */ #include "service.h"
@@ -53,6 +54,195 @@ ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status)return res; } +static const TCHAR DialerDllName[] =TEXT ("libopenvpndialer-0.dll" ); +static const TCHAR RegValueName[] =TEXT ("CustomDLL" ); + +static int +HandleDialerRegistration (int uninstall) +{ +TCHAR path[512 ], customDllString[1024 ]; +HKEY parametersKey; +LONG result; +DWORD customDllSize =sizeof (customDllString); + +/* Assumption is that the dialer DLL is installed to the same bin directory as everything else. */ +if (GetModuleFileName (NULL , path,sizeof (path)) ==0 ) + { +_tprintf (TEXT ("Unable to get module path - %lu\n" ),GetLastError ()); +return 1 ; + } + +/* The version of NSIS we use to create the installer doesn't yet have support for +* writing multi-string registry entries, which we need to do in order to register our +* custom dialer DLL. Instead, we'll update this registry entry on install/uninstall. +*/ + +TCHAR *lastBackslash =_tcsrchr (path,TEXT ('\\' )); +if (NULL == lastBackslash) + { +_tprintf (TEXT ("Could not locate last backslash in path: %s\n" ), path); +return 1 ; + } + + lastBackslash[1 ] =TEXT ('\0' ); + +/* Bounds checking. */ +if ((_tcslen (path) +_countof (DialerDllName)) >_countof (path)) + { +_tprintf (TEXT ("Out of buffer adding dialer filename to path" )); +return 1 ; + } + +_tcscat (path, DialerDllName); + + result =RegOpenKeyEx (HKEY_LOCAL_MACHINE , +TEXT ("SYSTEM\\CurrentControlSet\\Services\\RasMan\\Parameters" ), +0 , +KEY_ALL_ACCESS , + ¶metersKey); +if (ERROR_SUCCESS != result) + { +_tprintf (TEXT ("Could not open RasMan parameters key: %ld\n" ), result); +return 1 ; + } + +/* Must RegCloseKey(parametersKey) from this point */ + + result =RegGetValue (parametersKey, +NULL , + RegValueName, +RRF_RT_REG_MULTI_SZ , +NULL , + customDllString, + &customDllSize); + +/* If we're installing, the key being absent is okay. Any other error is fatal. */ +if (ERROR_FILE_NOT_FOUND == result) + { +if (0 != uninstall) + { +_tprintf (TEXT ("CustomDLL value was not found; skipping unregistration step\n" )); +RegCloseKey (parametersKey); +return 0 ;/* Not a fatal error but nothing to do */ + } +else + { + result =ERROR_SUCCESS ; + customDllString[0 ] =TEXT ('\0' ); + customDllSize =0 ; + } + } +else if (ERROR_SUCCESS != result) + { +_tprintf (TEXT ("Could not open CustomDLL value: %ld\n" ), result); +RegCloseKey (parametersKey); +return 1 ; + } + +/* Determine if the custom dialer DLL is present in the registry setting. This is a multi-string so we can't +* use _tcsstr. +*/ +TCHAR * p; +for (p = customDllString; *p !=TEXT ('\0' ); p +=_tcslen (p) +1 ) + { +if (0 ==_tcsicmp (path, p)) + { +/* It is. p points to where it begins. */ +break ; + } + } +/* If it's not present, p points at a NULL terminator. */ + +/* If we're installing and the DLL is present in the registry, do nothing. */ +/* If we're uninstalling and the DLL is not present in the registry, do nothing. */ +if ( ((0 == uninstall) && (*p !=TEXT ('\0' ))) || + ((0 != uninstall) && (*p ==TEXT ('\0' ))) ) + { +RegCloseKey (parametersKey); +return 0 ; + } + +/* If we're installing and the DLL is not present in the registry, append it at point p. */ +if ((0 == uninstall) && (*p ==TEXT ('\0' ))) + { +/* Make sure the string buffer has enough space left. p points at the second in the double-terminating null +* (or the sole NULL if the registry entry was empty or absent). +*/ +if (((p - customDllString) +_tcslen (path) +2 ) >_countof (customDllString)) + { +_tprintf (TEXT ("Not enough buffer to create new CustomDLL string\n" )); +RegCloseKey (parametersKey); +return 1 ; + } +_tcscpy (p, path); +/* Add second terminating NULL we overwrote with the copy. */ + p +=_tcslen (p) +1 ; + *p++ =TEXT ('\0' ); + +/* Set in the registry. */ + result =RegSetValueEx (parametersKey, + RegValueName, +0 , +REG_MULTI_SZ , + (const BYTE *)customDllString, + (DWORD )(sizeof (TCHAR ) * (p - customDllString))); + +RegCloseKey (parametersKey); +if (ERROR_SUCCESS != result) + { +_tprintf (TEXT ("Failed to RegSetValueEx: %ld\n" ), result); +return 1 ; + } + } +/* Else if we're uninstalling and the DLL is present, copy everything except strings matching path. */ +else if ((0 != uninstall) && (*p !=TEXT ('\0' ))) + { +TCHAR newCustomDllString[1024 ]; +TCHAR *n, *c; + +/* newCustomDllString is the same size as customDllString, and we're only removing, so no +* way to overflow the buffer. +*/ +for (c = customDllString, n = newCustomDllString; *c !=TEXT ('\0' ); c +=_tcslen (c) +1 ) + { +if (0 !=_tcsicmp (path, c)) + { +_tcscpy (n, c); + n +=_tcslen (n) +1 ; + } + } + +/* Add double-terminating NULL as is required for a multi-string. */ + *n++ =TEXT ('\0' ); + +/* If the new string is nonempty, set in the registry. Otherwise delete the value. */ +if (TEXT ('\0' ) != *newCustomDllString) + { + result =RegSetValueEx (parametersKey, + RegValueName, +0 , +REG_MULTI_SZ , + (const BYTE *)newCustomDllString, + (DWORD )(sizeof (TCHAR ) * (n - newCustomDllString))); + } +else + { + result =RegDeleteValue (parametersKey, RegValueName); + } + +RegCloseKey (parametersKey); +if (ERROR_SUCCESS != result) + { +_tprintf (TEXT ("Failed to %s new registry value: %ld\n" ), + (TEXT ('\0' ) != *newCustomDllString)?TEXT ("set" ):TEXT ("delete" ), + result); +return 1 ; + } + } + +return 0 ; +} +static int CmdInstallServices () {
@@ -77,27 +267,35 @@ CmdInstallServices()return 1 ; } -for (i =0 ; i < _service_max; i++) +if (0 !=HandleDialerRegistration (0 )) { - service =CreateService (svc_ctl_mgr, - openvpn_service[i].name, - openvpn_service[i].display_name, -SERVICE_QUERY_STATUS , -SERVICE_WIN32_SHARE_PROCESS , - openvpn_service[i].start_type, -SERVICE_ERROR_NORMAL , - path,NULL ,NULL , - openvpn_service[i].dependencies, -NULL ,NULL ); -if (service) - { -_tprintf (TEXT ("%s installed.\n" ), openvpn_service[i].display_name); -CloseServiceHandle (service); - --ret; - } -else +_tprintf (TEXT ("HandleDialerRegistration failed\n" )); + ret =1 ; + } +else + { +for (i =0 ; i < _service_max; i++) { -_tprintf (TEXT ("CreateService failed - %s\n" ),GetLastErrorText ()); + service =CreateService (svc_ctl_mgr, + openvpn_service[i].name, + openvpn_service[i].display_name, +SERVICE_QUERY_STATUS , +SERVICE_WIN32_SHARE_PROCESS , + openvpn_service[i].start_type, +SERVICE_ERROR_NORMAL , + path,NULL ,NULL , + openvpn_service[i].dependencies, +NULL ,NULL ); +if (service) + { +_tprintf (TEXT ("%s installed.\n" ), openvpn_service[i].display_name); +CloseServiceHandle (service); + --ret; + } +else + { +_tprintf (TEXT ("CreateService failed - %s\n" ),GetLastErrorText ()); + } } }
@@ -160,6 +358,11 @@ CmdRemoveServices()return 1 ; } +if (0 !=HandleDialerRegistration (1 )) + { +_tprintf (TEXT ("HandleDialerRegistration uninstall failed; ignoring\n" )); + } +for (i =0 ; i < _service_max; i++) {openvpn_service_t *ovpn_svc = &openvpn_service[i];
Signature · 1 line
2.17.1.windows.2