//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1997. // // File: var2sec.cxx // // Contents: // // Functions: // // History: 25-Apr-97 KrishnaG Created. // //---------------------------------------------------------------------------- #include "iis.hxx" #pragma hdrstop HRESULT ConvertSecurityDescriptorToSecDes( IADsSecurityDescriptor FAR * pSecDes, PSECURITY_DESCRIPTOR * ppSecurityDescriptor, 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; LONG lControlFlags = 0; SECURITY_DESCRIPTOR_CONTROL dwControlFlags = 0; SECURITY_DESCRIPTOR_CONTROL dwControlMask = SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED | SE_DACL_PROTECTED | SE_SACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERITED | SE_SACL_PROTECTED; // // Initialize *pSizeSD = 0; // dwRet = InitializeSecurityDescriptor ( &AbsoluteSD, SECURITY_DESCRIPTOR_REVISION1 ); if (!dwRet) { hr = E_FAIL; BAIL_ON_FAILURE(hr); } hr = pSecDes->get_Control(&lControlFlags); BAIL_ON_FAILURE(hr); dwControlFlags = dwControlMask & (SECURITY_DESCRIPTOR_CONTROL)lControlFlags; dwStatus = SetSecurityDescriptorControl( &AbsoluteSD, dwControlMask, dwControlFlags ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); 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 = AllocADsMem(dwSDLength); if (!pRelative) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) { FreeADsMem(pRelative); hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); } *ppSecurityDescriptor = pRelative; *pdwSDLength = dwSDLength; cleanup: if (pDacl) { FreeADsMem(pDacl); } if (pSacl) { FreeADsMem(pSacl); } if (pOwnerSid) { FreeADsMem(pOwnerSid); } if (pGroupSid) { FreeADsMem(pGroupSid); } RRETURN(hr); error: if (pRelative) { FreeADsMem(pRelative); } *ppSecurityDescriptor = NULL; *pdwSDLength = 0; goto cleanup; } 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) { ADsFreeString(bstrOwner); } RRETURN(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) { ADsFreeString(bstrGroup); } RRETURN(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(); } RRETURN(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(); } RRETURN(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; BOOL bRet = 0; DWORD dwAclRevision = 0; 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 = (PACE_HEADER *)AllocADsMem(sizeof(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) ); VariantClear(&varAce); if (pAccessControlEntry) { pAccessControlEntry->Release(); pAccessControlEntry = NULL; } if (SUCCEEDED(hr)) { *(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce; dwCount++; } } hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize); BAIL_ON_FAILURE(hr); pAcl = (PACL)AllocADsMem(dwAclSize); if (!pAcl) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } #if 0 hr = pAccessList->get_AclRevision((long *)&dwAclRevision); BAIL_ON_FAILURE(hr); #else dwAclRevision = ACL_REVISION; #endif bRet = InitializeAcl( pAcl, dwAclSize, dwAclRevision ); if (!bRet) { dwRet = GetLastError(); hr = HRESULT_FROM_WIN32(dwRet); BAIL_ON_FAILURE(hr); } for (i = 0; i < dwCount; i++) { bRet = AddAce( pAcl, dwAclRevision, i, (LPBYTE)*(ppAceHdr + i), (*(ppAceHdr + i))->AceSize ); if (!bRet) { dwRet = GetLastError(); hr = HRESULT_FROM_WIN32(dwRet); BAIL_ON_FAILURE(hr); } } *ppAcl = pAcl; error: if (ppAceHdr) { for (i = 0; i < dwCount; i++) { if (*(ppAceHdr + i)) { FreeADsMem(*(ppAceHdr + i)); } } FreeADsMem(ppAceHdr); } if (pUnknown) { pUnknown->Release(); } if (pEnumerator) { pEnumerator->Release(); } RRETURN(hr); } 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); // // 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 = (LPBYTE)AllocADsMem(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 = (LPBYTE)AllocADsMem(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 = (LPBYTE)AllocADsMem(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 = (LPBYTE)AllocADsMem(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 = (LPBYTE)AllocADsMem(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 = (LPBYTE)AllocADsMem(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) { ADsFreeString(bstrTrustee); } if (pSid) { FreeADsMem(pSid); } RRETURN(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; RRETURN(S_OK); } HRESULT ConvertTrusteeToSid( BSTR bstrTrustee, PSID * ppSid, PDWORD pdwSidSize ) { HRESULT hr = S_OK; BYTE Sid[MAX_PATH]; DWORD dwSidSize = sizeof(Sid); DWORD dwRet = 0; WCHAR szDomainName[MAX_PATH]; DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR); SID_NAME_USE eUse; LPWSTR pszTrustee = (LPWSTR)bstrTrustee; PSID pSid = NULL; dwSidSize = sizeof(Sid); if ((*pszTrustee == (WCHAR)'\\') || (*pszTrustee == WCHAR('/'))){ pszTrustee++; } dwRet = LookupAccountName( NULL, pszTrustee, Sid, &dwSidSize, szDomainName, &dwDomainSize, (PSID_NAME_USE)&eUse ); if (!dwRet) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } pSid = AllocADsMem(dwSidSize); if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } memcpy(pSid, Sid, dwSidSize); *pdwSidSize = dwSidSize; *ppSid = pSid; error: RRETURN(hr); }