1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Kernel 3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: ntoskrnl/ob/obsecure.c 5c2c66affSColin Finck * PURPOSE: SRM Interface of the Object Manager 6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7c2c66affSColin Finck * Eric Kohl 8c2c66affSColin Finck */ 9c2c66affSColin Finck 10c2c66affSColin Finck /* INCLUDES *****************************************************************/ 11c2c66affSColin Finck 12c2c66affSColin Finck #include <ntoskrnl.h> 13c2c66affSColin Finck #define NDEBUG 14c2c66affSColin Finck #include <debug.h> 15c2c66affSColin Finck 16c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 17c2c66affSColin Finck 18c2c66affSColin Finck NTSTATUS 19c2c66affSColin Finck NTAPI 20c2c66affSColin Finck ObAssignObjectSecurityDescriptor(IN PVOID Object, 21c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, 22c2c66affSColin Finck IN POOL_TYPE PoolType) 23c2c66affSColin Finck { 24c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 25c2c66affSColin Finck NTSTATUS Status; 26c2c66affSColin Finck PSECURITY_DESCRIPTOR NewSd; 27c2c66affSColin Finck PEX_FAST_REF FastRef; 28c2c66affSColin Finck PAGED_CODE(); 29c2c66affSColin Finck 30c2c66affSColin Finck /* Get the object header */ 31c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 32c2c66affSColin Finck FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor; 33c2c66affSColin Finck if (!SecurityDescriptor) 34c2c66affSColin Finck { 35c2c66affSColin Finck /* Nothing to assign */ 36c2c66affSColin Finck ExInitializeFastReference(FastRef, NULL); 37c2c66affSColin Finck return STATUS_SUCCESS; 38c2c66affSColin Finck } 39c2c66affSColin Finck 40c2c66affSColin Finck /* Add it to our internal cache */ 41c2c66affSColin Finck Status = ObLogSecurityDescriptor(SecurityDescriptor, 42c2c66affSColin Finck &NewSd, 43c2c66affSColin Finck MAX_FAST_REFS + 1); 44c2c66affSColin Finck if (NT_SUCCESS(Status)) 45c2c66affSColin Finck { 46c2c66affSColin Finck /* Free the old copy */ 47c2c66affSColin Finck ExFreePoolWithTag(SecurityDescriptor, TAG_SD); 48c2c66affSColin Finck 49c2c66affSColin Finck /* Set the new pointer */ 50c2c66affSColin Finck ASSERT(NewSd); 51c2c66affSColin Finck ExInitializeFastReference(FastRef, NewSd); 52c2c66affSColin Finck } 53c2c66affSColin Finck 54c2c66affSColin Finck /* Return status */ 55c2c66affSColin Finck return Status; 56c2c66affSColin Finck } 57c2c66affSColin Finck 58c2c66affSColin Finck NTSTATUS 59c2c66affSColin Finck NTAPI 60c2c66affSColin Finck ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) 61c2c66affSColin Finck { 62c2c66affSColin Finck EX_FAST_REF FastRef; 63c2c66affSColin Finck ULONG Count; 64c2c66affSColin Finck PSECURITY_DESCRIPTOR OldSecurityDescriptor; 65c2c66affSColin Finck 66c2c66affSColin Finck /* Get the fast reference and capture it */ 67c2c66affSColin Finck FastRef = *(PEX_FAST_REF)SecurityDescriptor; 68c2c66affSColin Finck 69c2c66affSColin Finck /* Don't free again later */ 70c2c66affSColin Finck *SecurityDescriptor = NULL; 71c2c66affSColin Finck 72c2c66affSColin Finck /* Get the descriptor and reference count */ 73c2c66affSColin Finck OldSecurityDescriptor = ExGetObjectFastReference(FastRef); 74c2c66affSColin Finck Count = ExGetCountFastReference(FastRef); 75c2c66affSColin Finck 76c2c66affSColin Finck /* Dereference the descriptor */ 77c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1); 78c2c66affSColin Finck 79c2c66affSColin Finck /* All done */ 80c2c66affSColin Finck return STATUS_SUCCESS; 81c2c66affSColin Finck } 82c2c66affSColin Finck 83c2c66affSColin Finck NTSTATUS 84c2c66affSColin Finck NTAPI 85c2c66affSColin Finck ObQuerySecurityDescriptorInfo(IN PVOID Object, 86c2c66affSColin Finck IN PSECURITY_INFORMATION SecurityInformation, 87c2c66affSColin Finck OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 88c2c66affSColin Finck IN OUT PULONG Length, 89c2c66affSColin Finck IN PSECURITY_DESCRIPTOR *OutputSecurityDescriptor) 90c2c66affSColin Finck { 91c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 92c2c66affSColin Finck NTSTATUS Status; 93c2c66affSColin Finck PSECURITY_DESCRIPTOR ObjectSd; 94c2c66affSColin Finck PAGED_CODE(); 95c2c66affSColin Finck 96c2c66affSColin Finck /* Get the object header */ 97c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 98c2c66affSColin Finck 99c2c66affSColin Finck /* Get the SD */ 100c2c66affSColin Finck ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader); 101c2c66affSColin Finck 102c2c66affSColin Finck /* Query the information */ 103c2c66affSColin Finck Status = SeQuerySecurityDescriptorInfo(SecurityInformation, 104c2c66affSColin Finck SecurityDescriptor, 105c2c66affSColin Finck Length, 106c2c66affSColin Finck &ObjectSd); 107c2c66affSColin Finck 108c2c66affSColin Finck /* Check if we have an object SD and dereference it, if so */ 109c2c66affSColin Finck if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1); 110c2c66affSColin Finck 111c2c66affSColin Finck /* Return status */ 112c2c66affSColin Finck return Status; 113c2c66affSColin Finck } 114c2c66affSColin Finck 115c2c66affSColin Finck NTSTATUS 116c2c66affSColin Finck NTAPI 117c2c66affSColin Finck ObSetSecurityDescriptorInfo(IN PVOID Object, 118c2c66affSColin Finck IN PSECURITY_INFORMATION SecurityInformation, 119c2c66affSColin Finck IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 120c2c66affSColin Finck IN OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, 121c2c66affSColin Finck IN POOL_TYPE PoolType, 122c2c66affSColin Finck IN PGENERIC_MAPPING GenericMapping) 123c2c66affSColin Finck { 124c2c66affSColin Finck NTSTATUS Status; 125c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 126c2c66affSColin Finck PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor; 127c2c66affSColin Finck PEX_FAST_REF FastRef; 128c2c66affSColin Finck EX_FAST_REF OldValue; 129c2c66affSColin Finck ULONG Count; 130c2c66affSColin Finck PAGED_CODE(); 131c2c66affSColin Finck 132c2c66affSColin Finck /* Get the object header */ 133c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 134c2c66affSColin Finck while (TRUE) 135c2c66affSColin Finck { 136c2c66affSColin Finck /* Reference the old descriptor */ 137c2c66affSColin Finck OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader); 138c2c66affSColin Finck NewDescriptor = OldDescriptor; 139c2c66affSColin Finck 140c2c66affSColin Finck /* Set the SD information */ 141c2c66affSColin Finck Status = SeSetSecurityDescriptorInfo(Object, 142c2c66affSColin Finck SecurityInformation, 143c2c66affSColin Finck SecurityDescriptor, 144c2c66affSColin Finck &NewDescriptor, 145c2c66affSColin Finck PoolType, 146c2c66affSColin Finck GenericMapping); 147c2c66affSColin Finck if (!NT_SUCCESS(Status)) 148c2c66affSColin Finck { 149c2c66affSColin Finck /* We failed, dereference the old one */ 150c2c66affSColin Finck if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1); 151c2c66affSColin Finck break; 152c2c66affSColin Finck } 153c2c66affSColin Finck 154c2c66affSColin Finck /* Now add this to the cache */ 155c2c66affSColin Finck Status = ObLogSecurityDescriptor(NewDescriptor, 156c2c66affSColin Finck &CachedDescriptor, 157c2c66affSColin Finck MAX_FAST_REFS + 1); 158c2c66affSColin Finck 159c2c66affSColin Finck /* Let go of our uncached copy */ 160c2c66affSColin Finck ExFreePool(NewDescriptor); 161c2c66affSColin Finck 162c2c66affSColin Finck /* Check for success */ 163c2c66affSColin Finck if (!NT_SUCCESS(Status)) 164c2c66affSColin Finck { 165c2c66affSColin Finck /* We failed, dereference the old one */ 166c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldDescriptor, 1); 167c2c66affSColin Finck break; 168c2c66affSColin Finck } 169c2c66affSColin Finck 170c2c66affSColin Finck /* Do the swap */ 171c2c66affSColin Finck FastRef = (PEX_FAST_REF)OutputSecurityDescriptor; 172c2c66affSColin Finck OldValue = ExCompareSwapFastReference(FastRef, 173c2c66affSColin Finck CachedDescriptor, 174c2c66affSColin Finck OldDescriptor); 175c2c66affSColin Finck 176c2c66affSColin Finck /* Make sure the swap worked */ 177c2c66affSColin Finck if (ExGetObjectFastReference(OldValue) == OldDescriptor) 178c2c66affSColin Finck { 179c2c66affSColin Finck /* Flush waiters */ 180c2c66affSColin Finck ObpAcquireObjectLock(ObjectHeader); 181c2c66affSColin Finck ObpReleaseObjectLock(ObjectHeader); 182c2c66affSColin Finck 183c2c66affSColin Finck /* And dereference the old one */ 184c2c66affSColin Finck Count = ExGetCountFastReference(OldValue); 185c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2); 186c2c66affSColin Finck break; 187c2c66affSColin Finck } 188c2c66affSColin Finck else 189c2c66affSColin Finck { 190c2c66affSColin Finck /* Someone changed it behind our back -- try again */ 191c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldDescriptor, 1); 192c2c66affSColin Finck ObDereferenceSecurityDescriptor(CachedDescriptor, 193c2c66affSColin Finck MAX_FAST_REFS + 1); 194c2c66affSColin Finck } 195c2c66affSColin Finck } 196c2c66affSColin Finck 197c2c66affSColin Finck /* Return status */ 198c2c66affSColin Finck return Status; 199c2c66affSColin Finck } 200c2c66affSColin Finck 201c2c66affSColin Finck BOOLEAN 202c2c66affSColin Finck NTAPI 203c2c66affSColin Finck ObCheckCreateObjectAccess(IN PVOID Object, 204c2c66affSColin Finck IN ACCESS_MASK CreateAccess, 205c2c66affSColin Finck IN PACCESS_STATE AccessState, 206c2c66affSColin Finck IN PUNICODE_STRING ComponentName, 207c2c66affSColin Finck IN BOOLEAN LockHeld, 208c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 209c2c66affSColin Finck OUT PNTSTATUS AccessStatus) 210c2c66affSColin Finck { 211c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 212c2c66affSColin Finck POBJECT_TYPE ObjectType; 213c2c66affSColin Finck PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 214c2c66affSColin Finck BOOLEAN SdAllocated; 215c2c66affSColin Finck BOOLEAN Result = TRUE; 216c2c66affSColin Finck ACCESS_MASK GrantedAccess = 0; 217c2c66affSColin Finck PPRIVILEGE_SET Privileges = NULL; 218c2c66affSColin Finck NTSTATUS Status; 219c2c66affSColin Finck PAGED_CODE(); 220c2c66affSColin Finck 221c2c66affSColin Finck /* Get the header and type */ 222c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 223c2c66affSColin Finck ObjectType = ObjectHeader->Type; 224c2c66affSColin Finck 225c2c66affSColin Finck /* Get the security descriptor */ 226c2c66affSColin Finck Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 227c2c66affSColin Finck if (!NT_SUCCESS(Status)) 228c2c66affSColin Finck { 229c2c66affSColin Finck /* We failed */ 230c2c66affSColin Finck *AccessStatus = Status; 231c2c66affSColin Finck return FALSE; 232c2c66affSColin Finck } 233c2c66affSColin Finck 234c2c66affSColin Finck /* Lock the security context */ 235c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 236c2c66affSColin Finck 237c2c66affSColin Finck /* Check if we have an SD */ 238c2c66affSColin Finck if (SecurityDescriptor) 239c2c66affSColin Finck { 240c2c66affSColin Finck /* Now do the entire access check */ 241c2c66affSColin Finck Result = SeAccessCheck(SecurityDescriptor, 242c2c66affSColin Finck &AccessState->SubjectSecurityContext, 243c2c66affSColin Finck TRUE, 244c2c66affSColin Finck CreateAccess, 245c2c66affSColin Finck 0, 246c2c66affSColin Finck &Privileges, 247c2c66affSColin Finck &ObjectType->TypeInfo.GenericMapping, 248c2c66affSColin Finck AccessMode, 249c2c66affSColin Finck &GrantedAccess, 250c2c66affSColin Finck AccessStatus); 251c2c66affSColin Finck if (Privileges) 252c2c66affSColin Finck { 253c2c66affSColin Finck /* We got privileges, append them to the access state and free them */ 254c2c66affSColin Finck Status = SeAppendPrivileges(AccessState, Privileges); 255c2c66affSColin Finck SeFreePrivileges(Privileges); 256c2c66affSColin Finck } 257c2c66affSColin Finck } 258c2c66affSColin Finck 259c2c66affSColin Finck /* We're done, unlock the context and release security */ 260c2c66affSColin Finck SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 261c2c66affSColin Finck ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 262c2c66affSColin Finck return Result; 263c2c66affSColin Finck } 264c2c66affSColin Finck 265c2c66affSColin Finck BOOLEAN 266c2c66affSColin Finck NTAPI 267c2c66affSColin Finck ObpCheckTraverseAccess(IN PVOID Object, 268c2c66affSColin Finck IN ACCESS_MASK TraverseAccess, 269c2c66affSColin Finck IN PACCESS_STATE AccessState OPTIONAL, 270c2c66affSColin Finck IN BOOLEAN LockHeld, 271c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 272c2c66affSColin Finck OUT PNTSTATUS AccessStatus) 273c2c66affSColin Finck { 274c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 275c2c66affSColin Finck POBJECT_TYPE ObjectType; 276c2c66affSColin Finck PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 277c2c66affSColin Finck BOOLEAN SdAllocated; 278c2c66affSColin Finck BOOLEAN Result; 279c2c66affSColin Finck ACCESS_MASK GrantedAccess = 0; 280c2c66affSColin Finck PPRIVILEGE_SET Privileges = NULL; 281c2c66affSColin Finck NTSTATUS Status; 282c2c66affSColin Finck PAGED_CODE(); 283c2c66affSColin Finck 284c2c66affSColin Finck /* Get the header and type */ 285c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 286c2c66affSColin Finck ObjectType = ObjectHeader->Type; 287c2c66affSColin Finck 288c2c66affSColin Finck /* Get the security descriptor */ 289c2c66affSColin Finck Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 290c2c66affSColin Finck if (!NT_SUCCESS(Status)) 291c2c66affSColin Finck { 292c2c66affSColin Finck /* We failed */ 293c2c66affSColin Finck *AccessStatus = Status; 294c2c66affSColin Finck return FALSE; 295c2c66affSColin Finck } 296c2c66affSColin Finck 297c2c66affSColin Finck /* First try to perform a fast traverse check 298c2c66affSColin Finck * If it fails, then the entire access check will 299c2c66affSColin Finck * have to be done. 300c2c66affSColin Finck */ 301c2c66affSColin Finck Result = SeFastTraverseCheck(SecurityDescriptor, 302c2c66affSColin Finck AccessState, 303c2c66affSColin Finck FILE_WRITE_DATA, 304c2c66affSColin Finck AccessMode); 305c2c66affSColin Finck if (Result) 306c2c66affSColin Finck { 307c2c66affSColin Finck ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 308c2c66affSColin Finck return TRUE; 309c2c66affSColin Finck } 310c2c66affSColin Finck 311c2c66affSColin Finck /* Lock the security context */ 312c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 313c2c66affSColin Finck 314c2c66affSColin Finck /* Now do the entire access check */ 315c2c66affSColin Finck Result = SeAccessCheck(SecurityDescriptor, 316c2c66affSColin Finck &AccessState->SubjectSecurityContext, 317c2c66affSColin Finck TRUE, 318c2c66affSColin Finck TraverseAccess, 319c2c66affSColin Finck 0, 320c2c66affSColin Finck &Privileges, 321c2c66affSColin Finck &ObjectType->TypeInfo.GenericMapping, 322c2c66affSColin Finck AccessMode, 323c2c66affSColin Finck &GrantedAccess, 324c2c66affSColin Finck AccessStatus); 325c2c66affSColin Finck if (Privileges) 326c2c66affSColin Finck { 327c2c66affSColin Finck /* We got privileges, append them to the access state and free them */ 328c2c66affSColin Finck Status = SeAppendPrivileges(AccessState, Privileges); 329c2c66affSColin Finck SeFreePrivileges(Privileges); 330c2c66affSColin Finck } 331c2c66affSColin Finck 332c2c66affSColin Finck /* We're done, unlock the context and release security */ 333c2c66affSColin Finck SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 334c2c66affSColin Finck ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 335c2c66affSColin Finck return Result; 336c2c66affSColin Finck } 337c2c66affSColin Finck 338c2c66affSColin Finck BOOLEAN 339c2c66affSColin Finck NTAPI 340c2c66affSColin Finck ObpCheckObjectReference(IN PVOID Object, 341c2c66affSColin Finck IN OUT PACCESS_STATE AccessState, 342c2c66affSColin Finck IN BOOLEAN LockHeld, 343c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 344c2c66affSColin Finck OUT PNTSTATUS AccessStatus) 345c2c66affSColin Finck { 346c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 347c2c66affSColin Finck POBJECT_TYPE ObjectType; 348c2c66affSColin Finck PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 349c2c66affSColin Finck BOOLEAN SdAllocated; 350c2c66affSColin Finck BOOLEAN Result; 351c2c66affSColin Finck ACCESS_MASK GrantedAccess = 0; 352c2c66affSColin Finck PPRIVILEGE_SET Privileges = NULL; 353c2c66affSColin Finck NTSTATUS Status; 354c2c66affSColin Finck PAGED_CODE(); 355c2c66affSColin Finck 356c2c66affSColin Finck /* Get the header and type */ 357c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 358c2c66affSColin Finck ObjectType = ObjectHeader->Type; 359c2c66affSColin Finck 360c2c66affSColin Finck /* Get the security descriptor */ 361c2c66affSColin Finck Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 362c2c66affSColin Finck if (!NT_SUCCESS(Status)) 363c2c66affSColin Finck { 364c2c66affSColin Finck /* We failed */ 365c2c66affSColin Finck *AccessStatus = Status; 366c2c66affSColin Finck return FALSE; 367c2c66affSColin Finck } 368c2c66affSColin Finck 369c2c66affSColin Finck /* Lock the security context */ 370c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 371c2c66affSColin Finck 372c2c66affSColin Finck /* Now do the entire access check */ 373c2c66affSColin Finck Result = SeAccessCheck(SecurityDescriptor, 374c2c66affSColin Finck &AccessState->SubjectSecurityContext, 375c2c66affSColin Finck TRUE, 376c2c66affSColin Finck AccessState->RemainingDesiredAccess, 377c2c66affSColin Finck AccessState->PreviouslyGrantedAccess, 378c2c66affSColin Finck &Privileges, 379c2c66affSColin Finck &ObjectType->TypeInfo.GenericMapping, 380c2c66affSColin Finck AccessMode, 381c2c66affSColin Finck &GrantedAccess, 382c2c66affSColin Finck AccessStatus); 383c2c66affSColin Finck if (Result) 384c2c66affSColin Finck { 385c2c66affSColin Finck /* Update the access state */ 386c2c66affSColin Finck AccessState->RemainingDesiredAccess &= ~GrantedAccess; 387c2c66affSColin Finck AccessState->PreviouslyGrantedAccess |= GrantedAccess; 388c2c66affSColin Finck } 389c2c66affSColin Finck 390c2c66affSColin Finck /* Check if we have an SD */ 391c2c66affSColin Finck if (SecurityDescriptor) 392c2c66affSColin Finck { 393c2c66affSColin Finck /* Do audit alarm */ 394c2c66affSColin Finck #if 0 395c2c66affSColin Finck SeObjectReferenceAuditAlarm(&AccessState->OperationID, 396c2c66affSColin Finck Object, 397c2c66affSColin Finck SecurityDescriptor, 398c2c66affSColin Finck &AccessState->SubjectSecurityContext, 399c2c66affSColin Finck AccessState->RemainingDesiredAccess | 400c2c66affSColin Finck AccessState->PreviouslyGrantedAccess, 401c2c66affSColin Finck ((PAUX_ACCESS_DATA)(AccessState->AuxData))-> 402c2c66affSColin Finck PrivilegeSet, 403c2c66affSColin Finck Result, 404c2c66affSColin Finck AccessMode); 405c2c66affSColin Finck #endif 406c2c66affSColin Finck } 407c2c66affSColin Finck 408c2c66affSColin Finck /* We're done, unlock the context and release security */ 409c2c66affSColin Finck SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 410c2c66affSColin Finck ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 411c2c66affSColin Finck return Result; 412c2c66affSColin Finck } 413c2c66affSColin Finck 414c2c66affSColin Finck /*++ 415c2c66affSColin Finck * @name ObCheckObjectAccess 416c2c66affSColin Finck * 417c2c66affSColin Finck * The ObCheckObjectAccess routine <FILLMEIN> 418c2c66affSColin Finck * 419c2c66affSColin Finck * @param Object 420c2c66affSColin Finck * <FILLMEIN> 421c2c66affSColin Finck * 422c2c66affSColin Finck * @param AccessState 423c2c66affSColin Finck * <FILLMEIN> 424c2c66affSColin Finck * 425c2c66affSColin Finck * @param LockHeld 426c2c66affSColin Finck * <FILLMEIN> 427c2c66affSColin Finck * 428c2c66affSColin Finck * @param AccessMode 429c2c66affSColin Finck * <FILLMEIN> 430c2c66affSColin Finck * 431c2c66affSColin Finck * @param ReturnedStatus 432c2c66affSColin Finck * <FILLMEIN> 433c2c66affSColin Finck * 434c2c66affSColin Finck * @return TRUE if access was granted, FALSE otherwise. 435c2c66affSColin Finck * 436c2c66affSColin Finck * @remarks None. 437c2c66affSColin Finck * 438c2c66affSColin Finck *--*/ 439c2c66affSColin Finck BOOLEAN 440c2c66affSColin Finck NTAPI 441c2c66affSColin Finck ObCheckObjectAccess(IN PVOID Object, 442c2c66affSColin Finck IN OUT PACCESS_STATE AccessState, 443c2c66affSColin Finck IN BOOLEAN LockHeld, 444c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 445c2c66affSColin Finck OUT PNTSTATUS ReturnedStatus) 446c2c66affSColin Finck { 447c2c66affSColin Finck POBJECT_HEADER ObjectHeader; 448c2c66affSColin Finck POBJECT_TYPE ObjectType; 449c2c66affSColin Finck PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 450c2c66affSColin Finck BOOLEAN SdAllocated; 451c2c66affSColin Finck NTSTATUS Status; 452c2c66affSColin Finck BOOLEAN Result; 453c2c66affSColin Finck ACCESS_MASK GrantedAccess; 454c2c66affSColin Finck PPRIVILEGE_SET Privileges = NULL; 455c2c66affSColin Finck PAGED_CODE(); 456c2c66affSColin Finck 457c2c66affSColin Finck /* Get the object header and type */ 458c2c66affSColin Finck ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 459c2c66affSColin Finck ObjectType = ObjectHeader->Type; 460c2c66affSColin Finck 461c2c66affSColin Finck /* Get security information */ 462c2c66affSColin Finck Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 463c2c66affSColin Finck if (!NT_SUCCESS(Status)) 464c2c66affSColin Finck { 465c2c66affSColin Finck /* Return failure */ 466c2c66affSColin Finck *ReturnedStatus = Status; 467c2c66affSColin Finck return FALSE; 468c2c66affSColin Finck } 469c2c66affSColin Finck else if (!SecurityDescriptor) 470c2c66affSColin Finck { 471c2c66affSColin Finck /* Otherwise, if we don't actually have an SD, return success */ 472c2c66affSColin Finck *ReturnedStatus = Status; 473c2c66affSColin Finck return TRUE; 474c2c66affSColin Finck } 475c2c66affSColin Finck 476c2c66affSColin Finck /* Lock the security context */ 477c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 478c2c66affSColin Finck 479c2c66affSColin Finck /* Now do the entire access check */ 480c2c66affSColin Finck Result = SeAccessCheck(SecurityDescriptor, 481c2c66affSColin Finck &AccessState->SubjectSecurityContext, 482c2c66affSColin Finck TRUE, 483c2c66affSColin Finck AccessState->RemainingDesiredAccess, 484c2c66affSColin Finck AccessState->PreviouslyGrantedAccess, 485c2c66affSColin Finck &Privileges, 486c2c66affSColin Finck &ObjectType->TypeInfo.GenericMapping, 487c2c66affSColin Finck AccessMode, 488c2c66affSColin Finck &GrantedAccess, 489c2c66affSColin Finck ReturnedStatus); 490c2c66affSColin Finck if (Privileges) 491c2c66affSColin Finck { 492c2c66affSColin Finck /* We got privileges, append them to the access state and free them */ 493c2c66affSColin Finck Status = SeAppendPrivileges(AccessState, Privileges); 494c2c66affSColin Finck SeFreePrivileges(Privileges); 495c2c66affSColin Finck } 496c2c66affSColin Finck 497c2c66affSColin Finck /* Check if access was granted */ 498c2c66affSColin Finck if (Result) 499c2c66affSColin Finck { 500c2c66affSColin Finck /* Update the access state */ 501c2c66affSColin Finck AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 502c2c66affSColin Finck MAXIMUM_ALLOWED); 503c2c66affSColin Finck AccessState->PreviouslyGrantedAccess |= GrantedAccess; 504c2c66affSColin Finck } 505c2c66affSColin Finck 506c2c66affSColin Finck /* Do audit alarm */ 507c2c66affSColin Finck SeOpenObjectAuditAlarm(&ObjectType->Name, 508c2c66affSColin Finck Object, 509c2c66affSColin Finck NULL, 510c2c66affSColin Finck SecurityDescriptor, 511c2c66affSColin Finck AccessState, 512c2c66affSColin Finck FALSE, 513c2c66affSColin Finck Result, 514c2c66affSColin Finck AccessMode, 515c2c66affSColin Finck &AccessState->GenerateOnClose); 516c2c66affSColin Finck 517c2c66affSColin Finck /* We're done, unlock the context and release security */ 518c2c66affSColin Finck SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 519c2c66affSColin Finck ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 520c2c66affSColin Finck return Result; 521c2c66affSColin Finck } 522c2c66affSColin Finck 523c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/ 524c2c66affSColin Finck 525c2c66affSColin Finck /*++ 526c2c66affSColin Finck * @name ObAssignSecurity 527c2c66affSColin Finck * @implemented NT4 528c2c66affSColin Finck * 529c2c66affSColin Finck * The ObAssignSecurity routine <FILLMEIN> 530c2c66affSColin Finck * 531c2c66affSColin Finck * @param AccessState 532c2c66affSColin Finck * <FILLMEIN> 533c2c66affSColin Finck * 534c2c66affSColin Finck * @param SecurityDescriptor 535c2c66affSColin Finck * <FILLMEIN> 536c2c66affSColin Finck * 537c2c66affSColin Finck * @param Object 538c2c66affSColin Finck * <FILLMEIN> 539c2c66affSColin Finck * 540c2c66affSColin Finck * @param Type 541c2c66affSColin Finck * <FILLMEIN> 542c2c66affSColin Finck * 543c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 544c2c66affSColin Finck * 545c2c66affSColin Finck * @remarks None. 546c2c66affSColin Finck * 547c2c66affSColin Finck *--*/ 548c2c66affSColin Finck NTSTATUS 549c2c66affSColin Finck NTAPI 550c2c66affSColin Finck ObAssignSecurity(IN PACCESS_STATE AccessState, 551c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor, 552c2c66affSColin Finck IN PVOID Object, 553c2c66affSColin Finck IN POBJECT_TYPE Type) 554c2c66affSColin Finck { 555c2c66affSColin Finck PSECURITY_DESCRIPTOR NewDescriptor; 556c2c66affSColin Finck NTSTATUS Status; 557c2c66affSColin Finck KIRQL CalloutIrql; 558c2c66affSColin Finck PAGED_CODE(); 559c2c66affSColin Finck 560c2c66affSColin Finck /* Build the new security descriptor */ 561c2c66affSColin Finck Status = SeAssignSecurity(SecurityDescriptor, 562c2c66affSColin Finck AccessState->SecurityDescriptor, 563c2c66affSColin Finck &NewDescriptor, 564*2c909db2STimo Kreuzer (Type == ObpDirectoryObjectType), 565c2c66affSColin Finck &AccessState->SubjectSecurityContext, 566c2c66affSColin Finck &Type->TypeInfo.GenericMapping, 567c2c66affSColin Finck PagedPool); 568c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 569c2c66affSColin Finck 570c2c66affSColin Finck /* Call the security method */ 571c2c66affSColin Finck ObpCalloutStart(&CalloutIrql); 572c2c66affSColin Finck Status = Type->TypeInfo.SecurityProcedure(Object, 573c2c66affSColin Finck AssignSecurityDescriptor, 574c2c66affSColin Finck NULL, 575c2c66affSColin Finck NewDescriptor, 576c2c66affSColin Finck NULL, 577c2c66affSColin Finck NULL, 578c2c66affSColin Finck PagedPool, 579c2c66affSColin Finck &Type->TypeInfo.GenericMapping); 580c2c66affSColin Finck ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 581c2c66affSColin Finck 582c2c66affSColin Finck /* Check for failure and deassign security if so */ 583c2c66affSColin Finck if (!NT_SUCCESS(Status)) SeDeassignSecurity(&NewDescriptor); 584c2c66affSColin Finck 585c2c66affSColin Finck /* Return to caller */ 586c2c66affSColin Finck return Status; 587c2c66affSColin Finck } 588c2c66affSColin Finck 589c2c66affSColin Finck /*++ 590c2c66affSColin Finck * @name ObGetObjectSecurity 591c2c66affSColin Finck * @implemented NT4 592c2c66affSColin Finck * 593c2c66affSColin Finck * The ObGetObjectSecurity routine <FILLMEIN> 594c2c66affSColin Finck * 595c2c66affSColin Finck * @param Object 596c2c66affSColin Finck * <FILLMEIN> 597c2c66affSColin Finck * 598c2c66affSColin Finck * @param SecurityDescriptor 599c2c66affSColin Finck * <FILLMEIN> 600c2c66affSColin Finck * 601c2c66affSColin Finck * @param MemoryAllocated 602c2c66affSColin Finck * <FILLMEIN> 603c2c66affSColin Finck * 604c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 605c2c66affSColin Finck * 606c2c66affSColin Finck * @remarks None. 607c2c66affSColin Finck * 608c2c66affSColin Finck *--*/ 609c2c66affSColin Finck NTSTATUS 610c2c66affSColin Finck NTAPI 611c2c66affSColin Finck ObGetObjectSecurity(IN PVOID Object, 612c2c66affSColin Finck OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, 613c2c66affSColin Finck OUT PBOOLEAN MemoryAllocated) 614c2c66affSColin Finck { 615c2c66affSColin Finck POBJECT_HEADER Header; 616c2c66affSColin Finck POBJECT_TYPE Type; 617c2c66affSColin Finck ULONG Length = 0; 618c2c66affSColin Finck NTSTATUS Status; 619c2c66affSColin Finck SECURITY_INFORMATION SecurityInformation; 620c2c66affSColin Finck KIRQL CalloutIrql; 621c2c66affSColin Finck PAGED_CODE(); 622c2c66affSColin Finck 623c2c66affSColin Finck /* Get the object header and type */ 624c2c66affSColin Finck Header = OBJECT_TO_OBJECT_HEADER(Object); 625c2c66affSColin Finck Type = Header->Type; 626c2c66affSColin Finck 627c2c66affSColin Finck /* Tell the caller that we didn't have to allocate anything yet */ 628c2c66affSColin Finck *MemoryAllocated = FALSE; 629c2c66affSColin Finck 630c2c66affSColin Finck /* Check if the object uses default security */ 631c2c66affSColin Finck if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) 632c2c66affSColin Finck { 633c2c66affSColin Finck /* Reference the descriptor */ 634c2c66affSColin Finck *SecurityDescriptor = ObpReferenceSecurityDescriptor(Header); 635c2c66affSColin Finck return STATUS_SUCCESS; 636c2c66affSColin Finck } 637c2c66affSColin Finck 638c2c66affSColin Finck /* Set mask to query */ 639c2c66affSColin Finck SecurityInformation = OWNER_SECURITY_INFORMATION | 640c2c66affSColin Finck GROUP_SECURITY_INFORMATION | 641c2c66affSColin Finck DACL_SECURITY_INFORMATION | 642c2c66affSColin Finck SACL_SECURITY_INFORMATION; 643c2c66affSColin Finck 644c2c66affSColin Finck /* Get the security descriptor size */ 645c2c66affSColin Finck ObpCalloutStart(&CalloutIrql); 646c2c66affSColin Finck Status = Type->TypeInfo.SecurityProcedure(Object, 647c2c66affSColin Finck QuerySecurityDescriptor, 648c2c66affSColin Finck &SecurityInformation, 649c2c66affSColin Finck *SecurityDescriptor, 650c2c66affSColin Finck &Length, 651c2c66affSColin Finck &Header->SecurityDescriptor, 652c2c66affSColin Finck Type->TypeInfo.PoolType, 653c2c66affSColin Finck &Type->TypeInfo.GenericMapping); 654c2c66affSColin Finck ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 655c2c66affSColin Finck 656c2c66affSColin Finck /* Check for failure */ 657c2c66affSColin Finck if (Status != STATUS_BUFFER_TOO_SMALL) return Status; 658c2c66affSColin Finck 659c2c66affSColin Finck /* Allocate security descriptor */ 660c2c66affSColin Finck *SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, 661c2c66affSColin Finck Length, 662c2c66affSColin Finck TAG_SEC_QUERY); 663c2c66affSColin Finck if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES; 664c2c66affSColin Finck *MemoryAllocated = TRUE; 665c2c66affSColin Finck 666c2c66affSColin Finck /* Query security descriptor */ 667c2c66affSColin Finck ObpCalloutStart(&CalloutIrql); 668c2c66affSColin Finck Status = Type->TypeInfo.SecurityProcedure(Object, 669c2c66affSColin Finck QuerySecurityDescriptor, 670c2c66affSColin Finck &SecurityInformation, 671c2c66affSColin Finck *SecurityDescriptor, 672c2c66affSColin Finck &Length, 673c2c66affSColin Finck &Header->SecurityDescriptor, 674c2c66affSColin Finck Type->TypeInfo.PoolType, 675c2c66affSColin Finck &Type->TypeInfo.GenericMapping); 676c2c66affSColin Finck ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 677c2c66affSColin Finck 678c2c66affSColin Finck /* Check for failure */ 679c2c66affSColin Finck if (!NT_SUCCESS(Status)) 680c2c66affSColin Finck { 681c2c66affSColin Finck /* Free the descriptor and tell the caller we failed */ 682c2c66affSColin Finck ExFreePoolWithTag(*SecurityDescriptor, TAG_SEC_QUERY); 683c2c66affSColin Finck *MemoryAllocated = FALSE; 684c2c66affSColin Finck } 685c2c66affSColin Finck 686c2c66affSColin Finck /* Return status */ 687c2c66affSColin Finck return Status; 688c2c66affSColin Finck } 689c2c66affSColin Finck 690c2c66affSColin Finck /*++ 691c2c66affSColin Finck * @name ObReleaseObjectSecurity 692c2c66affSColin Finck * @implemented NT4 693c2c66affSColin Finck * 694c2c66affSColin Finck * The ObReleaseObjectSecurity routine <FILLMEIN> 695c2c66affSColin Finck * 696c2c66affSColin Finck * @param SecurityDescriptor 697c2c66affSColin Finck * <FILLMEIN> 698c2c66affSColin Finck * 699c2c66affSColin Finck * @param MemoryAllocated 700c2c66affSColin Finck * <FILLMEIN> 701c2c66affSColin Finck * 702c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 703c2c66affSColin Finck * 704c2c66affSColin Finck * @remarks None. 705c2c66affSColin Finck * 706c2c66affSColin Finck *--*/ 707c2c66affSColin Finck VOID 708c2c66affSColin Finck NTAPI 709c2c66affSColin Finck ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 710c2c66affSColin Finck IN BOOLEAN MemoryAllocated) 711c2c66affSColin Finck { 712c2c66affSColin Finck PAGED_CODE(); 713c2c66affSColin Finck 714c2c66affSColin Finck /* Nothing to do in this case */ 715c2c66affSColin Finck if (!SecurityDescriptor) return; 716c2c66affSColin Finck 717c2c66affSColin Finck /* Check if we had allocated it from memory */ 718c2c66affSColin Finck if (MemoryAllocated) 719c2c66affSColin Finck { 720c2c66affSColin Finck /* Free it */ 721c2c66affSColin Finck ExFreePool(SecurityDescriptor); 722c2c66affSColin Finck } 723c2c66affSColin Finck else 724c2c66affSColin Finck { 725c2c66affSColin Finck /* Otherwise this means we used an internal descriptor */ 726c2c66affSColin Finck ObDereferenceSecurityDescriptor(SecurityDescriptor, 1); 727c2c66affSColin Finck } 728c2c66affSColin Finck } 729c2c66affSColin Finck 730c2c66affSColin Finck /*++ 731c2c66affSColin Finck * @name ObSetSecurityObjectByPointer 732c2c66affSColin Finck * @implemented NT5.1 733c2c66affSColin Finck * 734c2c66affSColin Finck * The ObSetSecurityObjectByPointer routine <FILLMEIN> 735c2c66affSColin Finck * 736c2c66affSColin Finck * @param SecurityDescriptor 737c2c66affSColin Finck * <FILLMEIN> 738c2c66affSColin Finck * 739c2c66affSColin Finck * @param MemoryAllocated 740c2c66affSColin Finck * <FILLMEIN> 741c2c66affSColin Finck * 742c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 743c2c66affSColin Finck * 744c2c66affSColin Finck * @remarks None. 745c2c66affSColin Finck * 746c2c66affSColin Finck *--*/ 747c2c66affSColin Finck NTSTATUS 748c2c66affSColin Finck NTAPI 749c2c66affSColin Finck ObSetSecurityObjectByPointer(IN PVOID Object, 750c2c66affSColin Finck IN SECURITY_INFORMATION SecurityInformation, 751c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor) 752c2c66affSColin Finck { 753c2c66affSColin Finck POBJECT_TYPE Type; 754c2c66affSColin Finck POBJECT_HEADER Header; 755c2c66affSColin Finck PAGED_CODE(); 756c2c66affSColin Finck 757c2c66affSColin Finck /* Get the header and type */ 758c2c66affSColin Finck Header = OBJECT_TO_OBJECT_HEADER(Object); 759c2c66affSColin Finck Type = Header->Type; 760c2c66affSColin Finck 761c2c66affSColin Finck /* Sanity check */ 762c2c66affSColin Finck ASSERT(SecurityDescriptor); 763c2c66affSColin Finck 764c2c66affSColin Finck /* Call the security procedure */ 765c2c66affSColin Finck return Type->TypeInfo.SecurityProcedure(Object, 766c2c66affSColin Finck SetSecurityDescriptor, 767c2c66affSColin Finck &SecurityInformation, 768c2c66affSColin Finck SecurityDescriptor, 769c2c66affSColin Finck NULL, 770c2c66affSColin Finck &Header->SecurityDescriptor, 771c2c66affSColin Finck Type->TypeInfo.PoolType, 772c2c66affSColin Finck &Type->TypeInfo.GenericMapping); 773c2c66affSColin Finck } 774c2c66affSColin Finck 775c2c66affSColin Finck /*++ 776c2c66affSColin Finck * @name NtQuerySecurityObject 777c2c66affSColin Finck * @implemented NT4 778c2c66affSColin Finck * 779c2c66affSColin Finck * The NtQuerySecurityObject routine <FILLMEIN> 780c2c66affSColin Finck * 781c2c66affSColin Finck * @param Handle 782c2c66affSColin Finck * <FILLMEIN> 783c2c66affSColin Finck * 784c2c66affSColin Finck * @param SecurityInformation 785c2c66affSColin Finck * <FILLMEIN> 786c2c66affSColin Finck * 787c2c66affSColin Finck * @param SecurityDescriptor 788c2c66affSColin Finck * <FILLMEIN> 789c2c66affSColin Finck * 790c2c66affSColin Finck * @param Length 791c2c66affSColin Finck * <FILLMEIN> 792c2c66affSColin Finck * 793c2c66affSColin Finck * @param ResultLength 794c2c66affSColin Finck * <FILLMEIN> 795c2c66affSColin Finck * 796c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 797c2c66affSColin Finck * 798c2c66affSColin Finck * @remarks None. 799c2c66affSColin Finck * 800c2c66affSColin Finck *--*/ 801c2c66affSColin Finck NTSTATUS 802c2c66affSColin Finck NTAPI 803c2c66affSColin Finck NtQuerySecurityObject(IN HANDLE Handle, 804c2c66affSColin Finck IN SECURITY_INFORMATION SecurityInformation, 805c2c66affSColin Finck OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 806c2c66affSColin Finck IN ULONG Length, 807c2c66affSColin Finck OUT PULONG ResultLength) 808c2c66affSColin Finck { 809c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 810c2c66affSColin Finck PVOID Object; 811c2c66affSColin Finck POBJECT_HEADER Header; 812c2c66affSColin Finck POBJECT_TYPE Type; 813c2c66affSColin Finck ACCESS_MASK DesiredAccess; 814c2c66affSColin Finck NTSTATUS Status; 815c2c66affSColin Finck PAGED_CODE(); 816c2c66affSColin Finck 817c2c66affSColin Finck /* Check if we came from user mode */ 818c2c66affSColin Finck if (PreviousMode != KernelMode) 819c2c66affSColin Finck { 820c2c66affSColin Finck /* Enter SEH */ 821c2c66affSColin Finck _SEH2_TRY 822c2c66affSColin Finck { 823c2c66affSColin Finck /* Probe the SD and the length pointer */ 824c2c66affSColin Finck ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG)); 825c2c66affSColin Finck ProbeForWriteUlong(ResultLength); 826c2c66affSColin Finck } 827c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 828c2c66affSColin Finck { 829c2c66affSColin Finck /* Return the exception code */ 830c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 831c2c66affSColin Finck } 832c2c66affSColin Finck _SEH2_END; 833c2c66affSColin Finck } 834c2c66affSColin Finck 835c2c66affSColin Finck /* Get the required access rights for the operation */ 836c2c66affSColin Finck SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess); 837c2c66affSColin Finck 838c2c66affSColin Finck /* Reference the object */ 839c2c66affSColin Finck Status = ObReferenceObjectByHandle(Handle, 840c2c66affSColin Finck DesiredAccess, 841c2c66affSColin Finck NULL, 842c2c66affSColin Finck PreviousMode, 843c2c66affSColin Finck &Object, 844c2c66affSColin Finck NULL); 845c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 846c2c66affSColin Finck 847c2c66affSColin Finck /* Get the Object Header and Type */ 848c2c66affSColin Finck Header = OBJECT_TO_OBJECT_HEADER(Object); 849c2c66affSColin Finck Type = Header->Type; 850c2c66affSColin Finck 851c2c66affSColin Finck /* Call the security procedure's query function */ 852c2c66affSColin Finck Status = Type->TypeInfo.SecurityProcedure(Object, 853c2c66affSColin Finck QuerySecurityDescriptor, 854c2c66affSColin Finck &SecurityInformation, 855c2c66affSColin Finck SecurityDescriptor, 856c2c66affSColin Finck &Length, 857c2c66affSColin Finck &Header->SecurityDescriptor, 858c2c66affSColin Finck Type->TypeInfo.PoolType, 859c2c66affSColin Finck &Type->TypeInfo.GenericMapping); 860c2c66affSColin Finck 861c2c66affSColin Finck /* Dereference the object */ 862c2c66affSColin Finck ObDereferenceObject(Object); 863c2c66affSColin Finck 864c2c66affSColin Finck /* Protect write with SEH */ 865c2c66affSColin Finck _SEH2_TRY 866c2c66affSColin Finck { 867c2c66affSColin Finck /* Return the needed length */ 868c2c66affSColin Finck *ResultLength = Length; 869c2c66affSColin Finck } 870c2c66affSColin Finck _SEH2_EXCEPT(ExSystemExceptionFilter()) 871c2c66affSColin Finck { 872c2c66affSColin Finck /* Get the exception code */ 873c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 874c2c66affSColin Finck } 875c2c66affSColin Finck _SEH2_END; 876c2c66affSColin Finck 877c2c66affSColin Finck /* Return status */ 878c2c66affSColin Finck return Status; 879c2c66affSColin Finck } 880c2c66affSColin Finck 881c2c66affSColin Finck /*++ 882c2c66affSColin Finck * @name NtSetSecurityObject 883c2c66affSColin Finck * @implemented NT4 884c2c66affSColin Finck * 885c2c66affSColin Finck * The NtSetSecurityObject routine <FILLMEIN> 886c2c66affSColin Finck * 887c2c66affSColin Finck * @param Handle 888c2c66affSColin Finck * <FILLMEIN> 889c2c66affSColin Finck * 890c2c66affSColin Finck * @param SecurityInformation 891c2c66affSColin Finck * <FILLMEIN> 892c2c66affSColin Finck * 893c2c66affSColin Finck * @param SecurityDescriptor 894c2c66affSColin Finck * <FILLMEIN> 895c2c66affSColin Finck * 896c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 897c2c66affSColin Finck * 898c2c66affSColin Finck * @remarks None. 899c2c66affSColin Finck * 900c2c66affSColin Finck *--*/ 901c2c66affSColin Finck NTSTATUS 902c2c66affSColin Finck NTAPI 903c2c66affSColin Finck NtSetSecurityObject(IN HANDLE Handle, 904c2c66affSColin Finck IN SECURITY_INFORMATION SecurityInformation, 905c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor) 906c2c66affSColin Finck { 907c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 908c2c66affSColin Finck PVOID Object; 909c2c66affSColin Finck SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor; 910c2c66affSColin Finck ACCESS_MASK DesiredAccess = 0; 911c2c66affSColin Finck NTSTATUS Status; 912c2c66affSColin Finck PAGED_CODE(); 913c2c66affSColin Finck 914c2c66affSColin Finck /* Make sure the caller doesn't pass a NULL security descriptor! */ 915c2c66affSColin Finck if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION; 916c2c66affSColin Finck 917c2c66affSColin Finck /* Set the required access rights for the operation */ 918c2c66affSColin Finck SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess); 919c2c66affSColin Finck 920c2c66affSColin Finck /* Reference the object */ 921c2c66affSColin Finck Status = ObReferenceObjectByHandle(Handle, 922c2c66affSColin Finck DesiredAccess, 923c2c66affSColin Finck NULL, 924c2c66affSColin Finck PreviousMode, 925c2c66affSColin Finck &Object, 926c2c66affSColin Finck NULL); 927c2c66affSColin Finck if (NT_SUCCESS(Status)) 928c2c66affSColin Finck { 929c2c66affSColin Finck /* Capture and make a copy of the security descriptor */ 930c2c66affSColin Finck Status = SeCaptureSecurityDescriptor(SecurityDescriptor, 931c2c66affSColin Finck PreviousMode, 932c2c66affSColin Finck PagedPool, 933c2c66affSColin Finck TRUE, 934c2c66affSColin Finck (PSECURITY_DESCRIPTOR*) 935c2c66affSColin Finck &CapturedDescriptor); 936c2c66affSColin Finck if (!NT_SUCCESS(Status)) 937c2c66affSColin Finck { 938c2c66affSColin Finck /* Fail */ 939c2c66affSColin Finck ObDereferenceObject(Object); 940c2c66affSColin Finck return Status; 941c2c66affSColin Finck } 942c2c66affSColin Finck 943c2c66affSColin Finck /* Sanity check */ 944c2c66affSColin Finck ASSERT(CapturedDescriptor->Control & SE_SELF_RELATIVE); 945c2c66affSColin Finck 946c2c66affSColin Finck /* 947c2c66affSColin Finck * Make sure the security descriptor passed by the caller 948c2c66affSColin Finck * is valid for the operation we're about to perform 949c2c66affSColin Finck */ 950c2c66affSColin Finck if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && 951c2c66affSColin Finck !(CapturedDescriptor->Owner)) || 952c2c66affSColin Finck ((SecurityInformation & GROUP_SECURITY_INFORMATION) && 953c2c66affSColin Finck !(CapturedDescriptor->Group))) 954c2c66affSColin Finck { 955c2c66affSColin Finck /* Set the failure status */ 956c2c66affSColin Finck Status = STATUS_INVALID_SECURITY_DESCR; 957c2c66affSColin Finck } 958c2c66affSColin Finck else 959c2c66affSColin Finck { 960c2c66affSColin Finck /* Set security */ 961c2c66affSColin Finck Status = ObSetSecurityObjectByPointer(Object, 962c2c66affSColin Finck SecurityInformation, 963c2c66affSColin Finck CapturedDescriptor); 964c2c66affSColin Finck } 965c2c66affSColin Finck 966c2c66affSColin Finck /* Release the descriptor and return status */ 967c2c66affSColin Finck SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedDescriptor, 968c2c66affSColin Finck PreviousMode, 969c2c66affSColin Finck TRUE); 970c2c66affSColin Finck 971c2c66affSColin Finck /* Now we can dereference the object */ 972c2c66affSColin Finck ObDereferenceObject(Object); 973c2c66affSColin Finck } 974c2c66affSColin Finck 975c2c66affSColin Finck return Status; 976c2c66affSColin Finck } 977c2c66affSColin Finck 978c2c66affSColin Finck /*++ 979c2c66affSColin Finck * @name ObQueryObjectAuditingByHandle 980c2c66affSColin Finck * @implemented NT5 981c2c66affSColin Finck * 982c2c66affSColin Finck * The ObDereferenceSecurityDescriptor routine <FILLMEIN> 983c2c66affSColin Finck * 984c2c66affSColin Finck * @param SecurityDescriptor 985c2c66affSColin Finck * <FILLMEIN> 986c2c66affSColin Finck * 987c2c66affSColin Finck * @param Count 988c2c66affSColin Finck * <FILLMEIN> 989c2c66affSColin Finck * 990c2c66affSColin Finck * @return STATUS_SUCCESS or appropriate error value. 991c2c66affSColin Finck * 992c2c66affSColin Finck * @remarks None. 993c2c66affSColin Finck * 994c2c66affSColin Finck *--*/ 995c2c66affSColin Finck NTSTATUS 996c2c66affSColin Finck NTAPI 997c2c66affSColin Finck ObQueryObjectAuditingByHandle(IN HANDLE Handle, 998c2c66affSColin Finck OUT PBOOLEAN GenerateOnClose) 999c2c66affSColin Finck { 1000c2c66affSColin Finck PHANDLE_TABLE_ENTRY HandleEntry; 1001c2c66affSColin Finck PVOID HandleTable; 1002c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 1003c2c66affSColin Finck PAGED_CODE(); 1004c2c66affSColin Finck 1005c2c66affSColin Finck /* Check if we're dealing with a kernel handle */ 1006c2c66affSColin Finck if (ObpIsKernelHandle(Handle, ExGetPreviousMode())) 1007c2c66affSColin Finck { 1008c2c66affSColin Finck /* Use the kernel table and convert the handle */ 1009c2c66affSColin Finck HandleTable = ObpKernelHandleTable; 1010c2c66affSColin Finck Handle = ObKernelHandleToHandle(Handle); 1011c2c66affSColin Finck } 1012c2c66affSColin Finck else 1013c2c66affSColin Finck { 1014c2c66affSColin Finck /* Use the process's handle table */ 1015c2c66affSColin Finck HandleTable = PsGetCurrentProcess()->ObjectTable; 1016c2c66affSColin Finck } 1017c2c66affSColin Finck 1018c2c66affSColin Finck /* Enter a critical region while we touch the handle table */ 1019c2c66affSColin Finck KeEnterCriticalRegion(); 1020c2c66affSColin Finck 1021c2c66affSColin Finck /* Map the handle */ 1022c2c66affSColin Finck HandleEntry = ExMapHandleToPointer(HandleTable, Handle); 1023c2c66affSColin Finck if(HandleEntry) 1024c2c66affSColin Finck { 1025c2c66affSColin Finck /* Check if the flag is set */ 1026c2c66affSColin Finck *GenerateOnClose = HandleEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE; 1027c2c66affSColin Finck 1028c2c66affSColin Finck /* Unlock the entry */ 1029c2c66affSColin Finck ExUnlockHandleTableEntry(HandleTable, HandleEntry); 1030c2c66affSColin Finck } 1031c2c66affSColin Finck else 1032c2c66affSColin Finck { 1033c2c66affSColin Finck /* Otherwise, fail */ 1034c2c66affSColin Finck Status = STATUS_INVALID_HANDLE; 1035c2c66affSColin Finck } 1036c2c66affSColin Finck 1037c2c66affSColin Finck /* Leave the critical region and return the status */ 1038c2c66affSColin Finck KeLeaveCriticalRegion(); 1039c2c66affSColin Finck return Status; 1040c2c66affSColin Finck } 1041c2c66affSColin Finck 1042c2c66affSColin Finck /* EOF */ 1043