BOOL BackupReadSecurityData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { if (!pbif->fProcessSecurity) { return(TRUE); } if (pbuc->fStreamStart) { while (TRUE) { NTSTATUS Status; DWORD cbSecurityInfo; // First try to read all the security data RtlZeroMemory(pbuc->pBuffer, pbuc->cbBuffer); Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); if (!NT_SUCCESS(Status) && !BufferOverflow(Status)) { // Now just try everything but SACL Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); } #if 0 if (!NT_SUCCESS(Status) && !BufferOverflow(Status)) { // Now just try to read the DACL Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); } #endif if (NT_SUCCESS(Status)) { pbuc->fBufferReady = TRUE; break; } if (!BufferOverflow(Status)) { return(TRUE); // No Security info, do next stream type } if (!GrowBuffer(pbuc, cbSecurityInfo)) { return(FALSE); // No memory } // else grow succeeded } pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex]; pbuc->head.dwStreamAttributes = STREAM_CONTAINS_SECURITY; pbuc->head.dwStreamNameSize = 0; pbuc->cbHeader = CB_NAMELESSHEADER; pbuc->head.Size.LowPart = RtlLengthSecurityDescriptor(pbuc->pBuffer); pbuc->head.Size.HighPart = 0; pbuc->fStreamStart = FALSE; } else if (pbuc->liStreamOffset.HighPart != 0 || pbuc->liStreamOffset.LowPart >= pbuc->cbHeader) { BackupReadBuffer(pbuc, pbif); } return(TRUE); }
/*++ * @name ObLogSecurityDescriptor * @implemented NT5.2 * * The ObLogSecurityDescriptor routine <FILLMEIN> * * @param InputSecurityDescriptor * <FILLMEIN> * * @param OutputSecurityDescriptor * <FILLMEIN> * * @param RefBias * <FILLMEIN> * * @return STATUS_SUCCESS or appropriate error value. * * @remarks None. * *--*/ NTSTATUS NTAPI ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, IN ULONG RefBias) { PSECURITY_DESCRIPTOR_HEADER SdHeader = NULL, NewHeader = NULL; ULONG Length, Hash, Index; POB_SD_CACHE_LIST CacheEntry; BOOLEAN Result; PLIST_ENTRY NextEntry; /* Get the length */ Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor); /* Get the hash */ Hash = ObpHashSecurityDescriptor(InputSecurityDescriptor, Length); /* Now select the appropriate cache entry */ Index = Hash % SD_CACHE_ENTRIES; CacheEntry = &ObsSecurityDescriptorCache[Index]; /* Lock it shared */ ObpSdAcquireLockShared(CacheEntry); /* Start our search */ while (TRUE) { /* Reset result found */ Result = FALSE; /* Loop the hash list */ NextEntry = CacheEntry->Head.Flink; while (NextEntry != &CacheEntry->Head) { /* Get the header */ SdHeader = ObpGetHeaderForEntry(NextEntry); /* Our hashes are ordered, so quickly check if we should stop now */ if (SdHeader->FullHash > Hash) break; /* We survived the quick hash check, now check for equalness */ if (SdHeader->FullHash == Hash) { /* Hashes match, now compare descriptors */ Result = ObpCompareSecurityDescriptors(InputSecurityDescriptor, Length, &SdHeader->SecurityDescriptor); if (Result) break; } /* Go to the next entry */ NextEntry = NextEntry->Flink; } /* Check if we found anything */ if (Result) { /* Increment its reference count */ InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, RefBias); /* Release the lock */ ObpSdReleaseLockShared(CacheEntry); /* Return the descriptor */ *OutputSecurityDescriptor = &SdHeader->SecurityDescriptor; /* Free anything that we may have had to create */ if (NewHeader) ExFreePool(NewHeader); return STATUS_SUCCESS; } /* Check if we got here, and didn't create a descriptor yet */ if (!NewHeader) { /* Release the lock */ ObpSdReleaseLockShared(CacheEntry); /* This should be our first time in the loop, create it */ NewHeader = ObpCreateCacheEntry(InputSecurityDescriptor, Length, Hash, RefBias); if (!NewHeader) return STATUS_INSUFFICIENT_RESOURCES; /* Now acquire the exclusive lock and we should hit the right path */ ObpSdAcquireLock(CacheEntry); } else { /* We have inserted the SD, we're fine now */ break; } } /* Okay, now let's do the insert, we should have the exclusive lock */ InsertTailList(NextEntry, &NewHeader->Link); /* Release the lock */ ObpSdReleaseLock(CacheEntry); /* Return the SD*/ *OutputSecurityDescriptor = &NewHeader->SecurityDescriptor; return STATUS_SUCCESS; }
NTSTATUS AfdCreateRawSecurityDescriptor( VOID ) /*++ Routine Description: This routine creates a security descriptor which gives access only to Administrtors and LocalSystem. This descriptor is used to access check raw endpoint opens. Arguments: None. Return Value: STATUS_SUCCESS or an appropriate error code. --*/ { PACL rawAcl; NTSTATUS status; BOOLEAN memoryAllocated = FALSE; PSECURITY_DESCRIPTOR afdSecurityDescriptor; ULONG afdSecurityDescriptorLength; CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR localSecurityDescriptor = (PSECURITY_DESCRIPTOR) &buffer; SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION; // // Get a pointer to the security descriptor from the AFD device object. // status = ObGetObjectSecurity( AfdDeviceObject, &afdSecurityDescriptor, &memoryAllocated ); if (!NT_SUCCESS(status)) { KdPrint(( "AFD: Unable to get security descriptor, error: %x\n", status )); ASSERT(memoryAllocated == FALSE); return(status); } // // Build a local security descriptor with an ACL giving only // administrators and system access. // status = AfdBuildDeviceAcl(&rawAcl); if (!NT_SUCCESS(status)) { KdPrint(("AFD: Unable to create Raw ACL, error: %x\n", status)); goto error_exit; } (VOID) RtlCreateSecurityDescriptor( localSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); (VOID) RtlSetDaclSecurityDescriptor( localSecurityDescriptor, TRUE, rawAcl, FALSE ); // // Make a copy of the AFD descriptor. This copy will be the raw descriptor. // afdSecurityDescriptorLength = RtlLengthSecurityDescriptor( afdSecurityDescriptor ); AfdRawSecurityDescriptor = AFD_ALLOCATE_POOL( PagedPool, afdSecurityDescriptorLength, AFD_SECURITY_POOL_TAG ); if (AfdRawSecurityDescriptor == NULL) { KdPrint(("AFD: couldn't allocate security descriptor\n")); goto error_exit; } RtlMoveMemory( AfdRawSecurityDescriptor, afdSecurityDescriptor, afdSecurityDescriptorLength ); // // Now apply the local descriptor to the raw descriptor. // status = SeSetSecurityDescriptorInfo( NULL, &securityInformation, localSecurityDescriptor, &AfdRawSecurityDescriptor, PagedPool, IoGetFileObjectGenericMapping() ); if (!NT_SUCCESS(status)) { KdPrint(("AFD: SeSetSecurity failed, %lx\n", status)); AFD_FREE_POOL( AfdRawSecurityDescriptor, AFD_SECURITY_POOL_TAG ); AFD_FREE_POOL( rawAcl, AFD_SECURITY_POOL_TAG ); AfdRawSecurityDescriptor = NULL; goto error_exit; } status = STATUS_SUCCESS; error_exit: ObReleaseObjectSecurity( afdSecurityDescriptor, memoryAllocated ); return(status); }