Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenobsecure.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ob/obsecure.c 00005 * PURPOSE: SRM Interface of the Object Manager 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 * Eric Kohl 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* PRIVATE FUNCTIONS *********************************************************/ 00017 00018 NTSTATUS 00019 NTAPI 00020 ObAssignObjectSecurityDescriptor(IN PVOID Object, 00021 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, 00022 IN POOL_TYPE PoolType) 00023 { 00024 POBJECT_HEADER ObjectHeader; 00025 NTSTATUS Status; 00026 PSECURITY_DESCRIPTOR NewSd; 00027 PEX_FAST_REF FastRef; 00028 PAGED_CODE(); 00029 00030 /* Get the object header */ 00031 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00032 FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor; 00033 if (!SecurityDescriptor) 00034 { 00035 /* Nothing to assign */ 00036 ExInitializeFastReference(FastRef, NULL); 00037 return STATUS_SUCCESS; 00038 } 00039 00040 /* Add it to our internal cache */ 00041 Status = ObLogSecurityDescriptor(SecurityDescriptor, 00042 &NewSd, 00043 MAX_FAST_REFS + 1); 00044 if (NT_SUCCESS(Status)) 00045 { 00046 /* Free the old copy */ 00047 ExFreePoolWithTag(SecurityDescriptor, TAG_SD); 00048 00049 /* Set the new pointer */ 00050 ASSERT(NewSd); 00051 ExInitializeFastReference(FastRef, NewSd); 00052 } 00053 00054 /* Return status */ 00055 return Status; 00056 } 00057 00058 NTSTATUS 00059 NTAPI 00060 ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) 00061 { 00062 EX_FAST_REF FastRef; 00063 ULONG Count; 00064 PSECURITY_DESCRIPTOR OldSecurityDescriptor; 00065 00066 /* Get the fast reference and capture it */ 00067 FastRef = *(PEX_FAST_REF)SecurityDescriptor; 00068 00069 /* Don't free again later */ 00070 *SecurityDescriptor = NULL; 00071 00072 /* Get the descriptor and reference count */ 00073 OldSecurityDescriptor = ExGetObjectFastReference(FastRef); 00074 Count = ExGetCountFastReference(FastRef); 00075 00076 /* Dereference the descriptor */ 00077 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1); 00078 00079 /* All done */ 00080 return STATUS_SUCCESS; 00081 } 00082 00083 NTSTATUS 00084 NTAPI 00085 ObQuerySecurityDescriptorInfo(IN PVOID Object, 00086 IN PSECURITY_INFORMATION SecurityInformation, 00087 OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 00088 IN OUT PULONG Length, 00089 IN PSECURITY_DESCRIPTOR *OutputSecurityDescriptor) 00090 { 00091 POBJECT_HEADER ObjectHeader; 00092 NTSTATUS Status; 00093 PSECURITY_DESCRIPTOR ObjectSd; 00094 PAGED_CODE(); 00095 00096 /* Get the object header */ 00097 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00098 00099 /* Get the SD */ 00100 ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader); 00101 00102 /* Query the information */ 00103 Status = SeQuerySecurityDescriptorInfo(SecurityInformation, 00104 SecurityDescriptor, 00105 Length, 00106 &ObjectSd); 00107 00108 /* Check if we have an object SD and dereference it, if so */ 00109 if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1); 00110 00111 /* Return status */ 00112 return Status; 00113 } 00114 00115 NTSTATUS 00116 NTAPI 00117 ObSetSecurityDescriptorInfo(IN PVOID Object, 00118 IN PSECURITY_INFORMATION SecurityInformation, 00119 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 00120 IN OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, 00121 IN POOL_TYPE PoolType, 00122 IN PGENERIC_MAPPING GenericMapping) 00123 { 00124 NTSTATUS Status; 00125 POBJECT_HEADER ObjectHeader; 00126 PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor; 00127 PEX_FAST_REF FastRef; 00128 EX_FAST_REF OldValue; 00129 ULONG Count; 00130 PAGED_CODE(); 00131 00132 /* Get the object header */ 00133 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00134 while (TRUE) 00135 { 00136 /* Reference the old descriptor */ 00137 OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader); 00138 NewDescriptor = OldDescriptor; 00139 00140 /* Set the SD information */ 00141 Status = SeSetSecurityDescriptorInfo(Object, 00142 SecurityInformation, 00143 SecurityDescriptor, 00144 &NewDescriptor, 00145 PoolType, 00146 GenericMapping); 00147 if (NT_SUCCESS(Status)) 00148 { 00149 /* Now add this to the cache */ 00150 Status = ObLogSecurityDescriptor(NewDescriptor, 00151 &CachedDescriptor, 00152 MAX_FAST_REFS + 1); 00153 00154 /* Let go of our uncached copy */ 00155 ExFreePool(NewDescriptor); 00156 00157 /* Check for success */ 00158 if (NT_SUCCESS(Status)) 00159 { 00160 /* Do the swap */ 00161 FastRef = (PEX_FAST_REF)OutputSecurityDescriptor; 00162 OldValue = ExCompareSwapFastReference(FastRef, 00163 CachedDescriptor, 00164 OldDescriptor); 00165 00166 /* Get the security descriptor */ 00167 SecurityDescriptor = ExGetObjectFastReference(OldValue); 00168 Count = ExGetCountFastReference(OldValue); 00169 00170 /* Make sure the swap worked */ 00171 if (SecurityDescriptor == OldDescriptor) 00172 { 00173 /* Flush waiters */ 00174 ObpAcquireObjectLock(ObjectHeader); 00175 ObpReleaseObjectLock(ObjectHeader); 00176 00177 /* And dereference the old one */ 00178 ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2); 00179 break; 00180 } 00181 else 00182 { 00183 /* Someone changed it behind our back -- try again */ 00184 ObDereferenceSecurityDescriptor(OldDescriptor, 1); 00185 ObDereferenceSecurityDescriptor(CachedDescriptor, 00186 MAX_FAST_REFS + 1); 00187 } 00188 } 00189 else 00190 { 00191 /* We failed, dereference the old one */ 00192 ObDereferenceSecurityDescriptor(OldDescriptor, 1); 00193 break; 00194 } 00195 } 00196 else 00197 { 00198 /* We failed, dereference the old one */ 00199 if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1); 00200 break; 00201 } 00202 } 00203 00204 /* Return status */ 00205 return Status; 00206 } 00207 00208 BOOLEAN 00209 NTAPI 00210 ObCheckCreateObjectAccess(IN PVOID Object, 00211 IN ACCESS_MASK CreateAccess, 00212 IN PACCESS_STATE AccessState, 00213 IN PUNICODE_STRING ComponentName, 00214 IN BOOLEAN LockHeld, 00215 IN KPROCESSOR_MODE AccessMode, 00216 OUT PNTSTATUS AccessStatus) 00217 { 00218 POBJECT_HEADER ObjectHeader; 00219 POBJECT_TYPE ObjectType; 00220 PSECURITY_DESCRIPTOR SecurityDescriptor; 00221 BOOLEAN SdAllocated; 00222 BOOLEAN Result = TRUE; 00223 ACCESS_MASK GrantedAccess = 0; 00224 PPRIVILEGE_SET Privileges = NULL; 00225 NTSTATUS Status; 00226 PAGED_CODE(); 00227 00228 /* Get the header and type */ 00229 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00230 ObjectType = ObjectHeader->Type; 00231 00232 /* Get the security descriptor */ 00233 Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 00234 if (!NT_SUCCESS(Status)) 00235 { 00236 /* We failed */ 00237 *AccessStatus = Status; 00238 return FALSE; 00239 } 00240 00241 /* Lock the security context */ 00242 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00243 00244 /* Check if we have an SD */ 00245 if (SecurityDescriptor) 00246 { 00247 /* Now do the entire access check */ 00248 Result = SeAccessCheck(SecurityDescriptor, 00249 &AccessState->SubjectSecurityContext, 00250 TRUE, 00251 CreateAccess, 00252 0, 00253 &Privileges, 00254 &ObjectType->TypeInfo.GenericMapping, 00255 AccessMode, 00256 &GrantedAccess, 00257 AccessStatus); 00258 if (Privileges) 00259 { 00260 /* We got privileges, append them to the access state and free them */ 00261 Status = SeAppendPrivileges(AccessState, Privileges); 00262 SeFreePrivileges(Privileges); 00263 } 00264 } 00265 00266 /* We're done, unlock the context and release security */ 00267 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 00268 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 00269 return Result; 00270 } 00271 00272 BOOLEAN 00273 NTAPI 00274 ObpCheckTraverseAccess(IN PVOID Object, 00275 IN ACCESS_MASK TraverseAccess, 00276 IN PACCESS_STATE AccessState OPTIONAL, 00277 IN BOOLEAN LockHeld, 00278 IN KPROCESSOR_MODE AccessMode, 00279 OUT PNTSTATUS AccessStatus) 00280 { 00281 POBJECT_HEADER ObjectHeader; 00282 POBJECT_TYPE ObjectType; 00283 PSECURITY_DESCRIPTOR SecurityDescriptor; 00284 BOOLEAN SdAllocated; 00285 BOOLEAN Result; 00286 ACCESS_MASK GrantedAccess = 0; 00287 PPRIVILEGE_SET Privileges = NULL; 00288 NTSTATUS Status; 00289 PAGED_CODE(); 00290 00291 /* Get the header and type */ 00292 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00293 ObjectType = ObjectHeader->Type; 00294 00295 /* Get the security descriptor */ 00296 Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 00297 if (!NT_SUCCESS(Status)) 00298 { 00299 /* We failed */ 00300 *AccessStatus = Status; 00301 return FALSE; 00302 } 00303 00304 /* Lock the security context */ 00305 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00306 00307 /* Now do the entire access check */ 00308 Result = SeAccessCheck(SecurityDescriptor, 00309 &AccessState->SubjectSecurityContext, 00310 TRUE, 00311 TraverseAccess, 00312 0, 00313 &Privileges, 00314 &ObjectType->TypeInfo.GenericMapping, 00315 AccessMode, 00316 &GrantedAccess, 00317 AccessStatus); 00318 if (Privileges) 00319 { 00320 /* We got privileges, append them to the access state and free them */ 00321 Status = SeAppendPrivileges(AccessState, Privileges); 00322 SeFreePrivileges(Privileges); 00323 } 00324 00325 /* We're done, unlock the context and release security */ 00326 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 00327 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 00328 return Result; 00329 } 00330 00331 BOOLEAN 00332 NTAPI 00333 ObpCheckObjectReference(IN PVOID Object, 00334 IN OUT PACCESS_STATE AccessState, 00335 IN BOOLEAN LockHeld, 00336 IN KPROCESSOR_MODE AccessMode, 00337 OUT PNTSTATUS AccessStatus) 00338 { 00339 POBJECT_HEADER ObjectHeader; 00340 POBJECT_TYPE ObjectType; 00341 PSECURITY_DESCRIPTOR SecurityDescriptor; 00342 BOOLEAN SdAllocated; 00343 BOOLEAN Result; 00344 ACCESS_MASK GrantedAccess = 0; 00345 PPRIVILEGE_SET Privileges = NULL; 00346 NTSTATUS Status; 00347 PAGED_CODE(); 00348 00349 /* Get the header and type */ 00350 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00351 ObjectType = ObjectHeader->Type; 00352 00353 /* Get the security descriptor */ 00354 Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 00355 if (!NT_SUCCESS(Status)) 00356 { 00357 /* We failed */ 00358 *AccessStatus = Status; 00359 return FALSE; 00360 } 00361 00362 /* Lock the security context */ 00363 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00364 00365 /* Now do the entire access check */ 00366 Result = SeAccessCheck(SecurityDescriptor, 00367 &AccessState->SubjectSecurityContext, 00368 TRUE, 00369 AccessState->RemainingDesiredAccess, 00370 AccessState->PreviouslyGrantedAccess, 00371 &Privileges, 00372 &ObjectType->TypeInfo.GenericMapping, 00373 AccessMode, 00374 &GrantedAccess, 00375 AccessStatus); 00376 if (Result) 00377 { 00378 /* Update the access state */ 00379 AccessState->RemainingDesiredAccess &= ~GrantedAccess; 00380 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00381 } 00382 00383 /* Check if we have an SD */ 00384 if (SecurityDescriptor) 00385 { 00386 /* Do audit alarm */ 00387 #if 0 00388 SeObjectReferenceAuditAlarm(&AccessState->OperationID, 00389 Object, 00390 SecurityDescriptor, 00391 &AccessState->SubjectSecurityContext, 00392 AccessState->RemainingDesiredAccess | 00393 AccessState->PreviouslyGrantedAccess, 00394 ((PAUX_ACCESS_DATA)(AccessState->AuxData))-> 00395 PrivilegeSet, 00396 Result, 00397 AccessMode); 00398 #endif 00399 } 00400 00401 /* We're done, unlock the context and release security */ 00402 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 00403 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 00404 return Result; 00405 } 00406 00407 /*++ 00408 * @name ObCheckObjectAccess 00409 * 00410 * The ObCheckObjectAccess routine <FILLMEIN> 00411 * 00412 * @param Object 00413 * <FILLMEIN> 00414 * 00415 * @param AccessState 00416 * <FILLMEIN> 00417 * 00418 * @param LockHeld 00419 * <FILLMEIN> 00420 * 00421 * @param AccessMode 00422 * <FILLMEIN> 00423 * 00424 * @param ReturnedStatus 00425 * <FILLMEIN> 00426 * 00427 * @return TRUE if access was granted, FALSE otherwise. 00428 * 00429 * @remarks None. 00430 * 00431 *--*/ 00432 BOOLEAN 00433 NTAPI 00434 ObCheckObjectAccess(IN PVOID Object, 00435 IN OUT PACCESS_STATE AccessState, 00436 IN BOOLEAN LockHeld, 00437 IN KPROCESSOR_MODE AccessMode, 00438 OUT PNTSTATUS ReturnedStatus) 00439 { 00440 POBJECT_HEADER ObjectHeader; 00441 POBJECT_TYPE ObjectType; 00442 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; 00443 BOOLEAN SdAllocated; 00444 NTSTATUS Status; 00445 BOOLEAN Result; 00446 ACCESS_MASK GrantedAccess; 00447 PPRIVILEGE_SET Privileges = NULL; 00448 PAGED_CODE(); 00449 00450 /* Get the object header and type */ 00451 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); 00452 ObjectType = ObjectHeader->Type; 00453 00454 /* Get security information */ 00455 Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated); 00456 if (!NT_SUCCESS(Status)) 00457 { 00458 /* Return failure */ 00459 *ReturnedStatus = Status; 00460 return FALSE; 00461 } 00462 else if (!SecurityDescriptor) 00463 { 00464 /* Otherwise, if we don't actually have an SD, return success */ 00465 *ReturnedStatus = Status; 00466 return TRUE; 00467 } 00468 00469 /* Lock the security context */ 00470 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00471 00472 /* Now do the entire access check */ 00473 Result = SeAccessCheck(SecurityDescriptor, 00474 &AccessState->SubjectSecurityContext, 00475 TRUE, 00476 AccessState->RemainingDesiredAccess, 00477 AccessState->PreviouslyGrantedAccess, 00478 &Privileges, 00479 &ObjectType->TypeInfo.GenericMapping, 00480 AccessMode, 00481 &GrantedAccess, 00482 ReturnedStatus); 00483 if (Privileges) 00484 { 00485 /* We got privileges, append them to the access state and free them */ 00486 Status = SeAppendPrivileges(AccessState, Privileges); 00487 SeFreePrivileges(Privileges); 00488 } 00489 00490 /* Check if access was granted */ 00491 if (Result) 00492 { 00493 /* Update the access state */ 00494 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 00495 MAXIMUM_ALLOWED); 00496 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00497 } 00498 00499 /* Do audit alarm */ 00500 SeOpenObjectAuditAlarm(&ObjectType->Name, 00501 Object, 00502 NULL, 00503 SecurityDescriptor, 00504 AccessState, 00505 FALSE, 00506 Result, 00507 AccessMode, 00508 &AccessState->GenerateOnClose); 00509 00510 /* We're done, unlock the context and release security */ 00511 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 00512 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); 00513 return Result; 00514 } 00515 00516 /* PUBLIC FUNCTIONS **********************************************************/ 00517 00518 /*++ 00519 * @name ObAssignSecurity 00520 * @implemented NT4 00521 * 00522 * The ObAssignSecurity routine <FILLMEIN> 00523 * 00524 * @param AccessState 00525 * <FILLMEIN> 00526 * 00527 * @param SecurityDescriptor 00528 * <FILLMEIN> 00529 * 00530 * @param Object 00531 * <FILLMEIN> 00532 * 00533 * @param Type 00534 * <FILLMEIN> 00535 * 00536 * @return STATUS_SUCCESS or appropriate error value. 00537 * 00538 * @remarks None. 00539 * 00540 *--*/ 00541 NTSTATUS 00542 NTAPI 00543 ObAssignSecurity(IN PACCESS_STATE AccessState, 00544 IN PSECURITY_DESCRIPTOR SecurityDescriptor, 00545 IN PVOID Object, 00546 IN POBJECT_TYPE Type) 00547 { 00548 PSECURITY_DESCRIPTOR NewDescriptor; 00549 NTSTATUS Status; 00550 KIRQL CalloutIrql; 00551 PAGED_CODE(); 00552 00553 /* Build the new security descriptor */ 00554 Status = SeAssignSecurity(SecurityDescriptor, 00555 AccessState->SecurityDescriptor, 00556 &NewDescriptor, 00557 (Type == ObDirectoryType), 00558 &AccessState->SubjectSecurityContext, 00559 &Type->TypeInfo.GenericMapping, 00560 PagedPool); 00561 if (!NT_SUCCESS(Status)) return Status; 00562 00563 /* Call the security method */ 00564 ObpCalloutStart(&CalloutIrql); 00565 Status = Type->TypeInfo.SecurityProcedure(Object, 00566 AssignSecurityDescriptor, 00567 NULL, 00568 NewDescriptor, 00569 NULL, 00570 NULL, 00571 PagedPool, 00572 &Type->TypeInfo.GenericMapping); 00573 ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 00574 00575 /* Check for failure and deassign security if so */ 00576 if (!NT_SUCCESS(Status)) SeDeassignSecurity(&NewDescriptor); 00577 00578 /* Return to caller */ 00579 return Status; 00580 } 00581 00582 /*++ 00583 * @name ObGetObjectSecurity 00584 * @implemented NT4 00585 * 00586 * The ObGetObjectSecurity routine <FILLMEIN> 00587 * 00588 * @param Object 00589 * <FILLMEIN> 00590 * 00591 * @param SecurityDescriptor 00592 * <FILLMEIN> 00593 * 00594 * @param MemoryAllocated 00595 * <FILLMEIN> 00596 * 00597 * @return STATUS_SUCCESS or appropriate error value. 00598 * 00599 * @remarks None. 00600 * 00601 *--*/ 00602 NTSTATUS 00603 NTAPI 00604 ObGetObjectSecurity(IN PVOID Object, 00605 OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, 00606 OUT PBOOLEAN MemoryAllocated) 00607 { 00608 POBJECT_HEADER Header; 00609 POBJECT_TYPE Type; 00610 ULONG Length = 0; 00611 NTSTATUS Status; 00612 SECURITY_INFORMATION SecurityInformation; 00613 KIRQL CalloutIrql; 00614 PAGED_CODE(); 00615 00616 /* Get the object header and type */ 00617 Header = OBJECT_TO_OBJECT_HEADER(Object); 00618 Type = Header->Type; 00619 00620 /* Tell the caller that we didn't have to allocate anything yet */ 00621 *MemoryAllocated = FALSE; 00622 00623 /* Check if the object uses default security */ 00624 if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) 00625 { 00626 /* Reference the descriptor */ 00627 *SecurityDescriptor = ObpReferenceSecurityDescriptor(Header); 00628 return STATUS_SUCCESS; 00629 } 00630 00631 /* Set mask to query */ 00632 SecurityInformation = OWNER_SECURITY_INFORMATION | 00633 GROUP_SECURITY_INFORMATION | 00634 DACL_SECURITY_INFORMATION | 00635 SACL_SECURITY_INFORMATION; 00636 00637 /* Get the security descriptor size */ 00638 ObpCalloutStart(&CalloutIrql); 00639 Status = Type->TypeInfo.SecurityProcedure(Object, 00640 QuerySecurityDescriptor, 00641 &SecurityInformation, 00642 *SecurityDescriptor, 00643 &Length, 00644 &Header->SecurityDescriptor, 00645 Type->TypeInfo.PoolType, 00646 &Type->TypeInfo.GenericMapping); 00647 ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 00648 00649 /* Check for failure */ 00650 if (Status != STATUS_BUFFER_TOO_SMALL) return Status; 00651 00652 /* Allocate security descriptor */ 00653 *SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, 00654 Length, 00655 TAG_SEC_QUERY); 00656 if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES; 00657 *MemoryAllocated = TRUE; 00658 00659 /* Query security descriptor */ 00660 ObpCalloutStart(&CalloutIrql); 00661 Status = Type->TypeInfo.SecurityProcedure(Object, 00662 QuerySecurityDescriptor, 00663 &SecurityInformation, 00664 *SecurityDescriptor, 00665 &Length, 00666 &Header->SecurityDescriptor, 00667 Type->TypeInfo.PoolType, 00668 &Type->TypeInfo.GenericMapping); 00669 ObpCalloutEnd(CalloutIrql, "Security", Type, Object); 00670 00671 /* Check for failure */ 00672 if (!NT_SUCCESS(Status)) 00673 { 00674 /* Free the descriptor and tell the caller we failed */ 00675 ExFreePoolWithTag(*SecurityDescriptor, TAG_SEC_QUERY); 00676 *MemoryAllocated = FALSE; 00677 } 00678 00679 /* Return status */ 00680 return Status; 00681 } 00682 00683 /*++ 00684 * @name ObReleaseObjectSecurity 00685 * @implemented NT4 00686 * 00687 * The ObReleaseObjectSecurity routine <FILLMEIN> 00688 * 00689 * @param SecurityDescriptor 00690 * <FILLMEIN> 00691 * 00692 * @param MemoryAllocated 00693 * <FILLMEIN> 00694 * 00695 * @return STATUS_SUCCESS or appropriate error value. 00696 * 00697 * @remarks None. 00698 * 00699 *--*/ 00700 VOID 00701 NTAPI 00702 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, 00703 IN BOOLEAN MemoryAllocated) 00704 { 00705 PAGED_CODE(); 00706 00707 /* Nothing to do in this case */ 00708 if (!SecurityDescriptor) return; 00709 00710 /* Check if we had allocated it from memory */ 00711 if (MemoryAllocated) 00712 { 00713 /* Free it */ 00714 ExFreePool(SecurityDescriptor); 00715 } 00716 else 00717 { 00718 /* Otherwise this means we used an internal descriptor */ 00719 ObDereferenceSecurityDescriptor(SecurityDescriptor, 1); 00720 } 00721 } 00722 00723 /*++ 00724 * @name ObSetSecurityObjectByPointer 00725 * @implemented NT5.1 00726 * 00727 * The ObSetSecurityObjectByPointer routine <FILLMEIN> 00728 * 00729 * @param SecurityDescriptor 00730 * <FILLMEIN> 00731 * 00732 * @param MemoryAllocated 00733 * <FILLMEIN> 00734 * 00735 * @return STATUS_SUCCESS or appropriate error value. 00736 * 00737 * @remarks None. 00738 * 00739 *--*/ 00740 NTSTATUS 00741 NTAPI 00742 ObSetSecurityObjectByPointer(IN PVOID Object, 00743 IN SECURITY_INFORMATION SecurityInformation, 00744 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 00745 { 00746 POBJECT_TYPE Type; 00747 POBJECT_HEADER Header; 00748 PAGED_CODE(); 00749 00750 /* Get the header and type */ 00751 Header = OBJECT_TO_OBJECT_HEADER(Object); 00752 Type = Header->Type; 00753 00754 /* Sanity check */ 00755 ASSERT(SecurityDescriptor); 00756 00757 /* Call the security procedure */ 00758 return Type->TypeInfo.SecurityProcedure(Object, 00759 SetSecurityDescriptor, 00760 &SecurityInformation, 00761 SecurityDescriptor, 00762 NULL, 00763 &Header->SecurityDescriptor, 00764 Type->TypeInfo.PoolType, 00765 &Type->TypeInfo.GenericMapping); 00766 } 00767 00768 /*++ 00769 * @name NtQuerySecurityObject 00770 * @implemented NT4 00771 * 00772 * The NtQuerySecurityObject routine <FILLMEIN> 00773 * 00774 * @param Handle 00775 * <FILLMEIN> 00776 * 00777 * @param SecurityInformation 00778 * <FILLMEIN> 00779 * 00780 * @param SecurityDescriptor 00781 * <FILLMEIN> 00782 * 00783 * @param Length 00784 * <FILLMEIN> 00785 * 00786 * @param ResultLength 00787 * <FILLMEIN> 00788 * 00789 * @return STATUS_SUCCESS or appropriate error value. 00790 * 00791 * @remarks None. 00792 * 00793 *--*/ 00794 NTSTATUS 00795 NTAPI 00796 NtQuerySecurityObject(IN HANDLE Handle, 00797 IN SECURITY_INFORMATION SecurityInformation, 00798 OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 00799 IN ULONG Length, 00800 OUT PULONG ResultLength) 00801 { 00802 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00803 PVOID Object; 00804 POBJECT_HEADER Header; 00805 POBJECT_TYPE Type; 00806 ACCESS_MASK DesiredAccess; 00807 NTSTATUS Status; 00808 PAGED_CODE(); 00809 00810 /* Check if we came from user mode */ 00811 if (PreviousMode != KernelMode) 00812 { 00813 /* Enter SEH */ 00814 _SEH2_TRY 00815 { 00816 /* Probe the SD and the length pointer */ 00817 ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG)); 00818 ProbeForWriteUlong(ResultLength); 00819 } 00820 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00821 { 00822 /* Return the exception code */ 00823 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00824 } 00825 _SEH2_END; 00826 } 00827 00828 /* Get the required access rights for the operation */ 00829 SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess); 00830 00831 /* Reference the object */ 00832 Status = ObReferenceObjectByHandle(Handle, 00833 DesiredAccess, 00834 NULL, 00835 PreviousMode, 00836 &Object, 00837 NULL); 00838 if (!NT_SUCCESS(Status)) return Status; 00839 00840 /* Get the Object Header and Type */ 00841 Header = OBJECT_TO_OBJECT_HEADER(Object); 00842 Type = Header->Type; 00843 00844 /* Call the security procedure's query function */ 00845 Status = Type->TypeInfo.SecurityProcedure(Object, 00846 QuerySecurityDescriptor, 00847 &SecurityInformation, 00848 SecurityDescriptor, 00849 &Length, 00850 &Header->SecurityDescriptor, 00851 Type->TypeInfo.PoolType, 00852 &Type->TypeInfo.GenericMapping); 00853 00854 /* Dereference the object */ 00855 ObDereferenceObject(Object); 00856 00857 /* Protect write with SEH */ 00858 _SEH2_TRY 00859 { 00860 /* Return the needed length */ 00861 *ResultLength = Length; 00862 } 00863 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00864 { 00865 /* Get the exception code */ 00866 Status = _SEH2_GetExceptionCode(); 00867 } 00868 _SEH2_END; 00869 00870 /* Return status */ 00871 return Status; 00872 } 00873 00874 /*++ 00875 * @name NtSetSecurityObject 00876 * @implemented NT4 00877 * 00878 * The NtSetSecurityObject routine <FILLMEIN> 00879 * 00880 * @param Handle 00881 * <FILLMEIN> 00882 * 00883 * @param SecurityInformation 00884 * <FILLMEIN> 00885 * 00886 * @param SecurityDescriptor 00887 * <FILLMEIN> 00888 * 00889 * @return STATUS_SUCCESS or appropriate error value. 00890 * 00891 * @remarks None. 00892 * 00893 *--*/ 00894 NTSTATUS 00895 NTAPI 00896 NtSetSecurityObject(IN HANDLE Handle, 00897 IN SECURITY_INFORMATION SecurityInformation, 00898 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 00899 { 00900 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00901 PVOID Object; 00902 SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor; 00903 ACCESS_MASK DesiredAccess = 0; 00904 NTSTATUS Status; 00905 PAGED_CODE(); 00906 00907 /* Make sure the caller doesn't pass a NULL security descriptor! */ 00908 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION; 00909 00910 /* Set the required access rights for the operation */ 00911 SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess); 00912 00913 /* Reference the object */ 00914 Status = ObReferenceObjectByHandle(Handle, 00915 DesiredAccess, 00916 NULL, 00917 PreviousMode, 00918 &Object, 00919 NULL); 00920 if (NT_SUCCESS(Status)) 00921 { 00922 /* Capture and make a copy of the security descriptor */ 00923 Status = SeCaptureSecurityDescriptor(SecurityDescriptor, 00924 PreviousMode, 00925 PagedPool, 00926 TRUE, 00927 (PSECURITY_DESCRIPTOR*) 00928 &CapturedDescriptor); 00929 if (!NT_SUCCESS(Status)) 00930 { 00931 /* Fail */ 00932 ObDereferenceObject(Object); 00933 return Status; 00934 } 00935 00936 /* Sanity check */ 00937 ASSERT(CapturedDescriptor->Control & SE_SELF_RELATIVE); 00938 00939 /* 00940 * Make sure the security descriptor passed by the caller 00941 * is valid for the operation we're about to perform 00942 */ 00943 if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && 00944 !(CapturedDescriptor->Owner)) || 00945 ((SecurityInformation & GROUP_SECURITY_INFORMATION) && 00946 !(CapturedDescriptor->Group))) 00947 { 00948 /* Set the failure status */ 00949 Status = STATUS_INVALID_SECURITY_DESCR; 00950 } 00951 else 00952 { 00953 /* Set security */ 00954 Status = ObSetSecurityObjectByPointer(Object, 00955 SecurityInformation, 00956 CapturedDescriptor); 00957 } 00958 00959 /* Release the descriptor and return status */ 00960 SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedDescriptor, 00961 PreviousMode, 00962 TRUE); 00963 00964 /* Now we can dereference the object */ 00965 ObDereferenceObject(Object); 00966 } 00967 00968 return Status; 00969 } 00970 00971 /*++ 00972 * @name ObQueryObjectAuditingByHandle 00973 * @implemented NT5 00974 * 00975 * The ObDereferenceSecurityDescriptor routine <FILLMEIN> 00976 * 00977 * @param SecurityDescriptor 00978 * <FILLMEIN> 00979 * 00980 * @param Count 00981 * <FILLMEIN> 00982 * 00983 * @return STATUS_SUCCESS or appropriate error value. 00984 * 00985 * @remarks None. 00986 * 00987 *--*/ 00988 NTSTATUS 00989 NTAPI 00990 ObQueryObjectAuditingByHandle(IN HANDLE Handle, 00991 OUT PBOOLEAN GenerateOnClose) 00992 { 00993 PHANDLE_TABLE_ENTRY HandleEntry; 00994 PVOID HandleTable; 00995 NTSTATUS Status = STATUS_SUCCESS; 00996 PAGED_CODE(); 00997 00998 /* Check if we're dealing with a kernel handle */ 00999 if (ObIsKernelHandle(Handle, ExGetPreviousMode())) 01000 { 01001 /* Use the kernel table and convert the handle */ 01002 HandleTable = ObpKernelHandleTable; 01003 Handle = ObKernelHandleToHandle(Handle); 01004 } 01005 else 01006 { 01007 /* Use the process's handle table */ 01008 HandleTable = PsGetCurrentProcess()->ObjectTable; 01009 } 01010 01011 /* Enter a critical region while we touch the handle table */ 01012 KeEnterCriticalRegion(); 01013 01014 /* Map the handle */ 01015 HandleEntry = ExMapHandleToPointer(HandleTable, Handle); 01016 if(HandleEntry) 01017 { 01018 /* Check if the flag is set */ 01019 *GenerateOnClose = HandleEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE; 01020 01021 /* Unlock the entry */ 01022 ExUnlockHandleTableEntry(HandleTable, HandleEntry); 01023 } 01024 else 01025 { 01026 /* Otherwise, fail */ 01027 Status = STATUS_INVALID_HANDLE; 01028 } 01029 01030 /* Leave the critical region and return the status */ 01031 KeLeaveCriticalRegion(); 01032 return Status; 01033 } 01034 01035 /* EOF */ Generated on Mon May 28 2012 04:37:34 for ReactOS by
1.7.6.1
|