static VOID LwpsLegacyFreeSecurityDescriptor( IN OUT PSECURITY_DESCRIPTOR_ABSOLUTE *ppSecurityDescriptor ) { if (*ppSecurityDescriptor) { PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = *ppSecurityDescriptor; PSID pOwner = NULL; PSID pGroup = NULL; PACL pDacl = NULL; PACL pSacl = NULL; BOOLEAN bDefaulted = FALSE; BOOLEAN bPresent = FALSE; RtlGetOwnerSecurityDescriptor(pSecDesc, &pOwner, &bDefaulted); RtlGetGroupSecurityDescriptor(pSecDesc, &pGroup, &bDefaulted); RtlGetDaclSecurityDescriptor(pSecDesc, &bPresent, &pDacl, &bDefaulted); RtlGetSaclSecurityDescriptor(pSecDesc, &bPresent, &pSacl, &bDefaulted); LW_RTL_FREE(&pSecDesc); LW_RTL_FREE(&pOwner); LW_RTL_FREE(&pGroup); LW_RTL_FREE(&pDacl); LW_RTL_FREE(&pSacl); *ppSecurityDescriptor = NULL; } }
NTSTATUS PhSetSeObjectSecurity( _In_ HANDLE Handle, _In_ ULONG ObjectType, _In_ SECURITY_INFORMATION SecurityInformation, _In_ PSECURITY_DESCRIPTOR SecurityDescriptor ) { ULONG win32Result; SECURITY_INFORMATION securityInformation = 0; BOOLEAN present; BOOLEAN defaulted; PSID owner = NULL; PSID group = NULL; PACL dacl = NULL; PACL sacl = NULL; if (SecurityInformation & OWNER_SECURITY_INFORMATION) { if (NT_SUCCESS(RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &owner, &defaulted))) securityInformation |= OWNER_SECURITY_INFORMATION; } if (SecurityInformation & GROUP_SECURITY_INFORMATION) { if (NT_SUCCESS(RtlGetGroupSecurityDescriptor(SecurityDescriptor, &group, &defaulted))) securityInformation |= GROUP_SECURITY_INFORMATION; } if (SecurityInformation & DACL_SECURITY_INFORMATION) { if (NT_SUCCESS(RtlGetDaclSecurityDescriptor(SecurityDescriptor, &present, &dacl, &defaulted)) && present) securityInformation |= DACL_SECURITY_INFORMATION; } if (SecurityInformation & SACL_SECURITY_INFORMATION) { if (NT_SUCCESS(RtlGetSaclSecurityDescriptor(SecurityDescriptor, &present, &sacl, &defaulted)) && present) securityInformation |= SACL_SECURITY_INFORMATION; } win32Result = SetSecurityInfo( Handle, ObjectType, SecurityInformation, owner, group, dacl, sacl ); if (win32Result != ERROR_SUCCESS) return NTSTATUS_FROM_WIN32(win32Result); return STATUS_SUCCESS; }
VOID EVTFreeSecurityDescriptor( PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc ) { PSID pOwnerSid = NULL; BOOLEAN bOwnerDefaulted = FALSE; PSID pPrimaryGroupSid = NULL; BOOLEAN bPrimaryGroupDefaulted = FALSE; PACL pDacl = NULL; BOOLEAN bDaclPresent = FALSE; BOOLEAN bDaclDefaulted = FALSE; PACL pSacl = NULL; BOOLEAN bSaclPresent = FALSE; BOOLEAN bSaclDefaulted = FALSE; if (pSecDesc) { RtlGetOwnerSecurityDescriptor(pSecDesc, &pOwnerSid, &bOwnerDefaulted); LW_SAFE_FREE_MEMORY(pOwnerSid); RtlGetGroupSecurityDescriptor(pSecDesc, &pPrimaryGroupSid, &bPrimaryGroupDefaulted); LW_SAFE_FREE_MEMORY(pPrimaryGroupSid); RtlGetDaclSecurityDescriptor(pSecDesc, &bDaclPresent, &pDacl, &bDaclDefaulted); LW_SAFE_FREE_MEMORY(pDacl); RtlGetSaclSecurityDescriptor(pSecDesc, &bSaclPresent, &pSacl, &bSaclDefaulted); LW_SAFE_FREE_MEMORY(pSacl); LW_SAFE_FREE_MEMORY(pSecDesc); } }
VOID EventLogShutdown( VOID ) { EventLogRPCShutdown(); EventLogServiceShutdown(); EventLogDbShutdown(); #ifndef _WIN32 if (gEventLogServerGlobals.gSecurityDescriptor) { PSID pOwnerSID = NULL; BOOLEAN bDefaulted = FALSE; BOOLEAN bDaclPresent = FALSE; PACL pDacl = NULL; if (STATUS_SUCCESS == RtlGetOwnerSecurityDescriptor( gEventLogServerGlobals.gSecurityDescriptor, &pOwnerSID, &bDefaulted)) { RTL_FREE(&pOwnerSID); } if (STATUS_SUCCESS == RtlGetDaclSecurityDescriptor( gEventLogServerGlobals.gSecurityDescriptor, &bDaclPresent, &pDacl, &bDefaulted) && bDaclPresent && pDacl) { EventLogFreeMemory(pDacl); } EventLogFreeMemory(gEventLogServerGlobals.gSecurityDescriptor); } #endif }
static VOID SrvShareFreeAbsoluteSecurityDescriptor( IN OUT PSECURITY_DESCRIPTOR_ABSOLUTE *ppSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSID pOwner = NULL; PSID pGroup = NULL; PACL pDacl = NULL; PACL pSacl = NULL; BOOLEAN bDefaulted = FALSE; BOOLEAN bPresent = FALSE; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; if ((ppSecDesc == NULL) || (*ppSecDesc == NULL)) { return; } pSecDesc = *ppSecDesc; ntStatus = RtlGetOwnerSecurityDescriptor(pSecDesc, &pOwner, &bDefaulted); ntStatus = RtlGetGroupSecurityDescriptor(pSecDesc, &pGroup, &bDefaulted); ntStatus = RtlGetDaclSecurityDescriptor(pSecDesc, &bPresent, &pDacl, &bDefaulted); ntStatus = RtlGetSaclSecurityDescriptor(pSecDesc, &bPresent, &pSacl, &bDefaulted); ntStatus = ntStatus; RTL_FREE(&pSecDesc); RTL_FREE(&pOwner); RTL_FREE(&pGroup); RTL_FREE(&pDacl); RTL_FREE(&pSacl); *ppSecDesc = NULL; return; }
/* * @implemented */ BOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID *pOwner, LPBOOL lpbOwnerDefaulted) { BOOLEAN OwnerDefaulted; NTSTATUS Status; Status = RtlGetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, &OwnerDefaulted); *lpbOwnerDefaulted = (BOOL)OwnerDefaulted; if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
NTSTATUS SrvShareSetSecurity( IN PSRV_SHARE_INFO pShareInfo, IN PSECURITY_DESCRIPTOR_RELATIVE pIncRelSecDesc, IN ULONG ulIncRelSecDescLen ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pIncAbsSecDesc = NULL; PSECURITY_DESCRIPTOR_ABSOLUTE pFinalAbsSecDesc = NULL; PSECURITY_DESCRIPTOR_RELATIVE pFinalRelSecDesc = NULL; ULONG ulFinalRelSecDescLen = 0; SECURITY_INFORMATION secInfo = 0; PSID pOwner = NULL; PSID pGroup = NULL; PACL pDacl = NULL; PACL pSacl = NULL; BOOLEAN bDefaulted = FALSE; BOOLEAN bPresent = FALSE; GENERIC_MAPPING GenericMap = { .GenericRead = FILE_GENERIC_READ, .GenericWrite = FILE_GENERIC_WRITE, .GenericExecute = FILE_GENERIC_EXECUTE, .GenericAll = FILE_ALL_ACCESS }; /* Sanity checks */ if ((pIncRelSecDesc == NULL) || (ulIncRelSecDescLen == 0)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } if (pShareInfo->ulSecDescLen == 0) { ntStatus = SrvShareSetDefaultSecurity(pShareInfo); BAIL_ON_NT_STATUS(ntStatus); } /* Make the Absolute version of thr incoming SD and get the SecurityInformation */ ntStatus = SrvShareCreateAbsoluteSecDescFromRel( &pIncAbsSecDesc, pIncRelSecDesc) ; BAIL_ON_NT_STATUS(ntStatus); /* Don't bail on these. We'll be checking the pointer */ ntStatus = RtlGetOwnerSecurityDescriptor( pIncAbsSecDesc, &pOwner, &bDefaulted); secInfo |= pOwner ? OWNER_SECURITY_INFORMATION : 0; ntStatus = RtlGetGroupSecurityDescriptor( pIncAbsSecDesc, &pGroup, &bDefaulted); secInfo |= pGroup ? GROUP_SECURITY_INFORMATION : 0; ntStatus = RtlGetDaclSecurityDescriptor( pIncAbsSecDesc, &bPresent, &pDacl, &bDefaulted); secInfo |= pDacl ? DACL_SECURITY_INFORMATION : 0; ntStatus = RtlGetSaclSecurityDescriptor( pIncAbsSecDesc, &bPresent, &pSacl, &bDefaulted); secInfo |= pSacl ? SACL_SECURITY_INFORMATION : 0; /* Assume the new length is not longer than the combined length of both the current and incoming relative SecDesc buffers */ ulFinalRelSecDescLen = ulIncRelSecDescLen + pShareInfo->ulSecDescLen; ntStatus = SrvAllocateMemory( ulFinalRelSecDescLen, (PVOID*)&pFinalRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetSecurityDescriptorInfo( secInfo, pIncRelSecDesc, pShareInfo->pSecDesc, pFinalRelSecDesc, &ulFinalRelSecDescLen, &GenericMap); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareCreateAbsoluteSecDescFromRel( &pFinalAbsSecDesc, pFinalRelSecDesc) ; BAIL_ON_NT_STATUS(ntStatus); /* Free the old SecDesc and save the new one */ SrvShareFreeSecurity(pShareInfo); pShareInfo->pSecDesc = pFinalRelSecDesc; pShareInfo->ulSecDescLen = ulFinalRelSecDescLen; pShareInfo->pAbsSecDesc = pFinalAbsSecDesc; ntStatus = STATUS_SUCCESS; cleanup: if (pIncAbsSecDesc) { SrvShareFreeAbsoluteSecurityDescriptor(&pIncAbsSecDesc); } return ntStatus; error: if (pFinalRelSecDesc) { SrvFreeMemory(pFinalRelSecDesc); } if (pFinalAbsSecDesc) { SrvShareFreeAbsoluteSecurityDescriptor(&pFinalAbsSecDesc); } goto cleanup; }
NTSTATUS PvfsAccessCheckFileEnumerate( PPVFS_CCB pCcb, PCSTR pszRelativeFilename ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PACCESS_TOKEN pToken = pCcb->pUserToken; PSTR pszFilename = NULL; ACCESS_MASK AccessMask = 0; ACCESS_MASK GrantedAccess = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; BYTE pRelativeSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulRelativeSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; BOOLEAN bGranted = FALSE; SECURITY_INFORMATION SecInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION); ACCESS_MASK Desired = (FILE_READ_ATTRIBUTES| FILE_READ_EA| FILE_READ_DATA| READ_CONTROL); PSID pOwner = NULL; BOOLEAN bOwnerDefaulted = FALSE; /* Create the absolute path */ ntError = LwRtlCStringAllocatePrintf( &pszFilename, "%s/%s", pCcb->pScb->pOwnerFcb->pszFilename, pszRelativeFilename); BAIL_ON_NT_STATUS(ntError); /* Check the file object itself */ ntError = PvfsGetSecurityDescriptorFilename( pszFilename, SecInfo, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer), &ulRelativeSecDescLength); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD( &pSecDesc, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer)); BAIL_ON_NT_STATUS(ntError); // Tests against NTFS/Win2003R2 show that the file/directory object // owner is always granted FILE_READ_ATTRIBUTE ntError = RtlGetOwnerSecurityDescriptor( pSecDesc, &pOwner, &bOwnerDefaulted); BAIL_ON_NT_STATUS(ntError); if (RtlIsSidMemberOfToken(pToken, pOwner)) { ClearFlag(Desired, FILE_READ_ATTRIBUTES); SetFlag(GrantedAccess, FILE_READ_ATTRIBUTES); } /* Now check access */ bGranted = RtlAccessCheck( pSecDesc, pToken, Desired, GrantedAccess, &gPvfsDriverState.GenericSecurityMap, &AccessMask, &ntError); if (!bGranted) { ntError = STATUS_ACCESS_DENIED; } BAIL_ON_NT_STATUS(ntError); cleanup: if (pszFilename) { LwRtlCStringFree(&pszFilename); } if (pSecDesc) { PvfsFreeAbsoluteSecurityDescriptor(&pSecDesc); } return ntError; error: goto cleanup; }
NTSTATUS PvfsAccessCheckFile( PACCESS_TOKEN pToken, PPVFS_FILE_NAME FileName, ACCESS_MASK Desired, ACCESS_MASK *pGranted ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; ACCESS_MASK AccessMask = 0; ACCESS_MASK GrantedAccess = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; BYTE pRelativeSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulRelativeSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; PSECURITY_DESCRIPTOR_ABSOLUTE pParentSecDesc = NULL; BYTE pParentRelSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulParentRelSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; BOOLEAN bGranted = FALSE; SECURITY_INFORMATION SecInfo = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION); PSID pOwner = NULL; BOOLEAN bOwnerDefaulted = FALSE; BOOLEAN bWantsDelete = FALSE; BOOLEAN bWantsMaximumAccess = FALSE; PPVFS_FILE_NAME parentDirectoryName = NULL; PPVFS_FILE_NAME relativeFileName = NULL; BAIL_ON_INVALID_PTR(pToken, ntError); BAIL_ON_INVALID_PTR(pGranted, ntError); // Check the file object itself ntError = PvfsGetSecurityDescriptorFilename( PvfsGetCStringBaseFileName(FileName), SecInfo, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer), &ulRelativeSecDescLength); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD( &pSecDesc, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pRelativeSecDescBuffer)); BAIL_ON_NT_STATUS(ntError); // Tests against NTFS/Win2003R2 show that the file/directory object // owner is always granted FILE_READ_ATTRIBUTE ntError = RtlGetOwnerSecurityDescriptor( pSecDesc, &pOwner, &bOwnerDefaulted); BAIL_ON_NT_STATUS(ntError); if (RtlIsSidMemberOfToken(pToken, pOwner)) { ClearFlag(Desired, FILE_READ_ATTRIBUTES); SetFlag(GrantedAccess, FILE_READ_ATTRIBUTES); } // Check for access rights. We'll deal with DELETE separately since that // could be granted by the parent directory security descriptor if (Desired & DELETE) { bWantsDelete = TRUE; ClearFlag(Desired, DELETE); } if (Desired & MAXIMUM_ALLOWED) { bWantsMaximumAccess = TRUE; } bGranted = RtlAccessCheck( pSecDesc, pToken, Desired, GrantedAccess, &gPvfsDriverState.GenericSecurityMap, &AccessMask, &ntError); if (!bGranted) { BAIL_ON_NT_STATUS(ntError); } GrantedAccess = AccessMask; // See if the file object security descriptor grants DELETE // Only continue when checking for MAXIMUM_ALLOWED if we haven't been // granted DELETE already if (bWantsDelete || (bWantsMaximumAccess && !(GrantedAccess & DELETE))) { AccessMask = 0; bGranted = RtlAccessCheck( pSecDesc, pToken, DELETE, GrantedAccess, &gPvfsDriverState.GenericSecurityMap, &AccessMask, &ntError); if (!bGranted) { ntError = PvfsSplitFileNamePath( &parentDirectoryName, &relativeFileName, FileName); BAIL_ON_NT_STATUS(ntError); ntError = PvfsGetSecurityDescriptorFilename( PvfsGetCStringBaseFileName(parentDirectoryName), SecInfo, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pParentRelSecDescBuffer), &ulParentRelSecDescLength); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD( &pParentSecDesc, (PSECURITY_DESCRIPTOR_RELATIVE)((PVOID)pParentRelSecDescBuffer)); BAIL_ON_NT_STATUS(ntError); AccessMask = 0; bGranted = RtlAccessCheck( pParentSecDesc, pToken, FILE_DELETE_CHILD, 0, &gPvfsDriverState.GenericSecurityMap, &AccessMask, &ntError); // This is a hard failure unless we are just trying to determine // what the maximum allowed access would be if (!bGranted && !bWantsMaximumAccess) { BAIL_ON_NT_STATUS(ntError); } AccessMask = DELETE; } // Combine directory and file object granted permissions AccessMask |= GrantedAccess; } *pGranted = AccessMask; ntError = STATUS_SUCCESS; error: if (parentDirectoryName) { PvfsFreeFileName(relativeFileName); } if (relativeFileName) { PvfsFreeFileName(parentDirectoryName); } if (pParentSecDesc) { PvfsFreeAbsoluteSecurityDescriptor(&pParentSecDesc); } if (pSecDesc) { PvfsFreeAbsoluteSecurityDescriptor(&pSecDesc); } return ntError; }
/****************************************************************************** * GetSecurityDescriptorOwner [ADVAPI32.@] * * PARAMS * pOwner [] * lpbOwnerDefaulted [] */ BOOL WINAPI GetSecurityDescriptorOwner( SECURITY_DESCRIPTOR *pDescr, PSID *pOwner, LPBOOL lpbOwnerDefaulted ) { CallWin32ToNt (RtlGetOwnerSecurityDescriptor( pDescr, pOwner, (PBOOLEAN)lpbOwnerDefaulted )); }
VOID LocalDirFreeSecurityDescriptor( PSECURITY_DESCRIPTOR_ABSOLUTE *ppSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; PSID pOwnerSid = NULL; BOOLEAN bOwnerDefaulted = FALSE; PSID pPrimaryGroupSid = NULL; BOOLEAN bPrimaryGroupDefaulted = FALSE; PACL pDacl = NULL; BOOLEAN bDaclPresent = FALSE; BOOLEAN bDaclDefaulted = FALSE; PACL pSacl = NULL; BOOLEAN bSaclPresent = FALSE; BOOLEAN bSaclDefaulted = FALSE; if (ppSecDesc == NULL || *ppSecDesc == NULL) { return; } pSecDesc = *ppSecDesc; ntStatus = RtlGetOwnerSecurityDescriptor(pSecDesc, &pOwnerSid, &bOwnerDefaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlGetGroupSecurityDescriptor(pSecDesc, &pPrimaryGroupSid, &bPrimaryGroupDefaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlGetDaclSecurityDescriptor(pSecDesc, &bDaclPresent, &pDacl, &bDaclDefaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlGetSaclSecurityDescriptor(pSecDesc, &bSaclPresent, &pSacl, &bSaclDefaulted); BAIL_ON_NT_STATUS(ntStatus); error: LW_SAFE_FREE_MEMORY(pOwnerSid); LW_SAFE_FREE_MEMORY(pPrimaryGroupSid); if (bDaclPresent) { LW_SAFE_FREE_MEMORY(pDacl); } if (bSaclPresent) { LW_SAFE_FREE_MEMORY(pSacl); } LW_SAFE_FREE_MEMORY(pSecDesc); *ppSecDesc = NULL; }
/* creates a struct security_descriptor and contained information in one contiguous piece of memory */ NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd, data_size_t *server_sd_len) { unsigned int len; PSID owner, group; ACL *dacl, *sacl; BOOLEAN owner_present, group_present, dacl_present, sacl_present; BOOLEAN defaulted; NTSTATUS status; unsigned char *ptr; if (!nt_sd) { *server_sd = NULL; *server_sd_len = 0; return STATUS_SUCCESS; } len = sizeof(struct security_descriptor); status = RtlGetOwnerSecurityDescriptor(nt_sd, &owner, &owner_present); if (status != STATUS_SUCCESS) return status; status = RtlGetGroupSecurityDescriptor(nt_sd, &group, &group_present); if (status != STATUS_SUCCESS) return status; status = RtlGetSaclSecurityDescriptor(nt_sd, &sacl_present, &sacl, &defaulted); if (status != STATUS_SUCCESS) return status; status = RtlGetDaclSecurityDescriptor(nt_sd, &dacl_present, &dacl, &defaulted); if (status != STATUS_SUCCESS) return status; if (owner_present) len += RtlLengthSid(owner); if (group_present) len += RtlLengthSid(group); if (sacl_present && sacl) len += sacl->AclSize; if (dacl_present && dacl) len += dacl->AclSize; /* fix alignment for the Unicode name that follows the structure */ len = (len + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1); *server_sd = RtlAllocateHeap(GetProcessHeap(), 0, len); if (!*server_sd) return STATUS_NO_MEMORY; (*server_sd)->control = ((SECURITY_DESCRIPTOR *)nt_sd)->Control & ~SE_SELF_RELATIVE; (*server_sd)->owner_len = owner_present ? RtlLengthSid(owner) : 0; (*server_sd)->group_len = group_present ? RtlLengthSid(group) : 0; (*server_sd)->sacl_len = (sacl_present && sacl) ? sacl->AclSize : 0; (*server_sd)->dacl_len = (dacl_present && dacl) ? dacl->AclSize : 0; ptr = (unsigned char *)(*server_sd + 1); memcpy(ptr, owner, (*server_sd)->owner_len); ptr += (*server_sd)->owner_len; memcpy(ptr, group, (*server_sd)->group_len); ptr += (*server_sd)->group_len; memcpy(ptr, sacl, (*server_sd)->sacl_len); ptr += (*server_sd)->sacl_len; memcpy(ptr, dacl, (*server_sd)->dacl_len); *server_sd_len = len; return STATUS_SUCCESS; }
NTSTATUS PvfsSetSecurityDescriptorFile( IN PPVFS_CCB pCcb, IN SECURITY_INFORMATION SecInfo, IN PSECURITY_DESCRIPTOR_RELATIVE pSecDesc, IN ULONG SecDescLength ) { NTSTATUS ntError = STATUS_ACCESS_DENIED; PSECURITY_DESCRIPTOR_RELATIVE pFinalSecDesc = NULL; ULONG ulFinalSecDescLength = 0; SECURITY_INFORMATION SecInfoAll = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION); BYTE pCurrentSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulCurrentSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; BYTE pNewSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE]; ULONG ulNewSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE; PSECURITY_DESCRIPTOR_ABSOLUTE pIncAbsSecDesc = NULL; union { TOKEN_OWNER TokenOwnerInfo; BYTE Buffer[SID_MAX_SIZE]; } TokenOwnerBuffer; PTOKEN_OWNER pTokenOwnerInformation = (PTOKEN_OWNER)&TokenOwnerBuffer; ULONG ulTokenOwnerLength = 0; union { SID Sid; BYTE Buffer[SID_MAX_SIZE]; } LocalSystemSidBuffer; PSID pLocalSystemSid = (PSID)&LocalSystemSidBuffer; ULONG ulLocalSystemSidLength = sizeof(LocalSystemSidBuffer); memset(pCurrentSecDescBuffer, 0, SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE); memset(pNewSecDescBuffer, 0, SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE); memset(TokenOwnerBuffer.Buffer, 0, SID_MAX_SIZE); /* Sanity checks */ if (SecInfo == 0) { ntError = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntError); } /* If the new Security Descriptor contains owner or group SID information, berify that the user's ACCESS_TOKEN contains the SID as a member */ if (SecInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION)) { PSID pOwner = NULL; PSID pGroup = NULL; BOOLEAN bDefaulted = FALSE; ntError = PvfsSecurityAclSelfRelativeToAbsoluteSD( &pIncAbsSecDesc, pSecDesc); BAIL_ON_NT_STATUS(ntError); ntError = RtlQueryAccessTokenInformation( pCcb->pUserToken, TokenOwner, (PVOID)pTokenOwnerInformation, sizeof(TokenOwnerBuffer), &ulTokenOwnerLength); BAIL_ON_NT_STATUS(ntError); ntError = RtlCreateWellKnownSid( WinLocalSystemSid, NULL, pLocalSystemSid, &ulLocalSystemSidLength); BAIL_ON_NT_STATUS(ntError); if (SecInfo & OWNER_SECURITY_INFORMATION) { ntError = RtlGetOwnerSecurityDescriptor( pIncAbsSecDesc, &pOwner, &bDefaulted); BAIL_ON_NT_STATUS(ntError); if (!RtlIsSidMemberOfToken(pCcb->pUserToken, pOwner) && !RtlEqualSid(pLocalSystemSid, pTokenOwnerInformation->Owner)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } } if (SecInfo & GROUP_SECURITY_INFORMATION) { ntError = RtlGetGroupSecurityDescriptor( pIncAbsSecDesc, &pGroup, &bDefaulted); BAIL_ON_NT_STATUS(ntError); if (!RtlIsSidMemberOfToken(pCcb->pUserToken, pGroup) && !RtlEqualSid(pLocalSystemSid, pTokenOwnerInformation->Owner)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } } } if (SecInfo == SecInfoAll) { /* We already have a fully formed Security Descriptor */ pFinalSecDesc = pSecDesc; ulFinalSecDescLength = SecDescLength; } else { /* Retrieve the existing SD and merge with the incoming one */ ntError = PvfsGetSecurityDescriptorFile( pCcb, SecInfoAll, (PSECURITY_DESCRIPTOR_RELATIVE)pCurrentSecDescBuffer, &ulCurrentSecDescLength); BAIL_ON_NT_STATUS(ntError); /* Assume that the new SD is <= the combined size of the current SD and the incoming one */ ntError = RtlSetSecurityDescriptorInfo( SecInfo, pSecDesc, (PSECURITY_DESCRIPTOR_RELATIVE)pCurrentSecDescBuffer, (PSECURITY_DESCRIPTOR_RELATIVE)pNewSecDescBuffer, &ulNewSecDescLength, &gPvfsFileGenericMapping); BAIL_ON_NT_STATUS(ntError); pFinalSecDesc = (PSECURITY_DESCRIPTOR_RELATIVE)pNewSecDescBuffer; ulFinalSecDescLength = ulNewSecDescLength; } /* Save the combined SD */ #ifdef HAVE_EA_SUPPORT ntError = PvfsSetSecurityDescriptorFileXattr( pCcb, pFinalSecDesc, ulFinalSecDescLength); #else ntError = PvfsSetSecurityDescriptorPosix( pCcb, pFinalSecDesc, ulFinalSecDescLength); #endif BAIL_ON_NT_STATUS(ntError); PvfsNotifyScheduleFullReport( pCcb->pFcb, FILE_NOTIFY_CHANGE_SECURITY, FILE_ACTION_MODIFIED, pCcb->pszFilename); cleanup: if (pIncAbsSecDesc) { PvfsFreeAbsoluteSecurityDescriptor(&pIncAbsSecDesc); } return ntError; error: goto cleanup; }
static NTSTATUS RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle, IN PISECURITY_DESCRIPTOR SecurityDescriptor) { PSECURITY_DESCRIPTOR RelSD = NULL; PSECURITY_DESCRIPTOR NewRelSD = NULL; PSECURITY_DESCRIPTOR AbsSD = NULL; #ifdef _WIN64 BOOLEAN AbsSDAllocated = FALSE; #endif PSID AdminSid = NULL; PSID LocalSystemSid = NULL; ULONG DescriptorSize; ULONG AbsSDSize, RelSDSize = 0; PACL Dacl; BOOLEAN DaclPresent, DaclDefaulted; PSID OwnerSid; BOOLEAN OwnerDefaulted; ULONG AceIndex; PACE Ace = NULL; NTSTATUS Status; /* find out how much memory we need to allocate for the self-relative descriptor we're querying */ Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &DescriptorSize); if (Status != STATUS_BUFFER_TOO_SMALL) { /* looks like the FS doesn't support security... return success */ Status = STATUS_SUCCESS; goto Cleanup; } /* allocate enough memory for the security descriptor */ RelSD = RtlpAllocateMemory(DescriptorSize, 'dSeS'); if (RelSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } /* query the self-relative security descriptor */ Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, RelSD, DescriptorSize, &DescriptorSize); if (!NT_SUCCESS(Status)) { /* FIXME - handle the case where someone else modified the owner and/or DACL while we allocated memory. But that should be *very* unlikely.... */ goto Cleanup; } /* query the owner and DACL from the descriptor */ Status = RtlGetOwnerSecurityDescriptor(RelSD, &OwnerSid, &OwnerDefaulted); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlGetDaclSecurityDescriptor(RelSD, &DaclPresent, &Dacl, &DaclDefaulted); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the Administrators SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the local SYSTEM SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* check if the Administrators are the owner and at least a not-NULL DACL is present */ if (OwnerSid != NULL && RtlEqualSid(OwnerSid, AdminSid) && DaclPresent && Dacl != NULL) { /* check the DACL for an Allowed ACE for the SYSTEM account */ AceIndex = 0; do { Status = RtlGetAce(Dacl, AceIndex++, (PVOID*)&Ace); if (!NT_SUCCESS(Status)) { Ace = NULL; } else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { /* check if the the ACE is a set of allowed permissions for the local SYSTEM account */ if (RtlEqualSid((PSID)(Ace + 1), LocalSystemSid)) { /* check if the ACE is inherited by noncontainer and container objects, if not attempt to change that */ if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) || !(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE)) { Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = ZwSetSecurityObject(DirectoryHandle, DACL_SECURITY_INFORMATION, RelSD); } else { /* all done, we have access */ Status = STATUS_SUCCESS; } goto Cleanup; } } } while (Ace != NULL); } AbsSDSize = DescriptorSize; /* because we need to change any existing data we need to convert it to an absolute security descriptor first */ Status = RtlSelfRelativeToAbsoluteSD2(RelSD, &AbsSDSize); #ifdef _WIN64 if (Status == STATUS_BUFFER_TOO_SMALL) { /* this error code can only be returned on 64 bit builds because the size of an absolute security descriptor is greater than the size of a self-relative security descriptor */ ASSERT(AbsSDSize > DescriptorSize); AbsSD = RtlpAllocateMemory(DescriptorSize, 'dSeS'); if (AbsSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } AbsSDAllocated = TRUE; /* make a raw copy of the self-relative descriptor */ RtlCopyMemory(AbsSD, RelSD, DescriptorSize); /* finally convert it */ Status = RtlSelfRelativeToAbsoluteSD2(AbsSD, &AbsSDSize); } else #endif { AbsSD = RelSD; } if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the owner SID */ Status = RtlSetOwnerSecurityDescriptor(AbsSD, AdminSid, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the DACL in the security descriptor */ Status = RtlSetDaclSecurityDescriptor(AbsSD, TRUE, SecurityDescriptor->Dacl, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* convert it back to a self-relative descriptor, find out how much memory we need */ Status = RtlAbsoluteToSelfRelativeSD(AbsSD, NULL, &RelSDSize); if (Status != STATUS_BUFFER_TOO_SMALL) { goto Cleanup; } /* allocate enough memory for the new self-relative descriptor */ NewRelSD = RtlpAllocateMemory(RelSDSize, 'dSeS'); if (NewRelSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } /* convert the security descriptor to self-relative format */ Status = RtlAbsoluteToSelfRelativeSD(AbsSD, NewRelSD, &RelSDSize); if (Status == STATUS_BUFFER_TOO_SMALL) { goto Cleanup; } /* finally attempt to change the security information */ Status = ZwSetSecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NewRelSD); Cleanup: if (AdminSid != NULL) { RtlFreeSid(AdminSid); } if (LocalSystemSid != NULL) { RtlFreeSid(LocalSystemSid); } if (RelSD != NULL) { RtlpFreeMemory(RelSD, 'dSeS'); } if (NewRelSD != NULL) { RtlpFreeMemory(NewRelSD, 'dSeS'); } #ifdef _WIN64 if (AbsSDAllocated) { RtlpFreeMemory(AbsSD, 'dSeS'); } #endif return Status; }
static NTSTATUS LsaSrvQueryPolicySecurity( PPOLICY_CONTEXT pAccountContext, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR_RELATIVE *ppSecurityDescRelative, PDWORD pSecurityDescRelativeSize ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD err = ERROR_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = gpLsaSecDesc; PSECURITY_DESCRIPTOR_ABSOLUTE pSecurityDesc = NULL; PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescRelative = NULL; DWORD securityDescRelativeSize = 0; err = LwAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pSecurityDesc)); BAIL_ON_LSA_ERROR(err); ntStatus = RtlCreateSecurityDescriptorAbsolute( pSecurityDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); if (SecurityInformation & OWNER_SECURITY_INFORMATION) { PSID owner = NULL; BOOLEAN defaulted = FALSE; ntStatus = RtlGetOwnerSecurityDescriptor( pSecDesc, &owner, &defaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDesc, owner, defaulted); BAIL_ON_NT_STATUS(ntStatus); } if (SecurityInformation & GROUP_SECURITY_INFORMATION) { PSID group = NULL; BOOLEAN defaulted = FALSE; ntStatus = RtlGetGroupSecurityDescriptor( pSecDesc, &group, &defaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pSecurityDesc, group, defaulted); BAIL_ON_NT_STATUS(ntStatus); } if (SecurityInformation & DACL_SECURITY_INFORMATION) { PACL pDacl = NULL; BOOLEAN daclPresent = FALSE; BOOLEAN defaulted = FALSE; ntStatus = RtlGetDaclSecurityDescriptor( pSecDesc, &daclPresent, &pDacl, &defaulted); BAIL_ON_NT_STATUS(ntStatus); if (daclPresent) { ntStatus = RtlSetDaclSecurityDescriptor( pSecurityDesc, daclPresent, pDacl, defaulted); BAIL_ON_NT_STATUS(ntStatus); } } if (SecurityInformation & SACL_SECURITY_INFORMATION) { PACL pSacl = NULL; BOOLEAN saclPresent = FALSE; BOOLEAN defaulted = FALSE; ntStatus = RtlGetSaclSecurityDescriptor( pSecDesc, &saclPresent, &pSacl, &defaulted); BAIL_ON_NT_STATUS(ntStatus); if (saclPresent) { ntStatus = RtlSetSaclSecurityDescriptor( pSecurityDesc, saclPresent, pSacl, defaulted); BAIL_ON_NT_STATUS(ntStatus); } } ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDesc, pSecurityDescRelative, &securityDescRelativeSize); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = STATUS_SUCCESS; } else if (ntStatus != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LsaSrvAllocateMemory( OUT_PPVOID(&pSecurityDescRelative), securityDescRelativeSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDesc, pSecurityDescRelative, &securityDescRelativeSize); BAIL_ON_NT_STATUS(ntStatus); *ppSecurityDescRelative = pSecurityDescRelative; *pSecurityDescRelativeSize = securityDescRelativeSize; error: if (err || ntStatus) { if (pSecurityDescRelative) { LsaSrvFreeMemory(pSecurityDescRelative); } *ppSecurityDescRelative = NULL; *pSecurityDescRelativeSize = 0; } LW_SAFE_FREE_MEMORY(pSecurityDesc); if (ntStatus == STATUS_SUCCESS && err != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(err); } return ntStatus; }
//---------------------------------------------------------------------- // // NTIMakeAbsoluteSD // // Takes a self-relative security descriptor and returns an allocated // absolute version. Caller is responsibile for freeing the allocated // buffer on success. // //---------------------------------------------------------------------- NTSTATUS NTIMakeAbsoluteSD( PSECURITY_DESCRIPTOR RelSecurityDescriptor, PSECURITY_DESCRIPTOR *pAbsSecurityDescriptor ) { NTSTATUS status; BOOLEAN DaclPresent, DaclDefaulted, OwnerDefaulted, GroupDefaulted; PACL Dacl; PSID Owner, Group; PSECURITY_DESCRIPTOR absSecurityDescriptor; // // Initialize buffer pointers // absSecurityDescriptor = (PSECURITY_DESCRIPTOR) ExAllocatePool( NonPagedPool, 1024 ); *pAbsSecurityDescriptor = absSecurityDescriptor; // // Create an absolute-form security descriptor for manipulation. // The one on the security descriptor is in self-relative form. // status = RtlCreateSecurityDescriptor( absSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if( !NT_SUCCESS( status ) ) { DbgPrint(("Secsys: Unable to initialize security descriptor\n")); goto cleanup; } // // Locate the descriptor's DACL and apply the DACL to the new // descriptor we're going to modify // status = RtlGetDaclSecurityDescriptor( RelSecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted ); if( !NT_SUCCESS( status ) || !DaclPresent ) { if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Error obtaining security descriptor's DACL: %x\n", status )); } else { DbgPrint(("Secsys: Security descriptor does not have a DACL\n" )); } goto cleanup; } status = RtlSetDaclSecurityDescriptor( absSecurityDescriptor, DaclPresent, Dacl, DaclDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Coult not set new security descriptor DACL: %x\n", status )); goto cleanup; } // // We would get and apply the SACL at this point, but NT does not export // the appropriate function, RtlGetSaclSecurityDescriptor :-( // // // Get and apply the owner // status = RtlGetOwnerSecurityDescriptor( RelSecurityDescriptor, &Owner, &OwnerDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not security descriptor owner: %x\n", Owner )); goto cleanup; } status = RtlSetOwnerSecurityDescriptor( absSecurityDescriptor, Owner, OwnerDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not set owner: %x\n", status )); goto cleanup; } // // Get and apply group // status = RtlGetGroupSecurityDescriptor( RelSecurityDescriptor, &Group, &GroupDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not security descriptor group: %x\n", Owner )); goto cleanup; } status = RtlSetGroupSecurityDescriptor( absSecurityDescriptor, Group, GroupDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not set group: %x\n", status )); goto cleanup; } // // Finally, make sure that what we made is valid // if( !RtlValidSecurityDescriptor( absSecurityDescriptor )) { DbgPrint(("Secsys: absolute descriptor not valid!\n")); status = STATUS_UNSUCCESSFUL; } // // Done! Return. // cleanup: if( !NT_SUCCESS( status ) ) { ExFreePool( absSecurityDescriptor ); } return status; }
static VOID CheckDirectorySecurity__( _In_ PCWSTR DirectoryName, _In_ PSID ExpectedOwner, _In_ PSID ExpectedGroup, _In_ ULONG AceCount, _In_ PCSTR FileAndLine, ...) { NTSTATUS Status; UNICODE_STRING DirectoryNameString; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE DirectoryHandle; PSECURITY_DESCRIPTOR SecurityDescriptor; ULONG SecurityDescriptorSize; PSID Owner; PSID Group; PACL Dacl; PACL Sacl; BOOLEAN Present; BOOLEAN Defaulted; va_list Arguments; RtlInitUnicodeString(&DirectoryNameString, DirectoryName); InitializeObjectAttributes(&ObjectAttributes, &DirectoryNameString, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenDirectoryObject(&DirectoryHandle, READ_CONTROL | ACCESS_SYSTEM_SECURITY, &ObjectAttributes); ok_eq_hex(Status, STATUS_SUCCESS); if (skip(NT_SUCCESS(Status), "No directory (%ls)\n", DirectoryName)) { return; } Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, NULL, 0, &SecurityDescriptorSize); ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); if (skip(Status == STATUS_BUFFER_TOO_SMALL, "No security size (%ls)\n", DirectoryName)) { ObCloseHandle(DirectoryHandle, KernelMode); return; } SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, SecurityDescriptorSize, 'dSmK'); ok(SecurityDescriptor != NULL, "Failed to allocate %lu bytes\n", SecurityDescriptorSize); if (skip(SecurityDescriptor != NULL, "No memory for descriptor (%ls)\n", DirectoryName)) { ObCloseHandle(DirectoryHandle, KernelMode); return; } Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, SecurityDescriptor, SecurityDescriptorSize, &SecurityDescriptorSize); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { Owner = NULL; Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &Owner, &Defaulted); if (ExpectedOwner) CheckSid__(Owner, NO_SIZE, ExpectedOwner, FileAndLine); ok(Defaulted == FALSE, "Owner defaulted for %ls\n", DirectoryName); Group = NULL; Status = RtlGetGroupSecurityDescriptor(SecurityDescriptor, &Group, &Defaulted); if (ExpectedGroup) CheckSid__(Group, NO_SIZE, ExpectedGroup, FileAndLine); ok(Defaulted == FALSE, "Group defaulted for %ls\n", DirectoryName); Dacl = NULL; Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &Present, &Dacl, &Defaulted); ok_eq_hex(Status, STATUS_SUCCESS); ok(Present == TRUE, "DACL not present for %ls\n", DirectoryName); ok(Defaulted == FALSE, "DACL defaulted for %ls\n", DirectoryName); va_start(Arguments, FileAndLine); VCheckAcl__(Dacl, AceCount, FileAndLine, Arguments); va_end(Arguments); Sacl = NULL; Status = RtlGetSaclSecurityDescriptor(SecurityDescriptor, &Present, &Sacl, &Defaulted); ok_eq_hex(Status, STATUS_SUCCESS); ok(Present == FALSE, "SACL present for %ls\n", DirectoryName); ok(Defaulted == FALSE, "SACL defaulted for %ls\n", DirectoryName); ok(Sacl == NULL, "Sacl is %p for %ls\n", Sacl, DirectoryName); } ExFreePoolWithTag(SecurityDescriptor, 'dSmK'); ObCloseHandle(DirectoryHandle, KernelMode); }