|
|
//+----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: security.cxx
//
// Contents:
//
// Classes:
//
// Interfaces:
//
// History: 06-Jul-96 MarkBl Created.
// 03-Mar-01 JBenton Prefix Bug 350196
// invalid pointer could be dereferenced on cleanup
//
//-----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "common.hxx"
#include "debug.hxx"
#include "security.hxx"
#include "proto.hxx"
typedef struct _MYSIDINFO { PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority; DWORD dwSubAuthority; PSID pSid; } MYSIDINFO;
#define TASK_ALL (GENERIC_READ | GENERIC_WRITE | \
GENERIC_EXECUTE | GENERIC_ALL) #define TASK_READ (GENERIC_READ)
DWORD AllocateAndInitializeDomainSid( PSID pDomainSid, MYSIDINFO * pDomainSidInfo); HRESULT GetFileOwnerSid( LPCWSTR pwszFileName, PSID * ppSid);
//+---------------------------------------------------------------------------
//
// Function: SetTaskFileSecurity
//
// Synopsis: Grant the following permissions to the task object:
//
// LocalSystem All Access.
// Creator All Access.
// Domain Admininstrators All Access.
//
// Arguments: [fIsATTask] -- TRUE if the task is an AT-submitted task;
// FALSE otherwise.
// [pwszTaskPath] -- Task object path.
//
// Notes: None.
//
//----------------------------------------------------------------------------
HRESULT SetTaskFileSecurity(LPCWSTR pwszTaskPath, BOOL fIsATTask) { #define BASE_SID_COUNT 2
#define DOMAIN_SID_COUNT 1
#define TASK_ACE_COUNT 3
FILESYSTEMTYPE FileSystemType; HRESULT hr;
hr = GetFileSystemTypeFromPath(pwszTaskPath, &FileSystemType);
if (FAILED(hr)) { return(hr); }
if (FileSystemType == FILESYSTEM_FAT) { //
// No security on FAT. This isn't an error. Let the caller
// think everything went fine.
//
return(S_OK); }
//
// Retrieve the SID of the file owner.
//
PSID pOwnerSid = NULL;
hr = GetFileOwnerSid(pwszTaskPath, &pOwnerSid);
if (FAILED(hr)) { return(hr); }
//
// OK, the fun begins. Build a security descriptor and set file security.
//
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; DWORD Status;
SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY CreatorSidAuth = SECURITY_CREATOR_SID_AUTHORITY;
MYSIDINFO rgBaseSidInfo[BASE_SID_COUNT] = { { &NtAuth, // Local System.
SECURITY_LOCAL_SYSTEM_RID, NULL }, { &NtAuth, // Built in domain.
SECURITY_BUILTIN_DOMAIN_RID, NULL } };
MYSIDINFO rgDomainSidInfo[DOMAIN_SID_COUNT] = { { NULL, // Domain administrators.
DOMAIN_ALIAS_RID_ADMINS, NULL } };
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
//
// Make sure we didn't goof.
//
schAssert(BASE_SID_COUNT == (sizeof(rgBaseSidInfo) / sizeof(MYSIDINFO))); schAssert(DOMAIN_SID_COUNT == (sizeof(rgDomainSidInfo) / sizeof(MYSIDINFO)));
//
// Create the base SIDs.
//
DWORD i;
for (i = 0; i < BASE_SID_COUNT; i++) { if (!AllocateAndInitializeSid(rgBaseSidInfo[i].pIdentifierAuthority, 1, rgBaseSidInfo[i].dwSubAuthority, 0, 0, 0, 0, 0, 0, 0, &rgBaseSidInfo[i].pSid)) { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); break; }
if (!IsValidSid(rgBaseSidInfo[i].pSid)) { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); break; } }
if (SUCCEEDED(hr)) { //
// Create the domain SIDs.
//
for (i = 0; i < DOMAIN_SID_COUNT; i++) { DWORD dwError = AllocateAndInitializeDomainSid( rgBaseSidInfo[1].pSid, &rgDomainSidInfo[i]);
if (dwError != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwError); CHECK_HRESULT(hr); break; } } }
//
// Create the security descriptor.
//
// Possibly adjust the array size to account for two special cases:
// 1. If this job is an AT job, only local system and administrators
// are to have access; don't grant users access. This case
// also encompasses case (2).
// 2. The owner sid and the domain administrator SID will be equal
// if the user is an admin. If the user is an admin, ignore the
// administrator setting.
//
DWORD ActualTaskAceCount;
if (fIsATTask) { ActualTaskAceCount = TASK_ACE_COUNT - 1; } else if (EqualSid(pOwnerSid, rgDomainSidInfo[0].pSid)) { ActualTaskAceCount = TASK_ACE_COUNT - 1; } else { ActualTaskAceCount = TASK_ACE_COUNT; }
PACCESS_ALLOWED_ACE rgAce[TASK_ACE_COUNT] = { NULL, NULL, NULL // Supply this to CreateSD so we
}; // so we don't have to allocate
// memory.
MYACE rgMyAce[TASK_ACE_COUNT] = { { TASK_ALL, // Acess mask.
NO_PROPAGATE_INHERIT_ACE, // Inherit flags.
rgBaseSidInfo[0].pSid }, // SID.
{ TASK_ALL, NO_PROPAGATE_INHERIT_ACE, rgDomainSidInfo[0].pSid }, { TASK_ALL, NO_PROPAGATE_INHERIT_ACE, pOwnerSid } };
schAssert(TASK_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) && TASK_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
if (FAILED(hr)) { goto CleanExit; }
if ((pSecurityDescriptor = CreateSecurityDescriptor(ActualTaskAceCount, rgMyAce, rgAce, &Status)) == NULL) { hr = HRESULT_FROM_WIN32(Status); goto CleanExit; }
//
// Finally, set permissions.
//
if (!SetFileSecurity(pwszTaskPath, si, pSecurityDescriptor)) { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); goto CleanExit; }
CleanExit: delete pOwnerSid; for (i = 0; i < BASE_SID_COUNT; i++) { if (rgBaseSidInfo[i].pSid != NULL) { FreeSid(rgBaseSidInfo[i].pSid); } } for (i = 0; i < DOMAIN_SID_COUNT; i++) { if (rgDomainSidInfo[i].pSid != NULL) { delete rgDomainSidInfo[i].pSid; } } if (pSecurityDescriptor != NULL) { DeleteSecurityDescriptor(pSecurityDescriptor); }
return(hr); }
//+---------------------------------------------------------------------------
//
// Function: AllocateAndInitializeDomainSid
//
// Synopsis:
//
// Arguments: [pDomainSid] --
// [pDomainSidInfo] --
//
// Notes: None.
//
//----------------------------------------------------------------------------
DWORD AllocateAndInitializeDomainSid( PSID pDomainSid, MYSIDINFO * pDomainSidInfo) { UCHAR DomainIdSubAuthorityCount; DWORD SidLength;
//
// Allocate a Sid which has one more sub-authority than the domain ID.
//
DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount(pDomainSid)); SidLength = GetSidLengthRequired(DomainIdSubAuthorityCount + 1);
pDomainSidInfo->pSid = new BYTE[SidLength];
if (pDomainSidInfo->pSid == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return(ERROR_NOT_ENOUGH_MEMORY); }
//
// Initialize the new SID to have the same inital value as the
// domain ID.
//
if (!CopySid(SidLength, pDomainSidInfo->pSid, pDomainSid)) { delete pDomainSidInfo->pSid; pDomainSidInfo->pSid = NULL; CHECK_HRESULT(HRESULT_FROM_WIN32(GetLastError())); return(GetLastError()); }
//
// Adjust the sub-authority count and add the relative Id unique
// to the newly allocated SID
//
(*(GetSidSubAuthorityCount(pDomainSidInfo->pSid)))++; *(GetSidSubAuthority(pDomainSidInfo->pSid, DomainIdSubAuthorityCount)) = pDomainSidInfo->dwSubAuthority;
return(ERROR_SUCCESS); }
//+---------------------------------------------------------------------------
//
// Function: GetFileOwnerSid
//
// Synopsis:
//
// Arguments: [pwszFileName] --
// [ppSid] --
//
// Notes: None.
//
//----------------------------------------------------------------------------
HRESULT GetFileOwnerSid(LPCWSTR pwszFileName, PSID * ppSid) { DWORD cbSizeNeeded;
//
// Retrieve the file owner. Call GetFileSecurity twice - first to get
// the buffer size, then the actual information retrieval.
//
if (GetFileSecurity(pwszFileName, OWNER_SECURITY_INFORMATION, NULL, 0, &cbSizeNeeded)) { //
// Didn't expect this to succeed!
//
CHECK_HRESULT(E_UNEXPECTED); return(E_UNEXPECTED); }
DWORD Status = GetLastError(); PSECURITY_DESCRIPTOR pOwnerSecDescr = NULL; HRESULT hr = S_OK;
if ((Status == ERROR_INSUFFICIENT_BUFFER) && (cbSizeNeeded > 0)) { //
// Allocate the buffer space necessary and retrieve the info.
//
pOwnerSecDescr = (SECURITY_DESCRIPTOR *)new BYTE[cbSizeNeeded];
if (pOwnerSecDescr == NULL) { CHECK_HRESULT(E_OUTOFMEMORY); return(E_OUTOFMEMORY); }
if (!GetFileSecurity(pwszFileName, OWNER_SECURITY_INFORMATION, pOwnerSecDescr, cbSizeNeeded, &cbSizeNeeded)) { delete pOwnerSecDescr; hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); return(hr); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); return(hr); }
//
// Retrieve & validate the owner sid.
//
// NB : After this, pOwnerSid will point into the security descriptor,
// pOwnerSecDescr; hence, the descriptor must exist for the
// lifetime of pOwnerSid.
//
DWORD cbOwnerSid; PSID pOwnerSid; BOOL fOwnerDefaulted;
if (GetSecurityDescriptorOwner(pOwnerSecDescr, &pOwnerSid, &fOwnerDefaulted)) { if (IsValidSid(pOwnerSid)) { *ppSid = new BYTE[cbOwnerSid = GetLengthSid(pOwnerSid)];
if (*ppSid != NULL) { if (!CopySid(cbOwnerSid, *ppSid, pOwnerSid)) { delete *ppSid; *ppSid = NULL; hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); } } else { hr = E_OUTOFMEMORY; CHECK_HRESULT(hr); }
} else { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HRESULT(hr); }
delete pOwnerSecDescr;
return(hr); }
|