Windows-Server-2003/admin/dscmd/secutil.cpp

563 lines
14 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: SecUtil.cpp
//
// Contents: Utility functions for working with security APIs
//
// History: 15-Sep-2000 JeffJon Created
//
//
//--------------------------------------------------------------------------
#include "pch.h"
#include "secutil.h"
extern const GUID GUID_CONTROL_UserChangePassword =
{ 0xab721a53, 0x1e2f, 0x11d0, { 0x98, 0x19, 0x00, 0xaa, 0x00, 0x40, 0x52, 0x9b}};
//+--------------------------------------------------------------------------
//
// Member: CSimpleSecurityDescriptorHolder::CSimpleSecurityDescriptorHolder
//
// Synopsis: Constructor for the smart security descriptor
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
CSimpleSecurityDescriptorHolder::CSimpleSecurityDescriptorHolder()
{
m_pSD = NULL;
}
//+--------------------------------------------------------------------------
//
// Member: CSimpleSecurityDescriptorHolder::~CSimpleSecurityDescriptorHolder
//
// Synopsis: Destructor for the smart security descriptor
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
CSimpleSecurityDescriptorHolder::~CSimpleSecurityDescriptorHolder()
{
if (m_pSD != NULL)
{
::LocalFree(m_pSD);
m_pSD = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::CSidHolder
//
// Synopsis: Constructor : initializes the member data
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
CSidHolder::CSidHolder()
{
_Init();
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::~CSidHolder
//
// Synopsis: Destructor : Frees all data associated with the wrapped SID
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
CSidHolder::~CSidHolder()
{
_Free();
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::Get
//
// Synopsis: Public accessor to the SID being wrapped
//
// Arguments:
//
// Returns: PSID : pointer to the SID being wrapped. NULL if the class
// is not currently wrapping a SID
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
PSID CSidHolder::Get()
{
return m_pSID;
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::Copy
//
// Synopsis: Frees the memory associated with the currently wrapped SID
// and then copies the new SID
//
// Arguments: [p - IN] : SID to be copied
//
// Returns: bool : true if the copy was successful, false otherwise
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
bool CSidHolder::Copy(PSID p)
{
_Free();
return _Copy(p);
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::Attach
//
// Synopsis: Attaches the SID to the wrapper
//
// Arguments: [p - IN] : SID to be wrapped by this class
// [bLocalAlloc - OUT] : tells whether the SID should be freed
// with LocalFree
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CSidHolder::Attach(PSID p, bool bLocalAlloc)
{
_Free();
m_pSID = p;
m_bLocalAlloc = bLocalAlloc;
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::Clear
//
// Synopsis: Frees the memory associated with the SID being wrapped
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CSidHolder::Clear()
{
_Free();
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::_Init
//
// Synopsis: Initializes the member data to default values
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CSidHolder::_Init()
{
m_pSID = NULL;
m_bLocalAlloc = TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::_Free
//
// Synopsis: Frees the memory associated with the SID being wrapped
//
// Arguments:
//
// Returns:
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
void CSidHolder::_Free()
{
if (m_pSID != NULL)
{
if (m_bLocalAlloc)
{
::LocalFree(m_pSID);
}
else
{
::FreeSid(m_pSID);
_Init();
}
}
}
//+--------------------------------------------------------------------------
//
// Member: CSidHolder::_Copy
//
// Synopsis: Makes a copy of the SID being wrapped
//
// Arguments: [p - OUT] : destination of the SID being copied
//
// Returns: bool : true if SID was copied successfully
// false if there was a failure
//
// History: 15-Sep-2000 JeffJon Created
//
//---------------------------------------------------------------------------
bool CSidHolder::_Copy(PSID p)
{
if ( (p == NULL) || !::IsValidSid(p) )
{
return false;
}
DWORD dwLen = ::GetLengthSid(p);
PSID pNew = ::LocalAlloc(LPTR, dwLen);
if (pNew == NULL)
{
return false;
}
//Security Review:This is fine. Buffer is correctly allocated.
if (!::CopySid(dwLen, pNew, p))
{
::LocalFree(pNew);
return false;
}
m_bLocalAlloc = TRUE;
m_pSID = pNew;
ASSERT(dwLen == ::GetLengthSid(m_pSID));
ASSERT(memcmp(p, m_pSID, dwLen) == 0);
return true;
}
//+---------------------------------------------------------------------------
//
// Function: SetSecurityInfoMask
//
// Synopsis: Reads the security descriptor from the specied DS object
//
// Arguments: [IN punk] -- IUnknown from IDirectoryObject
// [IN si] -- SecurityInformation
//// History: 25-Dec-2000 -- Hiteshr Created
//----------------------------------------------------------------------------
HRESULT
SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
{
HRESULT hr = E_INVALIDARG;
if (punk)
{
IADsObjectOptions *pOptions;
hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
if (SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
V_VT(&var) = VT_I4;
V_I4(&var) = si;
hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
pOptions->Release();
}
}
return hr;
}
WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
//+---------------------------------------------------------------------------
//
// Function: DSReadObjectSecurity
//
// Synopsis: Reads the Dacl from the specied DS object
//
// Arguments: [in pDsObject] -- IDirettoryObject for dsobject
// [psdControl] -- Control Setting for SD
// They can be returned when calling
// DSWriteObjectSecurity
// [OUT ppDacl] -- DACL returned here
//
//
// History 25-Oct-2000 -- hiteshr created
//
// Notes: If Object Doesn't have DACL, function will succeed but *ppDacl will
// be NULL.
// Caller must free *ppDacl, if not NULL, by calling LocalFree
//
//----------------------------------------------------------------------------
HRESULT
DSReadObjectSecurity(IN IDirectoryObject *pDsObject,
OUT SECURITY_DESCRIPTOR_CONTROL * psdControl,
OUT PACL *ppDacl)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSReadObjectSecurity, hr);
PADS_ATTR_INFO pSDAttributeInfo = NULL;
do // false loop
{
LPWSTR pszSDProperty = (LPWSTR)c_szSDProperty;
DWORD dwAttributesReturned;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pAcl = NULL;
if(!pDsObject || !ppDacl)
{
ASSERT(FALSE);
hr = E_INVALIDARG;
break;
}
*ppDacl = NULL;
// Set the SECURITY_INFORMATION mask
hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
if(FAILED(hr))
{
break;
}
//
// Read the security descriptor
//
hr = pDsObject->GetObjectAttributes(&pszSDProperty,
1,
&pSDAttributeInfo,
&dwAttributesReturned);
if (SUCCEEDED(hr) && !pSDAttributeInfo)
hr = E_ACCESSDENIED; // This happens for SACL if no SecurityPrivilege
if(FAILED(hr))
{
break;
}
ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType);
ASSERT(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType);
pSD = (PSECURITY_DESCRIPTOR)pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue;
ASSERT(IsValidSecurityDescriptor(pSD));
//
//Get the security descriptor control
//
if(psdControl)
{
DWORD dwRevision;
if(!GetSecurityDescriptorControl(pSD, psdControl, &dwRevision))
{
DWORD _dwErr = GetLastError();
hr = HRESULT_FROM_WIN32( _dwErr );
break;
}
}
//
//Get pointer to DACL
//
BOOL bDaclPresent, bDaclDefaulted;
if(!GetSecurityDescriptorDacl(pSD,
&bDaclPresent,
&pAcl,
&bDaclDefaulted))
{
DWORD _dwErr = GetLastError();
hr = HRESULT_FROM_WIN32( _dwErr );
break;
}
if(!bDaclPresent ||
!pAcl)
{
break;
}
ASSERT(IsValidAcl(pAcl));
//
//Make a copy of the DACL
//
*ppDacl = (PACL)LocalAlloc(LPTR,pAcl->AclSize);
if(!*ppDacl)
{
hr = E_OUTOFMEMORY;
break;
}
//Security Review:This is fine. Memory is correctly allocted above.
CopyMemory(*ppDacl,pAcl,pAcl->AclSize);
}while(0);
if (pSDAttributeInfo)
FreeADsMem(pSDAttributeInfo);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: DSWriteObjectSecurity
//
// Synopsis: Writes the Dacl to the specied DS object
//
// Arguments: [in pDsObject] -- IDirettoryObject for dsobject
// [sdControl] -- control for security descriptor
// [IN pDacl] -- The DACL to be written
//
// History 25-Oct-2000 -- hiteshr created
//----------------------------------------------------------------------------
HRESULT
DSWriteObjectSecurity(IN IDirectoryObject *pDsObject,
IN SECURITY_DESCRIPTOR_CONTROL sdControl,
PACL pDacl)
{
ENTER_FUNCTION_HR(LEVEL5_LOGGING, DSWriteObjectSecurity, hr);
PISECURITY_DESCRIPTOR pSD = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
do // false loop
{
ADSVALUE attributeValue;
ADS_ATTR_INFO attributeInfo;
DWORD dwAttributesModified;
DWORD dwSDLength;
if(!pDsObject || !pDacl)
{
ASSERT(FALSE);
hr = E_INVALIDARG;
break;
}
ASSERT(IsValidAcl(pDacl));
// Set the SECURITY_INFORMATION mask
hr = SetSecurityInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
if(FAILED(hr))
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"SetSecurityInfoMask failed: hr = 0x%x",
hr);
break;
}
//
//Build the Security Descriptor
//
pSD = (PISECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (pSD == NULL)
{
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"Failed to allocate memory for Security Descriptor");
hr = E_OUTOFMEMORY;
break;
}
//Security Review:This is fine.
InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
//
// Finally, build the security descriptor
//
pSD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ
| (sdControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
if(pDacl->AclSize)
{
pSD->Dacl = pDacl;
}
//
// Need the total size
//
dwSDLength = GetSecurityDescriptorLength(pSD);
//
// If necessary, make a self-relative copy of the security descriptor
//
psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
if (psd == NULL ||
!MakeSelfRelativeSD(pSD, psd, &dwSDLength))
{
DWORD _dwErr = GetLastError();
hr = HRESULT_FROM_WIN32( _dwErr );
DEBUG_OUTPUT(MINIMAL_LOGGING,
L"MakeSelfRelativeSD failed: hr = 0x%x",
hr);
break;
}
attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
attributeValue.SecurityDescriptor.dwLength = dwSDLength;
attributeValue.SecurityDescriptor.lpValue = (LPBYTE)psd;
attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
attributeInfo.pADsValues = &attributeValue;
attributeInfo.dwNumValues = 1;
// Write the security descriptor
hr = pDsObject->SetObjectAttributes(&attributeInfo,
1,
&dwAttributesModified);
} while (false);
if (psd != NULL)
{
LocalFree(psd);
}
if(pSD != NULL)
{
LocalFree(pSD);
}
return hr;
}