/* * @implemented */ BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL *pDacl, LPBOOL lpbDaclDefaulted) { BOOLEAN DaclPresent; BOOLEAN DaclDefaulted; NTSTATUS Status; Status = RtlGetDaclSecurityDescriptor(pSecurityDescriptor, &DaclPresent, pDacl, &DaclDefaulted); *lpbDaclPresent = (BOOL)DaclPresent; *lpbDaclDefaulted = (BOOL)DaclDefaulted; if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
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; } }
/****************************************************************************** * GetSecurityDescriptorDacl [ADVAPI32.@] */ BOOL WINAPI GetSecurityDescriptorDacl( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, OUT LPBOOL lpbDaclPresent, OUT PACL *pDacl, OUT LPBOOL lpbDaclDefaulted) { CallWin32ToNt (RtlGetDaclSecurityDescriptor(pSecurityDescriptor, (PBOOLEAN)lpbDaclPresent, pDacl, (PBOOLEAN)lpbDaclDefaulted)); }
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; }
/*++ * @name FreeDosDevicesProtection * * The FreeDosDevicesProtection frees the security descriptor that was created * by GetDosDevicesProtection * * @param DosDevicesSd * Pointer to the security descriptor to free. * @return None. * * @remarks None. * *--*/ VOID NTAPI FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd) { PACL Dacl; BOOLEAN Present, Default; NTSTATUS Status; /* Get the DACL corresponding to this SD */ Status = RtlGetDaclSecurityDescriptor(DosDevicesSd, &Present, &Dacl, &Default); ASSERT(NT_SUCCESS(Status)); ASSERT(Present); ASSERT(Dacl != NULL); /* Free it */ if ((NT_SUCCESS(Status)) && (Dacl)) RtlFreeHeap(CsrHeap, 0, Dacl); }
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 ObpFreeDosDevicesProtection( PSECURITY_DESCRIPTOR SecurityDescriptor ) /*++ Routine Description: This routine frees memory allocated via ObpGetDosDevicesProtection(). Arguments: SecurityDescriptor - The address of a security descriptor initialized by ObpGetDosDevicesProtection(). Return Value: None. --*/ { NTSTATUS Status; PACL Dacl; BOOLEAN DaclPresent, Defaulted; Status = RtlGetDaclSecurityDescriptor ( SecurityDescriptor, &DaclPresent, &Dacl, &Defaulted ); ASSERT( NT_SUCCESS( Status ) ); ASSERT( DaclPresent ); ASSERT( Dacl != NULL ); ExFreePool( (PVOID)Dacl ); return; }
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; }
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; }
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; }
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; }
DWORD ApplySecurity( HWND hwndParent, HANDLE hInstance, ULONG CallbackContext, PSECURITY_DESCRIPTOR SecDesc, PSECURITY_DESCRIPTOR SecDescNewObjects, BOOLEAN ApplyToSubContainers, BOOLEAN ApplyToSubObjects, LPDWORD StatusReturn ) { HANDLE MyToken = (HANDLE)CallbackContext; HANDLE Token = NULL; PTOKEN_DEFAULT_DACL DefaultDacl = NULL; NTSTATUS Status; BOOLEAN DaclPresent; BOOLEAN DaclDefaulted; *StatusReturn = SED_STATUS_FAILED_TO_MODIFY; // // Get a handle to the token // Token = OpenToken(MyToken, TOKEN_ADJUST_DEFAULT); if (Token == NULL) { DbgPrint("SECEDIT : Failed to open the token for TOKEN_ADJUST_DEFAULT access\n"); goto CleanupAndExit; } DefaultDacl = Alloc(sizeof(TOKEN_DEFAULT_DACL)); if (DefaultDacl == NULL) { goto CleanupAndExit; } Status = RtlGetDaclSecurityDescriptor ( SecDesc, &DaclPresent, &DefaultDacl->DefaultDacl, &DaclDefaulted ); ASSERT(NT_SUCCESS(Status)); ASSERT(DaclPresent); if (SetTokenInfo(Token, TokenDefaultDacl, (PVOID)DefaultDacl)) { *StatusReturn = SED_STATUS_MODIFIED; } CleanupAndExit: if (Token != NULL) { CloseToken(Token); } if (DefaultDacl != NULL) { Free(DefaultDacl); } if (*StatusReturn != SED_STATUS_MODIFIED) { MessageBox(hwndParent, "Failed to set default DACL", NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK); } return(ERROR_SUCCESS); }
/* 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; }
//---------------------------------------------------------------------- // // 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; }
BOOLEAN NTAPI SepAccessCheckEx(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, IN ACCESS_MASK PreviouslyGrantedAccess, OUT PPRIVILEGE_SET* Privileges, IN PGENERIC_MAPPING GenericMapping, IN KPROCESSOR_MODE AccessMode, OUT PACCESS_MASK GrantedAccessList, OUT PNTSTATUS AccessStatusList, IN BOOLEAN UseResultList) { ACCESS_MASK RemainingAccess; ACCESS_MASK TempAccess; ACCESS_MASK TempGrantedAccess = 0; ACCESS_MASK TempDeniedAccess = 0; PACCESS_TOKEN Token; ULONG i, ResultListLength; PACL Dacl; BOOLEAN Present; BOOLEAN Defaulted; PACE CurrentAce; PSID Sid; NTSTATUS Status; PAGED_CODE(); DPRINT("SepAccessCheckEx()\n"); /* Check for no access desired */ if (!DesiredAccess) { /* Check if we had no previous access */ if (!PreviouslyGrantedAccess) { /* Then there's nothing to give */ Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } /* Return the previous access only */ Status = STATUS_SUCCESS; *Privileges = NULL; goto ReturnCommonStatus; } /* Map given accesses */ RtlMapGenericMask(&DesiredAccess, GenericMapping); if (PreviouslyGrantedAccess) RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping); /* Initialize remaining access rights */ RemainingAccess = DesiredAccess; Token = SubjectSecurityContext->ClientToken ? SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */ Status = SePrivilegePolicyCheck(&RemainingAccess, &PreviouslyGrantedAccess, NULL, Token, NULL, UserMode); if (!NT_SUCCESS(Status)) { goto ReturnCommonStatus; } /* Succeed if there are no more rights to grant */ if (RemainingAccess == 0) { Status = STATUS_SUCCESS; goto ReturnCommonStatus; } /* Get the DACL */ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &Present, &Dacl, &Defaulted); if (!NT_SUCCESS(Status)) { goto ReturnCommonStatus; } /* RULE 1: Grant desired access if the object is unprotected */ if (Present == FALSE || Dacl == NULL) { PreviouslyGrantedAccess |= RemainingAccess; if (RemainingAccess & MAXIMUM_ALLOWED) { PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED; PreviouslyGrantedAccess |= GenericMapping->GenericAll; } Status = STATUS_SUCCESS; goto ReturnCommonStatus; } /* Deny access if the DACL is empty */ if (Dacl->AceCount == 0) { if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0) { Status = STATUS_SUCCESS; } else { PreviouslyGrantedAccess = 0; Status = STATUS_ACCESS_DENIED; } goto ReturnCommonStatus; } /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */ if (DesiredAccess & MAXIMUM_ALLOWED) { CurrentAce = (PACE)(Dacl + 1); for (i = 0; i < Dacl->AceCount; i++) { if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) { Sid = (PSID)(CurrentAce + 1); if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Deny access rights that have not been granted yet */ TempDeniedAccess |= (TempAccess & ~TempGrantedAccess); } } else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Grant access rights that have not been denied yet */ TempGrantedAccess |= (TempAccess & ~TempDeniedAccess); } } else { DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); } } /* Get the next ACE */ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); } /* Fail if some rights have not been granted */ RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess); if (RemainingAccess != 0) { PreviouslyGrantedAccess = 0; Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } /* Set granted access right and access status */ PreviouslyGrantedAccess |= TempGrantedAccess; if (PreviouslyGrantedAccess != 0) { Status = STATUS_SUCCESS; } else { Status = STATUS_ACCESS_DENIED; } goto ReturnCommonStatus; } /* RULE 4: Grant rights according to the DACL */ CurrentAce = (PACE)(Dacl + 1); for (i = 0; i < Dacl->AceCount; i++) { if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) { Sid = (PSID)(CurrentAce + 1); if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; RtlMapGenericMask(&TempAccess, GenericMapping); /* Leave if a remaining right must be denied */ if (RemainingAccess & TempAccess) break; } } else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { if (SepSidInToken(Token, Sid)) { /* Map access rights from the ACE */ TempAccess = CurrentAce->AccessMask; DPRINT("TempAccess 0x%08lx\n", TempAccess); RtlMapGenericMask(&TempAccess, GenericMapping); /* Remove granted rights */ DPRINT("RemainingAccess 0x%08lx TempAccess 0x%08lx\n", RemainingAccess, TempAccess); RemainingAccess &= ~TempAccess; DPRINT("RemainingAccess 0x%08lx\n", RemainingAccess); } } else { DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); } } /* Get the next ACE */ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); } DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n", DesiredAccess, PreviouslyGrantedAccess, RemainingAccess); /* Fail if some rights have not been granted */ if (RemainingAccess != 0) { DPRINT1("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess); #if 0 /* HACK HACK HACK */ Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; #endif } /* Set granted access rights */ PreviouslyGrantedAccess |= DesiredAccess; /* Fail if no rights have been granted */ if (PreviouslyGrantedAccess == 0) { DPRINT1("PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess); Status = STATUS_ACCESS_DENIED; goto ReturnCommonStatus; } Status = STATUS_SUCCESS; goto ReturnCommonStatus; ReturnCommonStatus: ResultListLength = UseResultList ? ObjectTypeListLength : 1; for (i = 0; i < ResultListLength; i++) { GrantedAccessList[i] = PreviouslyGrantedAccess; AccessStatusList[i] = Status; } return NT_SUCCESS(Status); }
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; }
//---------------------------------------------------------------------- // // NTIRemoveWorldAce // // Scans the passed security descriptor's DACL, looking for // the World SID's ACE (its first because the of the way device object // security descriptors are created) and removes it. // // If successful, the original security descriptor is deallocated // and a new one is returned. // //---------------------------------------------------------------------- NTSTATUS NTIRemoveWorldAce( PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR *NewSecurityDescriptor ) { PSECURITY_DESCRIPTOR absSecurityDescriptor; PSECURITY_DESCRIPTOR relSecurityDescriptor; PACE_HEADER aceHeader; NTSTATUS status; PACL Dacl; BOOLEAN DaclPresent, DaclDefaulted; USHORT aceIndex; ULONG worldSidLength; SID_IDENTIFIER_AUTHORITY worldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; PULONG worldSidSubAuthority; ULONG relLength; PSID worldSid; PSID aceSid; // // First, get an absolute version of the self-relative descriptor // relLength = RtlLengthSecurityDescriptor( SecurityDescriptor ); status = NTIMakeAbsoluteSD( SecurityDescriptor, &absSecurityDescriptor ); if( !NT_SUCCESS( status )) { return status; } // // Pull the DACL out so that we can scan it // status = RtlGetDaclSecurityDescriptor( absSecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted ); if( !NT_SUCCESS( status ) || !DaclPresent ) { DbgPrint(("Secsys: strange - couldn't get DACL from our absolute SD: %x\n", status )); ExFreePool( absSecurityDescriptor ); return status; } // // Initialize a SID that identifies the world-authority so // that we can recognize it in the ACL // worldSidLength = RtlLengthRequiredSid( 1 ); worldSid = (PSID) ExAllocatePool( PagedPool, worldSidLength ); RtlInitializeSid( worldSid, &worldSidAuthority, 1 ); worldSidSubAuthority = RtlSubAuthoritySid( worldSid, 0 ); *worldSidSubAuthority = SECURITY_WORLD_RID; // // Now march through the ACEs looking for the World ace. We could // do one of two things: // // - remove the ACE // - convert it into a grant-nothing ACE // // For demonstration purposes I'll remove the ACE. In addition, // this requires that I implement kernel-mode GetAce and DeleteAce functions, // since they are not implemented by the NT kernel. // DbgPrint(("Secsys: %d ACEs in DACL\n", Dacl->AceCount )); for( aceIndex = 0; aceIndex < Dacl->AceCount; aceIndex++ ) { aceHeader = NTIGetAce( Dacl, aceIndex ); DbgPrint((" ACE: type: %s mask: %x\n", (aceHeader->AceType & ACCESS_DENIED_ACE_TYPE ? "Deny" : "Allow"), *(PULONG) ((PUCHAR) aceHeader + sizeof(ACE_HEADER)))); // // Get the SID in this ACE and see if its the WORLD (Everyone) SID // aceSid = (PSID) ((PUCHAR) aceHeader + sizeof(ACE_HEADER) + sizeof(ULONG)); if( RtlEqualSid( worldSid, aceSid )) { // // We found it: remove it. // DbgPrint(("Secsys: Deleting ace %d\n", aceIndex )); NTIDeleteAce( Dacl, aceIndex ); break; } } // // Write new DACL back to security descriptor // status = RtlSetDaclSecurityDescriptor( absSecurityDescriptor, TRUE, Dacl, FALSE ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not update SD Dacl: %x\n", status )); goto cleanup; } // // Make sure its valid // if( !RtlValidSecurityDescriptor( absSecurityDescriptor )) { DbgPrint(("Secsys: SD after remove is invalid!\n")); status = STATUS_UNSUCCESSFUL; goto cleanup; } // // Now convert the security descriptor back to // self-relative // relSecurityDescriptor = ExAllocatePool( PagedPool, relLength ); status = RtlAbsoluteToSelfRelativeSD( absSecurityDescriptor, relSecurityDescriptor, &relLength ); if( !NT_SUCCESS( status )) { DbgPrint(("Could not convert absolute SD to relative: %x\n", status )); } // // Final step, free the original security descriptor and return the new one // ExFreePool( SecurityDescriptor ); *NewSecurityDescriptor = relSecurityDescriptor; cleanup: ExFreePool( worldSid ); 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); }