871 lines
24 KiB
C++
871 lines
24 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
service.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file provides access to the service control
|
|||
|
manager for starting, stopping, adding, and removing
|
|||
|
services.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
WIN32 User Mode
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Wesley Witt (wesw) 17-Feb-1996
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
|
|||
|
#include "faxocm.h"
|
|||
|
|
|||
|
#include <ntsecapi.h>
|
|||
|
#include <lm.h>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
OpenPolicy(
|
|||
|
LPWSTR ServerName, // machine to open policy on (Unicode)
|
|||
|
DWORD DesiredAccess, // desired access to policy
|
|||
|
PLSA_HANDLE PolicyHandle // resultant policy handle
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
GetAccountSid(
|
|||
|
LPWSTR SystemName, // where to lookup account
|
|||
|
LPWSTR AccountName, // account of interest
|
|||
|
PSID *Sid // resultant buffer containing SID
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SetPrivilegeOnAccount(
|
|||
|
LSA_HANDLE PolicyHandle, // open policy handle
|
|||
|
PSID AccountSid, // SID to grant privilege to
|
|||
|
LPWSTR PrivilegeName, // privilege to grant (Unicode)
|
|||
|
BOOL bEnable // enable or disable
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
InitLsaString(
|
|||
|
PLSA_UNICODE_STRING LsaString, // destination
|
|||
|
LPWSTR String // source (Unicode)
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
DisplayNtStatus(
|
|||
|
LPSTR szAPI, // pointer to function name (ANSI)
|
|||
|
NTSTATUS Status // NTSTATUS error value
|
|||
|
);
|
|||
|
|
|||
|
void
|
|||
|
DisplayWinError(
|
|||
|
LPSTR szAPI, // pointer to function name (ANSI)
|
|||
|
DWORD WinError // DWORD WinError
|
|||
|
);
|
|||
|
|
|||
|
#define RTN_OK 0
|
|||
|
#define RTN_USAGE 1
|
|||
|
#define RTN_ERROR 13
|
|||
|
|
|||
|
//
|
|||
|
// If you have the ddk, include ntstatus.h.
|
|||
|
//
|
|||
|
#ifndef STATUS_SUCCESS
|
|||
|
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
GetDefaultDomainName(
|
|||
|
LPWSTR DomainName
|
|||
|
)
|
|||
|
{
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
NTSTATUS NtStatus;
|
|||
|
DWORD err = 0;
|
|||
|
LSA_HANDLE LsaPolicyHandle = NULL;
|
|||
|
PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Open a handle to the local machine's LSA policy object.
|
|||
|
//
|
|||
|
|
|||
|
InitializeObjectAttributes( &ObjectAttributes, // object attributes
|
|||
|
NULL, // name
|
|||
|
0L, // attributes
|
|||
|
NULL, // root directory
|
|||
|
NULL ); // security descriptor
|
|||
|
|
|||
|
NtStatus = LsaOpenPolicy( NULL, // system name
|
|||
|
&ObjectAttributes, // object attributes
|
|||
|
POLICY_EXECUTE, // access mask
|
|||
|
&LsaPolicyHandle ); // policy handle
|
|||
|
|
|||
|
if( !NT_SUCCESS( NtStatus ) )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Query the domain information from the policy object.
|
|||
|
//
|
|||
|
NtStatus = LsaQueryInformationPolicy( LsaPolicyHandle,
|
|||
|
PolicyAccountDomainInformation,
|
|||
|
(PVOID *) &DomainInfo );
|
|||
|
|
|||
|
if (!NT_SUCCESS(NtStatus))
|
|||
|
{
|
|||
|
LsaClose(LsaPolicyHandle);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
(void) LsaClose(LsaPolicyHandle);
|
|||
|
|
|||
|
//
|
|||
|
// Copy the domain name into our cache, and
|
|||
|
//
|
|||
|
|
|||
|
CopyMemory( DomainName,
|
|||
|
DomainInfo->DomainName.Buffer,
|
|||
|
DomainInfo->DomainName.Length );
|
|||
|
|
|||
|
//
|
|||
|
// Null terminate it appropriately
|
|||
|
//
|
|||
|
|
|||
|
DomainName[DomainInfo->DomainName.Length / sizeof(WCHAR)] = L'\0';
|
|||
|
|
|||
|
//
|
|||
|
// Clean up
|
|||
|
//
|
|||
|
LsaFreeMemory( (PVOID)DomainInfo );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LPWSTR
|
|||
|
GetMachineName(
|
|||
|
LPWSTR AccountName
|
|||
|
)
|
|||
|
{
|
|||
|
LSA_HANDLE PolicyHandle = NULL;
|
|||
|
WCHAR DomainName[128];
|
|||
|
WCHAR LocalComputerName[128];
|
|||
|
LPWSTR MachineName = NULL;
|
|||
|
LPWSTR p;
|
|||
|
LPWSTR DCName = NULL;
|
|||
|
NET_API_STATUS NetStatus;
|
|||
|
UNICODE_STRING NameStrings;
|
|||
|
PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
|
|||
|
PLSA_TRANSLATED_SID LsaSids = NULL;
|
|||
|
PUSER_MODALS_INFO_1 Modals = NULL;
|
|||
|
DWORD Size;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// get the domain name
|
|||
|
//
|
|||
|
|
|||
|
p = wcschr( AccountName, L'\\' );
|
|||
|
if (p) {
|
|||
|
*p = 0;
|
|||
|
wcscpy( DomainName, AccountName );
|
|||
|
*p = L'\\';
|
|||
|
} else {
|
|||
|
wcscpy( DomainName, AccountName );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Open the policy on the target machine.
|
|||
|
//
|
|||
|
Status = OpenPolicy(
|
|||
|
NULL,
|
|||
|
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
|||
|
&PolicyHandle
|
|||
|
);
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// lookup the domain name for the account
|
|||
|
//
|
|||
|
|
|||
|
InitLsaString( &NameStrings, AccountName );
|
|||
|
|
|||
|
Status = LsaLookupNames(
|
|||
|
PolicyHandle,
|
|||
|
1,
|
|||
|
&NameStrings,
|
|||
|
&ReferencedDomains,
|
|||
|
&LsaSids
|
|||
|
);
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get the local computer name
|
|||
|
//
|
|||
|
|
|||
|
Size = sizeof(LocalComputerName);
|
|||
|
if (!GetComputerName( LocalComputerName, &Size )) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// see if we are tring to set a local account
|
|||
|
//
|
|||
|
|
|||
|
if (wcscmp( LocalComputerName, ReferencedDomains->Domains->Name.Buffer ) != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// see what part of the domain we are attempting to set
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = NetUserModalsGet( NULL, 1, (LPBYTE*) &Modals );
|
|||
|
if (NetStatus != NERR_Success) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (Modals->usrmod1_role != UAS_ROLE_PRIMARY) {
|
|||
|
|
|||
|
//
|
|||
|
// we know we are remote, so get the real dc name
|
|||
|
//
|
|||
|
|
|||
|
NetStatus = NetGetDCName( NULL, DomainName, (LPBYTE*) &DCName );
|
|||
|
if (NetStatus != NERR_Success) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
MachineName = StringDup( DCName );
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
exit:
|
|||
|
if (Modals) {
|
|||
|
NetApiBufferFree( Modals );
|
|||
|
}
|
|||
|
if (DCName) {
|
|||
|
NetApiBufferFree( DCName );
|
|||
|
}
|
|||
|
if (ReferencedDomains) {
|
|||
|
LsaFreeMemory( ReferencedDomains );
|
|||
|
}
|
|||
|
if (LsaSids) {
|
|||
|
LsaFreeMemory( LsaSids );
|
|||
|
}
|
|||
|
if (PolicyHandle) {
|
|||
|
LsaClose( PolicyHandle );
|
|||
|
}
|
|||
|
|
|||
|
return MachineName;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
SetServiceSecurity(
|
|||
|
LPWSTR AccountName
|
|||
|
)
|
|||
|
{
|
|||
|
LSA_HANDLE PolicyHandle;
|
|||
|
PSID pSid;
|
|||
|
NTSTATUS Status;
|
|||
|
int iRetVal=RTN_ERROR;
|
|||
|
LPWSTR MachineName;
|
|||
|
WCHAR NewAccountName[512];
|
|||
|
|
|||
|
|
|||
|
if (AccountName[0] == L'.') {
|
|||
|
if (GetDefaultDomainName( NewAccountName )) {
|
|||
|
wcscat( NewAccountName, &AccountName[1] );
|
|||
|
AccountName = NewAccountName;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// try to get the correct machine name
|
|||
|
//
|
|||
|
MachineName = GetMachineName( AccountName );
|
|||
|
|
|||
|
//
|
|||
|
// Open the policy on the target machine.
|
|||
|
//
|
|||
|
Status = OpenPolicy(
|
|||
|
MachineName,
|
|||
|
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
|||
|
&PolicyHandle
|
|||
|
);
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
return RTN_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Obtain the SID of the user/group.
|
|||
|
// Note that we could target a specific machine, but we don't.
|
|||
|
// Specifying NULL for target machine searches for the SID in the
|
|||
|
// following order: well-known, Built-in and local, primary domain,
|
|||
|
// trusted domains.
|
|||
|
//
|
|||
|
if(GetAccountSid(
|
|||
|
MachineName, // target machine
|
|||
|
AccountName,// account to obtain SID
|
|||
|
&pSid // buffer to allocate to contain resultant SID
|
|||
|
)) {
|
|||
|
//
|
|||
|
// We only grant the privilege if we succeeded in obtaining the
|
|||
|
// SID. We can actually add SIDs which cannot be looked up, but
|
|||
|
// looking up the SID is a good sanity check which is suitable for
|
|||
|
// most cases.
|
|||
|
|
|||
|
//
|
|||
|
// Grant the SeServiceLogonRight to users represented by pSid.
|
|||
|
//
|
|||
|
if((Status=SetPrivilegeOnAccount(
|
|||
|
PolicyHandle, // policy handle
|
|||
|
pSid, // SID to grant privilege
|
|||
|
L"SeServiceLogonRight", // Unicode privilege
|
|||
|
TRUE // enable the privilege
|
|||
|
)) == STATUS_SUCCESS) {
|
|||
|
iRetVal=RTN_OK;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Close the policy handle.
|
|||
|
//
|
|||
|
LsaClose(PolicyHandle);
|
|||
|
|
|||
|
//
|
|||
|
// Free memory allocated for SID.
|
|||
|
//
|
|||
|
if(pSid != NULL) MemFree(pSid);
|
|||
|
|
|||
|
return iRetVal;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
InitLsaString(
|
|||
|
PLSA_UNICODE_STRING LsaString,
|
|||
|
LPWSTR String
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD StringLength;
|
|||
|
|
|||
|
if (String == NULL) {
|
|||
|
LsaString->Buffer = NULL;
|
|||
|
LsaString->Length = 0;
|
|||
|
LsaString->MaximumLength = 0;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
StringLength = wcslen(String);
|
|||
|
LsaString->Buffer = String;
|
|||
|
LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
|
|||
|
LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
OpenPolicy(
|
|||
|
LPWSTR ServerName,
|
|||
|
DWORD DesiredAccess,
|
|||
|
PLSA_HANDLE PolicyHandle
|
|||
|
)
|
|||
|
{
|
|||
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
LSA_UNICODE_STRING ServerString;
|
|||
|
PLSA_UNICODE_STRING Server = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Always initialize the object attributes to all zeroes.
|
|||
|
//
|
|||
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
|||
|
|
|||
|
if (ServerName != NULL) {
|
|||
|
//
|
|||
|
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
|
|||
|
//
|
|||
|
InitLsaString(&ServerString, ServerName);
|
|||
|
Server = &ServerString;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Attempt to open the policy.
|
|||
|
//
|
|||
|
return LsaOpenPolicy(
|
|||
|
Server,
|
|||
|
&ObjectAttributes,
|
|||
|
DesiredAccess,
|
|||
|
PolicyHandle
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
/*++
|
|||
|
This function attempts to obtain a SID representing the supplied
|
|||
|
account on the supplied system.
|
|||
|
|
|||
|
If the function succeeds, the return value is TRUE. A buffer is
|
|||
|
allocated which contains the SID representing the supplied account.
|
|||
|
This buffer should be freed when it is no longer needed by calling
|
|||
|
HeapFree(GetProcessHeap(), 0, buffer)
|
|||
|
|
|||
|
If the function fails, the return value is FALSE. Call GetLastError()
|
|||
|
to obtain extended error information.
|
|||
|
--*/
|
|||
|
|
|||
|
BOOL
|
|||
|
GetAccountSid(
|
|||
|
LPWSTR SystemName,
|
|||
|
LPWSTR AccountName,
|
|||
|
PSID *Sid
|
|||
|
)
|
|||
|
{
|
|||
|
LPWSTR ReferencedDomain=NULL;
|
|||
|
DWORD cbSid=128; // initial allocation attempt
|
|||
|
DWORD cbReferencedDomain=32; // initial allocation size
|
|||
|
SID_NAME_USE peUse;
|
|||
|
BOOL bSuccess=FALSE; // assume this function will fail
|
|||
|
|
|||
|
__try {
|
|||
|
|
|||
|
//
|
|||
|
// initial memory allocations
|
|||
|
//
|
|||
|
if((*Sid=MemAlloc(cbSid)) == NULL) __leave;
|
|||
|
if((ReferencedDomain=(LPWSTR)MemAlloc(cbReferencedDomain)) == NULL) __leave;
|
|||
|
|
|||
|
//
|
|||
|
// Obtain the SID of the specified account on the specified system.
|
|||
|
//
|
|||
|
while(!LookupAccountName(
|
|||
|
SystemName, // machine to lookup account on
|
|||
|
AccountName, // account to lookup
|
|||
|
*Sid, // SID of interest
|
|||
|
&cbSid, // size of SID
|
|||
|
ReferencedDomain, // domain account was found on
|
|||
|
&cbReferencedDomain,
|
|||
|
&peUse
|
|||
|
)) {
|
|||
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|||
|
//
|
|||
|
// reallocate memory
|
|||
|
//
|
|||
|
if((*Sid=HeapReAlloc(
|
|||
|
GetProcessHeap(),
|
|||
|
0,
|
|||
|
*Sid,
|
|||
|
cbSid
|
|||
|
)) == NULL) __leave;
|
|||
|
|
|||
|
if((ReferencedDomain=(LPWSTR)HeapReAlloc(
|
|||
|
GetProcessHeap(),
|
|||
|
0,
|
|||
|
ReferencedDomain,
|
|||
|
cbReferencedDomain
|
|||
|
)) == NULL) __leave;
|
|||
|
}
|
|||
|
else __leave;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Indicate success.
|
|||
|
//
|
|||
|
bSuccess=TRUE;
|
|||
|
|
|||
|
} // finally
|
|||
|
__finally {
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup and indicate failure, if appropriate.
|
|||
|
//
|
|||
|
|
|||
|
MemFree(ReferencedDomain);
|
|||
|
|
|||
|
if(!bSuccess) {
|
|||
|
if(*Sid != NULL) {
|
|||
|
MemFree(*Sid);
|
|||
|
*Sid = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} // finally
|
|||
|
|
|||
|
return bSuccess;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SetPrivilegeOnAccount(
|
|||
|
LSA_HANDLE PolicyHandle, // open policy handle
|
|||
|
PSID AccountSid, // SID to grant privilege to
|
|||
|
LPWSTR PrivilegeName, // privilege to grant (Unicode)
|
|||
|
BOOL bEnable // enable or disable
|
|||
|
)
|
|||
|
{
|
|||
|
LSA_UNICODE_STRING PrivilegeString;
|
|||
|
|
|||
|
//
|
|||
|
// Create a LSA_UNICODE_STRING for the privilege name.
|
|||
|
//
|
|||
|
InitLsaString(&PrivilegeString, PrivilegeName);
|
|||
|
|
|||
|
//
|
|||
|
// grant or revoke the privilege, accordingly
|
|||
|
//
|
|||
|
if(bEnable) {
|
|||
|
return LsaAddAccountRights(
|
|||
|
PolicyHandle, // open policy handle
|
|||
|
AccountSid, // target SID
|
|||
|
&PrivilegeString, // privileges
|
|||
|
1 // privilege count
|
|||
|
);
|
|||
|
}
|
|||
|
else {
|
|||
|
return LsaRemoveAccountRights(
|
|||
|
PolicyHandle, // open policy handle
|
|||
|
AccountSid, // target SID
|
|||
|
FALSE, // do not disable all rights
|
|||
|
&PrivilegeString, // privileges
|
|||
|
1 // privilege count
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
PSID WorldSid = NULL;
|
|||
|
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|||
|
PACL gDacl = NULL,gSacl = NULL;
|
|||
|
PSID gGroup = NULL,gOwner = NULL;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
MakeAbsoluteCopyFromRelative(
|
|||
|
PSECURITY_DESCRIPTOR psdOriginal,
|
|||
|
PSECURITY_DESCRIPTOR* ppsdNew
|
|||
|
)
|
|||
|
{
|
|||
|
// we have to find out whether the original is already self-relative
|
|||
|
SECURITY_DESCRIPTOR_CONTROL sdc = 0;
|
|||
|
PSECURITY_DESCRIPTOR psdAbsoluteCopy = NULL;
|
|||
|
DWORD dwRevision = 0;
|
|||
|
DWORD cb = 0;
|
|||
|
PACL Dacl = NULL, Sacl = NULL;
|
|||
|
|
|||
|
BOOL bDefaulted;
|
|||
|
PSID Owner = NULL, Group = NULL;
|
|||
|
|
|||
|
DWORD dwDaclSize = 0;
|
|||
|
BOOL bDaclPresent = FALSE;
|
|||
|
DWORD dwSaclSize = 0;
|
|||
|
BOOL bSaclPresent = FALSE;
|
|||
|
|
|||
|
DWORD dwOwnerSize = 0;
|
|||
|
DWORD dwPrimaryGroupSize = 0;
|
|||
|
|
|||
|
if( !IsValidSecurityDescriptor( psdOriginal ) ) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if( !GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) ) {
|
|||
|
DWORD err = GetLastError();
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
if( sdc & SE_SELF_RELATIVE ) {
|
|||
|
// the original is in self-relative format, build an absolute copy
|
|||
|
|
|||
|
// get the dacl
|
|||
|
if( !GetSecurityDescriptorDacl(
|
|||
|
psdOriginal, // address of security descriptor
|
|||
|
&bDaclPresent, // address of flag for presence of disc. ACL
|
|||
|
&Dacl, // address of pointer to ACL
|
|||
|
&bDefaulted // address of flag for default disc. ACL
|
|||
|
)
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// get the sacl
|
|||
|
if( !GetSecurityDescriptorSacl(
|
|||
|
psdOriginal, // address of security descriptor
|
|||
|
&bSaclPresent, // address of flag for presence of disc. ACL
|
|||
|
&Sacl, // address of pointer to ACL
|
|||
|
&bDefaulted // address of flag for default disc. ACL
|
|||
|
)
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// get the owner
|
|||
|
if( !GetSecurityDescriptorOwner(
|
|||
|
psdOriginal, // address of security descriptor
|
|||
|
&Owner, // address of pointer to owner security
|
|||
|
// identifier (SID)
|
|||
|
&bDefaulted // address of flag for default
|
|||
|
)
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// get the group
|
|||
|
if( !GetSecurityDescriptorGroup(
|
|||
|
psdOriginal, // address of security descriptor
|
|||
|
&Group, // address of pointer to owner security
|
|||
|
// identifier (SID)
|
|||
|
&bDefaulted // address of flag for default
|
|||
|
)
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// get required buffer size
|
|||
|
cb = 0;
|
|||
|
MakeAbsoluteSD(
|
|||
|
psdOriginal, // address of self-relative SD
|
|||
|
psdAbsoluteCopy, // address of absolute SD
|
|||
|
&cb, // address of size of absolute SD
|
|||
|
NULL, // address of discretionary ACL
|
|||
|
&dwDaclSize, // address of size of discretionary ACL
|
|||
|
NULL, // address of system ACL
|
|||
|
&dwSaclSize, // address of size of system ACL
|
|||
|
NULL, // address of owner SID
|
|||
|
&dwOwnerSize, // address of size of owner SID
|
|||
|
NULL, // address of primary-group SID
|
|||
|
&dwPrimaryGroupSize // address of size of group SID
|
|||
|
);
|
|||
|
|
|||
|
// alloc the memory
|
|||
|
psdAbsoluteCopy = (PSECURITY_DESCRIPTOR) MemAlloc( cb );
|
|||
|
Dacl = (PACL) MemAlloc( dwDaclSize );
|
|||
|
Sacl = (PACL) MemAlloc( dwSaclSize );
|
|||
|
Owner = (PSID) MemAlloc( dwOwnerSize );
|
|||
|
Group = (PSID) MemAlloc( dwPrimaryGroupSize );
|
|||
|
|
|||
|
if(NULL == psdAbsoluteCopy ||
|
|||
|
NULL == Dacl ||
|
|||
|
NULL == Sacl ||
|
|||
|
NULL == Owner ||
|
|||
|
NULL == Group
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// make the copy
|
|||
|
if( !MakeAbsoluteSD(
|
|||
|
psdOriginal, // address of self-relative SD
|
|||
|
psdAbsoluteCopy, // address of absolute SD
|
|||
|
&cb, // address of size of absolute SD
|
|||
|
Dacl, // address of discretionary ACL
|
|||
|
&dwDaclSize, // address of size of discretionary ACL
|
|||
|
Sacl, // address of system ACL
|
|||
|
&dwSaclSize, // address of size of system ACL
|
|||
|
Owner, // address of owner SID
|
|||
|
&dwOwnerSize, // address of size of owner SID
|
|||
|
Group, // address of primary-group SID
|
|||
|
&dwPrimaryGroupSize // address of size of group SID
|
|||
|
)
|
|||
|
) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// the original is in absolute format, fail
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
*ppsdNew = psdAbsoluteCopy;
|
|||
|
|
|||
|
// paranoia check
|
|||
|
if( !IsValidSecurityDescriptor( *ppsdNew ) ) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
if( !IsValidSecurityDescriptor( psdOriginal ) ) {
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
gDacl = Dacl;
|
|||
|
gSacl = Sacl;
|
|||
|
gOwner = Owner;
|
|||
|
gGroup = Group;
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
|
|||
|
cleanup:
|
|||
|
if( Dacl != NULL && bDaclPresent == TRUE ) {
|
|||
|
MemFree((PVOID) Dacl );
|
|||
|
Dacl = NULL;
|
|||
|
}
|
|||
|
if( Sacl != NULL && bSaclPresent == TRUE ) {
|
|||
|
MemFree((PVOID) Sacl );
|
|||
|
Sacl = NULL;
|
|||
|
}
|
|||
|
if( Owner != NULL ) {
|
|||
|
MemFree((PVOID) Owner );
|
|||
|
Owner = NULL;
|
|||
|
}
|
|||
|
if( Group != NULL ) {
|
|||
|
MemFree((PVOID) Group );
|
|||
|
Group = NULL;
|
|||
|
}
|
|||
|
if( psdAbsoluteCopy != NULL ) {
|
|||
|
MemFree((PVOID) psdAbsoluteCopy );
|
|||
|
psdAbsoluteCopy = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return (FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SetServiceWorldAccessMask(
|
|||
|
SC_HANDLE hService,
|
|||
|
DWORD AccessMask
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL Rval = FALSE;
|
|||
|
DWORD Size = 0;
|
|||
|
PSECURITY_DESCRIPTOR sd = NULL, sdnew = NULL;
|
|||
|
BOOL DaclPresent = FALSE;
|
|||
|
PACL Dacl = NULL;
|
|||
|
BOOL DaclDefaulted = FALSE;
|
|||
|
PACCESS_ALLOWED_ACE Ace = NULL;
|
|||
|
BOOL bEveryoneFound = FALSE;
|
|||
|
DWORD cbAcl, cbAce;
|
|||
|
PACL DaclNew = NULL;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
if (WorldSid == NULL) {
|
|||
|
if (!AllocateAndInitializeSid( &WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &WorldSid )) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!QueryServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, &sd, 0, &Size ) &&
|
|||
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
|
|||
|
(sd = (PSECURITY_DESCRIPTOR) MemAlloc( Size )) &&
|
|||
|
QueryServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, sd, Size, &Size ))
|
|||
|
{
|
|||
|
if (GetSecurityDescriptorDacl( sd, &DaclPresent, &Dacl, &DaclDefaulted )) {
|
|||
|
if (!IsValidSecurityDescriptor(sd)) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
cbAcl = sizeof (ACL);
|
|||
|
for (i=0; i<Dacl->AceCount; i++) {
|
|||
|
if (GetAce( Dacl, i, (LPVOID*)&Ace )) {
|
|||
|
if (EqualSid( WorldSid, &(Ace->SidStart))) {
|
|||
|
Ace->Mask |= AccessMask;
|
|||
|
bEveryoneFound = TRUE;
|
|||
|
}
|
|||
|
cbAce = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); // add this ACE's SID length
|
|||
|
cbAce += GetLengthSid (Ace);
|
|||
|
// add the length of each ACE to the total ACL length
|
|||
|
cbAcl += cbAce;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!MakeAbsoluteCopyFromRelative( sd, &sdnew )){
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (!bEveryoneFound) {
|
|||
|
|
|||
|
// subtract ACE.SidStart from the size
|
|||
|
cbAce = sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD); // add this ACE's SID length
|
|||
|
cbAce += GetLengthSid (WorldSid);
|
|||
|
// add the length of each ACE to the total ACL length
|
|||
|
cbAcl += cbAce;
|
|||
|
|
|||
|
DaclNew = (PACL) MemAlloc( cbAcl *4 );
|
|||
|
if (!DaclNew) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (!InitializeAcl(DaclNew, cbAcl*4, ACL_REVISION )) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (!IsValidAcl(DaclNew)) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i< Dacl->AceCount; i++) {
|
|||
|
if (GetAce( Dacl, i, (LPVOID*)&Ace )) {
|
|||
|
if (!AddAccessAllowedAce(
|
|||
|
DaclNew,
|
|||
|
ACL_REVISION,
|
|||
|
Ace->Mask,
|
|||
|
&(Ace->SidStart)
|
|||
|
)) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
if (!IsValidAcl(DaclNew)) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
} else {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if (!AddAccessAllowedAce(
|
|||
|
DaclNew, // pointer to access-control list
|
|||
|
ACL_REVISION, // ACL revision level
|
|||
|
SERVICE_QUERY_STATUS | AccessMask, // access mask
|
|||
|
WorldSid // pointer to security identifier);
|
|||
|
)) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if (!IsValidAcl(DaclNew) ||
|
|||
|
!IsValidSecurityDescriptor(sdnew) ||
|
|||
|
!SetSecurityDescriptorDacl(
|
|||
|
sdnew,
|
|||
|
TRUE,
|
|||
|
DaclNew,
|
|||
|
FALSE )) {
|
|||
|
goto exit;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (IsValidSecurityDescriptor( sdnew ) &&
|
|||
|
SetServiceObjectSecurity( hService, DACL_SECURITY_INFORMATION, sdnew )) {
|
|||
|
Rval = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
exit:
|
|||
|
MemFree( sd );
|
|||
|
|
|||
|
MemFree( sdnew );
|
|||
|
|
|||
|
MemFree( DaclNew );
|
|||
|
|
|||
|
MemFree( gDacl );
|
|||
|
MemFree( gSacl );
|
|||
|
MemFree( gGroup );
|
|||
|
MemFree( gOwner );
|
|||
|
|
|||
|
return Rval;
|
|||
|
}
|
|||
|
|