From: Kevin Kane Date: Wed, 25 Jul 2018 17:01:38 +0000 Message-ID: Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_BL0PR2101MB10582678FD3D21C0355098E1AB540BL0PR2101MB1058_" MIME-Version: 1.0 Subject: [Openvpn-devel] [PATCH] [openvpn] Register/unregister trusted custom dialer DLL when installing/uninstalling service List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: openvpn-devel --_000_BL0PR2101MB10582678FD3D21C0355098E1AB540BL0PR2101MB1058_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable From 58cc8b37f567da867e3a6e2efa4c15de36495a79 Mon Sep 17 00:00:00 2001 From: Kevin Kane Date: Fri, 13 Jul 2018 09:44:00 -0700 Subject: 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 --- src/openvpnserv/service.c | 241 +++++++++++++++++++++++++++++++++++--- 1 file changed, 222 insertions(+), 19 deletions(-) diff --git a/src/openvpnserv/service.c b/src/openvpnserv/service.c index 7157bea2..edb21b0d 100644 --- a/src/openvpnserv/service.c +++ b/src/openvpnserv/service.c @@ -6,6 +6,7 @@ * * Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved. * 2013 Heiko Hund + * Portions Copyright (C) 2018 Microsoft Corporation */ #include "service.h" @@ -53,6 +54,195 @@ ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERV= ICE_STATUS *status) return res; } +static const TCHAR DialerDllName[] =3D TEXT("libopenvpndialer-0.dll"); +static const TCHAR RegValueName[] =3D TEXT("CustomDLL"); + +static int +HandleDialerRegistration(int uninstall) +{ + TCHAR path[512], customDllString[1024]; + HKEY parametersKey; + LONG result; + DWORD customDllSize =3D sizeof(customDllString); + + /* Assumption is that the dialer DLL is installed to the same bin dire= ctory as everything else. */ + if (GetModuleFileName(NULL, path, sizeof(path)) =3D=3D 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 ins= tall/uninstall. + */ + + TCHAR *lastBackslash =3D _tcsrchr(path, TEXT('\\')); + if (NULL =3D=3D lastBackslash) + { + _tprintf(TEXT("Could not locate last backslash in path: %s\n"), pa= th); + return 1; + } + + lastBackslash[1] =3D 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 =3D RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\CurrentControlSet\\Services\\RasMan\\Parameters"), + 0, + KEY_ALL_ACCESS, + ¶metersKey); + if (ERROR_SUCCESS !=3D result) + { + _tprintf(TEXT("Could not open RasMan parameters key: %ld\n"), resu= lt); + return 1; + } + + /* Must RegCloseKey(parametersKey) from this point */ + + result =3D 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 =3D=3D result) + { + if (0 !=3D uninstall) + { + _tprintf(TEXT("CustomDLL value was not found; skipping unregis= tration step\n")); + RegCloseKey(parametersKey); + return 0; /* Not a fatal error but nothing to do */ + } + else + { + result =3D ERROR_SUCCESS; + customDllString[0] =3D TEXT('\0'); + customDllSize =3D 0; + } + } + else if (ERROR_SUCCESS !=3D 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 setti= ng. This is a multi-string so we can't + * use _tcsstr. + */ + TCHAR* p; + for (p =3D customDllString; *p !=3D TEXT('\0'); p +=3D _tcslen(p) + 1) + { + if (0 =3D=3D _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 noth= ing. */ + /* If we're uninstalling and the DLL is not present in the registry, d= o nothing. */ + if ( ((0 =3D=3D uninstall) && (*p !=3D TEXT('\0'))) || + ((0 !=3D uninstall) && (*p =3D=3D TEXT('\0'))) ) + { + RegCloseKey(parametersKey); + return 0; + } + + /* If we're installing and the DLL is not present in the registry, app= end it at point p. */ + if ((0 =3D=3D uninstall) && (*p =3D=3D 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(customD= llString)) + { + _tprintf(TEXT("Not enough buffer to create new CustomDLL strin= g\n")); + RegCloseKey(parametersKey); + return 1; + } + _tcscpy(p, path); + /* Add second terminating NULL we overwrote with the copy. */ + p +=3D _tcslen(p) + 1; + *p++ =3D TEXT('\0'); + + /* Set in the registry. */ + result =3D RegSetValueEx(parametersKey, + RegValueName, + 0, + REG_MULTI_SZ, + (const BYTE*)customDllString, + (DWORD)(sizeof(TCHAR) * (p - customDllString))); + + RegCloseKey(parametersKey); + if (ERROR_SUCCESS !=3D 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 !=3D uninstall) && (*p !=3D 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 =3D customDllString, n =3D newCustomDllString; *c !=3D TEXT= ('\0'); c +=3D _tcslen(c) + 1) + { + if (0 !=3D _tcsicmp(path, c)) + { + _tcscpy(n, c); + n +=3D _tcslen(n) + 1; + } + } + + /* Add double-terminating NULL as is required for a multi-string. = */ + *n++ =3D TEXT('\0'); + + /* If the new string is nonempty, set in the registry. Otherwise d= elete the value. */ + if (TEXT('\0') !=3D *newCustomDllString) + { + result =3D RegSetValueEx(parametersKey, + RegValueName, + 0, + REG_MULTI_SZ, + (const BYTE*)newCustomDllString, + (DWORD)(sizeof(TCHAR) * (n - newCustomDllString))); + } + else + { + result =3D RegDeleteValue(parametersKey, RegValueName); + } + + RegCloseKey(parametersKey); + if (ERROR_SUCCESS !=3D result) + { + _tprintf(TEXT("Failed to %s new registry value: %ld\n"), + (TEXT('\0') !=3D *newCustomDllString)?TEXT("set"):TEXT("de= lete"), + result); + return 1; + } + } + + return 0; +} + static int CmdInstallServices() { @@ -77,27 +267,35 @@ CmdInstallServices() return 1; } - for (i =3D 0; i < _service_max; i++) + if (0 !=3D HandleDialerRegistration(0)) { - service =3D 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_n= ame); - CloseServiceHandle(service); - --ret; - } - else + _tprintf(TEXT("HandleDialerRegistration failed\n")); + ret =3D 1; + } + else + { + for (i =3D 0; i < _service_max; i++) { - _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText= ()); + service =3D 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].displ= ay_name); + CloseServiceHandle(service); + --ret; + } + else + { + _tprintf(TEXT("CreateService failed - %s\n"), GetLastError= Text()); + } } } @@ -160,6 +358,11 @@ CmdRemoveServices() return 1; } + if (0 !=3D HandleDialerRegistration(1)) + { + _tprintf(TEXT("HandleDialerRegistration uninstall failed; ignoring= \n")); + } + for (i =3D 0; i < _service_max; i++) { openvpn_service_t *ovpn_svc =3D &openvpn_service[i]; -- 2.17.1.windows.2 --_000_BL0PR2101MB10582678FD3D21C0355098E1AB540BL0PR2101MB1058_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

From 58cc8b37f567da867e3a6e2efa4c15de36495a79 Mon Se= p 17 00:00:00 2001

From: Kevin Kane <kkane@...2393...>=

Date: Fri, 13 Jul 2018 09:44:00 -0700

Subject: Register/unregister trusted custom dialer D= LL when

installing/uninstalling service

 

Add copyright notice as required where Microsoft has= contributed code

 

Signed-off-by: Kevin Kane <kkane@...2393...>

---

src/openvpnserv/service.c | 241 ++++= +++++++++++++++= +++++++++++++++= +---

1 file changed, 222 insertions(+), 19 deletions(= -)

 

diff --git a/src/openvpnserv/service.c b/src/openvpn= serv/service.c

index 7157bea2..edb21b0d 100644

--- a/src/openvpnserv/service.c

+++ b/src/openvpnserv/service.c

@@ -6,6 +6,7 @@

  *

  * Copyright (C) 1993 - 2000.  Microsoft = Corporation.  All rights reserved.

  *       &n= bsp;            = ;  2013 Heiko Hund <heiko.hund@...1489...>

+ * Portions Copyright (C) 2018 Microsoft Corpor= ation

  */

 

#include "service.h"

@@ -53,6 +54,195 @@ ReportStatusToSCMgr(SERVICE_= STATUS_HANDLE service, SERVICE_STATUS *status)

     return res;

}

 

+static const TCHAR DialerDllName[] =3D TEXT(&qu= ot;libopenvpndialer-0.dll");

+static const TCHAR RegValueName[] =3D TEXT(&quo= t;CustomDLL");

+

+static int

+HandleDialerRegistration(int uninstall)

+{

+    TCHAR path[512], customDllSt= ring[1024];

+    HKEY parametersKey;

+    LONG result;

+    DWORD customDllSize =3D size= of(customDllString);

+

+    /* Assumption is that the di= aler DLL is installed to the same bin directory as everything else. */=

+    if (GetModuleFileName(NULL, = path, sizeof(path)) =3D=3D 0)

+    {

+        _tpr= intf(TEXT("Unable to get module path - %lu\n"), GetLastError());<= o:p>

+        retu= rn 1;

+    }

+

+    /* The version of NSIS we us= e 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<= /p>

+     * custom dialer DLL. I= nstead, we'll update this registry entry on install/uninstall.

+     */

+

+    TCHAR *lastBackslash =3D _tc= srchr(path, TEXT('\\'));

+    if (NULL =3D=3D lastBackslas= h)

+    {

+        _tpr= intf(TEXT("Could not locate last backslash in path: %s\n"), path)= ;

+        retu= rn 1;

+    }

+

+    lastBackslash[1] =3D TEXT('\= 0');

+

+    /* Bounds checking. */<= /o:p>

+    if ((_tcslen(path) + _co= untof(DialerDllName)) > _countof(path))

+    {

+        _tpr= intf(TEXT("Out of buffer adding dialer filename to path"));<= /o:p>

+        retu= rn 1;

+    }

+

+    _tcscat(path, DialerDllName)= ;

+

+    result =3D RegOpenKeyEx(HKEY= _LOCAL_MACHINE,

+        TEXT= ("SYSTEM\\CurrentControlSet\\Services\\RasMan\\Parameters"),

+        0, <= o:p>

+        KEY_= ALL_ACCESS,

+        &= ;parametersKey);

+    if (ERROR_SUCCESS !=3D resul= t)

+    {

+        _tpr= intf(TEXT("Could not open RasMan parameters key: %ld\n"), result)= ;

+        retu= rn 1;

+    }

+

+    /* Must RegCloseKey(paramete= rsKey) from this point */

+

+    result =3D RegGetValue(param= etersKey,

+        NULL= ,

+        RegV= alueName,

+        RRF_= RT_REG_MULTI_SZ,

+        NULL= ,

+        cust= omDllString,

+        &= ;customDllSize);

+

+    /* If we're installing, the = key being absent is okay. Any other error is fatal. */

+    if (ERROR_FILE_NOT_FOUND =3D= =3D result)

+    {

+        if (= 0 !=3D uninstall)

+        {

+        = ;    _tprintf(TEXT("CustomDLL value was not found; skip= ping unregistration step\n"));

+        = ;    RegCloseKey(parametersKey);

+        = ;    return 0; /* Not a fatal error but nothing to do */

+        }

+        else=

+        {

+        = ;    result =3D ERROR_SUCCESS;

+        = ;    customDllString[0] =3D TEXT('\0');

+        = ;    customDllSize =3D 0;

+        }

+    }

+    else if (ERROR_SUCCESS !=3D = result)

+    {

+        _tpr= intf(TEXT("Could not open CustomDLL value: %ld\n"), result);=

+        RegC= loseKey(parametersKey);

+        retu= rn 1;

+    }

+

+    /* Determine if the custom d= ialer DLL is present in the registry setting. This is a multi-string so we = can't

+     * use _tcsstr.

+     */

+    TCHAR* p;

+    for (p =3D customDllString; = *p !=3D TEXT('\0'); p +=3D _tcslen(p) + 1)

+    {

+        if (= 0 =3D=3D _tcsicmp(path, p))

+        {

+        = ;    /* It is. p points to where it begins. */

+        = ;    break;

+        }

+    }

+    /* If it's not present, p po= ints at a NULL terminator. */

+

+    /* If we're installing and t= he 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 =3D=3D uninstall) &= amp;& (*p !=3D TEXT('\0'))) ||

+        = ; ((0 !=3D uninstall) && (*p =3D=3D TEXT('\0'))) )

+    {

+        RegC= loseKey(parametersKey);

+        retu= rn 0;

+    }

+

+    /* If we're installing and t= he DLL is not present in the registry, append it at point p. */<= /p>

+    if ((0 =3D=3D uninstall) &am= p;& (*p =3D=3D TEXT('\0')))

+    {

+        /* M= ake 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(customDll= String))

+        {

+        = ;    _tprintf(TEXT("Not enough buffer to create new Cus= tomDLL string\n"));

+        = ;    RegCloseKey(parametersKey);

+        = ;    return 1;

+        }

+        _tcs= cpy(p, path);

+        /* A= dd second terminating NULL we overwrote with the copy. */

+        p &#= 43;=3D _tcslen(p) + 1;

+        *p&#= 43;+ =3D TEXT('\0');

+

+        /* S= et in the registry. */

+        resu= lt =3D RegSetValueEx(parametersKey,

+        = ;    RegValueName,

+        = ;    0,

+        = ;    REG_MULTI_SZ,

+        = ;    (const BYTE*)customDllString,

+        = ;    (DWORD)(sizeof(TCHAR) * (p - customDllString)));

+

+        RegC= loseKey(parametersKey);

+        if (= ERROR_SUCCESS !=3D result)

+        {

+        = ;    _tprintf(TEXT("Failed to RegSetValueEx: %ld\n"= ;), result);

+        &nbs= p;   return 1;

+        }

+    }

+    /* Else if we're uninstallin= g and the DLL is present, copy everything except strings matching path. */<= o:p>

+    else if ((0 !=3D uninstall) = && (*p !=3D TEXT('\0')))

+    {

+        TCHA= R newCustomDllString[1024];

+        TCHA= R *n, *c;

+

+        /* n= ewCustomDllString is the same size as customDllString, and we're only remov= ing, so no

+        = ; * way to overflow the buffer.

+        = ; */

+        for = (c =3D customDllString, n =3D newCustomDllString; *c !=3D TEXT('\0'); c = 3;=3D _tcslen(c) + 1)

+        {

+        = ;    if (0 !=3D _tcsicmp(path, c))

+        = ;    {

+        = ;        _tcscpy(n, c);

+        = ;        n +=3D _tcslen(n) + 1;<= o:p>

+        = ;    }

+        }

+

+        /* A= dd double-terminating NULL as is required for a multi-string. */=

+        *n&#= 43;+ =3D TEXT('\0');

+

+        /* I= f the new string is nonempty, set in the registry. Otherwise delete the val= ue. */

+        if (= TEXT('\0') !=3D *newCustomDllString)

+        {

+        = ;    result =3D RegSetValueEx(parametersKey,

+        = ;        RegValueName,

+        = ;        0,

+        = ;        REG_MULTI_SZ,

+        = ;        (const BYTE*)newCustomDllString= ,

+        = ;        (DWORD)(sizeof(TCHAR) * (n - ne= wCustomDllString)));

+        }

+        else=

+        {

+        = ;    result =3D RegDeleteValue(parametersKey, RegValueName);=

+        }

+

+        RegC= loseKey(parametersKey);

+        if (= ERROR_SUCCESS !=3D result)

+        {

+        = ;    _tprintf(TEXT("Failed to %s new registry value: %l= d\n"),

+        = ;        (TEXT('\0') !=3D *newCustomDllS= tring)?TEXT("set"):TEXT("delete"),

+        = ;        result);

+        = ;    return 1;

+        }

+    }

+

+    return 0;

+}

+

static int

CmdInstallServices()

{

@@ -77,27 +267,35 @@ CmdInstallServices()

         ret= urn 1;

     }

 

-    for (i =3D 0; i < _service_ma= x; i++)

+    if (0 !=3D HandleDialerRegis= tration(0))

     {

-        service = =3D CreateService(svc_ctl_mgr,

-        &nb= sp;            =            openvpn_servic= e[i].name,

-        &nb= sp;            =            openvpn_servic= e[i].display_name,

-        &nb= sp;            =            SERVICE_QUERY_= STATUS,

-        &nb= sp;            =            SERVICE_WIN32_= SHARE_PROCESS,

-        &nb= sp;            =            openvpn_servic= e[i].start_type,

-        &nb= sp;            =            SERVICE_ERROR_= NORMAL,

-        &nb= sp;            =            path, NULL, NU= LL,

-         &n= bsp;            = ;          openvpn_servic= e[i].dependencies,

-        &nb= sp;            =            NULL, NULL);

-        if (serv= ice)

-        {

-        &nb= sp;   _tprintf(TEXT("%s installed.\n"), openvpn_service= [i].display_name);

-        &nb= sp;   CloseServiceHandle(service);

-        &nb= sp;   --ret;

-        }

-        else

+        _tpr= intf(TEXT("HandleDialerRegistration failed\n"));

+        ret = =3D 1;

+    }

+    else

+    {

+        for = (i =3D 0; i < _service_max; i++)

         {

-        &nb= sp;   _tprintf(TEXT("CreateService failed - %s\n"), Get= LastErrorText());

+        = ;    service =3D CreateService(svc_ctl_mgr,

+        = ;            &n= bsp;            = ;   openvpn_service[i].name,

+        = ;            &n= bsp;            = ;   openvpn_service[i].display_name,

+        = ;            &n= bsp;            = ;   SERVICE_QUERY_STATUS,

+        = ;            &n= bsp;            = ;   SERVICE_WIN32_SHARE_PROCESS,

+        = ;            &n= bsp;            = ;   openvpn_service[i].start_type,

+        = ;            &n= bsp;            = ;   SERVICE_ERROR_NORMAL,

+        = ;            &n= bsp;            = ;   path, NULL, NULL,

+        = ;            &n= bsp;            = ;   openvpn_service[i].dependencies,

+        = ;            &n= bsp;            = ;   NULL, NULL);

+        = ;    if (service)

+        = ;    {

+        = ;        _tprintf(TEXT("%s installe= d.\n"), openvpn_service[i].display_name);

+        = ;        CloseServiceHandle(service);

+        = ;        --ret;

+        = ;    }

+        = ;    else

+        = ;    {

+        = ;        _tprintf(TEXT("CreateServi= ce failed - %s\n"), GetLastErrorText());

+        = ;    }

         }

     }

 

@@ -160,6 +358,11 @@ CmdRemoveServices()

         ret= urn 1;

     }

 

+    if (0 !=3D HandleDialerRegis= tration(1))

+    {

+        _tpr= intf(TEXT("HandleDialerRegistration uninstall failed; ignoring\n"= ));

+    }

+

     for (i =3D 0; i < _servi= ce_max; i++)

     {

         ope= nvpn_service_t *ovpn_svc =3D &openvpn_service[i];

--

2.17.1.windows.2

 

--_000_BL0PR2101MB10582678FD3D21C0355098E1AB540BL0PR2101MB1058_--