Reputation: 43
I want to be able to do sc sdset $serviceName $accessString
to allow a specific user to stop and start a service, see also this question. But I wish to do it without the command line and with c++ using the Windows API instead.
I already got a SecurityDescriptor and the SecurityInfo. Where I fail now is adding this new rule to the service. I found this resource but it's unclear to me how I can turn my SecurityDescriptor into a EXPLICIT_ACCESS structure to use with SetEntriesInAcl().
Upvotes: 1
Views: 340
Reputation: 33706
here main question - how decide - which account (SID) must have rights. if want allow NetworkService
start/stop/pause itself - it need SERVICE_START
,
SERVICE_STOP
, SERVICE_PAUSE_CONTINUE
- so in fact GENERIC_EXECUTE
if look in Service Security and Access Rights
we can design for example next DACL:
GENERIC_ALL
for LocalSystem and AdministratorsGENERIC_READ
for EveryoneGENERIC_READ | GENERIC_EXECUTE
for NetworkService--
#include <sddl.h>
ULONG afe(PCWSTR lpServiceName)
{
ULONG err = 0;
if (SC_HANDLE hSCManager = OpenSCManagerW(0, 0, 0))
{
if (SC_HANDLE hService = OpenService(hSCManager, lpServiceName, WRITE_DAC))
{
PSECURITY_DESCRIPTOR SecurityDescriptor;
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
L"D:(A;;GA;;;SY)" // SDDL_LOCAL_SYSTEM -> SDDL_GENERIC_ALL
L"(A;;GA;;;BA)" // SDDL_BUILTIN_ADMINISTRATORS -> SDDL_GENERIC_ALL
L"(A;;GR;;;WD)" // SDDL_EVERYONE -> SDDL_GENERIC_READ
L"(A;;GRGX;;;NS)", // SDDL_NETWORK_SERVICE -> SDDL_GENERIC_READ|SDDL_GENERIC_EXECUTE
SDDL_REVISION_1, &SecurityDescriptor, 0))
{
if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, SecurityDescriptor))
{
err = GetLastError();
}
LocalFree(SecurityDescriptor);
}
else
{
err = GetLastError();
}
CloseServiceHandle(hService);
}
else
{
err = GetLastError();
}
CloseServiceHandle(hSCManager);
}
else
{
err = GetLastError();
}
return err;
}
Upvotes: 2