Windows Services Programming 17

 

 

 

 

 

Modifying the DACL for a Windows Service Example

 

A service control program can create or modify the DACL associated with a service to control access. To retrieve the DACL associated with a service object, we can use QueryServiceObjectSecurity() function and to set the DACL, use the SetServiceObjectSecurity() function. Any changes made to the SECURITY_DESCRIPTOR associated with the service object are persistent until the service is removed from the system.

The following code fragment example creates and sets a new DACL for the service. The code merges one access control entry (ACE) to the existing DACL for the service. The new ACE grants the Guest account start, stop, delete, and READ_CONTROL access to the specified service. Access to the service can be modified by the AccessPermissions parameter passed to the BuildExplicitAccessWithName() function. The szSvcName variable is a global variable that contains the name of the service.

 

// Purpose: Updates the service DACL to grant start, stop, delete, and read control access to the Guest account.

// Parameters: None

// Return value: None

void __stdcall DoUpdateSvcDacl(void)

{

    EXPLICIT_ACCESS      ea;

    SECURITY_DESCRIPTOR  sd;

    PSECURITY_DESCRIPTOR psd            = NULL;

    PACL                 pacl           = NULL;

    PACL                 pNewAcl        = NULL;

    BOOL                 bDaclPresent   = FALSE;

    BOOL                 bDaclDefaulted = FALSE;

    DWORD                dwError        = 0;

    DWORD                dwSize         = 0;

    DWORD                dwBytesNeeded  = 0;

 

    // Get a handle to the SCM database.

    schSCManager = OpenSCManager(

        NULL,                    // local computer

        NULL,                    // ServicesActive database

        SC_MANAGER_ALL_ACCESS);  // full access rights

 

    if (schSCManager == NULL)

    {

        wprintf(L"OpenSCManager() failed, error %u\n", GetLastError());

        return;

    }

      else

            wprintf(L"OpenSCManager() is OK!\n");

 

    // Get a handle to the service

    schService = OpenService(

        schSCManager,              // SCManager database

        szSvcName,                 // name of service

        READ_CONTROL | WRITE_DAC); // access

 

    if (schService == NULL)

    {

        wprintf(L"OpenService() failed, error %u\n", GetLastError());

        CloseServiceHandle(schSCManager);

        return;

    }

      else

            wprintf(L"OpenService() is pretty fine!\n");

 

    // Get the current security descriptor.

    if (!QueryServiceObjectSecurity(schService,

        DACL_SECURITY_INFORMATION,

        &psd,           // using NULL does not work on all versions

        0,

        &dwBytesNeeded))

    {

        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)

        {

            dwSize = dwBytesNeeded;

            psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwSize);

            if (psd == NULL)

            {

                // Note: HeapAlloc does not support GetLastError().

                wprintf(L"HeapAlloc() failed!\n");

                goto dacl_cleanup;

            }

 

            if (!QueryServiceObjectSecurity(schService,DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))

            {

                wprintf(L"QueryServiceObjectSecurity() failed, error %u\n", GetLastError());

                goto dacl_cleanup;

            }

        }

        else

        {

            wprintf(L"QueryServiceObjectSecurity() failed, error %u\n", GetLastError());

            goto dacl_cleanup;

        }

    }

 

    // Get the DACL.

    if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted))

    {

        wprintf(L"GetSecurityDescriptorDacl() failed, error %u\n", GetLastError());

        goto dacl_cleanup;

    }

      else

            wprintf(L"GetSecurityDescriptorDacl() totally working!\n");

 

    // Build the ACE.

    BuildExplicitAccessWithName(&ea, L"GUEST",SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE, SET_ACCESS, NO_INHERITANCE);

 

    dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);

    if (dwError != ERROR_SUCCESS)

    {

        wprintf(L"SetEntriesInAcl() failed, error %u\n", dwError);

        goto dacl_cleanup;

    }

      else

            wprintf(L"SetEntriesInAcl() is no problem!\n");

 

    // Initialize a new security descriptor.

    if (!InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION))

    {

        wprintf(L"InitializeSecurityDescriptor() failed, error %u\n", GetLastError());

        goto dacl_cleanup;

    }

      else

            wprintf(L"InitializeSecurityDescriptor() is working perfectly!\n");

 

    // Set the new DACL in the security descriptor.

    if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))

    {

        wprintf(L"SetSecurityDescriptorDacl() failed, error %u\n", GetLastError());

        goto dacl_cleanup;

    }

      else

            wprintf(L"SetSecurityDescriptorDacl() is absolutely working!\n");

 

    // Set the new DACL for the service object.

    if (!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd))

    {

        wprintf(L"SetServiceObjectSecurity() failed, error %u\n", GetLastError());

        goto dacl_cleanup;

    }

    else

            wprintf(L"SetServiceObjectSecurity() - Service DACL updated successfully\n");

 

dacl_cleanup:

    CloseServiceHandle(schSCManager);

    CloseServiceHandle(schService);

 

    if(NULL != pNewAcl)

        LocalFree((HLOCAL)pNewAcl);

    if(NULL != psd)

        HeapFree(GetProcessHeap(), 0, (LPVOID)psd);

}

 

 

 

 

< Windows Services 16 | Win32 Programming | Windows Services Win32 Programming | Windows Services 18 >