ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

obsecure.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.