|
|
/*++
Copyright (c) 1995-1999 Microsoft Corporation
Module Name:
rndsec.cpp
Abstract:
Security utilities for Rendezvous Control.
Author:
KrishnaG (from OLEDS team)
Environment:
User Mode - Win32
Revision History:
12-Dec-1997 DonRyan Munged KrishnaG's code to work with Rendezvous Control.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <security.h>
#include <initguid.h>
#include <iads.h>
#include <ntlsa.h>
#include <stdlib.h>
#include <limits.h>
#include <io.h>
#include <wchar.h>
#include <tchar.h>
#include "rndsec.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Private macros //
// //
///////////////////////////////////////////////////////////////////////////////
#define BAIL_ON_FAILURE(hr) \
if (FAILED(hr)) { goto error; }
#define CONTINUE_ON_FAILURE(hr) \
if (FAILED(hr)) { continue; }
///////////////////////////////////////////////////////////////////////////////
// //
// Private procedures //
// //
///////////////////////////////////////////////////////////////////////////////
LPWSTR AllocADsStr( LPWSTR pStr ) { LPWSTR pMem;
if (!pStr) return NULL;
if (pMem = new WCHAR[wcslen(pStr) + 1]) wcscpy(pMem, pStr);
return pMem; }
HRESULT ConvertSidToString( PSID pSid, LPWSTR String )
/*++
Routine Description:
This function generates a printable unicode string representation of a SID.
The resulting string will take one of two forms. If the IdentifierAuthority value is not greater than 2^32, then the SID will be in the form:
S-1-281736-12-72-9-110 ^ ^^ ^^ ^ ^^^ | | | | | +-----+--+-+--+---- Decimal
Otherwise it will take the form:
S-1-0x173495281736-12-72-9-110 ^^^^^^^^^^^^^^ ^^ ^^ ^ ^^^ Hexidecimal | | | | +--+-+--+---- Decimal
Arguments:
pSid - opaque pointer that supplies the SID that is to be converted to Unicode.
Return Value:
If the Sid is successfully converted to a Unicode string, a pointer to the Unicode string is returned, else NULL is returned.
--*/
{ WCHAR Buffer[256]; UCHAR i; ULONG Tmp; HRESULT hr = S_OK;
SID_IDENTIFIER_AUTHORITY *pSidIdentifierAuthority; PUCHAR pSidSubAuthorityCount;
//
// IsValidSid fiers an AV is pSid == NULL
//
if( NULL == pSid ) { *String= L'\0'; hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); return(hr); }
if (!IsValidSid( pSid )) { *String= L'\0'; hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); return(hr); }
wsprintf(Buffer, L"S-%u-", (USHORT)(((PISID)pSid)->Revision )); wcscpy(String, Buffer);
pSidIdentifierAuthority = GetSidIdentifierAuthority(pSid);
if ( (pSidIdentifierAuthority->Value[0] != 0) || (pSidIdentifierAuthority->Value[1] != 0) ){ wsprintf(Buffer, L"0x%02hx%02hx%02hx%02hx%02hx%02hx", (USHORT)pSidIdentifierAuthority->Value[0], (USHORT)pSidIdentifierAuthority->Value[1], (USHORT)pSidIdentifierAuthority->Value[2], (USHORT)pSidIdentifierAuthority->Value[3], (USHORT)pSidIdentifierAuthority->Value[4], (USHORT)pSidIdentifierAuthority->Value[5] ); wcscat(String, Buffer);
} else {
Tmp = (ULONG)pSidIdentifierAuthority->Value[5] + (ULONG)(pSidIdentifierAuthority->Value[4] << 8) + (ULONG)(pSidIdentifierAuthority->Value[3] << 16) + (ULONG)(pSidIdentifierAuthority->Value[2] << 24); wsprintf(Buffer, L"%lu", Tmp); wcscat(String, Buffer); }
pSidSubAuthorityCount = GetSidSubAuthorityCount(pSid);
for (i=0;i< *(pSidSubAuthorityCount);i++ ) { wsprintf(Buffer, L"-%lu", *(GetSidSubAuthority(pSid, i))); wcscat(String, Buffer); }
return(S_OK); }
HRESULT ConvertSidToFriendlyName( PSID pSid, LPWSTR * ppszAccountName ) { HRESULT hr = S_OK; SID_NAME_USE eUse; WCHAR szAccountName[MAX_PATH]; WCHAR szDomainName[MAX_PATH]; DWORD dwLen = 0; DWORD dwRet = 0;
LPWSTR pszAccountName = NULL;
DWORD dwAcctLen = 0; DWORD dwDomainLen = 0; dwAcctLen = sizeof(szAccountName); dwDomainLen = sizeof(szDomainName);
dwRet = LookupAccountSid( NULL, pSid, szAccountName, &dwAcctLen, szDomainName, &dwDomainLen, (PSID_NAME_USE)&eUse ); if (!dwRet) {
hr = ConvertSidToString( pSid, szAccountName ); BAIL_ON_FAILURE(hr);
pszAccountName = AllocADsStr(szAccountName); if (!pszAccountName) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
*ppszAccountName = pszAccountName;
}else {
dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
pszAccountName = new WCHAR [dwLen]; if (!pszAccountName) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
if (szDomainName[0] && szAccountName[0]) { wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName); }else if (szAccountName[0]) { wsprintf(pszAccountName,L"%s", szAccountName); }
*ppszAccountName = pszAccountName;
}
error:
return(hr); }
//
// Converts an ACE to a variant, but leaves the trustee name unset.
// Instead it returns a pointer to the SID in this ACE, so that
// we can go back and convert all the SIDs to trustee names at once
// and set them on the ACEs later.
//
HRESULT ConvertAceToVariant( PBYTE pAce, LPVARIANT pvarAce, PSID * ppSid ) { IADsAccessControlEntry * pAccessControlEntry = NULL; IDispatch * pDispatch = NULL;
DWORD dwAceType = 0; DWORD dwAceFlags = 0; DWORD dwAccessMask = 0; PACE_HEADER pAceHeader = NULL; LPBYTE pSidAddress = NULL; LPBYTE pOffset = NULL; DWORD dwFlags = 0;
GUID ObjectGUID; GUID InheritedObjectGUID; WCHAR szObjectGUID[MAX_PATH]; WCHAR szInheritedObjectGUID[MAX_PATH];
HRESULT hr = S_OK;
szObjectGUID[0] = L'\0'; szInheritedObjectGUID[0] = L'\0';
VariantInit(pvarAce);
hr = CoCreateInstance( CLSID_AccessControlEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlEntry, (void **)&pAccessControlEntry ); BAIL_ON_FAILURE(hr);
pAceHeader = (ACE_HEADER *)pAce;
dwAceType = pAceHeader->AceType; dwAceFlags = pAceHeader->AceFlags; dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
switch (dwAceType) {
case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_DENIED_ACE_TYPE: case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_ALARM_ACE_TYPE: pSidAddress = (LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: case SYSTEM_ALARM_OBJECT_ACE_TYPE: pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK)); dwFlags = (DWORD)(*(PDWORD)pOffset);
//
// Now advance by the size of the flags
//
pOffset += sizeof(ULONG);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
memcpy(&ObjectGUID, pOffset, sizeof(GUID));
StringFromGUID2(ObjectGUID, szObjectGUID, MAX_PATH);
pOffset += sizeof (GUID);
}
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { memcpy(&InheritedObjectGUID, pOffset, sizeof(GUID));
StringFromGUID2(InheritedObjectGUID, szInheritedObjectGUID, MAX_PATH);
pOffset += sizeof (GUID);
}
pSidAddress = pOffset; break;
default: break;
}
//
// return a pointer to the SID for this ACE, rather than converting the
// SID to a trustee name (and taking forever for a large ACL)
//
*ppSid = (PSID) pSidAddress;
//
// Now set all the information in the Access Control Entry
//
hr = pAccessControlEntry->put_AccessMask(dwAccessMask); hr = pAccessControlEntry->put_AceFlags(dwAceFlags); hr = pAccessControlEntry->put_AceType(dwAceType);
//
// Extended ACE information
//
hr = pAccessControlEntry->put_Flags(dwFlags);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
//
// Add in the Object Type GUID
//
hr = pAccessControlEntry->put_ObjectType(szObjectGUID);
}
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
//
// Add in the Inherited Object Type GUID
//
hr = pAccessControlEntry->put_InheritedObjectType(szInheritedObjectGUID);
}
hr = pAccessControlEntry->QueryInterface( IID_IDispatch, (void **)&pDispatch ); BAIL_ON_FAILURE(hr);
V_DISPATCH(pvarAce) = pDispatch; V_VT(pvarAce) = VT_DISPATCH;
cleanup:
if (pAccessControlEntry) {
pAccessControlEntry->Release(); }
return(hr);
error:
if (pDispatch) {
pDispatch->Release();
}
goto cleanup; }
BOOL APIENTRY LookupArrayOfSids( DWORD dwCount, PSID * ppSids, LSA_REFERENCED_DOMAIN_LIST ** ppDomains, LSA_TRANSLATED_NAME ** ppTrustees ) {
PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains; PLSA_TRANSLATED_NAME Names;
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle;
NTSTATUS Status; NTSTATUS TmpStatus;
SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation; SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; SecurityQualityOfService.EffectiveOnly = FALSE;
//
// Set up the object attributes prior to opening the LSA.
//
InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );
//
// The InitializeObjectAttributes macro presently stores NULL for
// the SecurityQualityOfService field, so we must manually copy that
// structure for now.
//
ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
Status = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle );
if ( !NT_SUCCESS( Status )) {
// BaseSetLastNTError( Status );
return( FALSE ); }
Status = LsaLookupSids( PolicyHandle, dwCount, ppSids, ppDomains, ppTrustees );
TmpStatus = LsaClose( PolicyHandle );
//
// If an error was returned, check specifically for STATUS_NONE_MAPPED.
// In this case, we may need to dispose of the returned Referenced Domain
// List and Names structures. For all other errors, LsaLookupSids()
// frees these structures prior to exit.
//
if ( !NT_SUCCESS( Status )) { if (Status == STATUS_NONE_MAPPED) {
if ( *ppDomains != NULL) {
TmpStatus = LsaFreeMemory( *ppDomains ); _ASSERTE( NT_SUCCESS( TmpStatus )); *ppDomains = NULL; }
if ( *ppTrustees != NULL) {
TmpStatus = LsaFreeMemory( *ppTrustees ); _ASSERTE( NT_SUCCESS( TmpStatus )); *ppTrustees = NULL; } }
// BaseSetLastNTError( Status );
return( FALSE ); }
//
// The Sids were successfully translated.
//
return TRUE; }
//
// ZoltanS
//
HRESULT SetTrusteeOnACE( VARIANT * pVarAce, PLSA_REFERENCED_DOMAIN_LIST pDomains, PLSA_TRANSLATED_NAME pName ) { //
// Make sure pName is valid
//
if ((pName->Use == SidTypeInvalid) || (pName->Use == SidTypeUnknown)) { return E_INVALIDARG; }
//
// Find the domain and account names.
//
DWORD dwAccountNameSize = pName->Name.Length / 2; WCHAR * szAccountName = pName->Name.Buffer;
DWORD dwDomainNameSize = (pDomains->Domains + pName->DomainIndex)->Name.Length / 2; WCHAR * szDomainName = (pDomains->Domains + pName->DomainIndex)->Name.Buffer;
//
// Allocate space for the compound name
//
DWORD dwLen = dwAccountNameSize + dwDomainNameSize + 1 + 1; if( (dwLen <= dwAccountNameSize) || (dwLen<=dwDomainNameSize) ) { return E_FAIL; }
WCHAR * pszAccountName = new WCHAR [dwLen];
if (!pszAccountName) { return E_OUTOFMEMORY; }
//
// Copy in the domain and user name
// to get the trustee name
//
if ( dwDomainNameSize != 0 ) { // strange +1 needed because it will also put in a NULL terminator
lstrcpynW(pszAccountName, szDomainName, dwDomainNameSize+1);
lstrcatW(pszAccountName, L"\\"); } else { pszAccountName[0] = L'\0'; }
wcsncat(pszAccountName, szAccountName, dwAccountNameSize);
//
// Set the trustee name on the ACE
//
IDispatch * pDispatch = V_DISPATCH(pVarAce);
IADsAccessControlEntry * pACE;
HRESULT hr;
hr = pDispatch->QueryInterface(IID_IADsAccessControlEntry, (void **) & pACE);
hr = pACE->put_Trustee(pszAccountName);
pACE->Release();
delete [] pszAccountName;
return hr; }
//
// ZoltanS optimized version of ConvertACLToVariant
//
HRESULT ConvertACLToVariant( PACL pACL, LPVARIANT pvarACL ) { IADsAccessControlList * pAccessControlList = NULL; IDispatch * pDispatch = NULL;
DWORD dwAclSize = 0; DWORD dwAclRevision = 0; DWORD dwAceCount = 0;
ACL_SIZE_INFORMATION AclSize; ACL_REVISION_INFORMATION AclRevision; DWORD dwStatus = 0;
DWORD i = 0; DWORD dwNewAceCount = 0;
HRESULT hr = S_OK; LPBYTE pAceAddress = NULL;
memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION)); memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
dwStatus = GetAclInformation( pACL, &AclSize, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation );
dwStatus = GetAclInformation( pACL, &AclRevision, sizeof(ACL_REVISION_INFORMATION), AclRevisionInformation );
dwAceCount = AclSize.AceCount; dwAclRevision = AclRevision.AclRevision;
VariantInit(pvarACL);
hr = CoCreateInstance( CLSID_AccessControlList, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlList, (void **)&pAccessControlList );
if ( FAILED(hr) ) { return hr; }
PSID * apSids = new PSID[ dwAceCount ];
if ( apSids == NULL ) { pAccessControlList->Release(); return E_OUTOFMEMORY; }
VARIANT * aVarAces = new VARIANT[ dwAceCount ];
if ( aVarAces == NULL ) { pAccessControlList->Release(); delete apSids; return E_OUTOFMEMORY; }
for (i = 0; i < dwAceCount; i++) { dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
hr = ConvertAceToVariant( pAceAddress, aVarAces + i, apSids + i ); }
//
// Above, ConvertAceToVariant did not set the trustee names on the ACEs.
// Instead we have an array (apSids) of dwNewAceCount valid PSIDs.
// Convert all of these to trustees now.
//
PLSA_REFERENCED_DOMAIN_LIST pDomains = NULL; PLSA_TRANSLATED_NAME pTrustees = NULL;
BOOL fStatus = LookupArrayOfSids( dwAceCount, // IN count
apSids, // IN array of sid pointers
&pDomains, // OUT referenced domain list
&pTrustees); // OUT translated name list
delete apSids;
if ( fStatus == FALSE ) { // LookupArrayOfSids failed
hr = E_FAIL; } else { //
// Set the trustees on the ACEs here
//
for ( i = 0; i < dwAceCount; i++ ) { VARIANT * pVarAce = aVarAces + i;
hr = SetTrusteeOnACE( pVarAce, pDomains, pTrustees + i );
hr = pAccessControlList->AddAce( V_DISPATCH ( pVarAce ) ); VariantClear( pVarAce );
if ( SUCCEEDED(hr) ) { dwNewAceCount++; }
}
//
// Free output buffers returned by LsaLookupSids
//
DWORD Status;
Status = LsaFreeMemory( pTrustees ); _ASSERTE( NT_SUCCESS( Status ));
Status = LsaFreeMemory( pDomains ); _ASSERTE( NT_SUCCESS( Status ));
pAccessControlList->put_AclRevision(dwAclRevision);
pAccessControlList->put_AceCount(dwNewAceCount);
hr = pAccessControlList->QueryInterface( IID_IDispatch, (void **)&pDispatch ); V_VT(pvarACL) = VT_DISPATCH; V_DISPATCH(pvarACL) = pDispatch; }
pAccessControlList->Release();
//
// aVarAces was dynamic allocated
// aVarAces should be deallocated
//
delete aVarAces;
return(hr); }
HRESULT SecCreateSidFromArray ( OUT PSID *PPSid, IN PSID_IDENTIFIER_AUTHORITY PSidAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthorities[], OUT PDWORD pdwSidSize ) /*++
Routine Description:
Creates a SID with desired authority and sub authorities.
NOTE: This routine allocates memory for the SID. When finished the caller should free memory using SEC_FREE (PSid).
Arguments:
PPSid -- addr of ptr to SID to be created Note: if SID creation fails ptr set to NULL
PSidAuthority -- desired value for SID authority
SubAuthorityCount -- number of sub authorities desired
SubAuthorities -- sub-authority values, MUST SPECIFY contain at least SubAuthorityCount number of values
Return Value:
STATUS_SUCCESS if SID created. STATUS_UNSUCCESSFUL otherwise.
--*/ { USHORT iSub; /* sub-authority index */ DWORD dwSidSize = 0; HRESULT hr = S_OK;
/* allocate memory for SID */
dwSidSize = RtlLengthRequiredSid(SubAuthorityCount); *PPSid = (PSID) new BYTE[dwSidSize]; if (! *PPSid){ hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
*pdwSidSize = dwSidSize;
/* initialize SID with top level SID identifier authority */ RtlInitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
/* fill in sub authorities */ for (iSub=0; iSub < SubAuthorityCount; iSub++) * RtlSubAuthoritySid( *PPSid, iSub) = SubAuthorities[iSub];
/* sanity check */
if ( ! RtlValidSid( *PPSid) ) { delete (*PPSid); *PPSid = NULL; hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); BAIL_ON_FAILURE(hr); }
error:
return(hr); }
HRESULT ConvertStringToSid( IN PWSTR string, OUT PSID *sid, OUT PDWORD pdwSidSize, OUT PWSTR *end ) { HRESULT hr = S_OK; UCHAR revision; UCHAR sub_authority_count; SID_IDENTIFIER_AUTHORITY authority; ULONG sub_authority[SID_MAX_SUB_AUTHORITIES]; PWSTR end_list; PWSTR current; PWSTR next; ULONG x;
*sid = NULL;
if ( string == NULL ) { return E_POINTER; }
if (((*string != L'S') && (*string != L's')) || (*(string + 1) != L'-')) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); BAIL_ON_FAILURE(hr); }
current = string + 2;
revision = (UCHAR)wcstol(current, &end_list, 10);
current = end_list + 1;
//
// Count the number of characters in the indentifer authority...
//
next = wcschr(current, L'-');
if((next != NULL) && (next - current == 6)) { for(x = 0; x < 6; x++) { authority.Value[x] = (UCHAR)next[x]; }
current +=6; } else { ULONG Auto = wcstoul(current, &end_list, 10); authority.Value[0] = authority.Value[1] = 0; authority.Value[5] = (UCHAR)Auto & 0xF; authority.Value[4] = (UCHAR)((Auto >> 8) & 0xFF); authority.Value[3] = (UCHAR)((Auto >> 16) & 0xFF); authority.Value[2] = (UCHAR)((Auto >> 24) & 0xFF); current = end_list; }
//
// Now, count the number of sub auths
//
sub_authority_count = 0;
//
// Initialize sub_authority array
//
memset( sub_authority, 0, sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES );
next = current;
//
// We'll have to count our sub authoritys one character at a time,
// since there are several deliminators that we can have...
//
while(next) { next++;
if(*next == L'-') { //
// We've found one!
//
sub_authority_count++; } else if(*next == L';' || *next == L'\0') { *end = next; sub_authority_count++; break; } }
if(sub_authority_count != 0) { current++;
for(x = 0; x < sub_authority_count; x++) { sub_authority[x] = wcstoul(current, &end_list, 10); current = end_list + 1; } }
//
// Now, create the SID
//
hr = SecCreateSidFromArray( sid, &authority, sub_authority_count, sub_authority, pdwSidSize );
if (SUCCEEDED(hr)) { /* Set the revision to what was specified in the string, in case, our
system creates one with newer revision */
((SID *)(*sid))->Revision = revision; }
error:
return(hr); }
HRESULT ConvertTrusteeToSid( BSTR bstrTrustee, PSID * ppSid, PDWORD pdwSidSize ) { HRESULT hr = S_OK; BYTE Sid[MAX_PATH]; ZeroMemory(Sid, MAX_PATH*sizeof(BYTE)); DWORD dwSidSize = sizeof(Sid); DWORD dwRet = 0; WCHAR szDomainName[MAX_PATH]; DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR); SID_NAME_USE eUse;
PSID pSid = NULL; LPWSTR pszEnd = NULL; BOOL fNTDSType = FALSE;
dwSidSize = sizeof(Sid);
dwRet = LookupAccountName( NULL, bstrTrustee, Sid, &dwSidSize, szDomainName, &dwDomainSize, (PSID_NAME_USE)&eUse ); if (!dwRet) { hr = HRESULT_FROM_WIN32(GetLastError()); }
//
// If neither the NTDS nor the U2 conversion
// worked, then try a textual translation
//
if (FAILED(hr)) {
hr = ConvertStringToSid( bstrTrustee, &pSid, &dwSidSize, &pszEnd ); BAIL_ON_FAILURE(hr);
memcpy(Sid,pSid, dwSidSize);
if (pSid) { delete pSid; }
}
pSid = (PSID) new BYTE[dwSidSize]; if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
memcpy(pSid, Sid, dwSidSize);
*pdwSidSize = dwSidSize;
*ppSid = pSid;
error:
return(hr); }
HRESULT GetOwnerSecurityIdentifier( IADsSecurityDescriptor FAR * pSecDes, PSID * ppSid, PBOOL pfOwnerDefaulted ) { BSTR bstrOwner = NULL; DWORD dwSidSize = 0; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_Owner( &bstrOwner ); BAIL_ON_FAILURE(hr);
hr = pSecDes->get_OwnerDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) {
if (bstrOwner && *bstrOwner) {
hr = ConvertTrusteeToSid( bstrOwner, ppSid, &dwSidSize ); BAIL_ON_FAILURE(hr); *pfOwnerDefaulted = FALSE; }else {
*ppSid = NULL; *pfOwnerDefaulted = FALSE; }
}else { *ppSid = NULL; dwSidSize = 0; *pfOwnerDefaulted = TRUE; }
error:
if (bstrOwner) { SysFreeString(bstrOwner); }
return(hr); }
HRESULT ComputeTotalAclSize( PACE_HEADER * ppAceHdr, DWORD dwAceCount, PDWORD pdwAclSize ) { DWORD i = 0; PACE_HEADER pAceHdr = NULL; DWORD dwAceSize = 0; DWORD dwAclSize = 0;
for (i = 0; i < dwAceCount; i++) {
pAceHdr = *(ppAceHdr + i); dwAceSize = pAceHdr->AceSize; dwAclSize += dwAceSize; }
dwAclSize += sizeof(ACL);
*pdwAclSize = dwAclSize;
return(S_OK);
}
HRESULT ConvertAccessControlEntryToAce( IADsAccessControlEntry * pAccessControlEntry, LPBYTE * ppAce ) {
DWORD dwAceType = 0; HRESULT hr = S_OK; BSTR bstrTrustee = NULL; PSID pSid = NULL; DWORD dwSidSize = 0;
DWORD dwAceFlags = 0; DWORD dwAccessMask = 0; DWORD dwAceSize = 0; LPBYTE pAce = NULL; PACCESS_MASK pAccessMask = NULL; PSID pSidAddress = NULL;
PUSHORT pCompoundAceType = NULL; DWORD dwCompoundAceType = 0;
PACE_HEADER pAceHeader = NULL;
LPBYTE pOffset = NULL;
BSTR bstrObjectTypeClsid = NULL; BSTR bstrInheritedObjectTypeClsid = NULL;
GUID ObjectTypeGUID; GUID InheritedObjectTypeGUID; PULONG pFlags; DWORD dwFlags = 0;
hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_Trustee(&bstrTrustee); BAIL_ON_FAILURE(hr);
hr = ConvertTrusteeToSid( bstrTrustee, &pSid, &dwSidSize ); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask); BAIL_ON_FAILURE(hr);
if( pSid ) { PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
if( pSIA ) { SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY; if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0) { // It is an Everyone user
dwAccessMask |= ADS_RIGHT_READ_CONTROL; } } }
//
// we will compensateby adding the entire ACE size
//
dwAceSize = dwSidSize - sizeof(ULONG);
switch (dwAceType) {
case ACCESS_ALLOWED_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_DENIED_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case SYSTEM_AUDIT_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case SYSTEM_ALARM_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK)); *pCompoundAceType = (USHORT)dwCompoundAceType;
//
// Fill in the reserved field here.
//
pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags); BAIL_ON_FAILURE(hr);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) { dwAceSize += sizeof(GUID); }
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { dwAceSize += sizeof(GUID); }
hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid); BAIL_ON_FAILURE(hr);
hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid); BAIL_ON_FAILURE(hr);
hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID); BAIL_ON_FAILURE(hr);
dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE); pAce = new BYTE[dwAceSize]; if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
//
// Fill in Flags
//
pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
pFlags = (PULONG)(pOffset);
*pFlags = dwFlags;
pOffset += sizeof(ULONG);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
pOffset += sizeof(GUID);
}
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
pOffset += sizeof(GUID); }
pSidAddress = (PSID)((LPBYTE)pOffset); memcpy(pSidAddress, pSid, dwSidSize); break;
}
*ppAce = pAce;
error:
if (bstrTrustee) { SysFreeString(bstrTrustee); }
if (pSid) { delete (pSid); }
return(hr); }
HRESULT AddACEEveryone( IADsAccessControlList FAR * pAccessList ) { // Declarations
DWORD dwAceCount = 0; HRESULT hr = S_OK; IUnknown * pUnknown = NULL; IEnumVARIANT * pEnumerator = NULL; DWORD i = 0; DWORD cReturned = 0; VARIANT varAce; BOOL bEveryone = FALSE; IADsAccessControlEntry FAR * pAccessControlEntry = NULL; IDispatch* pACEDispatch = NULL; PSID pSid = NULL; DWORD dwSidSize = 0; BSTR bstrTrustee = NULL;
// Get the ACE count
hr = pAccessList->get_AceCount((long*)&dwAceCount); BAIL_ON_FAILURE(hr);
// Get the ACE enumeration
hr = pAccessList->get__NewEnum( &pUnknown ); BAIL_ON_FAILURE(hr);
hr = pUnknown->QueryInterface( IID_IEnumVARIANT, (void FAR * FAR *)&pEnumerator); BAIL_ON_FAILURE(hr);
// Browse the enumeration
for (i = 0; i < dwAceCount; i++) { VariantInit(&varAce); hr = pEnumerator->Next( 1, &varAce, &cReturned );
CONTINUE_ON_FAILURE(hr);
hr = (V_DISPATCH(&varAce))->QueryInterface( IID_IADsAccessControlEntry, (void **)&pAccessControlEntry ); CONTINUE_ON_FAILURE(hr);
//
// Get the user
//
hr = pAccessControlEntry->get_Trustee(&bstrTrustee); if( FAILED(hr) ) { // Clean-up
VariantClear(&varAce); pAccessControlEntry->Release(); pAccessControlEntry = NULL;
continue; }
//
// Get the SID
//
hr = ConvertTrusteeToSid( bstrTrustee, &pSid, &dwSidSize );
if( FAILED(hr) ) { // Clean-up
if( bstrTrustee ) { SysFreeString( bstrTrustee ); bstrTrustee = NULL; } VariantClear(&varAce); pAccessControlEntry->Release(); pAccessControlEntry = NULL;
continue; }
//
// Validate if is the Everyone SID
//
if( pSid ) { PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
if( pSIA ) { SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY; if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0) { // It is an Everyone user
bEveryone = TRUE;
// Clean-up
VariantClear(&varAce); pAccessControlEntry->Release(); pAccessControlEntry = NULL;
// Break the loop
break; } } } VariantClear(&varAce); if (pAccessControlEntry) { pAccessControlEntry->Release(); pAccessControlEntry = NULL; }
if( bstrTrustee ) { SysFreeString( bstrTrustee ); bstrTrustee = NULL; } }
if( !bEveryone) { // We have to add an everyone entry
hr = CoCreateInstance( CLSID_AccessControlEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlEntry, (void**)&pAccessControlEntry);
BAIL_ON_FAILURE(hr);
// Access mask
hr = pAccessControlEntry->put_AccessMask( ADS_RIGHT_READ_CONTROL ); BAIL_ON_FAILURE(hr);
// Ace type
hr = pAccessControlEntry->put_AceType( 0 ); BAIL_ON_FAILURE(hr);
// Ace flags
hr = pAccessControlEntry->put_AceFlags( 0 ); BAIL_ON_FAILURE(hr);
// Get the SID for everyone
WCHAR Trustee[256]; PSID pSidEveryone = NULL; SID_IDENTIFIER_AUTHORITY siaEveryone = SECURITY_WORLD_SID_AUTHORITY; BOOL bAllocate = AllocateAndInitializeSid( &siaEveryone, 1,0,0,0,0,0,0,0,0, &pSidEveryone); if( !bAllocate ) { BAIL_ON_FAILURE(E_OUTOFMEMORY); } // Get the trustee for everyone
hr = ConvertSidToString( pSidEveryone, Trustee ); FreeSid( pSidEveryone); BAIL_ON_FAILURE(hr); bstrTrustee = SysAllocString( Trustee ); if( bstrTrustee == NULL) { BAIL_ON_FAILURE(E_OUTOFMEMORY); } // Add trustee
hr = pAccessControlEntry->put_Trustee( bstrTrustee ); BAIL_ON_FAILURE(hr);
// Get the IDispatch
hr = pAccessControlEntry->QueryInterface( IID_IDispatch, (void**)&pACEDispatch); BAIL_ON_FAILURE(hr);
// Add ACE to the ACL
hr = pAccessList->AddAce( pACEDispatch ); BAIL_ON_FAILURE(hr); }
error: if (pUnknown) { pUnknown->Release(); }
if (pEnumerator) { pEnumerator->Release(); }
if( pACEDispatch ) { pACEDispatch->Release(); }
if(pAccessControlEntry) { pAccessControlEntry->Release(); }
if( bstrTrustee ) { SysFreeString( bstrTrustee ); }
if (pSid) { delete (pSid); }
return(hr); }
HRESULT ConvertAccessControlListToAcl( IADsAccessControlList FAR * pAccessList, PACL * ppAcl ) { IUnknown * pUnknown = NULL; IEnumVARIANT * pEnumerator = NULL; HRESULT hr = S_OK; DWORD i = 0; DWORD cReturned = 0; VARIANT varAce;
DWORD dwAceCount = 0;
IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
LPBYTE pTempAce = NULL; DWORD dwCount = 0;
PACL pAcl = NULL; DWORD dwAclSize = 0; PACE_HEADER * ppAceHdr = NULL;
DWORD dwRet = 0; DWORD dwAclRevision = 0; DWORD dwStatus = 0; DWORD dwError = 0;
hr = AddACEEveryone( pAccessList ); BAIL_ON_FAILURE(hr);
hr = pAccessList->get_AceCount((long *)&dwAceCount); BAIL_ON_FAILURE(hr);
hr = pAccessList->get__NewEnum( &pUnknown ); BAIL_ON_FAILURE(hr);
hr = pUnknown->QueryInterface( IID_IEnumVARIANT, (void FAR * FAR *)&pEnumerator ); BAIL_ON_FAILURE(hr);
ppAceHdr = new PACE_HEADER [dwAceCount]; if (!ppAceHdr) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
for (i = 0; i < dwAceCount; i++) {
VariantInit(&varAce);
hr = pEnumerator->Next( 1, &varAce, &cReturned );
CONTINUE_ON_FAILURE(hr);
hr = (V_DISPATCH(&varAce))->QueryInterface( IID_IADsAccessControlEntry, (void **)&pAccessControlEntry ); CONTINUE_ON_FAILURE(hr);
hr = ConvertAccessControlEntryToAce( pAccessControlEntry, &(pTempAce) );
// ZoltanS: Rather than CONTINUE_ON_FAILURE, let's bail so that we
// know if the Ace we set is invalid.
BAIL_ON_FAILURE(hr);
*(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
VariantClear(&varAce); if (pAccessControlEntry) { pAccessControlEntry->Release(); pAccessControlEntry = NULL; }
dwCount++; }
hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize); BAIL_ON_FAILURE(hr);
pAcl = (PACL)new BYTE[dwAclSize]; if (!pAcl) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
hr = pAccessList->get_AclRevision((long *)&dwAclRevision);
//
// we have to deallocate memory
//
if( FAILED(hr) && (NULL != pAcl) ) delete( pAcl );
BAIL_ON_FAILURE(hr);
dwRet = InitializeAcl( pAcl, dwAclSize, dwAclRevision ); if (!dwRet) { hr = HRESULT_FROM_WIN32(GetLastError());
//
// we have to deallocate memory
//
if( FAILED(hr) && (NULL != pAcl) ) delete( pAcl );
BAIL_ON_FAILURE(hr); }
for (i = 0; i < dwCount; i++) {
dwStatus = AddAce( pAcl, dwAclRevision, i, (LPBYTE)*(ppAceHdr + i), (*(ppAceHdr + i))->AceSize ); if (!dwStatus) {
dwError = GetLastError(); } }
*ppAcl = pAcl;
error:
if (ppAceHdr) { for (i = 0; i < dwCount; i++) { if (*(ppAceHdr + i)) {
delete (*(ppAceHdr + i)); } }
delete (ppAceHdr); }
if (pUnknown) { pUnknown->Release(); }
if (pEnumerator) { pEnumerator->Release(); }
return(hr); }
HRESULT GetGroupSecurityIdentifier( IADsSecurityDescriptor FAR * pSecDes, PSID * ppSid, PBOOL pfGroupDefaulted ) { BSTR bstrGroup = NULL; DWORD dwSidSize = 0; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_Group( &bstrGroup ); BAIL_ON_FAILURE(hr);
hr = pSecDes->get_GroupDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) {
if (bstrGroup && *bstrGroup) {
hr = ConvertTrusteeToSid( bstrGroup, ppSid, &dwSidSize ); BAIL_ON_FAILURE(hr); *pfGroupDefaulted = FALSE; }else { *ppSid = NULL; *pfGroupDefaulted = FALSE; }
}else { *ppSid = NULL; dwSidSize = 0; *pfGroupDefaulted = TRUE; }
error:
if (bstrGroup) { SysFreeString(bstrGroup); }
return(hr);
}
HRESULT GetDacl( IADsSecurityDescriptor FAR * pSecDes, PACL * ppDacl, PBOOL pfDaclDefaulted ) { IADsAccessControlList FAR * pDiscAcl = NULL; IDispatch FAR * pDispatch = NULL; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_DaclDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) { *pfDaclDefaulted = FALSE; }else { *pfDaclDefaulted = TRUE; }
hr = pSecDes->get_DiscretionaryAcl( &pDispatch ); BAIL_ON_FAILURE(hr);
if (!pDispatch) { *ppDacl = NULL; goto error; }
hr = pDispatch->QueryInterface( IID_IADsAccessControlList, (void **)&pDiscAcl ); BAIL_ON_FAILURE(hr);
hr = ConvertAccessControlListToAcl( pDiscAcl, ppDacl ); BAIL_ON_FAILURE(hr);
error:
if (pDispatch) { pDispatch->Release(); }
if (pDiscAcl) { pDiscAcl->Release(); }
return(hr); }
HRESULT GetSacl( IADsSecurityDescriptor FAR * pSecDes, PACL * ppSacl, PBOOL pfSaclDefaulted ) { IADsAccessControlList FAR * pSystemAcl = NULL; IDispatch FAR * pDispatch = NULL; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_SaclDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) { *pfSaclDefaulted = FALSE; }else { *pfSaclDefaulted = TRUE; }
hr = pSecDes->get_SystemAcl( &pDispatch ); BAIL_ON_FAILURE(hr);
if (!pDispatch) { *ppSacl = NULL; goto error; }
hr = pDispatch->QueryInterface( IID_IADsAccessControlList, (void **)&pSystemAcl ); BAIL_ON_FAILURE(hr);
hr = ConvertAccessControlListToAcl( pSystemAcl, ppSacl ); BAIL_ON_FAILURE(hr);
error:
if (pDispatch) { pDispatch->Release(); }
if (pSystemAcl) { pSystemAcl->Release(); }
return(hr); }
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT ConvertSDToIDispatch( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, OUT IDispatch ** ppIDispatch ) { IADsSecurityDescriptor * pSecDes = NULL; IDispatch * pDispatch = NULL; LPWSTR pszGroup = NULL; LPWSTR pszOwner = NULL;
BOOL fOwnerDefaulted = 0; BOOL fGroupDefaulted = 0; BOOL fDaclDefaulted = 0; BOOL fSaclDefaulted = 0;
BOOL fSaclPresent = 0; BOOL fDaclPresent = 0;
LPBYTE pOwnerSidAddress = NULL; LPBYTE pGroupSidAddress = NULL; LPBYTE pDACLAddress = NULL; LPBYTE pSACLAddress = NULL;
DWORD dwRet = 0;
VARIANT varDACL; VARIANT varSACL;
HRESULT hr = S_OK;
DWORD dwRevision = 0; WORD wControl = 0;
memset(&varSACL, 0, sizeof(VARIANT)); memset(&varDACL, 0, sizeof(VARIANT));
if (!pSecurityDescriptor) { return(E_FAIL); }
dwRet = GetSecurityDescriptorControl( pSecurityDescriptor, &wControl, &dwRevision ); if (!dwRet){ hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
dwRet = GetSecurityDescriptorOwner( pSecurityDescriptor, (PSID *)&pOwnerSidAddress, &fOwnerDefaulted );
if (!dwRet){ hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = ConvertSidToFriendlyName( pOwnerSidAddress, &pszOwner ); BAIL_ON_FAILURE(hr);
dwRet = GetSecurityDescriptorGroup( pSecurityDescriptor, (PSID *)&pGroupSidAddress, &fOwnerDefaulted ); if (!dwRet){ hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = ConvertSidToFriendlyName( pGroupSidAddress, &pszGroup ); BAIL_ON_FAILURE(hr);
dwRet = GetSecurityDescriptorDacl( pSecurityDescriptor, &fDaclPresent, (PACL*)&pDACLAddress, &fDaclDefaulted ); if (pDACLAddress) {
hr = ConvertACLToVariant( (PACL)pDACLAddress, &varDACL ); BAIL_ON_FAILURE(hr); }
dwRet = GetSecurityDescriptorSacl( pSecurityDescriptor, &fSaclPresent, (PACL *)&pSACLAddress, &fSaclDefaulted );
if (!dwRet){ hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
if (pSACLAddress) {
hr = ConvertACLToVariant( (PACL)pSACLAddress, &varSACL ); BAIL_ON_FAILURE(hr); }
hr = CoCreateInstance( CLSID_SecurityDescriptor, NULL, CLSCTX_INPROC_SERVER, IID_IADsSecurityDescriptor, (void **)&pSecDes ); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_Owner(pszOwner); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_Group(pszGroup); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_Revision(dwRevision); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_Control((DWORD)wControl); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL)); BAIL_ON_FAILURE(hr);
hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL)); BAIL_ON_FAILURE(hr);
hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch); BAIL_ON_FAILURE(hr);
*ppIDispatch = pDispatch;
error: VariantClear(&varSACL); VariantClear(&varDACL);
if (pszOwner) { delete (pszOwner); }
if (pszGroup) { delete (pszGroup); }
if (pSecDes) { pSecDes->Release(); }
return(hr); }
HRESULT ConvertSDToVariant( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, OUT VARIANT * pVarSec ) { IDispatch *pIDispatch;
HRESULT hr = ConvertSDToIDispatch(pSecurityDescriptor, &pIDispatch);
if (FAILED(hr)) { return hr; }
VariantInit(pVarSec); V_VT(pVarSec) = VT_DISPATCH; V_DISPATCH(pVarSec) = pIDispatch;
return S_OK; }
HRESULT ConvertObjectToSD( IN IADsSecurityDescriptor FAR * pSecDes, OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor, OUT PDWORD pdwSDLength ) { HRESULT hr = S_OK;
SECURITY_DESCRIPTOR AbsoluteSD; PSECURITY_DESCRIPTOR pRelative = NULL; BOOL Defaulted = FALSE; BOOL DaclPresent = FALSE; BOOL SaclPresent = FALSE;
BOOL fDaclDefaulted = FALSE; BOOL fSaclDefaulted = FALSE; BOOL fOwnerDefaulted = FALSE; BOOL fGroupDefaulted = FALSE;
PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; PACL pSacl = NULL; DWORD dwSDLength = 0; DWORD dwRet = 0; BOOL dwStatus = 0;
//
// Initialize *pSizeSD = 0;
//
dwRet = InitializeSecurityDescriptor ( &AbsoluteSD, SECURITY_DESCRIPTOR_REVISION1 ); if (!dwRet) { hr = E_FAIL; BAIL_ON_FAILURE(hr); }
hr = GetOwnerSecurityIdentifier( pSecDes, &pOwnerSid, &fOwnerDefaulted ); BAIL_ON_FAILURE(hr);
dwStatus = SetSecurityDescriptorOwner( &AbsoluteSD, pOwnerSid, fOwnerDefaulted ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetGroupSecurityIdentifier( pSecDes, &pGroupSid, &fGroupDefaulted ); BAIL_ON_FAILURE(hr);
dwStatus = SetSecurityDescriptorGroup( &AbsoluteSD, pGroupSid, fGroupDefaulted );
if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetDacl( pSecDes, &pDacl, &fDaclDefaulted ); BAIL_ON_FAILURE(hr);
if (pDacl || fDaclDefaulted) { DaclPresent = TRUE; }
dwStatus = SetSecurityDescriptorDacl( &AbsoluteSD, DaclPresent, pDacl, fDaclDefaulted ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetSacl( pSecDes, &pSacl, &fSaclDefaulted ); BAIL_ON_FAILURE(hr);
if (pSacl || fSaclDefaulted) { SaclPresent = TRUE; }
dwStatus = SetSecurityDescriptorSacl( &AbsoluteSD, SaclPresent, pSacl, fSaclDefaulted );
if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
dwSDLength = GetSecurityDescriptorLength( &AbsoluteSD );
pRelative = new BYTE[dwSDLength]; if (!pRelative) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) { delete (pRelative);
hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
*ppSecurityDescriptor = pRelative; *pdwSDLength = dwSDLength;
cleanup:
if (pDacl) { delete (pDacl); }
if (pSacl) { delete (pSacl); }
if (pOwnerSid) { delete (pOwnerSid); }
if (pGroupSid) { delete (pGroupSid); }
return(hr);
error: if (pRelative) { delete (pRelative); }
*ppSecurityDescriptor = NULL; *pdwSDLength = 0;
goto cleanup;
}
HRESULT ConvertObjectToSDDispatch( IN IDispatch * pDisp, OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor, OUT PDWORD pdwSDLength ) { HRESULT hr; IADsSecurityDescriptor * pSecDes;
hr = pDisp->QueryInterface( IID_IADsSecurityDescriptor, (VOID **)&pSecDes );
if (FAILED(hr)) { return hr; }
hr = ConvertObjectToSD(pSecDes, ppSecurityDescriptor, pdwSDLength);
//
// Release the reference to the pSecSes
//
pSecDes->Release();
return hr; }
// Returns FALSE if these two security descriptors are identical.
// Returns TRUE if they differ, or if there is any error parsing either of them
BOOL CheckIfSecurityDescriptorsDiffer(PSECURITY_DESCRIPTOR pSD1, DWORD dwSDSize1, PSECURITY_DESCRIPTOR pSD2, DWORD dwSDSize2) { //
// If one of them is null, then they differ. (It should be impossible for them
// to both be null, but if they are, they had better both have size 0, which
// would just make us return TRUE below, so that's ok.)
//
if ( ( pSD1 == NULL ) || ( pSD2 == NULL ) ) { return TRUE; }
// if they converted to different sized structures then they are different
if ( dwSDSize1 != dwSDSize2 ) { return TRUE; }
// we know both succeeded conversion and converted to the same sized structures
// if the structures contain the same bytes then they are identical
if ( 0 == memcmp(pSD1, pSD2, dwSDSize1) ) { return FALSE; }
// else they differ
return TRUE; }
// eof
|